wip
This commit is contained in:
380
README.md
380
README.md
@@ -1,380 +0,0 @@
|
||||
|
||||
The main directory examples are for the older/est pi1 boards maybe
|
||||
some attempts at newer boards. These are retained for legacy reasons
|
||||
some folks have direct links. They are still valid for those boards.
|
||||
The boards directory has the first attempt at solving the too many
|
||||
boards issue and that is where I recommend you go. My third string
|
||||
attempt is I have a raspberrypi-zero and raspberrypi-three repos that
|
||||
are for those boards specifically. Little to no verbage though, the
|
||||
rambling text is mostly in this repo.
|
||||
|
||||
--------------
|
||||
|
||||
This repo is getting a bit messy starting with the first released to
|
||||
the public pi and then all that came after. I want to rework it but
|
||||
it is going slowly. Recently started creating directories pi1, piaplus
|
||||
and so on to target the examples specifically to the different cards.
|
||||
Again that is slow going. Likewise this README will be rewritten perhaps
|
||||
but for now...
|
||||
|
||||
--------------
|
||||
|
||||
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 bare
|
||||
metal education is just as important as Python programming.
|
||||
|
||||
So I started this years ago when got my first ARM11 based raspberry pi
|
||||
maybe we call that a raspberry pi 1, I dont know a good term. But
|
||||
now there is a growing number of variations.
|
||||
|
||||
ARM11 based (BCM2835)
|
||||
Raspberry Pi B
|
||||
Raspberry Pi B2
|
||||
Raspberry Pi A+
|
||||
Raspberry Pi B+
|
||||
Raspberry Pi Zero
|
||||
Cortex-A7 based (BCM2836)
|
||||
Raspberry Pi 2 B
|
||||
Cortex-A53 based (BCM2837)
|
||||
Raspberry Pi 3 B
|
||||
|
||||
There is also the compute module but I dont have one of those.
|
||||
|
||||
General differences that we care about for these examples. The amount
|
||||
of ram varies from board to board. The peripheral base address is
|
||||
different between the BCM2835 and BCM2836. The BCM2835 looks for the
|
||||
file kernel.img the BCM2836 looks for kernel7.img. The ARM11 based
|
||||
Zero is a B with stuff removed and a new layout, but they up/over
|
||||
clocked the processor from 750MHz to 1000MHz, one led on gpio 16. The
|
||||
A+ and B+ they moved the led (or put two) on gpio 35 and 47. The
|
||||
raspberry pi 2 is B+ like but with the different chip, supposedly the
|
||||
BCM2836 is BCM2835 with the ARM11 core removed and replaced with
|
||||
the Cortex A7 and for the most part it appears to be. The raspberry
|
||||
pi 3 is Cortex A8 based, 64 bit. And they moved the LED (the leds)
|
||||
to an i2c gpio expander.
|
||||
|
||||
As of this writing I am adding plus and pi2 versions of the examples
|
||||
as many of them are based on the early/original. No guarantees I will
|
||||
do that, just looking at the differences between the blinker01 examples
|
||||
should show you what to do to convert these yourself. In some cases
|
||||
I am intentionally not trying to have one code base build for all
|
||||
three with ifdefs and such, keep it simple stupid then complicate it
|
||||
as needed. The text may say kernel.img but substitute with kernel7.img
|
||||
as needed.
|
||||
|
||||
I still have a number of raspberry pi 2 examples to port, and now a
|
||||
bunch of examples to port to the raspberry pi 3. The raspberry pi 3
|
||||
as of this writing, without a config.txt, is switched to 32 bit
|
||||
compatibility mode. See the aarch64 directory for 64 bit ARM examples.
|
||||
|
||||
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 and start.elf in the root dir of the first partition
|
||||
(fat32 formatted, loader.bin no longer used/required)
|
||||
3) in the same dir it looks for config.txt which you can do things like
|
||||
change the arm speed, or 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
|
||||
|
||||
The memory is split between the GPU and the ARM, I believe the default
|
||||
is to split the memory in half. And there are ways to change that
|
||||
split (to give the ARM more)(using config.txt). Not going to worry
|
||||
about that here.
|
||||
|
||||
From the ARMs perspective the kernel.img file is loaded, by default,
|
||||
to address 0x8000. (there are ways to change that, not going to worry
|
||||
about that right now).
|
||||
|
||||
Hardware and programming information:
|
||||
|
||||
You will want to go here
|
||||
http://elinux.org/RPi_Hardware
|
||||
And the datasheet and schematic. These are moving targets the above
|
||||
elinux link has the datasheet and errata which is important. They
|
||||
didnt give us a full datasheet for the BCM2836 have to go with the
|
||||
BCM2835.
|
||||
You will want to go to
|
||||
http://raspberrypi.org and then the forum tab then slide down to
|
||||
the Bare Metal forum, the first (only) Sticky topic is Bare Metal
|
||||
Resources. There are many more links there for good information.
|
||||
Also go to
|
||||
http://infocenter.arm.com and get the Architectural Reference Manual
|
||||
and the Techincal Reference Manual for the ARM1176JZF-S (BCM2835)
|
||||
and/or the Cortex-A7 (BCM2836).
|
||||
|
||||
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. The bottom of this picture shows total system
|
||||
sdram (memory) and somewhere between zero and the top of ram is a
|
||||
split between sdram for the ARM on the bottom and a chunk of that
|
||||
for the VC SDRAM, basically memory for the gpu and memory shared
|
||||
between the ARM and GPU to allow the ARM to ask the GPU to draw stuff
|
||||
on the video screen. 256MBytes is 0x10000000, and 512MBytes is
|
||||
0x20000000. Some models of raspberry pi have 256MB, newer models have
|
||||
512MB total ram which is split between the GPU and the ARM. Assume
|
||||
the ARM gets at least half of this. Peripherals (uart, gpio, etc)
|
||||
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. From the
|
||||
Broadcom doc this looks to be giving us access to the memory with
|
||||
different caching schemes (cached, uncached, etc) depending on which
|
||||
upper address bits you use. Most likely to allow more room for RAM
|
||||
the Raspberry Pi 2 uses a peripheral base address of 0x3Fxxxxxx instead
|
||||
of the 0x20xxxxxx.
|
||||
|
||||
I do not normally zero out .bss or use .data so if you do this to my
|
||||
examples
|
||||
|
||||
int x;
|
||||
fun()
|
||||
{
|
||||
static int y;
|
||||
}
|
||||
|
||||
dont assume x and y are zero when your program starts. Nor if you do
|
||||
this
|
||||
|
||||
int x=5;
|
||||
fun()
|
||||
{
|
||||
static int y=7;
|
||||
}
|
||||
|
||||
will x=5 or y=7.
|
||||
|
||||
See the bssdata directory for more information, you can most likely
|
||||
use the linker script to solve the problem for you since .text, .data,
|
||||
.bss, (.rodata), everything lives in ram.
|
||||
|
||||
Nor do I use 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. I have not
|
||||
looked in a while but formerly codesourcery.com (now a part of Mentor
|
||||
Graphics) had a free LITE version of their toolchain which was pretty
|
||||
easy to come by. An even easier place is here
|
||||
https://launchpad.net/gcc-arm-embedded
|
||||
to get a cross compiler. Building your own toolchain from gnu sources
|
||||
(binutils and gcc) is fairly straight forward see my build_gcc
|
||||
repository for a build script (Linux only but from that you might get
|
||||
other platforms to build). And also remember that you can run linux
|
||||
on the pi and on that it has a native, not cross, gnu toolchain.
|
||||
|
||||
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 special 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
|
||||
it boots off of an sd card which we can easily remove and replace
|
||||
ourselves. I dont know for sure, a lot more info is out about the
|
||||
GPU since I started with this, but I assume that there is some GPU code
|
||||
that boots off of an internal rom, I doubt with two on chip processors
|
||||
they created pure logic to read the sd card, wade through the filesystem
|
||||
to find a specific bootcode.bin file, load that into ram and run it.
|
||||
If that assumption is true is that on chip rom one time programmable
|
||||
or can it be erased/reprogrammed, and if the latter how lucky do we have
|
||||
to be with a broken program to erase that? So I am not 100% sure but
|
||||
almost 100% sure the Raspberry Pi is not brickable. This is actually
|
||||
a big deal for bare metal programming, in particular if it is your first
|
||||
platform. With decades of experience I still make mistakes from time
|
||||
to time and brick a board, never to be recovered.
|
||||
|
||||
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.
|
||||
I use the firmware from http://github.com/raspberrypi. The minimum
|
||||
configuration you need to get started at this level is:
|
||||
|
||||
go to https://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 and start.elf (NOT kernel.img,
|
||||
dont need it, too big)(loader.bin is no longer used/required). 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 minimum number
|
||||
of files on the sd card, bootcode.bin, start.elf and either kernel.img
|
||||
or kernel7.img (or sometimes both).
|
||||
|
||||
My examples are basically the kernel.img file. Not a linux kernel,
|
||||
just bare metal programs. Since the GPU bootloader is looking for
|
||||
that file name, you use that file name. The kernel.img file is just a
|
||||
blob that is copied to memory, dont worry about what they named it.
|
||||
|
||||
What I do is setup the sd card with a single partition, fat32. And
|
||||
copy the above files in the root directory. bootcode.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 requires soldering on older
|
||||
of the older models, but unless you were an early adopter, you dont
|
||||
need to worry about that all the signals are on the P1 connector. How
|
||||
to use the jtag and how to hook it up 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
|
||||
|
||||
Or if you solder on a reset button
|
||||
|
||||
1) reset raspi
|
||||
2) type command to load and start new program
|
||||
|
||||
I have working bootloader examples. bootloader05 is currently the last
|
||||
of the xmodem based ones (that basically take a kernel.img file),
|
||||
personally I use bootloader07 which takes an intel hex formatted file
|
||||
which these examples also build. The .bin file would be used with
|
||||
bootloader05, the .hex with bootloader07. 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:
|
||||
|
||||
A recent purchase, experimentally white is RX and green is TX, black GND
|
||||
http://www.nexuscyber.com/usb-to-ttl-serial-debug-console-cable-for-raspberry-pi
|
||||
Sparkfun has one
|
||||
https://www.sparkfun.com/products/12977
|
||||
As does Adafruit
|
||||
https://www.adafruit.com/products/954
|
||||
The above, assuming you figure out rx from tx, are all you need. The
|
||||
ones below you may need to solder or may need some jumper wires.
|
||||
|
||||
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
|
||||
|
||||
Or see the pitopi (pi to pi) directory. This talks about how to take
|
||||
two raspberry pi's and connect them together. One being the
|
||||
host/development platform (a raspberry pi running linux is a native
|
||||
arm development platform, no need to find/get/build a cross compiler)
|
||||
the other being the target that runs your bare metal programs.
|
||||
|
||||
Lastly and perhaps the best solution IMO, is the FT4232H or FT2232H
|
||||
mini module from FTDI. It gives you UART and JTAG for under $30.
|
||||
See the armjtag directory README for more and you will want some
|
||||
female/female wire from sparkfun or adafruit or elsewhere
|
||||
https://www.sparkfun.com/products/8430
|
||||
(I use these F/F wires for most projects, buy/bought the 100 pack)
|
||||
|
||||
---- connecting to the uart pins ----
|
||||
|
||||
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.
|
||||
|
||||
2 outer corner
|
||||
4
|
||||
6 ground
|
||||
8 TX out
|
||||
10 RX in
|
||||
|
||||
ground is not necessarily needed if both the raspberry pi and the
|
||||
usb to serial board are powered by the same computer (I recommend
|
||||
you do that) as they will ideally have the same ground.
|
||||
|
||||
Read more about the bootloaders in their local README files. Likewise
|
||||
if you interested in jtag see the armjatag 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.
|
||||
|
||||
Update, amontec is history their website is gone. But you can
|
||||
get j-link (or clone) boxes from asia on ebay for around $11, so far
|
||||
I have tried them with ARM JTAG and ARM SWD. Very pleased so far.
|
||||
|
||||
If you can solder, the A+, B+, Zero and Pi 2 all have a pair of holes
|
||||
sometimes with the text RUN next to them. I use buttons like this
|
||||
https://www.sparkfun.com/products/97
|
||||
with two of the legs broken off then the others twisted and adjusted
|
||||
to fit in the holes and soldered down.
|
||||
|
||||
As far as these samples go I recommend starting with blinker01 then
|
||||
follow the discovery of the chip into uart01, etc.
|
||||
|
||||
The bssdata and baremetal directories attempt to explain a little
|
||||
bit about taking control of the gnu toolchain to build bare metal
|
||||
programs like these examples. As with any bare metal programmer I have
|
||||
my ways of doing things and these two directories hopefully will show
|
||||
you some basics, get you thinking about how these tools really work,
|
||||
take the fear away from using them, as well as some comments on why
|
||||
I take the approach I take (not worrying about .bss nor .data). Since
|
||||
the raspberry pi is from our perspective RAM based (the GPU loads our
|
||||
whole binary into memory), we dont have to deal with the things we
|
||||
would deal with on a FLASH/PROM + RAM system. This RAM only approach
|
||||
makes life a lot easier, but leaves out some important bare metal
|
||||
experiences that you will have to find elsewhere.
|
||||
|
||||
-----------
|
||||
[](https://github.com)
|
||||
|
||||
Reference in New Issue
Block a user