Olimex Support Forum

OLinuXino Android / Linux boards and System On Modules => A13 => Topic started by: Vinuthan on March 11, 2013, 02:49:44 PM

Title: Help regarding programming for GPIOs on A13, without any linux kernel overhead
Post by: Vinuthan on March 11, 2013, 02:49:44 PM
Hi friends,
I want to control the GPIOs present on my A13 olinuxino Wifi without any linux overhead(like debian or android). I know there are API, libraries available on debain in python. But i don't like to use them.
So, how can i program my board without any of these. Are there any IDEs available or any other preferred ways i can use this.

Please help me with this regard.

Thank you.
Title: Re: Help regarding programming for GPIOs on A13, without any linux kernel overhead
Post by: JohnS on March 11, 2013, 05:26:21 PM
What has IDE (or non-IDE) to do with the overhead you allege?

The only way to avoid kernel overhead is not to have a kernel.  I bet you don't want to go that way!

Take a good look at the just-posted GPIO code.

John
Title: Re: Help regarding programming for GPIOs on A13, without any linux kernel overhead
Post by: jwischka on March 11, 2013, 05:50:09 PM
Quote from: Vinuthan on March 11, 2013, 02:49:44 PM
Hi friends,
I want to control the GPIOs present on my A13 olinuxino Wifi without any linux overhead(like debian or android). I know there are API, libraries available on debain in python. But i don't like to use them.
So, how can i program my board without any of these. Are there any IDEs available or any other preferred ways i can use this.

Please help me with this regard.

Thank you.

You are basically asking, "How can I run my computer without an operating system?" and the answer is, "You can't."

If you want something that doesn't have an OS overhead, you want a dedicated microcontroller board like an Arduino. Any board with a generic microprocessor is going to need some sort of kernel. You can, if you'd like, put together a rather lean kernel with a minimal OS, or you can try to go with the Xenomai thread to get more RT like performance.

You don't have to use Python (and maybe shouldn't, depending on your application), but you do have to use an operating system.
Title: Re: Help regarding programming for GPIOs on A13, without any linux kernel overhead
Post by: Vinuthan on March 12, 2013, 12:36:09 PM
The IDE is asked was like there are IDEs for microcontrollers like KEIL and more, So i asked are there any IDEs for ARMv7 processors for programming and compiliation.

The kernel is required to initialize and communicate with all the peripherials on the board.
I just need to interface the GPIOs as they are directly connected to the chip. I know this may not serve that much as i may not make complete use of my board, and also can achieve the objective using a simple microcontroller.
But i wanted to try it out on this board.
Title: Re: Help regarding programming for GPIOs on A13, without any linux kernel overhead
Post by: jwischka on March 12, 2013, 05:27:36 PM
Quote from: Vinuthan on March 12, 2013, 12:36:09 PM
The IDE is asked was like there are IDEs for microcontrollers like KEIL and more, So i asked are there any IDEs for ARMv7 processors for programming and compiliation.

The kernel is required to initialize and communicate with all the peripherials on the board.
I just need to interface the GPIOs as they are directly connected to the chip. I know this may not serve that much as i may not make complete use of my board, and also can achieve the objective using a simple microcontroller.
But i wanted to try it out on this board.

Again, I think you are misunderstanding how ARM7 processors, and ARM7 SOCs in particular work. But the answer to your question is no, nothing like that for this board, or for ARM7 boards in general. The GPIOs are not connected to the chip, they are a part of the chip itself.
Title: Re: Help regarding programming for GPIOs on A13, without any linux kernel overhead
Post by: JohnS on March 12, 2013, 06:18:15 PM
With "some" effort I expect Eclipse+gdb+OpenOCD with JTAG would work.

If the above isn't immediately obvious, I suggest to change "some" into "a lot of learning and then some".

