A13 baremetal programming, coding direct on hardware without linux or android

Started by saand, April 14, 2013, 04:28:00 AM

Previous topic - Next topic

saand

Hi All,
Has anyone achieved the ability to program with the A13 system without linux or android.

I am attempting to write a CPU demanding program which will need every last bit of CPU grunt, real time control and tight control of memory locations and peripherals.
I am not after video output, USB or wifi control.

I suspect all of the memory addresses and info for initializing the processor can be found in the source code for the linux system.

If anyone has anything going let me know.

JohnS

Look at U-boot and if you need more then Linux/Android

Nothing special needed but it's not a small/simple chip so neither is the code.

Follow lots of the URLs on Olimex pages for the Allwinner boards (and this forum if you like to read its posts).
That will take you to copious doc (but very incomplete) and code.

You know it's not a very fast CPU and its I/O pins much slower in many cases, I hope.
Good value, though!

John

saand

Hi John,
Thanks for the guidance,
I suspect i will still use uboot and have it point to an address to start running "my code" rather than linux. I guess i will look to the linux kernel source code to work out how it initializes the chip at start up and generally copy all the parts up until the processor is initialized.
Then for using peripherals i can make use of header files which will give memory locations of registers then i should be good to go. I am sure there will be something that will trip me up though.
If im successful i'll post instructions.

As for speed, this is the fastest CPU currently that doesn't require BGA soldering. at 1Ghz its quite powerful compared to most microprocessors which i am used to which run around 72MHz.
IO i am not too worried about, i suspect once i dont have linux inbetween my code and the hardware the IO will be sufficiently fast anyway.

My project is generally image processing of live video so i would like 5 or 10 frames a second which will involve processing a sequence of large images. Not too demanding for a 1Ghz processor i think (i hope) ;)

olimex

note there are also NEON co-processor and GPU which could be used for image processing

saand

Hi All,
After much researching documents, working out bugs on forums and help from a kind software developer i have managed to get a program running on the A13olinuxino board without linux or android.

It uses Uboot as the booting system which then executes a "stand alone" program.

The stand alone program is already created when uboot is compiled however there were a few issues getting it to execute and a bug was found in the sunxi port which henrik has now kindly fixed in the development branch

anyway long story short a hello world program executes.

Today i was also able to toggle a GPIO at 1MHz but still looking into a bug which is confusing me a bit before i publish how i did that, i would expect i could get much faster than 1MHz.

I have published how i have the hello world program working in the wiki
https://www.olimex.com/wiki/Bare_Metal_programming_A13

once i work out the GPIO bug ill update the wiki with GPIO toggling and hopefully how to include in additional features from the kernel.

JohnS

I could only get in the region of a bit less than 4MHz.  Tsvetan put that it's AMBA bottleneck in another thread on here.  It does seem incredibly slow for a 1GHz cpu!

I got faster with a PIC32 at 80MHz.  (It should be possible to run more code on the A13, though.)

I didn't try to get an accurate speed as I just wanted to see roughly how fast GPIO would go (and don't own a scope so put the signal through a divider to a LED).

I just stuck the code into U-boot itself (as I suggested above) to make it a quick hack.

John

saand

Hi John,
Interesting info. It makes sense that AMBA would cause a bottle neck. At 4MHz i wonder what else it will bottleneck. Now i know the suggested speeds of the busses ill look at the datasheet to see how it affects the other things ill try to do next.

As you have done this before i wonder if you can help with 2 questions

- I am currently having issues with GPIO where i attempt to toggle the GPIO by changing the memory mapped location. However that does not affect the GPIO unless i call the function tstc() This function checks for serial output.
I have not been able to find this function within the code yet (I am not used to developing in linux and dont yet know how to setup links between functions yet)
Do you know if something else needs to happen for the GPIO to be affected from the memory mapped location. I am guessing something with the memory bus

