{"id":19577998,"url":"https://github.com/mihaigalos/miniboot","last_synced_at":"2025-04-27T06:33:09.838Z","repository":{"id":47101265,"uuid":"117458368","full_name":"mihaigalos/miniboot","owner":"mihaigalos","description":"🏗️ An I2C bootloader for Arduino.","archived":false,"fork":false,"pushed_at":"2022-04-30T08:23:25.000Z","size":1674,"stargazers_count":62,"open_issues_count":0,"forks_count":20,"subscribers_count":10,"default_branch":"master","last_synced_at":"2023-03-03T21:46:19.768Z","etag":null,"topics":["arduino","arduino-library","avr","bootloader","eeprom","i2c","i2c-memory","reflash"],"latest_commit_sha":null,"homepage":"","language":"Makefile","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mihaigalos.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-01-14T19:05:40.000Z","updated_at":"2022-10-06T02:09:58.000Z","dependencies_parsed_at":"2022-09-03T04:12:00.100Z","dependency_job_id":null,"html_url":"https://github.com/mihaigalos/miniboot","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mihaigalos%2Fminiboot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mihaigalos%2Fminiboot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mihaigalos%2Fminiboot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mihaigalos%2Fminiboot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mihaigalos","download_url":"https://codeload.github.com/mihaigalos/miniboot/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224062761,"owners_count":17249291,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["arduino","arduino-library","avr","bootloader","eeprom","i2c","i2c-memory","reflash"],"created_at":"2024-11-11T07:09:17.907Z","updated_at":"2024-11-11T07:09:19.451Z","avatar_url":"https://github.com/mihaigalos.png","language":"Makefile","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Miniboot - an I2C bootloader for Arduino\n\n[![CI](https://github.com/mihaigalos/miniboot/actions/workflows/main.yml/badge.svg)](https://github.com/mihaigalos/miniboot/actions/workflows/main.yml) [![license](https://img.shields.io/badge/license-GPLv3-brightgreen.svg)](LICENSE) [![LoC](https://tokei.rs/b1/github/mihaigalos/miniboot)](https://github.com/Aaronepower/tokei)\n\nMiniboot is an I2C bootloader for Arduino, tested on AtMega328p. It is designed to reflash\nthe Mega328p with code residing in an external I2C memory or another I2C device. For testing,\nCAT24M01 1Mbit (128kByte) external EEPROM was used.\n\n# Requirements\n\nMiniboot depends on [avr-bootloader-common](https://github.com/mihaigalos/avr-bootloader-common/) for commonalities between bootloaders.\nThis dependency will be automatically downloaded by `bazel` so you don't have to.\n\nFlash size requirements are \u003c2kBytes. With respect to RAM, AtMega328p's 2kBytes should be enough, actual stack usage is way lower than that anyway.\n```\n$ avr-size -B miniboot.elf\n   text    data     bss     dec     hex filename\n   1944       0       0    1944     798 miniboot.elf\n```\n\n# Usage\n\n## Flash the correct fuses\n\nPlease use the following reccommended fuses, or compatible:\n\nhttps://github.com/mihaigalos/miniboot/blob/995c05d0aa989123e3cbfa012caa9d9c19f22886/src/miniboot.c#L2\n\n## Get the sources\n\n`git clone --recursive  https://github.com/mihaigalos/miniboot.git`\n\n## Build the hex\n\nBuilding is managed by [`bazel`](https://github.com/bazelbuild/bazel/releases), so make sure you have it first.\n\n* `bazel build --config=328p --verbose_failures //:miniboot.elf`\n* `bazel build --config=328p --verbose_failures //:miniboot_hex`\n\n## Once Miniboot starts\nMiniboot reads the metadata header and it starts reflashing the microcontroller with the information\nstated there. It expects the following memory layout of the metadata in the (external) I2C memory:\n\n- [last free byte pointer]          : 2 bytes - should point to first byte after the appplication. Ignored.\n- ['m' 'i' 'n' 'i' 'b' 'o' 'o' 't'] : 8 bytes.\n- [name of application]             : 10 bytes - user defined.\n- [timestamp application]           : 4 bytes - unix timestamp when the application in the I2C memory was generated.\n- [timestamp of write]              : 4 bytes - unix timestamp when the application was flashed to the I2c memory.\n- [CRC32]                           : 4 bytes - generated with polynomial representation 0xEDB88320. Details in Drivers/CRC.\n- [length]                          : 2 bytes - amount of bytes for the application.\n- [application]                     : *length* bytes - actual payload of the application code.\n\nMiniboot computes a CRC32 checksum on the payload, excluding the header metadata and starting with the first byte of\nthe application.\nIt is important that the length be at byte location 32 and the application start at byte 34.\n\n# Bootloader start address\n\nMiniboot can be modified to place the bootloader code at a specific address, via\nthe macro BOOTLOADER_START_ADDRESS. Please ensure that the address lies in the bootloader\nsection, specified by the High fusebits. I recommend using at least 1024 words (2048 bytes) for\nthe bootloader section (Hi fuse : 0xD8). If you choose to modify miniboot, please ensure that your new bootloader\nfits in the section you specify with the Hi fuse.\n\nComputing the hexadecimal address for bootloader start section:\n- bazel clean; bazel build --config=328p --verbose_failures //:miniboot_hex ; take output, let's say it's 2123 (or similar).\n- for the size of your device (32kB = 1024 * 32 = 32768 bytes) minus above value 2123... = 30645.\n- Which yields 30645 / 128 (128 = mega328p page size in bytes) = 239.41 pages of flash memory.\n- round it down to 239 - our new bootloader address is 239 * 128 = 30592, in hex = 7780h.\n- put the value in the BOOTLOADER_START_ADDRESS variable in the BUILD file.\n\n# Internal EEPROM last application timestamp\n\nAfter running, miniboot writes the application timestamp (specified earlier) to 4 bytes in the microcontroller's\ninternal EEPROM. The next time the system restarts, it will compare the application's timestamp with the information\nit reads from the internal eeprom and will only rewrite it again if the timestamp is different or the internal eeprom\nis unprogrammed (4 bytes of 0xFF). This prevents a new unnecessary rewrite on each system restart.\n\nThe variable EEPROM_CONFIGURATION_START_BYTE can be edited to generate the desired macro in bootloader.h for the above logic.\n\n# Storing the application in the external EEPROM\n\n## Create the binary file\n\nExport the hex file of the application (the one you want to transfer to the I2C memory) to binary before continuing:\n\n`avr-objcopy -I ihex application.hex -O binary application.bin`\n\n## Send it!\n\n`Disclaimer: At the time of this posting, I was using Windows. Sigh.`\n![alt text](memes/cry.jpg \"Why?!\")\n\nWe finally want to send it over to the microcontroller which will write it to the I2C memory.\n\nYou may choose to use the UART method or the Monolithic Binary Method.\n\n* The Monolithic Binary Method: creates a sketch with Arduino which contains a copy-pasted version of the application.hex and its associated metadata filled in manually.\n* The UART Method: uses `YAT Terminal` to fill in the application payload and metadata in the external\nEEPROM.\n\nI personally think the UART Method is easier and more generic.\n\n```\nPlease be aware, the metadata needs to be present alongside the payload. Without proper setup of the\nmetadata (i.e. : timestamp and CRC), the payload will be ignored by miniboot and not be reflashed.\n```\n\n### The Monolithic Binary Method\n\nDon't let the name scare you. :grinning:\n\nYou can compose your metadata by hand, using my [eeprom](https://github.com/mihaigalos/Drivers/tree/master/Eeprom/src) driver, store both the metadata\nand the payload in the external I2C, for miniboot to use. Have a look at the `blink_hex` variable in [intel_hex.cpp](https://github.com/mihaigalos/Drivers/blob/1d91716ae377027199c316b348553ea9f591e0e6/Eeprom/src/intel_hex.cpp#L28). You need to compile the example sketch and\nflash the MCU with it. Once it runs successfuly, you will have the code in the external I2C EEPROM.\n\n### The UART Method\n\nBr@y's Terminal is broken when using the send file feature.\nUse YAT Terminal to send the file via UART instead.\n\nFirst, the Arduino board needs to be flashed with the miniboot_uart_to_eeprom_uploader.hex sketch which can be found in the Drivers/Eeprom/bin folder in this repo. This will read from the UART and will put the information in the external I2C memory.\n\nAt this point, you will need a USB to UART bridge hooked up to your Arduino's UART.\n\nIn YAT, go to Terminal-\u003eSettings and select your baudrate:\n\n- If your Arduino is running at 16Mhz : select 600 bits per second.\n- If your Arduino is running at 8Mhz or have a custom board runing at 8Mhz: select 300 bits per second.\n\nThe low baudrate ensures the external EEPROM has time to write the payload it receives, since the communication is asynchronous.\n\nWhen asked to do so, follow the instructions to input the application unix timestamp, the unix timestamp of the time of writing, crc value and the data length.\nFor the unix timestamp, you can use the [epoch converter](https://www.epochconverter.com/).\nFor computing the crc32 on your binary file, drag and drop the application.bin created earlier in the webpage found [here](http://emn178.github.io/online-tools/crc32_checksum.html).\n\nYou will next be prompted to switch to binary mode and send the binary file.\n\nYAT tries to parse the \\r\\n sequence when sending, which leads to an error being shown and the transmission is interrupted, the file is not fully sent.\nTo overcome this, -\u003eselect Terminal Type: binary. Select Binary Settings... and uncheck everything.\n\nNext select the exported binary file (application.bin) and click Send File.\n\nYou should now be able to send the file in full.\n\n## No global variables\n\nMiniboot uses no global variables. Thus you can call bootloader functions from the application,\nwithout worrying that the application's variables will get overwritten by the bootloader code.\n\nWhy should you care, you may ask? Well, if you find you need to compile and link functions which are\nalready present in miniboot, you can just call them from your application to miniboot, potentially\nreducing the application size.\n\nMore details in Section # 14 (Can the application use code built into the bootloader) of doc/bootloader_faq.pdf\nor [AvrFreaks](https://www.avrfreaks.net/sites/default/files/bootloader_faq.pdf).\n\n# License\n\nThis software is freely available under the GNU GPL v3.0 aegis, please consult the LICENSE file for further information.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmihaigalos%2Fminiboot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmihaigalos%2Fminiboot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmihaigalos%2Fminiboot/lists"}