John
Title: Re: Help regarding programming for GPIOs on A13, without any linux kernel overhead
Post by: olimex on March 12, 2013, 06:46:01 PM
is it possible?
yes, sure it is, but I do not see the point to use 1Ghz processor to drive some GPIOs

one AVR will drive GPIOs faster and much easier

people use OS on Cortex-A8 devices as there are *hundreds* of registers you should initialize before you are able even to blink a LED

open imx6 or AM335x users manual and read all 3000+ pages with registers to get a glue what amount of work you are asking about, for A13 all initilizations are in the kernel and there is even no description what register what is doing
Title: Re: Help regarding programming for GPIOs on A13, without any linux kernel overhead
Post by: JohnS on March 12, 2013, 07:23:20 PM
To be fair, I think the A13 would be a lot faster than AVR!

(But painful.)

John
Title: Re: Help regarding programming for GPIOs on A13, without any linux kernel overhead
Post by: olimex on March 12, 2013, 10:33:16 PM
ARM GPIOs are slow IIRC imx233 (@454Mhz) max GPIO toggle we achieved was less 6Mhz (about 5.7Mhz), on A13 (@1008MHz) they are even slower something like 3.5Mhz with the Allwinner's kernel and 1.5Mhz with Linux-sunxi kernel as there some internal bus PLL divider is not set correctly

one small AVR will toggle GPIOs at much higher speed, so to use Cortex-A8 @1Ghz to toggle GPIOs is waste of resources, the benefit would be that A13 will keep toggling these GPIOs at 1.5Mhz even if play HD video at the same time, while AVR will not :)
Title: Re: Help regarding programming for GPIOs on A13, without any linux kernel overhead
Post by: JohnS on March 12, 2013, 11:01:27 PM
I don't see the relevance of the PLL?

I thought the test for how fast a GPIO can be is a software loop essentially:
while (1) sethi(), setlow();

Isn't 1GHz A13 far faster doing that?

Important not to use python and keep code simple (no syscalls, no long-winded libs)...

John
Title: Re: Help regarding programming for GPIOs on A13, without any linux kernel overhead
Post by: olimex on March 13, 2013, 08:47:52 AM
this loop will execute at 1Ghz in the core cache :)
when it access the AMBA bus where the GPIOs are connected it will have to wait a lot until the bus responds
Title: Re: Help regarding programming for GPIOs on A13, without any linux kernel overhead
Post by: JohnS on March 13, 2013, 09:03:09 AM
A 'scope would  be useful LOL

John
Title: Re: Help regarding programming for GPIOs on A13, without any linux kernel overhead
Post by: Vinuthan on March 13, 2013, 04:35:34 PM
Ya, they are part of the chip that is what i referred the metal pins on the board are connected.
But i did not know there were so many registers to be initialized before playing with the GPIOs.

I just now had a look at the AM335x as you referred, and it has some 170kB on chip ROM within it. How much does A13 processor has? So, i think this is the memory(bootloader) which initializes a small part of the chip and passes the control to either the NAND or MMC where u-boot and linux kernel can take over the initialization process and proceed with it.

Am i right about this?

Also, i have an A13 olinixino Wifi which comes with Android onboard the NAND flash. Can i use the MMC to boot another OS or perform other process?. I mean what is the boot order in which the board performes booting.
Is it first MMC, then NAND. Or the other way round.

Please help me with this regard, i don't want to mess up my NAND flash.
Title: Re: Help regarding programming for GPIOs on A13, without any linux kernel overhead
Post by: crubille on March 13, 2013, 08:26:37 PM
Quote from: olimex on March 13, 2013, 08:47:52 AM
this loop will execute at 1Ghz in the core cache :)
when it access the AMBA bus where the GPIOs are connected it will have to wait a lot until the bus responds

Oh, I thought the long delay (and even min delay) we have in xenomai are cache flush latency, but perhaps it is just that.

I look at the register which define the clock for the AMBA and so if all the divisors are at their maximum value, the APB bus get a 4MHz clock. Coherent with what you see.

