On old iMX.6 BSP without DT (Device Tree), GPIO is controlled by following code:
#define SABRESD_SHUTDOWN IMX_GPIO_NR(4, 15)
gpio_request(SABRESD_SHUTDOWN, "shutdown");
gpio_direction_output(SABRESD_SHUTDOWN, 1);
gpio_set_value(SABRESD_SHUTDOWN, 0);
gpio_free(SABRESD_SHUTDOWN);
However on new BSP, I cannot use IMX_GPIO_NR anymore. Instead, of_get_named_gpio provides access to GPIO defined in DT. But it is a little complicated because our product never changes the GPIO ports.
My question is, is it possible to control GPIOs without DT definition (just using the old method)?
First of all, if you are using newer kernel, I would recommend you to port your code to support the latest features. Otherwise - why bothering upgrading the kernel if you are not willing to adapt to it?
Second, never say never.
And finally:
#define IMX_GPIO_NR(bank, nr) (((bank) - 1) * 32 + (nr))
Related
Coming form this question yesterday, I decided to port this library to my board. I was aware that I needed to change something, so I compiled the library, call it on a small program and see what happens. The 1st problem is here:
// Check for GPIO and peripheral addresses from device tree.
// Adapted from code in the RPi.GPIO library at:
// http://sourceforge.net/p/raspberry-gpio-python/
FILE *fp = fopen("/proc/device-tree/soc/ranges", "rb");
if (fp == NULL) {
return MMIO_ERROR_OFFSET;
}
This lib is aimed for Rpi, os the structure of the system on my board is not the same. So I was wondering if somebody could tell me where I could find this file or how it looks like so I can find it by my self in order to proceed the job.
Thanks.
You don't necessarily want that "file" (or more precisely /proc node).
The code this is found in is setting up to do direct memory mapped I/O using what appears to be a pi-specific gpio-flavored version of the /dev/mem type of device driver for exposing hardware special function registers to userspace.
To port this to your board, you would need to first determine if there is a /dev/mem or similar capability in your kernel which you can activate. Then you would need to determine the appropriate I/O registers for GPIO pins. The pi-specific code is reading the Device Tree to figure this out, but there are other ways, for example you can manually read the programmer's manual of the SoC on which you are running.
Another approach you can consider is adding some small microcontroller (or yes, barebones ***duino) to the system, and using that to collect information from various sensors and peripherals. This can then be forwarded to the SoC over a UART link, or queried out via I2C or similar - add a small amount of cost and some degree of bottleneck, but also means that the software on the SoC then becomes very portable - to a different comparable chip, or perhaps even to run on a desktop PC during development.
I am having troubles with gpio interrupt issue.
According documentation for ep93xx ports A, B, F can be configured to generate interrupts.
quote:
Any of the 19 GPIO lines maybe configured to generate interrupts
However arch/arm/march-ep93xx/gpio.c is handling only interrupts from port A. And doesn't react to port B and F.
static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
{
unsigned char status;
int i;
printk(KERN_INFO "ep93xx_gpio_ab_irq_handler: irq=%u", irq);
I know printk is terrible in irq_handlers.
I am configuring iterrupts via sysfs.
GPIO 0,8 are wired with Port F if it is important to issue.
Also when enabling interrupts on port B without having configured port A i get following warning:
------------[ cut here ]------------
WARNING: at drivers/gpio/gpiolib.c:103 gpio_ensure_requested+0x54/0x118()
autorequest GPIO-1
Modules linked in:
[<c002696c>] (unwind_backtrace+0x0/0xf0) from [<c00399d4>] (warn_slowpath_fmt+0x54/0x78)
[<c00399d4>] (warn_slowpath_fmt+0x54/0x78) from [<c019dd90>] (gpio_ensure_requested+0x54/0x118)
[<c019dd90>] (gpio_ensure_requested+0x54/0x118) from [<c019e05c>] (gpio_direction_input+0xb0/0x150)
[<c019e05c>] (gpio_direction_input+0xb0/0x150) from [<c002c9a8>] (ep93xx_gpio_irq_type+0x3c/0x1d8)
[<c002c9a8>] (ep93xx_gpio_irq_type+0x3c/0x1d8) from [<c0066ad8>] (__irq_set_trigger+0x38/0x9c)
[<c0066ad8>] (__irq_set_trigger+0x38/0x9c) from [<c0066e14>] (__setup_irq+0x2d8/0x354)
[<c0066e14>] (__setup_irq+0x2d8/0x354) from [<c0066f38>] (request_threaded_irq+0xa8/0x140)
[<c0066f38>] (request_threaded_irq+0xa8/0x140) from [<c019e784>] (gpio_setup_irq+0x14c/0x260)
[<c019e784>] (gpio_setup_irq+0x14c/0x260) from [<c019ec1c>] (gpio_edge_store+0x90/0xac)
[<c019ec1c>] (gpio_edge_store+0x90/0xac) from [<c01be8fc>] (dev_attr_store+0x1c/0x28)
[<c01be8fc>] (dev_attr_store+0x1c/0x28) from [<c00e8b2c>] (sysfs_write_file+0x168/0x19c)
[<c00e8b2c>] (sysfs_write_file+0x168/0x19c) from [<c009a3d4>] (vfs_write+0xa4/0x160)
[<c009a3d4>] (vfs_write+0xa4/0x160) from [<c009a6a4>] (sys_write+0x3c/0x7c)
[<c009a6a4>] (sys_write+0x3c/0x7c) from [<c0020e40>] (ret_fast_syscall+0x0/0x2c)
---[ end trace ff56c09a294dbe68 ]---
I am using kernel version 2.6.34.14 with linux-2.6.34-ts7200_matt-6.tar.gz patch (hovewer it doesn't seem contain patches for gpio.c or gpiolib.c)
cross version:
binutils-2.23.1
gcc-4.7.3
glibc-2.17
Also i crawled through change history of gpio.c and gpiolib.c and didn't find anything that can be related to this issue.
Can someone give me and advice regarding this issue? I want interrupts on all ports (A,B,F) not just A.
There are a lot of question on this issue (and ARM irq OR interrupt). Please look at them.
We can see many changes by looking at more recent Linux 3.0 gpio.c change logs versus the 2.6.34 logs and the current version. You should be able to get the current Linux stable tree and extract these patches and back port them to your kernel. For instance, there is a bug where port C and F are swapped; I don't know if this is in your ts7200_matt variant.
Some important change sets to look at,
arm: Fold irq_set_chip/irq_set_handler
arm: Cleanup the irq namespace
arm: ep93xx: Use proper irq accessor functions
arm: ep93xx: Add basic interrupt info
ARM: ep93xx: irq_data conversion.
ARM: 5954/1: ep93xx: move gpio interrupt support to gpio.c
[ARM] 5243/1: ep93xx: bugfix, GPIO ports C and F are swapped
You may have #6, but it is worth looking at as it is basically the interrupt implementation for your controller. After about linux-3.0, your SOC's GPIO controller was moved to drivers/gpio/gpio-ep93xx.c. You may wish to look at these changes, but none seem to be related to your issue. You should be aware of structural changes to Linux. Ie, overall changes to interrupt handling and/or the generic GPIO infrastructure. A good guess is that Thomas Gleixner or Russell King will make these changes.
The patches can be extracted from a particular Linux stable tree with git format-patch b685004.. b0ec5cf1 gpio.c. This will create several patch files. Move them to your tree and apply with either git am or patch -p1. You may have to massage these files to get them to apply cleanly to your tree; if you take them all, even though they are not related to interrupt handling, you will have better luck doing this automatically. You can also look at the patch set and try to manually patch the file with a text editor.
None of this addresses your specific questions. However, it gives a path to merge changes from the latest Linux versions. Also, the previous stack overflow questions give details on the structure of the GPIO interrupt handling. Coupled with your data sheet, the Linux GPIO document, and the given change sets, you should be able to fix your own problem. Otherwise, you need someone familiar with the EP93xx and the question is fairly localized.
Note: The stack trace indicates that a GPIO is being used without a corresponding gpio_request()
. This is either a bug in the machine file or in the EP93xx GPIO interrupt handling code.
I had the same warning:
------------[ cut here ]------------
WARNING: at drivers/gpio/gpiolib.c:103 gpio_ensure_requested
From my research we have to call gpio_request_one / gpio_request, before gpio_direction_input.
It fixed the problem for me.
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=99789
http://e2e.ti.com/support/embedded/linux/f/354/p/119946/427889.aspx
I was able to control GPIO using mmap system call to control LED operation directly from the user space. Now I want to implement driver in kernel space.
I am trying to write my first kernel space device driver for 16*2 line of LCD in Linux for ARM controller RPi.
Now i need to access the GPIO for this purpose.
In AVR i use to access the Port like this.
#define PORTA *(volatile unsigned char*)0x30
I was reading LLD it tells to use inb() & outb() function to access the i/o port.
http://www.makelinux.net/ldd3/chp-9-sect-2
1> Can we not use #define address of port to access the GPIO ?
2> What is the advantages to use use inb() & outb() functions for controlling the GPIO ?
Please suggest.
In AVR i use to access the Port like this.
#define PORTA *(volatile unsigned char*)0x30
That's an improper definition that overloads the symbol PORTA.
Besides defining the port address as 0x30, you are also dereferencing that location.
So it is actually a read operation, but there's no indication of that in the name, i.e. you have really defined a macro for READ_PORTA.
1> Can we not use #define address of port to access the GPIO ?
Of course you can (and should).
#define PORTA (unsigned char *)0x30
You'll find similar statements in header files for device registers in the Linux source tree. When developing a new device driver, I look for a header file of #defines for all of the device's registers and command codes, and start writing one if no file is already available.
2> What is the advantages to use use inb() & outb() functions for controlling the GPIO ?
The code is then an unambiguous statement that I/O is being performed, regardless of whether the architecture uses I/O ports or memory-mapped I/O.
Anyone reading the following should be able to deduce what is going on:
x = inb(PORTA);
versus the confusion when using your macro:
x = PORTA;
The above statement using an overloaded macro would not pass a code review conducted by competent coders.
You should also get familiar with and use the Linux kernel coding style.
1) the use of defines simplifies your task often. You could, of course, not use define for your port and use this construction literally everywhere you need to access the port. But then you will have to replace the 0x30 everywhere with another address if you change the design of your device, for example, if you decide to connect your LED to port B. Also, it will make your code less readable. Alternatively you could declare a function that will access your port. If such a simple function is declared inline (if your compiler supports inlines) then there is no difference in performance.
2) the advantage of using inb() and outb() is portability of your program. If this is not an issue, then it is fine to access your port directly.
I am trying to use the expansion header to control a couple motors and auxiliary task mechanism. For this I am using the appropriate pins as GPIO and merely attempting to send high or low signals as needed by the robot. (For instance, I might need the robot to move forward and so I'd send high signals on both sets of pins, whereas if I needed the robot to turn I'd send a high signal to one pin and a low to the other.)
However, the problem is that the pins will only stay high! I've followed the conventions for sysfs just via the terminal, and, although I'm able to set the "values", "active_lows", etc. to 0 or 1, I can't actually get the pins to send 0V. After checking the beagle.h file I used for u-boot it looks like the multiplexer mode is configured correctly. This is also reflected when I get the info from sys/class/gpio/gpio%/% and sys/kernel/debug/gpio. Furthermore I don't get any errors or indication from anywhere that there is something wrong...it just doesn't work!
What should I do? For the first time in my life I have seemingly exhausted the internet...
details:
Beagleboard xm rev c1
ubuntu 12.04
kernel 3.6.8-x4
Im pretty new to the beagle board and I have recently been trying to configure the GPIO pins on my classic beagleboard c4, which i believe should be fairly similar.
Half of my GPIO pins seemed to work fine and the other half seemed to remain high or low no matter what i did. Even though they were configured the same way as the working pins in /sys/class/gpio/
have you tried to use other gpio pins?
I ended up following http://labs.isee.biz/index.php/Mux_instructions
to configure the mux to 4 and now i can control the pins that were not working.
I basically used the command:
sudo echo 0x004 > /sys/kernel/debug/omap_mux/(mux 0 name)
where (mux 0 name) was the name of the subsystem for the mux 0 setting for the gpio pin you wish to configure
ie. for gpio 183 on beagleboard c4
sudo echo 0x004 > /sys/kernel/debug/omap_mux/i2c2_sda
Though I had to change permissions to modify these files
As I said I am pretty new to the beagleboard and ubuntu but this worked for me so I thought I would share it with you, I hope it is of some help.
Regards;
Paul;
It seems that the beagleboard expansion pins are numbered in alternating fashion, as clearly and professionally depicted here.
Thanks to everyone for your help. I now know way more than I should about GPIO on OMAP systems (and so do you). Good luck on finals/life!**
tl;dr I'm an idiot!
Well, the question says it all.
What I would like to do is that, every time I power up the micro-controller, it should take some data from the saved data and use it. It should not use any external flash chip.
If possible, please give some code-snippet so that I can use them in AVR studio 4. for example if I save 8 uint16_t data it should load those data into an array of uint16_t.
You have to burn the data to the program memory of the chip if you don't need to update them programmatically, or if you want read-write support, you should use the built-in EPROM.
Pgmem example:
#include <avr/pgmspace.h>
PROGMEM uint16_t data[] = { 0, 1, 2, 3 };
int main()
{
uint16_t x = pgm_read_word_near(data + 1); // access 2nd element
}
You need to get the datasheet for the part you are using. Microcontrollers like these typically contain at least a flash and sometimes multiple banks of flash to allow for different bootloaders while making it easy to erase one whole flash without affecting another. Likewise some have eeprom. This is all internal, not external. Esp since you say you need to save programatically this should work (remember how easy it is to wear out a flash do dont save unless you need to). Either eeprom or flash will meet the requirement of having that information there when you power up, non-volatile. As well as being able to save it programmatically. Googling will find a number of examples on how to do this, in addition to the datasheet you apparently have not read, as well as the app notes that also contain this information (that you should have read). If you are looking for some sort of one time programmable fuse blowing thing, there may be OTP versions of the avr, and you will have to read the datasheets, programmers references and app notes on how to program that memory, and should tell you if OTP parts can be written programmatically or if they are treated differently.
The reading of the data is in the memory map in the datasheet, write code to read those adresses. Writing is described in the datasheet (programmers reference manual, users guide, whatever atmel calls it) as well and there are many examples on the net.