{"id":19964889,"url":"https://github.com/infinitimeorg/pinetime-mcuboot-bootloader","last_synced_at":"2025-03-16T07:06:23.275Z","repository":{"id":41314045,"uuid":"323651590","full_name":"InfiniTimeOrg/pinetime-mcuboot-bootloader","owner":"InfiniTimeOrg","description":"An open source bootloader for the PineTime based on MyNEWT and MCUBoot.","archived":false,"fork":false,"pushed_at":"2024-09-04T19:17:51.000Z","size":1559,"stargazers_count":74,"open_issues_count":5,"forks_count":18,"subscribers_count":7,"default_branch":"develop","last_synced_at":"2025-03-02T09:11:34.290Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/InfiniTimeOrg.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-12-22T14:39:26.000Z","updated_at":"2025-03-01T19:05:01.000Z","dependencies_parsed_at":"2024-09-06T03:17:49.995Z","dependency_job_id":null,"html_url":"https://github.com/InfiniTimeOrg/pinetime-mcuboot-bootloader","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/InfiniTimeOrg%2Fpinetime-mcuboot-bootloader","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/InfiniTimeOrg%2Fpinetime-mcuboot-bootloader/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/InfiniTimeOrg%2Fpinetime-mcuboot-bootloader/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/InfiniTimeOrg%2Fpinetime-mcuboot-bootloader/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/InfiniTimeOrg","download_url":"https://codeload.github.com/InfiniTimeOrg/pinetime-mcuboot-bootloader/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243835960,"owners_count":20355613,"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":[],"created_at":"2024-11-13T02:25:57.628Z","updated_at":"2025-03-16T07:06:23.255Z","avatar_url":"https://github.com/InfiniTimeOrg.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PineTime MCUBoot bootloader\nAn open source bootloader for the PineTime based on MyNEWT and MCUBoot.\n\n## About this project\nThis repo is based on [Lupyuen's](https://github.com/lupyuen) [amazing work](https://github.com/lupyuen/pinetime-rust-mynewt).\n\nLup is the very first developer to have dared to build a bootloader for the PineTime. And it was a success as [version 4.1.7](https://github.com/lupyuen/pinetime-rust-mynewt/releases/tag/v4.1.7) was preloaded in the new batch of PineTime devkits in September 2020.\n\nLup uses [his repo](https://github.com/lupyuen/pinetime-rust-mynewt) to conduct many experiments (Rust firmware, mynewt, lvgl,...). In this the, the code of the bootloader was mixed with a lot of other code, and the history was not easy to read.\n\nThat's why I decided (with his agreement) to extract the bootloader code into a shiny new project. This will ease the code readability and its maintenance.\n\nChanges between the original repo and the \"Initial commit\" of this one can be seen in this fork : https://github.com/JF002/pinetime-rust-mynewt/tree/restore-factory-image.\n\n## Features\n\n- Start the **application** firmware\n- Provide a safe and efficient way to **swap firmwares** from the secondary slot (in external flash memory) and the primary slot (in internal flash memory), thanks to MCUBoot\n- **Revert** to the previous version of the firmware\n- Load and run a **recovery** firmware\n- Basic UI (logo, progress bar, button)\n\n## Update\n\nPlease see [this page](docs/howToUpdate.md) for more info about the update procedure.\n\n## Memory map\n\n![Memory Map](docs/pictures/memoryMap.png \"Memory map\")\n\nThe PineTime is based on 2 flash memories:\n - **The internal flash** (512KB) : this flash is integrated into the MCU. The MCU runs the code from this memory. It cannot run codes directly from the external SPI flash memory. It contains the following sections:\n   - **Bootloader** (28KB - 0x7000B) : This bootloader.\n   - **Log** (4KB - 0x1000B) : Space reserved for boot/error logs. Not currently useed.\n   - **Application firmware** (464KB - 0x74000B) : application wrapped into a MCUBoot image (header, TLV, trailer).\n   - **Scrach** (4KB - 0x1000B) : the scratch area that allows MCUBoot to swap firmware between the internal and external memories.\n   - **Spare** (12KB - 0x3000B) : a spare and unused area.\n - **The external** flash (4MB) : this memory is external to the MCU and is connected to the MCU using an SPI bus. It contains the recovery firmware (in the section *Bootloader Assets*) and the secondary slot for MCUBoot (*OTA section*). The *FS* part is available for the application firmware.\n\n## Boot flow\n\nThe bootloader is the first piece of software that is running on the PineTime. Its main goal is to load the application firmware. It is also responsible to swap the firmware from the secondary and primary slot if a newer version of the firmware is present in the secondary slot. It also provides the possibility to revert to the previous version of the firmware and to restore a recovery firmware that supports OTA.\n\n![Boot flow](docs/pictures/workflow.png \"Boot flow\")\n\n\nAt startup, the bootloader displays a **logo and its version**:\n\n![Bootloader start](docs/pictures/bootloader_start.png \"Bootloader start\")\n\nThen, it waits for ~5s in case the user presses the button. The **progress** is shown by the color of the logo.\n\nWhen the user just wants to **run the current firmware**, they won't touch the button, and the logo will be filled in **green**:\n\n![Bootloader normal boot](docs/pictures/bootloader_normal_boot.png \"Bootloader normal boot\")\n\nWhen the timeout is elapsed, **MCUBoot** will be run. It'll swap the firmware if needed and then run the firmware from the primary slot.\n\nIf the user presses the button until the logo is drawn in **blue**, the previous version of the firmware will be **reverted**:\n\n![Bootloader revert](docs/pictures/bootloader_revert.png \"Bootloader revert\")\n\nIf the user presses the button longer, until the logo is drawn in **red**, the **recovery** firmware will be loaded into the primary slot and will be run after the next reset:\n\n![Bootloader recovery](docs/pictures/bootloader_recovery.png \"Bootloader recovery\")\n\n## Recovery firmware\n\nThe recovery firmware is a \"lightweight\" version of InfiniTime. It is stripped of most of its functionalities : it only provides **basic UI, BLE connectivity and OTA**.\n\nThe goal of this firmware is to provide a mean for the user to OTA a new firmware in case the current firmware does not work properly or does not provide OTA.\n\n![Bootloader recovery OTA](docs/pictures/bootloader_recovery_ota.png \"Bootloader recovery OTA\")\n\n\n## How to build\n\n- Install `newt` tool\n- Clone the project and `cd` into it\n- Init and update submodules : `git submodule update --init --recursive`\n- Configure mynewt : `newt upgrade`\n- Build : `scripts/nrf52/build-boot.sh`. The firmware is generated in `bin/targets/nrf52_boot/app/@mcuboot/boot/mynewt/mynewt.elf` and the DFU file for the reloader : `reloader/build-pinetime/reloader-mcuboot.zip`\n\n### Bitmap generation\n\nThis project uses 2 bitmaps (defined in [graphic.h](libs/pinetime_boot/src/graphic.h)) : \n - the Pine logo\n - the version indicator\n\nTo reduce the amount of flash memory needed to store them, they are compressed using a simple [RLE encoding](https://en.wikipedia.org/wiki/Run-length_encoding).\n\nUse the tool [rle_encode.py](tools/rle_encode.py) to convert a png file into a RLE encoded buffer:\n\n```shell\npython tools/rle_encode.py --c libs/pinetime_boot/src/version-1.0.1.png\n```\n\nHere is the corresponding output : \n\n```\n// 1-bit RLE, generated from libs/pinetime_boot/src/version-1.0.1.png, 269 bytes\nstatic const uint8_t version-1.0.1[] = {\n  0x59, 0x56, 0x2, 0x56, 0x2, 0x56, 0x2, 0x56, 0x2, 0x2, 0x2, 0xd,\n  0x2, 0x5, 0x4, 0x15, 0x5, 0x12, 0x4, 0xa, 0x2, 0x3, 0x2, 0xb,\n  0x2, 0x4, 0x6, 0x13, 0x9, 0xe, 0x6, 0xa, 0x2, 0x3, 0x2, 0xb,\n  0x2, 0x4, 0x2, 0x2, 0x2, 0x13, 0x2, 0x5, 0x2, 0xe, 0x2, 0x2,\n  0x2, 0xa, 0x2, 0x3, 0x3, 0x9, 0x3, 0x8, 0x2, 0x12, 0x2, 0x7,\n  0x2, 0x11, 0x2, 0xa, 0x2, 0x4, 0x2, 0x9, 0x2, 0x9, 0x2, 0x12,\n  0x2, 0x7, 0x2, 0x11, 0x2, 0xa, 0x2, 0x4, 0x2, 0x9, 0x2, 0x9,\n  0x2, 0x11, 0x2, 0x9, 0x2, 0x10, 0x2, 0xa, 0x2, 0x5, 0x2, 0x7,\n  0x2, 0xa, 0x2, 0x11, 0x2, 0x9, 0x2, 0x10, 0x2, 0xa, 0x2, 0x5,\n  0x2, 0x7, 0x2, 0xa, 0x2, 0x11, 0x2, 0x9, 0x2, 0x10, 0x2, 0xa,\n  0x2, 0x5, 0x3, 0x5, 0x3, 0xa, 0x2, 0x11, 0x2, 0x9, 0x2, 0x10,\n  0x2, 0xa, 0x2, 0x6, 0x2, 0x5, 0x2, 0xb, 0x2, 0x11, 0x2, 0x9,\n  0x2, 0x10, 0x2, 0xa, 0x2, 0x6, 0x2, 0x5, 0x2, 0xb, 0x2, 0x11,\n  0x2, 0x9, 0x2, 0x10, 0x2, 0xa, 0x2, 0x7, 0x2, 0x3, 0x2, 0xc,\n  0x2, 0x11, 0x2, 0x9, 0x2, 0x10, 0x2, 0xa, 0x2, 0x7, 0x2, 0x3,\n  0x2, 0xc, 0x2, 0x11, 0x2, 0x9, 0x2, 0x10, 0x2, 0xa, 0x2, 0x7,\n  0x2, 0x3, 0x2, 0xc, 0x2, 0x12, 0x2, 0x7, 0x2, 0x11, 0x2, 0xa,\n  0x2, 0x8, 0x2, 0x1, 0x2, 0xd, 0x2, 0x12, 0x2, 0x7, 0x2, 0x11,\n  0x2, 0xa, 0x2, 0x8, 0x2, 0x1, 0x2, 0xd, 0x2, 0xa, 0x2, 0x7,\n  0x2, 0x5, 0x2, 0x6, 0x2, 0xa, 0x2, 0xa, 0x2, 0x8, 0x5, 0x9,\n  0xa, 0x6, 0x2, 0x7, 0x9, 0x6, 0x2, 0x6, 0xa, 0x6, 0x2, 0x9,\n  0x3, 0xa, 0xa, 0x6, 0x2, 0x9, 0x5, 0x8, 0x2, 0x6, 0xa, 0x6,\n  0x2, 0x56, 0x2, 0x56, 0x59,\n};\n```\n\nYou can then copy/paste this C array to the corresponding definition in [graphic.h](libs/pinetime_boot/src/graphic.h). \n\n## About the code\n\nThis project is based on MyNEWT RTOS and MCUBoot bootloader. The specific code for the PineTime is located in `libs/pinetime_boot`.\n\n# Patches\n\n - [01-spiflash.patch](libs/pinetime_boot/patches/01-spiflash.patch) - July 2024 : Add support for the new SPI Flash memory chip (BY25Q32) into the `spiflash` driver of MyNewt. See [this issue](https://github.com/InfiniTimeOrg/pinetime-mcuboot-bootloader/issues/11) for more information.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finfinitimeorg%2Fpinetime-mcuboot-bootloader","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finfinitimeorg%2Fpinetime-mcuboot-bootloader","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finfinitimeorg%2Fpinetime-mcuboot-bootloader/lists"}