- How did you stick the code into U boot itself, are you also using a stand alone program as well or did you put it into the uboot code so it executes in the uboot code. If that is the case are you able to give instructions or a snapshot of the code and where you put it. I suspect this method would be a lot easier than the way i did it so may help others

JohnS

I literally changed U-boot a little.

So I know nothing about the function you mentioned or the environment of memory you're using.

First, get U-boot and check you can make it and it works from an SD card.

1. U-boot is on the net in various places, not sure which I used as I had it for ages before deciding to try this.
Chances are it's hno's
git clone https://github.com/hno/uboot-allwinner.git

2. Grab or build ARM cross-compiler such as from launchpad.net and use such as
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- a13_olinuxino_config
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- a13_olinuxino

3. Put on SD card such as
sudo dd if=spl/sunxi-spl.bin of=$1 bs=1024 seek=8
sudo dd if=u-boot.bin of=$1 bs=1024 seek=32
($1 needs to be your SD card as a raw device such as /dev/sdb)

4. Put in A13, boot and check it's OK

Next, change U-boot then re-do the above.

I really recommend reading the code.  U-boot has lots of good stuff in it and it's worth investing time in it.  At least figure out what the above 2 dd commands do and why plus find the board-specific code and study it.  U-boot is used widely in embedded systems so it's good to get to know it.

I figured I could tweak U-boot's LED command.  I added a line in boards.cfg like the existing one for my board but instead of SPL I used SPL,CMD_LED,STATUS_LED,BOARD_SPECIFIC_LED

Then I added board/allwinner/a13_olinuxino/led.c and put it in board/allwinner/a13_olinuxino/Makefile
(both attached, sorry not cleaned up)

Er... not attached as I can't see what to click on to do that - help!

Rebuilt and I think that was about it.  Using LED 1 ON or the like actually triggers a loop in led.c rather than the code you'd usually have.

Oh, hung a pair of divide-by-4096 (74HC4040) chips and a LED off the pin used (port G bit 9).

John

hno

sunxi u-boot repository is at

    https://github.com/linux-sunxi/u-boot-sunxi

if you insists on using mine personal repository then be warned that there may be unfinished stuff.

Some notes regarding running sunxi bare metal programs:

If your goal is just to load a bare metal program then there is no need for a full u-boot, just the SPL is sufficient to initialize the board. You can then dd a binary image of your program instead of u-boot.bin. SPL by default loads CONFIG_SYS_MONITOR_LEN (512KByte) amount of data at address CONFIG_SYS_TEXT_BASE(0x4A000000). Or if you use uImage format then any size & address is supported.

Another alternative if you want to benefit of the framework of u-boot is to write a u-boot standalone programs. This way you have access to the console and storage device I/O provided by u-boot. See examples/standalone/hello_world.c and doc/README.standalone in the u-boot sources.


JohnS: It would be great if you could post your u-boot changes for review to the linux-sunxi@googlegroups.com mailing list.

JohnS

Er, happy to do that but no idea how so will go try to find out LOL

Was purely for Olimex (non-Micro) A13 Olinuxino as it has a user LED.  I then subverted the led.c I'd written to waggle gpio as fast as I could.

John

saand

Hi All,
I am still working on just flashing an LED which is proving difficult to do reliably with the lack of doc.

I have written some code in the hello_world.c file that flashes an LED at around a 1 second interval. It doesn't use any of the build in uboot commands so using this tactic of changing memory locations should work for any peripherals and wont have licensing issues.

Unfortunately the only way to have this work is to include the print command. As soon as i take out the print command line
      printf ("A%d\n", foo);
the LED stops flashing.

I have to assume the print command does something to send the memory location being changed to the GPIO register.

Does anyone have any ideas what this could be?


#include <common.h>
#include <exports.h>
//#include <asm/arch-sunxi/cpu.h>
//#include <asm/arch/gpio.h>

#define CCMBase 0x01C20000 //clock module
#define Def_APB0_Gating CCMBase + 0x68
//#define Def_APB0_Gating 0x01C20068

