205 lines
10 KiB
Plaintext
205 lines
10 KiB
Plaintext
|
|
This repo serves as a collection of low level examples. No operating
|
|
system, embedded or low level embedded or deeply embedded or bare metal,
|
|
whatever your term is for this.
|
|
|
|
I am in no way shape or form associated with the raspberry pi organization
|
|
nor broadcom. I just happen to own one (some) and am sharing my
|
|
experiences. The raspberry pi is about education, and I feel low
|
|
level education is just as important as Python programming.
|
|
|
|
From what we know so far there is a gpu on chip which:
|
|
|
|
1) boots off of an on chip rom of some sort
|
|
2) reads the sd card and looks for additional gpu specific boot files
|
|
bootcode.bin, loader.bin, start.elf in the root dir of the first partition
|
|
(fat formatted)
|
|
3) in the same dir it looks for config.txt which you can do things like
|
|
change the arm speed from the default 700MHz, change the address where
|
|
to load kernel.img, and many others
|
|
4) it reads kernel.img the arm boot binary file and copies it to memory
|
|
5) releases reset on the arm such that it runs from the address where
|
|
the kernel.img data was written
|
|
|
|
I have tried a few things for example incorrectly assuming kernel.img
|
|
was loaded at address 0x00000000 as a default. If you tell it zero you
|
|
still get 0x8000. The arm and gpu share memory I am guessing the gpu
|
|
is using that first part of memory, dont really know. 0x8000 being
|
|
familiar to linux folks and this is intended to be first a linux
|
|
computer so this makes sense.
|
|
|
|
You will want to go here
|
|
http://elinux.org/RPi_Hardware
|
|
And get the datasheet for the part
|
|
http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
|
|
(might be an old link, find the one on the wiki page)
|
|
And the schematic for the board
|
|
http://www.raspberrypi.org/wp-content/uploads/2012/04/Raspberry-Pi-Schematics-R1.0.pdf
|
|
(might be an old link, find the one on the wiki page)
|
|
|
|
Early in the BCM2835 document you see a memory map. I am going to
|
|
operate based on the middle map, this is how the ARM comes up. The
|
|
left side is the system which we dont have direct access to in that
|
|
form, the gpu probably, not the ARM. The ARM comes up with a memory
|
|
space that is basically 0x40000000 bytes in size as it mentions in
|
|
the middle chart. 256MBytes is 0x10000000, I am guessing they gave
|
|
room to add memory as peripherals are mapped into arm address space at
|
|
0x20000000. When you see 0x7Exxxxxx in the manual replace that with
|
|
0x20xxxxxx as your ARM physical address. Experimentally I have seen
|
|
the memory repeats every 0x40000000, read 0x40008000 and you see the
|
|
data from 0x8000. I wouldnt rely on this, just an observation (likely
|
|
ignoring the upper address bits in the memory controller).
|
|
|
|
Now this memory map shows that somewhere within the SDRAM address space
|
|
there is a boundary between the ARM memory in the lower addresses and
|
|
the GPU memory in the upper addresses. That boundary is not explained
|
|
in that document. There are at the moment three gpu start.elf files
|
|
to choose from. A or the difference between them is where this boundary
|
|
lies. The default is a 50/50 split the arm gets 128MBytes, and the gpu
|
|
128MBytes. arm224_start.elf for example gives 224MBytes to the ARM
|
|
and 32MBytes to the GPU. They say that you dont get full gpu performance
|
|
if you limit the gpu memory this much. These examples are all going
|
|
to assume that the ARM only has 128MBytes and the default boot setting
|
|
of 0x8000 for the kernel_address.
|
|
|
|
I do not normally use .data nor gcc libraries nor C libraries so you can
|
|
build most if not all of my examples using a gcc cross compiler. Basically
|
|
it doesnt matter if you use arm-none-linux-gnueabi or arm-none-eabi.
|
|
What was formerly codesourcery.com still has a LITE version of their
|
|
toolchain which is easy to come by, easy to install and well maybe not
|
|
easy to use but you can use it. Building your own toolchain from gnu
|
|
sources (binutils and gcc) is fairly straight forward see the build_gcc
|
|
directory for a build script.
|
|
|
|
As far as we know so far the Raspberry Pi is not "brickable". Normally
|
|
what brickable means is the processor relies on a boot flash and with
|
|
that flash it is possible to change/erase it such that the processor will
|
|
not boot normally. Brickable and bricked sometimes excludes things
|
|
like jtag or speciall programming headers. From the customers perspective
|
|
a bricked board is...bricked. But on return to the vendor they may
|
|
have other equipment that is able to recover the board without doing
|
|
any soldering, perhaps plugging in jtag or some other cable on pins/pads
|
|
they have declared as reserved. Take apart a tv remote control or
|
|
calculator, etc and you may see some holes or pads on the circuit board,
|
|
for some of these devices just opening the battery case you have a view
|
|
of some of the pcboard. This is no doubt a programming header. Long
|
|
story short, so far as I know the Raspberry Pi is not brickable because
|
|
the rom/flash that performs the initial boot is for the gpu and we dont
|
|
have access to the gpu nor its boot rom/flash. The gpu relies on the
|
|
sd card to complete the boot, so the sd card flash is really the boot
|
|
flash for the system. And it is very easy for the customer to remove
|
|
and replace/modify that boot flash. So from a software perspective
|
|
unless you/we accidentally figure out how to change/erase the gpu boot
|
|
code (my guess is it is a one time programmable) you cant brick it.
|
|
|
|
To use my samples you do not need a huge sd card. Nor do you need nor
|
|
want to download one of the linux images, takes a while to download,
|
|
takes a bigger sd card to use, and takes forever to write to the sd card.
|
|
AND I am not able to run with the firmware on those cards. I use the
|
|
firmware from http://github.com/raspberrypi. The minimum configuration
|
|
you need to get started at this level is:
|
|
|
|
go to http://github.com/raspberrypi, you DO NOT need to download
|
|
the repo, they have some large files in there you will not need (for
|
|
my examples). go to the firmware directory and then the boot directory.
|
|
For each of these files, bootcode.bin, loader.bin, start.elf (NOT
|
|
kernel.img, dont need it, too big). Click on the file name, it will
|
|
go to another page then click on View Raw and it will let you download
|
|
the file. For reference, I do not use nor have a config.txt file on my
|
|
sd card. I only have the four files.
|
|
|
|
bootcode.bin is about 2MBytes, the other files are smaller, so you will
|
|
want an sd card that is at least a few meg, probably a full 128MBytes or
|
|
256MBytes or larger (gigabytes are just fine) for the gpu files plus
|
|
the sample files here. ARM memory for these samples is assumed 128MB
|
|
so they wont be even that large.
|
|
|
|
What I do is setup the sd card with a single partition, fat32. And
|
|
copy the above files. bootcode.bin, loader.bin and start.elf. From
|
|
there you take .bin files from my examples and place them on the sd card
|
|
with the name kernel.img. It wont take you very long to figure out this
|
|
is going to get painful.
|
|
|
|
1) power off raspi
|
|
2) remove sd card
|
|
3) insert sd card in reader
|
|
4) plug reader into computer
|
|
5) mount/wait
|
|
6) copy binary file to kernel.img
|
|
7) sync/wait
|
|
8) unmount
|
|
9) insert sd card in raspi
|
|
10) power raspi
|
|
11) repeat
|
|
|
|
There are ways to avoid this, one is jtag, which is not as expensive
|
|
as it used to be. It used to be in the thousands of dollars, now it
|
|
is under $50 and the software tools are free. Now the raspi does have
|
|
jtag on the arm, getting the jtag connected to that is going to require
|
|
some soldering. (this is described later and in the armjtag sample).
|
|
|
|
Another method is a bootloader, typically you use a serial port connected
|
|
to the target processor. That processor boots a bootloader program that
|
|
in some way, shape, or form allows you to interact with the bootloader
|
|
and load programs into memory (that the bootloader is not using itself)
|
|
and then the bootloader branches/jumps to your program. If your program
|
|
is still being debugged and you want to try again, you reboot the processor
|
|
the bootloader comes up and you can try again without having to move any
|
|
sd cards, etc. The sd card dance above is now replaced with the
|
|
bootloader dance:
|
|
|
|
1) power off raspi
|
|
2) power on raspi
|
|
3) type command to load and start new program
|
|
|
|
I have working bootloader examples. bootloader03 is the currently
|
|
recommended version. But you need more hardware (no soldering is
|
|
required). For those old enough to know what a serial port is, you
|
|
CANNOT connect your raspberry pi directly to this port, you will fry
|
|
the raspberry pi. You need some sort of serial port at 3.3V either
|
|
a level shifter of some sort (transceiver like a MAX232) or a usb
|
|
serial port where the signals are 3.3V (dont need to use RS232 just
|
|
stay at the logic level). The solution I recommend is a non-solder
|
|
solution:
|
|
|
|
http://www.sparkfun.com/products/9873
|
|
plus some male/female wire
|
|
http://www.sparkfun.com/products/9140
|
|
|
|
Solutions that may involve soldering
|
|
http://www.sparkfun.com/products/718
|
|
http://www.sparkfun.com/products/8430
|
|
|
|
Or this for level shifting to a real com port.
|
|
http://www.sparkfun.com/products/449
|
|
|
|
On the raspberry pi, the connector with two rows of a bunch of pins is
|
|
P1. Starting at that corner of the board, the outside corner pin is
|
|
pin 2. From pin 2 heading toward the yellow rca connector the pins
|
|
are 2, 4, 6, 8, 10. Pin 6 connect to gnd on the usb to serial board
|
|
pin 8 is TX out of the raspi connect that to RX on the usb to serial
|
|
board. pin 10 is RX into the raspi, connect that to TX on the usb to
|
|
serial board. Careful not to have metal items on the usb to serial
|
|
board touch metal items on the raspberry pi (other than the three
|
|
connections described). On your host computer you will want to use
|
|
some sort of dumb terminal program, minicom, putty, etc. Set the
|
|
serial port (usb to serial board) to 115200 baud, 8 data bits, no
|
|
parity, 1 stop bit. NO flow control. With minicom to get no flow
|
|
control you normally have to save the config, exit minicom, then
|
|
restart minicom and load the config in order for flow control
|
|
changes to take effect. Once you have a saved config you dont have
|
|
to mess with it any more.
|
|
|
|
Read more about the bootloaders in their local README files. Likewise
|
|
if you are able to do some soldering on electronics see the armjtag
|
|
README file. Other than chewing up a few more GPIO pins, and another
|
|
thing you have to buy, the jtag solution is the most powerful and useful.
|
|
My typical setup is the armjtag binary as kernel.img, a usb to jtag
|
|
board like the amontec jtag-tiny and a usb to serial using minicom.
|
|
|
|
As far as these samples go I recommend starting with blinker01 then
|
|
follow the discovery of the chip into uart01, etc. You will need some
|
|
sort of cross compiler (well maybe a native compiler on a raspberry pi
|
|
or other arm system). See the build_gcc directory if you cant get
|
|
the LITE version from codesourcery.com (now mentor graphics).
|