Title: Re: Help regarding programming for GPIOs on A13, without any linux kernel overhead
Post by: crubille on March 14, 2013, 01:17:38 AM
It look like there is no effective configuration for the AMBA in the linux kernel. There is 2 different codes about it in the 3.4.24 kernel but none are active at least with my .config.

I dump the key register which define the divisors between the CPU Clock, AXI, AHB and APB:

- AXI_CLOCK is set at CPU_CLOCK/3 = 333 MHz   
- AHB_CLOCK is set at AXI_CLOCK/8 = 41.6 MHz  # and this is very slow for AHB
- APB_CLOCK is set at AHB_CLOCK/2 = 20.8 MHz  # and 3 cycles per read or write

Sure we can found a better config.
Title: Re: Help regarding programming for GPIOs on A13, without any linux kernel overhead
Post by: olimex on March 14, 2013, 10:33:36 AM
how do you dump the key register?
as the kernel on Allwinner Android image toggle GPIOs at double speed, so we can see how AXI AHB APB clocks are initialized there
with no proper docs we can only assume that Allwinner setup their clocks correctly :)
Title: Re: Help regarding programming for GPIOs on A13, without any linux kernel overhead
Post by: crubille on March 14, 2013, 09:50:00 PM
 ;D                     ;D
    ;D               ;D
       ;D         ;D
          ;D   ;D
             ;D

So, I patch the linux kernel roughly and set the AHB divisor to 1,
compile,
reboot,


So PLL1 is at 1000 MHz, AXI at 333MHz
AHB was at 41.6 MHz and is now at 166 MHz
APB was at 20.8 MHz ans is now at 83,3 MHz



It look ok. I check the SYSCLKDIV is  was it should be.

Then i do some xenomai test:

first "echo 0 > /proc/xenomai/latency"  so there is no pre calibration of the delay.

xenomai task in user mode:
"latency -p 100" minimal time from 8.9 micro seconds to 4.0 micro seconds - more than twice
"latency -p 100" average time from 10.4 micro seconds to 4.8 micro seconds - more than twice

xenomai driver in kernel mode:
"latency -p 100 -t 2" minimal time from 4.58 micro seconds to 1.33 micro seconds - more than three times faster
"latency -p 100 -t 2" average time from 5.58 micro seconds to 1.77 micro seconds - more than three times faster

I check the usb and mmc access too:
"hdparm -tT /dev/uba"  throughput go from 18.2 to 18.7 - just a bit better
"hdparm -tT /dev/mmcblk0"  throughput go from 20.4 to 20.7 - not significant.

I copy a large file from my host to the A13 with "scp" and get 2.7MB/s - so ethernet is ok;

The display with VGA is OK.

The proc is not warmer.

Only one point: The patch is really ugly  :P


Title: Re: Help regarding programming for GPIOs on A13, without any linux kernel overhead
Post by: crubille on March 14, 2013, 10:11:02 PM
I patch the kernel to get the register state and all the modification of PLL (which are done from the code in this file).
Just a little line change the divisor for ABP.


Then, after booting just to:
"dmesg | grep PC-MSG"


Here is the patch (from kernel 3.4.24 )


pc@debian:~$ cat /usr/src/sysclk.patch
--- linux-sunxi-sunxi-3.4/arch/arm/mach-sun5i/clock/ccmu/ccm_sys_clk.c  2013-02-21 19:50:22.000000000 +0000
+++ linux-sunxi-sunxi-3.4-xenomai-prio_irq/arch/arm/mach-sun5i/clock/ccmu/ccm_sys_clk.c 2013-03-14 18:07:13.000000000 +0000
@@ -725,10 +725,12 @@
             /* delay 500us for pll be stably */
             __delay((rate >> 20) * 500 / 2);

