I'm using iMX6Q without any OS. Toggling GPIO was intended for testing purpose.
From the testing, the output frequency is only 700kHz. It's far less then expectation.
Do I miss anything?
---------
DETAILS
---------
- All settings remain default, one GPIO pin in GPIO_18 group was used.
- 4 Assembly lines was written for this routine.
- read GPIO register
- toggle GPIO pin (using XOR logic)
- write to GPIO register
- jump to 1st line
- Clock setting is shown as below:
- PLL1 - System : 792 MHz
- PLL2 - System Bus : 528 MHz
- IPG clock : 66 MHz
- AHB clock : 132 MHz
- AXI clock : 264 MHz
- DDR clock : 528 MHz
Hi Anson,
seems one can only enable caches (if they are not
yet enabled). Also one can try to write on assembler or
try another attached example (based on SDK).
Actually there are no other ways to make GPIO to toggle faster.
"MX6_PLATFORM_SDK "
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi,
I've tested 5.5Mhz in kernel space (3.0.5) using memory mapped + pointers (writel/readl is 100% slower): would be possible to improve this frequency using inline assembler?. Is there any example of inline assembler handling GPIOs?
Thanks,
Manuel.
Hi Anson,
What do you mean with "stable"? All the time?. If do: that's not possible. With a "regular" linux 100% not possible. Using a RTOS (i.e.: Xenomai) you can get a "relatively" stable throughput but of course not 5.5mbps/gpio. What I meant is we got toggle a GPIO at 5.5Mhz measured with an oscilloscope.
I hope to be helpful.
Manuel.
Hi EgleTeam,
I understand your point. I'm wondering how you could get 5.5Mhz waveform. Mind to share your toggling code and setting?
I'm using RTOS (QNX), it toggle at 1.6Mhz (Full waveform, from rising edge to next rising edge).
I tried assembler without OS, it toggle at 1.0Mhz (very stable, error of 0.003Mhz max).
CODE:
while(1){
GPIO = 0x1
GPIO = 0x0
}
Setting:
CPU = 982 MHz
AHB = 132 Mhz
IPG = 66Mhz
Rgds,
Anson
Anson,
--------------------
#define GPIO_VAL 0x0
#define GPIO_DIR 0x4
static void *GPIO4_BADDR;
..............................
GPIO4_BADDR = ioremap(0x20A8000, 28);
writel(0x00800000,GPIO4_BADDR+GPIO_DIR);
for(i=0;i<100;i++){
writel(0x00800000,GPIO4_BADDR+GPIO_VAL);
writel(0,GPIO4_BADDR+GPIO_VAL);
}
-----------------------------------
Toggle pin 24 - bank 4.
Hope to be helpful.
Manuel.
Anson,
so sorry: I copied/pasted some of our code too fast.
Please use a pointer instead of "writel":
volatile u32 *gpio4_val = (u32 *)GPIO4_BADDR;
for(i=0;i<100;i++){
*gpio4_val = 0x00800000;
*gpio4_val = 0;
}
Merry Christmas to all the community!
Manuel.
Nice programming and record, I was only able to toggle it at 3.6 MHz ! You can otpmize a few cycles @ 1 GHz but at one point there is a limit due to the fact we have to go through caches, a couple of crossbars and a peripheral bridge @ 66 MHz. The trick to reproduce it with platform SDK (and QNX, they should be aware of this) was to enable caches, MMU and configure mmu entry for those as a standard entry and not as strongly ordered as it is by default, it allows the accesses to be buffered :
+ mmu_enable();
+ // Enable L2 Cache
+ _l2c310_cache_setup();
+ _l2c310_cache_invalidate();
+ _l2c310_cache_enable();
- mmu_map_l1_range(0x00a00000, 0x00a00000, 0x0f600000, kStronglyOrdered,kShareable, kRWAccess); // More peripherals
+ mmu_map_l1_range(0x00a00000, 0x00a00000, 0x0f600000, kDevice, kShareable, kRWAccess); // More peripherals
I forgot, there's another way from userspace, perhaps "more comfortably" than implement a kernel driver/module as we did: mapping on "/dev/mem". Here an example for i.MX233:
OLINUXINO/gpio-mmap.h at master · OLIMEX/OLINUXINO · GitHub
Now we are testing this code for i.MX28 but shouldn't be hard to port it for i.MX6.
Regards,
Manuel.
Anson,
I will look for the code tomorrow in the office and share. On any case it was not very complicated, just write to the RAM location where the gpio value register (GPIOx_DR) is mapped.
Regards,
Manuel.