GPIO on AT91SAM9260

This forum is for users of Microchip MPUs and who are interested in using Linux OS.

Moderator: nferre

pkavan
Location: Omaha, Nebraska, USA
Posts: 38
Joined: Wed Mar 21, 2007 4:40 pm

GPIO on AT91SAM9260

Mon Apr 02, 2007 9:34 pm

I have a working kernel and am simply trying to read/write some of the gpio pins and hopefully some of the registers (e.g. for the ADC). Has anyone had any success on this and care to share how they did it.
pkavan
Location: Omaha, Nebraska, USA
Posts: 38
Joined: Wed Mar 21, 2007 4:40 pm

Tue Apr 03, 2007 4:35 pm

As an update, I am now using the devmem2 code to work the with mmap to try to access the pins and registers directly. However, I cannot seem to figure out how these are mapped. Has anyone tried this approach and, if so, do you have an idea of where to find the gpio and hw registers in mmap?
michel
Posts: 5
Joined: Fri Dec 01, 2006 3:00 pm

Thu Apr 12, 2007 7:12 am

See mmap, devmem2 and uclibc discussions on arm linux mailing list for a solution to this problem.
blue_z
Location: USA
Posts: 1979
Joined: Thu Apr 19, 2007 10:15 pm

Re: GPIO on AT91SAM9260

Thu Apr 19, 2007 11:08 pm

[quote="pkavan"]I have a working kernel and am simply trying to read/write some of the gpio pins and hopefully some of the registers (e.g. for the ADC). Has anyone had any success on this and care to share how they did it.[/quote]

Hi there

I don't know if this is the preferred Linux way, but I just allocate some virtual memory address space with request_mem_region() and ioremap().

Regards
pkavan
Location: Omaha, Nebraska, USA
Posts: 38
Joined: Wed Mar 21, 2007 4:40 pm

Tue Apr 24, 2007 7:31 pm

Seems the best way to handle this is to write a driver that handles the functionality you want. I was able to use the functions described in gpio.c to write my driver. So, if anyone else wants to read/write the gpio, a driver might be your best approach.

I could never get a handle on the mmap approach with busybox as there is something wrong with mmap in uclibc that I was unable to resolve on my own.
blue_z
Location: USA
Posts: 1979
Joined: Thu Apr 19, 2007 10:15 pm

Tue Apr 24, 2007 9:34 pm

pkavan wrote:Seems the best way to handle this is to write a driver that handles the functionality you want. I was able to use the functions described in gpio.c to write my driver. So, if anyone else wants to read/write the gpio, a driver might be your best approach.
Hi there

Sorry for being so vague in the previous post, but, I meant to write that a device driver using request_mem_region() and ioremap() will get you access to the device. Performing I/O from the kernel rather than userland is probably always the prefered method.