+printk(KERN_NOTICE "PC-MSG set PLL1 rate : %lld \n", rate);
             return 0;
         }
         case AW_SYS_CLK_PLL2:
         {
+printk(KERN_NOTICE "PC-MSG set PLL2 rate : %lld \n", rate);
             if(rate == 22579200)
             {
                 /* chip is version B, FactorN=79, PreDiv=21, PostDiv=4,
@@ -759,6 +761,7 @@
         }
         case AW_SYS_CLK_PLL2X8:
         {
+printk(KERN_NOTICE "PC-MSG set PLL2x8 rate : %lld \n", rate);
             if((sys_clk_get_rate(AW_SYS_CLK_PLL2) == 24576000) && (rate == 24576000 * 18))
             {
                 return 0;
@@ -773,6 +776,13 @@
         }
         case AW_SYS_CLK_PLL3:
         {
+printk(KERN_NOTICE "PC-MSG SysClkDiv AXI %d - AHB %d - APB %d -- SRC-CPU %d - SRC-AHB %d\n",
+       aw_ccu_reg->SysClkDiv.AXIClkDiv ,
+       aw_ccu_reg->SysClkDiv.AHBClkDiv ,
+       aw_ccu_reg->SysClkDiv.APB0ClkDiv ,
+       aw_ccu_reg->SysClkDiv.AC328ClkSrc ,
+       aw_ccu_reg->SysClkDiv.AHBClkSel );
+printk(KERN_NOTICE "PC-MSG set PLL3 rate : %lld \n", rate);
             if((rate < 9*3000000) || (rate > (127*3000000)))
             {
                 CCU_ERR("Rate(%lld) is invalid when set PLL3 rate!\n", rate);
@@ -798,6 +808,7 @@
         }
         case AW_SYS_CLK_PLL3X2:
         {
+printk(KERN_NOTICE "PC-MSG set PLL3x2 rate : %lld \n", rate);
             if(rate == (sys_clk_get_rate(AW_SYS_CLK_PLL3) << 1))
             {
                 return 0;
@@ -808,6 +819,9 @@
         {
             struct core_pll_factor_t    factor;
             __u32   tmpDly = ccu_clk_uldiv(sys_clk_get_rate(AW_SYS_CLK_CPU), 1000000) * 200;
+printk(KERN_NOTICE "PC-MSG set PLL4 rate : %lld \n", rate);
+
+ aw_ccu_reg->SysClkDiv.AHBClkDiv = 1 ;// PC-MSG - PATCH SAUVAGE !!

             ccm_clk_get_pll_para(&factor, rate);

@@ -824,7 +838,7 @@
         case AW_SYS_CLK_PLL5:
         {
             __s32   tmpFactorN, tmpFactorK;
-
+printk(KERN_NOTICE "PC-MSG set PLL5 rate : %lld \n", rate);
             if(rate < 240000000)
             {
                 CCU_ERR("Rate(%lld) is invalid when set PLL5 rate!\n", rate);
@@ -865,7 +879,7 @@
         {
             __u32   tmpFactorM;
             __s64   tmpPLL5;
-
+printk(KERN_NOTICE "PC-MSG set PLL5M rate : %lld \n", rate);
             tmpPLL5 = sys_clk_get_rate(AW_SYS_CLK_PLL5);
             if((rate > tmpPLL5) || (tmpPLL5 > rate*4))
             {
@@ -880,6 +894,7 @@
         }
         case AW_SYS_CLK_PLL5P:
         {
+printk(KERN_NOTICE "PC-MSG set PLL5P rate : %lld \n", rate);
             __s32   tmpFactorP = -1;
             __s64   tmpPLL5 = sys_clk_get_rate(AW_SYS_CLK_PLL5);

@@ -898,6 +913,8 @@
         {
             __s32   tmpFactorN, tmpFactorK;

+printk(KERN_NOTICE "PC-MSG set PLL6 rate : %lld \n", rate);
+
             if(rate <= 600000000)
                 tmpFactorK = 0;
             else if(rate <= 1200000000)
@@ -925,6 +942,8 @@
             __s64   tmpPLL6 = sys_clk_get_rate(AW_SYS_CLK_PLL6);
             __s32   tmpFactorM = ccu_clk_uldiv(tmpPLL6, rate*6);

+printk(KERN_NOTICE "PC-MSG set PLL6M rate : %lld \n", rate);
+
             tmpFactorM = tmpFactorM ? tmpFactorM : 1;
             aw_ccu_reg->Pll6Ctl.FactorM = tmpFactorM - 1;
             return 0;
@@ -936,6 +955,7 @@
         }
         case AW_SYS_CLK_PLL7:
         {
+printk(KERN_NOTICE "PC-MSG set PLL7 rate : %lld \n", rate);
             if((rate < 9*3000000) || (rate > (127*3000000)))
             {
                 CCU_ERR("Rate(%lld) is invalid when set PLL7 rate!\n", rate);
@@ -961,6 +981,7 @@
         }
         case AW_SYS_CLK_PLL7X2:
         {
+printk(KERN_NOTICE "PC-MSG set PLL7x2 rate : %lld \n", rate);
             if(rate == (sys_clk_get_rate(AW_SYS_CLK_PLL7) << 1))
             {
                 return 0;
@@ -969,6 +990,7 @@
         }
         case AW_SYS_CLK_200M:
         {
+printk(KERN_NOTICE "PC-MSG set CLK_200M rate : %lld \n", rate);
             if(rate == 200000000)
             {
                 return 0;
@@ -981,6 +1003,7 @@
         case AW_SYS_CLK_CPU:
         {
             __s64   tmpRate = sys_clk_get_rate(sys_clk_get_parent(AW_SYS_CLK_CPU));
+printk(KERN_NOTICE "PC-MSG set CLK_CPU rate : %lld \n", rate);

             if(rate != tmpRate)
             {
@@ -996,6 +1019,7 @@
         case AW_SYS_CLK_AXI:
         {
             __s32   tmpDiv = ccu_clk_uldiv(sys_clk_get_rate(AW_SYS_CLK_CPU) + (rate - 1), rate);
+printk(KERN_NOTICE "PC-MSG set CLK_AXI rate : %lld \n", rate);
             if(tmpDiv > 4)
             {
                 CCU_ERR("Rate(%lld) is invalid when set axi rate\n", rate);
@@ -1009,7 +1033,7 @@
         case AW_SYS_CLK_AHB:
         {
             __s32   tmpVal = -1, tmpDiv = ccu_clk_uldiv(sys_clk_get_rate(AW_SYS_CLK_AXI) + (rate - 1), rate);
-
+printk(KERN_NOTICE "PC-MSG set CLK_AHB rate : %lld \n", rate);
             if(tmpDiv > 8)
             {
                 CCU_ERR("Rate(%lld) is invalid for set AHB rate!\n", rate);
@@ -1024,7 +1048,7 @@
         case AW_SYS_CLK_APB0:
         {
             __s32   tmpVal = -1, tmpDiv = ccu_clk_uldiv(sys_clk_get_rate(AW_SYS_CLK_AHB) + (rate - 1), rate);
-
+printk(KERN_NOTICE "PC-MSG set CLK_APB0 rate : %lld \n", rate);
             if(tmpDiv > 8)
             {
                 CCU_ERR("Rate(%lld) is invalid for set APB0 rate!\n", rate);
@@ -1040,6 +1064,7 @@
         {
             __s64   tmpRate = sys_clk_get_rate(sys_clk_get_parent(AW_SYS_CLK_APB1));
             __s32   tmpDivP, tmpDivM;
+printk(KERN_NOTICE "PC-MSG set CLK_APB1 rate : %lld \n", rate);

             if(tmpRate < rate)
             {