Until now, Raspberry Pi remains one of the most popular technological gadgets. You can install almost any operating system on this board. But today we will talk about how to write programs for this board without an operating system, using only hardware.
What's the catch?
At first glance, the task seems trivial: download keil, create a project ... But everything is not so simple. All programming environments (keil, IAR, Atolic) support maximum ARM9. We have the same ARM11. This is due to the unspoken rule that they write on bare hardware before ARM9, and then on Linux. But still there is one loophole: arm-none-eabi-gcc supports any ARM.
The second problem is that under this processor (BCM2835) there are no configuration files, headers, etc. This is where the Raspberry Pi bootloader comes to the rescue. And nothing that he is proprietary. It performs two functions: it initializes the processor and its peripherals, and also transfers control to the kernel kernel.img. We will simply disguise our program as a kernel and the loader will launch it.
What do we need?
1) The Raspberry Pi itself, a memory card for it and power.
2)
Datasheet on the processor3) A computer with installed Linux (but maybe it can be on Windows. I do not know, I have not tried it).
4) Crosscompiler installed on the computer from point 3. I use
arm-none-eabi-gcc5) The contents of
this daddy.
Cooking
We need to format the memory card in FAT16 and drop the contents of
this folder onto it. This is the bootloader plus the kernel. Then we remove the files kernel.img and kernel_emergency.img from there. This is the Linux kernel, and we don't need it.
')
The first program.
Now we can start writing the first program. Create a file main.c and write the following code
int main (void) { while(1) { } } void exit (void) { while(1) { } }
As you can see, this program does nothing. The exit function is needed for some reason by the compiler.
Now we will collect it.
arm-none-eabi-gcc -O2 -mfpu = vfp -mfloat-abi = hard -march = armv6zk -mtune = arm1176jzf-s -nostartfiles main.c -o kernel.elf
arm-none-eabi-objcopy kernel.elf -O binary kernel.img
The resulting file kernel.img throw on the memory card. Done!
GPIO
It is unlikely that you will be satisfied with a program that will do absolutely nothing. Now try to light a light bulb.
To begin, let us announce the address where the GPIO is located (this can be read in the datasheet).
#define GPIO_BASE 0x20200000UL
And we declare a variable that determines that the port is configured for output (GPIO_GPFSEL1) and a variable that supplies a low level (that is, the light is on) to the port (GPIO_GPCLR0).
#define GPIO_GPFSEL1 1
#define GPIO_GPCLR0 10
Finally, we modify the main function for the ignition of the bulb:
volatile unsigned int* gpio; int main(void) { gpio = (unsigned int*)GPIO_BASE; gpio[GPIO_GPFSEL1] |= (1 << 16); gpio[GPIO_GPCLR0] = (1 << 16); while(1) { } }
We collect, stitch and rejoice.
In the next part we will try to play with timers and interrupts.