diff --git a/README.md b/README.md new file mode 100644 index 0000000..3ddc059 --- /dev/null +++ b/README.md @@ -0,0 +1,380 @@ + +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. + +----------- +[![hello](https://img.shields.io/github/languages/count/badges/shields.svg)](https://github.com) +