Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++

PIO devices under uClinux

Altera_Forum
Honored Contributor II
1,233 Views

I'm having a problem getting the PIO ports to work under uClinux. 

 

If I try to access the PIO by reading or writing to the memory location, pointed to by the pio struct, then nothing seems to happen. Monitoring the bit on the hardware side shows that it isn't toggling. 

 

I have data cache, but was under the impression that setting the most significant bit of the address would force the data to ignore cache and go out to memory space, therefore hitting the PIO registers. Is this not the case? In other words, all the peripherals off the Avalon bus utilize and address with its most significant bit set. 

 

In order to overcome this issue, I tried using the standard io macros utilized in Linux. 

However, I had problems using the outl and inl functions. 

It warns that they are not defined, even though asm/io.h is included. 

I little digging into asm/io.h shows that these inline macros aren't included, because their are behind an "#ifdef __KERNEL__". 

Basically, I guess the code was written, so that these inline macros are only valid from kernel space. 

 

It seems like there should be a simple way to directly control the pio devices within a user-space program under uClinux. 

 

Does anybody have a proven method? 

 

Is there anything else that might be going wrong???  

 

Thanks in advance. http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/sad.gif
0 Kudos
5 Replies
Altera_Forum
Honored Contributor II
334 Views

Hi trk_golf, 

 

> setting the most significant bit of the address would force the data to ignore 

> cache and go out to memory space, therefore hitting the PIO registers. 

> Is this not the case? 

 

Correct. 

 

> In other words, all the peripherals off the Avalon bus utilize and address with 

> its most significant bit set. 

 

Cache bypass is internal to the CPU (and its data cache) ... I don&#39;t believe the 

"avalon bus" cares. 

 

> However, I had problems using the outl and inl functions. 

<<snip>> 

> I guess the code was written, so that these inline macros are only valid from 

> kernel space. 

 

Correct. The (standard) linux macros expect a physical address, not a virtual 

address -- and user-space addresses are always virtual. But this is all moot 

(at least for now) since Nios-II doesn&#39;t have an MMU. 

 

> It seems like there should be a simple way to directly control the pio devices 

> within a user-space program under uClinux. 

> Does anybody have a proven method? 

 

The "correct" way for an application to access memory mapped devices under 

linux is to use mmap, provided the device driver supports it. 

 

The quick &#39;n dirty way is to just cut &#39;n paste the macros into your own header. 

 

Provided an MMU doesn&#39;t suddenly appear in your design, either method 

will give you access ... although the macros do have that "natural feel", no? ;-)  

 

Regards, 

--Scott
0 Kudos
Altera_Forum
Honored Contributor II
334 Views

Thanks for your help. 

 

I will try the "quick and dirty" way to see if I have succes.
0 Kudos
Altera_Forum
Honored Contributor II
334 Views

OK...so far I&#39;m still having troubles. 

 

When trying to use the "outl" and "inl" macros, there is a problem. These only expect an address of size short. How would I tell it to use the full 32 bit address. In any case, I tried this and it didn&#39;t seem to have any effect on the registers or on the pins. 

 

I also tried using mmap. I finally was able to get this to compile and run, but it didn&#39;t have any effect either. When trying to use either "MAP_SHARED" or "MAP_PRIVATE" and perform a write, it would complain and say that it isn&#39;t supported. The only way I could get it not to complain was to set this parameter to "0". This didn&#39;t produce the desired effect, because the registers wouldn&#39;t update. Basically, no matter what I tried with mmap, the memory address that was supposed to be mapped from the pio peripheral was changed in an erratic way, or it wasn&#39;t changed at all. 

 

Now I am back to trying the plain and simple method where you set up a pointer of type np_pio and set it to the address defined in the nios2_system.h file. 

 

This is where I originally started and wasn&#39;t able to get the registers to update or see any changes on the pio pins. 

 

However, this time I&#39;m going to try to manually remove Dcache from the NIOS2 and see if this produces the desired affect. 

cc 

I don&#39;t understand why something as simple as the pio&#39;s would exhibit such a problem. I am using multiple i2c controllers and uarts with 100% success. The only difference is that I&#39;m trying to access the pio registers directly from a user-space application, vs. going through a Linux driver. 

 

Shouldn&#39;t I be able to do this with little effort? 

The main reason for accessing them from user space was so that I could quickly package some utilities together for our Test Engineer to use.  

 

Any other suggestions? 

 

Do you or anyone else have a sample user application that accesses a pio peripheral under Linux? 

 

Thanks...
0 Kudos
Altera_Forum
Honored Contributor II
334 Views

I got it working!!! 

 

 

The problem was entirely mine and present in my code. I apologize for any time that was wasted. 

 

Just for anyone else&#39;s benefit, the simplest method that worked for me was just to declare a pointer of type np_pio. I then used the variables within the structure to address the peripheral directly. It works great. I DID NOT have to remove DCACHE either, so the MSB of the address being set truly does bypass the cache. 

 

The error in my code was the use of a "<" instead of a "<<" to perform a bit-shift operation. I have done this thousands of times, but it was a simple typo. 

 

Thanks for your help.
0 Kudos
Altera_Forum
Honored Contributor II
334 Views

Hi trk_golf, 

 

Glad you have things working :-) 

 

> When trying to use the "outl" and "inl" macros, there is a problem. 

> These only expect an address of size short. 

 

They expect the full 32-bit address. They are macros with inline assembly 

that use register parameters -- the full 32-bits, unmodified. When used with 

the inline string io functions, these are traditionally defined as unsigned long. 

 

You shouldn&#39;t have observed any problems. 

 

Best Regards, 

--Scott
0 Kudos
Reply