{"id":18163713,"url":"https://github.com/chuckb/raspberrypi","last_synced_at":"2026-07-09T23:31:32.876Z","repository":{"id":143216647,"uuid":"259083638","full_name":"chuckb/raspberrypi","owner":"chuckb","description":"Raspberry Pi ARM based bare metal examples...from dwelch67","archived":false,"fork":false,"pushed_at":"2020-04-26T16:54:10.000Z","size":6536,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-08T06:48:07.205Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Assembly","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chuckb.png","metadata":{"files":{"readme":"README","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-04-26T16:50:20.000Z","updated_at":"2020-04-26T17:00:14.000Z","dependencies_parsed_at":null,"dependency_job_id":"e32c6108-61de-4e1b-882d-a8eb79c3aac6","html_url":"https://github.com/chuckb/raspberrypi","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/chuckb/raspberrypi","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chuckb%2Fraspberrypi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chuckb%2Fraspberrypi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chuckb%2Fraspberrypi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chuckb%2Fraspberrypi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chuckb","download_url":"https://codeload.github.com/chuckb/raspberrypi/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chuckb%2Fraspberrypi/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35315892,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-09T02:00:07.329Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-02T11:05:58.508Z","updated_at":"2026-07-09T23:31:32.852Z","avatar_url":"https://github.com/chuckb.png","language":"Assembly","funding_links":[],"categories":[],"sub_categories":[],"readme":"\nThe main directory examples are for the older/est pi1 boards maybe\nsome attempts at newer boards.  These are retained for legacy reasons\nsome folks have direct links.  They are still valid for those boards.\nThe boards directory has the first attempt at solving the too many\nboards issue and that is where I recommend you go.  My third string\nattempt is I have a raspberrypi-zero and raspberrypi-three repos that\nare for those boards specifically.  Little to no verbage though, the\nrambling text is mostly in this repo.\n\n--------------\n\nThis repo is getting a bit messy starting with the first released to\nthe public pi and then all that came after.  I want to rework it but\nit is going slowly.  Recently started creating directories pi1, piaplus\nand so on to target the examples specifically to the different cards.\nAgain that is slow going.  Likewise this README will be rewritten perhaps\nbut for now...\n\n--------------\n\nThis repo serves as a collection of low level examples.  No operating\nsystem, embedded or low level embedded or deeply embedded or bare metal,\nwhatever your term is for this.\n\nI am in no way shape or form associated with the raspberry pi organization\nnor broadcom.  I just happen to own one (some) and am sharing my\nexperiences.  The raspberry pi is about education, and I feel bare\nmetal education is just as important as Python programming.\n\nSo I started this years ago when got my first ARM11 based raspberry pi\nmaybe we call that a raspberry pi 1, I dont know a good term.  But\nnow there is a growing number of variations.\n\nARM11 based (BCM2835)\nRaspberry Pi B\nRaspberry Pi B2\nRaspberry Pi A+\nRaspberry Pi B+\nRaspberry Pi Zero\nCortex-A7 based (BCM2836)\nRaspberry Pi 2 B\nCortex-A53 based (BCM2837)\nRaspberry Pi 3 B\n\nThere is also the compute module but I dont have one of those.\n\nGeneral differences that we care about for these examples.  The amount\nof ram varies from board to board.  The peripheral base address is\ndifferent between the BCM2835 and BCM2836.  The BCM2835 looks for the\nfile kernel.img the BCM2836 looks for kernel7.img.  The ARM11 based\nZero is a B with stuff removed and a new layout, but they up/over\nclocked the processor from 750MHz to 1000MHz, one led on gpio 16.  The\nA+ and B+ they moved the led (or put two) on gpio 35 and 47.  The\nraspberry pi 2 is B+ like but with the different chip, supposedly the\nBCM2836 is  BCM2835 with the ARM11 core removed and replaced with\nthe Cortex A7 and for the most part it appears to be.  The raspberry\npi 3 is Cortex A8 based, 64 bit.  And they moved the LED (the leds)\nto an i2c gpio expander.\n\nAs of this writing I am adding plus and pi2 versions of the examples\nas many of them are based on the early/original.  No guarantees I will\ndo that, just looking at the differences between the blinker01 examples\nshould show you what to do to convert these yourself.  In some cases\nI am intentionally not trying to have one code base build for all\nthree with ifdefs and such, keep it simple stupid then complicate it\nas needed.  The text may say kernel.img but substitute with kernel7.img\nas needed.\n\nI still have a number of raspberry pi 2 examples to port, and now a\nbunch of examples to port to the raspberry pi 3.  The raspberry pi 3\nas of this writing, without a config.txt, is switched to 32 bit\ncompatibility mode.  See the aarch64 directory for 64 bit ARM examples.\n\nFrom what we know so far there is a gpu on chip which:\n\n1) boots off of an on chip rom of some sort\n2) reads the sd card and looks for additional gpu specific boot files\nbootcode.bin and start.elf in the root dir of the first partition\n(fat32 formatted, loader.bin no longer used/required)\n3) in the same dir it looks for config.txt which you can do things like\nchange the arm speed, or change the address where to load kernel.img,\nand many others\n4) it reads kernel.img the arm boot binary file and copies it to memory\n5) releases reset on the arm such that it runs from the address where\nthe kernel.img data was written\n\nThe memory is split between the GPU and the ARM, I believe the default\nis to split the memory in half.  And there are ways to change that\nsplit (to give the ARM more)(using config.txt).  Not going to worry\nabout that here.\n\nFrom the ARMs perspective the kernel.img file is loaded, by default,\nto address 0x8000.  (there are ways to change that, not going to worry\nabout that right now).\n\nHardware and programming information:\n\nYou will want to go here\nhttp://elinux.org/RPi_Hardware\nAnd the datasheet and schematic.  These are moving targets the above\nelinux link has the datasheet and errata which is important.  They\ndidnt give us a full datasheet for the BCM2836 have to go with the\nBCM2835.\nYou will want to go to\nhttp://raspberrypi.org and then the forum tab then slide down to\nthe Bare Metal forum, the first (only) Sticky topic is Bare Metal\nResources.  There are many more links there for good information.\nAlso go to\nhttp://infocenter.arm.com and get the Architectural Reference Manual\nand the Techincal Reference Manual for the ARM1176JZF-S (BCM2835)\nand/or the Cortex-A7 (BCM2836).\n\nEarly in the BCM2835 document you see a memory map.  I am going to\noperate based on the middle map, this is how the ARM comes up.  The\nleft side is the system which we dont have direct access to in that\nform, the gpu probably, not the ARM.  The ARM comes up with a memory\nspace that is basically 0x40000000 bytes in size as it mentions in\nthe middle chart.  The bottom of this picture shows total system\nsdram (memory) and somewhere between zero and the top of ram is a\nsplit between sdram for the ARM on the bottom and a chunk of that\nfor the VC SDRAM, basically memory for the gpu and memory shared\nbetween the ARM and GPU to allow the ARM to ask the GPU to draw stuff\non the video screen.  256MBytes is 0x10000000, and 512MBytes is\n0x20000000.  Some models of raspberry pi have 256MB, newer models have\n512MB total ram which is split between the GPU and the ARM.  Assume\nthe ARM gets at least half of this.  Peripherals (uart, gpio, etc)\nare mapped into arm address space at 0x20000000.  When you see\n0x7Exxxxxx in the manual replace that with 0x20xxxxxx as your ARM\nphysical address.  Experimentally I have seen the memory repeats every\n0x40000000, read 0x40008000 and you see the data from 0x8000.  From the\nBroadcom doc this looks to be giving us access to the memory with\ndifferent caching schemes (cached, uncached, etc) depending on which\nupper address bits you use.  Most likely to allow more room for RAM\nthe Raspberry Pi 2 uses a peripheral base address of 0x3Fxxxxxx instead\nof the 0x20xxxxxx.\n\nI do not normally zero out .bss or use .data so if you do this to my\nexamples\n\nint x;\nfun()\n{\n  static int y;\n}\n\ndont assume x and y are zero when your program starts. Nor if you do\nthis\n\nint x=5;\nfun()\n{\n  static int y=7;\n}\n\nwill x=5 or y=7.\n\nSee the bssdata directory for more information, you can most likely\nuse the linker script to solve the problem for you since .text, .data,\n.bss, (.rodata), everything lives in ram.\n\nNor do I use gcc libraries nor C libraries so you can build most if not\nall of my examples using a gcc cross compiler.  Basically it doesnt\nmatter if you use arm-none-linux-gnueabi or arm-none-eabi.  I have not\nlooked in a while but formerly codesourcery.com (now a part of Mentor\nGraphics) had a free LITE version of their toolchain which was pretty\neasy to come by.  An even easier place is here\nhttps://launchpad.net/gcc-arm-embedded\nto get a cross compiler.  Building your own toolchain from gnu sources\n(binutils and gcc) is fairly straight forward see my build_gcc\nrepository for a build script (Linux only but from that you might get\nother platforms to build).  And also remember that you can run linux\non the pi and on that it has a native, not cross, gnu toolchain.\n\nAs far as we know so far the Raspberry Pi is not \"brickable\".  Normally\nwhat brickable means is the processor relies on a boot flash and with\nthat flash it is possible to change/erase it such that the processor will\nnot boot normally.  Brickable and bricked sometimes excludes things\nlike jtag or special programming headers.  From the customers perspective\na bricked board is...bricked.  But on return to the vendor they may\nhave other equipment that is able to recover the board without doing\nany soldering, perhaps plugging in jtag or some other cable on pins/pads\nthey have declared as reserved.  Take apart a tv remote control or\ncalculator, etc and you may see some holes or pads on the circuit board,\nfor some of these devices just opening the battery case you have a view\nof some of the pcboard.  This is no doubt a programming header.  Long\nstory short, so far as I know the Raspberry Pi is not brickable because\nit boots off of an sd card which we can easily remove and replace\nourselves.  I dont know for sure, a lot more info is out about the\nGPU since I started with this, but I assume that there is some GPU code\nthat boots off of an internal rom, I doubt with two on chip processors\nthey created pure logic to read the sd card, wade through the filesystem\nto find a specific bootcode.bin file, load that into ram and run it.\nIf that assumption is true is that on chip rom one time programmable\nor can it be erased/reprogrammed, and if the latter how lucky do we have\nto be with a broken program to erase that?  So I am not 100% sure but\nalmost 100% sure the Raspberry Pi is not brickable.  This is actually\na big deal for bare metal programming, in particular if it is your first\nplatform.  With decades of experience I still make mistakes from time\nto time and brick a board, never to be recovered.\n\nTo use my samples you do not need a huge sd card.  Nor do you need nor\nwant to download one of the linux images, takes a while to download,\ntakes a bigger sd card to use, and takes forever to write to the sd card.\nI use the firmware from http://github.com/raspberrypi.  The minimum\nconfiguration you need to get started at this level is:\n\ngo to https://github.com/raspberrypi, you DO NOT need to download\nthe repo, they have some large files in there you will not need (for\nmy examples).  go to the firmware directory and then the boot directory.\nFor each of these files, bootcode.bin and start.elf (NOT kernel.img,\ndont need it, too big)(loader.bin is no longer used/required).  Click\non the file name, it will go to another page then click on View Raw and\nit will let you download the file.  For reference, I do not use nor\nhave a config.txt file on my sd card.  I only have the minimum number\nof files on the sd card, bootcode.bin, start.elf and either kernel.img\nor kernel7.img (or sometimes both).\n\nMy examples are basically the kernel.img file.  Not a linux kernel,\njust bare metal programs.  Since the GPU bootloader is looking for\nthat file name, you use that file name.  The kernel.img file is just a\nblob that is copied to memory, dont worry about what they named it.\n\nWhat I do is setup the sd card with a single partition, fat32.  And\ncopy the above files in the root directory.  bootcode.bin and start.elf.\nFrom there you take .bin files from my examples and place them on the sd\ncard with the name kernel.img.  It wont take you very long to figure out\nthis is going to get painful.\n\n1) power off raspi\n2) remove sd card\n3) insert sd card in reader\n4) plug reader into computer\n5) mount/wait\n6) copy binary file to kernel.img\n7) sync/wait\n8) unmount\n9) insert sd card in raspi\n10) power raspi\n11) repeat\n\nThere are ways to avoid this, one is jtag, which is not as expensive\nas it used to be.  It used to be in the thousands of dollars, now it\nis under $50 and the software tools are free.  Now the raspi does have\njtag on the arm, getting the jtag connected requires soldering on older\nof the older models, but unless you were an early adopter, you dont\nneed to worry about that all the signals are on the P1 connector. How\nto use the jtag and how to hook it up is described later and in\nthe armjtag sample.\n\nAnother method is a bootloader, typically you use a serial port connected\nto the target processor.  That processor boots a bootloader program that\nin some way, shape, or form allows you to interact with the bootloader\nand load programs into memory (that the bootloader is not using itself)\nand then the bootloader branches/jumps to your program.  If your program\nis still being debugged and you want to try again, you reboot the processor\nthe bootloader comes up and you can try again without having to move any\nsd cards, etc.  The sd card dance above is now replaced with the\nbootloader dance:\n\n1) power off raspi\n2) power on raspi\n3) type command to load and start new program\n\nOr if you solder on a reset button\n\n1) reset raspi\n2) type command to load and start new program\n\nI have working bootloader examples.  bootloader05 is currently the last\nof the xmodem based ones (that basically take a kernel.img file),\npersonally I use bootloader07 which takes an intel hex formatted file\nwhich these examples also build.  The .bin file would be used with\nbootloader05, the .hex with bootloader07.  But you need more hardware\n(no soldering is required).  For those old enough to know what a serial\nport is, you CANNOT connect your raspberry pi directly to this port,\nyou will fry the raspberry pi.  You need some sort of serial port at\n3.3V either a level shifter of some sort (transceiver like a MAX232) or\na usb serial port where the signals are 3.3V (dont need to use RS232\njust stay at the logic level).  The solution I recommend is a non-solder\nsolution:\n\nA recent purchase, experimentally white is RX and green is TX, black GND\nhttp://www.nexuscyber.com/usb-to-ttl-serial-debug-console-cable-for-raspberry-pi\nSparkfun has one\nhttps://www.sparkfun.com/products/12977\nAs does Adafruit\nhttps://www.adafruit.com/products/954\nThe above, assuming you figure out rx from tx, are all you need.  The\nones below you may need to solder or may need some jumper wires.\n\nhttp://www.sparkfun.com/products/9873\nplus some male/female wire\nhttp://www.sparkfun.com/products/9140\n\nSolutions that may involve soldering\nhttp://www.sparkfun.com/products/718\nhttp://www.sparkfun.com/products/8430\n\nOr this for level shifting to a real com port.\nhttp://www.sparkfun.com/products/449\n\nOr see the pitopi (pi to pi) directory.  This talks about how to take\ntwo raspberry pi's and connect them together.  One being the\nhost/development platform (a raspberry pi running linux is a native\narm development platform, no need to find/get/build a cross compiler)\nthe other being the target that runs your bare metal programs.\n\nLastly and perhaps the best solution IMO, is the FT4232H or FT2232H\nmini module from FTDI.  It gives you UART and JTAG for under $30.\nSee the armjtag directory README for more and you will want some\nfemale/female wire from sparkfun or adafruit or elsewhere\nhttps://www.sparkfun.com/products/8430\n(I use these F/F wires for most projects, buy/bought the 100 pack)\n\n---- connecting to the uart pins ----\n\nOn the raspberry pi, the connector with two rows of a bunch of pins is\nP1.  Starting at that corner of the board, the outside corner pin is\npin 2.  From pin 2 heading toward the yellow rca connector the pins\nare 2, 4, 6, 8, 10.  Pin 6 connect to gnd on the usb to serial board\npin 8 is TX out of the raspi connect that to RX on the usb to serial\nboard.  Pin 10 is RX into the raspi, connect that to TX on the usb to\nserial board.  Careful not to have metal items on the usb to serial\nboard touch metal items on the raspberry pi (other than the three\nconnections described).  On your host computer you will want to use\nsome sort of dumb terminal program, minicom, putty, etc.  Set the\nserial port (usb to serial board) to 115200 baud, 8 data bits, no\nparity, 1 stop bit.  NO flow control.  With minicom to get no flow\ncontrol you normally have to save the config, exit minicom, then\nrestart minicom and load the config in order for flow control\nchanges to take effect.  Once you have a saved config you dont have\nto mess with it any more.\n\n2  outer corner\n4\n6  ground\n8  TX out\n10 RX in\n\nground is not necessarily needed if both the raspberry pi and the\nusb to serial board are powered by the same computer (I recommend\nyou do that) as they will ideally have the same ground.\n\nRead more about the bootloaders in their local README files.  Likewise\nif you interested in jtag see the armjatag README file.  Other than\nchewing up a few more GPIO pins, and another thing you have to buy, the\njtag solution is the most powerful and useful.  My typical setup is the\narmjtag binary as kernel.img, a usb to jtag board like the amontec\njtag-tiny and a usb to serial using minicom.\n\nUpdate, amontec is history their website is gone.  But you can\nget j-link (or clone) boxes from asia on ebay for around $11, so far\nI have tried them with ARM JTAG and ARM SWD.  Very pleased so far.\n\nIf you can solder, the A+, B+, Zero and Pi 2 all have a pair of holes\nsometimes with the text RUN next to them.  I use buttons like this\nhttps://www.sparkfun.com/products/97\nwith two of the legs broken off then the others twisted and adjusted\nto fit in the holes and soldered down.\n\nAs far as these samples go I recommend starting with blinker01 then\nfollow the discovery of the chip into uart01, etc.\n\nThe bssdata and baremetal directories attempt to explain a little\nbit about taking control of the gnu toolchain to build bare metal\nprograms like these examples.  As with any bare metal programmer I have\nmy ways of doing things and these two directories hopefully will show\nyou some basics, get you thinking about how these tools really work,\ntake the fear away from using them, as well as some comments on why\nI take the approach I take (not worrying about .bss nor .data).  Since\nthe raspberry pi is from our perspective RAM based (the GPU loads our\nwhole binary into memory), we dont have to deal with the things we\nwould deal with on a FLASH/PROM + RAM system.  This RAM only approach\nmakes life a lot easier, but leaves out some important bare metal\nexperiences that you will have to find elsewhere.\n\n-----------\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchuckb%2Fraspberrypi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchuckb%2Fraspberrypi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchuckb%2Fraspberrypi/lists"}