For efficiency the drivers I wrote use ioctl() rather than read(0 and write(), since the data moved is no more than a word long.

Regards
pkavan
Location: Omaha, Nebraska, USA
Posts: 38
Joined: Wed Mar 21, 2007 4:40 pm

Tue Apr 24, 2007 9:49 pm

blue_z wrote:
pkavan wrote:Seems the best way to handle this is to write a driver that handles the functionality you want. I was able to use the functions described in gpio.c to write my driver. So, if anyone else wants to read/write the gpio, a driver might be your best approach.
Hi there

Sorry for being so vague in the previous post, but, I meant to write that a device driver using request_mem_region() and ioremap() will get you access to the device. Performing I/O from the kernel rather than userland is probably always the prefered method.

For efficiency the drivers I wrote use ioctl() rather than read(0 and write(), since the data moved is no more than a word long.

Regards
You were not vague at all. I had actually come to the same conclusion you had pointed out in the post. I was merely trying to make sure that I responded so folks would know I had managed to figure out the gpio.

I had not thought of using iocntl() to handle the gpio--it is likely a better way to implement the driver, because--as you pointed out--you are dealing with a small data set to handle the gpio.

What I am really pulling my hair out about now is both the i2c and trying to implement a more useful adc driver.

My adc driver works quite well in terms of taking readings and moving those to userspace. However, what I really need is a driver that starts the adc on a button press--continuing while the button is pressed--and moves that data to userspace--and then terminates when the button is released.

Right now I can make the adc start and take readings while the button is pressed. The start is interrupt driven off one of the user buttons. The interrupt calls a work censored that cycles as long as the button is pressed, taking readings as fast as the machine will allow. It loops while the button is pressed and then terminates when the button is released. However, I am having a hard time--as I am really new to driver writing--figuring out how to get each of those samples back to userspace from the work censored.

The i2c is a whole other beast I am trying to figure out. Not too fun.

Thanks for the reply.

Paul
blue_z
Location: USA
Posts: 1979
Joined: Thu Apr 19, 2007 10:15 pm

Tue Apr 24, 2007 10:29 pm

pkavan wrote: However, what I really need is a driver that starts the adc on a button press--continuing while the button is pressed--and moves that data to userspace--and then terminates when the button is released.
Hi there

Not sure of what you implemented so far, but I would not try to consolidate the I/O into one driver. I prefer to have one driver for just for the ADC, another for the button. Or for quick testing, one driver (module) for the device major number, and switch/case statements for the minor device numbers in the open(), close() and ioctl() routines.

Seems like there are 2 events for your application to handle: button press and button release. And in between those 2 events the app should perform ADConversions. The device drivers could just perform very simple I/O operations, and the interaction between devices is done in the app code. I haven't figured out how to load/unload a Linux device driver (which I have done for SunOS drivers), so I'd rather be recompiling/testing userland code than building/installing kernels.

Regards
pkavan
Location: Omaha, Nebraska, USA
Posts: 38
Joined: Wed Mar 21, 2007 4:40 pm

Tue Apr 24, 2007 10:40 pm

blue_z wrote:
pkavan wrote: However, what I really need is a driver that starts the adc on a button press--continuing while the button is pressed--and moves that data to userspace--and then terminates when the button is released.
Hi there

Not sure of what you implemented so far, but I would not try to consolidate the I/O into one driver. I prefer to have one driver for just for the ADC, another for the button. Or for quick testing, one driver (module) for the device major number, and switch/case statements for the minor device numbers in the open(), close() and ioctl() routines.

Seems like there are 2 events for your application to handle: button press and button release. And in between those 2 events the app should perform ADConversions. The device drivers could just perform very simple I/O operations, and the interaction between devices is done in the app code. I haven't figured out how to load/unload a Linux device driver (which I have done for SunOS drivers), so I'd rather be recompiling/testing userland code than building/installing kernels.

Regards
When you say that you have not been able to figure out loading/unloading, what do you mean. I assume you do not mean insmod rmmod type stuff. What I do is make the drivers as modules on my host and then tftp them into the target. insmod the module you have made and then test it. As long as it does not hang the processor, you can rmmod it. Is there something more here you are not understanding? Let me know. I have a pretty good procedure for writing, compiling, loading, and testing drivers. Just am not sure what I am doing sometimes when I am writing the drivers...

The other issue is the separate drivers for gpio and adc. I would prefer to do it this way, but I have not figured out how to get a interrupt to start a process in userspace yet--I am pretty new to drivers. I would prefer to have the gpio tell a userspace process to start the adc conversions and then generate a clean way to stop the process when the button is released. Keep in mind that the reads are going to written to a file, so I have to kill the reads cleanly so the file is properly closed and such. Any hints?

Thanks

Paul
blue_z
Location: USA
Posts: 1979
Joined: Thu Apr 19, 2007 10:15 pm

Wed Apr 25, 2007 12:32 am

Hi there

Actually I did not bother to look at driver/module loading/unloading at all, since I knew that the drivers would always need to be loaded for the embedded product. I simply decided to forego the convienence during the development crunch. But you seemed to have laid out what I now need to look at.

I'm not sure either on how to get an interrupt to actually start a process. You could have a process (or even better, a thread) waiting on a semaphore that the int handler would use to signal an event. The thread could wait for the button press semaphore event, then make repeated ioctl() calls to start/get ADC values (and file writes) as long as the button release event (a second semaphore?) has not occured. (This is just a crude design idea unitl I receive the retainer for consulting services :D )

If you instead decide to have an ioctl() call wait for an interrupt to occur, then you should probably investigate the wait_event_interruptible() and wake_up_interruptible() for the driver's ioctl and interrupt handlers respectively. I've used this pair of calls to implement an ioctl() to wait for int then read a port and return the value.

The complexity of "killing the reads" is something I rather completely avoid. Perhaps you could simplify the alogorithm to a do...while (!button_is_released) loop, and have the calls to perform ADC conversions and file writes in the loop. This loop or procedure is invoked when the button_pressed semaphore wait is over.

Regards
ghofman
Location: Vancouver, BC, Canada
Posts: 28
Joined: Sun May 20, 2007 5:11 am

Wed May 23, 2007 7:55 pm

Hi

Since you cant use interrupts from user -space, wouldnt be easier to write one driver to wait for your button, one to read the ADC. In userland, you open the first driver file with a blocking read, which returns only when the button is pressed, then open the adc device files and read that and keep checking the button driver with a non-blocking read until it signals the 2nd press. But what I really wanted to ask is whether you could post your gpio driver. Thanks

Gertjan

Return to “LINUX”

Who is online

Users browsing this forum: No registered users and 1 guest