#define GPIOBase 0x01C20800
#define GPIOIncrement 0x24

#define ALLWINNER_GPIO_A    GPIOBase
#define ALLWINNER_GPIO_B    GPIOBase + (1*GPIOIncrement)
#define ALLWINNER_GPIO_C    GPIOBase + (2*GPIOIncrement)
#define ALLWINNER_GPIO_D    GPIOBase + (3*GPIOIncrement)
#define ALLWINNER_GPIO_E    GPIOBase + (4*GPIOIncrement)
#define ALLWINNER_GPIO_F    GPIOBase + (5*GPIOIncrement)
#define ALLWINNER_GPIO_G    GPIOBase + (6*GPIOIncrement)
#define ALLWINNER_GPIO_H    GPIOBase + (7*GPIOIncrement)
#define ALLWINNER_GPIO_I    GPIOBase + (8*GPIOIncrement)

#define Port_CFG0 0x00 //pin direction and function 0 to 7
#define Port_CFG1 0x04 //pin direction and function 8 to 15
#define Port_CFG2 0x08 //pin direction and function 16 to 24
#define Port_CFG3 0x0C //pin direction and function 25 to 32
#define Port_DAT  0x10
#define Port_DRV0 0x14
#define Port_DRV1 0x18
#define Port_PUL0 0x1C


int hello_world (int argc, char * const argv[])
{
   int       i;
   int       j;

   uint32_t     *portGConfig;
   uint32_t     *portGData;
   uint32_t     *APB0Gating;

   /* Print the ABI version */
   app_startup(argv);

   printf ("Hello World\n");

   //setup pointers for registers
   portGConfig = (uint32_t *)(ALLWINNER_GPIO_G + Port_CFG1);
   portGData = (uint32_t *)(ALLWINNER_GPIO_G + Port_DAT);
   APB0Gating = (uint32_t *)(Def_APB0_Gating);

   //enable clocking for GPIO
   *APB0Gating |= 0x0020;
   //configure port G pin 9 to output
   *portGConfig |= 0x10;
   //set output to on
   *portGData |= 0x0200;


   int foo = 0;
   for (j = 0 ; j < 100 ; j++)
   {
      //toggle output
      *portGData ^= 0x0200;

      foo=j;
      for (i = 0 ; i < 30000000 ; i++)
      {
         if(i>10)
         {
            foo++;
         }
      }
      printf ("A%d\n", foo);
   }
   printf ("\n Finished A%d\n", foo);//must use "foo" to ensure look isn't optimised out by compiler

   return (0);
}

Fadil Berisha

I had similar problem during testing my SPL program developed for A13-micro. I used by accident printf before console was activated.

saand

thanks Fadil, good to know i wasn't the only one with this issue.

After a few weeks i finally found the issue.

It was my compilation flags in the make file. The compiler was compiling out the setting of a memory location.
I had a compilation flag of -Os and when i changed it to -O0 it was resolved.
Note: it doesnt come out in the text on here but the flag -O0 is actually - capital o then zero

Ill put my process and files on the wiki if anyone wants more info

JohnS

Further to the max speed of flashing a LED (less than 4 MHz), I now tried it on a Raspberry Pi.

Raspberry Pi is about 7 times faster.  So, less delay between cpu internals getting at GPIO.

John

keesj

Hi guys,

I am not much of a forum user. I spent some time in the last weeks doing the same kind of stuff you have been doing. I hope you are aware of the "User Manual"
http://dl.linux-sunxi.org/A13/A13%20User%20Manual%20-%20v1.2%20(2013-01-08).pdf it at least contains some basic information about registers and the memory map.

I have written what I know on this website:
http://keesj.github.io/A13-OlinuXino-playground/

I also pushed some documented code and scripts to build upload / test bare bones application(it works quite well). Checkout https://github.com/keesj/A13-OlinuXino-playground/tree/master/bare/00_serial_write . This code assumes u-boot us already on the device and depend on the initialization done by u-boot so not "real" bare bones.

keesj