Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
20 years ago

PIO devices under uClinux

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

5 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Thanks for your help.

    I will try the "quick and dirty" way to see if I have succes.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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...
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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