mirror of
https://github.com/oltaco/Adafruit_nRF52_Bootloader_OTAFIX.git
synced 2026-10-25 14:54:11 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c67f0bcf0f | ||
|
|
dc42c2a7c0 | ||
|
|
4b0fc1c504 | ||
|
|
00dba18703 | ||
|
|
2f272950fc | ||
|
|
64f1b70922 | ||
|
|
b3ac920e82 | ||
|
|
67105f8db3 | ||
|
|
48a149ffcb | ||
|
|
ac086326fe | ||
|
|
545fc0534d | ||
|
|
1f17efd611 | ||
|
|
96c57447c6 | ||
|
|
57ce8b2e93 | ||
|
|
8023c1e6a0 | ||
|
|
a32baf561b | ||
|
|
dd816e511a | ||
|
|
2d889d35d5 | ||
|
|
c2ae4183aa | ||
|
|
48cfda2a29 | ||
|
|
8c45bf843c | ||
|
|
c3282f4c0a | ||
|
|
3714bb727d | ||
|
|
c61f330c1d | ||
|
|
1307fe7f57 | ||
|
|
951a93abb4 |
No files matched your search
@@ -1,13 +1,18 @@
|
||||
name: Build
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
push:
|
||||
repository_dispatch:
|
||||
branches: [ master ]
|
||||
release:
|
||||
types:
|
||||
- created
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
set-matrix:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
+1
-1
@@ -56,6 +56,7 @@ dkms.conf
|
||||
|
||||
segger/Output
|
||||
_build/
|
||||
cmake-build-*/
|
||||
bin/
|
||||
*.emSession
|
||||
*.jlink
|
||||
@@ -68,4 +69,3 @@ Makefile.user
|
||||
|
||||
# Exclude all SoftDevice S340 files
|
||||
lib/softdevice/s340*
|
||||
|
||||
@@ -1,25 +1,102 @@
|
||||
# Agent Instructions
|
||||
|
||||
This file provides guidance to AI agents when working with code in this repository.
|
||||
|
||||
## Project Overview
|
||||
|
||||
CDC/DFU/UF2 bootloader for Nordic nRF52 microcontrollers (nRF52832, nRF52833, nRF52840). Supports DFU over Serial, BLE OTA, and USB mass storage (UF2). Runs on 60+ boards.
|
||||
|
||||
## Style
|
||||
- Follow the repo `.clang-format` when making changes.
|
||||
|
||||
Follow the repo `.clang-format` when making changes.
|
||||
|
||||
## Build / Verify
|
||||
- Prefer CMake for testing/verification.
|
||||
- Always build both boards during verification:
|
||||
- `feather_nrf52832`
|
||||
- `feather_nrf52840_express`
|
||||
|
||||
Default board: `feather_nrf52840_express`. Always verify changes against both boards:
|
||||
- `feather_nrf52840_express` (nRF52840)
|
||||
- `feather_nrf52832` (nRF52832)
|
||||
|
||||
### CMake (preferred)
|
||||
```bash
|
||||
cmake -S . -B cmake-build-feather_nrf52832 -DBOARD=feather_nrf52832
|
||||
cmake --build cmake-build-feather_nrf52832
|
||||
|
||||
cmake -S . -B cmake-build-feather_nrf52840_express -DBOARD=feather_nrf52840_express
|
||||
cmake --build cmake-build-feather_nrf52840_express
|
||||
|
||||
cmake -S . -B cmake-build-feather_nrf52832 -DBOARD=feather_nrf52832
|
||||
cmake --build cmake-build-feather_nrf52832
|
||||
```
|
||||
|
||||
### Make (alternate)
|
||||
```bash
|
||||
make BOARD=feather_nrf52832 all
|
||||
make BOARD=feather_nrf52840_express all
|
||||
make BOARD=feather_nrf52832 all
|
||||
```
|
||||
|
||||
### Flashing
|
||||
```bash
|
||||
make BOARD={board} flash # Flash via JLink
|
||||
make BOARD={board} flash-dfu # Flash via Serial/CDC DFU
|
||||
make BOARD={board} flash-sd # Flash SoftDevice only
|
||||
```
|
||||
|
||||
### Build all boards
|
||||
```bash
|
||||
python3 tools/build_all.py
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
### MCU Variants and SoftDevices
|
||||
- **nrf52** (nRF52832): UART-only bootloader, default SoftDevice s132 v6.1.1
|
||||
- **nrf52833**: USB support, default SoftDevice s140 v7.3.0
|
||||
- **nrf52840**: Full USB + OTA, default SoftDevice s140 v6.1.1
|
||||
- Boards may override `SD_NAME`/`SD_VERSION` in their `board.mk`
|
||||
|
||||
### Key Source Structure
|
||||
- `src/main.c` — Bootloader entry point, DFU mode detection, LED/button init
|
||||
- `src/dfu_init.c` — DFU packet validation, CRC/signature verification
|
||||
- `src/dfu_ble_svc.c` — BLE DFU service
|
||||
- `src/flash_nrf5x.c` — Flash memory operations
|
||||
- `src/boards/boards.c` — Board abstraction (LED control, buttons, timing)
|
||||
- `src/usb/` — USB stack (nRF52833/nRF52840): CDC serial, MSC storage, UF2 handler
|
||||
- `src/usb/uf2/ghostfat.c` — Virtual FAT filesystem for UF2 drag-and-drop
|
||||
|
||||
### Board Definition System
|
||||
|
||||
Each board lives in `src/boards/{board_name}/` with:
|
||||
- `board.h` — Pin definitions, LED/button assignments, USB VID/PID, UF2 metadata
|
||||
- `board.mk` — Makefile variable `MCU_SUB_VARIANT` (nrf52, nrf52833, or nrf52840)
|
||||
- `board.cmake` — CMake variable `MCU_VARIANT`
|
||||
- `pinconfig.c` — CF2 bootloader configuration (flash/RAM size, UF2 family ID)
|
||||
|
||||
### Memory Layout (linker scripts in `linker/`)
|
||||
- Bootloader occupies ~38KB near end of flash (e.g., 0xF4000–0xFD800 on nRF52840)
|
||||
- No heap (`__HEAP_SIZE=0`), static allocation only
|
||||
- Special sections: double-reset detection word, bond info for OTA, MBR params, bootloader settings
|
||||
|
||||
### Submodules (`lib/`)
|
||||
- `tinyusb` — USB device stack
|
||||
- `nrfx` — Nordic HAL drivers
|
||||
- `uf2` — UF2 format tools
|
||||
- `tinycrypt` — Crypto (only when `SIGNED_FW=1`)
|
||||
- `sdk/`, `sdk11/` — Nordic SDK libraries
|
||||
- `softdevice/` — Precompiled Bluetooth stack binaries
|
||||
|
||||
### Compile-Time Feature Flags
|
||||
- `SIGNED_FW` — Require signed firmware (disables UF2 unless `FORCE_UF2=1`)
|
||||
- `DUALBANK_FW` — Dual-bank updates
|
||||
- `DEFAULT_TO_OTA_DFU` — Default to BLE OTA instead of serial DFU
|
||||
- `DEBUG` — Enable RTT debugging, larger bootloader region
|
||||
|
||||
## PR Review Checklist
|
||||
|
||||
- **VID/PID assignment**: When a PR adds or modifies a board, verify `USB_DESC_VID`/`USB_DESC_UF2_PID` in `board.h`. New boards should use unique values. The Adafruit VID `0x239A` is reserved for Adafruit-allocated boards; third-party boards must use their own VID. Some legacy boards intentionally share a VID/PID with a reference board (see `// Shared VID/PID with ...` comments) — these are pending cleanup, not a template for new boards.
|
||||
|
||||
## CI
|
||||
|
||||
GitHub Actions (`.github/workflows/githubci.yml`) builds all boards in parallel using a matrix generated from `src/boards/` directory names. On release, artifacts (zip, hex, uf2) are uploaded as release assets.
|
||||
|
||||
## Required Toolchain
|
||||
|
||||
- `arm-none-eabi-gcc` (tested with 12.3.1)
|
||||
- Python 3 with: `adafruit-nrfutil`, `intelhex`
|
||||
- `nrfjprog` (for JLink flashing)
|
||||
+16
-7
@@ -316,13 +316,22 @@ endif()
|
||||
execute_process(COMMAND git describe --dirty --always --tags OUTPUT_VARIABLE GIT_VERSION)
|
||||
string(STRIP ${GIT_VERSION} GIT_VERSION)
|
||||
|
||||
string(REPLACE "-" ";" RELEASE_VERSION ${GIT_VERSION})
|
||||
list(GET RELEASE_VERSION 0 RELEASE_VERSION)
|
||||
string(REPLACE "." ";" RELEASE_VERSION ${RELEASE_VERSION})
|
||||
list(GET RELEASE_VERSION 0 RELEASE_VERSION_MAJOR)
|
||||
list(GET RELEASE_VERSION 1 RELEASE_VERSION_MINOR)
|
||||
list(GET RELEASE_VERSION 2 RELEASE_VERSION_PATCH)
|
||||
math(EXPR MK_BOOTLOADER_VERSION "(${RELEASE_VERSION_MAJOR} << 16) + (${RELEASE_VERSION_MINOR} << 8) + ${RELEASE_VERSION_PATCH}")
|
||||
# Extract semantic version numbers (MAJOR.MINOR.PATCH) from GIT_VERSION.
|
||||
# Supports tags like:
|
||||
# v1.2.3
|
||||
# 1.2.3
|
||||
# 1.2.3-147-gd71abcd
|
||||
# If the version string does not match MAJOR.MINOR.PATCH, defaults to 0.0.0.
|
||||
if(GIT_VERSION MATCHES "^v?([0-9]+)\\.([0-9]+)\\.([0-9]+)")
|
||||
set(RELEASE_VERSION_MAJOR ${CMAKE_MATCH_1})
|
||||
set(RELEASE_VERSION_MINOR ${CMAKE_MATCH_2})
|
||||
set(RELEASE_VERSION_PATCH ${CMAKE_MATCH_3})
|
||||
else()
|
||||
set(RELEASE_VERSION_MAJOR 0)
|
||||
set(RELEASE_VERSION_MINOR 0)
|
||||
set(RELEASE_VERSION_PATCH 0)
|
||||
endif()
|
||||
math(EXPR MK_BOOTLOADER_VERSION "((${RELEASE_VERSION_MAJOR} << 16) | (${RELEASE_VERSION_MINOR} << 8) | ${RELEASE_VERSION_PATCH})")
|
||||
|
||||
cmake_print_variables(GIT_VERSION MK_BOOTLOADER_VERSION)
|
||||
|
||||
|
||||
@@ -262,7 +262,7 @@ IPATH += \
|
||||
src/cmsis/include \
|
||||
src/usb \
|
||||
$(TUSB_PATH)
|
||||
|
||||
|
||||
ifeq ($(SIGNED_FW), 1)
|
||||
IPATH += \
|
||||
$(TCRYPT_PATH)/include
|
||||
@@ -376,8 +376,25 @@ ifeq ($(DEFAULT_TO_OTA_DFU), 1)
|
||||
CFLAGS += -DDEFAULT_TO_OTA_DFU
|
||||
endif
|
||||
|
||||
_VER = $(subst ., ,$(word 1, $(subst -, ,$(GIT_VERSION))))
|
||||
CFLAGS += -DMK_BOOTLOADER_VERSION='($(word 1,$(_VER)) << 16) + ($(word 2,$(_VER)) << 8) + $(word 3,$(_VER))'
|
||||
# Extract semantic version numbers (MAJOR.MINOR.PATCH) from GIT_VERSION.
|
||||
# Supports tags like:
|
||||
# v1.2.3
|
||||
# 1.2.3
|
||||
# 1.2.3-147-gd71abcd
|
||||
# If the version string does not match MAJOR.MINOR.PATCH, defaults to 0.0.0.
|
||||
_VER3 := $(shell echo "$(GIT_VERSION)" | sed -E 's/^v?([0-9]+)\.([0-9]+)\.([0-9]+).*/\1 \2 \3/; t; s/.*/0 0 0/')
|
||||
|
||||
# Split extracted version into individual numeric components
|
||||
_VER_MAJ := $(word 1,$(_VER3))
|
||||
_VER_MIN := $(word 2,$(_VER3))
|
||||
_VER_PAT := $(word 3,$(_VER3))
|
||||
|
||||
# Pack MAJOR.MINOR.PATCH into a single 32-bit integer:
|
||||
# [31:16] MAJOR
|
||||
# [15:8] MINOR
|
||||
# [7:0] PATCH
|
||||
# This value is stored in the bootloader version register and must be a valid C integer constant.
|
||||
CFLAGS += -DMK_BOOTLOADER_VERSION='((($(_VER_MAJ)<<16)|($(_VER_MIN)<<8)|($(_VER_PAT))))'
|
||||
|
||||
# Debug option use RTT for printf
|
||||
ifeq ($(DEBUG), 1)
|
||||
|
||||
@@ -51,9 +51,31 @@ typedef enum
|
||||
static pstorage_handle_t m_bootsettings_handle; /**< Pstorage handle to use for registration and identifying the bootloader module on subsequent calls to the pstorage module for load and store of bootloader setting in flash. */
|
||||
static bootloader_status_t m_update_status; /**< Current update status for the bootloader module to ensure correct behaviour when updating settings and when update completes. */
|
||||
static bool m_cancel_timeout_on_usb; /**< If set the timeout is cancelled when USB is enumerated. Otherwise, the timeout is only cancelled when DFU update is started. */
|
||||
static bool m_usb_was_mounted; /**< Tracks whether the USB DFU session was ever enumerated so we can exit when cable is later removed. */
|
||||
static bool m_startup_dfu_has_activity; /**< Tracks whether any valid serial or UF2 update traffic has started. */
|
||||
|
||||
APP_TIMER_DEF( _dfu_startup_timer );
|
||||
volatile bool dfu_startup_packet_received = false;
|
||||
|
||||
static void bootloader_timeout_startup_dfu(void)
|
||||
{
|
||||
if (!m_startup_dfu_has_activity)
|
||||
{
|
||||
dfu_update_status_t update_status;
|
||||
update_status.status_code = DFU_TIMEOUT;
|
||||
|
||||
bootloader_dfu_update_process(update_status);
|
||||
}
|
||||
}
|
||||
|
||||
void bootloader_dfu_activity_mark(void)
|
||||
{
|
||||
m_startup_dfu_has_activity = true;
|
||||
}
|
||||
|
||||
void bootloader_mark_usb_mounted(void)
|
||||
{
|
||||
m_usb_was_mounted = true;
|
||||
}
|
||||
|
||||
/**@brief Function for handling callbacks from pstorage module.
|
||||
*
|
||||
@@ -82,22 +104,17 @@ static void pstorage_callback_handler(pstorage_handle_t * p_handle,
|
||||
static void dfu_startup_timer_handler(void * p_context)
|
||||
{
|
||||
#ifdef NRF_USBD
|
||||
if (m_cancel_timeout_on_usb && tud_mounted())
|
||||
// If host enumerated the device, keep waiting — m_usb_was_mounted was set
|
||||
// by tud_mount_cb() and the unplug path in wait_for_events() will handle exit.
|
||||
if (m_cancel_timeout_on_usb && m_usb_was_mounted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// nRF52832 forced DFU on startup
|
||||
// No packets are received within timeout, exit DFU mode
|
||||
// dfu_startup_packet_received is set by process_dfu_packet() in dfu_transport_serial.c
|
||||
if (!dfu_startup_packet_received)
|
||||
{
|
||||
dfu_update_status_t update_status;
|
||||
update_status.status_code = DFU_TIMEOUT;
|
||||
|
||||
bootloader_dfu_update_process(update_status);
|
||||
}
|
||||
// No update activity is received within timeout, exit DFU mode
|
||||
bootloader_timeout_startup_dfu();
|
||||
}
|
||||
|
||||
/**@brief Function for waiting for events.
|
||||
@@ -133,6 +150,14 @@ static void wait_for_events(void)
|
||||
tud_task();
|
||||
tud_cdc_write_flush();
|
||||
}
|
||||
|
||||
// Exit startup DFU once USB was actually unplugged (VBUS gone), not on a
|
||||
// host-side re-enumeration or temporary unmount.
|
||||
if (m_cancel_timeout_on_usb && m_usb_was_mounted &&
|
||||
!(NRF_POWER->USBREGSTATUS & POWER_USBREGSTATUS_VBUSDETECT_Msk))
|
||||
{
|
||||
bootloader_timeout_startup_dfu();
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((m_update_status == BOOTLOADER_COMPLETE) ||
|
||||
@@ -149,23 +174,22 @@ static void wait_for_events(void)
|
||||
|
||||
bool bootloader_app_is_valid(void)
|
||||
{
|
||||
bool success = false;
|
||||
uint32_t const app_addr = DFU_BANK_0_REGION_START;
|
||||
|
||||
bootloader_settings_t const *p_bootloader_settings;
|
||||
bootloader_util_settings_get(&p_bootloader_settings);
|
||||
uint32_t const sp_addr = *((uint32_t*)app_addr);
|
||||
uint32_t const reset_addr = *((uint32_t*)(app_addr + 4));
|
||||
|
||||
enum { EMPTY_FLASH = 0xFFFFFFFFUL };
|
||||
|
||||
// Application is invalid if first 2 words are all 0xFFFFFFF
|
||||
if ( *((uint32_t *)app_addr ) == EMPTY_FLASH &&
|
||||
*((uint32_t *)(app_addr+4)) == EMPTY_FLASH )
|
||||
if (sp_addr == EMPTY_FLASH && reset_addr == EMPTY_FLASH)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// The application in CODE region 1 is flagged as valid during update.
|
||||
if ( p_bootloader_settings->bank_0 == BANK_VALID_APP )
|
||||
bootloader_settings_t const * p_bootloader_settings;
|
||||
bootloader_util_settings_get(&p_bootloader_settings);
|
||||
|
||||
// Primary path: a prior DFU flagged bank 0 as valid.
|
||||
if (p_bootloader_settings->bank_0 == BANK_VALID_APP)
|
||||
{
|
||||
uint16_t image_crc = 0;
|
||||
|
||||
@@ -177,10 +201,26 @@ bool bootloader_app_is_valid(void)
|
||||
NULL);
|
||||
}
|
||||
|
||||
success = (image_crc == p_bootloader_settings->bank_0_crc);
|
||||
return (image_crc == p_bootloader_settings->bank_0_crc);
|
||||
}
|
||||
|
||||
return success;
|
||||
// Fallback for debugger-flashed apps: settings page is erased (bank_0 = 0xFFFF)
|
||||
// but an app may still have been written to bank 0 directly. Accept it if its
|
||||
// Cortex-M vector table is plausible: initial SP within RAM, reset vector
|
||||
// within app flash region with the Thumb bit set. The SP upper bound is
|
||||
// inclusive because the empty-descending stack initializes one past RAM end.
|
||||
if (p_bootloader_settings->bank_0 == 0xFFFF)
|
||||
{
|
||||
uint32_t const ram_start = 0x20000000UL;
|
||||
uint32_t const ram_end = ram_start + (NRF_FICR->INFO.RAM << 10u);
|
||||
bool const sp_valid = (sp_addr >= ram_start) && (sp_addr <= ram_end) && ((sp_addr & 3U) == 0);
|
||||
bool const reset_in_app = (reset_addr & 1U) &&
|
||||
(reset_addr >= app_addr) &&
|
||||
(reset_addr < BOOTLOADER_REGION_START);
|
||||
return sp_valid && reset_in_app;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -358,6 +398,8 @@ uint32_t bootloader_dfu_start(bool ota, uint32_t timeout_ms, bool cancel_timeout
|
||||
uint32_t err_code;
|
||||
|
||||
m_cancel_timeout_on_usb = cancel_timeout_on_usb && !ota;
|
||||
m_usb_was_mounted = false;
|
||||
m_startup_dfu_has_activity = false;
|
||||
|
||||
// Clear swap if banked update is used.
|
||||
err_code = dfu_init();
|
||||
@@ -373,8 +415,6 @@ uint32_t bootloader_dfu_start(bool ota, uint32_t timeout_ms, bool cancel_timeout
|
||||
// - Makecode single tap reset but no enumerated (battery power)
|
||||
if ( timeout_ms )
|
||||
{
|
||||
dfu_startup_packet_received = false;
|
||||
|
||||
app_timer_create(&_dfu_startup_timer, APP_TIMER_MODE_SINGLE_SHOT, dfu_startup_timer_handler);
|
||||
app_timer_start(_dfu_startup_timer, APP_TIMER_TICKS(timeout_ms), NULL);
|
||||
}
|
||||
|
||||
@@ -74,6 +74,20 @@ void bootloader_settings_get(bootloader_settings_t * const p_settings);
|
||||
*/
|
||||
void bootloader_dfu_update_process(dfu_update_status_t update_status);
|
||||
|
||||
/**@brief Mark that startup DFU has received valid update activity.
|
||||
*
|
||||
* @details This suppresses the startup timeout or USB unplug fallback that is only
|
||||
* meant for the "entered bootloader, but never started an update" case.
|
||||
*/
|
||||
void bootloader_dfu_activity_mark(void);
|
||||
|
||||
/**@brief Mark that the USB DFU session was enumerated by a host.
|
||||
*
|
||||
* @details Called from tud_mount_cb(). Enables the USB-unplug exit path in
|
||||
* wait_for_events(), which exits startup DFU once VBUS is removed.
|
||||
*/
|
||||
void bootloader_mark_usb_mounted(void);
|
||||
|
||||
/**@brief Function getting state of SoftDevice update in progress.
|
||||
* After a successfull SoftDevice transfer the system restarts in orderto disable SoftDevice
|
||||
* and complete the update.
|
||||
|
||||
@@ -11,9 +11,12 @@
|
||||
*/
|
||||
|
||||
#include "bootloader_util.h"
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "dfu_types.h"
|
||||
#include "nrf_peripherals.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* @brief Function for aborting current application/bootloader jump to to other app/bootloader.
|
||||
@@ -164,8 +167,76 @@ static inline void bootloader_util_reset(uint32_t start_addr)
|
||||
#error Compiler not supported.
|
||||
#endif
|
||||
|
||||
// protect flash region from write access
|
||||
static uint32_t bootloader_util_flash_protect(uint32_t address, uint32_t size) {
|
||||
if ((size & (CODE_PAGE_SIZE - 1)) || (address & (CODE_PAGE_SIZE - 1)) || (address > BOOTLOADER_SETTINGS_ADDRESS)) {
|
||||
return NRF_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
void bootloader_util_app_start(uint32_t start_addr)
|
||||
{
|
||||
bootloader_util_reset(start_addr);
|
||||
#if defined(ACL_PRESENT)
|
||||
// Protect using ACL.
|
||||
static uint32_t acl_instance = 0;
|
||||
|
||||
volatile ACL_ACL_Type *p_acl;
|
||||
const uint32_t mask = (ACL_ACL_PERM_WRITE_Disable << ACL_ACL_PERM_WRITE_Pos);
|
||||
|
||||
do {
|
||||
if (acl_instance >= ACL_REGIONS_COUNT) {
|
||||
return NRF_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
p_acl = &NRF_ACL->ACL[acl_instance];
|
||||
p_acl->ADDR = address;
|
||||
p_acl->SIZE = size;
|
||||
p_acl->PERM = mask;
|
||||
|
||||
acl_instance++;
|
||||
|
||||
} while (p_acl->ADDR != address || p_acl->SIZE != size ||
|
||||
p_acl->PERM != mask); // Check whether the acl_instance has been used before.
|
||||
|
||||
#elif defined(BPROT_PRESENT)
|
||||
// Protect using BPROT. BPROT does not support read protection.
|
||||
uint32_t pagenum_start = address / CODE_PAGE_SIZE;
|
||||
uint32_t pagenum_end = pagenum_start + ((size - 1) / CODE_PAGE_SIZE);
|
||||
|
||||
for (uint32_t i = pagenum_start; i <= pagenum_end; i++) {
|
||||
uint32_t config_index = i / 32;
|
||||
uint32_t mask = (1 << (i - config_index * 32));
|
||||
|
||||
switch (config_index) {
|
||||
case 0:
|
||||
NRF_BPROT->CONFIG0 = mask;
|
||||
break;
|
||||
case 1:
|
||||
NRF_BPROT->CONFIG1 = mask;
|
||||
break;
|
||||
#if BPROT_REGIONS_NUM > 64
|
||||
case 2:
|
||||
NRF_BPROT->CONFIG2 = mask;
|
||||
break;
|
||||
case 3:
|
||||
NRF_BPROT->CONFIG3 = mask;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
void bootloader_util_app_start(uint32_t start_addr) {
|
||||
// Protect MBR against user writes
|
||||
bootloader_util_flash_protect(0, MBR_SIZE);
|
||||
|
||||
// Size of the bootloader flash area to protect (Bootloader + MBR params + Bootloader settings)
|
||||
const uint32_t area_size = BOOTLOADER_SETTINGS_ADDRESS + CODE_PAGE_SIZE - BOOTLOADER_REGION_START;
|
||||
|
||||
// Protect bootloader code and params pages against user writes
|
||||
bootloader_util_flash_protect(BOOTLOADER_REGION_START, area_size);
|
||||
|
||||
// Jump to user application
|
||||
bootloader_util_reset(start_addr);
|
||||
}
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "dfu_transport.h"
|
||||
#include <stddef.h>
|
||||
#include "bootloader.h"
|
||||
#include "dfu.h"
|
||||
#include <dfu_types.h>
|
||||
#include "app_error.h"
|
||||
@@ -197,9 +198,8 @@ static void process_dfu_packet(void * p_event_data, uint16_t event_size)
|
||||
uint32_t index;
|
||||
dfu_update_packet_t * packet;
|
||||
|
||||
// Adafruit modification for startup dfu
|
||||
extern bool dfu_startup_packet_received;
|
||||
dfu_startup_packet_received = true;
|
||||
// Mark that startup DFU has transitioned into a real update flow.
|
||||
bootloader_dfu_activity_mark();
|
||||
|
||||
while (false == DATA_QUEUE_EMPTY())
|
||||
{
|
||||
|
||||
@@ -20,6 +20,37 @@
|
||||
* @brief Device Firmware Update module type and definitions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Flash layout (nrf52840, see linker/nrf52840.ld):
|
||||
*
|
||||
* -------------------------
|
||||
* | Bootloader Settings |
|
||||
* | 4 KB |
|
||||
* |-------------------------| 0xFF000 BOOTLOADER_SETTINGS_ADDRESS
|
||||
* | MBR Params Page |
|
||||
* | 4 KB |
|
||||
* |-------------------------| 0xFE000
|
||||
* | Bootloader Config |
|
||||
* | 2 KB |
|
||||
* |-------------------------| 0xFD800
|
||||
* | Bootloader |
|
||||
* | 38 KB |
|
||||
* |-------------------------| 0xF4000 BOOTLOADER_REGION_START
|
||||
* | App Data Reserved |
|
||||
* | 40 KB |
|
||||
* |-------------------------| 0xEA000
|
||||
* | Application |
|
||||
* | Single/ Dual Bank |
|
||||
* | |
|
||||
* |-------------------------| CODE_REGION_1_START
|
||||
* | SoftDevice |
|
||||
* | 0x26000 (optional) |
|
||||
* |-------------------------| 0x01000
|
||||
* | MBR |
|
||||
* | 4 KB |
|
||||
* ------------------------- 0x00000
|
||||
*/
|
||||
|
||||
#ifndef DFU_TYPES_H__
|
||||
#define DFU_TYPES_H__
|
||||
|
||||
|
||||
@@ -28,10 +28,10 @@
|
||||
/*------------------------------------------------------------------*/
|
||||
/* LED
|
||||
*------------------------------------------------------------------*/
|
||||
// The board has 3 leds, but changing the number here causes OTA issues.
|
||||
#define LEDS_NUMBER 1
|
||||
#define LED_PRIMARY_PIN PINNUM(0, 26)
|
||||
#define LED_STATE_ON 0
|
||||
#define LEDS_NUMBER 2
|
||||
#define LED_PRIMARY_PIN PINNUM(0, 26) // red
|
||||
#define LED_SECONDARY_PIN PINNUM(0, 6) // blue
|
||||
#define LED_STATE_ON 0
|
||||
|
||||
#define NEOPIXELS_NUMBER 0
|
||||
|
||||
|
||||
@@ -28,10 +28,10 @@
|
||||
/*------------------------------------------------------------------*/
|
||||
/* LED
|
||||
*------------------------------------------------------------------*/
|
||||
// The board has 3 leds, but changing the number here causes OTA issues.
|
||||
#define LEDS_NUMBER 1
|
||||
#define LED_PRIMARY_PIN PINNUM(0, 26)
|
||||
#define LED_STATE_ON 0
|
||||
#define LEDS_NUMBER 2
|
||||
#define LED_PRIMARY_PIN PINNUM(0, 26) // red
|
||||
#define LED_SECONDARY_PIN PINNUM(0, 6) // blue
|
||||
#define LED_STATE_ON 0
|
||||
|
||||
#define NEOPIXELS_NUMBER 0
|
||||
|
||||
|
||||
+11
-1
@@ -145,9 +145,19 @@ int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t*
|
||||
uint32_t count = 0;
|
||||
while ( count < bufsize )
|
||||
{
|
||||
int written;
|
||||
|
||||
// Consider non-uf2 block write as successful
|
||||
// only break if write_block is busy with flashing (return 0)
|
||||
if ( 0 == write_block(lba, buffer, &_wr_state) ) break;
|
||||
written = write_block(lba, buffer, &_wr_state);
|
||||
if ( written > 0 )
|
||||
{
|
||||
bootloader_dfu_activity_mark();
|
||||
}
|
||||
else if ( written == 0 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
lba++;
|
||||
buffer += 512;
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
#include "uf2/uf2.h"
|
||||
#include "boards.h"
|
||||
#include "bootloader.h"
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
|
||||
@@ -115,6 +116,7 @@ void usb_teardown(void) {
|
||||
//--------------------------------------------------------------------+
|
||||
void tud_mount_cb(void) {
|
||||
led_state(STATE_USB_MOUNTED);
|
||||
bootloader_mark_usb_mounted();
|
||||
}
|
||||
|
||||
void tud_umount_cb(void) {
|
||||
|
||||
Reference in new issue
Block a user