access I/O ports from user space, not GPIO

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hi everyone again.

I was wondering if it was possible to read and write register values to control AVR32's functionalities from user space.
I already made kernel modules to do such things, but this time I would like to experiment with user space code.
I know the GPIO modules are there to perform a similar task, but is it possible to tell linux to let me modify some registers from user space? I mean, like PIO pins, etc.

As far as I remember there were some functions for the i386 architecture, like ioperm(), outb, inb, etc. I can't find those on the avr32 toolchain, which is very likely since there isn't a I/O and memory separation.

Many may consider doing this harmful, but since I'm not running a preemptive kernel (regarding kernel threads), if my modules use up too much CPU then they will block some other important modules from executing.
For instance, the LCD module uses the PIO interface, and has some udelay and mdelay functions inside. I don't need anything time-crucial there, so that could be done with a user space program, but I don't want to use any modules, nor GPIO nor mine's.

thanks everyone,

Carlos

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

cbecker wrote:
I was wondering if it was possible to read and write register values to control AVR32's functionalities from user space. ...
You'll need to do like gpio does and wrap the registers in a user interface. gpiodev doesn't let you write to the memory directly, just gives you a convenient way of telling the driver to write to restricted memory for you.
cbecker wrote:
As far as I remember there were some functions for the i386 architecture, like ioperm(), outb, inb, etc. I can't find those on the avr32 toolchain, which is very likely since there isn't a I/O and memory separation.
You can still map physical address space in to a userspace processes VMA but if you try and do this to a memory segment not available to unprivileged users, you'll segfault. Refer to the avr32 arch manual for the segment layout in privileged and unprivileged modes. Peripheral registers are only accessible to a privileged (i.e. kernelspace) app.
cbecker wrote:
Many may consider doing this harmful, but since I'm not running a preemptive kernel (regarding kernel threads), if my modules use up too much CPU then they will block some other important modules from executing.
For instance, the LCD module uses the PIO interface, and has some udelay and mdelay functions inside. I don't need anything time-crucial there, so that could be done with a user space program, but I don't want to use any modules, nor GPIO nor mine's.
Well you can do as I suggest above and write a simple user interface to the registers of interest, but if this is the only problem you're trying to overcome, can you use delayed workqueues instead of blocking sleeps? Kernel preempt != kernel threads, you can have a multithreaded kernel that can't be preempted. In fact there's not a chance that your running kernel now is single-threaded, you may as well hook in to one of those callback threads for your own purpose too.

-S.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

that's good news.
I'm still a little bit confused about kernel preemption and kernel threads but I think I get the point.
So as far as I can see, there are kernel threads, only that they work in a kind of "cooperative" fashion when kernel preemption is not enabled. Am I right?
So usleep() and msleep() may help to this cooperativity.. but I don't know. Better yet, I'll take a look at the kernel source to see it clearly.

Thanks for the information, it was clear and precise. Now I know what to do if I want to control the ports from user space.

thanks again,

Carlos

----------------EDIT----------------------
I was using udelay() and mdelay() in my module, and according to arch/avr32/lib/delay.c those routines just hang the avr for as long as requiered...not what I am looking for.
I guess the best is to make something like GPIO, as you said, and call it from userspace, using delays from userspace.

thanks!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

cbecker wrote:
So usleep() and msleep() may help to this cooperativity.. but I don't know. Better yet, I'll take a look at the kernel source to see it clearly.
They don't, they just block. I think what you may be looking for is something like delayed worqueues. These allow you to schedule a callback some time in the future. Unfortunately this interface changed a little bit recently so I haven't been able to find a nice definitive resource to point you to. Have a look at http://lwn.net/Articles/11360/ to get an idea of what a workqueue is and why to use it but recent kernels change the deal slightly for delayed work. Details of the change (which is little more than changing struct work to struct delayed_work) can be found in http://lwn.net/Articles/213149/ with a more userfriendly version http://lwn.net/Articles/211279/. Pretty much the idea is simply that you fill in a struct delayed_work with callback details then call queue_delayed_work(). After the designated time elapses your function will get a callback and you'll be right.
cbecker wrote:

----------------EDIT----------------------
I was using udelay() and mdelay() in my module, and according to arch/avr32/lib/delay.c those routines just hang the avr for as long as requiered...not what I am looking for.
I guess the best is to make something like GPIO, as you said, and call it from userspace, using delays from userspace.
My $0.02 would still be to stay in kernel and use the appropriate in-kernel timed callbacks. It's more secure, more predictable and, for want of a better word, more "correct".

-S.

p.s. this is probably a good time to plug one of my favorite books in the world, Robert Love's Linux Kernel Development ( http://www.amazon.com/Linux-Kern... ). This isn't exactly correct for the latest kernels due to the delayed_work changes above, but will teach you plenty nevertheless!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks for the information!
I will take a look at those queues. That book seems interesting too.

thanks once again,

Carlos

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

squidgit wrote:
You can still map physical address space in to a userspace processes VMA but if you try and do this to a memory segment not available to unprivileged users, you'll segfault. Refer to the avr32 arch manual for the segment layout in privileged and unprivileged modes. Peripheral registers are only accessible to a privileged (i.e. kernelspace) app.

Just to clarify: You _can_ access any physical memory address from application mode by setting up one or more TLB entries with the right permissions. This includes peripheral registers. You can not access any memory through the default Px segments from application mode.

So to access privileged memory from a Linux application, open /dev/mem and use mmap() to get a virtual mapping of the physical memory region given by the offset and length parameters. This is only possible to do as root, provided /dev/mem is set up with the correct permissions (if not, this would be a huge security hole.)

ISTR some discussion about disabling the /dev/mem interface completely some time ago. It's not used all that much, and it can be quite dangerous.