From 99ad4d5c0f9ad3065904905269348f94d908835d Mon Sep 17 00:00:00 2001 From: Paperino Date: Thu, 26 Jan 2023 17:37:18 -0800 Subject: [PATCH 01/90] Add support for xiao ble nrf52840 based boards. --- src/boards/xiao_nrf52840_ble/board.h | 68 ++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/boards/xiao_nrf52840_ble/board.h diff --git a/src/boards/xiao_nrf52840_ble/board.h b/src/boards/xiao_nrf52840_ble/board.h new file mode 100644 index 0000000..b883be7 --- /dev/null +++ b/src/boards/xiao_nrf52840_ble/board.h @@ -0,0 +1,68 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018 Ha Thach for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef _XIAO_BLE +#define _XIAO_BLE + +#define _PINNUM(port, pin) ((port)*32 + (pin)) + +/*------------------------------------------------------------------*/ +/* 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 NEOPIXELS_NUMBER 0 + +/*------------------------------------------------------------------*/ +/* BUTTON + *------------------------------------------------------------------*/ +#define BUTTONS_NUMBER 2 +#define BUTTON_1 _PINNUM(0, 18) +// Button 2 is defined as D1 from expansion board. +#define BUTTON_2 _PINNUM(0, 3) +#define BUTTON_PULL NRF_GPIO_PIN_PULLUP + +//--------------------------------------------------------------------+ +// BLE OTA +//--------------------------------------------------------------------+ +#define BLEDIS_MANUFACTURER "Seeed" +#define BLEDIS_MODEL "XIAO nRF52840" + +//--------------------------------------------------------------------+ +// USB +//--------------------------------------------------------------------+ +#define USB_DESC_VID 0x2886 +#define USB_DESC_UF2_PID 0x0044 +#define USB_DESC_CDC_ONLY_PID 0x0044 + +//------------- UF2 -------------// +#define UF2_PRODUCT_NAME "Seeed XIAO nRF52840" +#define UF2_VOLUME_LABEL "XIAO-BOOT" +#define UF2_BOARD_ID "Seeed_XIAO_nRF52840" +#define UF2_INDEX_URL "https://www.seeedstudio.com/" + +#endif // _XIAO_BLE From cf3f39f576ef2dd0a1e78e4d9ca31096743b3c9b Mon Sep 17 00:00:00 2001 From: Paperino Date: Thu, 26 Jan 2023 17:37:43 -0800 Subject: [PATCH 02/90] Add support for Xiao BLE boards --- src/boards/xiao_nrf52840_ble/board.mk | 2 + src/boards/xiao_nrf52840_ble/pinconfig.c | 19 ++++++ src/boards/xiao_nrf52840_ble_sense/board.h | 68 +++++++++++++++++++ src/boards/xiao_nrf52840_ble_sense/board.mk | 2 + .../xiao_nrf52840_ble_sense/pinconfig.c | 19 ++++++ 5 files changed, 110 insertions(+) create mode 100644 src/boards/xiao_nrf52840_ble/board.mk create mode 100644 src/boards/xiao_nrf52840_ble/pinconfig.c create mode 100644 src/boards/xiao_nrf52840_ble_sense/board.h create mode 100644 src/boards/xiao_nrf52840_ble_sense/board.mk create mode 100644 src/boards/xiao_nrf52840_ble_sense/pinconfig.c diff --git a/src/boards/xiao_nrf52840_ble/board.mk b/src/boards/xiao_nrf52840_ble/board.mk new file mode 100644 index 0000000..8a77053 --- /dev/null +++ b/src/boards/xiao_nrf52840_ble/board.mk @@ -0,0 +1,2 @@ +MCU_SUB_VARIANT = nrf52840 +SD_VERSION = 7.3.0 \ No newline at end of file diff --git a/src/boards/xiao_nrf52840_ble/pinconfig.c b/src/boards/xiao_nrf52840_ble/pinconfig.c new file mode 100644 index 0000000..2a592df --- /dev/null +++ b/src/boards/xiao_nrf52840_ble/pinconfig.c @@ -0,0 +1,19 @@ +#include "boards.h" +#include "uf2/configkeys.h" + +__attribute__((used, section(".bootloaderConfig"))) +const uint32_t bootloaderConfig[] = +{ + /* CF2 START */ + CFG_MAGIC0, CFG_MAGIC1, // magic + 5, 100, // used entries, total entries + + 204, 0x100000, // FLASH_BYTES = 0x100000 + 205, 0x40000, // RAM_BYTES = 0x40000 + 208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2 + 209, 0xada52840, // UF2_FAMILY = 0xada52840 + 210, 0x20, // PINS_PORT_SIZE = PA_32 + + 0, 0, 0, 0, 0, 0, 0, 0 + /* CF2 END */ +}; \ No newline at end of file diff --git a/src/boards/xiao_nrf52840_ble_sense/board.h b/src/boards/xiao_nrf52840_ble_sense/board.h new file mode 100644 index 0000000..4872b0a --- /dev/null +++ b/src/boards/xiao_nrf52840_ble_sense/board.h @@ -0,0 +1,68 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018 Ha Thach for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef _XIAO_BLE_SENSE +#define _XIAO_BLE_SENSE + +#define _PINNUM(port, pin) ((port)*32 + (pin)) + +/*------------------------------------------------------------------*/ +/* 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 NEOPIXELS_NUMBER 0 + +/*------------------------------------------------------------------*/ +/* BUTTON + *------------------------------------------------------------------*/ +#define BUTTONS_NUMBER 2 +#define BUTTON_1 _PINNUM(0, 18) +// Button 2 is defined as D1 from expansion board. +#define BUTTON_2 _PINNUM(0, 3) +#define BUTTON_PULL NRF_GPIO_PIN_PULLUP + +//--------------------------------------------------------------------+ +// BLE OTA +//--------------------------------------------------------------------+ +#define BLEDIS_MANUFACTURER "Seeed" +#define BLEDIS_MODEL "XIAO nRF52840 Sense" + +//--------------------------------------------------------------------+ +// USB +//--------------------------------------------------------------------+ +#define USB_DESC_VID 0x2886 +#define USB_DESC_UF2_PID 0x0045 +#define USB_DESC_CDC_ONLY_PID 0x0045 + +//------------- UF2 -------------// +#define UF2_PRODUCT_NAME "Seeed XIAO nRF52840" +#define UF2_VOLUME_LABEL "XIAO-SENSE" +#define UF2_BOARD_ID "Seeed_XIAO_nRF52840_Sense" +#define UF2_INDEX_URL "https://www.seeedstudio.com/" + +#endif // _XIAO_BLE_SENSE diff --git a/src/boards/xiao_nrf52840_ble_sense/board.mk b/src/boards/xiao_nrf52840_ble_sense/board.mk new file mode 100644 index 0000000..8a77053 --- /dev/null +++ b/src/boards/xiao_nrf52840_ble_sense/board.mk @@ -0,0 +1,2 @@ +MCU_SUB_VARIANT = nrf52840 +SD_VERSION = 7.3.0 \ No newline at end of file diff --git a/src/boards/xiao_nrf52840_ble_sense/pinconfig.c b/src/boards/xiao_nrf52840_ble_sense/pinconfig.c new file mode 100644 index 0000000..2a592df --- /dev/null +++ b/src/boards/xiao_nrf52840_ble_sense/pinconfig.c @@ -0,0 +1,19 @@ +#include "boards.h" +#include "uf2/configkeys.h" + +__attribute__((used, section(".bootloaderConfig"))) +const uint32_t bootloaderConfig[] = +{ + /* CF2 START */ + CFG_MAGIC0, CFG_MAGIC1, // magic + 5, 100, // used entries, total entries + + 204, 0x100000, // FLASH_BYTES = 0x100000 + 205, 0x40000, // RAM_BYTES = 0x40000 + 208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2 + 209, 0xada52840, // UF2_FAMILY = 0xada52840 + 210, 0x20, // PINS_PORT_SIZE = PA_32 + + 0, 0, 0, 0, 0, 0, 0, 0 + /* CF2 END */ +}; \ No newline at end of file From aac573642ba77f99213fb8d33b817e12fe81c8b8 Mon Sep 17 00:00:00 2001 From: Paperinik <42046613+aovestdipaperino@users.noreply.github.com> Date: Sun, 5 Feb 2023 18:23:35 -0800 Subject: [PATCH 03/90] Update board.h UF2 board ID updated to specs. --- src/boards/xiao_nrf52840_ble/board.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boards/xiao_nrf52840_ble/board.h b/src/boards/xiao_nrf52840_ble/board.h index b883be7..9f4c45e 100644 --- a/src/boards/xiao_nrf52840_ble/board.h +++ b/src/boards/xiao_nrf52840_ble/board.h @@ -62,7 +62,7 @@ //------------- UF2 -------------// #define UF2_PRODUCT_NAME "Seeed XIAO nRF52840" #define UF2_VOLUME_LABEL "XIAO-BOOT" -#define UF2_BOARD_ID "Seeed_XIAO_nRF52840" +#define UF2_BOARD_ID "nRF52840-SeeedXiao-v1" #define UF2_INDEX_URL "https://www.seeedstudio.com/" #endif // _XIAO_BLE From d7494e81cee46878d78a24b436d783b12ef72bd8 Mon Sep 17 00:00:00 2001 From: Paperinik <42046613+aovestdipaperino@users.noreply.github.com> Date: Sun, 5 Feb 2023 18:24:19 -0800 Subject: [PATCH 04/90] Update board.h --- src/boards/xiao_nrf52840_ble_sense/board.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boards/xiao_nrf52840_ble_sense/board.h b/src/boards/xiao_nrf52840_ble_sense/board.h index 4872b0a..e512c1b 100644 --- a/src/boards/xiao_nrf52840_ble_sense/board.h +++ b/src/boards/xiao_nrf52840_ble_sense/board.h @@ -62,7 +62,7 @@ //------------- UF2 -------------// #define UF2_PRODUCT_NAME "Seeed XIAO nRF52840" #define UF2_VOLUME_LABEL "XIAO-SENSE" -#define UF2_BOARD_ID "Seeed_XIAO_nRF52840_Sense" +#define UF2_BOARD_ID "nRF52840-SeeedXiaoSense-v1" #define UF2_INDEX_URL "https://www.seeedstudio.com/" #endif // _XIAO_BLE_SENSE From 1bca78c0c8f79acb79ed8105725c39b08284b4e6 Mon Sep 17 00:00:00 2001 From: Paperinik <42046613+aovestdipaperino@users.noreply.github.com> Date: Sun, 5 Feb 2023 18:27:02 -0800 Subject: [PATCH 05/90] Update githubci.yml Added: -xiao_nrf52840_ble -xiao_nrf52840_ble_sense --- .github/workflows/githubci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/githubci.yml b/.github/workflows/githubci.yml index 7644c7c..ad77865 100644 --- a/.github/workflows/githubci.yml +++ b/.github/workflows/githubci.yml @@ -58,7 +58,9 @@ jobs: - 'raytac_mdbt50q_rx' - 'sparkfun_nrf52840_micromod' - 'waveshare_nrf52840_eval' - + - 'xiao_nrf52840_ble' + - 'xiao_nrf52840_ble_sense' + steps: - name: Setup Python uses: actions/setup-python@v3 From a980696dd0d7509b6a2c1212c243fa4ce9a648f9 Mon Sep 17 00:00:00 2001 From: montea Date: Sun, 12 Feb 2023 18:51:21 +0000 Subject: [PATCH 06/90] Changed the default max MTU size within the DFU transport to 23, which is the required size for the legacy bootloader to perform a successful OTA with the latest Nordic-DFU-Library. --- .../components/libraries/bootloader_dfu/dfu_transport_ble.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c b/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c index 4b459d7..2715dce 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c @@ -37,7 +37,7 @@ #define BLEGAP_EVENT_LENGTH 6 -#define BLEGATT_ATT_MTU_MAX 247 +#define BLEGATT_ATT_MTU_MAX 23 enum { BLE_CONN_CFG_HIGH_BANDWIDTH = 1 }; #define DFU_REV_MAJOR 0x00 /** DFU Major revision number to be exposed. */ From 5f95de13141384269fb0f30f23c31aeefb510196 Mon Sep 17 00:00:00 2001 From: montea Date: Mon, 13 Feb 2023 10:46:51 +0000 Subject: [PATCH 07/90] Set MTU to 23 within main.c file as per request on the comment above it --- src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index 47386ca..960daa4 100644 --- a/src/main.c +++ b/src/main.c @@ -131,7 +131,7 @@ extern void tusb_hal_nrf_power_event(uint32_t event); // These value must be the same with one in dfu_transport_ble.c #define BLEGAP_EVENT_LENGTH 6 -#define BLEGATT_ATT_MTU_MAX 247 +#define BLEGATT_ATT_MTU_MAX 23 enum { BLE_CONN_CFG_HIGH_BANDWIDTH = 1 }; //--------------------------------------------------------------------+ From 188e25948bb3be314949ac2e810778afd0bb435e Mon Sep 17 00:00:00 2001 From: hyx0329 Date: Thu, 25 May 2023 17:32:33 +0800 Subject: [PATCH 08/90] Add `board_init2` and `board_teardown2` This also replace `board_init_extra`. --- src/boards/boards.c | 11 +++++++++-- src/boards/challenger_840_ble/pinconfig.c | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/boards/boards.c b/src/boards/boards.c index e86edd6..de95950 100644 --- a/src/boards/boards.c +++ b/src/boards/boards.c @@ -63,7 +63,8 @@ bool button_pressed(uint32_t pin) } // This is declared so that a board specific init can be called from here. -void __attribute__((weak)) board_init_extra(void) { } +void __attribute__((weak)) board_init2(void) { } + void board_init(void) { // stop LF clock just in case we jump from application without reset @@ -96,7 +97,7 @@ void board_init(void) NRF_POWER->DCDCEN = 1; #endif // Make sure any custom inits are performed - board_init_extra(); + board_init2(); // When board is supplied on VDDH (and not VDD), this specifies what voltage the GPIO should run at // and what voltage is output at VDD. The default (0xffffffff) is 1.8V; typically you'll want @@ -129,6 +130,9 @@ void board_init(void) SysTick_Config(SystemCoreClock/1000); } +// Actions at the end of board_teardown. +void __attribute__((weak)) board_teardown2(void) { } + void board_teardown(void) { // Disable systick, turn off LEDs @@ -159,6 +163,9 @@ void board_teardown(void) { nrf_gpio_cfg_default(i); } + + // board specific teardown actions + board_teardown2(); } static uint32_t _systick_count = 0; diff --git a/src/boards/challenger_840_ble/pinconfig.c b/src/boards/challenger_840_ble/pinconfig.c index cb83e33..601844c 100644 --- a/src/boards/challenger_840_ble/pinconfig.c +++ b/src/boards/challenger_840_ble/pinconfig.c @@ -19,7 +19,7 @@ const uint32_t bootloaderConfig[] = /* CF2 END */ }; -void board_init_extra(void) +void board_init2(void) { // Turn LDO on nrf_gpio_cfg_output(LDO_CONTROL_PIN); From e34b183f1d77ada051893bd6ee1b08660c292b78 Mon Sep 17 00:00:00 2001 From: hyx0329 Date: Thu, 25 May 2023 17:56:05 +0800 Subject: [PATCH 09/90] Fix support for M60 keyboard - Change BUTTON_2 to ESC and setup related pins properly - Always enable the battery --- src/boards/m60_keyboard/board.h | 7 +++++- src/boards/m60_keyboard/pinconfig.c | 38 +++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/boards/m60_keyboard/board.h b/src/boards/m60_keyboard/board.h index e17f8b5..77371b1 100644 --- a/src/boards/m60_keyboard/board.h +++ b/src/boards/m60_keyboard/board.h @@ -43,9 +43,14 @@ *------------------------------------------------------------------*/ #define BUTTONS_NUMBER 2 #define BUTTON_1 _PINNUM(0, 27) -#define BUTTON_2 _PINNUM(1, 7) +#define BUTTON_2 _PINNUM(0, 19) // ESC #define BUTTON_PULL NRF_GPIO_PIN_PULLUP +/*------------------------------------------------------------------*/ +/* On board regulator control + *------------------------------------------------------------------*/ +#define LDO_CONTROL_PIN _PINNUM(0, 28) // Enables external pwr + //--------------------------------------------------------------------+ // BLE OTA //--------------------------------------------------------------------+ diff --git a/src/boards/m60_keyboard/pinconfig.c b/src/boards/m60_keyboard/pinconfig.c index a983e4a..1df7a6f 100644 --- a/src/boards/m60_keyboard/pinconfig.c +++ b/src/boards/m60_keyboard/pinconfig.c @@ -1,4 +1,5 @@ #include "boards.h" +#include "board.h" #include "uf2/configkeys.h" __attribute__((used, section(".bootloaderConfig"))) @@ -17,3 +18,40 @@ const uint32_t bootloaderConfig[] = 0, 0, 0, 0, 0, 0, 0, 0 /* CF2 END */ }; + +static void power_on(void) +{ + // Turn on the regulator + nrf_gpio_cfg_output(LDO_CONTROL_PIN); + nrf_gpio_pin_write(LDO_CONTROL_PIN, 1); +} + +void board_init2(void) +{ + power_on(); + + // configure P0.05 for ESC/BUTTON_2 + // P0.05 --- |<- --- / --- P0.19 + // diode sw(esc) + // mode: output, push-pull, low + nrf_gpio_cfg( + _PINNUM(0, 5), + NRF_GPIO_PIN_DIR_OUTPUT, + NRF_GPIO_PIN_INPUT_DISCONNECT, + NRF_GPIO_PIN_NOPULL, + NRF_GPIO_PIN_H0D1, + NRF_GPIO_PIN_NOSENSE + ); + nrf_gpio_pin_write(_PINNUM(0, 5), 0); + + // Wait the buttons stable. + // This is mandatory, or the keyboard will enter bootloader whenever + // booted by pressing the button at back (same with BUTTON_1) + NRFX_DELAY_MS(300); +} + +void board_teardown2(void) +{ + // re-enable the battery + power_on(); +} \ No newline at end of file From aebee3dfd4f1b46a1b8a1e1fd38e78e348725fe3 Mon Sep 17 00:00:00 2001 From: Mark Trevor Birss Date: Thu, 20 Jul 2023 09:46:00 +0200 Subject: [PATCH 10/90] Add files via upload --- src/boards/nRF52840_connect_kit/board.h | 71 +++++++++++++++++++++ src/boards/nRF52840_connect_kit/board.mk | 2 + src/boards/nRF52840_connect_kit/pinconfig.c | 19 ++++++ 3 files changed, 92 insertions(+) create mode 100644 src/boards/nRF52840_connect_kit/board.h create mode 100644 src/boards/nRF52840_connect_kit/board.mk create mode 100644 src/boards/nRF52840_connect_kit/pinconfig.c diff --git a/src/boards/nRF52840_connect_kit/board.h b/src/boards/nRF52840_connect_kit/board.h new file mode 100644 index 0000000..1181629 --- /dev/null +++ b/src/boards/nRF52840_connect_kit/board.h @@ -0,0 +1,71 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Yihui Xiong for Makerdiary + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef _MAKERDIARY_NRF82540_CONNECT_KIT_H_ +#define _MAKERDIARY_NRF82540_CONNECT_KIT_H_ + +#define _PINNUM(port, pin) ((port)*32 + (pin)) + +/*------------------------------------------------------------------*/ +/* LED + *------------------------------------------------------------------*/ +#define LEDS_NUMBER 1 +#define LED_PRIMARY_PIN _PINNUM(1, 15) // Green +#define LED_STATE_ON 0 + +#define LED_RGB_RED_PIN _PINNUM(1, 10) +#define LED_RGB_GREEN_PIN _PINNUM(1, 11) +#define LED_RGB_BLUE_PIN _PINNUM(1, 12) +#define BOARD_RGB_BRIGHTNESS 0x404040 +/*------------------------------------------------------------------*/ +/* BUTTON + *------------------------------------------------------------------*/ +#define BUTTONS_NUMBER 2 +#define BUTTON_1 _PINNUM(1, 0) // P1.00: User Button +#define BUTTON_2 _PINNUM(1, 7) // P1.07: NC +#define BUTTON_PULL NRF_GPIO_PIN_PULLUP + +//--------------------------------------------------------------------+ +// BLE OTA +//--------------------------------------------------------------------+ +#define BLEDIS_MANUFACTURER "Makerdiary" +#define BLEDIS_MODEL "nRF52840 Connect Kit" + +//--------------------------------------------------------------------+ +// USB +//--------------------------------------------------------------------+ +#define USB_DESC_VID 0x2886 +#define USB_DESC_UF2_PID 0xF00E +#define USB_DESC_CDC_ONLY_PID 0xF00E + +//--------------------------------------------------------------------+ +// UF2 +//--------------------------------------------------------------------+ +#define UF2_PRODUCT_NAME "nRF52840 Connect Kit" +#define UF2_VOLUME_LABEL "CONNECTKIT" +#define UF2_BOARD_ID "CONNECTKIT" +#define UF2_INDEX_URL "https://wiki.makerdiary.com/nrf52840-connectkit/" + + +#endif /* _MAKERDIARY_NRF82540_CONNECT_KIT_H_ */ diff --git a/src/boards/nRF52840_connect_kit/board.mk b/src/boards/nRF52840_connect_kit/board.mk new file mode 100644 index 0000000..bea74cc --- /dev/null +++ b/src/boards/nRF52840_connect_kit/board.mk @@ -0,0 +1,2 @@ +MCU_SUB_VARIANT = nrf52840 +USE_NFCT = yes diff --git a/src/boards/nRF52840_connect_kit/pinconfig.c b/src/boards/nRF52840_connect_kit/pinconfig.c new file mode 100644 index 0000000..a983e4a --- /dev/null +++ b/src/boards/nRF52840_connect_kit/pinconfig.c @@ -0,0 +1,19 @@ +#include "boards.h" +#include "uf2/configkeys.h" + +__attribute__((used, section(".bootloaderConfig"))) +const uint32_t bootloaderConfig[] = +{ + /* CF2 START */ + CFG_MAGIC0, CFG_MAGIC1, // magic + 5, 100, // used entries, total entries + + 204, 0x100000, // FLASH_BYTES = 0x100000 + 205, 0x40000, // RAM_BYTES = 0x40000 + 208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2 + 209, 0xada52840, // UF2_FAMILY = 0xada52840 + 210, 0x20, // PINS_PORT_SIZE = PA_32 + + 0, 0, 0, 0, 0, 0, 0, 0 + /* CF2 END */ +}; From ffa2379818448c66751898d03fb77616d54faea8 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 26 May 2023 13:10:49 +0700 Subject: [PATCH 11/90] add cmake support, starting with feather nrf52840 and pca10056. Seems to work well --- CMakeLists.txt | 304 ++++++++++++++++++ cmake/cpu/cortex-m33.cmake | 19 ++ cmake/cpu/cortex-m4.cmake | 23 ++ cmake/toolchain/arm_gcc.cmake | 46 +++ cmake/toolchain/set_flags.cmake | 17 + .../feather_nrf52840_express/board.cmake | 1 + src/boards/pca10056/board.cmake | 1 + 7 files changed, 411 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 cmake/cpu/cortex-m33.cmake create mode 100644 cmake/cpu/cortex-m4.cmake create mode 100644 cmake/toolchain/arm_gcc.cmake create mode 100644 cmake/toolchain/set_flags.cmake create mode 100644 src/boards/feather_nrf52840_express/board.cmake create mode 100644 src/boards/pca10056/board.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..d5b2369 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,304 @@ +cmake_minimum_required(VERSION 3.17) + +if (NOT DEFINED BOARD) + message(FATAL_ERROR "BOARD is not defined") +endif () + +if (NOT DEFINED TOOLCHAIN) + set(TOOLCHAIN gcc) +endif () + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/src/boards/${BOARD}/board.cmake) + +# toolchain set up +if (MCU_VARIANT STREQUAL "nrf5340_application") + set(CMAKE_SYSTEM_PROCESSOR cortex-m33 CACHE INTERNAL "System Processor") + set(JLINK_DEVICE nrf5340_xxaa_app) +else () + set(CMAKE_SYSTEM_PROCESSOR cortex-m4 CACHE INTERNAL "System Processor") + set(JLINK_DEVICE ${MCU_VARIANT}_xxaa) +endif () + +set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/cmake/toolchain/arm_${TOOLCHAIN}.cmake) + +project(Adafruit_nRF52_Bootloader C ASM) + +set(NRFX ${CMAKE_CURRENT_LIST_DIR}/lib/nrfx) +set(SDK11 ${CMAKE_CURRENT_LIST_DIR}/lib/sdk11/components) +set(SDK ${CMAKE_CURRENT_LIST_DIR}/lib/sdk/components) +set(SOFTDEVICE ${CMAKE_CURRENT_LIST_DIR}/lib/softdevice) +set(TUSB ${CMAKE_CURRENT_LIST_DIR}/lib/tinyusb/src) + +#------------------- +# Bootloader +#------------------- +set(CMAKE_EXECUTABLE_SUFFIX .elf) +add_executable(bootloader) +#set_target_properties(bootloader PROPERTIES OUTPUT_NAME "${BOARD}_bootloader.elf") + + +# SD_VERSION can be overwritten by board.cmake +if(NOT DEFINED SD_VERSION) + set(SD_VERSION 6.1.1) +endif () + +set(MBR_HEX ${SOFTDEVICE}/mbr/hex/mbr_nrf52_2.4.1_mbr.hex) + +target_sources(bootloader PUBLIC + # src + src/dfu_ble_svc.c + src/dfu_init.c + src/flash_nrf5x.c + src/main.c + src/boards/boards.c + # nrfx + ${NRFX}/drivers/src/nrfx_power.c + ${NRFX}/drivers/src/nrfx_nvmc.c + ${NRFX}/mdk/system_${MCU_VARIANT}.c + # sdk 11 + ${SDK11}/libraries/bootloader_dfu/bootloader.c + ${SDK11}/libraries/bootloader_dfu/bootloader_settings.c + ${SDK11}/libraries/bootloader_dfu/bootloader_util.c + ${SDK11}/libraries/bootloader_dfu/dfu_transport_serial.c + ${SDK11}/libraries/bootloader_dfu/dfu_transport_ble.c + ${SDK11}/libraries/bootloader_dfu/dfu_single_bank.c + ${SDK11}/ble/ble_services/ble_dfu/ble_dfu.c + ${SDK11}/ble/ble_services/ble_dis/ble_dis.c + ${SDK11}/drivers_nrf/pstorage/pstorage_raw.c + # latest sdk + ${SDK}/libraries/timer/app_timer.c + ${SDK}/libraries/scheduler/app_scheduler.c + ${SDK}/libraries/util/app_error.c + ${SDK}/libraries/util/app_util_platform.c + ${SDK}/libraries/crc16/crc16.c + ${SDK}/libraries/hci/hci_mem_pool.c + ${SDK}/libraries/hci/hci_slip.c + ${SDK}/libraries/hci/hci_transport.c + ${SDK}/libraries/util/nrf_assert.c + # ASM + ${NRFX}/mdk/gcc_startup_${MCU_VARIANT}.S + ) +target_include_directories(bootloader PUBLIC + src + src/boards + src/boards/${BOARD} + src/cmsis/include + src/usb + ${TUSB} + # nrfx + ${NRFX} + ${NRFX}/mdk + ${NRFX}/hal + ${NRFX}/drivers/include + ${NRFX}/drivers/src + # sdk 11 for cdc/ble dfu + ${SDK11}/libraries/bootloader_dfu + ${SDK11}/libraries/bootloader_dfu/hci_transport + ${SDK11}/drivers_nrf/pstorage + ${SDK11}/ble/common + ${SDK11}/ble/ble_services/ble_dfu + ${SDK11}/ble/ble_services/ble_dis + # later sdk with updated drivers + ${SDK}/libraries/timer + ${SDK}/libraries/scheduler + ${SDK}/libraries/crc16 + ${SDK}/libraries/util + ${SDK}/libraries/hci/config + ${SDK}/libraries/hci + ${SDK}/libraries/uart + ${SDK}/drivers_nrf/delay + # Softdevice + ${SOFTDEVICE}/mbr/headers + ) + +if (CMAKE_BUILD_TYPE STREQUAL "Debug") + # TODO not work yet, also need to add segger rtt, DFU_APP_DATA_RESERVED=0, BOOTLOADER_REGION_START=0xED000 + set(LD_FILE ${CMAKE_CURRENT_LIST_DIR}/linker/${MCU_VARIANT}_debug.ld) + message(FATAL_ERROR "Debug build not supported yet") +else () + set(LD_FILE ${CMAKE_CURRENT_LIST_DIR}/linker/${MCU_VARIANT}.ld) +endif () + +target_link_options(bootloader PUBLIC + "LINKER:--script=${LD_FILE}" + -L${NRFX}/mdk + --specs=nosys.specs + --specs=nano.specs + ) +target_compile_options(bootloader PUBLIC + -fno-builtin + -fshort-enums + -fstack-usage + -fno-strict-aliasing + -Wall + -Wextra + -Werror + -Wfatal-errors + -Werror-implicit-function-declaration + -Wfloat-equal + -Wundef + -Wshadow + -Wwrite-strings + -Wsign-compare + -Wmissing-format-attribute + -Wno-endif-labels + -Wunreachable-code + # Suppress warning caused by SDK + -Wno-unused-parameter -Wno-expansion-to-defined + ) +target_compile_definitions(bootloader PUBLIC + SOFTDEVICE_PRESENT + DFU_APP_DATA_RESERVED=7*4096 + ) + +if (TRACE_ETM STREQUAL "1") + # ENABLE_TRACE will cause system_nrf5x.c to set up ETM trace + target_compile_definitions(bootloader PUBLIC ENABLE_TRACE) +endif () + +if (MCU_VARIANT STREQUAL "nrf52") + # UART transport + target_sources(bootloader PUBLIC + ${SDK}/libraries/uart/app_uart.c + ${SDK}/drivers_nrf/uart/nrf_drv_uart.c + ${SDK}/drivers_nrf/common/nrf_drv_common.c + ) + target_include_directories(bootloader PUBLIC + ${SDK11}/libraries/util + ${SDK}/drivers_nrf/common + ${SDK}/drivers_nrf/uart + ) +else () + # USB transport + target_sources(bootloader PUBLIC + src/boards/${BOARD}/pinconfig.c + src/usb/msc_uf2.c + src/usb/usb.c + src/usb/usb_desc.c + src/usb/uf2/ghostfat.c + # TinyUSB + ${TUSB}/portable/nordic/nrf5x/dcd_nrf5x.c + ${TUSB}/common/tusb_fifo.c + ${TUSB}/device/usbd.c + ${TUSB}/device/usbd_control.c + ${TUSB}/class/cdc/cdc_device.c + ${TUSB}/class/msc/msc_device.c + ${TUSB}/tusb.c + ) +endif () + +#---------------------------------------------------- +# MCU Variant differences +# Supported are: nrf52 (nrf52832), nrf52833, nrf52840 +#---------------------------------------------------- +if (MCU_VARIANT STREQUAL "nrf52") + set(SD_NAME s132) + set(DFU_DEV_REV 0xADAF) + target_compile_definitions(bootloader PUBLIC + NRF52 + NRF52832_XXAA + S132 + ) + target_include_directories(bootloader PUBLIC + ${SOFTDEVICE}/s132_nrf52_6.1.1/s132_nrf52_6.1.1_API/include + ) + +elseif (MCU_VARIANT STREQUAL "nrf52833") + set(SD_NAME s140) + set(DFU_DEV_REV 52833) + target_compile_definitions(bootloader PUBLIC + NRF52833_XXAA + S140 + ) + target_include_directories(bootloader PUBLIC + ${SOFTDEVICE}/s140_nrf52_6.1.1/s140_nrf52_6.1.1_API/include + ) + +elseif (MCU_VARIANT STREQUAL "nrf52840") + set(SD_NAME s140) + set(DFU_DEV_REV 52840) + target_compile_definitions(bootloader PUBLIC + NRF52840_XXAA + S140 + ) + target_include_directories(bootloader PUBLIC + ${SOFTDEVICE}/s140_nrf52_6.1.1/s140_nrf52_6.1.1_API/include + ) + +else () + message(FATAL_ERROR "MCU_VARIANT ${MCU_VARIANT} is unknown") +endif () + +set(SD_FILENAME ${SD_NAME}_nrf52_${SD_VERSION}) +set(SD_HEX ${SOFTDEVICE}/${SD_FILENAME}/${SD_FILENAME}_softdevice.hex) + +#---------------------------------- +# Get UF2 version from git +#---------------------------------- +execute_process(COMMAND git describe --dirty --always --tags OUTPUT_VARIABLE GIT_VERSION) +string(STRIP ${GIT_VERSION} GIT_VERSION) + +execute_process(COMMAND bash "-c" "git submodule status | cut -d\" \" -f3,4 | paste -s -d\" \" -" + OUTPUT_VARIABLE GIT_SUBMODULE_VERSIONS + ) +string(STRIP ${GIT_SUBMODULE_VERSIONS} GIT_SUBMODULE_VERSIONS) +string(REPLACE ../ "" GIT_SUBMODULE_VERSIONS ${GIT_SUBMODULE_VERSIONS}) +string(REPLACE lib/ "" GIT_SUBMODULE_VERSIONS ${GIT_SUBMODULE_VERSIONS}) + +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}") + +cmake_print_variables(GIT_VERSION GIT_SUBMODULE_VERSIONS MK_BOOTLOADER_VERSION) + +target_compile_definitions(bootloader PUBLIC + UF2_VERSION="${GIT_VERSION} - ${GIT_SUBMODULE_VERSIONS}" + BLEDIS_FW_VERSION="${GIT_VERSION} ${SD_NAME} ${SD_VERSION}" + MK_BOOTLOADER_VERSION=${MK_BOOTLOADER_VERSION} + ) + + +#---------------------------------- +# Post build +#---------------------------------- + +# run size after build +add_custom_command(TARGET bootloader POST_BUILD + COMMAND ${CMAKE_SIZE} $ + ) + +# Add bin/hex output +add_custom_command(TARGET bootloader POST_BUILD + COMMAND ${CMAKE_OBJCOPY} -Obinary $ $/bootloader.bin + COMMAND ${CMAKE_OBJCOPY} -Oihex $ $/bootloader.hex + VERBATIM) + +#---------------------------------- +# Flashing target +#---------------------------------- + +if (NOT DEFINED NRFJPROG) + set(NRFJPROG nrfjprog) +endif() + +add_custom_target(flash + DEPENDS bootloader + COMMAND ${NRFJPROG} --program $ --verify --sectoranduicrerase -f nrf52 --reset + ) + +add_custom_target(flash-sd + COMMAND ${NRFJPROG} --program ${SD_HEX} --verify --sectorerase -f nrf52 --reset + ) + +add_custom_target(flash-mbr + COMMAND ${NRFJPROG} --program ${MBR_HEX} --verify --sectorerase -f nrf52 --reset + ) + +add_custom_target(flash-erase + COMMAND ${NRFJPROG} -f nrf52 --eraseall + ) \ No newline at end of file diff --git a/cmake/cpu/cortex-m33.cmake b/cmake/cpu/cortex-m33.cmake new file mode 100644 index 0000000..a028cd4 --- /dev/null +++ b/cmake/cpu/cortex-m33.cmake @@ -0,0 +1,19 @@ +if (TOOLCHAIN STREQUAL "gcc") + set(TOOLCHAIN_COMMON_FLAGS + -mthumb + -mcpu=cortex-m33 + -mfloat-abi=hard + -mfpu=fpv5-sp-d16 + ) + + set(FREERTOS_PORT GCC_ARM_CM33_NTZ_NONSECURE CACHE INTERNAL "") + +elseif (TOOLCHAIN STREQUAL "iar") + set(TOOLCHAIN_COMMON_FLAGS + --cpu cortex-m33 + --fpu VFPv5-SP + ) + + set(FREERTOS_PORT IAR_ARM_CM4F CACHE INTERNAL "") + +endif () diff --git a/cmake/cpu/cortex-m4.cmake b/cmake/cpu/cortex-m4.cmake new file mode 100644 index 0000000..79f97e2 --- /dev/null +++ b/cmake/cpu/cortex-m4.cmake @@ -0,0 +1,23 @@ +if (TOOLCHAIN STREQUAL "gcc") + set(TOOLCHAIN_COMMON_FLAGS + -mthumb + -mcpu=cortex-m4 + -mfloat-abi=hard + -mfpu=fpv4-sp-d16 + ) + + if (NOT DEFINED FREERTOS_PORT) + set(FREERTOS_PORT GCC_ARM_CM4F CACHE INTERNAL "") + endif () + +elseif (TOOLCHAIN STREQUAL "iar") + set(TOOLCHAIN_COMMON_FLAGS + --cpu cortex-m4 + --fpu VFPv4 + ) + + if (NOT DEFINED FREERTOS_PORT) + set(FREERTOS_PORT IAR_ARM_CM4F CACHE INTERNAL "") + endif () + +endif () diff --git a/cmake/toolchain/arm_gcc.cmake b/cmake/toolchain/arm_gcc.cmake new file mode 100644 index 0000000..5203d1e --- /dev/null +++ b/cmake/toolchain/arm_gcc.cmake @@ -0,0 +1,46 @@ +set(CMAKE_SYSTEM_NAME Generic) + +set(CMAKE_C_COMPILER "arm-none-eabi-gcc") +set(CMAKE_CXX_COMPILER "arm-none-eabi-g++") +set(CMAKE_ASM_COMPILER "arm-none-eabi-gcc") + +set(CMAKE_SIZE "arm-none-eabi-size" CACHE FILEPATH "") +set(CMAKE_OBJCOPY "arm-none-eabi-objcopy" CACHE FILEPATH "") +set(CMAKE_OBJDUMP "arm-none-eabi-objdump" CACHE FILEPATH "") + +set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE) + +# Look for includes and libraries only in the target system prefix. +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + +# pass TOOLCHAIN_CPU to +set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES CMAKE_SYSTEM_PROCESSOR) + +include(${CMAKE_CURRENT_LIST_DIR}/../cpu/${CMAKE_SYSTEM_PROCESSOR}.cmake) + +# enable all possible warnings for building examples +list(APPEND TOOLCHAIN_COMMON_FLAGS + -fdata-sections + -ffunction-sections + -fsingle-precision-constant + -fno-strict-aliasing + ) + +set(TOOLCHAIN_EXE_LINKER_FLAGS + -Wl,--print-memory-usage + -Wl,--gc-sections + #-Wl,--cref + ) + +include(${CMAKE_CURRENT_LIST_DIR}/set_flags.cmake) + +# try_compile is cmake test compiling its own example, +# pass -nostdlib to skip stdlib linking +get_property(IS_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE) +if (IS_IN_TRY_COMPILE) + set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -nostdlib") + set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -nostdlib") +endif () diff --git a/cmake/toolchain/set_flags.cmake b/cmake/toolchain/set_flags.cmake new file mode 100644 index 0000000..bbbd211 --- /dev/null +++ b/cmake/toolchain/set_flags.cmake @@ -0,0 +1,17 @@ +include(CMakePrintHelpers) + +# join the toolchain flags into a single string +list(JOIN TOOLCHAIN_COMMON_FLAGS " " TOOLCHAIN_COMMON_FLAGS) + +foreach (LANG IN ITEMS C CXX ASM) + set(CMAKE_${LANG}_FLAGS_INIT ${TOOLCHAIN_COMMON_FLAGS}) + + #cmake_print_variables(CMAKE_${LANG}_FLAGS_INIT) + + # optimization flags for LOG, LOGGER ? + #set(CMAKE_${LANG}_FLAGS_RELEASE_INIT "-Os") + #set(CMAKE_${LANG}_FLAGS_DEBUG_INIT "-O0") +endforeach () + +# Linker +list(JOIN TOOLCHAIN_EXE_LINKER_FLAGS " " CMAKE_EXE_LINKER_FLAGS_INIT) diff --git a/src/boards/feather_nrf52840_express/board.cmake b/src/boards/feather_nrf52840_express/board.cmake new file mode 100644 index 0000000..2715f36 --- /dev/null +++ b/src/boards/feather_nrf52840_express/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/pca10056/board.cmake b/src/boards/pca10056/board.cmake new file mode 100644 index 0000000..2715f36 --- /dev/null +++ b/src/boards/pca10056/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) From dbc7648649b183883226da7d8d83c5ba3678ecbd Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 20 Jul 2023 21:08:19 +0700 Subject: [PATCH 12/90] add linker --print-memory-usage --- Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 323a702..fb1f521 100644 --- a/Makefile +++ b/Makefile @@ -28,9 +28,9 @@ MBR_HEX = lib/softdevice/mbr/hex/mbr_nrf52_2.4.1_mbr.hex # linker by MCU eg. nrf52840.ld ifeq ($(DEBUG), 1) - LD_FILE = linker/$(MCU_SUB_VARIANT)_debug.ld + LD_FILE = linker/$(MCU_SUB_VARIANT)_debug.ld else - LD_FILE = linker/$(MCU_SUB_VARIANT).ld + LD_FILE = linker/$(MCU_SUB_VARIANT).ld endif GIT_VERSION := $(shell git describe --dirty --always --tags) @@ -123,6 +123,7 @@ else ifeq ($(MCU_SUB_VARIANT),nrf52840) SD_NAME = s140 DFU_DEV_REV = 52840 CFLAGS += -DNRF52840_XXAA -DS140 + # App reserved 40KB to match circuitpython for 840 DFU_APP_DATA_RESERVED=10*4096 else $(error Sub Variant $(MCU_SUB_VARIANT) is unknown) @@ -349,6 +350,7 @@ endif LDFLAGS += \ $(CFLAGS) \ -Wl,-L,linker -Wl,-T,$(LD_FILE) \ + -Wl,--print-memory-usage \ -Wl,-Map=$@.map -Wl,-cref -Wl,-gc-sections \ -specs=nosys.specs -specs=nano.specs From 2de2fbf82f8ab5e1e422da0c1f2a18ddaf8fc753 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 20 Jul 2023 22:06:28 +0700 Subject: [PATCH 13/90] add PR template --- .github/PULL_REQUEST_TEMPLATE.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..6953d76 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,18 @@ +## Checklist + +*By completing this PR sufficiently, you help us to review this Pull Request quicker and also help improve the quality of Release Notes* + +- [ ] Please provide specific title of the PR describing the change +- [ ] Please provide related links (*eg. Issue which will be closed by this Pull Request*) +- [ ] If you are adding an new boards, please make sure + - [ ] Provide link to your allocated VID/PID if applicable + - [ ] Add your board to [action ci](/.github/workflows) in correct workflow and alphabet order for release binary + - [ ] `UF2_BOARD_ID` in your board.h follow correct format from [uf2 specs](https://github.com/microsoft/uf2#files-exposed-by-bootloaders) + +*This checklist items that are not applicable to your PR can be deleted.* + +----------- + +## Description of Change + +Please describe your proposed Pull Request and it's impact. From c87ea51b86b96f9b19458abfc6b37d4cb52e160b Mon Sep 17 00:00:00 2001 From: Mark Trevor Birss Date: Thu, 20 Jul 2023 17:28:03 +0200 Subject: [PATCH 14/90] Update board.h changes requested to board-id --- src/boards/nRF52840_connect_kit/board.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boards/nRF52840_connect_kit/board.h b/src/boards/nRF52840_connect_kit/board.h index 1181629..9661e30 100644 --- a/src/boards/nRF52840_connect_kit/board.h +++ b/src/boards/nRF52840_connect_kit/board.h @@ -64,7 +64,7 @@ //--------------------------------------------------------------------+ #define UF2_PRODUCT_NAME "nRF52840 Connect Kit" #define UF2_VOLUME_LABEL "CONNECTKIT" -#define UF2_BOARD_ID "CONNECTKIT" +#define UF2_BOARD_ID "nRF52840-Connect-Kit" #define UF2_INDEX_URL "https://wiki.makerdiary.com/nrf52840-connectkit/" From 386ed04058473d7104240f68e59312df335c94ac Mon Sep 17 00:00:00 2001 From: Mark Trevor Birss Date: Fri, 21 Jul 2023 10:37:04 +0200 Subject: [PATCH 15/90] Update githubci.yml add Makerdiary nrf52840 connectkit --- .github/workflows/githubci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/githubci.yml b/.github/workflows/githubci.yml index ad77865..dfd20f6 100644 --- a/.github/workflows/githubci.yml +++ b/.github/workflows/githubci.yml @@ -45,6 +45,7 @@ jobs: - 'mikoto' - 'nice_nano' - 'nrf52840_bboard' + - 'nrf52840-connectkit' - 'nrf52840_m2' - 'ohs2020_badge' - 'particle_argon' From 39da39544b46fa1ee9bd07a20690c3e61e08f5b0 Mon Sep 17 00:00:00 2001 From: Mark Trevor Birss Date: Fri, 21 Jul 2023 12:58:07 +0200 Subject: [PATCH 16/90] Update githubci.yml --- .github/workflows/githubci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/githubci.yml b/.github/workflows/githubci.yml index dfd20f6..a6bb95e 100644 --- a/.github/workflows/githubci.yml +++ b/.github/workflows/githubci.yml @@ -45,7 +45,7 @@ jobs: - 'mikoto' - 'nice_nano' - 'nrf52840_bboard' - - 'nrf52840-connectkit' + - 'nRF52840_connect_kit' - 'nrf52840_m2' - 'ohs2020_badge' - 'particle_argon' From 8b8c9d58bebfe0c740bb04299e6ca185fb8d410d Mon Sep 17 00:00:00 2001 From: Mark Trevor Birss Date: Tue, 1 Aug 2023 15:44:15 +0200 Subject: [PATCH 17/90] Update board.h --- src/boards/nRF52840_connect_kit/board.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/boards/nRF52840_connect_kit/board.h b/src/boards/nRF52840_connect_kit/board.h index 9661e30..3740928 100644 --- a/src/boards/nRF52840_connect_kit/board.h +++ b/src/boards/nRF52840_connect_kit/board.h @@ -56,8 +56,8 @@ // USB //--------------------------------------------------------------------+ #define USB_DESC_VID 0x2886 -#define USB_DESC_UF2_PID 0xF00E -#define USB_DESC_CDC_ONLY_PID 0xF00E +#define USB_DESC_UF2_PID 0xF00F +#define USB_DESC_CDC_ONLY_PID 0xF00F //--------------------------------------------------------------------+ // UF2 From 36a1f428ddaa4faf89951972d462483c97687d28 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 3 Jan 2024 22:10:22 +0700 Subject: [PATCH 18/90] add feather nrf52840 tft --- src/boards/feather_nrf52840_tft/board.cmake | 1 + src/boards/feather_nrf52840_tft/board.h | 69 +++++++++++++++++++++ src/boards/feather_nrf52840_tft/board.mk | 1 + src/boards/feather_nrf52840_tft/pinconfig.c | 19 ++++++ 4 files changed, 90 insertions(+) create mode 100644 src/boards/feather_nrf52840_tft/board.cmake create mode 100644 src/boards/feather_nrf52840_tft/board.h create mode 100644 src/boards/feather_nrf52840_tft/board.mk create mode 100644 src/boards/feather_nrf52840_tft/pinconfig.c diff --git a/src/boards/feather_nrf52840_tft/board.cmake b/src/boards/feather_nrf52840_tft/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/feather_nrf52840_tft/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/feather_nrf52840_tft/board.h b/src/boards/feather_nrf52840_tft/board.h new file mode 100644 index 0000000..29ac9f9 --- /dev/null +++ b/src/boards/feather_nrf52840_tft/board.h @@ -0,0 +1,69 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018 Ha Thach for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef _FEATHER_NRF52840_TFT_H +#define _FEATHER_NRF52840_TFT_H + +#define _PINNUM(port, pin) ((port)*32 + (pin)) + +/*------------------------------------------------------------------*/ +/* LED + *------------------------------------------------------------------*/ +#define LEDS_NUMBER 1 +#define LED_PRIMARY_PIN _PINNUM(0, 11) +#define LED_STATE_ON 1 + +#define LED_NEOPIXEL _PINNUM(1, 8) +#define NEOPIXEL_POWER_PIN _PINNUM(1, 2) +#define NEOPIXELS_NUMBER 1 +#define BOARD_RGB_BRIGHTNESS 0x040404 + +/*------------------------------------------------------------------*/ +/* BUTTON + *------------------------------------------------------------------*/ +#define BUTTONS_NUMBER 2 +#define BUTTON_1 _PINNUM(1, 6) +#define BUTTON_2 _PINNUM(1, 4) +#define BUTTON_PULL NRF_GPIO_PIN_PULLUP + +//--------------------------------------------------------------------+ +// BLE OTA +//--------------------------------------------------------------------+ +#define BLEDIS_MANUFACTURER "Adafruit Industries" +#define BLEDIS_MODEL "Feather nRF52840 TFT" + +//--------------------------------------------------------------------+ +// USB +//--------------------------------------------------------------------+ +#define USB_DESC_VID 0x239A +#define USB_DESC_UF2_PID 0x0029 +#define USB_DESC_CDC_ONLY_PID 0x002A + +//------------- UF2 -------------// +#define UF2_PRODUCT_NAME "Adafruit Feather nRF52840 TFT" +#define UF2_VOLUME_LABEL "FTHR840BOOT" +#define UF2_BOARD_ID "nRF52840-FeatherTFT-revA" +#define UF2_INDEX_URL "https://www.adafruit.com/product/" + +#endif diff --git a/src/boards/feather_nrf52840_tft/board.mk b/src/boards/feather_nrf52840_tft/board.mk new file mode 100644 index 0000000..9d29ac6 --- /dev/null +++ b/src/boards/feather_nrf52840_tft/board.mk @@ -0,0 +1 @@ +MCU_SUB_VARIANT = nrf52840 diff --git a/src/boards/feather_nrf52840_tft/pinconfig.c b/src/boards/feather_nrf52840_tft/pinconfig.c new file mode 100644 index 0000000..a983e4a --- /dev/null +++ b/src/boards/feather_nrf52840_tft/pinconfig.c @@ -0,0 +1,19 @@ +#include "boards.h" +#include "uf2/configkeys.h" + +__attribute__((used, section(".bootloaderConfig"))) +const uint32_t bootloaderConfig[] = +{ + /* CF2 START */ + CFG_MAGIC0, CFG_MAGIC1, // magic + 5, 100, // used entries, total entries + + 204, 0x100000, // FLASH_BYTES = 0x100000 + 205, 0x40000, // RAM_BYTES = 0x40000 + 208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2 + 209, 0xada52840, // UF2_FAMILY = 0xada52840 + 210, 0x20, // PINS_PORT_SIZE = PA_32 + + 0, 0, 0, 0, 0, 0, 0, 0 + /* CF2 END */ +}; From 66db5aeda34f9d1351a10d952a37a3bfa90fbce7 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 3 Jan 2024 22:11:00 +0700 Subject: [PATCH 19/90] add support for NEOPIXEL_POWER_PIN, also change code style --- src/boards/boards.c | 346 +++++++++++------------- src/boards/feather_nrf52840_tft/board.h | 2 +- src/main.c | 171 +++++------- 3 files changed, 224 insertions(+), 295 deletions(-) diff --git a/src/boards/boards.c b/src/boards/boards.c index de95950..8b4583f 100644 --- a/src/boards/boards.c +++ b/src/boards/boards.c @@ -38,35 +38,29 @@ #define SCHED_QUEUE_SIZE 30 /**< Maximum number of events in the scheduler queue. */ #if defined(LED_NEOPIXEL) || defined(LED_RGB_RED_PIN) || defined(LED_APA102) - void neopixel_init(void); - void neopixel_write(uint8_t *pixels); - void neopixel_teardown(void); +void neopixel_init(void); +void neopixel_write(uint8_t* pixels); +void neopixel_teardown(void); #endif //------------- IMPLEMENTATION -------------// -void button_init(uint32_t pin) -{ - if ( BUTTON_PULL == NRF_GPIO_PIN_PULLDOWN ) - { +void button_init(uint32_t pin) { + if (BUTTON_PULL == NRF_GPIO_PIN_PULLDOWN) { nrf_gpio_cfg_sense_input(pin, BUTTON_PULL, NRF_GPIO_PIN_SENSE_HIGH); - } - else - { + } else { nrf_gpio_cfg_sense_input(pin, BUTTON_PULL, NRF_GPIO_PIN_SENSE_LOW); } } -bool button_pressed(uint32_t pin) -{ +bool button_pressed(uint32_t pin) { uint32_t const active_state = (BUTTON_PULL == NRF_GPIO_PIN_PULLDOWN ? 1 : 0); return nrf_gpio_pin_read(pin) == active_state; } // This is declared so that a board specific init can be called from here. -void __attribute__((weak)) board_init2(void) { } +void __attribute__((weak)) board_init2(void) {} -void board_init(void) -{ +void board_init(void) { // stop LF clock just in case we jump from application without reset NRF_CLOCK->TASKS_LFCLKSTOP = 1UL; @@ -85,8 +79,14 @@ void board_init(void) led_pwm_init(LED_SECONDARY, LED_SECONDARY_PIN); #endif #endif - // use neopixel for use enumeration + #if defined(LED_NEOPIXEL) || defined(LED_RGB_RED_PIN) || defined(LED_APA102) + // use neopixel for use enumeration + #ifdef NEOPIXEL_POWER_PIN + nrf_gpio_cfg_output(NEOPIXEL_POWER_PIN); + nrf_gpio_pin_write(NEOPIXEL_POWER_PIN, 1); + #endif + neopixel_init(); #endif @@ -99,23 +99,21 @@ void board_init(void) // Make sure any custom inits are performed board_init2(); -// When board is supplied on VDDH (and not VDD), this specifies what voltage the GPIO should run at -// and what voltage is output at VDD. The default (0xffffffff) is 1.8V; typically you'll want -// #define UICR_REGOUT0_VALUE UICR_REGOUT0_VOUT_3V3 -// in board.h when using that power configuration. + // When board is supplied on VDDH (and not VDD), this specifies what voltage the GPIO should run at + // and what voltage is output at VDD. The default (0xffffffff) is 1.8V; typically you'll want + // #define UICR_REGOUT0_VALUE UICR_REGOUT0_VOUT_3V3 + // in board.h when using that power configuration. #ifdef UICR_REGOUT0_VALUE - if ((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) != - (UICR_REGOUT0_VALUE << UICR_REGOUT0_VOUT_Pos)) - { - NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos; - while (NRF_NVMC->READY == NVMC_READY_READY_Busy){} - NRF_UICR->REGOUT0 = (NRF_UICR->REGOUT0 & ~((uint32_t)UICR_REGOUT0_VOUT_Msk)) | - (UICR_REGOUT0_VALUE << UICR_REGOUT0_VOUT_Pos); + if ((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) != (UICR_REGOUT0_VALUE << UICR_REGOUT0_VOUT_Pos)){ + NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos; + while (NRF_NVMC->READY == NVMC_READY_READY_Busy){} + NRF_UICR->REGOUT0 = (NRF_UICR->REGOUT0 & ~((uint32_t)UICR_REGOUT0_VOUT_Msk)) | + (UICR_REGOUT0_VALUE << UICR_REGOUT0_VOUT_Pos); - NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos; - while (NRF_NVMC->READY == NVMC_READY_READY_Busy){} + NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos; + while (NRF_NVMC->READY == NVMC_READY_READY_Busy){} - NVIC_SystemReset(); + NVIC_SystemReset(); } #endif @@ -127,14 +125,13 @@ void board_init(void) // Configure Systick for led blinky NVIC_SetPriority(SysTick_IRQn, 7); - SysTick_Config(SystemCoreClock/1000); + SysTick_Config(SystemCoreClock / 1000); } // Actions at the end of board_teardown. -void __attribute__((weak)) board_teardown2(void) { } +void __attribute__((weak)) board_teardown2(void) {} -void board_teardown(void) -{ +void board_teardown(void) { // Disable systick, turn off LEDs SysTick->CTRL = 0; @@ -149,9 +146,9 @@ void board_teardown(void) // Stop RTC1 used by app_timer NVIC_DisableIRQ(RTC1_IRQn); - NRF_RTC1->EVTENCLR = RTC_EVTEN_COMPARE0_Msk; - NRF_RTC1->INTENCLR = RTC_INTENSET_COMPARE0_Msk; - NRF_RTC1->TASKS_STOP = 1; + NRF_RTC1->EVTENCLR = RTC_EVTEN_COMPARE0_Msk; + NRF_RTC1->INTENCLR = RTC_INTENSET_COMPARE0_Msk; + NRF_RTC1->TASKS_STOP = 1; NRF_RTC1->TASKS_CLEAR = 1; // Stop LF clock @@ -159,8 +156,7 @@ void board_teardown(void) // make sure all pins are back in reset state // NUMBER_OF_PINS is defined in nrf_gpio.h - for (int i = 0; i < NUMBER_OF_PINS; ++i) - { + for (int i = 0; i < NUMBER_OF_PINS; ++i) { nrf_gpio_cfg_default(i); } @@ -169,42 +165,38 @@ void board_teardown(void) } static uint32_t _systick_count = 0; -void SysTick_Handler(void) -{ - _systick_count++; +void SysTick_Handler(void) { + _systick_count++; led_tick(); } - -void pwm_teardown(NRF_PWM_Type* pwm ) -{ +void pwm_teardown(NRF_PWM_Type* pwm) { pwm->TASKS_SEQSTART[0] = 0; - pwm->ENABLE = 0; + pwm->ENABLE = 0; pwm->PSEL.OUT[0] = 0xFFFFFFFF; pwm->PSEL.OUT[1] = 0xFFFFFFFF; pwm->PSEL.OUT[2] = 0xFFFFFFFF; pwm->PSEL.OUT[3] = 0xFFFFFFFF; - pwm->MODE = 0; - pwm->COUNTERTOP = 0x3FF; - pwm->PRESCALER = 0; - pwm->DECODER = 0; - pwm->LOOP = 0; - pwm->SEQ[0].PTR = 0; - pwm->SEQ[0].CNT = 0; + pwm->MODE = 0; + pwm->COUNTERTOP = 0x3FF; + pwm->PRESCALER = 0; + pwm->DECODER = 0; + pwm->LOOP = 0; + pwm->SEQ[0].PTR = 0; + pwm->SEQ[0].CNT = 0; } -static uint16_t led_duty_cycles[PWM0_CH_NUM] = { 0 }; +static uint16_t led_duty_cycles[PWM0_CH_NUM] = {0}; #if LEDS_NUMBER > PWM0_CH_NUM #error "Only " PWM0_CH_NUM " concurrent status LEDs are supported." #endif -void led_pwm_init(uint32_t led_index, uint32_t led_pin) -{ - NRF_PWM_Type* pwm = NRF_PWM0; +void led_pwm_init(uint32_t led_index, uint32_t led_pin) { + NRF_PWM_Type* pwm = NRF_PWM0; pwm->ENABLE = 0; @@ -213,15 +205,15 @@ void led_pwm_init(uint32_t led_index, uint32_t led_pin) pwm->PSEL.OUT[led_index] = led_pin; - pwm->MODE = PWM_MODE_UPDOWN_Up; - pwm->COUNTERTOP = 0xff; - pwm->PRESCALER = PWM_PRESCALER_PRESCALER_DIV_16; - pwm->DECODER = PWM_DECODER_LOAD_Individual; - pwm->LOOP = 0; + pwm->MODE = PWM_MODE_UPDOWN_Up; + pwm->COUNTERTOP = 0xff; + pwm->PRESCALER = PWM_PRESCALER_PRESCALER_DIV_16; + pwm->DECODER = PWM_DECODER_LOAD_Individual; + pwm->LOOP = 0; - pwm->SEQ[0].PTR = (uint32_t) (led_duty_cycles); - pwm->SEQ[0].CNT = 4; // default mode is Individual --> count must be 4 - pwm->SEQ[0].REFRESH = 0; + pwm->SEQ[0].PTR = (uint32_t) (led_duty_cycles); + pwm->SEQ[0].CNT = 4; // default mode is Individual --> count must be 4 + pwm->SEQ[0].REFRESH = 0; pwm->SEQ[0].ENDDELAY = 0; pwm->ENABLE = 1; @@ -230,13 +222,11 @@ void led_pwm_init(uint32_t led_index, uint32_t led_pin) // pwm->TASKS_SEQSTART[0] = 1; } -void led_pwm_teardown(void) -{ +void led_pwm_teardown(void) { pwm_teardown(NRF_PWM0); } -void led_pwm_duty_cycle(uint32_t led_index, uint16_t duty_cycle) -{ +void led_pwm_duty_cycle(uint32_t led_index, uint16_t duty_cycle) { led_duty_cycles[led_index] = duty_cycle; nrf_pwm_event_clear(NRF_PWM0, NRF_PWM_EVENT_SEQEND0); nrf_pwm_task_trigger(NRF_PWM0, NRF_PWM_TASK_SEQSTART0); @@ -246,102 +236,103 @@ static uint32_t primary_cycle_length; #ifdef LED_SECONDARY_PIN static uint32_t secondary_cycle_length; #endif + void led_tick() { - uint32_t millis = _systick_count; + uint32_t millis = _systick_count; - uint32_t cycle = millis % primary_cycle_length; - uint32_t half_cycle = primary_cycle_length / 2; - if (cycle > half_cycle) { - cycle = primary_cycle_length - cycle; - } - uint16_t duty_cycle = 0x4f * cycle / half_cycle; - #if LED_STATE_ON == 1 - duty_cycle = 0xff - duty_cycle; - #endif - led_pwm_duty_cycle(LED_PRIMARY, duty_cycle); + uint32_t cycle = millis % primary_cycle_length; + uint32_t half_cycle = primary_cycle_length / 2; + if (cycle > half_cycle) { + cycle = primary_cycle_length - cycle; + } + uint16_t duty_cycle = 0x4f * cycle / half_cycle; + #if LED_STATE_ON == 1 + duty_cycle = 0xff - duty_cycle; + #endif + led_pwm_duty_cycle(LED_PRIMARY, duty_cycle); - #ifdef LED_SECONDARY_PIN - cycle = millis % secondary_cycle_length; - half_cycle = secondary_cycle_length / 2; - if (cycle > half_cycle) { - cycle = secondary_cycle_length - cycle; - } - duty_cycle = 0x8f * cycle / half_cycle; - #if LED_STATE_ON == 1 - duty_cycle = 0xff - duty_cycle; - #endif - led_pwm_duty_cycle(LED_SECONDARY, duty_cycle); - #endif + #ifdef LED_SECONDARY_PIN + cycle = millis % secondary_cycle_length; + half_cycle = secondary_cycle_length / 2; + if (cycle > half_cycle) { + cycle = secondary_cycle_length - cycle; + } + duty_cycle = 0x8f * cycle / half_cycle; + #if LED_STATE_ON == 1 + duty_cycle = 0xff - duty_cycle; + #endif + led_pwm_duty_cycle(LED_SECONDARY, duty_cycle); + #endif } static uint32_t rgb_color; static bool temp_color_active = false; -void led_state(uint32_t state) -{ - uint32_t new_rgb_color = rgb_color; - uint32_t temp_color = 0; - switch (state) { - case STATE_USB_MOUNTED: - new_rgb_color = 0x00ff00; - primary_cycle_length = 3000; - break; - case STATE_BOOTLOADER_STARTED: - case STATE_USB_UNMOUNTED: - new_rgb_color = 0xff0000; - primary_cycle_length = 300; - break; +void led_state(uint32_t state) { + uint32_t new_rgb_color = rgb_color; + uint32_t temp_color = 0; + switch (state) { + case STATE_USB_MOUNTED: + new_rgb_color = 0x00ff00; + primary_cycle_length = 3000; + break; - case STATE_WRITING_STARTED: - temp_color = 0xff0000; - primary_cycle_length = 100; - break; + case STATE_BOOTLOADER_STARTED: + case STATE_USB_UNMOUNTED: + new_rgb_color = 0xff0000; + primary_cycle_length = 300; + break; - case STATE_WRITING_FINISHED: - // Empty means to unset any temp colors. - primary_cycle_length = 3000; - break; + case STATE_WRITING_STARTED: + temp_color = 0xff0000; + primary_cycle_length = 100; + break; - case STATE_BLE_CONNECTED: - new_rgb_color = 0x0000ff; - #ifdef LED_SECONDARY_PIN - secondary_cycle_length = 3000; - #else - primary_cycle_length = 3000; - #endif - break; + case STATE_WRITING_FINISHED: + // Empty means to unset any temp colors. + primary_cycle_length = 3000; + break; - case STATE_BLE_DISCONNECTED: - new_rgb_color = 0xff00ff; - #ifdef LED_SECONDARY_PIN - secondary_cycle_length = 300; - #else - primary_cycle_length = 300; - #endif - break; + case STATE_BLE_CONNECTED: + new_rgb_color = 0x0000ff; + #ifdef LED_SECONDARY_PIN + secondary_cycle_length = 3000; + #else + primary_cycle_length = 3000; + #endif + break; - default: - break; - } - uint8_t* final_color = NULL; - new_rgb_color &= BOARD_RGB_BRIGHTNESS; - if (temp_color != 0){ - temp_color &= BOARD_RGB_BRIGHTNESS; - final_color = (uint8_t*)&temp_color; - temp_color_active = true; - } else if (new_rgb_color != rgb_color) { - final_color = (uint8_t*)&new_rgb_color; - rgb_color = new_rgb_color; - } else if (temp_color_active) { - final_color = (uint8_t*)&rgb_color; - } + case STATE_BLE_DISCONNECTED: + new_rgb_color = 0xff00ff; + #ifdef LED_SECONDARY_PIN + secondary_cycle_length = 300; + #else + primary_cycle_length = 300; + #endif + break; + + default: + break; + } + uint8_t* final_color = NULL; + new_rgb_color &= BOARD_RGB_BRIGHTNESS; + if (temp_color != 0) { + temp_color &= BOARD_RGB_BRIGHTNESS; + final_color = (uint8_t*) &temp_color; + temp_color_active = true; + } else if (new_rgb_color != rgb_color) { + final_color = (uint8_t*) &new_rgb_color; + rgb_color = new_rgb_color; + } else if (temp_color_active) { + final_color = (uint8_t*) &rgb_color; + } #if defined(LED_NEOPIXEL) || defined(LED_RGB_RED_PIN) || defined(LED_APA102) - if (final_color != NULL) { - neopixel_write(final_color); - } + if (final_color != NULL) { + neopixel_write(final_color); + } #else - (void) final_color; + (void) final_color; #endif } @@ -354,11 +345,10 @@ void led_state(uint32_t state) #define BYTE_PER_PIXEL 3 -static uint16_t pixels_pattern[NEOPIXELS_NUMBER*BYTE_PER_PIXEL * 8 + 2]; +static uint16_t pixels_pattern[NEOPIXELS_NUMBER * BYTE_PER_PIXEL * 8 + 2]; // use PWM1 for neopixel -void neopixel_init(void) -{ +void neopixel_init(void) { // To support both the SoftDevice + Neopixels we use the EasyDMA // feature from the NRF25. However this technique implies to // generate a pattern and store it on the memory. The actual @@ -394,40 +384,33 @@ void neopixel_init(void) // pwm->INTEN |= (PWM_INTEN_SEQEND0_Enabled< 0; mask >>= 1 ) - { + for (uint8_t mask = 0x80; mask > 0; mask >>= 1) { pixels_pattern[pos] = (pix & mask) ? MAGIC_T1H : MAGIC_T0H; pos++; } @@ -441,14 +424,15 @@ void neopixel_write (uint8_t *pixels) NRF_PWM_Type* pwm = NRF_PWM1; nrf_pwm_seq_ptr_set(pwm, 0, pixels_pattern); - nrf_pwm_seq_cnt_set(pwm, 0, sizeof(pixels_pattern)/2); + nrf_pwm_seq_cnt_set(pwm, 0, sizeof(pixels_pattern) / 2); nrf_pwm_event_clear(pwm, NRF_PWM_EVENT_SEQEND0); nrf_pwm_task_trigger(pwm, NRF_PWM_TASK_SEQSTART0); // blocking wait for sequence complete - while( !nrf_pwm_event_check(pwm, NRF_PWM_EVENT_SEQEND0) ) {} + while (!nrf_pwm_event_check(pwm, NRF_PWM_EVENT_SEQEND0)) {} nrf_pwm_event_clear(pwm, NRF_PWM_EVENT_SEQEND0); } + #endif #ifdef LED_APA102 @@ -460,8 +444,7 @@ void neopixel_write (uint8_t *pixels) static uint8_t pixels_pattern[PATTERN_SIZE() + 4]; // use SPIM1 for dotstar -void neopixel_init(void) -{ +void neopixel_init(void) { NRF_SPIM_Type* spi = NRF_SPIM1; nrf_spim_disable(spi); @@ -492,8 +475,7 @@ void neopixel_init(void) neopixel_write(rgb); } -void neopixel_teardown(void) -{ +void neopixel_teardown(void) { uint8_t rgb[3] = {0, 0, 0 }; neopixel_write(rgb); @@ -502,8 +484,7 @@ void neopixel_teardown(void) } // write 3 bytes color RGB to built-in neopixel -void neopixel_write (uint8_t *pixels) -{ +void neopixel_write (uint8_t *pixels) { NRF_SPIM_Type* spi = NRF_SPIM1; //brightness, blue, green, red @@ -514,10 +495,10 @@ void neopixel_write (uint8_t *pixels) pixels_pattern[3] = 0; for (uint8_t i = 4; i < PATTERN_SIZE(); i+=4) { - pixels_pattern[i] = bbgr[0]; - pixels_pattern[i+1] = bbgr[1]; - pixels_pattern[i+2] = bbgr[2]; - pixels_pattern[i+3] = bbgr[3]; + pixels_pattern[i] = bbgr[0]; + pixels_pattern[i+1] = bbgr[1]; + pixels_pattern[i+2] = bbgr[2]; + pixels_pattern[i+3] = bbgr[3]; } pixels_pattern[PATTERN_SIZE()] = 0xff; @@ -545,15 +526,13 @@ void neopixel_write (uint8_t *pixels) #define LED_RGB_BLUE 2 #define LED_RGB_GREEN 3 -void neopixel_init(void) -{ +void neopixel_init(void) { led_pwm_init(LED_RGB_RED, LED_RGB_RED_PIN); led_pwm_init(LED_RGB_GREEN, LED_RGB_GREEN_PIN); led_pwm_init(LED_RGB_BLUE, LED_RGB_BLUE_PIN); } -void neopixel_teardown(void) -{ +void neopixel_teardown(void) { uint8_t rgb[3] = { 0, 0, 0 }; neopixel_write(rgb); nrf_gpio_cfg_default(LED_RGB_RED_PIN); @@ -562,8 +541,7 @@ void neopixel_teardown(void) } // write 3 bytes color to a built-in neopixel -void neopixel_write (uint8_t *pixels) -{ +void neopixel_write (uint8_t *pixels) { led_pwm_duty_cycle(LED_RGB_RED, pixels[2]); led_pwm_duty_cycle(LED_RGB_GREEN, pixels[1]); led_pwm_duty_cycle(LED_RGB_BLUE, pixels[0]); diff --git a/src/boards/feather_nrf52840_tft/board.h b/src/boards/feather_nrf52840_tft/board.h index 29ac9f9..8e3ad8d 100644 --- a/src/boards/feather_nrf52840_tft/board.h +++ b/src/boards/feather_nrf52840_tft/board.h @@ -44,7 +44,7 @@ *------------------------------------------------------------------*/ #define BUTTONS_NUMBER 2 #define BUTTON_1 _PINNUM(1, 6) -#define BUTTON_2 _PINNUM(1, 4) +#define BUTTON_2 _PINNUM(1, 4) // not connected #define BUTTON_PULL NRF_GPIO_PIN_PULLUP //--------------------------------------------------------------------+ diff --git a/src/main.c b/src/main.c index 960daa4..cf00541 100644 --- a/src/main.c +++ b/src/main.c @@ -68,6 +68,7 @@ #include "nrfx_nvmc.h" #ifdef NRF_USBD + #include "uf2/uf2.h" #include "nrf_usbd.h" #include "tusb.h" @@ -80,16 +81,11 @@ void usb_teardown(void); extern void tusb_hal_nrf_power_event(uint32_t event); #else - #define usb_init(x) led_state(STATE_USB_MOUNTED) // mark nrf52832 as mounted #define usb_teardown() #endif -//--------------------------------------------------------------------+ -// -//--------------------------------------------------------------------+ - /* * Blinking patterns: * - DFU Serial : LED Status blink @@ -132,20 +128,21 @@ extern void tusb_hal_nrf_power_event(uint32_t event); // These value must be the same with one in dfu_transport_ble.c #define BLEGAP_EVENT_LENGTH 6 #define BLEGATT_ATT_MTU_MAX 23 -enum { BLE_CONN_CFG_HIGH_BANDWIDTH = 1 }; +enum { + BLE_CONN_CFG_HIGH_BANDWIDTH = 1 +}; //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ -uint32_t* dbl_reset_mem = ((uint32_t*) DFU_DBL_RESET_MEM ); +uint32_t* dbl_reset_mem = ((uint32_t*) DFU_DBL_RESET_MEM); // true if ble, false if serial bool _ota_dfu = false; bool _ota_connected = false; bool _sd_inited = false; -bool is_ota(void) -{ +bool is_ota(void) { return _ota_dfu; } @@ -154,18 +151,16 @@ static uint32_t ble_stack_init(void); // The SoftDevice must only be initialized if a chip reset has occurred. // Soft reset (jump ) from application must not reinitialize the SoftDevice. -static void mbr_init_sd(void) -{ +static void mbr_init_sd(void) { PRINTF("SD_MBR_COMMAND_INIT_SD\r\n"); - sd_mbr_command_t com = { .command = SD_MBR_COMMAND_INIT_SD }; + sd_mbr_command_t com = {.command = SD_MBR_COMMAND_INIT_SD}; sd_mbr_command(&com); } //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ -int main(void) -{ +int main(void) { // Populate Boot Address and MBR Param into MBR if not already // MBR_BOOTLOADER_ADDR/MBR_PARAM_PAGE_ADDR are used if available, else UICR registers are used // Note: skip it for now since this will prevent us to change the size of bootloader in the future @@ -177,14 +172,11 @@ int main(void) board_init(); bootloader_init(); - PRINTF("Bootloader Start\r\n"); - led_state(STATE_BOOTLOADER_STARTED); // When updating SoftDevice, bootloader will reset before swapping SD - if (bootloader_dfu_sd_in_progress()) - { + if (bootloader_dfu_sd_in_progress()) { led_state(STATE_WRITING_STARTED); bootloader_dfu_sd_update_continue(); @@ -207,14 +199,11 @@ int main(void) * - sd_softdevice_vector_table_base_set(APP_ADDR) * - jump to App reset */ - - if (bootloader_app_is_valid() && !bootloader_dfu_sd_in_progress()) - { + if (bootloader_app_is_valid() && !bootloader_dfu_sd_in_progress()) { PRINTF("App is valid\r\n"); - if ( is_sd_existed() ) - { + if (is_sd_existed()) { // MBR forward IRQ to SD (if not already) - if ( !_sd_inited ) mbr_init_sd(); + if (!_sd_inited) mbr_init_sd(); // Make sure SD is disabled sd_softdevice_disable(); @@ -230,8 +219,7 @@ int main(void) NVIC_SystemReset(); } -static void check_dfu_mode(void) -{ +static void check_dfu_mode(void) { uint32_t const gpregret = NRF_POWER->GPREGRET; // SD is already Initialized in case of BOOTLOADER_DFU_OTA_MAGIC @@ -249,7 +237,7 @@ static void check_dfu_mode(void) // start either serial, uf2 or ble bool dfu_start = _ota_dfu || serial_only_dfu || uf2_dfu || - (((*dbl_reset_mem) == DFU_DBL_RESET_MAGIC) && reason_reset_pin); + (((*dbl_reset_mem) == DFU_DBL_RESET_MAGIC) && reason_reset_pin); // Clear GPREGRET if it is our values if (dfu_start || dfu_skip) NRF_POWER->GPREGRET = 0; @@ -262,7 +250,7 @@ static void check_dfu_mode(void) dfu_start = dfu_start || button_pressed(BUTTON_DFU); // DFU + FRESET are pressed --> OTA - _ota_dfu = _ota_dfu || ( button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) ) ; + _ota_dfu = _ota_dfu || (button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET)); bool const valid_app = bootloader_app_is_valid(); bool const just_start_app = valid_app && !dfu_start && (*dbl_reset_mem) == DFU_DBL_RESET_APP; @@ -270,8 +258,7 @@ static void check_dfu_mode(void) if (!just_start_app && APP_ASKS_FOR_SINGLE_TAP_RESET()) dfu_start = 1; // App mode: Double Reset detection or DFU startup for nrf52832 - if ( ! (just_start_app || dfu_start || !valid_app) ) - { + if (!(just_start_app || dfu_start || !valid_app)) { #ifdef NRF52832_XXAA /* Even DFU is not active, we still force an 1000 ms dfu serial mode when startup * to support auto programming from Arduino IDE @@ -281,8 +268,7 @@ static void check_dfu_mode(void) bootloader_dfu_start(false, DFU_SERIAL_STARTUP_INTERVAL, false); #else // Note: RESETREAS is not clear by bootloader, it should be cleared by application upon init() - if (reason_reset_pin) - { + if (reason_reset_pin) { // Register our first reset for double reset detection (*dbl_reset_mem) = DFU_DBL_RESET_MAGIC; @@ -292,77 +278,59 @@ static void check_dfu_mode(void) #endif } - if (APP_ASKS_FOR_SINGLE_TAP_RESET()) - { + if (APP_ASKS_FOR_SINGLE_TAP_RESET()) { (*dbl_reset_mem) = DFU_DBL_RESET_APP; - } - else - { + } else { (*dbl_reset_mem) = 0; } // Enter DFU mode accordingly to input - if ( dfu_start || !valid_app ) - { - if ( _ota_dfu ) - { + if (dfu_start || !valid_app) { + if (_ota_dfu) { led_state(STATE_BLE_DISCONNECTED); - - if (!_sd_inited ) mbr_init_sd(); + if (!_sd_inited) mbr_init_sd(); _sd_inited = true; - ble_stack_init(); - } - else - { + } else { led_state(STATE_USB_UNMOUNTED); usb_init(serial_only_dfu); } // Initiate an update of the firmware. - if (APP_ASKS_FOR_SINGLE_TAP_RESET() || uf2_dfu || serial_only_dfu) - { + if (APP_ASKS_FOR_SINGLE_TAP_RESET() || uf2_dfu || serial_only_dfu) { // If USB is not enumerated in 3s (eg. because we're running on battery), we restart into app. - bootloader_dfu_start(_ota_dfu, 3000, true); - } - else - { + bootloader_dfu_start(_ota_dfu, 3000, true); + } else { // No timeout if bootloader requires user action (double-reset). - bootloader_dfu_start(_ota_dfu, 0, false); + bootloader_dfu_start(_ota_dfu, 0, false); } - if ( _ota_dfu ) - { + if (_ota_dfu) { sd_softdevice_disable(); - }else - { + } else { usb_teardown(); } } } - // Initializes the SotdDevice by following SD specs section // "Master Boot Record and SoftDevice initializaton procedure" -static uint32_t ble_stack_init(void) -{ +static uint32_t ble_stack_init(void) { // Forward vector table to bootloader address so that we can handle BLE events sd_softdevice_vector_table_base_set(BOOTLOADER_REGION_START); // Enable Softdevice, Use Internal OSC to compatible with all boards - nrf_clock_lf_cfg_t clock_cfg = - { + nrf_clock_lf_cfg_t clock_cfg = { .source = NRF_CLOCK_LF_SRC_RC, .rc_ctiv = 16, .rc_temp_ctiv = 2, .accuracy = NRF_CLOCK_LF_ACCURACY_250_PPM }; - sd_softdevice_enable(&clock_cfg, app_error_fault_handler); sd_nvic_EnableIRQ(SD_EVT_IRQn); /*------------- Configure BLE params -------------*/ - extern uint32_t __data_start__[]; // defined in linker + extern uint32_t __data_start__[]; // defined in linker uint32_t ram_start = (uint32_t) __data_start__; ble_cfg_t blecfg; @@ -370,9 +338,9 @@ static uint32_t ble_stack_init(void) // Configure the maximum number of connections. varclr(&blecfg); blecfg.gap_cfg.role_count_cfg.adv_set_count = 1; - blecfg.gap_cfg.role_count_cfg.periph_role_count = 1; + blecfg.gap_cfg.role_count_cfg.periph_role_count = 1; blecfg.gap_cfg.role_count_cfg.central_role_count = 0; - blecfg.gap_cfg.role_count_cfg.central_sec_count = 0; + blecfg.gap_cfg.role_count_cfg.central_sec_count = 0; sd_ble_cfg_set(BLE_GAP_CFG_ROLE_COUNT, &blecfg, ram_start); // NRF_DFU_BLE_REQUIRES_BONDS @@ -389,7 +357,7 @@ static uint32_t ble_stack_init(void) // Event Length + HVN queue + WRITE CMD queue setting affecting bandwidth varclr(&blecfg); blecfg.conn_cfg.conn_cfg_tag = BLE_CONN_CFG_HIGH_BANDWIDTH; - blecfg.conn_cfg.params.gap_conn_cfg.conn_count = 1; + blecfg.conn_cfg.params.gap_conn_cfg.conn_count = 1; blecfg.conn_cfg.params.gap_conn_cfg.event_length = BLEGAP_EVENT_LENGTH; sd_ble_cfg_set(BLE_CONN_CFG_GAP, &blecfg, ram_start); @@ -407,19 +375,16 @@ static uint32_t ble_stack_init(void) return NRF_SUCCESS; } - //--------------------------------------------------------------------+ // Error Handler //--------------------------------------------------------------------+ -void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) -{ - volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ - if ( (*ARM_CM_DHCSR) & 1UL ) __asm("BKPT #0\n"); /* Only halt mcu if debugger is attached */ +void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) { + volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ + if ((*ARM_CM_DHCSR) & 1UL) __asm("BKPT #0\n"); /* Only halt mcu if debugger is attached */ NVIC_SystemReset(); } -void assert_nrf_callback (uint16_t line_num, uint8_t const * p_file_name) -{ +void assert_nrf_callback(uint16_t line_num, uint8_t const* p_file_name) { app_error_fault_handler(0xDEADBEEF, 0, 0); } @@ -428,9 +393,8 @@ void assert_nrf_callback (uint16_t line_num, uint8_t const * p_file_name) *------------------------------------------------------------------*/ // Process BLE event from SD -uint32_t proc_ble(void) -{ - __ALIGN(4) uint8_t ev_buf[ BLE_EVT_LEN_MAX(BLEGATT_ATT_MTU_MAX) ]; +uint32_t proc_ble(void) { + __ALIGN(4) uint8_t ev_buf[BLE_EVT_LEN_MAX(BLEGATT_ATT_MTU_MAX)]; uint16_t ev_len = BLE_EVT_LEN_MAX(BLEGATT_ATT_MTU_MAX); // Init header @@ -441,25 +405,24 @@ uint32_t proc_ble(void) uint32_t err = sd_ble_evt_get(ev_buf, &ev_len); // Handle valid event, ignore error - if( NRF_SUCCESS == err) - { - switch (evt->header.evt_id) - { + if (NRF_SUCCESS == err) { + switch (evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: _ota_connected = true; led_state(STATE_BLE_CONNECTED); - break; + break; case BLE_GAP_EVT_DISCONNECTED: _ota_connected = false; led_state(STATE_BLE_DISCONNECTED); - break; + break; - default: break; + default: + break; } // from dfu_transport_ble - extern void ble_evt_dispatch(ble_evt_t * p_ble_evt); + extern void ble_evt_dispatch(ble_evt_t* p_ble_evt); ble_evt_dispatch(evt); } @@ -467,68 +430,56 @@ uint32_t proc_ble(void) } // process SOC event from SD -uint32_t proc_soc(void) -{ +uint32_t proc_soc(void) { uint32_t soc_evt = 0; uint32_t err = sd_evt_get(&soc_evt); - if (NRF_SUCCESS == err) - { + if (NRF_SUCCESS == err) { pstorage_sys_event_handler(soc_evt); #ifdef NRF_USBD /*------------- usb power event handler -------------*/ - int32_t usbevt = (soc_evt == NRF_EVT_POWER_USB_DETECTED ) ? NRFX_POWER_USB_EVT_DETECTED: - (soc_evt == NRF_EVT_POWER_USB_POWER_READY) ? NRFX_POWER_USB_EVT_READY : - (soc_evt == NRF_EVT_POWER_USB_REMOVED ) ? NRFX_POWER_USB_EVT_REMOVED : -1; + int32_t usbevt = (soc_evt == NRF_EVT_POWER_USB_DETECTED) ? NRFX_POWER_USB_EVT_DETECTED : + (soc_evt == NRF_EVT_POWER_USB_POWER_READY) ? NRFX_POWER_USB_EVT_READY : + (soc_evt == NRF_EVT_POWER_USB_REMOVED) ? NRFX_POWER_USB_EVT_REMOVED : -1; - if ( usbevt >= 0) tusb_hal_nrf_power_event((uint32_t) usbevt); + if (usbevt >= 0) tusb_hal_nrf_power_event((uint32_t) usbevt); #endif } return err; } -void proc_sd_task(void* evt_data, uint16_t evt_size) -{ +void proc_sd_task(void* evt_data, uint16_t evt_size) { (void) evt_data; (void) evt_size; // process BLE and SOC until there is no more events - while( (NRF_ERROR_NOT_FOUND != proc_ble()) || (NRF_ERROR_NOT_FOUND != proc_soc()) ) - { - + while ((NRF_ERROR_NOT_FOUND != proc_ble()) || (NRF_ERROR_NOT_FOUND != proc_soc())) { + // nothing } } -void SD_EVT_IRQHandler(void) -{ +void SD_EVT_IRQHandler(void) { // Use App Scheduler to defer handling code in non-isr context app_sched_event_put(NULL, 0, proc_sd_task); } - //--------------------------------------------------------------------+ // RTT printf retarget for Debug //--------------------------------------------------------------------+ #ifdef CFG_DEBUG - #include "SEGGER_RTT.h" -__attribute__ ((used)) -int _write (int fhdl, const void *buf, size_t count) -{ +__attribute__ ((used)) int _write (int fhdl, const void *buf, size_t count) { (void) fhdl; SEGGER_RTT_Write(0, (char*) buf, (int) count); return count; } -__attribute__ ((used)) -int _read (int fhdl, char *buf, size_t count) -{ +__attribute__ ((used)) int _read (int fhdl, char *buf, size_t count) { (void) fhdl; return SEGGER_RTT_Read(0, buf, count); } - #endif From f5a1947974f4ebbb5c9941994e0ef1ad8b9630b2 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 3 Jan 2024 22:13:28 +0700 Subject: [PATCH 20/90] add feather tft to ci build --- .github/workflows/githubci.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/githubci.yml b/.github/workflows/githubci.yml index a6bb95e..fe6ed53 100644 --- a/.github/workflows/githubci.yml +++ b/.github/workflows/githubci.yml @@ -21,6 +21,7 @@ jobs: - 'feather_nrf52832' - 'feather_nrf52833_express' - 'feather_nrf52840_express' + - 'feather_nrf52840_tft' - 'feather_nrf52840_sense' - 'itsybitsy_nrf52840_express' - 'metro_nrf52840_express' @@ -67,13 +68,13 @@ jobs: uses: actions/setup-python@v3 - name: Checkout Code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 submodules: true - name: Checkout linkermap - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: hathach/linkermap path: linkermap From 1c85a7a5be5edb9bdfd0a7cde2da51941af05682 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 3 Jan 2024 22:21:29 +0700 Subject: [PATCH 21/90] try to install setuptools for linkermap --- .github/workflows/githubci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/githubci.yml b/.github/workflows/githubci.yml index fe6ed53..8ecc30d 100644 --- a/.github/workflows/githubci.yml +++ b/.github/workflows/githubci.yml @@ -86,7 +86,7 @@ jobs: - name: Install Tools run: | - pip3 install adafruit-nrfutil uritemplate requests intelhex + pip3 install adafruit-nrfutil uritemplate requests intelhex setuptools pip3 install linkermap/ - name: Build From e81391f395e23c73d8bc64598194efc22ca57419 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 4 Jan 2024 18:23:51 +0700 Subject: [PATCH 22/90] rename to feather sense tft --- .github/workflows/githubci.yml | 2 +- .../board.cmake | 0 .../board.h | 18 +++++++++--------- .../board.mk | 0 .../pinconfig.c | 0 5 files changed, 10 insertions(+), 10 deletions(-) rename src/boards/{feather_nrf52840_tft => feather_nrf52840_sense_tft}/board.cmake (100%) rename src/boards/{feather_nrf52840_tft => feather_nrf52840_sense_tft}/board.h (84%) rename src/boards/{feather_nrf52840_tft => feather_nrf52840_sense_tft}/board.mk (100%) rename src/boards/{feather_nrf52840_tft => feather_nrf52840_sense_tft}/pinconfig.c (100%) diff --git a/.github/workflows/githubci.yml b/.github/workflows/githubci.yml index 8ecc30d..5d8b275 100644 --- a/.github/workflows/githubci.yml +++ b/.github/workflows/githubci.yml @@ -21,8 +21,8 @@ jobs: - 'feather_nrf52832' - 'feather_nrf52833_express' - 'feather_nrf52840_express' - - 'feather_nrf52840_tft' - 'feather_nrf52840_sense' + - 'feather_nrf52840_sense_tft' - 'itsybitsy_nrf52840_express' - 'metro_nrf52840_express' - 'ledglasses_nrf52840' diff --git a/src/boards/feather_nrf52840_tft/board.cmake b/src/boards/feather_nrf52840_sense_tft/board.cmake similarity index 100% rename from src/boards/feather_nrf52840_tft/board.cmake rename to src/boards/feather_nrf52840_sense_tft/board.cmake diff --git a/src/boards/feather_nrf52840_tft/board.h b/src/boards/feather_nrf52840_sense_tft/board.h similarity index 84% rename from src/boards/feather_nrf52840_tft/board.h rename to src/boards/feather_nrf52840_sense_tft/board.h index 8e3ad8d..3dcea99 100644 --- a/src/boards/feather_nrf52840_tft/board.h +++ b/src/boards/feather_nrf52840_sense_tft/board.h @@ -22,8 +22,8 @@ * THE SOFTWARE. */ -#ifndef _FEATHER_NRF52840_TFT_H -#define _FEATHER_NRF52840_TFT_H +#ifndef _FEATHER_NRF52840_SENSE_TFT_H +#define _FEATHER_NRF52840_SENSE_TFT_H #define _PINNUM(port, pin) ((port)*32 + (pin)) @@ -44,26 +44,26 @@ *------------------------------------------------------------------*/ #define BUTTONS_NUMBER 2 #define BUTTON_1 _PINNUM(1, 6) -#define BUTTON_2 _PINNUM(1, 4) // not connected +#define BUTTON_2 _PINNUM(1, 10) // DFU pin #define BUTTON_PULL NRF_GPIO_PIN_PULLUP //--------------------------------------------------------------------+ // BLE OTA //--------------------------------------------------------------------+ #define BLEDIS_MANUFACTURER "Adafruit Industries" -#define BLEDIS_MODEL "Feather nRF52840 TFT" +#define BLEDIS_MODEL "Feather nRF52840 Sense TFT" //--------------------------------------------------------------------+ // USB //--------------------------------------------------------------------+ #define USB_DESC_VID 0x239A -#define USB_DESC_UF2_PID 0x0029 -#define USB_DESC_CDC_ONLY_PID 0x002A +#define USB_DESC_UF2_PID 0x0087 +#define USB_DESC_CDC_ONLY_PID 0x0088 //------------- UF2 -------------// -#define UF2_PRODUCT_NAME "Adafruit Feather nRF52840 TFT" -#define UF2_VOLUME_LABEL "FTHR840BOOT" -#define UF2_BOARD_ID "nRF52840-FeatherTFT-revA" +#define UF2_PRODUCT_NAME "Adafruit Feather nRF52840 Sense TFT" +#define UF2_VOLUME_LABEL "FTHRSNSBOOT" +#define UF2_BOARD_ID "nRF52840-FeatherSenseTFT-revA" #define UF2_INDEX_URL "https://www.adafruit.com/product/" #endif diff --git a/src/boards/feather_nrf52840_tft/board.mk b/src/boards/feather_nrf52840_sense_tft/board.mk similarity index 100% rename from src/boards/feather_nrf52840_tft/board.mk rename to src/boards/feather_nrf52840_sense_tft/board.mk diff --git a/src/boards/feather_nrf52840_tft/pinconfig.c b/src/boards/feather_nrf52840_sense_tft/pinconfig.c similarity index 100% rename from src/boards/feather_nrf52840_tft/pinconfig.c rename to src/boards/feather_nrf52840_sense_tft/pinconfig.c From 79add7baf5d4f7f77f8bb3cfcf4fd24483539e39 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 5 Jan 2024 15:49:27 +0700 Subject: [PATCH 23/90] - add screen/display support for st77xx - able to make spi transfer, but data seem to be off --- CMakeLists.txt | 39 ++++-- Makefile | 6 +- linker/nrf52840_debug.ld | 2 +- src/boards/boards.c | 245 ++++++++++++++++++++++++++++++++++++-- src/boards/boards.h | 10 ++ src/images.c | 124 +++++++++++++++++++ src/main.c | 5 - src/nrfx_config.h | 2 - src/screen.c | 251 +++++++++++++++++++++++++++++++++++++++ src/usb/usb.c | 45 +++---- 10 files changed, 676 insertions(+), 53 deletions(-) create mode 100644 src/images.c create mode 100644 src/screen.c diff --git a/CMakeLists.txt b/CMakeLists.txt index d5b2369..a124031 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,8 +35,6 @@ set(TUSB ${CMAKE_CURRENT_LIST_DIR}/lib/tinyusb/src) #------------------- set(CMAKE_EXECUTABLE_SUFFIX .elf) add_executable(bootloader) -#set_target_properties(bootloader PROPERTIES OUTPUT_NAME "${BOARD}_bootloader.elf") - # SD_VERSION can be overwritten by board.cmake if(NOT DEFINED SD_VERSION) @@ -51,6 +49,8 @@ target_sources(bootloader PUBLIC src/dfu_init.c src/flash_nrf5x.c src/main.c + src/screen.c + src/images.c src/boards/boards.c # nrfx ${NRFX}/drivers/src/nrfx_power.c @@ -112,10 +112,29 @@ target_include_directories(bootloader PUBLIC ${SOFTDEVICE}/mbr/headers ) +# Debug option if (CMAKE_BUILD_TYPE STREQUAL "Debug") # TODO not work yet, also need to add segger rtt, DFU_APP_DATA_RESERVED=0, BOOTLOADER_REGION_START=0xED000 set(LD_FILE ${CMAKE_CURRENT_LIST_DIR}/linker/${MCU_VARIANT}_debug.ld) - message(FATAL_ERROR "Debug build not supported yet") + + target_sources(bootloader PUBLIC + lib/SEGGER_RTT/RTT/SEGGER_RTT.c + ) + target_include_directories(bootloader PUBLIC + lib/SEGGER_RTT/RTT + ) + + target_compile_definitions(bootloader PUBLIC + CFG_DEBUG + SEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL + DFU_APP_DATA_RESERVED=0 + ) + + if (MCU_VARIANT STREQUAL "nrf52840") + target_compile_definitions(bootloader PUBLIC BOOTLOADER_REGION_START=0xEA000) + else () + target_compile_definitions(bootloader PUBLIC BOOTLOADER_REGION_START=0x6D000) + endif () else () set(LD_FILE ${CMAKE_CURRENT_LIST_DIR}/linker/${MCU_VARIANT}.ld) endif () @@ -123,8 +142,7 @@ endif () target_link_options(bootloader PUBLIC "LINKER:--script=${LD_FILE}" -L${NRFX}/mdk - --specs=nosys.specs - --specs=nano.specs + --specs=nosys.specs --specs=nano.specs ) target_compile_options(bootloader PUBLIC -fno-builtin @@ -149,7 +167,6 @@ target_compile_options(bootloader PUBLIC ) target_compile_definitions(bootloader PUBLIC SOFTDEVICE_PRESENT - DFU_APP_DATA_RESERVED=7*4096 ) if (TRACE_ETM STREQUAL "1") @@ -195,6 +212,7 @@ endif () if (MCU_VARIANT STREQUAL "nrf52") set(SD_NAME s132) set(DFU_DEV_REV 0xADAF) + set(DFU_APP_DATA_RESERVED 7*4096) target_compile_definitions(bootloader PUBLIC NRF52 NRF52832_XXAA @@ -207,6 +225,7 @@ if (MCU_VARIANT STREQUAL "nrf52") elseif (MCU_VARIANT STREQUAL "nrf52833") set(SD_NAME s140) set(DFU_DEV_REV 52833) + set(DFU_APP_DATA_RESERVED 7*4096) target_compile_definitions(bootloader PUBLIC NRF52833_XXAA S140 @@ -218,6 +237,8 @@ elseif (MCU_VARIANT STREQUAL "nrf52833") elseif (MCU_VARIANT STREQUAL "nrf52840") set(SD_NAME s140) set(DFU_DEV_REV 52840) + # App reserved 40KB (8+32) to match circuitpython for 840 + set(DFU_APP_DATA_RESERVED 10*4096) target_compile_definitions(bootloader PUBLIC NRF52840_XXAA S140 @@ -233,6 +254,10 @@ endif () set(SD_FILENAME ${SD_NAME}_nrf52_${SD_VERSION}) set(SD_HEX ${SOFTDEVICE}/${SD_FILENAME}/${SD_FILENAME}_softdevice.hex) +if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug") + target_compile_definitions(bootloader PUBLIC DFU_APP_DATA_RESERVED=${DFU_APP_DATA_RESERVED}) +endif () + #---------------------------------- # Get UF2 version from git #---------------------------------- @@ -257,12 +282,12 @@ math(EXPR MK_BOOTLOADER_VERSION "(${RELEASE_VERSION_MAJOR} << 16) + (${RELEASE_V cmake_print_variables(GIT_VERSION GIT_SUBMODULE_VERSIONS MK_BOOTLOADER_VERSION) target_compile_definitions(bootloader PUBLIC + UF2_VERSION_BASE="${GIT_VERSION}" UF2_VERSION="${GIT_VERSION} - ${GIT_SUBMODULE_VERSIONS}" BLEDIS_FW_VERSION="${GIT_VERSION} ${SD_NAME} ${SD_VERSION}" MK_BOOTLOADER_VERSION=${MK_BOOTLOADER_VERSION} ) - #---------------------------------- # Post build #---------------------------------- diff --git a/Makefile b/Makefile index fb1f521..866d4a6 100644 --- a/Makefile +++ b/Makefile @@ -123,7 +123,7 @@ else ifeq ($(MCU_SUB_VARIANT),nrf52840) SD_NAME = s140 DFU_DEV_REV = 52840 CFLAGS += -DNRF52840_XXAA -DS140 - # App reserved 40KB to match circuitpython for 840 + # App reserved 40KB (8+32) to match circuitpython for 840 DFU_APP_DATA_RESERVED=10*4096 else $(error Sub Variant $(MCU_SUB_VARIANT) is unknown) @@ -328,9 +328,9 @@ ifeq ($(DEBUG), 1) C_SRC += $(RTT_SRC)/RTT/SEGGER_RTT.c DFU_APP_DATA_RESERVED = 0 - # expand bootloader address to 28KB of reserved app + # expand bootloader address to 28KB/40KB of reserved app ifeq ($(MCU_SUB_VARIANT),nrf52840) - CFLAGS += -DBOOTLOADER_REGION_START=0xED000 + CFLAGS += -DBOOTLOADER_REGION_START=0xEA000 else CFLAGS += -DBOOTLOADER_REGION_START=0x6D000 endif diff --git a/linker/nrf52840_debug.ld b/linker/nrf52840_debug.ld index 324cad1..7c68a83 100644 --- a/linker/nrf52840_debug.ld +++ b/linker/nrf52840_debug.ld @@ -12,7 +12,7 @@ MEMORY * APP_ERROR_CHECK_BOOL(*((uint32_t *)NRF_UICR_BOOT_START_ADDRESS) == BOOTLOADER_REGION_START); */ /* due to lack of flash for debug, we will use reserved app to extend bootloader size */ - FLASH (rx) : ORIGIN = 0xF4000-28K, LENGTH = 0xFE000-0xF4000 - 2K + 28K /* 38 KB */ + FLASH (rx) : ORIGIN = 0xF4000 - 40K, LENGTH = 0xFE000-0xF4000 - 2K + 40K /* 38 KB */ BOOTLOADER_CONFIG (r): ORIGIN = 0xFE000 - 2K, LENGTH = 2K diff --git a/src/boards/boards.c b/src/boards/boards.c index 8b4583f..b88d3f5 100644 --- a/src/boards/boards.c +++ b/src/boards/boards.c @@ -24,6 +24,7 @@ #include "boards.h" #include "nrf_pwm.h" +#include "nrf_spim.h" #include "app_scheduler.h" #include "app_timer.h" @@ -31,9 +32,6 @@ #include "nrf_spim.h" #endif -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ #define SCHED_MAX_EVENT_DATA_SIZE sizeof(app_timer_event_t) /**< Maximum size of scheduler events. */ #define SCHED_QUEUE_SIZE 30 /**< Maximum number of events in the scheduler queue. */ @@ -43,7 +41,16 @@ void neopixel_write(uint8_t* pixels); void neopixel_teardown(void); #endif -//------------- IMPLEMENTATION -------------// +//--------------------------------------------------------------------+ +// IMPLEMENTATION +//--------------------------------------------------------------------+ + +static uint32_t _systick_count = 0; +void SysTick_Handler(void) { + _systick_count++; + led_tick(); +} + void button_init(uint32_t pin) { if (BUTTON_PULL == NRF_GPIO_PIN_PULLDOWN) { nrf_gpio_cfg_sense_input(pin, BUTTON_PULL, NRF_GPIO_PIN_SENSE_HIGH); @@ -96,6 +103,7 @@ void board_init(void) { #if ENABLE_DCDC_1 == 1 NRF_POWER->DCDCEN = 1; #endif + // Make sure any custom inits are performed board_init2(); @@ -144,6 +152,10 @@ void board_teardown(void) { neopixel_teardown(); #endif +#ifdef DISPLAY_PIN_SCK + board_display_teardown(); +#endif + // Stop RTC1 used by app_timer NVIC_DisableIRQ(RTC1_IRQn); NRF_RTC1->EVTENCLR = RTC_EVTEN_COMPARE0_Msk; @@ -164,13 +176,134 @@ void board_teardown(void) { board_teardown2(); } -static uint32_t _systick_count = 0; +//--------------------------------------------------------------------+ +// Display +//--------------------------------------------------------------------+ +#ifdef DISPLAY_PIN_SCK -void SysTick_Handler(void) { - _systick_count++; - led_tick(); +// Note don't use SPIM3 since it has lots of errata +NRF_SPIM_Type* _spim = NRF_SPIM0; + +static void spi_write(NRF_SPIM_Type *p_spim, uint8_t const *tx_buf, size_t tx_len) { + nrf_spim_tx_buffer_set(p_spim, tx_buf, tx_len); + nrf_spim_rx_buffer_set(p_spim, NULL, 0); + + nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_ENDTX); + nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_END); + nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_START); + + // blocking wait until xfer complete + while (!nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_END)){} } +static void tft_controller_init(void); + +static inline void tft_cs(bool state) { + if (state) { + nrf_gpio_pin_set(DISPLAY_PIN_CS); + } else { + nrf_gpio_pin_clear(DISPLAY_PIN_CS); + } +} + +static inline void tft_dc(bool state) { + if (state) { + nrf_gpio_pin_set(DISPLAY_PIN_DC); + } else { + nrf_gpio_pin_clear(DISPLAY_PIN_DC); + } +} + +static void tft_cmd(uint8_t cmd, uint8_t const* data, uint8_t narg) { + tft_cs(false); + + // send command + tft_dc(false); + spi_write(_spim, &cmd, 1); + + // send data + if (narg > 0) { + tft_dc(true); + spi_write(_spim, data, narg); + } + + tft_cs(true); +} + +void board_display_init(void) { + //------------- SPI init -------------// + // highspeed SPIM should set SCK and MOSI to high drive + nrf_gpio_cfg(DISPLAY_PIN_SCK, NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_CONNECT, + NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE); + nrf_gpio_cfg(DISPLAY_PIN_MOSI, NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, + NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE); + nrf_gpio_cfg_output(DISPLAY_PIN_CS); + nrf_gpio_pin_set(DISPLAY_PIN_CS); + + nrf_spim_pins_set(_spim, DISPLAY_PIN_SCK, DISPLAY_PIN_MOSI, NRF_SPIM_PIN_NOT_CONNECTED); + nrf_spim_frequency_set(_spim, NRF_SPIM_FREQ_4M); + nrf_spim_configure(_spim, NRF_SPIM_MODE_0, NRF_SPIM_BIT_ORDER_MSB_FIRST); + nrf_spim_orc_set(_spim, 0xFF); + + nrf_spim_enable(_spim); + + //------------- Display Init -------------// + nrf_gpio_cfg_output(DISPLAY_PIN_DC); + + #if defined(DISPLAY_PIN_RST) && DISPLAY_PIN_RST >= 0 + nrf_gpio_cfg_output(DISPLAY_PIN_RST); + nrf_gpio_pin_write(DISPLAY_PIN_RST, 0); + NRFX_DELAY_MS(10); + nrf_gpio_pin_write(DISPLAY_PIN_RST, 1); + #endif + + #if defined(DISPLAY_PIN_BL) && DISPLAY_PIN_BL >= 0 + nrf_gpio_cfg_output(DISPLAY_PIN_BL); + nrf_gpio_pin_write(DISPLAY_PIN_BL, DISPLAY_BL_ON); + #endif + + tft_controller_init(); +} + +void board_display_teardown(void) { + nrf_spim_disable(_spim); +} + +// Send the whole buffer data to display controller +extern const uint16_t color_palette[]; +void board_display_draw_screen(uint8_t const* fb) { + + tft_cs(false); + + // command: memory write + uint8_t cmd = 0x2C; + tft_dc(false); + spi_write(_spim, &cmd, 1); + + // data + tft_dc(true); + + uint8_t const* p = fb; + for (int i = 0; i < DISPLAY_WIDTH; ++i) { + uint8_t cc[DISPLAY_HEIGHT * 2]; + uint32_t dst = 0; + for (int j = 0; j < DISPLAY_HEIGHT; ++j) { + uint16_t color = color_palette[*p++ & 0xf]; + cc[dst++] = color >> 8; + cc[dst++] = color & 0xff; + } + + spi_write(_spim, cc, sizeof(cc)); + } + + tft_cs(true); +} + +#endif + +//--------------------------------------------------------------------+ +// LED Indicator +//--------------------------------------------------------------------+ void pwm_teardown(NRF_PWM_Type* pwm) { pwm->TASKS_SEQSTART[0] = 0; pwm->ENABLE = 0; @@ -547,3 +680,99 @@ void neopixel_write (uint8_t *pixels) { led_pwm_duty_cycle(LED_RGB_BLUE, pixels[0]); } #endif + +#ifdef DISPLAY_CONTROLLER_ST7789 + +#define ST_CMD_DELAY 0x80 // special signifier for command lists + +#define ST77XX_NOP 0x00 +#define ST77XX_SWRESET 0x01 +#define ST77XX_RDDID 0x04 +#define ST77XX_RDDST 0x09 + +#define ST77XX_SLPIN 0x10 +#define ST77XX_SLPOUT 0x11 +#define ST77XX_PTLON 0x12 +#define ST77XX_NORON 0x13 + +#define ST77XX_INVOFF 0x20 +#define ST77XX_INVON 0x21 +#define ST77XX_DISPOFF 0x28 +#define ST77XX_DISPON 0x29 +#define ST77XX_CASET 0x2A +#define ST77XX_RASET 0x2B +#define ST77XX_RAMWR 0x2C +#define ST77XX_RAMRD 0x2E + +#define ST77XX_PTLAR 0x30 +#define ST77XX_TEOFF 0x34 +#define ST77XX_TEON 0x35 +#define ST77XX_MADCTL 0x36 +#define ST77XX_COLMOD 0x3A + +#define ST77XX_MADCTL_MY 0x80 +#define ST77XX_MADCTL_MX 0x40 +#define ST77XX_MADCTL_MV 0x20 +#define ST77XX_MADCTL_ML 0x10 +#define ST77XX_MADCTL_RGB 0x00 + +#define ST77XX_RDID1 0xDA +#define ST77XX_RDID2 0xDB +#define ST77XX_RDID3 0xDC +#define ST77XX_RDID4 0xDD + +// Some ready-made 16-bit ('565') color settings: +#define ST77XX_BLACK 0x0000 +#define ST77XX_WHITE 0xFFFF +#define ST77XX_RED 0xF800 +#define ST77XX_GREEN 0x07E0 +#define ST77XX_BLUE 0x001F +#define ST77XX_CYAN 0x07FF +#define ST77XX_MAGENTA 0xF81F +#define ST77XX_YELLOW 0xFFE0 +#define ST77XX_ORANGE 0xFC00 + +static void tft_controller_init(void) { + // Init commands for 7789 screens + uint8_t cmdinit_st7789[] = { + // 1: Software reset, no args, w/delay ~150 ms delay + ST77XX_SWRESET, ST_CMD_DELAY, 150, + // 2: Out of sleep mode, no args, w/delay 10 ms delay + ST77XX_SLPOUT, ST_CMD_DELAY, 10, + // 3: Set color mode, 1 arg + delay: 16-bit color, 10 ms delay + ST77XX_COLMOD, 1 + ST_CMD_DELAY, 0x55, 10, + // 4: Mem access ctrl (directions), 1 arg: Row/col addr, bottom-top refresh + ST77XX_MADCTL, 1, 0x08, + // 5: Column addr set, 4 args, no delay: XSTART = 0, XEND = 240 + ST77XX_CASET, 4, 0x00, 0, 0, 240, + // 6: Row addr set, 4 args, no delay: YSTART = 0 YEND = 320 + ST77XX_RASET, 4, 0x00, 0, 320 >> 8, 320 & 0xFF, + // 7: hack + ST77XX_INVON, ST_CMD_DELAY, 10, + // 8: Normal display on, no args, w/delay 10 ms delay + ST77XX_NORON, ST_CMD_DELAY, 10, + // 9: Main screen turn on, no args, delay 10 ms delay + ST77XX_DISPON, ST_CMD_DELAY, 10 + }; + + size_t count = 0; + while (count < sizeof(cmdinit_st7789)) { + uint8_t const cmd = cmdinit_st7789[count++]; + uint8_t const cmd_arg = cmdinit_st7789[count++]; + uint8_t const has_delay = cmd_arg & ST_CMD_DELAY; + uint8_t const narg = cmd_arg & ~ST_CMD_DELAY; + + tft_cmd(cmd, cmdinit_st7789 + count, narg); + count += narg; + + if (has_delay) { + uint16_t delay = (uint16_t) cmdinit_st7789[count++]; + if (delay == 255) { + delay = 500; // If 255, delay for 500 ms + } + NRFX_DELAY_MS(delay); + } + } +} + +#endif \ No newline at end of file diff --git a/src/boards/boards.h b/src/boards/boards.h index 8aa0ece..e5bf3d8 100644 --- a/src/boards/boards.h +++ b/src/boards/boards.h @@ -114,6 +114,16 @@ bool button_pressed(uint32_t pin); bool is_ota(void); +//--------------------------------------------------------------------+ +// Display +//--------------------------------------------------------------------+ +#ifdef DISPLAY_PIN_SCK +void board_display_init(void); +void board_display_teardown(void); +void board_display_draw_screen(uint8_t const* fb); +void screen_draw_drag(void); +#endif + //--------------------------------------------------------------------+ // DEBUG //--------------------------------------------------------------------+ diff --git a/src/images.c b/src/images.c new file mode 100644 index 0000000..2f2767f --- /dev/null +++ b/src/images.c @@ -0,0 +1,124 @@ +#include "boards.h" + +#if defined(DISPLAY_PIN_SCK) + +#include + +// all https://makecode.com/_VrfEKzV4xfvq + +// https://makecode.com/_7VxXm3JMPXfM - file +// https://makecode.com/_LuEUCsPEKUbs - download +const uint8_t fileLogo[] = { +32, 32, 71, 140, 201, 151, 1, 2, 146, 1, 2, 146, 63, 2, 151, 9, 153, 9, 153, 9, 146, 1, 9, 146, 3, 9, 146, 7, 9, 137, 205, 72, 140, 206, 36, 139, 207, 18, 138, 206, 36, 139, 205, 72, 149, 7, 9, 146, 3, 9, 146, 1, 9, 153, 9, 153, 9, 153, 9, 148, 63, 2, 146, 1, 2, 146, 1, 2, 146, 201, 191, 191, 191, 174 +}; + +// https://makecode.com/_9b0RcK5yRa12 +const uint8_t pendriveLogo[] = { +32, 32, 59, 137, 215, 137, 1, 143, 1, 8, 146, 203, 149, 3, 8, 146, 3, 8, 146, 115, 8, 146, 115, 8, 146, 3, 8, 146, 3, 8, 146, 115, 8, 146, 115, 8, 146, 3, 8, 146, 3, 8, 146, 203, 149, 1, 8, 146, 1, 8, 146, 1, 120, 211, 191, 191, 191, 191, 191, 191, 191, 135 +}; + +// https://makecode.com/_TTqbj705L4mr +const uint8_t arrowLogo[] = { +32, 32, 54, 137, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 151, 201, 146, 211, 142, 209, 144, 207, 146, 205, 148, 203, 150, 201, 152, 199, 154, 31, 154, 7, 154, 1, 191, 191, 191, 175 +}; + +const uint8_t font8[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, +0x00, 0x0e, 0x00, 0x0e, 0x00, 0x00, +0x28, 0xfe, 0x28, 0xfe, 0x28, 0x00, +0x4c, 0x92, 0xff, 0x92, 0x64, 0x00, +0x02, 0x65, 0x12, 0x48, 0xa6, 0x40, +0x6c, 0x92, 0x92, 0x6c, 0xa0, 0x00, +0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0x82, 0x00, 0x00, +0x00, 0x00, 0x82, 0x7c, 0x00, 0x00, +0x54, 0x38, 0x10, 0x38, 0x54, 0x00, +0x10, 0x10, 0x7c, 0x10, 0x10, 0x00, +0x00, 0x00, 0x90, 0x70, 0x00, 0x00, +0x10, 0x10, 0x10, 0x10, 0x10, 0x00, +0x00, 0x00, 0x60, 0x60, 0x00, 0x00, +0x00, 0x60, 0x10, 0x08, 0x06, 0x00, +0x00, 0x3c, 0x42, 0x42, 0x3c, 0x00, +0x00, 0x44, 0x7e, 0x40, 0x00, 0x00, +0x00, 0x44, 0x62, 0x52, 0x4c, 0x00, +0x00, 0x42, 0x4a, 0x4e, 0x32, 0x00, +0x30, 0x28, 0x24, 0x7e, 0x20, 0x00, +0x00, 0x4e, 0x4a, 0x4a, 0x32, 0x00, +0x00, 0x3c, 0x4a, 0x4a, 0x30, 0x00, +0x00, 0x02, 0x62, 0x12, 0x0e, 0x00, +0x00, 0x34, 0x4a, 0x4a, 0x34, 0x00, +0x00, 0x0c, 0x52, 0x52, 0x3c, 0x00, +0x00, 0x00, 0x6c, 0x6c, 0x00, 0x00, +0x00, 0x00, 0x96, 0x76, 0x00, 0x00, +0x10, 0x28, 0x28, 0x44, 0x44, 0x00, +0x28, 0x28, 0x28, 0x28, 0x28, 0x00, +0x44, 0x44, 0x28, 0x28, 0x10, 0x00, +0x00, 0x02, 0x59, 0x09, 0x06, 0x00, +0x3c, 0x42, 0x5a, 0x56, 0x08, 0x00, +0x78, 0x14, 0x12, 0x14, 0x78, 0x00, +0x7e, 0x4a, 0x4a, 0x4a, 0x34, 0x00, +0x00, 0x3c, 0x42, 0x42, 0x24, 0x00, +0x00, 0x7e, 0x42, 0x42, 0x3c, 0x00, +0x00, 0x7e, 0x4a, 0x4a, 0x42, 0x00, +0x00, 0x7e, 0x0a, 0x0a, 0x02, 0x00, +0x00, 0x3c, 0x42, 0x52, 0x34, 0x00, +0x00, 0x7e, 0x08, 0x08, 0x7e, 0x00, +0x00, 0x42, 0x7e, 0x42, 0x00, 0x00, +0x20, 0x40, 0x42, 0x3e, 0x02, 0x00, +0x00, 0x7e, 0x08, 0x14, 0x62, 0x00, +0x00, 0x7e, 0x40, 0x40, 0x40, 0x00, +0x7e, 0x04, 0x18, 0x04, 0x7e, 0x00, +0x00, 0x7e, 0x04, 0x08, 0x7e, 0x00, +0x3c, 0x42, 0x42, 0x42, 0x3c, 0x00, +0x00, 0x7e, 0x12, 0x12, 0x0c, 0x00, +0x00, 0x3c, 0x52, 0x62, 0xbc, 0x00, +0x00, 0x7e, 0x12, 0x12, 0x6c, 0x00, +0x00, 0x24, 0x4a, 0x52, 0x24, 0x00, +0x02, 0x02, 0x7e, 0x02, 0x02, 0x00, +0x00, 0x3e, 0x40, 0x40, 0x3e, 0x00, +0x00, 0x1e, 0x70, 0x70, 0x1e, 0x00, +0x7e, 0x20, 0x18, 0x20, 0x7e, 0x00, +0x42, 0x24, 0x18, 0x24, 0x42, 0x00, +0x06, 0x08, 0x70, 0x08, 0x06, 0x00, +0x00, 0x62, 0x52, 0x4a, 0x46, 0x00, +0x00, 0x7e, 0x42, 0x42, 0x00, 0x00, +0x00, 0x06, 0x08, 0x10, 0x60, 0x00, +0x00, 0x42, 0x42, 0x7e, 0x00, 0x00, +0x08, 0x04, 0x02, 0x04, 0x08, 0x00, +0x80, 0x80, 0x80, 0x80, 0x80, 0x00, +0x00, 0x00, 0x02, 0x04, 0x00, 0x00, +0x00, 0x30, 0x48, 0x48, 0x78, 0x00, +0x00, 0x7e, 0x48, 0x48, 0x30, 0x00, +0x00, 0x30, 0x48, 0x48, 0x48, 0x00, +0x00, 0x30, 0x48, 0x48, 0x7e, 0x00, +0x00, 0x30, 0x68, 0x58, 0x50, 0x00, +0x00, 0x10, 0x7c, 0x12, 0x04, 0x00, +0x00, 0x18, 0xa4, 0xa4, 0x78, 0x00, +0x00, 0x7e, 0x08, 0x08, 0x70, 0x00, +0x00, 0x48, 0x7a, 0x40, 0x00, 0x00, +0x00, 0x40, 0x84, 0x7d, 0x00, 0x00, +0x00, 0x7e, 0x10, 0x28, 0x40, 0x00, +0x00, 0x42, 0x7e, 0x40, 0x00, 0x00, +0x78, 0x08, 0x30, 0x08, 0x70, 0x00, +0x00, 0x78, 0x08, 0x08, 0x70, 0x00, +0x00, 0x30, 0x48, 0x48, 0x30, 0x00, +0x00, 0xfc, 0x24, 0x24, 0x18, 0x00, +0x00, 0x18, 0x24, 0x24, 0xfc, 0x00, +0x00, 0x78, 0x10, 0x08, 0x10, 0x00, +0x00, 0x50, 0x58, 0x68, 0x28, 0x00, +0x00, 0x08, 0x3e, 0x48, 0x20, 0x00, +0x00, 0x38, 0x40, 0x40, 0x78, 0x00, +0x00, 0x18, 0x60, 0x60, 0x18, 0x00, +0x38, 0x40, 0x30, 0x40, 0x38, 0x00, +0x00, 0x48, 0x30, 0x30, 0x48, 0x00, +0x00, 0x5c, 0xa0, 0xa0, 0x7c, 0x00, +0x00, 0x48, 0x68, 0x58, 0x48, 0x00, +0x00, 0x08, 0x36, 0x41, 0x00, 0x00, +0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, +0x00, 0x41, 0x36, 0x08, 0x00, 0x00, +0x00, 0x08, 0x04, 0x08, 0x04, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +#endif \ No newline at end of file diff --git a/src/main.c b/src/main.c index cf00541..92ad020 100644 --- a/src/main.c +++ b/src/main.c @@ -477,9 +477,4 @@ __attribute__ ((used)) int _write (int fhdl, const void *buf, size_t count) { return count; } -__attribute__ ((used)) int _read (int fhdl, char *buf, size_t count) { - (void) fhdl; - return SEGGER_RTT_Read(0, buf, count); -} - #endif diff --git a/src/nrfx_config.h b/src/nrfx_config.h index b626e00..74e5fdb 100644 --- a/src/nrfx_config.h +++ b/src/nrfx_config.h @@ -18,10 +18,8 @@ // UART #ifdef NRF52832_XXAA - #define NRFX_UART_ENABLED 1 #define NRFX_UART0_ENABLED 1 - #define NRFX_UART_DEFAULT_CONFIG_IRQ_PRIORITY 7 #define NRFX_UART_DEFAULT_CONFIG_HWFC NRF_UART_HWFC_DISABLED #define NRFX_UART_DEFAULT_CONFIG_PARITY NRF_UART_PARITY_EXCLUDED diff --git a/src/screen.c b/src/screen.c new file mode 100644 index 0000000..adf2198 --- /dev/null +++ b/src/screen.c @@ -0,0 +1,251 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Ha Thach (tinyusb.org) for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "boards.h" + +#if defined(DISPLAY_PIN_SCK) + +#include +#include + +// Overlap 4x chars by this much. +#define CHAR4_KERNING 3 + +// Width of a single 4x char, adjusted by kerning +#define CHAR4_KERNED_WIDTH (6 * 4 - CHAR4_KERNING) + +#define COL0(r, g, b) ((((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3)) +#define COL(c) COL0((c >> 16) & 0xff, (c >> 8) & 0xff, c & 0xff) + +enum { + COLOR_BLACK = 0, + COLOR_WHITE = 1, + COLOR_RED = 2, + COLOR_PINK = 3, + COLOR_ORANGE = 4, + COLOR_YELLOW = 5, + COLOR_CYAN = 6, + COLOR_GREEN = 7, + COLOR_BLUE = 8, + COLOR_AQUA = 9, + COLOR_PURPLE = 10, +}; + +// 16-bit 565 color from 24-bit 888 format +const uint16_t color_palette[] = { + COL(0x000000), // 0 + COL(0xffffff), // 1 + COL(0xff2121), // 2 + COL(0xff93c4), // 3 + COL(0xff8135), // 4 + COL(0xfff609), // 5 + COL(0x249ca3), // 6 + COL(0x78dc52), // 7 + COL(0x003fad), // 8 + COL(0x87f2ff), // 9 + COL(0x8e2ec4), // 10 + + COL(0xa4839f), // 11 + COL(0x5c406c), // 12 + COL(0xe5cdc4), // 13 + COL(0x91463d), // 14 + COL(0x000000), // 15 +}; + +// TODO only buffer partial screen to save SRAM +// ESP32s2 can only statically allocated DRAM up to 160KB. +// the remaining 160KB can only be allocated at runtime as heap. +static uint8_t frame_buf[DISPLAY_WIDTH * DISPLAY_HEIGHT]; +//static uint8_t* frame_buf; + +extern const uint8_t font8[]; +extern const uint8_t fileLogo[]; +extern const uint8_t pendriveLogo[]; +extern const uint8_t arrowLogo[]; + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + +// print character with font size = 1 +static void printch(int x, int y, int color, const uint8_t* fnt) { + for (int i = 0; i < 6; ++i) { + uint8_t* p = frame_buf + (x + i) * DISPLAY_HEIGHT + y; + uint8_t mask = 0x01; + for (int j = 0; j < 8; ++j) { + if (*fnt & mask) { + *p = color; + } + p++; + mask <<= 1; + } + fnt++; + } +} + +// print character with font size = 4 +static void printch4(int x, int y, int color, const uint8_t* fnt) { + for (int i = 0; i < 6 * 4; ++i) { + uint8_t* p = frame_buf + (x + i) * DISPLAY_HEIGHT + y; + uint8_t mask = 0x01; + for (int j = 0; j < 8; ++j) { + for (int k = 0; k < 4; ++k) { + if (*fnt & mask) { + *p = color; + } + p++; + } + mask <<= 1; + } + if ((i & 3) == 3) { + fnt++; + } + } +} + +// print icon +static void printicon(int x, int y, int color, const uint8_t* icon) { + int w = *icon++; + int h = *icon++; + int sz = *icon++; + + uint8_t mask = 0x80; + int runlen = 0; + int runbit = 0; + uint8_t lastb = 0x00; + + for (int i = 0; i < w; ++i) { + uint8_t* p = frame_buf + (x + i) * DISPLAY_HEIGHT + y; + for (int j = 0; j < h; ++j) { + int c = 0; + if (mask != 0x80) { + if (lastb & mask) { + c = 1; + } + mask <<= 1; + } else if (runlen) { + if (runbit) { + c = 1; + } + runlen--; + } else { + if (sz-- <= 0) { + //TU_LOG1("Screen Panic code = 10"); + } + lastb = *icon++; + if (lastb & 0x80) { + runlen = lastb & 63; + runbit = lastb & 0x40; + } else { + mask = 0x01; + } + --j; + continue; // restart + } + if (c) { + *p = color; + } + p++; + } + } +} + +// print text with font size = 1 +static void print(int x, int y, int col, const char* text) { + int x0 = x; + while (*text) { + char c = *text++; + if (c == '\r') continue; + if (c == '\n') { + x = x0; + y += 10; + continue; + } + /* + if (x + 8 > DISPLAY_WIDTH) { + x = x0; + y += 10; + } + */ + if (c < ' ') c = '?'; + if (c >= 0x7f) c = '?'; + c -= ' '; + printch(x, y, col, &font8[c * 6]); + x += 6; + } +} + +// Print text with font size = 4 +static void print4(int x, int y, int color, const char* text) { + while (*text) { + char c = *text++; + c -= ' '; + printch4(x, y, color, &font8[c * 6]); + x += CHAR4_KERNED_WIDTH; + if (x + CHAR4_KERNED_WIDTH > DISPLAY_WIDTH) { + // Next char won't fit. + return; + } + } +} + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + +// draw color bar +static void drawBar(int y, int h, int color) { + for (int x = 0; x < DISPLAY_WIDTH; ++x) { + memset(frame_buf + x * DISPLAY_HEIGHT + y, color, h); + } +} + +// draw drag & drop screen +void screen_draw_drag(void) { + drawBar(0, 52, COLOR_GREEN); + drawBar(52, 55, COLOR_BLUE); + drawBar(107, 14, COLOR_ORANGE); + + // Center UF2_PRODUCT_NAME and UF2_VERSION_BASE. + int name_x = (DISPLAY_WIDTH - CHAR4_KERNED_WIDTH * (int) strlen(DISPLAY_TITLE)) / 2; + print4(name_x >= 0 ? name_x : 0, 5, COLOR_WHITE, DISPLAY_TITLE); + + int version_x = (DISPLAY_WIDTH - 6 * (int) strlen(UF2_VERSION_BASE)) / 2; + print(version_x >= 0 ? version_x : 0, 40, COLOR_PURPLE, UF2_VERSION_BASE); + + // TODO the reset should be center as well + print(23, 110, 1, "circuitpython.org"); + +#define DRAG 70 +#define DRAGX 10 + printicon(DRAGX + 20, DRAG + 5, COLOR_WHITE, fileLogo); + printicon(DRAGX + 66, DRAG, COLOR_WHITE, arrowLogo); + printicon(DRAGX + 108, DRAG, COLOR_WHITE, pendriveLogo); + print(10, DRAG - 12, COLOR_WHITE, "firmware.uf2"); + print(90, DRAG - 12, COLOR_WHITE, UF2_VOLUME_LABEL); + + board_display_draw_screen(frame_buf); +} + +#endif diff --git a/src/usb/usb.c b/src/usb/usb.c index 6cbfa76..30d91c0 100644 --- a/src/usb/usb.c +++ b/src/usb/usb.c @@ -43,49 +43,41 @@ extern void tusb_hal_nrf_power_event(uint32_t event); // power callback when SD is not enabled -static void power_event_handler(nrfx_power_usb_evt_t event) -{ +static void power_event_handler(nrfx_power_usb_evt_t event) { tusb_hal_nrf_power_event((uint32_t) event); } // Forward USB interrupt events to TinyUSB IRQ Handler -void USBD_IRQHandler(void) -{ +void USBD_IRQHandler(void) { tud_int_handler(0); } //------------- IMPLEMENTATION -------------// -void usb_init(bool cdc_only) -{ +void usb_init(bool cdc_only) { // 0, 1 is reserved for SD NVIC_SetPriority(USBD_IRQn, 2); // USB power may already be ready at this time -> no event generated // We need to invoke the handler based on the status initially uint32_t usb_reg; - uint8_t sd_en = false; - if ( is_sd_existed() ) - { + if (is_sd_existed()) { sd_softdevice_is_enabled(&sd_en); } - if ( sd_en ) - { + if (sd_en) { sd_power_usbdetected_enable(true); sd_power_usbpwrrdy_enable(true); sd_power_usbremoved_enable(true); - sd_power_usbregstatus_get(&usb_reg); - }else - { + } else { // Power module init - const nrfx_power_config_t pwr_cfg = { 0 }; + const nrfx_power_config_t pwr_cfg = {0}; nrfx_power_init(&pwr_cfg); // Register USB power handler - const nrfx_power_usbevt_config_t config = { .handler = power_event_handler }; + const nrfx_power_usbevt_config_t config = {.handler = power_event_handler}; nrfx_power_usbevt_init(&config); nrfx_power_usbevt_enable(); @@ -93,24 +85,25 @@ void usb_init(bool cdc_only) usb_reg = NRF_POWER->USBREGSTATUS; } - if ( usb_reg & POWER_USBREGSTATUS_VBUSDETECT_Msk ) { + if (usb_reg & POWER_USBREGSTATUS_VBUSDETECT_Msk) { tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_DETECTED); } - if ( usb_reg & POWER_USBREGSTATUS_OUTPUTRDY_Msk ) { + if (usb_reg & POWER_USBREGSTATUS_OUTPUTRDY_Msk) { tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_READY); } usb_desc_init(cdc_only); - uf2_init(); - - // Init TinyUSB stack tusb_init(); + + #ifdef DISPLAY_PIN_SCK + board_display_init(); + screen_draw_drag(); + #endif } -void usb_teardown(void) -{ +void usb_teardown(void) { // Simulate an disconnect which cause pullup disable, USB perpheral disable and hclk disable tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_REMOVED); } @@ -118,12 +111,10 @@ void usb_teardown(void) //--------------------------------------------------------------------+ // tinyusb callbacks //--------------------------------------------------------------------+ -void tud_mount_cb(void) -{ +void tud_mount_cb(void) { led_state(STATE_USB_MOUNTED); } -void tud_umount_cb(void) -{ +void tud_umount_cb(void) { led_state(STATE_USB_UNMOUNTED); } From a6a8962b1d286400b090cf2fc9d5123b653a7f69 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 5 Jan 2024 16:46:02 +0700 Subject: [PATCH 24/90] get slash screen running --- src/boards/boards.c | 48 ++++++++++++++++++++------------------------- src/boards/boards.h | 2 +- src/screen.c | 19 ++++++++++++++++-- 3 files changed, 39 insertions(+), 30 deletions(-) diff --git a/src/boards/boards.c b/src/boards/boards.c index b88d3f5..4ab04be 100644 --- a/src/boards/boards.c +++ b/src/boards/boards.c @@ -214,7 +214,7 @@ static inline void tft_dc(bool state) { } } -static void tft_cmd(uint8_t cmd, uint8_t const* data, uint8_t narg) { +static void tft_cmd(uint8_t cmd, uint8_t const* data, size_t narg) { tft_cs(false); // send command @@ -269,34 +269,20 @@ void board_display_teardown(void) { nrf_spim_disable(_spim); } -// Send the whole buffer data to display controller -extern const uint16_t color_palette[]; -void board_display_draw_screen(uint8_t const* fb) { +void board_display_draw_line(uint16_t y, uint8_t const* buf, size_t nbytes) { + // column and row address set + uint32_t xa32 = DISPLAY_COL_OFFSET << 16 | DISPLAY_WIDTH; + xa32 = __builtin_bswap32(xa32); - tft_cs(false); + y += DISPLAY_ROW_OFFSET; + uint32_t ya32 = (y << 16) | (y + 1); + ya32 = __builtin_bswap32(ya32); + + tft_cmd(0x2A, (uint8_t*) &xa32, 4); + tft_cmd(0x2B, (uint8_t*) &ya32, 4); // command: memory write - uint8_t cmd = 0x2C; - tft_dc(false); - spi_write(_spim, &cmd, 1); - - // data - tft_dc(true); - - uint8_t const* p = fb; - for (int i = 0; i < DISPLAY_WIDTH; ++i) { - uint8_t cc[DISPLAY_HEIGHT * 2]; - uint32_t dst = 0; - for (int j = 0; j < DISPLAY_HEIGHT; ++j) { - uint16_t color = color_palette[*p++ & 0xf]; - cc[dst++] = color >> 8; - cc[dst++] = color & 0xff; - } - - spi_write(_spim, cc, sizeof(cc)); - } - - tft_cs(true); + tft_cmd(0x2C, buf, nbytes); } #endif @@ -681,6 +667,14 @@ void neopixel_write (uint8_t *pixels) { } #endif +#define TFT_MADCTL_MY 0x80 ///< Page addr order: Bottom to top +#define TFT_MADCTL_MX 0x40 ///< Column addr order: Right to left +#define TFT_MADCTL_MV 0x20 ///< Page/Column order: Reverse Mode ( X <-> Y ) +#define TFT_MADCTL_ML 0x10 ///< LCD refresh Bottom to top +#define TFT_MADCTL_MH 0x04 ///< LCD refresh right to left +#define TFT_MADCTL_RGB 0x00 ///< Red-Green-Blue pixel order +#define TFT_MADCTL_BGR 0x08 ///< Blue-Green-Red pixel order + #ifdef DISPLAY_CONTROLLER_ST7789 #define ST_CMD_DELAY 0x80 // special signifier for command lists @@ -742,7 +736,7 @@ static void tft_controller_init(void) { // 3: Set color mode, 1 arg + delay: 16-bit color, 10 ms delay ST77XX_COLMOD, 1 + ST_CMD_DELAY, 0x55, 10, // 4: Mem access ctrl (directions), 1 arg: Row/col addr, bottom-top refresh - ST77XX_MADCTL, 1, 0x08, + ST77XX_MADCTL, 1, DISPLAY_MADCTL, // 5: Column addr set, 4 args, no delay: XSTART = 0, XEND = 240 ST77XX_CASET, 4, 0x00, 0, 0, 240, // 6: Row addr set, 4 args, no delay: YSTART = 0 YEND = 320 diff --git a/src/boards/boards.h b/src/boards/boards.h index e5bf3d8..26a3e13 100644 --- a/src/boards/boards.h +++ b/src/boards/boards.h @@ -120,7 +120,7 @@ bool is_ota(void); #ifdef DISPLAY_PIN_SCK void board_display_init(void); void board_display_teardown(void); -void board_display_draw_screen(uint8_t const* fb); +void board_display_draw_line(uint16_t y, uint8_t const* buf, size_t nbytes); void screen_draw_drag(void); #endif diff --git a/src/screen.c b/src/screen.c index adf2198..8931b55 100644 --- a/src/screen.c +++ b/src/screen.c @@ -53,7 +53,7 @@ enum { }; // 16-bit 565 color from 24-bit 888 format -const uint16_t color_palette[] = { +const uint16_t palette[] = { COL(0x000000), // 0 COL(0xffffff), // 1 COL(0xff2121), // 2 @@ -214,6 +214,21 @@ static void print4(int x, int y, int color, const char* text) { // //--------------------------------------------------------------------+ +static void draw_screen(uint8_t const* fb) { + uint8_t const* p = fb; + for (int y = 0; y < DISPLAY_WIDTH; ++y) { + uint8_t cc[DISPLAY_HEIGHT * 2]; + uint32_t dst = 0; + for (int x = 0; x < DISPLAY_HEIGHT; ++x) { + uint16_t color = palette[*p++ & 0xf]; + cc[dst++] = color >> 8; + cc[dst++] = color & 0xff; + } + + board_display_draw_line(y, cc, sizeof(cc)); + } +} + // draw color bar static void drawBar(int y, int h, int color) { for (int x = 0; x < DISPLAY_WIDTH; ++x) { @@ -245,7 +260,7 @@ void screen_draw_drag(void) { print(10, DRAG - 12, COLOR_WHITE, "firmware.uf2"); print(90, DRAG - 12, COLOR_WHITE, UF2_VOLUME_LABEL); - board_display_draw_screen(frame_buf); + draw_screen(frame_buf); } #endif From 0eead42aec954565a4d338b3da0edd94493a9493 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 5 Jan 2024 16:59:16 +0700 Subject: [PATCH 25/90] add display for sense tft --- Makefile | 3 ++ src/boards/boards.c | 42 +++++++++---------- src/boards/feather_nrf52840_sense_tft/board.h | 28 ++++++++++++- 3 files changed, 49 insertions(+), 24 deletions(-) diff --git a/Makefile b/Makefile index 866d4a6..17fa105 100644 --- a/Makefile +++ b/Makefile @@ -139,6 +139,8 @@ C_SRC += \ src/dfu_init.c \ src/flash_nrf5x.c \ src/main.c \ + src/screen.c \ + src/images.c \ # all files in boards C_SRC += src/boards/boards.c @@ -314,6 +316,7 @@ ifneq ($(USE_NFCT),yes) endif CFLAGS += -DSOFTDEVICE_PRESENT +CFLAGS += -DUF2_VERSION_BASE='"$(GIT_VERSION)"' CFLAGS += -DUF2_VERSION='"$(GIT_VERSION) $(GIT_SUBMODULE_VERSIONS)"' CFLAGS += -DBLEDIS_FW_VERSION='"$(GIT_VERSION) $(SD_NAME) $(SD_VERSION)"' diff --git a/src/boards/boards.c b/src/boards/boards.c index 4ab04be..563ed6f 100644 --- a/src/boards/boards.c +++ b/src/boards/boards.c @@ -181,6 +181,14 @@ void board_teardown(void) { //--------------------------------------------------------------------+ #ifdef DISPLAY_PIN_SCK +#define TFT_MADCTL_MY 0x80 ///< Page addr order: Bottom to top +#define TFT_MADCTL_MX 0x40 ///< Column addr order: Right to left +#define TFT_MADCTL_MV 0x20 ///< Page/Column order: Reverse Mode ( X <-> Y ) +#define TFT_MADCTL_ML 0x10 ///< LCD refresh Bottom to top +#define TFT_MADCTL_MH 0x04 ///< LCD refresh right to left +#define TFT_MADCTL_RGB 0x00 ///< Red-Green-Blue pixel order +#define TFT_MADCTL_BGR 0x08 ///< Blue-Green-Red pixel order + // Note don't use SPIM3 since it has lots of errata NRF_SPIM_Type* _spim = NRF_SPIM0; @@ -199,19 +207,11 @@ static void spi_write(NRF_SPIM_Type *p_spim, uint8_t const *tx_buf, size_t tx_le static void tft_controller_init(void); static inline void tft_cs(bool state) { - if (state) { - nrf_gpio_pin_set(DISPLAY_PIN_CS); - } else { - nrf_gpio_pin_clear(DISPLAY_PIN_CS); - } + nrf_gpio_pin_write(DISPLAY_PIN_CS, state); } static inline void tft_dc(bool state) { - if (state) { - nrf_gpio_pin_set(DISPLAY_PIN_DC); - } else { - nrf_gpio_pin_clear(DISPLAY_PIN_DC); - } + nrf_gpio_pin_write(DISPLAY_PIN_DC, state); } static void tft_cmd(uint8_t cmd, uint8_t const* data, size_t narg) { @@ -250,17 +250,17 @@ void board_display_init(void) { //------------- Display Init -------------// nrf_gpio_cfg_output(DISPLAY_PIN_DC); - #if defined(DISPLAY_PIN_RST) && DISPLAY_PIN_RST >= 0 +#if defined(DISPLAY_PIN_RST) && DISPLAY_PIN_RST >= 0 nrf_gpio_cfg_output(DISPLAY_PIN_RST); - nrf_gpio_pin_write(DISPLAY_PIN_RST, 0); + nrf_gpio_pin_clear(DISPLAY_PIN_RST); NRFX_DELAY_MS(10); - nrf_gpio_pin_write(DISPLAY_PIN_RST, 1); - #endif + nrf_gpio_pin_set(DISPLAY_PIN_RST); +#endif - #if defined(DISPLAY_PIN_BL) && DISPLAY_PIN_BL >= 0 +#if defined(DISPLAY_PIN_BL) && DISPLAY_PIN_BL >= 0 nrf_gpio_cfg_output(DISPLAY_PIN_BL); nrf_gpio_pin_write(DISPLAY_PIN_BL, DISPLAY_BL_ON); - #endif +#endif tft_controller_init(); } @@ -667,13 +667,9 @@ void neopixel_write (uint8_t *pixels) { } #endif -#define TFT_MADCTL_MY 0x80 ///< Page addr order: Bottom to top -#define TFT_MADCTL_MX 0x40 ///< Column addr order: Right to left -#define TFT_MADCTL_MV 0x20 ///< Page/Column order: Reverse Mode ( X <-> Y ) -#define TFT_MADCTL_ML 0x10 ///< LCD refresh Bottom to top -#define TFT_MADCTL_MH 0x04 ///< LCD refresh right to left -#define TFT_MADCTL_RGB 0x00 ///< Red-Green-Blue pixel order -#define TFT_MADCTL_BGR 0x08 ///< Blue-Green-Red pixel order +//--------------------------------------------------------------------+ +// Display controller +//--------------------------------------------------------------------+ #ifdef DISPLAY_CONTROLLER_ST7789 diff --git a/src/boards/feather_nrf52840_sense_tft/board.h b/src/boards/feather_nrf52840_sense_tft/board.h index 3dcea99..902e75c 100644 --- a/src/boards/feather_nrf52840_sense_tft/board.h +++ b/src/boards/feather_nrf52840_sense_tft/board.h @@ -47,6 +47,32 @@ #define BUTTON_2 _PINNUM(1, 10) // DFU pin #define BUTTON_PULL NRF_GPIO_PIN_PULLUP +//--------------------------------------------------------------------+ +// Display +//--------------------------------------------------------------------+ +#define DISPLAY_CONTROLLER_ST7789 + +#define DISPLAY_PIN_MOSI _PINNUM(0, 5) +#define DISPLAY_PIN_SCK _PINNUM(0, 26) + +#define DISPLAY_PIN_CS _PINNUM(1, 5) +#define DISPLAY_PIN_DC _PINNUM(1, 1) +#define DISPLAY_PIN_RST _PINNUM(1, 3) +#define DISPLAY_PIN_BL _PINNUM(0, 27) +#define DISPLAY_BL_ON 1 // GPIO state to enable back light + +#define DISPLAY_WIDTH 240 +#define DISPLAY_HEIGHT 135 + +#define DISPLAY_COL_OFFSET 53 +#define DISPLAY_ROW_OFFSET 40 + +// Memory Data Access Control & // Vertical Scroll Start Address +#define DISPLAY_MADCTL (TFT_MADCTL_MX) +#define DISPLAY_VSCSAD 0 + +#define DISPLAY_TITLE "Sense TFT" + //--------------------------------------------------------------------+ // BLE OTA //--------------------------------------------------------------------+ @@ -62,7 +88,7 @@ //------------- UF2 -------------// #define UF2_PRODUCT_NAME "Adafruit Feather nRF52840 Sense TFT" -#define UF2_VOLUME_LABEL "FTHRSNSBOOT" +#define UF2_VOLUME_LABEL "SENSTFTBOOT" #define UF2_BOARD_ID "nRF52840-FeatherSenseTFT-revA" #define UF2_INDEX_URL "https://www.adafruit.com/product/" From ed9bf7a8dd2590face6cc173e2239709b6804805 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 5 Jan 2024 17:25:53 +0700 Subject: [PATCH 26/90] fix ci --- src/boards/boards.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boards/boards.c b/src/boards/boards.c index 563ed6f..b9ed2c0 100644 --- a/src/boards/boards.c +++ b/src/boards/boards.c @@ -24,7 +24,6 @@ #include "boards.h" #include "nrf_pwm.h" -#include "nrf_spim.h" #include "app_scheduler.h" #include "app_timer.h" @@ -180,6 +179,7 @@ void board_teardown(void) { // Display //--------------------------------------------------------------------+ #ifdef DISPLAY_PIN_SCK +#include "nrf_spim.h" #define TFT_MADCTL_MY 0x80 ///< Page addr order: Bottom to top #define TFT_MADCTL_MX 0x40 ///< Column addr order: Right to left From 3d920bf62b57b2c82b24ac2545dc1a94225e8285 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 5 Jan 2024 19:06:01 +0700 Subject: [PATCH 27/90] - add slash screen for CLUE - optimize ST77XX_SWRESET, skip if reset pin is available. --- CMakeLists.txt | 13 +++++++++- src/boards/boards.c | 24 ++++++++++------- .../circuitplayground_nrf52840/board.cmake | 1 + src/boards/clue_nrf52840/board.cmake | 1 + src/boards/clue_nrf52840/board.h | 26 +++++++++++++++++++ src/boards/feather_nrf52840_sense_tft/board.h | 2 +- 6 files changed, 56 insertions(+), 11 deletions(-) create mode 100644 src/boards/circuitplayground_nrf52840/board.cmake create mode 100644 src/boards/clue_nrf52840/board.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index a124031..08ff5c2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,5 @@ cmake_minimum_required(VERSION 3.17) +find_package(Python COMPONENTS Interpreter) if (NOT DEFINED BOARD) message(FATAL_ERROR "BOARD is not defined") @@ -30,6 +31,9 @@ set(SDK ${CMAKE_CURRENT_LIST_DIR}/lib/sdk/components) set(SOFTDEVICE ${CMAKE_CURRENT_LIST_DIR}/lib/softdevice) set(TUSB ${CMAKE_CURRENT_LIST_DIR}/lib/tinyusb/src) +set(UF2CONV_PY ${CMAKE_CURRENT_LIST_DIR}/lib/uf2/utils/uf2conv.py) +set(UF2_FAMILY_ID_BOOTLOADER 0xd663823c) + #------------------- # Bootloader #------------------- @@ -301,6 +305,8 @@ add_custom_command(TARGET bootloader POST_BUILD add_custom_command(TARGET bootloader POST_BUILD COMMAND ${CMAKE_OBJCOPY} -Obinary $ $/bootloader.bin COMMAND ${CMAKE_OBJCOPY} -Oihex $ $/bootloader.hex + COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/tools/hexmerge.py --overlap=replace -o $/bootloader_mbr.hex $/bootloader.hex ${MBR_HEX} + COMMAND ${Python_EXECUTABLE} ${UF2CONV_PY} -f ${UF2_FAMILY_ID_BOOTLOADER} -c -o $/bootloader_mbr.uf2 $/bootloader_mbr.hex VERBATIM) #---------------------------------- @@ -311,11 +317,16 @@ if (NOT DEFINED NRFJPROG) set(NRFJPROG nrfjprog) endif() -add_custom_target(flash +add_custom_target(flash-jlink DEPENDS bootloader COMMAND ${NRFJPROG} --program $ --verify --sectoranduicrerase -f nrf52 --reset ) +add_custom_target(flash-uf2 + DEPENDS bootloader + COMMAND ${Python_EXECUTABLE} ${UF2CONV_PY} -f ${UF2_FAMILY_ID_BOOTLOADER} --deploy $/bootloader_mbr.uf2 + ) + add_custom_target(flash-sd COMMAND ${NRFJPROG} --program ${SD_HEX} --verify --sectorerase -f nrf52 --reset ) diff --git a/src/boards/boards.c b/src/boards/boards.c index b9ed2c0..74840bf 100644 --- a/src/boards/boards.c +++ b/src/boards/boards.c @@ -255,6 +255,7 @@ void board_display_init(void) { nrf_gpio_pin_clear(DISPLAY_PIN_RST); NRFX_DELAY_MS(10); nrf_gpio_pin_set(DISPLAY_PIN_RST); + NRFX_DELAY_MS(20); #endif #if defined(DISPLAY_PIN_BL) && DISPLAY_PIN_BL >= 0 @@ -698,6 +699,7 @@ void neopixel_write (uint8_t *pixels) { #define ST77XX_TEOFF 0x34 #define ST77XX_TEON 0x35 #define ST77XX_MADCTL 0x36 +#define ST77XX_VSCSAD 0x37 #define ST77XX_COLMOD 0x3A #define ST77XX_MADCTL_MY 0x80 @@ -725,23 +727,27 @@ void neopixel_write (uint8_t *pixels) { static void tft_controller_init(void) { // Init commands for 7789 screens uint8_t cmdinit_st7789[] = { - // 1: Software reset, no args, w/delay ~150 ms delay + #if !defined(DISPLAY_PIN_RST) || (DISPLAY_PIN_RST < 0) + // Software reset if rst pin not available, no args, w/delay ~150 ms delay ST77XX_SWRESET, ST_CMD_DELAY, 150, - // 2: Out of sleep mode, no args, w/delay 10 ms delay + #endif + // Out of sleep mode, no args, w/delay 10 ms delay ST77XX_SLPOUT, ST_CMD_DELAY, 10, - // 3: Set color mode, 1 arg + delay: 16-bit color, 10 ms delay + // Set color mode, 1 arg + delay: 16-bit color, 10 ms delay ST77XX_COLMOD, 1 + ST_CMD_DELAY, 0x55, 10, - // 4: Mem access ctrl (directions), 1 arg: Row/col addr, bottom-top refresh + // Mem access ctrl (directions), 1 arg: Row/col addr, bottom-top refresh ST77XX_MADCTL, 1, DISPLAY_MADCTL, - // 5: Column addr set, 4 args, no delay: XSTART = 0, XEND = 240 + // Vertical Scroll Start Address of RAM + // ST77XX_VSCSAD, 2, DISPLAY_VSCSAD >> 8, DISPLAY_VSCSAD & 0xFF, + // Column addr set, 4 args, no delay: XSTART = 0, XEND = 240 ST77XX_CASET, 4, 0x00, 0, 0, 240, - // 6: Row addr set, 4 args, no delay: YSTART = 0 YEND = 320 + // Row addr set, 4 args, no delay: YSTART = 0 YEND = 320 ST77XX_RASET, 4, 0x00, 0, 320 >> 8, 320 & 0xFF, - // 7: hack + // Inversion on ST77XX_INVON, ST_CMD_DELAY, 10, - // 8: Normal display on, no args, w/delay 10 ms delay + // Normal display on, no args, w/delay 10 ms delay ST77XX_NORON, ST_CMD_DELAY, 10, - // 9: Main screen turn on, no args, delay 10 ms delay + // Main screen turn on, no args, delay 10 ms delay ST77XX_DISPON, ST_CMD_DELAY, 10 }; diff --git a/src/boards/circuitplayground_nrf52840/board.cmake b/src/boards/circuitplayground_nrf52840/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/circuitplayground_nrf52840/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/clue_nrf52840/board.cmake b/src/boards/clue_nrf52840/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/clue_nrf52840/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/clue_nrf52840/board.h b/src/boards/clue_nrf52840/board.h index efba060..818f2f4 100644 --- a/src/boards/clue_nrf52840/board.h +++ b/src/boards/clue_nrf52840/board.h @@ -46,6 +46,32 @@ #define BUTTON_2 _PINNUM(1, 10) // right button #define BUTTON_PULL NRF_GPIO_PIN_PULLUP +//--------------------------------------------------------------------+ +// Display +//--------------------------------------------------------------------+ +#define DISPLAY_CONTROLLER_ST7789 + +#define DISPLAY_PIN_SCK _PINNUM(0, 14) +#define DISPLAY_PIN_MOSI _PINNUM(0, 15) + +#define DISPLAY_PIN_CS _PINNUM(0, 12) +#define DISPLAY_PIN_DC _PINNUM(0, 13) +#define DISPLAY_PIN_RST _PINNUM(1, 3) +#define DISPLAY_PIN_BL _PINNUM(1, 5) +#define DISPLAY_BL_ON 1 // GPIO state to enable back light + +#define DISPLAY_WIDTH 240 +#define DISPLAY_HEIGHT 240 + +#define DISPLAY_COL_OFFSET 0 +#define DISPLAY_ROW_OFFSET 80 + +// Memory Data Access Control & // Vertical Scroll Start Address +#define DISPLAY_MADCTL (TFT_MADCTL_MY) +#define DISPLAY_VSCSAD 0 + +#define DISPLAY_TITLE "CLUE" + //--------------------------------------------------------------------+ // BLE OTA //--------------------------------------------------------------------+ diff --git a/src/boards/feather_nrf52840_sense_tft/board.h b/src/boards/feather_nrf52840_sense_tft/board.h index 902e75c..b78e251 100644 --- a/src/boards/feather_nrf52840_sense_tft/board.h +++ b/src/boards/feather_nrf52840_sense_tft/board.h @@ -52,8 +52,8 @@ //--------------------------------------------------------------------+ #define DISPLAY_CONTROLLER_ST7789 -#define DISPLAY_PIN_MOSI _PINNUM(0, 5) #define DISPLAY_PIN_SCK _PINNUM(0, 26) +#define DISPLAY_PIN_MOSI _PINNUM(0, 5) #define DISPLAY_PIN_CS _PINNUM(1, 5) #define DISPLAY_PIN_DC _PINNUM(1, 1) From 59df4f9e8caabb6925f5b89b3d1e9ba98663ee7b Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 29 Jan 2024 16:41:46 +0700 Subject: [PATCH 28/90] add & enable DISPLAY_VSENSOR_PIN if available (required for sense tft) --- src/boards/boards.c | 7 ++++++- src/boards/feather_nrf52840_sense_tft/board.h | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/boards/boards.c b/src/boards/boards.c index 74840bf..e1b39f3 100644 --- a/src/boards/boards.c +++ b/src/boards/boards.c @@ -250,6 +250,11 @@ void board_display_init(void) { //------------- Display Init -------------// nrf_gpio_cfg_output(DISPLAY_PIN_DC); +#if defined(DISPLAY_VSENSOR_PIN) && DISPLAY_VSENSOR_PIN >= 0 + nrf_gpio_cfg_output(DISPLAY_VSENSOR_PIN); + nrf_gpio_pin_write(DISPLAY_VSENSOR_PIN, DISPLAY_VSENSOR_ON); +#endif + #if defined(DISPLAY_PIN_RST) && DISPLAY_PIN_RST >= 0 nrf_gpio_cfg_output(DISPLAY_PIN_RST); nrf_gpio_pin_clear(DISPLAY_PIN_RST); @@ -771,4 +776,4 @@ static void tft_controller_init(void) { } } -#endif \ No newline at end of file +#endif diff --git a/src/boards/feather_nrf52840_sense_tft/board.h b/src/boards/feather_nrf52840_sense_tft/board.h index b78e251..1fa03bd 100644 --- a/src/boards/feather_nrf52840_sense_tft/board.h +++ b/src/boards/feather_nrf52840_sense_tft/board.h @@ -50,6 +50,11 @@ //--------------------------------------------------------------------+ // Display //--------------------------------------------------------------------+ + +// VSensor required to power the display +#define DISPLAY_VSENSOR_PIN _PINNUM(1, 7) +#define DISPLAY_VSENSOR_ON 1 + #define DISPLAY_CONTROLLER_ST7789 #define DISPLAY_PIN_SCK _PINNUM(0, 26) From 4f8c2afabfe9c5b9cdf7e7e3fc766c69ec5e572d Mon Sep 17 00:00:00 2001 From: Said Alvarado-Marin Date: Sun, 4 Feb 2024 14:33:02 +0100 Subject: [PATCH 29/90] fix compilation for arm-none-eabi-gcc version 13 --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 17fa105..2f1ad99 100644 --- a/Makefile +++ b/Makefile @@ -342,7 +342,8 @@ endif CFLAGS += -DDFU_APP_DATA_RESERVED=$(DFU_APP_DATA_RESERVED) # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105523 -ifneq ($(findstring 12.,$(shell $(CC) --version 2>/dev/null)),) +# Fixes for gcc version 12 and 13. +ifneq (,$(filter 12.% 13.%,$(shell $(CC) -dumpversion 2>/dev/null))) CFLAGS += --param=min-pagesize=0 endif From 78b39b4347fdc6bfb96d07a32b97b20c9c936e5d Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 9 May 2024 19:56:52 +0700 Subject: [PATCH 30/90] bump up gcc to 12.3Rel1 --- .github/workflows/githubci.yml | 2 +- CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/githubci.yml b/.github/workflows/githubci.yml index 5d8b275..8ed72ee 100644 --- a/.github/workflows/githubci.yml +++ b/.github/workflows/githubci.yml @@ -82,7 +82,7 @@ jobs: - name: Install ARM GCC uses: carlosperate/arm-none-eabi-gcc-action@v1 with: - release: '10-2020-q4' + release: '12.3.Rel1' - name: Install Tools run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index 08ff5c2..c0ae6f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -167,7 +167,7 @@ target_compile_options(bootloader PUBLIC -Wno-endif-labels -Wunreachable-code # Suppress warning caused by SDK - -Wno-unused-parameter -Wno-expansion-to-defined + -Wno-unused-parameter -Wno-expansion-to-defined -Wno-array-bounds ) target_compile_definitions(bootloader PUBLIC SOFTDEVICE_PRESENT From 0bc8a8993f6b7b9a175bc1ba9aafa26f5e534122 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 9 May 2024 20:15:16 +0700 Subject: [PATCH 31/90] - add P1.14 as NEOPIXEL_POWER_PIN for feather nrf52840 revE - remove linkermap from ci --- .github/workflows/githubci.yml | 15 ++------------- src/boards/feather_nrf52840_express/board.h | 3 ++- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/.github/workflows/githubci.yml b/.github/workflows/githubci.yml index 8ed72ee..a31f84e 100644 --- a/.github/workflows/githubci.yml +++ b/.github/workflows/githubci.yml @@ -65,7 +65,7 @@ jobs: steps: - name: Setup Python - uses: actions/setup-python@v3 + uses: actions/setup-python@v5 - name: Checkout Code uses: actions/checkout@v4 @@ -73,12 +73,6 @@ jobs: fetch-depth: 0 submodules: true - - name: Checkout linkermap - uses: actions/checkout@v4 - with: - repository: hathach/linkermap - path: linkermap - - name: Install ARM GCC uses: carlosperate/arm-none-eabi-gcc-action@v1 with: @@ -87,18 +81,13 @@ jobs: - name: Install Tools run: | pip3 install adafruit-nrfutil uritemplate requests intelhex setuptools - pip3 install linkermap/ - name: Build run: | - arm-none-eabi-gcc --version make BOARD=${{ matrix.board }} all make BOARD=${{ matrix.board }} copy-artifact - - name: Linker Map - run: make BOARD=${{ matrix.board }} linkermap - - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: name: ${{ matrix.board }} path: _bin/${{ matrix.board }} diff --git a/src/boards/feather_nrf52840_express/board.h b/src/boards/feather_nrf52840_express/board.h index 3be5593..49994f0 100644 --- a/src/boards/feather_nrf52840_express/board.h +++ b/src/boards/feather_nrf52840_express/board.h @@ -36,6 +36,7 @@ #define LED_STATE_ON 1 #define LED_NEOPIXEL _PINNUM(0, 16) +#define NEOPIXEL_POWER_PIN _PINNUM(1, 14) #define NEOPIXELS_NUMBER 1 #define BOARD_RGB_BRIGHTNESS 0x040404 @@ -63,7 +64,7 @@ //------------- UF2 -------------// #define UF2_PRODUCT_NAME "Adafruit Feather nRF52840 Express" #define UF2_VOLUME_LABEL "FTHR840BOOT" -#define UF2_BOARD_ID "nRF52840-Feather-revD" +#define UF2_BOARD_ID "nRF52840-Feather-revE" #define UF2_INDEX_URL "https://www.adafruit.com/product/4062" #endif // _FEATHER_NRF52840_H From ea3bb737deda02e554e7a9f77e3367b16ebd7036 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 9 May 2024 20:17:33 +0700 Subject: [PATCH 32/90] fix ci warning --- .github/workflows/githubci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/githubci.yml b/.github/workflows/githubci.yml index a31f84e..7174e41 100644 --- a/.github/workflows/githubci.yml +++ b/.github/workflows/githubci.yml @@ -66,6 +66,8 @@ jobs: steps: - name: Setup Python uses: actions/setup-python@v5 + with: + python-version: '3.x' - name: Checkout Code uses: actions/checkout@v4 From 9e25f4ac0abe98d02b4eccc51ac01be119a91f85 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 9 May 2024 20:40:04 +0700 Subject: [PATCH 33/90] use script to set board matrix --- .github/workflows/githubci.yml | 67 +++++++++------------------------- 1 file changed, 18 insertions(+), 49 deletions(-) diff --git a/.github/workflows/githubci.yml b/.github/workflows/githubci.yml index 7174e41..658cff5 100644 --- a/.github/workflows/githubci.yml +++ b/.github/workflows/githubci.yml @@ -9,60 +9,29 @@ on: - created jobs: + set-matrix: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Set matrix + id: set-matrix + working-directory: src/boards + run: | + MATRIX_JSON=$(ls -d */ | sed 's/\/$//' | jq -R -s -c 'split("\n")[:-1]') + echo "matrix=$MATRIX_JSON" + echo "matrix=$MATRIX_JSON" >> $GITHUB_OUTPUT + build: + needs: set-matrix runs-on: ubuntu-latest strategy: fail-fast: false matrix: - board: - # Adafruit Boards - - 'circuitplayground_nrf52840' - - 'clue_nrf52840' - - 'feather_nrf52832' - - 'feather_nrf52833_express' - - 'feather_nrf52840_express' - - 'feather_nrf52840_sense' - - 'feather_nrf52840_sense_tft' - - 'itsybitsy_nrf52840_express' - - 'metro_nrf52840_express' - - 'ledglasses_nrf52840' - # Other Makers (Alphabetical order) - - 'adm_b_nrf52840_1' - - 'ae_bl652_bo' - - 'aramcon_badge_2019' - - 'aramcon2_badge' - - 'arcade_feather_nrf52840_express' - - 'arduino_nano_33_ble' - - 'bast_ble' - - 'bluemicro_nrf52833' - - 'bluemicro_nrf52840' - - 'challenger_840_ble' - - 'ebyte_e104_bt5032a' - - 'ebyte_e73_tbb' - - 'electronut_labs_papyr' - - 'ikigaisense_vita' - - 'm60_keyboard' - - 'mdk_nrf52840_dongle' - - 'mikoto' - - 'nice_nano' - - 'nrf52840_bboard' - - 'nRF52840_connect_kit' - - 'nrf52840_m2' - - 'ohs2020_badge' - - 'particle_argon' - - 'particle_boron' - - 'particle_xenon' - - 'pca10056' - - 'pca10059' - - 'pca10100' - - 'pitaya_go' - - 'raytac_mdbt50q_db_40' - - 'raytac_mdbt50q_rx' - - 'sparkfun_nrf52840_micromod' - - 'waveshare_nrf52840_eval' - - 'xiao_nrf52840_ble' - - 'xiao_nrf52840_ble_sense' - + board: ${{ fromJSON(needs.set-matrix.outputs.matrix) }} steps: - name: Setup Python uses: actions/setup-python@v5 From 2d68ec56e3de2c692c6c02de1921d04d14ba6c93 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 5 Jun 2024 17:29:26 +0700 Subject: [PATCH 34/90] default SD version to 7.3.0 for 833, 6.1.1 for 840 and 832 some cmake rename --- .github/workflows/githubci.yml | 7 +- CMakeLists.txt | 150 ++++++++++++++++---------------- Makefile | 24 ++--- src/boards/pca10100/board.cmake | 1 + src/boards/pca10100/board.mk | 3 +- 5 files changed, 84 insertions(+), 101 deletions(-) create mode 100644 src/boards/pca10100/board.cmake diff --git a/.github/workflows/githubci.yml b/.github/workflows/githubci.yml index 658cff5..103ecaa 100644 --- a/.github/workflows/githubci.yml +++ b/.github/workflows/githubci.yml @@ -33,15 +33,10 @@ jobs: matrix: board: ${{ fromJSON(needs.set-matrix.outputs.matrix) }} steps: - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: '3.x' - - name: Checkout Code uses: actions/checkout@v4 with: - fetch-depth: 0 + fetch-tags: true submodules: true - name: Install ARM GCC diff --git a/CMakeLists.txt b/CMakeLists.txt index c0ae6f2..567a815 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,11 +25,11 @@ set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/cmake/toolchain/arm_${TOOLCHA project(Adafruit_nRF52_Bootloader C ASM) -set(NRFX ${CMAKE_CURRENT_LIST_DIR}/lib/nrfx) -set(SDK11 ${CMAKE_CURRENT_LIST_DIR}/lib/sdk11/components) -set(SDK ${CMAKE_CURRENT_LIST_DIR}/lib/sdk/components) -set(SOFTDEVICE ${CMAKE_CURRENT_LIST_DIR}/lib/softdevice) -set(TUSB ${CMAKE_CURRENT_LIST_DIR}/lib/tinyusb/src) +set(NRFX_DIR ${CMAKE_CURRENT_LIST_DIR}/lib/nrfx) +set(SDK11_DIR ${CMAKE_CURRENT_LIST_DIR}/lib/sdk11/components) +set(SDK_DIR ${CMAKE_CURRENT_LIST_DIR}/lib/sdk/components) +set(SOFTDEVICE_DIR ${CMAKE_CURRENT_LIST_DIR}/lib/softdevice) +set(TINYUSB_DIR ${CMAKE_CURRENT_LIST_DIR}/lib/tinyusb/src) set(UF2CONV_PY ${CMAKE_CURRENT_LIST_DIR}/lib/uf2/utils/uf2conv.py) set(UF2_FAMILY_ID_BOOTLOADER 0xd663823c) @@ -42,10 +42,14 @@ add_executable(bootloader) # SD_VERSION can be overwritten by board.cmake if(NOT DEFINED SD_VERSION) - set(SD_VERSION 6.1.1) + if(MCU_VARIANT STREQUAL "nrf52833") + set(SD_VERSION 7.3.0) + else() + set(SD_VERSION 6.1.1) + endif() endif () -set(MBR_HEX ${SOFTDEVICE}/mbr/hex/mbr_nrf52_2.4.1_mbr.hex) +set(MBR_HEX ${SOFTDEVICE_DIR}/mbr/hex/mbr_nrf52_2.4.1_mbr.hex) target_sources(bootloader PUBLIC # src @@ -57,31 +61,31 @@ target_sources(bootloader PUBLIC src/images.c src/boards/boards.c # nrfx - ${NRFX}/drivers/src/nrfx_power.c - ${NRFX}/drivers/src/nrfx_nvmc.c - ${NRFX}/mdk/system_${MCU_VARIANT}.c + ${NRFX_DIR}/drivers/src/nrfx_power.c + ${NRFX_DIR}/drivers/src/nrfx_nvmc.c + ${NRFX_DIR}/mdk/system_${MCU_VARIANT}.c # sdk 11 - ${SDK11}/libraries/bootloader_dfu/bootloader.c - ${SDK11}/libraries/bootloader_dfu/bootloader_settings.c - ${SDK11}/libraries/bootloader_dfu/bootloader_util.c - ${SDK11}/libraries/bootloader_dfu/dfu_transport_serial.c - ${SDK11}/libraries/bootloader_dfu/dfu_transport_ble.c - ${SDK11}/libraries/bootloader_dfu/dfu_single_bank.c - ${SDK11}/ble/ble_services/ble_dfu/ble_dfu.c - ${SDK11}/ble/ble_services/ble_dis/ble_dis.c - ${SDK11}/drivers_nrf/pstorage/pstorage_raw.c + ${SDK11_DIR}/libraries/bootloader_dfu/bootloader.c + ${SDK11_DIR}/libraries/bootloader_dfu/bootloader_settings.c + ${SDK11_DIR}/libraries/bootloader_dfu/bootloader_util.c + ${SDK11_DIR}/libraries/bootloader_dfu/dfu_transport_serial.c + ${SDK11_DIR}/libraries/bootloader_dfu/dfu_transport_ble.c + ${SDK11_DIR}/libraries/bootloader_dfu/dfu_single_bank.c + ${SDK11_DIR}/ble/ble_services/ble_dfu/ble_dfu.c + ${SDK11_DIR}/ble/ble_services/ble_dis/ble_dis.c + ${SDK11_DIR}/drivers_nrf/pstorage/pstorage_raw.c # latest sdk - ${SDK}/libraries/timer/app_timer.c - ${SDK}/libraries/scheduler/app_scheduler.c - ${SDK}/libraries/util/app_error.c - ${SDK}/libraries/util/app_util_platform.c - ${SDK}/libraries/crc16/crc16.c - ${SDK}/libraries/hci/hci_mem_pool.c - ${SDK}/libraries/hci/hci_slip.c - ${SDK}/libraries/hci/hci_transport.c - ${SDK}/libraries/util/nrf_assert.c + ${SDK_DIR}/libraries/timer/app_timer.c + ${SDK_DIR}/libraries/scheduler/app_scheduler.c + ${SDK_DIR}/libraries/util/app_error.c + ${SDK_DIR}/libraries/util/app_util_platform.c + ${SDK_DIR}/libraries/crc16/crc16.c + ${SDK_DIR}/libraries/hci/hci_mem_pool.c + ${SDK_DIR}/libraries/hci/hci_slip.c + ${SDK_DIR}/libraries/hci/hci_transport.c + ${SDK_DIR}/libraries/util/nrf_assert.c # ASM - ${NRFX}/mdk/gcc_startup_${MCU_VARIANT}.S + ${NRFX_DIR}/mdk/gcc_startup_${MCU_VARIANT}.S ) target_include_directories(bootloader PUBLIC src @@ -89,31 +93,31 @@ target_include_directories(bootloader PUBLIC src/boards/${BOARD} src/cmsis/include src/usb - ${TUSB} + ${TINYUSB_DIR} # nrfx - ${NRFX} - ${NRFX}/mdk - ${NRFX}/hal - ${NRFX}/drivers/include - ${NRFX}/drivers/src + ${NRFX_DIR} + ${NRFX_DIR}/mdk + ${NRFX_DIR}/hal + ${NRFX_DIR}/drivers/include + ${NRFX_DIR}/drivers/src # sdk 11 for cdc/ble dfu - ${SDK11}/libraries/bootloader_dfu - ${SDK11}/libraries/bootloader_dfu/hci_transport - ${SDK11}/drivers_nrf/pstorage - ${SDK11}/ble/common - ${SDK11}/ble/ble_services/ble_dfu - ${SDK11}/ble/ble_services/ble_dis + ${SDK11_DIR}/libraries/bootloader_dfu + ${SDK11_DIR}/libraries/bootloader_dfu/hci_transport + ${SDK11_DIR}/drivers_nrf/pstorage + ${SDK11_DIR}/ble/common + ${SDK11_DIR}/ble/ble_services/ble_dfu + ${SDK11_DIR}/ble/ble_services/ble_dis # later sdk with updated drivers - ${SDK}/libraries/timer - ${SDK}/libraries/scheduler - ${SDK}/libraries/crc16 - ${SDK}/libraries/util - ${SDK}/libraries/hci/config - ${SDK}/libraries/hci - ${SDK}/libraries/uart - ${SDK}/drivers_nrf/delay + ${SDK_DIR}/libraries/timer + ${SDK_DIR}/libraries/scheduler + ${SDK_DIR}/libraries/crc16 + ${SDK_DIR}/libraries/util + ${SDK_DIR}/libraries/hci/config + ${SDK_DIR}/libraries/hci + ${SDK_DIR}/libraries/uart + ${SDK_DIR}/drivers_nrf/delay # Softdevice - ${SOFTDEVICE}/mbr/headers + ${SOFTDEVICE_DIR}/mbr/headers ) # Debug option @@ -145,7 +149,7 @@ endif () target_link_options(bootloader PUBLIC "LINKER:--script=${LD_FILE}" - -L${NRFX}/mdk + -L${NRFX_DIR}/mdk --specs=nosys.specs --specs=nano.specs ) target_compile_options(bootloader PUBLIC @@ -181,14 +185,14 @@ endif () if (MCU_VARIANT STREQUAL "nrf52") # UART transport target_sources(bootloader PUBLIC - ${SDK}/libraries/uart/app_uart.c - ${SDK}/drivers_nrf/uart/nrf_drv_uart.c - ${SDK}/drivers_nrf/common/nrf_drv_common.c + ${SDK_DIR}/libraries/uart/app_uart.c + ${SDK_DIR}/drivers_nrf/uart/nrf_drv_uart.c + ${SDK_DIR}/drivers_nrf/common/nrf_drv_common.c ) target_include_directories(bootloader PUBLIC - ${SDK11}/libraries/util - ${SDK}/drivers_nrf/common - ${SDK}/drivers_nrf/uart + ${SDK11_DIR}/libraries/util + ${SDK_DIR}/drivers_nrf/common + ${SDK_DIR}/drivers_nrf/uart ) else () # USB transport @@ -199,13 +203,13 @@ else () src/usb/usb_desc.c src/usb/uf2/ghostfat.c # TinyUSB - ${TUSB}/portable/nordic/nrf5x/dcd_nrf5x.c - ${TUSB}/common/tusb_fifo.c - ${TUSB}/device/usbd.c - ${TUSB}/device/usbd_control.c - ${TUSB}/class/cdc/cdc_device.c - ${TUSB}/class/msc/msc_device.c - ${TUSB}/tusb.c + ${TINYUSB_DIR}/portable/nordic/nrf5x/dcd_nrf5x.c + ${TINYUSB_DIR}/common/tusb_fifo.c + ${TINYUSB_DIR}/device/usbd.c + ${TINYUSB_DIR}/device/usbd_control.c + ${TINYUSB_DIR}/class/cdc/cdc_device.c + ${TINYUSB_DIR}/class/msc/msc_device.c + ${TINYUSB_DIR}/tusb.c ) endif () @@ -222,10 +226,6 @@ if (MCU_VARIANT STREQUAL "nrf52") NRF52832_XXAA S132 ) - target_include_directories(bootloader PUBLIC - ${SOFTDEVICE}/s132_nrf52_6.1.1/s132_nrf52_6.1.1_API/include - ) - elseif (MCU_VARIANT STREQUAL "nrf52833") set(SD_NAME s140) set(DFU_DEV_REV 52833) @@ -234,10 +234,6 @@ elseif (MCU_VARIANT STREQUAL "nrf52833") NRF52833_XXAA S140 ) - target_include_directories(bootloader PUBLIC - ${SOFTDEVICE}/s140_nrf52_6.1.1/s140_nrf52_6.1.1_API/include - ) - elseif (MCU_VARIANT STREQUAL "nrf52840") set(SD_NAME s140) set(DFU_DEV_REV 52840) @@ -247,16 +243,16 @@ elseif (MCU_VARIANT STREQUAL "nrf52840") NRF52840_XXAA S140 ) - target_include_directories(bootloader PUBLIC - ${SOFTDEVICE}/s140_nrf52_6.1.1/s140_nrf52_6.1.1_API/include - ) - else () message(FATAL_ERROR "MCU_VARIANT ${MCU_VARIANT} is unknown") endif () set(SD_FILENAME ${SD_NAME}_nrf52_${SD_VERSION}) -set(SD_HEX ${SOFTDEVICE}/${SD_FILENAME}/${SD_FILENAME}_softdevice.hex) +set(SD_HEX ${SOFTDEVICE_DIR}/${SD_FILENAME}/${SD_FILENAME}_softdevice.hex) + +target_include_directories(bootloader PUBLIC + ${SOFTDEVICE_DIR}/${SD_FILENAME}/${SD_FILENAME}_API/include + ) if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug") target_compile_definitions(bootloader PUBLIC DFU_APP_DATA_RESERVED=${DFU_APP_DATA_RESERVED}) diff --git a/Makefile b/Makefile index 2f1ad99..497831d 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,9 @@ # local customization -include Makefile.user +# Board specific +-include src/boards/$(BOARD)/board.mk + SDK_PATH = lib/sdk/components SDK11_PATH = lib/sdk11/components TUSB_PATH = lib/tinyusb/src @@ -18,7 +21,11 @@ SD_PATH = lib/softdevice/$(SD_FILENAME) # SD_VERSION can be overwritten by board.mk ifndef SD_VERSION -SD_VERSION = 6.1.1 + ifeq ($(MCU_SUB_VARIANT),nrf52833) + SD_VERSION = 7.3.0 + else + SD_VERSION = 6.1.1 + endif endif SD_FILENAME = $(SD_NAME)_nrf52_$(SD_VERSION) @@ -89,25 +96,10 @@ endif BMP_PORT ?= $(shell ls -1 /dev/cu.usbmodem????????1 | head -1) GDB_BMP = $(GDB) -ex 'target extended-remote $(BMP_PORT)' -ex 'monitor swdp_scan' -ex 'attach 1' -#--------------------------------- -# Select the board to build -#--------------------------------- -# Note: whitespace is not allowed in the filenames... it WILL break this part of the script -BOARD_LIST = $(sort $(filter-out boards.h boards.c,$(notdir $(wildcard src/boards/*)))) - -ifeq ($(filter $(BOARD),$(BOARD_LIST)),) - $(info You must provide a BOARD parameter with 'BOARD='. Supported boards are:) - $(foreach b,$(BOARD_LIST),$(info - $(b))) - $(error Invalid BOARD specified) -endif - # Build directory BUILD = _build/build-$(BOARD) BIN = _bin/$(BOARD) -# Board specific --include src/boards/$(BOARD)/board.mk - # MCU_SUB_VARIANT can be nrf52 (nrf52832), nrf52833, nrf52840 ifeq ($(MCU_SUB_VARIANT),nrf52) SD_NAME = s132 diff --git a/src/boards/pca10100/board.cmake b/src/boards/pca10100/board.cmake new file mode 100644 index 0000000..cb4f2f9 --- /dev/null +++ b/src/boards/pca10100/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52833) diff --git a/src/boards/pca10100/board.mk b/src/boards/pca10100/board.mk index d76b2b7..a979f7e 100644 --- a/src/boards/pca10100/board.mk +++ b/src/boards/pca10100/board.mk @@ -1,2 +1 @@ -MCU_SUB_VARIANT = nrf52833 -SD_VERSION=7.2.0 \ No newline at end of file +MCU_SUB_VARIANT = nrf52833 \ No newline at end of file From 438a08e0ac7ae62fa6d77954f2eec78d6ef47a8b Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 5 Jun 2024 17:30:27 +0700 Subject: [PATCH 35/90] change PID of argon,boron,xenon, pca10056 to 0x00DA (allocated by Adafruit), previously these shared with feather nrf52840 change PID of pca10100 to 0x00D8 (allocated by Adafruit) --- src/boards/particle_argon/board.h | 6 +++--- src/boards/particle_boron/board.h | 6 +++--- src/boards/particle_xenon/board.h | 6 +++--- src/boards/pca10056/board.h | 4 ++-- src/boards/pca10100/board.h | 7 ++++--- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/boards/particle_argon/board.h b/src/boards/particle_argon/board.h index 3f7078a..1f31d93 100644 --- a/src/boards/particle_argon/board.h +++ b/src/boards/particle_argon/board.h @@ -57,10 +57,10 @@ // USB //--------------------------------------------------------------------+ -// Shared VID/PID with Feather nRF52840, will be disabled for building in the future +// Shared VID/PID with pca10056 #define USB_DESC_VID 0x239A -#define USB_DESC_UF2_PID 0x0029 -#define USB_DESC_CDC_ONLY_PID 0x0029 +#define USB_DESC_UF2_PID 0x00DA +#define USB_DESC_CDC_ONLY_PID 0x00DA #define UF2_PRODUCT_NAME "Particle Argon" #define UF2_VOLUME_LABEL "ARGONBOOT " diff --git a/src/boards/particle_boron/board.h b/src/boards/particle_boron/board.h index 6db75be..ee5236a 100644 --- a/src/boards/particle_boron/board.h +++ b/src/boards/particle_boron/board.h @@ -57,10 +57,10 @@ // USB //--------------------------------------------------------------------+ -// Shared VID/PID with Feather nRF52840, will be disabled for building in the future +// Shared VID/PID with pca10056 #define USB_DESC_VID 0x239A -#define USB_DESC_UF2_PID 0x0029 -#define USB_DESC_CDC_ONLY_PID 0x0029 +#define USB_DESC_UF2_PID 0x00DA +#define USB_DESC_CDC_ONLY_PID 0x00DA #define UF2_PRODUCT_NAME "Particle Boron" #define UF2_VOLUME_LABEL "BORONBOOT " diff --git a/src/boards/particle_xenon/board.h b/src/boards/particle_xenon/board.h index ac2c9a7..3c77828 100644 --- a/src/boards/particle_xenon/board.h +++ b/src/boards/particle_xenon/board.h @@ -57,10 +57,10 @@ // USB //--------------------------------------------------------------------+ -// Shared VID/PID with Feather nRF52840, will be disabled for building in the future +// Shared VID/PID with pca10056 #define USB_DESC_VID 0x239A -#define USB_DESC_UF2_PID 0x0029 -#define USB_DESC_CDC_ONLY_PID 0x0029 +#define USB_DESC_UF2_PID 0x00DA +#define USB_DESC_CDC_ONLY_PID 0x00DA #define UF2_PRODUCT_NAME "Particle Xenon" #define UF2_VOLUME_LABEL "XENONBOOT " diff --git a/src/boards/pca10056/board.h b/src/boards/pca10056/board.h index 92ce346..51dc2fb 100644 --- a/src/boards/pca10056/board.h +++ b/src/boards/pca10056/board.h @@ -53,8 +53,8 @@ // Shared VID/PID with Feather nRF52840, will be disabled for building in the future #define USB_DESC_VID 0x239A -#define USB_DESC_UF2_PID 0x0029 -#define USB_DESC_CDC_ONLY_PID 0x0029 +#define USB_DESC_UF2_PID 0x00DA +#define USB_DESC_CDC_ONLY_PID 0x00DA #define UF2_PRODUCT_NAME "Nordic nRF52840 DK" #define UF2_BOARD_ID "nRF52840-pca10056-v1" diff --git a/src/boards/pca10100/board.h b/src/boards/pca10100/board.h index 743f175..e96b11c 100644 --- a/src/boards/pca10100/board.h +++ b/src/boards/pca10100/board.h @@ -50,11 +50,12 @@ //--------------------------------------------------------------------+ // USB //--------------------------------------------------------------------+ -#define USB_DESC_VID 0x1915 -#define USB_DESC_UF2_PID 0x521F -#define USB_DESC_CDC_ONLY_PID 0x521F +#define USB_DESC_VID 0x239A +#define USB_DESC_UF2_PID 0x00D8 +#define USB_DESC_CDC_ONLY_PID 0x00D8 #define UF2_PRODUCT_NAME "Nordic nRF52833 DK" +#define UF2_VOLUME_LABEL "NRF833BOOT" #define UF2_BOARD_ID "nRF52833-pca10100-v1" #define UF2_INDEX_URL "https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52833-DK" From c5150ccf02335fc19a0f36f3230a27acd88a1907 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 5 Jun 2024 17:32:51 +0700 Subject: [PATCH 36/90] update PR template --- .github/PULL_REQUEST_TEMPLATE.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 6953d76..6523363 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -3,10 +3,8 @@ *By completing this PR sufficiently, you help us to review this Pull Request quicker and also help improve the quality of Release Notes* - [ ] Please provide specific title of the PR describing the change -- [ ] Please provide related links (*eg. Issue which will be closed by this Pull Request*) - [ ] If you are adding an new boards, please make sure - [ ] Provide link to your allocated VID/PID if applicable - - [ ] Add your board to [action ci](/.github/workflows) in correct workflow and alphabet order for release binary - [ ] `UF2_BOARD_ID` in your board.h follow correct format from [uf2 specs](https://github.com/microsoft/uf2#files-exposed-by-bootloaders) *This checklist items that are not applicable to your PR can be deleted.* From 5f99d530ff2e471c9000a358871ddb97ae357019 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 5 Jun 2024 17:34:56 +0700 Subject: [PATCH 37/90] revert fetch-depth 0 --- .github/workflows/githubci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/githubci.yml b/.github/workflows/githubci.yml index 103ecaa..68b4f7f 100644 --- a/.github/workflows/githubci.yml +++ b/.github/workflows/githubci.yml @@ -36,7 +36,7 @@ jobs: - name: Checkout Code uses: actions/checkout@v4 with: - fetch-tags: true + fetch-depth: 0 submodules: true - name: Install ARM GCC From 4e700d490441c13fdadf113e69a46536d4118c5a Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 5 Jun 2024 17:42:13 +0700 Subject: [PATCH 38/90] bump feather 833 SD to 7.3.0 --- src/boards/feather_nrf52833_express/board.mk | 1 - 1 file changed, 1 deletion(-) diff --git a/src/boards/feather_nrf52833_express/board.mk b/src/boards/feather_nrf52833_express/board.mk index f94e72e..d60ac48 100644 --- a/src/boards/feather_nrf52833_express/board.mk +++ b/src/boards/feather_nrf52833_express/board.mk @@ -1,2 +1 @@ MCU_SUB_VARIANT = nrf52833 -SD_VERSION = 7.3.0 \ No newline at end of file From 155dedb04830bbfb811cea85d2e20ced18c691f8 Mon Sep 17 00:00:00 2001 From: Mark Trevor Birss Date: Fri, 12 Jul 2024 08:55:57 +0200 Subject: [PATCH 39/90] Add files via upload --- src/boards/t1000_e/board.h | 67 ++++++++++++++++++++++++++++++++++ src/boards/t1000_e/board.mk | 3 ++ src/boards/t1000_e/pinconfig.c | 19 ++++++++++ 3 files changed, 89 insertions(+) create mode 100644 src/boards/t1000_e/board.h create mode 100644 src/boards/t1000_e/board.mk create mode 100644 src/boards/t1000_e/pinconfig.c diff --git a/src/boards/t1000_e/board.h b/src/boards/t1000_e/board.h new file mode 100644 index 0000000..9b53203 --- /dev/null +++ b/src/boards/t1000_e/board.h @@ -0,0 +1,67 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Yihui Xiong for Makerdiary + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef _T1000_E_H +#define _T1000_E_H + +#define _PINNUM(port, pin) ((port)*32 + (pin)) + +/*------------------------------------------------------------------*/ +/* LED + *------------------------------------------------------------------*/ +#define LEDS_NUMBER 1 +#define LED_PRIMARY_PIN _PINNUM(0, 24) // Green +#define LED_STATE_ON 0 + +/*------------------------------------------------------------------*/ +/* BUTTON + *------------------------------------------------------------------*/ +#define BUTTONS_NUMBER 2 +#define BUTTON_1 _PINNUM(0, 6) // Primary Button +#define BUTTON_2 _PINNUM(0, 18) // unusable: RESET +#define BUTTON_PULL NRF_GPIO_PIN_PULLUP + +//--------------------------------------------------------------------+ +// BLE OTA +//--------------------------------------------------------------------+ +#define BLEDIS_MANUFACTURER "Seeed Studio" +#define BLEDIS_MODEL "T1000-E" + +//--------------------------------------------------------------------+ +// USB +//--------------------------------------------------------------------+ +#define USB_DESC_VID 0x2886 +#define USB_DESC_UF2_PID 0x0057 +#define USB_DESC_CDC_ONLY_PID 0x0057 + +//--------------------------------------------------------------------+ +// UF2 +//--------------------------------------------------------------------+ +#define UF2_PRODUCT_NAME "T1000-E" +#define UF2_VOLUME_LABEL "T1000-E" +#define UF2_BOARD_ID "T1000-E" +#define UF2_INDEX_URL "https://www.seeedstudio.com/SenseCAP-Card-Tracker-T1000-E-for-Meshtastic-p-5913.html" + + +#endif /* _T1000_E_H */ diff --git a/src/boards/t1000_e/board.mk b/src/boards/t1000_e/board.mk new file mode 100644 index 0000000..0fa4490 --- /dev/null +++ b/src/boards/t1000_e/board.mk @@ -0,0 +1,3 @@ +MCU_SUB_VARIANT = nrf52840 +SD_VERSION = 7.3.0 + diff --git a/src/boards/t1000_e/pinconfig.c b/src/boards/t1000_e/pinconfig.c new file mode 100644 index 0000000..a983e4a --- /dev/null +++ b/src/boards/t1000_e/pinconfig.c @@ -0,0 +1,19 @@ +#include "boards.h" +#include "uf2/configkeys.h" + +__attribute__((used, section(".bootloaderConfig"))) +const uint32_t bootloaderConfig[] = +{ + /* CF2 START */ + CFG_MAGIC0, CFG_MAGIC1, // magic + 5, 100, // used entries, total entries + + 204, 0x100000, // FLASH_BYTES = 0x100000 + 205, 0x40000, // RAM_BYTES = 0x40000 + 208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2 + 209, 0xada52840, // UF2_FAMILY = 0xada52840 + 210, 0x20, // PINS_PORT_SIZE = PA_32 + + 0, 0, 0, 0, 0, 0, 0, 0 + /* CF2 END */ +}; From 4f747e416b9b74e9d43cc8bf1ef3294abc700225 Mon Sep 17 00:00:00 2001 From: Mark Trevor Birss Date: Fri, 12 Jul 2024 09:02:34 +0200 Subject: [PATCH 40/90] Update board.h --- src/boards/t1000_e/board.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boards/t1000_e/board.h b/src/boards/t1000_e/board.h index 9b53203..db22150 100644 --- a/src/boards/t1000_e/board.h +++ b/src/boards/t1000_e/board.h @@ -60,7 +60,7 @@ //--------------------------------------------------------------------+ #define UF2_PRODUCT_NAME "T1000-E" #define UF2_VOLUME_LABEL "T1000-E" -#define UF2_BOARD_ID "T1000-E" +#define UF2_BOARD_ID "nRF52840-T1000-E" #define UF2_INDEX_URL "https://www.seeedstudio.com/SenseCAP-Card-Tracker-T1000-E-for-Meshtastic-p-5913.html" From 6b62aacdc9a7773f0c6f83a46700c493c8750d14 Mon Sep 17 00:00:00 2001 From: Mark Trevor Birss Date: Fri, 12 Jul 2024 09:20:53 +0200 Subject: [PATCH 41/90] Update board.h --- src/boards/t1000_e/board.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/boards/t1000_e/board.h b/src/boards/t1000_e/board.h index db22150..7c4db64 100644 --- a/src/boards/t1000_e/board.h +++ b/src/boards/t1000_e/board.h @@ -58,9 +58,9 @@ //--------------------------------------------------------------------+ // UF2 //--------------------------------------------------------------------+ -#define UF2_PRODUCT_NAME "T1000-E" +#define UF2_PRODUCT_NAME "Seeed T1000-E for Meshtastic" #define UF2_VOLUME_LABEL "T1000-E" -#define UF2_BOARD_ID "nRF52840-T1000-E" +#define UF2_BOARD_ID "Seeed-nRF52840-T1000-E" #define UF2_INDEX_URL "https://www.seeedstudio.com/SenseCAP-Card-Tracker-T1000-E-for-Meshtastic-p-5913.html" From 91fc6735e97d9889cbb3f41795f6d4ada460bcd6 Mon Sep 17 00:00:00 2001 From: Mark Trevor Birss Date: Fri, 12 Jul 2024 12:34:49 +0200 Subject: [PATCH 42/90] Update board.h --- src/boards/t1000_e/board.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boards/t1000_e/board.h b/src/boards/t1000_e/board.h index 7c4db64..1a08741 100644 --- a/src/boards/t1000_e/board.h +++ b/src/boards/t1000_e/board.h @@ -60,7 +60,7 @@ //--------------------------------------------------------------------+ #define UF2_PRODUCT_NAME "Seeed T1000-E for Meshtastic" #define UF2_VOLUME_LABEL "T1000-E" -#define UF2_BOARD_ID "Seeed-nRF52840-T1000-E" +#define UF2_BOARD_ID "nRF52840-T1000-E-v1" #define UF2_INDEX_URL "https://www.seeedstudio.com/SenseCAP-Card-Tracker-T1000-E-for-Meshtastic-p-5913.html" From ab74be4811ee462f6af126e0aaa3e4af342abb83 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 Jul 2024 13:02:31 +0700 Subject: [PATCH 43/90] correct itsybitsy dotstar --- Makefile | 9 +- src/boards/boards.c | 14 +- .../itsybitsy_nrf52840_express/board.cmake | 1 + src/boards/itsybitsy_nrf52840_express/board.h | 11 +- src/nrfx_config.h | 1 + src/nrfx_log.h | 135 ++++++++++++++++++ 6 files changed, 160 insertions(+), 11 deletions(-) create mode 100644 src/boards/itsybitsy_nrf52840_express/board.cmake create mode 100644 src/nrfx_log.h diff --git a/Makefile b/Makefile index 497831d..3235987 100644 --- a/Makefile +++ b/Makefile @@ -49,6 +49,8 @@ OUT_NAME = $(BOARD)_bootloader-$(GIT_VERSION) # merged file = compiled + sd MERGED_FILE = $(OUT_NAME)_$(SD_NAME)_$(SD_VERSION) +UF2_FAMILY_ID_BOOTLOADER = 0xd663823c + #------------------------------------------------------------------------------ # Tool Configure #------------------------------------------------------------------------------ @@ -435,7 +437,7 @@ $(BUILD)/$(OUT_NAME)_nosd.hex: $(BUILD)/$(OUT_NAME).hex # Bootolader self-update uf2 $(BUILD)/update-$(OUT_NAME)_nosd.uf2: $(BUILD)/$(OUT_NAME)_nosd.hex @echo Create $(notdir $@) - @python3 lib/uf2/utils/uf2conv.py -f 0xd663823c -c -o $@ $^ + @python3 lib/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID_BOOTLOADER) -c -o $@ $^ # merge bootloader and sd hex together $(BUILD)/$(MERGED_FILE).hex: $(BUILD)/$(OUT_NAME).hex @@ -488,6 +490,11 @@ flash-mbr: @echo Flashing: $(MBR_HEX) $(call FLASH_NOUICR_CMD,$(MBR_HEX)) +# flash using uf2 +flash-uf2: $(BUILD)/update-$(OUT_NAME)_nosd.uf2 + @echo Flashing: $(notdir $<) + python lib/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID_BOOTLOADER) --deploy $< + # dfu with adafruit-nrfutil using CDC interface dfu-flash: flash-dfu flash-dfu: $(BUILD)/$(MERGED_FILE).zip diff --git a/src/boards/boards.c b/src/boards/boards.c index e1b39f3..ea1f4b3 100644 --- a/src/boards/boards.c +++ b/src/boards/boards.c @@ -27,14 +27,14 @@ #include "app_scheduler.h" #include "app_timer.h" -#ifdef LED_APA102 +#ifdef LED_APA102_CLK #include "nrf_spim.h" #endif #define SCHED_MAX_EVENT_DATA_SIZE sizeof(app_timer_event_t) /**< Maximum size of scheduler events. */ #define SCHED_QUEUE_SIZE 30 /**< Maximum number of events in the scheduler queue. */ -#if defined(LED_NEOPIXEL) || defined(LED_RGB_RED_PIN) || defined(LED_APA102) +#if defined(LED_NEOPIXEL) || defined(LED_RGB_RED_PIN) || defined(LED_APA102_CLK) void neopixel_init(void); void neopixel_write(uint8_t* pixels); void neopixel_teardown(void); @@ -86,7 +86,7 @@ void board_init(void) { #endif #endif -#if defined(LED_NEOPIXEL) || defined(LED_RGB_RED_PIN) || defined(LED_APA102) +#if defined(LED_NEOPIXEL) || defined(LED_RGB_RED_PIN) || defined(LED_APA102_CLK) // use neopixel for use enumeration #ifdef NEOPIXEL_POWER_PIN nrf_gpio_cfg_output(NEOPIXEL_POWER_PIN); @@ -147,7 +147,7 @@ void board_teardown(void) { led_pwm_teardown(); #endif -#if defined(LED_NEOPIXEL) || defined(LED_RGB_RED_PIN) || defined(LED_APA102) +#if defined(LED_NEOPIXEL) || defined(LED_RGB_RED_PIN) || defined(LED_APA102_CLK) neopixel_teardown(); #endif @@ -362,7 +362,7 @@ static uint32_t primary_cycle_length; static uint32_t secondary_cycle_length; #endif -void led_tick() { +void led_tick(void) { uint32_t millis = _systick_count; uint32_t cycle = millis % primary_cycle_length; @@ -452,7 +452,7 @@ void led_state(uint32_t state) { final_color = (uint8_t*) &rgb_color; } -#if defined(LED_NEOPIXEL) || defined(LED_RGB_RED_PIN) || defined(LED_APA102) +#if defined(LED_NEOPIXEL) || defined(LED_RGB_RED_PIN) || defined(LED_APA102_CLK) if (final_color != NULL) { neopixel_write(final_color); } @@ -560,7 +560,7 @@ void neopixel_write(uint8_t* pixels) { #endif -#ifdef LED_APA102 +#ifdef LED_APA102_CLK #define BYTE_PER_PIXEL 4 // 4 zero bytes are required to initiate update diff --git a/src/boards/itsybitsy_nrf52840_express/board.cmake b/src/boards/itsybitsy_nrf52840_express/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/itsybitsy_nrf52840_express/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/itsybitsy_nrf52840_express/board.h b/src/boards/itsybitsy_nrf52840_express/board.h index 2bc82e0..a3b6c08 100644 --- a/src/boards/itsybitsy_nrf52840_express/board.h +++ b/src/boards/itsybitsy_nrf52840_express/board.h @@ -34,9 +34,14 @@ #define LED_PRIMARY_PIN _PINNUM(0, 6) #define LED_STATE_ON 1 -#define LED_NEOPIXEL _PINNUM(0, 8) -#define NEOPIXELS_NUMBER 1 -#define BOARD_RGB_BRIGHTNESS 0x040404 +#define LED_APA102_CLK _PINNUM(1, 9) +#define LED_APA102_DATA _PINNUM(0, 8) +#define LED_APA102_BRIGHTNESS 0x1 +#define APA102_NUMBER 1 + +// For dotstart set to max for colour information is not masked off +#define BOARD_RGB_BRIGHTNESS 0xffffffff + /*------------------------------------------------------------------*/ /* BUTTON diff --git a/src/nrfx_config.h b/src/nrfx_config.h index 74e5fdb..23b3d83 100644 --- a/src/nrfx_config.h +++ b/src/nrfx_config.h @@ -10,6 +10,7 @@ #define NRFX_PRS_ENABLED 0 +// PWM #define NRFX_PWM_ENABLED 0 #define NRFX_PWM0_ENABLED 0 #define NRFX_PWM1_ENABLED 0 diff --git a/src/nrfx_log.h b/src/nrfx_log.h new file mode 100644 index 0000000..3bc1b42 --- /dev/null +++ b/src/nrfx_log.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2017 - 2019, Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NRFX_LOG_H__ +#define NRFX_LOG_H__ + +// THIS IS A TEMPLATE FILE. +// It should be copied to a suitable location within the host environment into +// which nrfx is integrated, and the following macros should be provided with +// appropriate implementations. +// And this comment should be removed from the customized file. + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrfx_log nrfx_log.h + * @{ + * @ingroup nrfx + * + * @brief This file contains macros that should be implemented according to + * the needs of the host environment into which @em nrfx is integrated. + */ + +/** + * @brief Macro for logging a message with the severity level ERROR. + * + * @param format printf-style format string, optionally followed by arguments + * to be formatted and inserted in the resulting string. + */ +#define NRFX_LOG_ERROR(format, ...) + +/** + * @brief Macro for logging a message with the severity level WARNING. + * + * @param format printf-style format string, optionally followed by arguments + * to be formatted and inserted in the resulting string. + */ +#define NRFX_LOG_WARNING(format, ...) + +/** + * @brief Macro for logging a message with the severity level INFO. + * + * @param format printf-style format string, optionally followed by arguments + * to be formatted and inserted in the resulting string. + */ +#define NRFX_LOG_INFO(format, ...) + +/** + * @brief Macro for logging a message with the severity level DEBUG. + * + * @param format printf-style format string, optionally followed by arguments + * to be formatted and inserted in the resulting string. + */ +#define NRFX_LOG_DEBUG(format, ...) + + +/** + * @brief Macro for logging a memory dump with the severity level ERROR. + * + * @param[in] p_memory Pointer to the memory region to be dumped. + * @param[in] length Length of the memory region in bytes. + */ +#define NRFX_LOG_HEXDUMP_ERROR(p_memory, length) + +/** + * @brief Macro for logging a memory dump with the severity level WARNING. + * + * @param[in] p_memory Pointer to the memory region to be dumped. + * @param[in] length Length of the memory region in bytes. + */ +#define NRFX_LOG_HEXDUMP_WARNING(p_memory, length) + +/** + * @brief Macro for logging a memory dump with the severity level INFO. + * + * @param[in] p_memory Pointer to the memory region to be dumped. + * @param[in] length Length of the memory region in bytes. + */ +#define NRFX_LOG_HEXDUMP_INFO(p_memory, length) + +/** + * @brief Macro for logging a memory dump with the severity level DEBUG. + * + * @param[in] p_memory Pointer to the memory region to be dumped. + * @param[in] length Length of the memory region in bytes. + */ +#define NRFX_LOG_HEXDUMP_DEBUG(p_memory, length) + + +/** + * @brief Macro for getting the textual representation of a given error code. + * + * @param[in] error_code Error code. + * + * @return String containing the textual representation of the error code. + */ +#define NRFX_LOG_ERROR_STRING_GET(error_code) + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NRFX_LOG_H__ From 9027359cec40e8d32e42153b86554b0e26ffedb9 Mon Sep 17 00:00:00 2001 From: Patrick Cook Date: Sun, 8 Sep 2024 17:11:05 -0400 Subject: [PATCH 44/90] add support for promicro/supermini nrf52 boards --- src/boards/promicro_nrf52840/board.h | 66 ++++++++++++++++++++++++ src/boards/promicro_nrf52840/board.mk | 2 + src/boards/promicro_nrf52840/pinconfig.c | 19 +++++++ 3 files changed, 87 insertions(+) create mode 100644 src/boards/promicro_nrf52840/board.h create mode 100644 src/boards/promicro_nrf52840/board.mk create mode 100644 src/boards/promicro_nrf52840/pinconfig.c diff --git a/src/boards/promicro_nrf52840/board.h b/src/boards/promicro_nrf52840/board.h new file mode 100644 index 0000000..01f882f --- /dev/null +++ b/src/boards/promicro_nrf52840/board.h @@ -0,0 +1,66 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018 Ha Thach for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef _PROMICRO_NRF52840 +#define _PROMICRO_NRF52840 + +#define _PINNUM(port, pin) ((port)*32 + (pin)) + +/*------------------------------------------------------------------*/ +/* LED + *------------------------------------------------------------------*/ +#define LEDS_NUMBER 1 +#define LED_PRIMARY_PIN _PINNUM(0, 15) +#define LED_STATE_ON 1 // State when LED is lit (active HIGH) + +#define NEOPIXELS_NUMBER 0 + +/*------------------------------------------------------------------*/ +/* BUTTON + *------------------------------------------------------------------*/ +#define BUTTONS_NUMBER 2 +#define BUTTON_1 _PINNUM(0, 14) // RESET +#define BUTTON_2 _PINNUM(0, 3) // NC +#define BUTTON_PULL NRF_GPIO_PIN_PULLUP + +//--------------------------------------------------------------------+ +// BLE OTA +//--------------------------------------------------------------------+ +#define BLEDIS_MANUFACTURER "ProMicro" +#define BLEDIS_MODEL "ProMicro nRF52840" + +//--------------------------------------------------------------------+ +// USB +//--------------------------------------------------------------------+ +#define USB_DESC_VID 0x1209 +#define USB_DESC_UF2_PID 0x0064 +#define USB_DESC_CDC_ONLY_PID 0x0064 + +//------------- UF2 -------------// +#define UF2_PRODUCT_NAME "ProMicro nRF52840" +#define UF2_VOLUME_LABEL "PROMICRO" +#define UF2_BOARD_ID "ProMicro-nRF52840" +#define UF2_INDEX_URL "https://github.com/joric/nrfmicro/wiki" + +#endif // _PROMICRO_NRF52840 diff --git a/src/boards/promicro_nrf52840/board.mk b/src/boards/promicro_nrf52840/board.mk new file mode 100644 index 0000000..8a77053 --- /dev/null +++ b/src/boards/promicro_nrf52840/board.mk @@ -0,0 +1,2 @@ +MCU_SUB_VARIANT = nrf52840 +SD_VERSION = 7.3.0 \ No newline at end of file diff --git a/src/boards/promicro_nrf52840/pinconfig.c b/src/boards/promicro_nrf52840/pinconfig.c new file mode 100644 index 0000000..2a592df --- /dev/null +++ b/src/boards/promicro_nrf52840/pinconfig.c @@ -0,0 +1,19 @@ +#include "boards.h" +#include "uf2/configkeys.h" + +__attribute__((used, section(".bootloaderConfig"))) +const uint32_t bootloaderConfig[] = +{ + /* CF2 START */ + CFG_MAGIC0, CFG_MAGIC1, // magic + 5, 100, // used entries, total entries + + 204, 0x100000, // FLASH_BYTES = 0x100000 + 205, 0x40000, // RAM_BYTES = 0x40000 + 208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2 + 209, 0xada52840, // UF2_FAMILY = 0xada52840 + 210, 0x20, // PINS_PORT_SIZE = PA_32 + + 0, 0, 0, 0, 0, 0, 0, 0 + /* CF2 END */ +}; \ No newline at end of file From 4786a4a251951558f30850025bb6d484c797eebe Mon Sep 17 00:00:00 2001 From: Patrick Cook Date: Sun, 8 Sep 2024 17:14:35 -0400 Subject: [PATCH 45/90] fixed board-id to conform to standards --- src/boards/promicro_nrf52840/board.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/boards/promicro_nrf52840/board.h b/src/boards/promicro_nrf52840/board.h index 01f882f..c13b332 100644 --- a/src/boards/promicro_nrf52840/board.h +++ b/src/boards/promicro_nrf52840/board.h @@ -59,8 +59,8 @@ //------------- UF2 -------------// #define UF2_PRODUCT_NAME "ProMicro nRF52840" -#define UF2_VOLUME_LABEL "PROMICRO" -#define UF2_BOARD_ID "ProMicro-nRF52840" +#define UF2_VOLUME_LABEL "PROMICRO-BOOT" +#define UF2_BOARD_ID "nRF52840-ProMicro-v0" #define UF2_INDEX_URL "https://github.com/joric/nrfmicro/wiki" #endif // _PROMICRO_NRF52840 From 6940c5b73ea49613bcbe2434b7261e98e885af5e Mon Sep 17 00:00:00 2001 From: Patrick Cook Date: Sun, 8 Sep 2024 18:29:19 -0400 Subject: [PATCH 46/90] rename promicro->nrfmicro --- .../{promicro_nrf52840 => nrfmicro}/board.h | 16 ++++++++-------- .../{promicro_nrf52840 => nrfmicro}/board.mk | 0 .../{promicro_nrf52840 => nrfmicro}/pinconfig.c | 0 3 files changed, 8 insertions(+), 8 deletions(-) rename src/boards/{promicro_nrf52840 => nrfmicro}/board.h (86%) rename src/boards/{promicro_nrf52840 => nrfmicro}/board.mk (100%) rename src/boards/{promicro_nrf52840 => nrfmicro}/pinconfig.c (100%) diff --git a/src/boards/promicro_nrf52840/board.h b/src/boards/nrfmicro/board.h similarity index 86% rename from src/boards/promicro_nrf52840/board.h rename to src/boards/nrfmicro/board.h index c13b332..6f88b64 100644 --- a/src/boards/promicro_nrf52840/board.h +++ b/src/boards/nrfmicro/board.h @@ -22,8 +22,8 @@ * THE SOFTWARE. */ -#ifndef _PROMICRO_NRF52840 -#define _PROMICRO_NRF52840 +#ifndef _NRFMICRO_NRF52840 +#define _NRFMICRO_NRF52840 #define _PINNUM(port, pin) ((port)*32 + (pin)) @@ -47,8 +47,8 @@ //--------------------------------------------------------------------+ // BLE OTA //--------------------------------------------------------------------+ -#define BLEDIS_MANUFACTURER "ProMicro" -#define BLEDIS_MODEL "ProMicro nRF52840" +#define BLEDIS_MANUFACTURER "nRFMicro" +#define BLEDIS_MODEL "nRFMicro nRF52840" //--------------------------------------------------------------------+ // USB @@ -58,9 +58,9 @@ #define USB_DESC_CDC_ONLY_PID 0x0064 //------------- UF2 -------------// -#define UF2_PRODUCT_NAME "ProMicro nRF52840" -#define UF2_VOLUME_LABEL "PROMICRO-BOOT" -#define UF2_BOARD_ID "nRF52840-ProMicro-v0" +#define UF2_PRODUCT_NAME "nRFMicro nRF52840" +#define UF2_VOLUME_LABEL "NRFMICRO-BOOT" +#define UF2_BOARD_ID "nRF52840-nRFMicro-v0" #define UF2_INDEX_URL "https://github.com/joric/nrfmicro/wiki" -#endif // _PROMICRO_NRF52840 +#endif // _NRFMICRO_NRF52840 diff --git a/src/boards/promicro_nrf52840/board.mk b/src/boards/nrfmicro/board.mk similarity index 100% rename from src/boards/promicro_nrf52840/board.mk rename to src/boards/nrfmicro/board.mk diff --git a/src/boards/promicro_nrf52840/pinconfig.c b/src/boards/nrfmicro/pinconfig.c similarity index 100% rename from src/boards/promicro_nrf52840/pinconfig.c rename to src/boards/nrfmicro/pinconfig.c From f3b3a0de40e0f89e5e4808ec53f160fc82723a97 Mon Sep 17 00:00:00 2001 From: Patrick Cook Date: Sun, 8 Sep 2024 18:31:25 -0400 Subject: [PATCH 47/90] reduced number of chars, updated potential PID --- src/boards/nrfmicro/board.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/boards/nrfmicro/board.h b/src/boards/nrfmicro/board.h index 6f88b64..3f47149 100644 --- a/src/boards/nrfmicro/board.h +++ b/src/boards/nrfmicro/board.h @@ -54,12 +54,12 @@ // USB //--------------------------------------------------------------------+ #define USB_DESC_VID 0x1209 -#define USB_DESC_UF2_PID 0x0064 -#define USB_DESC_CDC_ONLY_PID 0x0064 +#define USB_DESC_UF2_PID 0x5284 +#define USB_DESC_CDC_ONLY_PID 0x5284 //------------- UF2 -------------// -#define UF2_PRODUCT_NAME "nRFMicro nRF52840" -#define UF2_VOLUME_LABEL "NRFMICRO-BOOT" +#define UF2_PRODUCT_NAME "nRFMicro" +#define UF2_VOLUME_LABEL "NRFMICRO" #define UF2_BOARD_ID "nRF52840-nRFMicro-v0" #define UF2_INDEX_URL "https://github.com/joric/nrfmicro/wiki" From 5a96435322d5f15dea512d9baf0180cd9939e135 Mon Sep 17 00:00:00 2001 From: Patrick Cook Date: Wed, 11 Sep 2024 23:19:40 -0400 Subject: [PATCH 48/90] commit correct file for nRFMicro --- src/boards/nrfmicro/board.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/boards/nrfmicro/board.h b/src/boards/nrfmicro/board.h index 3f47149..c6b2528 100644 --- a/src/boards/nrfmicro/board.h +++ b/src/boards/nrfmicro/board.h @@ -31,7 +31,7 @@ /* LED *------------------------------------------------------------------*/ #define LEDS_NUMBER 1 -#define LED_PRIMARY_PIN _PINNUM(0, 15) +#define LED_PRIMARY_PIN _PINNUM(1, 10) #define LED_STATE_ON 1 // State when LED is lit (active HIGH) #define NEOPIXELS_NUMBER 0 @@ -40,8 +40,8 @@ /* BUTTON *------------------------------------------------------------------*/ #define BUTTONS_NUMBER 2 -#define BUTTON_1 _PINNUM(0, 14) // RESET -#define BUTTON_2 _PINNUM(0, 3) // NC +#define BUTTON_1 _PINNUM(1, 2) // DFU +#define BUTTON_2 _PINNUM(0, 12) // FRST #define BUTTON_PULL NRF_GPIO_PIN_PULLUP //--------------------------------------------------------------------+ From 7f2b127506a4215014425b30dd2833ac223b2410 Mon Sep 17 00:00:00 2001 From: chibiegg Date: Mon, 4 Nov 2024 00:18:01 +0900 Subject: [PATCH 49/90] Add support Murata MBN52832DK board --- src/boards/mbn52832dk/board.h | 63 ++++++++++++++++++++++++++++++++++ src/boards/mbn52832dk/board.mk | 2 ++ 2 files changed, 65 insertions(+) create mode 100644 src/boards/mbn52832dk/board.h create mode 100644 src/boards/mbn52832dk/board.mk diff --git a/src/boards/mbn52832dk/board.h b/src/boards/mbn52832dk/board.h new file mode 100644 index 0000000..c9fda30 --- /dev/null +++ b/src/boards/mbn52832dk/board.h @@ -0,0 +1,63 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018 Ha Thach for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef _MBN52832DK_H +#define _MBN52832DK_H + +/*------------------------------------------------------------------*/ +/* LED + *------------------------------------------------------------------*/ +#define LEDS_NUMBER 2 +#define LED_PRIMARY_PIN 17 // LED1 +#define LED_SECONDARY_PIN 18 // LED2 +#define LED_STATE_ON 1 + +/*------------------------------------------------------------------*/ +/* BUTTON + *------------------------------------------------------------------*/ +#define BUTTONS_NUMBER 2 +#define BUTTON_1 13 +#define BUTTON_2 14 +#define BUTTON_PULL NRF_GPIO_PIN_PULLUP + +/*------------------------------------------------------------------*/ +/* UART (only used by nRF52832) + *------------------------------------------------------------------*/ +#define RX_PIN_NUMBER 8 +#define TX_PIN_NUMBER 6 +#define CTS_PIN_NUMBER 0 +#define RTS_PIN_NUMBER 0 +#define HWFC false + +//--------------------------------------------------------------------+ +// BLE OTA +//--------------------------------------------------------------------+ +#define BLEDIS_MANUFACTURER "Murata" +#define BLEDIS_MODEL "MBN52832DK" + +#define UF2_BOARD_ID "nRF52832-MBN52832DK-v1" +#define UF2_PRODUCT_NAME "Murata MBN52832DK" +#define UF2_INDEX_URL "https://www.murata.com/ja-jp/products/connectivitymodule/bluetooth/overview/lineup/mbn52832" + +#endif // _MBN52832DK_H diff --git a/src/boards/mbn52832dk/board.mk b/src/boards/mbn52832dk/board.mk new file mode 100644 index 0000000..f932bb8 --- /dev/null +++ b/src/boards/mbn52832dk/board.mk @@ -0,0 +1,2 @@ +# nrf52 is nrf52832 +MCU_SUB_VARIANT = nrf52 From fb557b2af98ea73d052a11474fd7d12e9ddba9ec Mon Sep 17 00:00:00 2001 From: fanoush Date: Sat, 16 Nov 2024 10:28:42 +0100 Subject: [PATCH 50/90] set REGOUT0 only when value is erased to default this fixes reboot loop when REGOUT0 is explicitly set to different value that cannot be rewritten by clearing bits in flash --- src/boards/boards.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boards/boards.c b/src/boards/boards.c index ea1f4b3..9eaf7b0 100644 --- a/src/boards/boards.c +++ b/src/boards/boards.c @@ -111,7 +111,7 @@ void board_init(void) { // #define UICR_REGOUT0_VALUE UICR_REGOUT0_VOUT_3V3 // in board.h when using that power configuration. #ifdef UICR_REGOUT0_VALUE - if ((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) != (UICR_REGOUT0_VALUE << UICR_REGOUT0_VOUT_Pos)){ + if ((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) == (UICR_REGOUT0_VOUT_DEFAULT << UICR_REGOUT0_VOUT_Pos)){ NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos; while (NRF_NVMC->READY == NVMC_READY_READY_Busy){} NRF_UICR->REGOUT0 = (NRF_UICR->REGOUT0 & ~((uint32_t)UICR_REGOUT0_VOUT_Msk)) | From 22224cef7b4fbd6c762821666c625ef790dba236 Mon Sep 17 00:00:00 2001 From: OmarEMbed <62099184+OmarEMbed@users.noreply.github.com> Date: Sun, 16 Feb 2025 11:04:50 +0100 Subject: [PATCH 51/90] Add files via upload --- src/boards/omnimo_nrf52840/board.cmake | 1 + src/boards/omnimo_nrf52840/board.h | 72 ++++++++++++++++++++++++++ src/boards/omnimo_nrf52840/board.mk | 1 + src/boards/omnimo_nrf52840/pinconfig.c | 19 +++++++ 4 files changed, 93 insertions(+) create mode 100644 src/boards/omnimo_nrf52840/board.cmake create mode 100644 src/boards/omnimo_nrf52840/board.h create mode 100644 src/boards/omnimo_nrf52840/board.mk create mode 100644 src/boards/omnimo_nrf52840/pinconfig.c diff --git a/src/boards/omnimo_nrf52840/board.cmake b/src/boards/omnimo_nrf52840/board.cmake new file mode 100644 index 0000000..2715f36 --- /dev/null +++ b/src/boards/omnimo_nrf52840/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/omnimo_nrf52840/board.h b/src/boards/omnimo_nrf52840/board.h new file mode 100644 index 0000000..cf4e3a7 --- /dev/null +++ b/src/boards/omnimo_nrf52840/board.h @@ -0,0 +1,72 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018 Ha Thach for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef _OMNIMO_NRF52840_H +#define _OMNIMO_NRF52840_H + +#define _PINNUM(port, pin) ((port)*32 + (pin)) + +/*------------------------------------------------------------------*/ +/* LED + *------------------------------------------------------------------*/ +#define LEDS_NUMBER 2 +#define LED_PRIMARY_PIN _PINNUM(1, 15) +#define LED_SECONDARY_PIN _PINNUM(1, 10) +#define LED_STATE_ON 1 + +#define LED_NEOPIXEL _PINNUM(0, 16) + +#define NEOPIXELS_NUMBER 1 +#define BOARD_RGB_BRIGHTNESS 0x040404 + +/*------------------------------------------------------------------*/ +/* BUTTON + *------------------------------------------------------------------*/ +#define BUTTONS_NUMBER 2 +#define BUTTON_1 _PINNUM(1, 02) +#define BUTTON_2 _PINNUM(1, 07) +#define BUTTON_PULL NRF_GPIO_PIN_PULLUP + +//--------------------------------------------------------------------+ +// BLE OTA +//--------------------------------------------------------------------+ +#define BLEDIS_MANUFACTURER "eAFAQ" +#define BLEDIS_MODEL "OMNIMO nRF52840" + +//--------------------------------------------------------------------+ +// USB +//--------------------------------------------------------------------+ + +//Shared VID/PID with pca10056 +#define USB_DESC_VID 0x239A +#define USB_DESC_UF2_PID 0x00DA +#define USB_DESC_CDC_ONLY_PID 0x00DA + +//------------- UF2 -------------// +#define UF2_PRODUCT_NAME "Omnimo nRF52840" +#define UF2_VOLUME_LABEL "OMNIn52BOOT" +#define UF2_BOARD_ID "nRF52840-Omnimo" +#define UF2_INDEX_URL "https://www.crowdsupply.com/eafaq/omnimo-nrf52840" + +#endif // _OMNIMO_NRF52840_H diff --git a/src/boards/omnimo_nrf52840/board.mk b/src/boards/omnimo_nrf52840/board.mk new file mode 100644 index 0000000..9d29ac6 --- /dev/null +++ b/src/boards/omnimo_nrf52840/board.mk @@ -0,0 +1 @@ +MCU_SUB_VARIANT = nrf52840 diff --git a/src/boards/omnimo_nrf52840/pinconfig.c b/src/boards/omnimo_nrf52840/pinconfig.c new file mode 100644 index 0000000..a983e4a --- /dev/null +++ b/src/boards/omnimo_nrf52840/pinconfig.c @@ -0,0 +1,19 @@ +#include "boards.h" +#include "uf2/configkeys.h" + +__attribute__((used, section(".bootloaderConfig"))) +const uint32_t bootloaderConfig[] = +{ + /* CF2 START */ + CFG_MAGIC0, CFG_MAGIC1, // magic + 5, 100, // used entries, total entries + + 204, 0x100000, // FLASH_BYTES = 0x100000 + 205, 0x40000, // RAM_BYTES = 0x40000 + 208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2 + 209, 0xada52840, // UF2_FAMILY = 0xada52840 + 210, 0x20, // PINS_PORT_SIZE = PA_32 + + 0, 0, 0, 0, 0, 0, 0, 0 + /* CF2 END */ +}; From 8970125e51544674747fa65b629e3c4ab71e486f Mon Sep 17 00:00:00 2001 From: OmarEMbed <62099184+OmarEMbed@users.noreply.github.com> Date: Sun, 16 Feb 2025 14:00:12 +0100 Subject: [PATCH 52/90] Update board.h --- src/boards/omnimo_nrf52840/board.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/boards/omnimo_nrf52840/board.h b/src/boards/omnimo_nrf52840/board.h index cf4e3a7..0a3b710 100644 --- a/src/boards/omnimo_nrf52840/board.h +++ b/src/boards/omnimo_nrf52840/board.h @@ -59,9 +59,9 @@ //--------------------------------------------------------------------+ //Shared VID/PID with pca10056 -#define USB_DESC_VID 0x239A -#define USB_DESC_UF2_PID 0x00DA -#define USB_DESC_CDC_ONLY_PID 0x00DA +#define USB_DESC_VID 0x1209 +#define USB_DESC_UF2_PID 0xCECE +#define USB_DESC_CDC_ONLY_PID 0xCECE //------------- UF2 -------------// #define UF2_PRODUCT_NAME "Omnimo nRF52840" From c83fa9fc2b7acc6c4beb171528d452514ffc570d Mon Sep 17 00:00:00 2001 From: Andreas Kurz Date: Sun, 4 May 2025 18:57:31 +0000 Subject: [PATCH 53/90] fix: array subscript 0 outside array bounds This will also add version 14.x of the compiler to apply additional CLFAGS. #339 Signed-off-by: Andreas Kurz --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 3235987..f345826 100644 --- a/Makefile +++ b/Makefile @@ -336,8 +336,8 @@ endif CFLAGS += -DDFU_APP_DATA_RESERVED=$(DFU_APP_DATA_RESERVED) # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105523 -# Fixes for gcc version 12 and 13. -ifneq (,$(filter 12.% 13.%,$(shell $(CC) -dumpversion 2>/dev/null))) +# Fixes for gcc version 12, 13 and 14. +ifneq (,$(filter 12.% 13.% 14.%,$(shell $(CC) -dumpversion 2>/dev/null))) CFLAGS += --param=min-pagesize=0 endif @@ -500,7 +500,7 @@ dfu-flash: flash-dfu flash-dfu: $(BUILD)/$(MERGED_FILE).zip @:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyACM0) $(NRFUTIL) --verbose dfu serial --package $< -p $(SERIAL) -b 115200 --singlebank --touch 1200 - + # flash skip crc magic ( app valid = 0x0001, crc = 0x0000 ) #flash-skip-crc: # nrfjprog --memwr $(BOOT_SETTING_ADDR) --val 0x00000001 -f nrf52 From 73020f3567b7ef7ed3bdbb6383d7b1cadeeb72d3 Mon Sep 17 00:00:00 2001 From: Andreas Kurz Date: Fri, 9 May 2025 08:15:14 +0000 Subject: [PATCH 54/90] fix: add size optimization This flag is also present in the Makefile and optimises the resulting binary for the size of the binary. Without that flag the flash consumption would be too high to fit inside the allocated space. Signed-off-by: Andreas Kurz --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 567a815..d621647 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -170,6 +170,7 @@ target_compile_options(bootloader PUBLIC -Wmissing-format-attribute -Wno-endif-labels -Wunreachable-code + -Os # Suppress warning caused by SDK -Wno-unused-parameter -Wno-expansion-to-defined -Wno-array-bounds ) @@ -333,4 +334,4 @@ add_custom_target(flash-mbr add_custom_target(flash-erase COMMAND ${NRFJPROG} -f nrf52 --eraseall - ) \ No newline at end of file + ) From ddcb2dba8c7090ced18a7a8b005ee79f168ae8e3 Mon Sep 17 00:00:00 2001 From: Andreas Kurz Date: Fri, 9 May 2025 10:31:05 +0200 Subject: [PATCH 55/90] chore: add documentation for CMake In this repository CMake and Make co-exists. Unfortunately there was no documentation on how to properly use CMake so this is a starting point. Signed-off-by: Andreas Kurz --- README.md | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b4e3cdb..2929ae2 100644 --- a/README.md +++ b/README.md @@ -114,14 +114,20 @@ You must have have a J-Link available to "unbrick" your device. ### Build: -Firstly clone this repo with following commands +Firstly clone this repo including its submodules with following command: +``` +git clone --recurse-submodules -j8 https://github.com/adafruit/Adafruit_nRF52_Bootloader +``` + +For git versions before `2.13.0` you have to do that manually: ``` git clone https://github.com/adafruit/Adafruit_nRF52_Bootloader cd Adafruit_nRF52_Bootloader git submodule update --init ``` +#### Build using `make` Then build it with `make BOARD={board} all`, for example: ``` @@ -137,6 +143,21 @@ Supported boards are: feather_nrf52840_express feather_nrf52840_express pca10056 Makefile:90: *** BOARD not defined. Stop ``` +#### Build using `cmake` + +Firstly initialize your build environment by passing your board to `cmake` via `-DBOARD={board}`: +``` +cmake -DBOARD=feather_nrf52840_express -S . -B _build -GNinja +``` + +And then build it with: +``` +cd _build +ninja +``` + +You can also use the generator of your choice. For example omit the `-GNinja` and then you can invoke `make` from inside `_build` instead of `ninja` + ### Flash To flash the bootloader (without softdevice/mbr) using JLink: From 389e5b004d112df4b406bde5d530b29db2bd9bb9 Mon Sep 17 00:00:00 2001 From: JuergenLeber Date: Sun, 8 Jun 2025 18:53:45 +0200 Subject: [PATCH 56/90] chore: update uf2 submodule to latest --- lib/uf2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/uf2 b/lib/uf2 index adbb8c7..b19ac9a 160000 --- a/lib/uf2 +++ b/lib/uf2 @@ -1 +1 @@ -Subproject commit adbb8c7260f938e810eb37f2287f8e1a055ff402 +Subproject commit b19ac9ad613e11a062e4d00845e2b80e6b0ad29f From 00b5e7249635795a66d6584ed3013f6a087a25c3 Mon Sep 17 00:00:00 2001 From: JuergenLeber Date: Sun, 8 Jun 2025 19:06:45 +0200 Subject: [PATCH 57/90] fix: fix small typo --- src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index 92ad020..dd66bd7 100644 --- a/src/main.c +++ b/src/main.c @@ -313,7 +313,7 @@ static void check_dfu_mode(void) { } } -// Initializes the SotdDevice by following SD specs section +// Initializes the SoftDevice by following SD specs section // "Master Boot Record and SoftDevice initializaton procedure" static uint32_t ble_stack_init(void) { // Forward vector table to bootloader address so that we can handle BLE events From b8544f5c8c7c1e5e185232b54fd9c696ceb17fc7 Mon Sep 17 00:00:00 2001 From: JuergenLeber Date: Sun, 8 Jun 2025 21:00:39 +0200 Subject: [PATCH 58/90] feat: add SD S340 support for nRF52840 and nRF52833 --- .github/workflows/githubci.yml | 2 +- .gitignore | 4 +++ CMakeLists.txt | 35 +++++++++++++++------- Makefile | 16 +++++++--- README.md | 19 ++++++++++++ lib/softdevice/s340_nrf52_7.0.1/readme.txt | 1 + src/main.c | 23 ++++++++++++-- 7 files changed, 82 insertions(+), 18 deletions(-) create mode 100644 lib/softdevice/s340_nrf52_7.0.1/readme.txt diff --git a/.github/workflows/githubci.yml b/.github/workflows/githubci.yml index 68b4f7f..55086fc 100644 --- a/.github/workflows/githubci.yml +++ b/.github/workflows/githubci.yml @@ -21,7 +21,7 @@ jobs: id: set-matrix working-directory: src/boards run: | - MATRIX_JSON=$(ls -d */ | sed 's/\/$//' | jq -R -s -c 'split("\n")[:-1]') + MATRIX_JSON=$(ls -d */ | sed 's/\/$//' | grep -vE '_s340$' | jq -R -s -c 'split("\n")[:-1]') echo "matrix=$MATRIX_JSON" echo "matrix=$MATRIX_JSON" >> $GITHUB_OUTPUT diff --git a/.gitignore b/.gitignore index 1c244fc..e7b13c9 100644 --- a/.gitignore +++ b/.gitignore @@ -65,3 +65,7 @@ TAGS .DS_Store Makefile.user + +# Exclude all SoftDevice S340 files +lib/softdevice/s340* + diff --git a/CMakeLists.txt b/CMakeLists.txt index 567a815..6d21fa6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -227,22 +227,37 @@ if (MCU_VARIANT STREQUAL "nrf52") S132 ) elseif (MCU_VARIANT STREQUAL "nrf52833") - set(SD_NAME s140) set(DFU_DEV_REV 52833) set(DFU_APP_DATA_RESERVED 7*4096) - target_compile_definitions(bootloader PUBLIC - NRF52833_XXAA - S140 - ) + if (SD_NAME STREQUAL "s340") + target_compile_definitions(bootloader PUBLIC + NRF52833_XXAA + S340 + ) + else () + set(SD_NAME s140) + target_compile_definitions(bootloader PUBLIC + NRF52833_XXAA + S140 + ) + endif () elseif (MCU_VARIANT STREQUAL "nrf52840") - set(SD_NAME s140) set(DFU_DEV_REV 52840) # App reserved 40KB (8+32) to match circuitpython for 840 set(DFU_APP_DATA_RESERVED 10*4096) - target_compile_definitions(bootloader PUBLIC - NRF52840_XXAA - S140 - ) + if (SD_NAME STREQUAL "s340") + target_compile_definitions(bootloader PUBLIC + NRF52840_XXAA + S340 + ) + else () + set(SD_NAME s140) + target_compile_definitions(bootloader PUBLIC + NRF52840_XXAA + S140 + ) + endif () + else () message(FATAL_ERROR "MCU_VARIANT ${MCU_VARIANT} is unknown") endif () diff --git a/Makefile b/Makefile index f345826..22ad007 100644 --- a/Makefile +++ b/Makefile @@ -109,14 +109,22 @@ ifeq ($(MCU_SUB_VARIANT),nrf52) CFLAGS += -DNRF52 -DNRF52832_XXAA -DS132 DFU_APP_DATA_RESERVED=7*4096 else ifeq ($(MCU_SUB_VARIANT),nrf52833) - SD_NAME = s140 + ifeq ($(SD_NAME),s340) + CFLAGS += -DNRF52833_XXAA -DS340 + else + SD_NAME = s140 + CFLAGS += -DNRF52833_XXAA -DS140 + endif DFU_DEV_REV = 52833 - CFLAGS += -DNRF52833_XXAA -DS140 DFU_APP_DATA_RESERVED=7*4096 else ifeq ($(MCU_SUB_VARIANT),nrf52840) - SD_NAME = s140 + ifeq ($(SD_NAME),s340) + CFLAGS += -DNRF52840_XXAA -DS340 + else + SD_NAME = s140 + CFLAGS += -DNRF52840_XXAA -DS140 + endif DFU_DEV_REV = 52840 - CFLAGS += -DNRF52840_XXAA -DS140 # App reserved 40KB (8+32) to match circuitpython for 840 DFU_APP_DATA_RESERVED=10*4096 else diff --git a/README.md b/README.md index b4e3cdb..ce2ab06 100644 --- a/README.md +++ b/README.md @@ -137,6 +137,25 @@ Supported boards are: feather_nrf52840_express feather_nrf52840_express pca10056 Makefile:90: *** BOARD not defined. Stop ``` +#### Working with SoftDevice S340: +The SoftDevice S340 is closed-source, not publicly available and is only distributed by Garmin Canada Inc. + +In order to be able to download the required ANT+ capable SoftDevice, you need to register an 'ANT+ Adopter' account at [thisisant.com](https://www.thisisant.com/register/). After around one business day you will receive access to the resources there. Then do the following steps: +- Download the SoftDevice S340 v7.0.1 [(here)](https://www.thisisant.com/developer/components/nrf52832#tab_protocol_stacks_tab) and extract its contents +- Under `lib/softdevice` in this repository there is a folder called `s340_nrf52_7.0.1` + - Copy the API folder `ANT_s340_nrf52_7.0.1.API`, the license agreement `License_Agreement_ANT_Softdevice_rev3_3.pdf` and the hex file `ANT_s340_nrf52_7.0.1.hex` from the extracted contents to it. + - Rename the API folder to `s340_nrf52_7.0.1_API` + - Rename the hex file to `s340_nrf52_7.0.1_softdevice.hex` + - Modify `lib/softdevice/s340_nrf52_7.0.1_API/include/nrf_sdm.h` on line 191 and remove the two slashes at the beginning of `//#define...` to use the *evaluation key* for the ANT SoftDevice. + - **VERY IMPORTANT:** You MUST obtain a valid commercial license key BEFORE releasing a product to market that uses the ANT SoftDevice! + +To add or modify a board with an ANT+ capable SoftDevice S340 the `SD_VERSION` and `SD_NAME` parameters in the corresponding `board.mk` file have to be set: +``` +SD_VERSION = 7.0.1 +SD_NAME = s340 +``` +**Important:** When adding a new board you must add the suffix `_s340` to the folder name to exclude it from automatic builds. + ### Flash To flash the bootloader (without softdevice/mbr) using JLink: diff --git a/lib/softdevice/s340_nrf52_7.0.1/readme.txt b/lib/softdevice/s340_nrf52_7.0.1/readme.txt new file mode 100644 index 0000000..3cde0e6 --- /dev/null +++ b/lib/softdevice/s340_nrf52_7.0.1/readme.txt @@ -0,0 +1 @@ +Place SoftDevice S340 v7.0.1 files here \ No newline at end of file diff --git a/src/main.c b/src/main.c index 92ad020..b48e1cb 100644 --- a/src/main.c +++ b/src/main.c @@ -157,6 +157,14 @@ static void mbr_init_sd(void) { sd_mbr_command(&com); } +// Helper function to check if SoftDevice is already enabled. +// Especially SoftDevice S340 locks up when calling sd_softdevice_disable() and it's not enabled. +static bool is_sd_enabled(void) { + uint8_t sd_enabled = 0; + sd_softdevice_is_enabled(&sd_enabled); + return (sd_enabled == 1); +} + //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ @@ -206,13 +214,16 @@ int main(void) { if (!_sd_inited) mbr_init_sd(); // Make sure SD is disabled - sd_softdevice_disable(); + if (is_sd_enabled()) { + sd_softdevice_disable(); + } } // clear in case we kept DFU_DBL_RESET_APP there (*dbl_reset_mem) = 0; // start application + PRINTF("Starting app...\r\n"); bootloader_app_start(); } @@ -306,7 +317,9 @@ static void check_dfu_mode(void) { } if (_ota_dfu) { - sd_softdevice_disable(); + if (is_sd_enabled()) { + sd_softdevice_disable(); + } } else { usb_teardown(); } @@ -326,7 +339,11 @@ static uint32_t ble_stack_init(void) { .rc_temp_ctiv = 2, .accuracy = NRF_CLOCK_LF_ACCURACY_250_PPM }; - sd_softdevice_enable(&clock_cfg, app_error_fault_handler); + #ifndef ANT_LICENSE_KEY + sd_softdevice_enable(&clock_cfg, app_error_fault_handler); + #else + sd_softdevice_enable(&clock_cfg, app_error_fault_handler, ANT_LICENSE_KEY); + #endif sd_nvic_EnableIRQ(SD_EVT_IRQn); /*------------- Configure BLE params -------------*/ From de9a9b79f4e60b68bda892e359276ec9be841273 Mon Sep 17 00:00:00 2001 From: JuergenLeber Date: Tue, 10 Jun 2025 18:44:51 +0200 Subject: [PATCH 59/90] refactor: deduplicate code for disabling SD --- src/main.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/main.c b/src/main.c index b48e1cb..2884993 100644 --- a/src/main.c +++ b/src/main.c @@ -157,12 +157,14 @@ static void mbr_init_sd(void) { sd_mbr_command(&com); } -// Helper function to check if SoftDevice is already enabled. +// Helper function to disable the SoftDevice with upfront check if it is enabled. // Especially SoftDevice S340 locks up when calling sd_softdevice_disable() and it's not enabled. -static bool is_sd_enabled(void) { +static void sd_disable(void) { uint8_t sd_enabled = 0; sd_softdevice_is_enabled(&sd_enabled); - return (sd_enabled == 1); + if (sd_enabled == 1) { + sd_softdevice_disable(); + } } //--------------------------------------------------------------------+ @@ -214,9 +216,7 @@ int main(void) { if (!_sd_inited) mbr_init_sd(); // Make sure SD is disabled - if (is_sd_enabled()) { - sd_softdevice_disable(); - } + sd_disable(); } // clear in case we kept DFU_DBL_RESET_APP there @@ -317,9 +317,7 @@ static void check_dfu_mode(void) { } if (_ota_dfu) { - if (is_sd_enabled()) { - sd_softdevice_disable(); - } + sd_disable(); } else { usb_teardown(); } From 3182f6036d6ecd690dafb655226169031e991251 Mon Sep 17 00:00:00 2001 From: JuergenLeber Date: Sun, 8 Jun 2025 19:04:20 +0200 Subject: [PATCH 60/90] fix: remove -lnosys option for debug linker scripts as it conflicts with RTT printf retarget --- linker/nrf52833_debug.ld | 2 +- linker/nrf52840_debug.ld | 2 +- linker/nrf52_debug.ld | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/linker/nrf52833_debug.ld b/linker/nrf52833_debug.ld index ed8f358..8898aa2 100644 --- a/linker/nrf52833_debug.ld +++ b/linker/nrf52833_debug.ld @@ -1,7 +1,7 @@ /* Linker script to configure memory regions. */ SEARCH_DIR(.) -GROUP(-lgcc -lc -lnosys) +GROUP(-lgcc -lc) MEMORY { diff --git a/linker/nrf52840_debug.ld b/linker/nrf52840_debug.ld index 7c68a83..2ca9fd6 100644 --- a/linker/nrf52840_debug.ld +++ b/linker/nrf52840_debug.ld @@ -1,7 +1,7 @@ /* Linker script to configure memory regions. */ SEARCH_DIR(.) -GROUP(-lgcc -lc -lnosys) +GROUP(-lgcc -lc) MEMORY { diff --git a/linker/nrf52_debug.ld b/linker/nrf52_debug.ld index b04b36a..2193ace 100644 --- a/linker/nrf52_debug.ld +++ b/linker/nrf52_debug.ld @@ -1,7 +1,7 @@ /* Linker script to configure memory regions. */ SEARCH_DIR(.) -GROUP(-lgcc -lc -lnosys) +GROUP(-lgcc -lc) MEMORY { From 70da7d88f4cdfd3eab65c4e8b3a6681b41393418 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 30 Jun 2025 10:45:38 +0700 Subject: [PATCH 61/90] set CMAKE_BUILD_TYPE to MinSizeRel if not defined instead of forcing -Os add CONFIG_GPIO_AS_PINRESET --- CMakeLists.txt | 14 ++++++++++++-- README.md | 30 +++++++++++++++++++++++------- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d621647..36d85f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,10 @@ set(TINYUSB_DIR ${CMAKE_CURRENT_LIST_DIR}/lib/tinyusb/src) set(UF2CONV_PY ${CMAKE_CURRENT_LIST_DIR}/lib/uf2/utils/uf2conv.py) set(UF2_FAMILY_ID_BOOTLOADER 0xd663823c) +if (NOT DEFINED CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "") + set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING "Build type" FORCE) +endif () + #------------------- # Bootloader #------------------- @@ -131,7 +135,6 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug") target_include_directories(bootloader PUBLIC lib/SEGGER_RTT/RTT ) - target_compile_definitions(bootloader PUBLIC CFG_DEBUG SEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL @@ -170,12 +173,12 @@ target_compile_options(bootloader PUBLIC -Wmissing-format-attribute -Wno-endif-labels -Wunreachable-code - -Os # Suppress warning caused by SDK -Wno-unused-parameter -Wno-expansion-to-defined -Wno-array-bounds ) target_compile_definitions(bootloader PUBLIC SOFTDEVICE_PRESENT + CONFIG_GPIO_AS_PINRESET ) if (TRACE_ETM STREQUAL "1") @@ -335,3 +338,10 @@ add_custom_target(flash-mbr add_custom_target(flash-erase COMMAND ${NRFJPROG} -f nrf52 --eraseall ) + +# flash skip crc magic ( app valid = 0x0001, crc = 0x0000 ) +#add_custom_target(flash-skip-crc +# #COMMAND ${NRFJPROG} --memwr $(BOOT_SETTING_ADDR) --val 0x00000001 -f nrf52 +# COMMAND ${NRFJPROG} --memwr 0xFF000 --val 0x00000001 -f nrf52 +# #COMMAND ${NRFJPROG} --memwr 0x7F000 --val 0x00000001 -f nrf52 +# ) diff --git a/README.md b/README.md index 2929ae2..4c7066f 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,7 @@ You must have have a J-Link available to "unbrick" your device. Firstly clone this repo including its submodules with following command: ``` -git clone --recurse-submodules -j8 https://github.com/adafruit/Adafruit_nRF52_Bootloader +git clone --recurse-submodules https://github.com/adafruit/Adafruit_nRF52_Bootloader ``` For git versions before `2.13.0` you have to do that manually: @@ -146,17 +146,33 @@ Makefile:90: *** BOARD not defined. Stop #### Build using `cmake` Firstly initialize your build environment by passing your board to `cmake` via `-DBOARD={board}`: -``` -cmake -DBOARD=feather_nrf52840_express -S . -B _build -GNinja + +```bash +mkdir build +cd build +cmake .. -DBOARD=feather_nrf52840_express ``` And then build it with: -``` -cd _build -ninja + +```bash +make ``` -You can also use the generator of your choice. For example omit the `-GNinja` and then you can invoke `make` from inside `_build` instead of `ninja` +You can also use the generator of your choice. For example adding the `-GNinja` and then you can invoke `ninja build` instead of `make`. + +To list all supported targets, run: + +```bash +cmake --build . --target help +``` + +To build individual targets, you can specify it directly with `make` or using `cmake --build`: + +```bash +make bootloader +cmake --build . --target bootloader +``` ### Flash From 31c3081668c0ffe0215c125b88d3cb5c2447050e Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 30 Jun 2025 17:32:49 +0700 Subject: [PATCH 62/90] update makefile/cmake for softdevice macro. Remove the _s340 filter in ci --- .github/workflows/githubci.yml | 2 +- CMakeLists.txt | 34 ++++++----------------- Makefile | 25 ++++++++--------- lib/softdevice/s340_nrf52_7.0.1/readme.md | 3 +- src/main.c | 15 +++++----- 5 files changed, 29 insertions(+), 50 deletions(-) diff --git a/.github/workflows/githubci.yml b/.github/workflows/githubci.yml index 55086fc..68b4f7f 100644 --- a/.github/workflows/githubci.yml +++ b/.github/workflows/githubci.yml @@ -21,7 +21,7 @@ jobs: id: set-matrix working-directory: src/boards run: | - MATRIX_JSON=$(ls -d */ | sed 's/\/$//' | grep -vE '_s340$' | jq -R -s -c 'split("\n")[:-1]') + MATRIX_JSON=$(ls -d */ | sed 's/\/$//' | jq -R -s -c 'split("\n")[:-1]') echo "matrix=$MATRIX_JSON" echo "matrix=$MATRIX_JSON" >> $GITHUB_OUTPUT diff --git a/CMakeLists.txt b/CMakeLists.txt index e66a274..7133135 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -225,47 +225,29 @@ if (MCU_VARIANT STREQUAL "nrf52") set(SD_NAME s132) set(DFU_DEV_REV 0xADAF) set(DFU_APP_DATA_RESERVED 7*4096) - target_compile_definitions(bootloader PUBLIC - NRF52 - NRF52832_XXAA - S132 - ) + target_compile_definitions(bootloader PUBLIC NRF52 NRF52832_XXAA) elseif (MCU_VARIANT STREQUAL "nrf52833") set(DFU_DEV_REV 52833) set(DFU_APP_DATA_RESERVED 7*4096) - if (SD_NAME STREQUAL "s340") - target_compile_definitions(bootloader PUBLIC - NRF52833_XXAA - S340 - ) - else () + target_compile_definitions(bootloader PUBLIC NRF52833_XXAA) + if (NOT DEFINED SD_NAME) set(SD_NAME s140) - target_compile_definitions(bootloader PUBLIC - NRF52833_XXAA - S140 - ) endif () elseif (MCU_VARIANT STREQUAL "nrf52840") set(DFU_DEV_REV 52840) # App reserved 40KB (8+32) to match circuitpython for 840 set(DFU_APP_DATA_RESERVED 10*4096) - if (SD_NAME STREQUAL "s340") - target_compile_definitions(bootloader PUBLIC - NRF52840_XXAA - S340 - ) - else () + target_compile_definitions(bootloader PUBLIC NRF52840_XXAA) + if (NOT DEFINED SD_NAME) set(SD_NAME s140) - target_compile_definitions(bootloader PUBLIC - NRF52840_XXAA - S140 - ) endif () - else () message(FATAL_ERROR "MCU_VARIANT ${MCU_VARIANT} is unknown") endif () +string(TOUPPER ${SD_NAME} SD_NAME_UPPER) +target_compile_definitions(bootloader PUBLIC ${SD_NAME_UPPER}) + set(SD_FILENAME ${SD_NAME}_nrf52_${SD_VERSION}) set(SD_HEX ${SOFTDEVICE_DIR}/${SD_FILENAME}/${SD_FILENAME}_softdevice.hex) diff --git a/Makefile b/Makefile index 22ad007..bea75cf 100644 --- a/Makefile +++ b/Makefile @@ -104,33 +104,32 @@ BIN = _bin/$(BOARD) # MCU_SUB_VARIANT can be nrf52 (nrf52832), nrf52833, nrf52840 ifeq ($(MCU_SUB_VARIANT),nrf52) + CFLAGS += -DNRF52 -DNRF52832_XXAA SD_NAME = s132 DFU_DEV_REV = 0xADAF - CFLAGS += -DNRF52 -DNRF52832_XXAA -DS132 DFU_APP_DATA_RESERVED=7*4096 else ifeq ($(MCU_SUB_VARIANT),nrf52833) - ifeq ($(SD_NAME),s340) - CFLAGS += -DNRF52833_XXAA -DS340 - else - SD_NAME = s140 - CFLAGS += -DNRF52833_XXAA -DS140 - endif + CFLAGS += -DNRF52833_XXAA DFU_DEV_REV = 52833 DFU_APP_DATA_RESERVED=7*4096 + ifndef SD_NAME + SD_NAME = s140 + endif else ifeq ($(MCU_SUB_VARIANT),nrf52840) - ifeq ($(SD_NAME),s340) - CFLAGS += -DNRF52840_XXAA -DS340 - else - SD_NAME = s140 - CFLAGS += -DNRF52840_XXAA -DS140 - endif + CFLAGS += -DNRF52840_XXAA DFU_DEV_REV = 52840 # App reserved 40KB (8+32) to match circuitpython for 840 DFU_APP_DATA_RESERVED=10*4096 + ifndef SD_NAME + SD_NAME = s140 + endif else $(error Sub Variant $(MCU_SUB_VARIANT) is unknown) endif +SD_NAME_UPPER = $(subst s,S,${SD_NAME}) +CFLAGS += -D$(SD_NAME_UPPER) + #------------------------------------------------------------------------------ # SOURCE FILES #------------------------------------------------------------------------------ diff --git a/lib/softdevice/s340_nrf52_7.0.1/readme.md b/lib/softdevice/s340_nrf52_7.0.1/readme.md index 55b790b..c408bbd 100644 --- a/lib/softdevice/s340_nrf52_7.0.1/readme.md +++ b/lib/softdevice/s340_nrf52_7.0.1/readme.md @@ -15,5 +15,4 @@ To add or modify a board with an ANT+ capable SoftDevice S340 the `SD_VERSION` a ``` SD_VERSION = 7.0.1 SD_NAME = s340 -``` -**Important:** When adding a new board you must add the suffix `_s340` to the folder name to exclude it from automatic builds. \ No newline at end of file +``` \ No newline at end of file diff --git a/src/main.c b/src/main.c index cd9de87..a4c0a70 100644 --- a/src/main.c +++ b/src/main.c @@ -157,9 +157,8 @@ static void mbr_init_sd(void) { sd_mbr_command(&com); } -// Helper function to disable the SoftDevice with upfront check if it is enabled. -// Especially SoftDevice S340 locks up when calling sd_softdevice_disable() and it's not enabled. -static void sd_disable(void) { +// Disable the SoftDevice if it is enabled. +static void disable_softdevice(void) { uint8_t sd_enabled = 0; sd_softdevice_is_enabled(&sd_enabled); if (sd_enabled == 1) { @@ -216,7 +215,7 @@ int main(void) { if (!_sd_inited) mbr_init_sd(); // Make sure SD is disabled - sd_disable(); + disable_softdevice(); } // clear in case we kept DFU_DBL_RESET_APP there @@ -317,7 +316,7 @@ static void check_dfu_mode(void) { } if (_ota_dfu) { - sd_disable(); + disable_softdevice(); } else { usb_teardown(); } @@ -337,10 +336,10 @@ static uint32_t ble_stack_init(void) { .rc_temp_ctiv = 2, .accuracy = NRF_CLOCK_LF_ACCURACY_250_PPM }; - #ifndef ANT_LICENSE_KEY - sd_softdevice_enable(&clock_cfg, app_error_fault_handler); - #else + #ifdef ANT_LICENSE_KEY sd_softdevice_enable(&clock_cfg, app_error_fault_handler, ANT_LICENSE_KEY); + #else + sd_softdevice_enable(&clock_cfg, app_error_fault_handler); #endif sd_nvic_EnableIRQ(SD_EVT_IRQn); From fa1caccd67536f9c90a1d76683163ebdfa712dd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Leber?= Date: Mon, 27 Oct 2025 20:57:29 +0100 Subject: [PATCH 63/90] feat: add ANT_LICENSE_KEY handling for SoftDevice S340 --- CMakeLists.txt | 7 +++++++ Makefile | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7133135..a78a250 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -259,6 +259,13 @@ if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug") target_compile_definitions(bootloader PUBLIC DFU_APP_DATA_RESERVED=${DFU_APP_DATA_RESERVED}) endif () +#---------------------------------- +# ANT_LICENSE_KEY handling +#---------------------------------- +if (DEFINED ANT_LICENSE_KEY) + target_compile_definitions(bootloader PUBLIC ANT_LICENSE_KEY=${ANT_LICENSE_KEY}) +endif + #---------------------------------- # Get UF2 version from git #---------------------------------- diff --git a/Makefile b/Makefile index bea75cf..326a709 100644 --- a/Makefile +++ b/Makefile @@ -130,6 +130,13 @@ endif SD_NAME_UPPER = $(subst s,S,${SD_NAME}) CFLAGS += -D$(SD_NAME_UPPER) +#---------------------------------- +# ANT_LICENSE_KEY handling +#---------------------------------- +ifdef ANT_LICENSE_KEY + CFLAGS += -DANT_LICENSE_KEY=\"$(ANT_LICENSE_KEY)\" +endif + #------------------------------------------------------------------------------ # SOURCE FILES #------------------------------------------------------------------------------ From 4ca93c51394e2907333f4a7d475ec6a566ff0af0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Leber?= Date: Mon, 27 Oct 2025 21:05:08 +0100 Subject: [PATCH 64/90] feat: adjust documentation for builds with SoftDevice S340 --- lib/softdevice/s340_nrf52_7.0.1/readme.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/softdevice/s340_nrf52_7.0.1/readme.md b/lib/softdevice/s340_nrf52_7.0.1/readme.md index c408bbd..95a0fee 100644 --- a/lib/softdevice/s340_nrf52_7.0.1/readme.md +++ b/lib/softdevice/s340_nrf52_7.0.1/readme.md @@ -5,12 +5,17 @@ The SoftDevice S340 is closed-source, not publicly available and is only distrib In order to be able to download the required ANT+ capable SoftDevice and place SoftDevice S340 v7.0.1 files here. You need to register an 'ANT+ Adopter' account at [thisisant.com](https://www.thisisant.com/register/). After around one business day you will receive access to the resources there. Then do the following steps: - Download the SoftDevice S340 v7.0.1 [(here)](https://www.thisisant.com/developer/components/nrf52832#tab_protocol_stacks_tab) and extract its contents - Under `lib/softdevice` in this repository there is a folder called `s340_nrf52_7.0.1` - - Copy the API folder `ANT_s340_nrf52_7.0.1.API`, the license agreement `License_Agreement_ANT_Softdevice_rev3_3.pdf` and the hex file `ANT_s340_nrf52_7.0.1.hex` from the extracted contents to it. + - Copy the API folder `ANT_s340_nrf52_7.0.1.API`, the license agreement `License_Agreement_ANT_Softdevice_rev3_3.pdf` and the hex file `ANT_s340_nrf52_7.0.1.hex` from the extracted contents to it - Rename the API folder to `s340_nrf52_7.0.1_API` - Rename the hex file to `s340_nrf52_7.0.1_softdevice.hex` - - Modify `lib/softdevice/s340_nrf52_7.0.1_API/include/nrf_sdm.h` on line 191 and remove the two slashes at the beginning of `//#define...` to use the *evaluation key* for the ANT SoftDevice. + - Check `lib/softdevice/s340_nrf52_7.0.1_API/include/nrf_sdm.h` on line 191 to get an *evaluation key* for the ANT SoftDevice which can later be used for the `ANT_LICENSE_KEY` parameter - **VERY IMPORTANT:** You MUST obtain a valid commercial license key BEFORE releasing a product to market that uses the ANT SoftDevice! +To use the SoftDevice S340 with an existing board the `SD_NAME`, `SD_VERSION` and `ANT_LICENSE_KEY` parameters can just be passed to the command line of the `make` command, e.g.: +``` +make BOARD=xiao_nrf52840_ble_sense SD_NAME=s340 SD_VERSION=7.0.1 ANT_LICENSE_KEY= all +``` + To add or modify a board with an ANT+ capable SoftDevice S340 the `SD_VERSION` and `SD_NAME` parameters in the corresponding `board.mk` file have to be set: ``` SD_VERSION = 7.0.1 From 6250be4bf1c4efb8e402f157af4663f1cd7c6419 Mon Sep 17 00:00:00 2001 From: Tomasz Duda Date: Tue, 11 Nov 2025 21:50:29 +0100 Subject: [PATCH 65/90] fix boot loop due to wrong value read from REGOUT0 --- src/boards/boards.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/boards/boards.c b/src/boards/boards.c index 9eaf7b0..87842a3 100644 --- a/src/boards/boards.c +++ b/src/boards/boards.c @@ -111,6 +111,12 @@ void board_init(void) { // #define UICR_REGOUT0_VALUE UICR_REGOUT0_VOUT_3V3 // in board.h when using that power configuration. #ifdef UICR_REGOUT0_VALUE + // for some reason bellow condition is true even though debugger show 3.0V + // pyocd> rw 0x10001304 + // 10001304: fffffffc + // it leads to infinite boot loop. Let wait for NVM to be ready first. + NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos; + while (NRF_NVMC->READY == NVMC_READY_READY_Busy){} if ((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) == (UICR_REGOUT0_VOUT_DEFAULT << UICR_REGOUT0_VOUT_Pos)){ NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos; while (NRF_NVMC->READY == NVMC_READY_READY_Busy){} @@ -119,8 +125,10 @@ void board_init(void) { NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos; while (NRF_NVMC->READY == NVMC_READY_READY_Busy){} - - NVIC_SystemReset(); + // to avoid infinity boot loop reset only if REGOUT0 was set correctly + if((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) == (UICR_REGOUT0_VALUE << UICR_REGOUT0_VOUT_Pos)){ + NVIC_SystemReset(); + } } #endif From 4493a352cbf377bff913b58993594d6dd45148df Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 Dec 2025 16:42:31 +0700 Subject: [PATCH 66/90] add board.cmake --- src/boards/adm_b_nrf52840_1/board.cmake | 1 + src/boards/ae_bl652_bo/board.cmake | 1 + src/boards/aramcon2_badge/board.cmake | 1 + src/boards/aramcon_badge_2019/board.cmake | 1 + src/boards/arcade_feather_nrf52840_express/board.cmake | 1 + src/boards/arduino_nano_33_ble/board.cmake | 1 + src/boards/bast_ble/board.cmake | 1 + src/boards/bluemicro_nrf52833/board.cmake | 1 + src/boards/bluemicro_nrf52840/board.cmake | 1 + src/boards/challenger_840_ble/board.cmake | 1 + src/boards/ebyte_e104_bt5032a/board.cmake | 1 + src/boards/ebyte_e73_tbb/board.cmake | 1 + src/boards/electronut_labs_papyr/board.cmake | 1 + src/boards/feather_nrf52832/board.cmake | 1 + src/boards/feather_nrf52833_express/board.cmake | 1 + src/boards/feather_nrf52840_sense/board.cmake | 1 + src/boards/ikigaisense_vita/board.cmake | 1 + src/boards/ledglasses_nrf52840/board.cmake | 1 + src/boards/m60_keyboard/board.cmake | 1 + src/boards/mbn52832dk/board.cmake | 1 + src/boards/mdk_nrf52840_dongle/board.cmake | 1 + src/boards/metro_nrf52840_express/board.cmake | 1 + src/boards/mikoto/board.cmake | 1 + src/boards/nRF52840_connect_kit/board.cmake | 1 + src/boards/nice_nano/board.cmake | 1 + src/boards/nrf52840_bboard/board.cmake | 1 + src/boards/nrf52840_m2/board.cmake | 1 + src/boards/nrfmicro/board.cmake | 1 + src/boards/ohs2020_badge/board.cmake | 1 + src/boards/particle_argon/board.cmake | 1 + src/boards/particle_boron/board.cmake | 1 + src/boards/particle_xenon/board.cmake | 1 + src/boards/pca10059/board.cmake | 1 + src/boards/pillbug/board.cmake | 1 + src/boards/pitaya_go/board.cmake | 1 + src/boards/raytac_mdbt50q_db_40/board.cmake | 1 + src/boards/raytac_mdbt50q_rx/board.cmake | 1 + src/boards/sparkfun_nrf52840_micromod/board.cmake | 1 + src/boards/t1000_e/board.cmake | 1 + src/boards/waveshare_nrf52840_eval/board.cmake | 1 + src/boards/xiao_nrf52840_ble/board.cmake | 1 + src/boards/xiao_nrf52840_ble_sense/board.cmake | 1 + 42 files changed, 42 insertions(+) create mode 100644 src/boards/adm_b_nrf52840_1/board.cmake create mode 100644 src/boards/ae_bl652_bo/board.cmake create mode 100644 src/boards/aramcon2_badge/board.cmake create mode 100644 src/boards/aramcon_badge_2019/board.cmake create mode 100644 src/boards/arcade_feather_nrf52840_express/board.cmake create mode 100644 src/boards/arduino_nano_33_ble/board.cmake create mode 100644 src/boards/bast_ble/board.cmake create mode 100644 src/boards/bluemicro_nrf52833/board.cmake create mode 100644 src/boards/bluemicro_nrf52840/board.cmake create mode 100644 src/boards/challenger_840_ble/board.cmake create mode 100644 src/boards/ebyte_e104_bt5032a/board.cmake create mode 100644 src/boards/ebyte_e73_tbb/board.cmake create mode 100644 src/boards/electronut_labs_papyr/board.cmake create mode 100644 src/boards/feather_nrf52832/board.cmake create mode 100644 src/boards/feather_nrf52833_express/board.cmake create mode 100644 src/boards/feather_nrf52840_sense/board.cmake create mode 100644 src/boards/ikigaisense_vita/board.cmake create mode 100644 src/boards/ledglasses_nrf52840/board.cmake create mode 100644 src/boards/m60_keyboard/board.cmake create mode 100644 src/boards/mbn52832dk/board.cmake create mode 100644 src/boards/mdk_nrf52840_dongle/board.cmake create mode 100644 src/boards/metro_nrf52840_express/board.cmake create mode 100644 src/boards/mikoto/board.cmake create mode 100644 src/boards/nRF52840_connect_kit/board.cmake create mode 100644 src/boards/nice_nano/board.cmake create mode 100644 src/boards/nrf52840_bboard/board.cmake create mode 100644 src/boards/nrf52840_m2/board.cmake create mode 100644 src/boards/nrfmicro/board.cmake create mode 100644 src/boards/ohs2020_badge/board.cmake create mode 100644 src/boards/particle_argon/board.cmake create mode 100644 src/boards/particle_boron/board.cmake create mode 100644 src/boards/particle_xenon/board.cmake create mode 100644 src/boards/pca10059/board.cmake create mode 100644 src/boards/pillbug/board.cmake create mode 100644 src/boards/pitaya_go/board.cmake create mode 100644 src/boards/raytac_mdbt50q_db_40/board.cmake create mode 100644 src/boards/raytac_mdbt50q_rx/board.cmake create mode 100644 src/boards/sparkfun_nrf52840_micromod/board.cmake create mode 100644 src/boards/t1000_e/board.cmake create mode 100644 src/boards/waveshare_nrf52840_eval/board.cmake create mode 100644 src/boards/xiao_nrf52840_ble/board.cmake create mode 100644 src/boards/xiao_nrf52840_ble_sense/board.cmake diff --git a/src/boards/adm_b_nrf52840_1/board.cmake b/src/boards/adm_b_nrf52840_1/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/adm_b_nrf52840_1/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/ae_bl652_bo/board.cmake b/src/boards/ae_bl652_bo/board.cmake new file mode 100644 index 0000000..e1b9ded --- /dev/null +++ b/src/boards/ae_bl652_bo/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52) diff --git a/src/boards/aramcon2_badge/board.cmake b/src/boards/aramcon2_badge/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/aramcon2_badge/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/aramcon_badge_2019/board.cmake b/src/boards/aramcon_badge_2019/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/aramcon_badge_2019/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/arcade_feather_nrf52840_express/board.cmake b/src/boards/arcade_feather_nrf52840_express/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/arcade_feather_nrf52840_express/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/arduino_nano_33_ble/board.cmake b/src/boards/arduino_nano_33_ble/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/arduino_nano_33_ble/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/bast_ble/board.cmake b/src/boards/bast_ble/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/bast_ble/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/bluemicro_nrf52833/board.cmake b/src/boards/bluemicro_nrf52833/board.cmake new file mode 100644 index 0000000..cb4f2f9 --- /dev/null +++ b/src/boards/bluemicro_nrf52833/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52833) diff --git a/src/boards/bluemicro_nrf52840/board.cmake b/src/boards/bluemicro_nrf52840/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/bluemicro_nrf52840/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/challenger_840_ble/board.cmake b/src/boards/challenger_840_ble/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/challenger_840_ble/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/ebyte_e104_bt5032a/board.cmake b/src/boards/ebyte_e104_bt5032a/board.cmake new file mode 100644 index 0000000..e1b9ded --- /dev/null +++ b/src/boards/ebyte_e104_bt5032a/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52) diff --git a/src/boards/ebyte_e73_tbb/board.cmake b/src/boards/ebyte_e73_tbb/board.cmake new file mode 100644 index 0000000..e1b9ded --- /dev/null +++ b/src/boards/ebyte_e73_tbb/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52) diff --git a/src/boards/electronut_labs_papyr/board.cmake b/src/boards/electronut_labs_papyr/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/electronut_labs_papyr/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/feather_nrf52832/board.cmake b/src/boards/feather_nrf52832/board.cmake new file mode 100644 index 0000000..e1b9ded --- /dev/null +++ b/src/boards/feather_nrf52832/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52) diff --git a/src/boards/feather_nrf52833_express/board.cmake b/src/boards/feather_nrf52833_express/board.cmake new file mode 100644 index 0000000..cb4f2f9 --- /dev/null +++ b/src/boards/feather_nrf52833_express/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52833) diff --git a/src/boards/feather_nrf52840_sense/board.cmake b/src/boards/feather_nrf52840_sense/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/feather_nrf52840_sense/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/ikigaisense_vita/board.cmake b/src/boards/ikigaisense_vita/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/ikigaisense_vita/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/ledglasses_nrf52840/board.cmake b/src/boards/ledglasses_nrf52840/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/ledglasses_nrf52840/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/m60_keyboard/board.cmake b/src/boards/m60_keyboard/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/m60_keyboard/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/mbn52832dk/board.cmake b/src/boards/mbn52832dk/board.cmake new file mode 100644 index 0000000..e1b9ded --- /dev/null +++ b/src/boards/mbn52832dk/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52) diff --git a/src/boards/mdk_nrf52840_dongle/board.cmake b/src/boards/mdk_nrf52840_dongle/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/mdk_nrf52840_dongle/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/metro_nrf52840_express/board.cmake b/src/boards/metro_nrf52840_express/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/metro_nrf52840_express/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/mikoto/board.cmake b/src/boards/mikoto/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/mikoto/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/nRF52840_connect_kit/board.cmake b/src/boards/nRF52840_connect_kit/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/nRF52840_connect_kit/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/nice_nano/board.cmake b/src/boards/nice_nano/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/nice_nano/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/nrf52840_bboard/board.cmake b/src/boards/nrf52840_bboard/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/nrf52840_bboard/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/nrf52840_m2/board.cmake b/src/boards/nrf52840_m2/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/nrf52840_m2/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/nrfmicro/board.cmake b/src/boards/nrfmicro/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/nrfmicro/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/ohs2020_badge/board.cmake b/src/boards/ohs2020_badge/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/ohs2020_badge/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/particle_argon/board.cmake b/src/boards/particle_argon/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/particle_argon/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/particle_boron/board.cmake b/src/boards/particle_boron/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/particle_boron/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/particle_xenon/board.cmake b/src/boards/particle_xenon/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/particle_xenon/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/pca10059/board.cmake b/src/boards/pca10059/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/pca10059/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/pillbug/board.cmake b/src/boards/pillbug/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/pillbug/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/pitaya_go/board.cmake b/src/boards/pitaya_go/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/pitaya_go/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/raytac_mdbt50q_db_40/board.cmake b/src/boards/raytac_mdbt50q_db_40/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/raytac_mdbt50q_db_40/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/raytac_mdbt50q_rx/board.cmake b/src/boards/raytac_mdbt50q_rx/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/raytac_mdbt50q_rx/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/sparkfun_nrf52840_micromod/board.cmake b/src/boards/sparkfun_nrf52840_micromod/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/sparkfun_nrf52840_micromod/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/t1000_e/board.cmake b/src/boards/t1000_e/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/t1000_e/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/waveshare_nrf52840_eval/board.cmake b/src/boards/waveshare_nrf52840_eval/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/waveshare_nrf52840_eval/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/xiao_nrf52840_ble/board.cmake b/src/boards/xiao_nrf52840_ble/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/xiao_nrf52840_ble/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) diff --git a/src/boards/xiao_nrf52840_ble_sense/board.cmake b/src/boards/xiao_nrf52840_ble_sense/board.cmake new file mode 100644 index 0000000..25daf71 --- /dev/null +++ b/src/boards/xiao_nrf52840_ble_sense/board.cmake @@ -0,0 +1 @@ +set(MCU_VARIANT nrf52840) From d7e4a2572a5d07263b44bd4c9bc849220a47028b Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 Dec 2025 17:25:24 +0700 Subject: [PATCH 67/90] update cmake build --- CMakeLists.txt | 30 +- cmake/cpu/cortex-m4.cmake | 29 +- cmake/toolchain/arm_gcc.cmake | 22 +- cmake/toolchain/set_flags.cmake | 17 - linker/nrf52.ld | 6 +- linker/nrf52833.ld | 2 +- linker/nrf52833_debug.ld | 2 +- linker/nrf52840.ld | 9 +- linker/nrf52840_debug.ld | 2 +- linker/nrf52_debug.ld | 2 +- segger/Adafruit_nRF52_Bootloader.emProject | 363 - segger/SEGGER_RTT.c | 1329 -- segger/SEGGER_RTT.h | 234 - segger/SEGGER_RTT_Conf.h | 242 - segger/SEGGER_RTT_SES.c | 76 - segger/flash_placement.xml | 43 - segger/nRF52832_xxAA_MemoryMap.xml | 10 - segger/nRF52840_xxAA_MemoryMap.xml | 10 - segger/nRF_Target.js | 19 - segger/nrf52840_Registers.xml | 22310 ------------------- segger/thumb_crt0.s | 420 - 21 files changed, 33 insertions(+), 25144 deletions(-) delete mode 100644 cmake/toolchain/set_flags.cmake delete mode 100644 segger/Adafruit_nRF52_Bootloader.emProject delete mode 100644 segger/SEGGER_RTT.c delete mode 100644 segger/SEGGER_RTT.h delete mode 100644 segger/SEGGER_RTT_Conf.h delete mode 100644 segger/SEGGER_RTT_SES.c delete mode 100644 segger/flash_placement.xml delete mode 100644 segger/nRF52832_xxAA_MemoryMap.xml delete mode 100644 segger/nRF52840_xxAA_MemoryMap.xml delete mode 100644 segger/nRF_Target.js delete mode 100644 segger/nrf52840_Registers.xml delete mode 100644 segger/thumb_crt0.s diff --git a/CMakeLists.txt b/CMakeLists.txt index a78a250..ae9b9cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,14 +1,11 @@ cmake_minimum_required(VERSION 3.17) +include(CMakePrintHelpers) find_package(Python COMPONENTS Interpreter) if (NOT DEFINED BOARD) message(FATAL_ERROR "BOARD is not defined") endif () -if (NOT DEFINED TOOLCHAIN) - set(TOOLCHAIN gcc) -endif () - # include board specific include(${CMAKE_CURRENT_LIST_DIR}/src/boards/${BOARD}/board.cmake) @@ -21,7 +18,8 @@ else () set(JLINK_DEVICE ${MCU_VARIANT}_xxaa) endif () -set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/cmake/toolchain/arm_${TOOLCHAIN}.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/cmake/toolchain/arm_gcc.cmake) + project(Adafruit_nRF52_Bootloader C ASM) @@ -153,6 +151,7 @@ endif () target_link_options(bootloader PUBLIC "LINKER:--script=${LD_FILE}" -L${NRFX_DIR}/mdk + -nostartfiles --specs=nosys.specs --specs=nano.specs ) target_compile_options(bootloader PUBLIC @@ -179,6 +178,8 @@ target_compile_options(bootloader PUBLIC target_compile_definitions(bootloader PUBLIC SOFTDEVICE_PRESENT CONFIG_GPIO_AS_PINRESET + __START=main + __STARTUP_CLEAR_BSS ) if (TRACE_ETM STREQUAL "1") @@ -264,7 +265,7 @@ endif () #---------------------------------- if (DEFINED ANT_LICENSE_KEY) target_compile_definitions(bootloader PUBLIC ANT_LICENSE_KEY=${ANT_LICENSE_KEY}) -endif +endif() #---------------------------------- # Get UF2 version from git @@ -296,15 +297,6 @@ target_compile_definitions(bootloader PUBLIC MK_BOOTLOADER_VERSION=${MK_BOOTLOADER_VERSION} ) -#---------------------------------- -# Post build -#---------------------------------- - -# run size after build -add_custom_command(TARGET bootloader POST_BUILD - COMMAND ${CMAKE_SIZE} $ - ) - # Add bin/hex output add_custom_command(TARGET bootloader POST_BUILD COMMAND ${CMAKE_OBJCOPY} -Obinary $ $/bootloader.bin @@ -316,12 +308,11 @@ add_custom_command(TARGET bootloader POST_BUILD #---------------------------------- # Flashing target #---------------------------------- - if (NOT DEFINED NRFJPROG) set(NRFJPROG nrfjprog) endif() -add_custom_target(flash-jlink +add_custom_target(flash-bootloader DEPENDS bootloader COMMAND ${NRFJPROG} --program $ --verify --sectoranduicrerase -f nrf52 --reset ) @@ -332,6 +323,7 @@ add_custom_target(flash-uf2 ) add_custom_target(flash-sd + DEPENDS flash-mbr COMMAND ${NRFJPROG} --program ${SD_HEX} --verify --sectorerase -f nrf52 --reset ) @@ -343,6 +335,10 @@ add_custom_target(flash-erase COMMAND ${NRFJPROG} -f nrf52 --eraseall ) +add_custom_target(flash-all + DEPENDS flash-erase flash-sd flash-bootloader + ) + # flash skip crc magic ( app valid = 0x0001, crc = 0x0000 ) #add_custom_target(flash-skip-crc # #COMMAND ${NRFJPROG} --memwr $(BOOT_SETTING_ADDR) --val 0x00000001 -f nrf52 diff --git a/cmake/cpu/cortex-m4.cmake b/cmake/cpu/cortex-m4.cmake index 79f97e2..91a615d 100644 --- a/cmake/cpu/cortex-m4.cmake +++ b/cmake/cpu/cortex-m4.cmake @@ -1,23 +1,6 @@ -if (TOOLCHAIN STREQUAL "gcc") - set(TOOLCHAIN_COMMON_FLAGS - -mthumb - -mcpu=cortex-m4 - -mfloat-abi=hard - -mfpu=fpv4-sp-d16 - ) - - if (NOT DEFINED FREERTOS_PORT) - set(FREERTOS_PORT GCC_ARM_CM4F CACHE INTERNAL "") - endif () - -elseif (TOOLCHAIN STREQUAL "iar") - set(TOOLCHAIN_COMMON_FLAGS - --cpu cortex-m4 - --fpu VFPv4 - ) - - if (NOT DEFINED FREERTOS_PORT) - set(FREERTOS_PORT IAR_ARM_CM4F CACHE INTERNAL "") - endif () - -endif () +set(TOOLCHAIN_COMMON_FLAGS + -mthumb + -mcpu=cortex-m4 + -mfloat-abi=hard + -mfpu=fpv4-sp-d16 +) \ No newline at end of file diff --git a/cmake/toolchain/arm_gcc.cmake b/cmake/toolchain/arm_gcc.cmake index 5203d1e..d11826c 100644 --- a/cmake/toolchain/arm_gcc.cmake +++ b/cmake/toolchain/arm_gcc.cmake @@ -3,10 +3,7 @@ set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_C_COMPILER "arm-none-eabi-gcc") set(CMAKE_CXX_COMPILER "arm-none-eabi-g++") set(CMAKE_ASM_COMPILER "arm-none-eabi-gcc") - -set(CMAKE_SIZE "arm-none-eabi-size" CACHE FILEPATH "") -set(CMAKE_OBJCOPY "arm-none-eabi-objcopy" CACHE FILEPATH "") -set(CMAKE_OBJDUMP "arm-none-eabi-objdump" CACHE FILEPATH "") +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE) @@ -16,9 +13,6 @@ set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) -# pass TOOLCHAIN_CPU to -set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES CMAKE_SYSTEM_PROCESSOR) - include(${CMAKE_CURRENT_LIST_DIR}/../cpu/${CMAKE_SYSTEM_PROCESSOR}.cmake) # enable all possible warnings for building examples @@ -27,6 +21,7 @@ list(APPEND TOOLCHAIN_COMMON_FLAGS -ffunction-sections -fsingle-precision-constant -fno-strict-aliasing + -g ) set(TOOLCHAIN_EXE_LINKER_FLAGS @@ -35,12 +30,9 @@ set(TOOLCHAIN_EXE_LINKER_FLAGS #-Wl,--cref ) -include(${CMAKE_CURRENT_LIST_DIR}/set_flags.cmake) +# join the toolchain flags into a single string +list(JOIN TOOLCHAIN_COMMON_FLAGS " " TOOLCHAIN_COMMON_FLAGS) +list(JOIN TOOLCHAIN_EXE_LINKER_FLAGS " " CMAKE_EXE_LINKER_FLAGS_INIT) -# try_compile is cmake test compiling its own example, -# pass -nostdlib to skip stdlib linking -get_property(IS_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE) -if (IS_IN_TRY_COMPILE) - set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -nostdlib") - set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -nostdlib") -endif () +set(CMAKE_C_FLAGS_INIT "${TOOLCHAIN_COMMON_FLAGS} ${TOOLCHAIN_C_FLAGS}") +set(CMAKE_ASM_FLAGS_INIT "${TOOLCHAIN_COMMON_FLAGS} ${TOOLCHAIN_ASM_FLAGS}") diff --git a/cmake/toolchain/set_flags.cmake b/cmake/toolchain/set_flags.cmake deleted file mode 100644 index bbbd211..0000000 --- a/cmake/toolchain/set_flags.cmake +++ /dev/null @@ -1,17 +0,0 @@ -include(CMakePrintHelpers) - -# join the toolchain flags into a single string -list(JOIN TOOLCHAIN_COMMON_FLAGS " " TOOLCHAIN_COMMON_FLAGS) - -foreach (LANG IN ITEMS C CXX ASM) - set(CMAKE_${LANG}_FLAGS_INIT ${TOOLCHAIN_COMMON_FLAGS}) - - #cmake_print_variables(CMAKE_${LANG}_FLAGS_INIT) - - # optimization flags for LOG, LOGGER ? - #set(CMAKE_${LANG}_FLAGS_RELEASE_INIT "-Os") - #set(CMAKE_${LANG}_FLAGS_DEBUG_INIT "-O0") -endforeach () - -# Linker -list(JOIN TOOLCHAIN_EXE_LINKER_FLAGS " " CMAKE_EXE_LINKER_FLAGS_INIT) diff --git a/linker/nrf52.ld b/linker/nrf52.ld index 756e490..f5bd6ce 100644 --- a/linker/nrf52.ld +++ b/linker/nrf52.ld @@ -1,7 +1,7 @@ /* Linker script to configure memory regions. */ SEARCH_DIR(.) -GROUP(-lgcc -lc -lnosys) +/*GROUP(-lgcc -lc -lnosys)*/ MEMORY { @@ -19,8 +19,6 @@ MEMORY /** Location of bootloader setting in flash. */ BOOTLOADER_SETTINGS (rw) : ORIGIN = 0x7F000, LENGTH = 0x1000 - - /** RAM Region for bootloader. */ RAM (rwx) : ORIGIN = 0x20008000, LENGTH = 0x20010000-0x20008000 @@ -30,8 +28,6 @@ MEMORY /** Location of non initialized RAM. Non initialized RAM is used for exchanging bond information * from application to bootloader when using buttonless DFU OTA. */ NOINIT (rwx) : ORIGIN = 0x20007F80, LENGTH = 0x80 - - /** Location in UICR where bootloader start address is stored. */ UICR_BOOTLOADER (r) : ORIGIN = 0x10001014, LENGTH = 0x04 diff --git a/linker/nrf52833.ld b/linker/nrf52833.ld index 49d8350..72af595 100644 --- a/linker/nrf52833.ld +++ b/linker/nrf52833.ld @@ -1,7 +1,7 @@ /* Linker script to configure memory regions. */ SEARCH_DIR(.) -GROUP(-lgcc -lc -lnosys) +/*GROUP(-lgcc -lc -lnosys)*/ MEMORY { diff --git a/linker/nrf52833_debug.ld b/linker/nrf52833_debug.ld index 8898aa2..f110738 100644 --- a/linker/nrf52833_debug.ld +++ b/linker/nrf52833_debug.ld @@ -1,7 +1,7 @@ /* Linker script to configure memory regions. */ SEARCH_DIR(.) -GROUP(-lgcc -lc) +/*GROUP(-lgcc -lc)*/ MEMORY { diff --git a/linker/nrf52840.ld b/linker/nrf52840.ld index 5eec85e..6d426f8 100644 --- a/linker/nrf52840.ld +++ b/linker/nrf52840.ld @@ -1,7 +1,7 @@ /* Linker script to configure memory regions. */ SEARCH_DIR(.) -GROUP(-lgcc -lc -lnosys) +/*GROUP(-lgcc -lc -lnosys)*/ MEMORY { @@ -21,8 +21,6 @@ MEMORY /** Location of bootloader setting in flash. */ BOOTLOADER_SETTINGS (rw) : ORIGIN = 0xFF000, LENGTH = 0x1000 - - /** RAM Region for bootloader. */ /* Avoid conflict with NOINIT for OTA bond sharing */ RAM (rwx) : ORIGIN = 0x20008000, LENGTH = 0x20040000-0x20008000 @@ -33,9 +31,7 @@ MEMORY /** Location of non initialized RAM. Non initialized RAM is used for exchanging bond information * from application to bootloader when using buttonless DFU OTA. */ NOINIT (rwx) : ORIGIN = 0x20007F80, LENGTH = 0x80 - - - + /** Location in UICR where bootloader start address is stored. */ UICR_BOOTLOADER (r) : ORIGIN = 0x10001014, LENGTH = 0x04 @@ -91,7 +87,6 @@ SECTIONS { } > NOINIT - /* other placements follow here... */ } diff --git a/linker/nrf52840_debug.ld b/linker/nrf52840_debug.ld index 2ca9fd6..4c8e794 100644 --- a/linker/nrf52840_debug.ld +++ b/linker/nrf52840_debug.ld @@ -1,7 +1,7 @@ /* Linker script to configure memory regions. */ SEARCH_DIR(.) -GROUP(-lgcc -lc) +/*GROUP(-lgcc -lc)*/ MEMORY { diff --git a/linker/nrf52_debug.ld b/linker/nrf52_debug.ld index 2193ace..27ab4ce 100644 --- a/linker/nrf52_debug.ld +++ b/linker/nrf52_debug.ld @@ -1,7 +1,7 @@ /* Linker script to configure memory regions. */ SEARCH_DIR(.) -GROUP(-lgcc -lc) +/*GROUP(-lgcc -lc)*/ MEMORY { diff --git a/segger/Adafruit_nRF52_Bootloader.emProject b/segger/Adafruit_nRF52_Bootloader.emProject deleted file mode 100644 index 8084a4d..0000000 --- a/segger/Adafruit_nRF52_Bootloader.emProject +++ /dev/null @@ -1,363 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/segger/SEGGER_RTT.c b/segger/SEGGER_RTT.c deleted file mode 100644 index aee5bd2..0000000 --- a/segger/SEGGER_RTT.c +++ /dev/null @@ -1,1329 +0,0 @@ -/********************************************************************* -* SEGGER MICROCONTROLLER GmbH & Co. KG * -* Solutions for real time microcontroller applications * -********************************************************************** -* * -* (c) 2014 - 2016 SEGGER Microcontroller GmbH & Co. KG * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* * This software may in its unmodified form be freely redistributed * -* in source form. * -* * The source code may be modified, provided the source code * -* retains the above copyright notice, this list of conditions and * -* the following disclaimer. * -* * Modified versions of this software in source or linkable form * -* may not be distributed without prior consent of SEGGER. * -* * This software may only be used for communication with SEGGER * -* J-Link debug probes. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** -* * -* RTT version: 5.12e * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT.c -Purpose : Implementation of SEGGER real-time transfer (RTT) which - allows real-time communication on targets which support - debugger memory accesses while the CPU is running. - -Additional information: - Type "int" is assumed to be 32-bits in size - H->T Host to target communication - T->H Target to host communication - - RTT channel 0 is always present and reserved for Terminal usage. - Name is fixed to "Terminal" - - Effective buffer size: SizeOfBuffer - 1 - - WrOff == RdOff: Buffer is empty - WrOff == (RdOff - 1): Buffer is full - WrOff > RdOff: Free space includes wrap-around - WrOff < RdOff: Used space includes wrap-around - (WrOff == (SizeOfBuffer - 1)) && (RdOff == 0): - Buffer full and wrap-around after next byte - - ----------------------------------------------------------------------- -*/ - -#include "SEGGER_RTT.h" - -#include // for memcpy - -/********************************************************************* -* -* Configuration, default values -* -********************************************************************** -*/ - -#ifndef BUFFER_SIZE_UP - #define BUFFER_SIZE_UP 1024 // Size of the buffer for terminal output of target, up to host -#endif - -#ifndef BUFFER_SIZE_DOWN - #define BUFFER_SIZE_DOWN 16 // Size of the buffer for terminal input to target from host (Usually keyboard input) -#endif - -#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS - #define SEGGER_RTT_MAX_NUM_UP_BUFFERS 2 // Number of up-buffers (T->H) available on this target -#endif - -#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS - #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 2 // Number of down-buffers (H->T) available on this target -#endif - -#ifndef SEGGER_RTT_BUFFER_SECTION - #if defined SEGGER_RTT_SECTION - #define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION - #endif -#endif - -#ifndef SEGGER_RTT_MODE_DEFAULT - #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP -#endif - -#ifndef SEGGER_RTT_LOCK - #define SEGGER_RTT_LOCK() -#endif - -#ifndef SEGGER_RTT_UNLOCK - #define SEGGER_RTT_UNLOCK() -#endif - -#ifndef STRLEN - #define STRLEN(a) strlen((a)) -#endif - -#ifndef MEMCPY - #define MEMCPY(pDest, pSrc, NumBytes) memcpy((pDest), (pSrc), (NumBytes)) -#endif - -#ifndef MIN - #define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#endif - -#ifndef MAX - #define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#endif -// -// For some environments, NULL may not be defined until certain headers are included -// -#ifndef NULL - #define NULL 0 -#endif - -/********************************************************************* -* -* Static const data -* -********************************************************************** -*/ - -static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - -/********************************************************************* -* -* Static data -* -********************************************************************** -*/ -// -// RTT Control Block and allocate buffers for channel 0 -// -#ifdef SEGGER_RTT_SECTION - #if (defined __GNUC__) - __attribute__ ((section (SEGGER_RTT_SECTION))) SEGGER_RTT_CB _SEGGER_RTT; - #elif (defined __ICCARM__) || (defined __ICCRX__) - #pragma location=SEGGER_RTT_SECTION - SEGGER_RTT_CB _SEGGER_RTT; - #elif (defined __CC_ARM__) - __attribute__ ((section (SEGGER_RTT_SECTION), zero_init)) SEGGER_RTT_CB _SEGGER_RTT; - #else - SEGGER_RTT_CB _SEGGER_RTT; - #endif -#else - SEGGER_RTT_CB _SEGGER_RTT; -#endif - -#ifdef SEGGER_RTT_BUFFER_SECTION - #if (defined __GNUC__) - __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION))) static char _acUpBuffer [BUFFER_SIZE_UP]; - __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION))) static char _acDownBuffer[BUFFER_SIZE_DOWN]; - #elif (defined __ICCARM__) || (defined __ICCRX__) - #pragma location=SEGGER_RTT_BUFFER_SECTION - static char _acUpBuffer [BUFFER_SIZE_UP]; - #pragma location=SEGGER_RTT_BUFFER_SECTION - static char _acDownBuffer[BUFFER_SIZE_DOWN]; - #elif (defined __CC_ARM__) - __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION), zero_init)) static char _acUpBuffer [BUFFER_SIZE_UP]; - __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION), zero_init)) static char _acDownBuffer[BUFFER_SIZE_DOWN]; - #else - static char _acUpBuffer [BUFFER_SIZE_UP]; - static char _acDownBuffer[BUFFER_SIZE_DOWN]; - #endif -#else - static char _acUpBuffer [BUFFER_SIZE_UP]; - static char _acDownBuffer[BUFFER_SIZE_DOWN]; -#endif - -static char _ActiveTerminal; - -/********************************************************************* -* -* Static functions -* -********************************************************************** -*/ - -/********************************************************************* -* -* _DoInit() -* -* Function description -* Initializes the control block an buffers. -* May only be called via INIT() to avoid overriding settings. -* -*/ -#define INIT() do { \ - if (_SEGGER_RTT.acID[0] == '\0') { _DoInit(); } \ - } while (0) -static void _DoInit(void) { - SEGGER_RTT_CB* p; - // - // Initialize control block - // - p = &_SEGGER_RTT; - p->MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS; - p->MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS; - // - // Initialize up buffer 0 - // - p->aUp[0].sName = "Terminal"; - p->aUp[0].pBuffer = _acUpBuffer; - p->aUp[0].SizeOfBuffer = sizeof(_acUpBuffer); - p->aUp[0].RdOff = 0u; - p->aUp[0].WrOff = 0u; - p->aUp[0].Flags = SEGGER_RTT_MODE_DEFAULT; - // - // Initialize down buffer 0 - // - p->aDown[0].sName = "Terminal"; - p->aDown[0].pBuffer = _acDownBuffer; - p->aDown[0].SizeOfBuffer = sizeof(_acDownBuffer); - p->aDown[0].RdOff = 0u; - p->aDown[0].WrOff = 0u; - p->aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT; - // - // Finish initialization of the control block. - // Copy Id string in three steps to make sure "SEGGER RTT" is not found - // in initializer memory (usually flash) by J-Link - // - strcpy(&p->acID[7], "RTT"); - strcpy(&p->acID[0], "SEGGER"); - p->acID[6] = ' '; -} - -/********************************************************************* -* -* _WriteBlocking() -* -* Function description -* Stores a specified number of characters in SEGGER RTT ring buffer -* and updates the associated write pointer which is periodically -* read by the host. -* The caller is responsible for managing the write chunk sizes as -* _WriteBlocking() will block until all data has been posted successfully. -* -* Parameters -* pRing Ring buffer to post to. -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* >= 0 - Number of bytes written into buffer. -*/ -static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing, const char* pBuffer, unsigned NumBytes) { - unsigned NumBytesToWrite; - unsigned NumBytesWritten; - unsigned RdOff; - unsigned WrOff; - // - // Write data to buffer and handle wrap-around if necessary - // - NumBytesWritten = 0u; - WrOff = pRing->WrOff; - do { - RdOff = pRing->RdOff; // May be changed by host (debug probe) in the meantime - if (RdOff > WrOff) { - NumBytesToWrite = RdOff - WrOff - 1u; - } else { - NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u); - } - NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff)); // Number of bytes that can be written until buffer wrap-around - NumBytesToWrite = MIN(NumBytesToWrite, NumBytes); - memcpy(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite); - NumBytesWritten += NumBytesToWrite; - pBuffer += NumBytesToWrite; - NumBytes -= NumBytesToWrite; - WrOff += NumBytesToWrite; - if (WrOff == pRing->SizeOfBuffer) { - WrOff = 0u; - } - pRing->WrOff = WrOff; - } while (NumBytes); - // - return NumBytesWritten; -} - -/********************************************************************* -* -* _WriteNoCheck() -* -* Function description -* Stores a specified number of characters in SEGGER RTT ring buffer -* and updates the associated write pointer which is periodically -* read by the host. -* It is callers responsibility to make sure data actually fits in buffer. -* -* Parameters -* pRing Ring buffer to post to. -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Notes -* (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking -*/ -static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsigned NumBytes) { - unsigned NumBytesAtOnce; - unsigned WrOff; - unsigned Rem; - - WrOff = pRing->WrOff; - Rem = pRing->SizeOfBuffer - WrOff; - if (Rem > NumBytes) { - // - // All data fits before wrap around - // - memcpy(pRing->pBuffer + WrOff, pData, NumBytes); - pRing->WrOff = WrOff + NumBytes; - } else { - // - // We reach the end of the buffer, so need to wrap around - // - NumBytesAtOnce = Rem; - memcpy(pRing->pBuffer + WrOff, pData, NumBytesAtOnce); - NumBytesAtOnce = NumBytes - Rem; - memcpy(pRing->pBuffer, pData + Rem, NumBytesAtOnce); - pRing->WrOff = NumBytesAtOnce; - } -} - -/********************************************************************* -* -* _PostTerminalSwitch() -* -* Function description -* Switch terminal to the given terminal ID. It is the caller's -* responsibility to ensure the terminal ID is correct and there is -* enough space in the buffer for this to complete successfully. -* -* Parameters -* pRing Ring buffer to post to. -* TerminalId Terminal ID to switch to. -*/ -static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) { - char ac[2]; - - ac[0] = 0xFFu; - ac[1] = _aTerminalId[TerminalId]; // Caller made already sure that TerminalId does not exceed our terminal limit - _WriteBlocking(pRing, ac, 2u); -} - -/********************************************************************* -* -* _GetAvailWriteSpace() -* -* Function description -* Returns the number of bytes that can be written to the ring -* buffer without blocking. -* -* Parameters -* pRing Ring buffer to check. -* -* Return value -* Number of bytes that are free in the buffer. -*/ -static unsigned _GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP* pRing) { - unsigned RdOff; - unsigned WrOff; - unsigned r; - // - // Avoid warnings regarding volatile access order. It's not a problem - // in this case, but dampen compiler enthusiasm. - // - RdOff = pRing->RdOff; - WrOff = pRing->WrOff; - if (RdOff <= WrOff) { - r = pRing->SizeOfBuffer - 1u - WrOff + RdOff; - } else { - r = RdOff - WrOff - 1u; - } - return r; -} - -/********************************************************************* -* -* Public code -* -********************************************************************** -*/ -/********************************************************************* -* -* SEGGER_RTT_ReadNoLock() -* -* Function description -* Reads characters from SEGGER real-time-terminal control block -* which have been previously stored by the host. -* Do not lock against interrupts and multiple access. -* -* Parameters -* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. -* BufferSize Size of the target application buffer. -* -* Return value -* Number of bytes that have been read. -*/ -unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { - unsigned NumBytesRem; - unsigned NumBytesRead; - unsigned RdOff; - unsigned WrOff; - unsigned char* pBuffer; - SEGGER_RTT_BUFFER_DOWN* pRing; - // - INIT(); - pRing = &_SEGGER_RTT.aDown[BufferIndex]; - pBuffer = (unsigned char*)pData; - RdOff = pRing->RdOff; - WrOff = pRing->WrOff; - NumBytesRead = 0u; - // - // Read from current read position to wrap-around of buffer, first - // - if (RdOff > WrOff) { - NumBytesRem = pRing->SizeOfBuffer - RdOff; - NumBytesRem = MIN(NumBytesRem, BufferSize); - memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); - NumBytesRead += NumBytesRem; - pBuffer += NumBytesRem; - BufferSize -= NumBytesRem; - RdOff += NumBytesRem; - // - // Handle wrap-around of buffer - // - if (RdOff == pRing->SizeOfBuffer) { - RdOff = 0u; - } - } - // - // Read remaining items of buffer - // - NumBytesRem = WrOff - RdOff; - NumBytesRem = MIN(NumBytesRem, BufferSize); - if (NumBytesRem > 0u) { - memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); - NumBytesRead += NumBytesRem; - pBuffer += NumBytesRem; - BufferSize -= NumBytesRem; - RdOff += NumBytesRem; - } - if (NumBytesRead) { - pRing->RdOff = RdOff; - } - // - return NumBytesRead; -} - -/********************************************************************* -* -* SEGGER_RTT_Read -* -* Function description -* Reads characters from SEGGER real-time-terminal control block -* which have been previously stored by the host. -* -* Parameters -* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. -* BufferSize Size of the target application buffer. -* -* Return value -* Number of bytes that have been read. -*/ -unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { - unsigned NumBytesRead; - // - SEGGER_RTT_LOCK(); - // - // Call the non-locking read function - // - NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize); - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - // - return NumBytesRead; -} - -/********************************************************************* -* -* SEGGER_RTT_WriteWithOverwriteNoLock -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block. -* SEGGER_RTT_WriteWithOverwriteNoLock does not lock the application -* and overwrites data if the data does not fit into the buffer. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, data is overwritten. -* (2) For performance reasons this function does not call Init() -* and may only be called after RTT has been initialized. -* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. -* (3) Do not use SEGGER_RTT_WriteWithOverwriteNoLock if a J-Link -* connection reads RTT data. -*/ -void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - const char* pData; - SEGGER_RTT_BUFFER_UP* pRing; - unsigned Avail; - - pData = (const char *)pBuffer; - // - // Get "to-host" ring buffer and copy some elements into local variables. - // - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - // - // Check if we will overwrite data and need to adjust the RdOff. - // - if (pRing->WrOff == pRing->RdOff) { - Avail = pRing->SizeOfBuffer - 1u; - } else if ( pRing->WrOff < pRing->RdOff) { - Avail = pRing->RdOff - pRing->WrOff - 1u; - } else { - Avail = pRing->RdOff - pRing->WrOff - 1u + pRing->SizeOfBuffer; - } - if (NumBytes > Avail) { - pRing->RdOff += (NumBytes - Avail); - while (pRing->RdOff >= pRing->SizeOfBuffer) { - pRing->RdOff -= pRing->SizeOfBuffer; - } - } - // - // Write all data, no need to check the RdOff, but possibly handle multiple wrap-arounds - // - Avail = pRing->SizeOfBuffer - pRing->WrOff; - do { - if (Avail > NumBytes) { - // - // Last round - // -#if 1 // memcpy() is good for large amounts of data, but the overhead is too big for small amounts. Use a simple byte loop instead. - char* pDst; - pDst = pRing->pBuffer + pRing->WrOff; - pRing->WrOff += NumBytes; - do { - *pDst++ = *pData++; - } while (--NumBytes); -#else - memcpy(pRing->pBuffer + WrOff, pData, NumBytes); - pRing->WrOff += NumBytes; -#endif - break; //Alternatively: NumBytes = 0; - } else { - // - // Wrap-around necessary, write until wrap-around and reset WrOff - // - memcpy(pRing->pBuffer + pRing->WrOff, pData, Avail); - pData += Avail; - pRing->WrOff = 0; - NumBytes -= Avail; - Avail = (pRing->SizeOfBuffer - 1); - } - } while (NumBytes); -} - -/********************************************************************* -* -* SEGGER_RTT_WriteSkipNoLock -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block which is then read by the host. -* SEGGER_RTT_WriteSkipNoLock does not lock the application and -* skips all data, if the data does not fit into the buffer. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, all data is dropped. -* (2) For performance reasons this function does not call Init() -* and may only be called after RTT has been initialized. -* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. -*/ -unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - const char* pData; - SEGGER_RTT_BUFFER_UP* pRing; - unsigned Avail; - unsigned RdOff; - unsigned WrOff; - unsigned Rem; - - pData = (const char *)pBuffer; - // - // Get "to-host" ring buffer and copy some elements into local variables. - // - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - RdOff = pRing->RdOff; - WrOff = pRing->WrOff; - // - // Handle the most common cases fastest. - // Which is: - // RdOff <= WrOff -> Space until wrap around is free. - // AND - // WrOff + NumBytes < SizeOfBuffer -> No Wrap around necessary. - // - // OR - // - // RdOff > WrOff -> Space until RdOff - 1 is free. - // AND - // WrOff + NumBytes < RdOff -> Data fits into buffer - // - if (RdOff <= WrOff) { - // - // Get space until WrOff will be at wrap around. - // - Avail = pRing->SizeOfBuffer - 1u - WrOff ; - if (Avail >= NumBytes) { -#if 1 // memcpy() is good for large amounts of data, but the overhead is too big for small amounts. Use a simple byte loop instead. - char* pDst; - pDst = pRing->pBuffer + WrOff; - WrOff += NumBytes; - do { - *pDst++ = *pData++; - } while (--NumBytes); - pRing->WrOff = WrOff + NumBytes; -#else - memcpy(pRing->pBuffer + WrOff, pData, NumBytes); - pRing->WrOff = WrOff + NumBytes; -#endif - return 1; - } - // - // If data did not fit into space until wrap around calculate complete space in buffer. - // - Avail += RdOff; - // - // If there is still no space for the whole of this output, don't bother. - // - if (Avail >= NumBytes) { - // - // OK, we have enough space in buffer. Copy in one or 2 chunks - // - Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer - if (Rem > NumBytes) { - memcpy(pRing->pBuffer + WrOff, pData, NumBytes); - pRing->WrOff = WrOff + NumBytes; - } else { - // - // We reach the end of the buffer, so need to wrap around - // - memcpy(pRing->pBuffer + WrOff, pData, Rem); - memcpy(pRing->pBuffer, pData + Rem, NumBytes - Rem); - pRing->WrOff = NumBytes - Rem; - } - return 1; - } - } else { - Avail = RdOff - WrOff - 1u; - if (Avail >= NumBytes) { - memcpy(pRing->pBuffer + WrOff, pData, NumBytes); - pRing->WrOff = WrOff + NumBytes; - return 1; - } - } - // - // If we reach this point no data has been written - // - return 0; -} - -/********************************************************************* -* -* SEGGER_RTT_WriteNoLock -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block which is then read by the host. -* SEGGER_RTT_WriteNoLock does not lock the application. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped. -* (2) For performance reasons this function does not call Init() -* and may only be called after RTT has been initialized. -* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. -*/ -unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - unsigned Status; - unsigned Avail; - const char* pData; - SEGGER_RTT_BUFFER_UP* pRing; - - pData = (const char *)pBuffer; - // - // Get "to-host" ring buffer. - // - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - // - // How we output depends upon the mode... - // - switch (pRing->Flags) { - case SEGGER_RTT_MODE_NO_BLOCK_SKIP: - // - // If we are in skip mode and there is no space for the whole - // of this output, don't bother. - // - Avail = _GetAvailWriteSpace(pRing); - if (Avail < NumBytes) { - Status = 0u; - } else { - Status = NumBytes; - _WriteNoCheck(pRing, pData, NumBytes); - } - break; - case SEGGER_RTT_MODE_NO_BLOCK_TRIM: - // - // If we are in trim mode, trim to what we can output without blocking. - // - Avail = _GetAvailWriteSpace(pRing); - Status = Avail < NumBytes ? Avail : NumBytes; - _WriteNoCheck(pRing, pData, Status); - break; - case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: - // - // If we are in blocking mode, output everything. - // - Status = _WriteBlocking(pRing, pData, NumBytes); - break; - default: - Status = 0u; - break; - } - // - // Finish up. - // - return Status; -} - -/********************************************************************* -* -* SEGGER_RTT_Write -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block which is then read by the host. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped. -*/ -unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - unsigned Status; - // - INIT(); - SEGGER_RTT_LOCK(); - // - // Call the non-locking write function - // - Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes); - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - // - return Status; -} - -/********************************************************************* -* -* SEGGER_RTT_WriteString -* -* Function description -* Stores string in SEGGER RTT control block. -* This data is read by the host. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* s Pointer to string. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, depending on configuration, -* remaining characters may be dropped or RTT module waits until there is more space in the buffer. -* (2) String passed to this function has to be \0 terminated -* (3) \0 termination character is *not* stored in RTT buffer -*/ -unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) { - unsigned Len; - - Len = STRLEN(s); - return SEGGER_RTT_Write(BufferIndex, s, Len); -} - -/********************************************************************* -* -* SEGGER_RTT_GetKey -* -* Function description -* Reads one character from the SEGGER RTT buffer. -* Host has previously stored data there. -* -* Return value -* < 0 - No character available (buffer empty). -* >= 0 - Character which has been read. (Possible values: 0 - 255) -* -* Notes -* (1) This function is only specified for accesses to RTT buffer 0. -*/ -int SEGGER_RTT_GetKey(void) { - char c; - int r; - - r = (int)SEGGER_RTT_Read(0u, &c, 1u); - if (r == 1) { - r = (int)(unsigned char)c; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_WaitKey -* -* Function description -* Waits until at least one character is avaible in the SEGGER RTT buffer. -* Once a character is available, it is read and this function returns. -* -* Return value -* >=0 - Character which has been read. -* -* Notes -* (1) This function is only specified for accesses to RTT buffer 0 -* (2) This function is blocking if no character is present in RTT buffer -*/ -int SEGGER_RTT_WaitKey(void) { - int r; - - do { - r = SEGGER_RTT_GetKey(); - } while (r < 0); - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_HasKey -* -* Function description -* Checks if at least one character for reading is available in the SEGGER RTT buffer. -* -* Return value -* == 0 - No characters are available to read. -* == 1 - At least one character is available. -* -* Notes -* (1) This function is only specified for accesses to RTT buffer 0 -*/ -int SEGGER_RTT_HasKey(void) { - unsigned RdOff; - int r; - - INIT(); - RdOff = _SEGGER_RTT.aDown[0].RdOff; - if (RdOff != _SEGGER_RTT.aDown[0].WrOff) { - r = 1; - } else { - r = 0; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_HasData -* -* Function description -* Check if there is data from the host in the given buffer. -* -* Return value: -* ==0: No data -* !=0: Data in buffer -* -*/ -unsigned SEGGER_RTT_HasData(unsigned BufferIndex) { - SEGGER_RTT_BUFFER_DOWN* pRing; - unsigned v; - - pRing = &_SEGGER_RTT.aDown[BufferIndex]; - v = pRing->WrOff; - return v - pRing->RdOff; -} - -/********************************************************************* -* -* SEGGER_RTT_AllocDownBuffer -* -* Function description -* Run-time configuration of the next down-buffer (H->T). -* The next buffer, which is not used yet is configured. -* This includes: Buffer address, size, name, flags, ... -* -* Parameters -* sName Pointer to a constant name string. -* pBuffer Pointer to a buffer to be used. -* BufferSize Size of the buffer. -* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). -* -* Return value -* >= 0 - O.K. Buffer Index -* < 0 - Error -*/ -int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { - int BufferIndex; - - INIT(); - SEGGER_RTT_LOCK(); - BufferIndex = 0; - do { - if (_SEGGER_RTT.aDown[BufferIndex].pBuffer == NULL) { - break; - } - BufferIndex++; - } while (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers); - if (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers) { - _SEGGER_RTT.aDown[BufferIndex].sName = sName; - _SEGGER_RTT.aDown[BufferIndex].pBuffer = pBuffer; - _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; - _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; - _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; - _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; - } else { - BufferIndex = -1; - } - SEGGER_RTT_UNLOCK(); - return BufferIndex; -} - -/********************************************************************* -* -* SEGGER_RTT_AllocUpBuffer -* -* Function description -* Run-time configuration of the next up-buffer (T->H). -* The next buffer, which is not used yet is configured. -* This includes: Buffer address, size, name, flags, ... -* -* Parameters -* sName Pointer to a constant name string. -* pBuffer Pointer to a buffer to be used. -* BufferSize Size of the buffer. -* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). -* -* Return value -* >= 0 - O.K. Buffer Index -* < 0 - Error -*/ -int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { - int BufferIndex; - - INIT(); - SEGGER_RTT_LOCK(); - BufferIndex = 0; - do { - if (_SEGGER_RTT.aUp[BufferIndex].pBuffer == NULL) { - break; - } - BufferIndex++; - } while (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers); - if (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers) { - _SEGGER_RTT.aUp[BufferIndex].sName = sName; - _SEGGER_RTT.aUp[BufferIndex].pBuffer = pBuffer; - _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; - _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; - _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; - _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; - } else { - BufferIndex = -1; - } - SEGGER_RTT_UNLOCK(); - return BufferIndex; -} - -/********************************************************************* -* -* SEGGER_RTT_ConfigUpBuffer -* -* Function description -* Run-time configuration of a specific up-buffer (T->H). -* Buffer to be configured is specified by index. -* This includes: Buffer address, size, name, flags, ... -* -* Parameters -* BufferIndex Index of the buffer to configure. -* sName Pointer to a constant name string. -* pBuffer Pointer to a buffer to be used. -* BufferSize Size of the buffer. -* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). -* -* Return value -* >= 0 - O.K. -* < 0 - Error -*/ -int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { - SEGGER_RTT_LOCK(); - if (BufferIndex > 0u) { - _SEGGER_RTT.aUp[BufferIndex].sName = sName; - _SEGGER_RTT.aUp[BufferIndex].pBuffer = pBuffer; - _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; - _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; - _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; - } - _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_ConfigDownBuffer -* -* Function description -* Run-time configuration of a specific down-buffer (H->T). -* Buffer to be configured is specified by index. -* This includes: Buffer address, size, name, flags, ... -* -* Parameters -* BufferIndex Index of the buffer to configure. -* sName Pointer to a constant name string. -* pBuffer Pointer to a buffer to be used. -* BufferSize Size of the buffer. -* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). -* -* Return value -* >= 0 O.K. -* < 0 Error -*/ -int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { - SEGGER_RTT_LOCK(); - if (BufferIndex > 0u) { - _SEGGER_RTT.aDown[BufferIndex].sName = sName; - _SEGGER_RTT.aDown[BufferIndex].pBuffer = pBuffer; - _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; - _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; - _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; - } - _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_SetNameUpBuffer -* -* Function description -* Run-time configuration of a specific up-buffer name (T->H). -* Buffer to be configured is specified by index. -* -* Parameters -* BufferIndex Index of the buffer to renamed. -* sName Pointer to a constant name string. -* -* Return value -* >= 0 O.K. -* < 0 Error -*/ -int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { - SEGGER_RTT_LOCK(); - _SEGGER_RTT.aUp[BufferIndex].sName = sName; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_SetNameDownBuffer -* -* Function description -* Run-time configuration of a specific Down-buffer name (T->H). -* Buffer to be configured is specified by index. -* -* Parameters -* BufferIndex Index of the buffer to renamed. -* sName Pointer to a constant name string. -* -* Return value -* >= 0 O.K. -* < 0 Error -*/ -int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { - SEGGER_RTT_LOCK(); - _SEGGER_RTT.aDown[BufferIndex].sName = sName; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_Init -* -* Function description -* Initializes the RTT Control Block. -* Should be used in RAM targets, at start of the application. -* -*/ -void SEGGER_RTT_Init (void) { - _DoInit(); -} - -/********************************************************************* -* -* SEGGER_RTT_SetTerminal -* -* Function description -* Sets the terminal to be used for output on channel 0. -* -* Parameters -* TerminalId Index of the terminal. -* -* Return value -* >= 0 O.K. -* < 0 Error (e.g. if RTT is configured for non-blocking mode and there was no space in the buffer to set the new terminal Id) -*/ -int SEGGER_RTT_SetTerminal (char TerminalId) { - char ac[2]; - SEGGER_RTT_BUFFER_UP* pRing; - unsigned Avail; - int r; - // - INIT(); - // - r = 0; - ac[0] = 0xFFU; - if ((unsigned char)TerminalId < (unsigned char)sizeof(_aTerminalId)) { // We only support a certain number of channels - ac[1] = _aTerminalId[(unsigned char)TerminalId]; - pRing = &_SEGGER_RTT.aUp[0]; // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed - SEGGER_RTT_LOCK(); // Lock to make sure that no other task is writing into buffer, while we are and number of free bytes in buffer does not change downwards after checking and before writing - if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { - _ActiveTerminal = TerminalId; - _WriteBlocking(pRing, ac, 2u); - } else { // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes - Avail = _GetAvailWriteSpace(pRing); - if (Avail >= 2) { - _ActiveTerminal = TerminalId; // Only change active terminal in case of success - _WriteNoCheck(pRing, ac, 2u); - } else { - r = -1; - } - } - SEGGER_RTT_UNLOCK(); - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_TerminalOut -* -* Function description -* Writes a string to the given terminal -* without changing the terminal for channel 0. -* -* Parameters -* TerminalId Index of the terminal. -* s String to be printed on the terminal. -* -* Return value -* >= 0 - Number of bytes written. -* < 0 - Error. -* -*/ -int SEGGER_RTT_TerminalOut (char TerminalId, const char* s) { - int Status; - unsigned FragLen; - unsigned Avail; - SEGGER_RTT_BUFFER_UP* pRing; - // - INIT(); - // - // Validate terminal ID. - // - if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels - // - // Get "to-host" ring buffer. - // - pRing = &_SEGGER_RTT.aUp[0]; - // - // Need to be able to change terminal, write data, change back. - // Compute the fixed and variable sizes. - // - FragLen = strlen(s); - // - // How we output depends upon the mode... - // - SEGGER_RTT_LOCK(); - Avail = _GetAvailWriteSpace(pRing); - switch (pRing->Flags & SEGGER_RTT_MODE_MASK) { - case SEGGER_RTT_MODE_NO_BLOCK_SKIP: - // - // If we are in skip mode and there is no space for the whole - // of this output, don't bother switching terminals at all. - // - if (Avail < (FragLen + 4u)) { - Status = 0; - } else { - _PostTerminalSwitch(pRing, TerminalId); - Status = (int)_WriteBlocking(pRing, s, FragLen); - _PostTerminalSwitch(pRing, _ActiveTerminal); - } - break; - case SEGGER_RTT_MODE_NO_BLOCK_TRIM: - // - // If we are in trim mode and there is not enough space for everything, - // trim the output but always include the terminal switch. If no room - // for terminal switch, skip that totally. - // - if (Avail < 4u) { - Status = -1; - } else { - _PostTerminalSwitch(pRing, TerminalId); - Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u)); - _PostTerminalSwitch(pRing, _ActiveTerminal); - } - break; - case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: - // - // If we are in blocking mode, output everything. - // - _PostTerminalSwitch(pRing, TerminalId); - Status = (int)_WriteBlocking(pRing, s, FragLen); - _PostTerminalSwitch(pRing, _ActiveTerminal); - break; - default: - Status = -1; - break; - } - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - } else { - Status = -1; - } - return Status; -} - - -/*************************** End of file ****************************/ diff --git a/segger/SEGGER_RTT.h b/segger/SEGGER_RTT.h deleted file mode 100644 index d3cac44..0000000 --- a/segger/SEGGER_RTT.h +++ /dev/null @@ -1,234 +0,0 @@ -/********************************************************************* -* SEGGER MICROCONTROLLER GmbH & Co. KG * -* Solutions for real time microcontroller applications * -********************************************************************** -* * -* (c) 2014 - 2016 SEGGER Microcontroller GmbH & Co. KG * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* * This software may in its unmodified form be freely redistributed * -* in source form. * -* * The source code may be modified, provided the source code * -* retains the above copyright notice, this list of conditions and * -* the following disclaimer. * -* * Modified versions of this software in source or linkable form * -* may not be distributed without prior consent of SEGGER. * -* * This software may only be used for communication with SEGGER * -* J-Link debug probes. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** -* * -* RTT version: 5.12e * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT.h -Purpose : Implementation of SEGGER real-time transfer which allows - real-time communication on targets which support debugger - memory accesses while the CPU is running. ----------------------------------------------------------------------- -*/ - -#ifndef SEGGER_RTT_H -#define SEGGER_RTT_H - -#include "SEGGER_RTT_Conf.h" - -/********************************************************************* -* -* Defines, fixed -* -********************************************************************** -*/ - -/********************************************************************* -* -* Types -* -********************************************************************** -*/ - -// -// Description for a circular buffer (also called "ring buffer") -// which is used as up-buffer (T->H) -// -typedef struct { - const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" - char* pBuffer; // Pointer to start of buffer - unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. - unsigned WrOff; // Position of next item to be written by either target. - volatile unsigned RdOff; // Position of next item to be read by host. Must be volatile since it may be modified by host. - unsigned Flags; // Contains configuration flags -} SEGGER_RTT_BUFFER_UP; - -// -// Description for a circular buffer (also called "ring buffer") -// which is used as down-buffer (H->T) -// -typedef struct { - const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" - char* pBuffer; // Pointer to start of buffer - unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. - volatile unsigned WrOff; // Position of next item to be written by host. Must be volatile since it may be modified by host. - unsigned RdOff; // Position of next item to be read by target (down-buffer). - unsigned Flags; // Contains configuration flags -} SEGGER_RTT_BUFFER_DOWN; - -// -// RTT control block which describes the number of buffers available -// as well as the configuration for each buffer -// -// -typedef struct { - char acID[16]; // Initialized to "SEGGER RTT" - int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2) - int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2) - SEGGER_RTT_BUFFER_UP aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS]; // Up buffers, transferring information up from target via debug probe to host - SEGGER_RTT_BUFFER_DOWN aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS]; // Down buffers, transferring information down from host via debug probe to target -} SEGGER_RTT_CB; - -/********************************************************************* -* -* Global data -* -********************************************************************** -*/ -extern SEGGER_RTT_CB _SEGGER_RTT; - -/********************************************************************* -* -* RTT API functions -* -********************************************************************** -*/ -#ifdef __cplusplus - extern "C" { -#endif -int SEGGER_RTT_AllocDownBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_AllocUpBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_ConfigUpBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_GetKey (void); -unsigned SEGGER_RTT_HasData (unsigned BufferIndex); -int SEGGER_RTT_HasKey (void); -void SEGGER_RTT_Init (void); -unsigned SEGGER_RTT_Read (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); -unsigned SEGGER_RTT_ReadNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); -int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName); -int SEGGER_RTT_SetNameUpBuffer (unsigned BufferIndex, const char* sName); -int SEGGER_RTT_WaitKey (void); -unsigned SEGGER_RTT_Write (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_WriteNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s); -void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -// -// Function macro for performance optimization -// -#define SEGGER_RTT_HASDATA(n) (_SEGGER_RTT.aDown[n].WrOff - _SEGGER_RTT.aDown[n].RdOff) - -/********************************************************************* -* -* RTT "Terminal" API functions -* -********************************************************************** -*/ -int SEGGER_RTT_SetTerminal (char TerminalId); -int SEGGER_RTT_TerminalOut (char TerminalId, const char* s); - -/********************************************************************* -* -* RTT printf functions (require SEGGER_RTT_printf.c) -* -********************************************************************** -*/ -int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...); -#ifdef __cplusplus - } -#endif - -/********************************************************************* -* -* Defines -* -********************************************************************** -*/ - -// -// Operating modes. Define behavior if buffer is full (not enough space for entire message) -// -#define SEGGER_RTT_MODE_NO_BLOCK_SKIP (0U) // Skip. Do not block, output nothing. (Default) -#define SEGGER_RTT_MODE_NO_BLOCK_TRIM (1U) // Trim: Do not block, output as much as fits. -#define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (2U) // Block: Wait until there is space in the buffer. -#define SEGGER_RTT_MODE_MASK (3U) - -// -// Control sequences, based on ANSI. -// Can be used to control color, and clear the screen -// -#define RTT_CTRL_RESET "" // Reset to default colors -#define RTT_CTRL_CLEAR "" // Clear screen, reposition cursor to top left - -#define RTT_CTRL_TEXT_BLACK "" -#define RTT_CTRL_TEXT_RED "" -#define RTT_CTRL_TEXT_GREEN "" -#define RTT_CTRL_TEXT_YELLOW "" -#define RTT_CTRL_TEXT_BLUE "" -#define RTT_CTRL_TEXT_MAGENTA "" -#define RTT_CTRL_TEXT_CYAN "" -#define RTT_CTRL_TEXT_WHITE "" - -#define RTT_CTRL_TEXT_BRIGHT_BLACK "" -#define RTT_CTRL_TEXT_BRIGHT_RED "" -#define RTT_CTRL_TEXT_BRIGHT_GREEN "" -#define RTT_CTRL_TEXT_BRIGHT_YELLOW "" -#define RTT_CTRL_TEXT_BRIGHT_BLUE "" -#define RTT_CTRL_TEXT_BRIGHT_MAGENTA "" -#define RTT_CTRL_TEXT_BRIGHT_CYAN "" -#define RTT_CTRL_TEXT_BRIGHT_WHITE "" - -#define RTT_CTRL_BG_BLACK "" -#define RTT_CTRL_BG_RED "" -#define RTT_CTRL_BG_GREEN "" -#define RTT_CTRL_BG_YELLOW "" -#define RTT_CTRL_BG_BLUE "" -#define RTT_CTRL_BG_MAGENTA "" -#define RTT_CTRL_BG_CYAN "" -#define RTT_CTRL_BG_WHITE "" - -#define RTT_CTRL_BG_BRIGHT_BLACK "" -#define RTT_CTRL_BG_BRIGHT_RED "" -#define RTT_CTRL_BG_BRIGHT_GREEN "" -#define RTT_CTRL_BG_BRIGHT_YELLOW "" -#define RTT_CTRL_BG_BRIGHT_BLUE "" -#define RTT_CTRL_BG_BRIGHT_MAGENTA "" -#define RTT_CTRL_BG_BRIGHT_CYAN "" -#define RTT_CTRL_BG_BRIGHT_WHITE "" - - -#endif - -/*************************** End of file ****************************/ diff --git a/segger/SEGGER_RTT_Conf.h b/segger/SEGGER_RTT_Conf.h deleted file mode 100644 index aef3b40..0000000 --- a/segger/SEGGER_RTT_Conf.h +++ /dev/null @@ -1,242 +0,0 @@ -/********************************************************************* -* SEGGER MICROCONTROLLER GmbH & Co. KG * -* Solutions for real time microcontroller applications * -********************************************************************** -* * -* (c) 2014 - 2016 SEGGER Microcontroller GmbH & Co. KG * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* * This software may in its unmodified form be freely redistributed * -* in source form. * -* * The source code may be modified, provided the source code * -* retains the above copyright notice, this list of conditions and * -* the following disclaimer. * -* * Modified versions of this software in source or linkable form * -* may not be distributed without prior consent of SEGGER. * -* * This software may only be used for communication with SEGGER * -* J-Link debug probes. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** -* * -* RTT version: 5.12e * -* * -********************************************************************** ----------------------------------------------------------------------- -File : SEGGER_RTT_Conf.h -Purpose : Implementation of SEGGER real-time transfer (RTT) which - allows real-time communication on targets which support - debugger memory accesses while the CPU is running. ----------------------------END-OF-HEADER------------------------------ -*/ - -#ifndef SEGGER_RTT_CONF_H -#define SEGGER_RTT_CONF_H - -#ifdef __ICCARM__ - #include -#endif - -/********************************************************************* -* -* Defines, configurable -* -********************************************************************** -*/ - -#define SEGGER_RTT_MAX_NUM_UP_BUFFERS (2) // Max. number of up-buffers (T->H) available on this target (Default: 2) -#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (2) // Max. number of down-buffers (H->T) available on this target (Default: 2) - -#define BUFFER_SIZE_UP (1024) // Size of the buffer for terminal output of target, up to host (Default: 1k) -#define BUFFER_SIZE_DOWN (16) // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16) - -#define SEGGER_RTT_PRINTF_BUFFER_SIZE (64u) // Size of buffer for RTT printf to bulk-send chars via RTT (Default: 64) - -#define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0) - -// -// Target is not allowed to perform other RTT operations while string still has not been stored completely. -// Otherwise we would probably end up with a mixed string in the buffer. -// If using RTT from within interrupts, multiple tasks or multi processors, define the SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() function here. -// -// SEGGER_RTT_MAX_INTERRUPT_PRIORITY can be used in the sample lock routines on Cortex-M3/4. -// Make sure to mask all interrupts which can send RTT data, i.e. generate SystemView events, or cause task switches. -// When high-priority interrupts must not be masked while sending RTT data, SEGGER_RTT_MAX_INTERRUPT_PRIORITY needs to be adjusted accordingly. -// (Higher priority = lower priority number) -// Default value for embOS: 128u -// Default configuration in FreeRTOS: configMAX_SYSCALL_INTERRUPT_PRIORITY: ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) -// In case of doubt mask all interrupts: 0u -// - -#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) // Interrupt priority to lock on SEGGER_RTT_LOCK on Cortex-M3/4 (Default: 0x20) - -/********************************************************************* -* -* RTT lock configuration for SEGGER Embedded Studio, -* Rowley CrossStudio and GCC -*/ -#if (defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__) - #ifdef __ARM_ARCH_6M__ - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - __asm volatile ("mrs %0, primask \n\t" \ - "mov r1, $1 \n\t" \ - "msr primask, r1 \n\t" \ - : "=r" (LockState) \ - : \ - : "r1" \ - ); - - #define SEGGER_RTT_UNLOCK() __asm volatile ("msr primask, %0 \n\t" \ - : \ - : "r" (LockState) \ - : \ - ); \ - } - - #elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)) - #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) - #endif - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - __asm volatile ("mrs %0, basepri \n\t" \ - "mov r1, %1 \n\t" \ - "msr basepri, r1 \n\t" \ - : "=r" (LockState) \ - : "i"(SEGGER_RTT_MAX_INTERRUPT_PRIORITY) \ - : "r1" \ - ); - - #define SEGGER_RTT_UNLOCK() __asm volatile ("msr basepri, %0 \n\t" \ - : \ - : "r" (LockState) \ - : \ - ); \ - } - - #elif defined(__ARM_ARCH_7A__) - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - __asm volatile ("mrs r1, CPSR \n\t" \ - "mov %0, r1 \n\t" \ - "orr r1, r1, #0xC0 \n\t" \ - "msr CPSR_c, r1 \n\t" \ - : "=r" (LockState) \ - : \ - : "r1" \ - ); - - #define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \ - "mrs r1, CPSR \n\t" \ - "bic r1, r1, #0xC0 \n\t" \ - "and r0, r0, #0xC0 \n\t" \ - "orr r1, r1, r0 \n\t" \ - "msr CPSR_c, r1 \n\t" \ - : \ - : "r" (LockState) \ - : "r0", "r1" \ - ); \ - } -#else - #define SEGGER_RTT_LOCK() - #define SEGGER_RTT_UNLOCK() - #endif -#endif - -/********************************************************************* -* -* RTT lock configuration for IAR EWARM -*/ -#ifdef __ICCARM__ - #if (defined (__ARM6M__) && (__CORE__ == __ARM6M__)) - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - LockState = __get_PRIMASK(); \ - __set_PRIMASK(1); - - #define SEGGER_RTT_UNLOCK() __set_PRIMASK(LockState); \ - } - #elif ((defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) || (defined (__ARM7M__) && (__CORE__ == __ARM7M__))) - #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) - #endif - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - LockState = __get_BASEPRI(); \ - __set_BASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY); - - #define SEGGER_RTT_UNLOCK() __set_BASEPRI(LockState); \ - } - #endif -#endif - -/********************************************************************* -* -* RTT lock configuration for KEIL ARM -*/ -#ifdef __CC_ARM - #if (defined __TARGET_ARCH_6S_M) - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - register unsigned char PRIMASK __asm( "primask"); \ - LockState = PRIMASK; \ - PRIMASK = 1u; \ - __schedule_barrier(); - - #define SEGGER_RTT_UNLOCK() PRIMASK = LockState; \ - __schedule_barrier(); \ - } - #elif (defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M)) - #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) - #endif - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - register unsigned char BASEPRI __asm( "basepri"); \ - LockState = BASEPRI; \ - BASEPRI = SEGGER_RTT_MAX_INTERRUPT_PRIORITY; \ - __schedule_barrier(); - - #define SEGGER_RTT_UNLOCK() BASEPRI = LockState; \ - __schedule_barrier(); \ - } - #endif -#endif - -/********************************************************************* -* -* RTT lock configuration fallback -*/ -#ifndef SEGGER_RTT_LOCK - #define SEGGER_RTT_LOCK() // Lock RTT (nestable) (i.e. disable interrupts) -#endif - -#ifndef SEGGER_RTT_UNLOCK - #define SEGGER_RTT_UNLOCK() // Unlock RTT (nestable) (i.e. enable previous interrupt lock state) -#endif - -#endif -/*************************** End of file ****************************/ diff --git a/segger/SEGGER_RTT_SES.c b/segger/SEGGER_RTT_SES.c deleted file mode 100644 index e663414..0000000 --- a/segger/SEGGER_RTT_SES.c +++ /dev/null @@ -1,76 +0,0 @@ -/********************************************************************* -* SEGGER MICROCONTROLLER GmbH & Co. KG * -* Solutions for real time microcontroller applications * -********************************************************************** -* * -* (c) 2014 - 2015 SEGGER Microcontroller GmbH & Co. KG * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* * This software may in its unmodified form be freely redistributed * -* in source form. * -* * The source code may be modified, provided the source code * -* retains the above copyright notice, this list of conditions and * -* the following disclaimer. * -* * Modified versions of this software in source or linkable form * -* may not be distributed without prior consent of SEGGER. * -* * This software may only be used for communication with SEGGER * -* J-Link debug probes. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** --------- END-OF-HEADER --------------------------------------------- -File : SEGGER_RTT_Syscalls_SES.c -Purpose : Reimplementation of printf, puts and - implementation of __putchar and __getchar using RTT in SES. - To use RTT for printf output, include this file in your - application. ----------------------------------------------------------------------- -*/ -#include "SEGGER_RTT.h" -#include "__libc.h" -#include -#include - -int printf(const char *fmt,...) { - char buffer[128]; - va_list args; - va_start (args, fmt); - int n = vsnprintf(buffer, sizeof(buffer), fmt, args); - SEGGER_RTT_Write(0, buffer, n); - va_end(args); - return n; -} - -int puts(const char *s) { - return SEGGER_RTT_WriteString(0, s); -} - -int __putchar(int x, __printf_tag_ptr ctx) { - (void)ctx; - SEGGER_RTT_Write(0, (char *)&x, 1); - return x; -} - -int __getchar() { - return SEGGER_RTT_WaitKey(); -} - -/****** End Of File *************************************************/ diff --git a/segger/flash_placement.xml b/segger/flash_placement.xml deleted file mode 100644 index 70d131a..0000000 --- a/segger/flash_placement.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/segger/nRF52832_xxAA_MemoryMap.xml b/segger/nRF52832_xxAA_MemoryMap.xml deleted file mode 100644 index 809e2a1..0000000 --- a/segger/nRF52832_xxAA_MemoryMap.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/segger/nRF52840_xxAA_MemoryMap.xml b/segger/nRF52840_xxAA_MemoryMap.xml deleted file mode 100644 index c37570c..0000000 --- a/segger/nRF52840_xxAA_MemoryMap.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/segger/nRF_Target.js b/segger/nRF_Target.js deleted file mode 100644 index 20560af..0000000 --- a/segger/nRF_Target.js +++ /dev/null @@ -1,19 +0,0 @@ -/***************************************************************************** - * SEGGER Microcontroller GmbH & Co. KG * - * Solutions for real time microcontroller applications * - ***************************************************************************** - * * - * (c) 2017 SEGGER Microcontroller GmbH & Co. KG * - * * - * Internet: www.segger.com Support: support@segger.com * - * * - *****************************************************************************/ - -function Reset() { - TargetInterface.resetAndStop(); -} - -function EnableTrace(traceInterfaceType) { - // TODO: Enable trace -} - diff --git a/segger/nrf52840_Registers.xml b/segger/nrf52840_Registers.xml deleted file mode 100644 index 39f861f..0000000 --- a/segger/nrf52840_Registers.xml +++ /dev/null @@ -1,22310 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/segger/thumb_crt0.s b/segger/thumb_crt0.s deleted file mode 100644 index 71820cb..0000000 --- a/segger/thumb_crt0.s +++ /dev/null @@ -1,420 +0,0 @@ -// SEGGER Embedded Studio, runtime support. -// -// Copyright (c) 2014-2017 SEGGER Microcontroller GmbH & Co KG -// Copyright (c) 2001-2017 Rowley Associates Limited. -// -// This file may be distributed under the terms of the License Agreement -// provided with this software. -// -// THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -// -// -// Preprocessor Definitions -// ------------------------ -// APP_ENTRY_POINT -// -// Defines the application entry point function, if undefined this setting -// defaults to "main". -// -// INITIALIZE_STACK -// -// If defined, the contents of the stack will be initialized to a the -// value 0xCC. -// -// INITIALIZE_SECONDARY_SECTIONS -// -// If defined, the .data2, .text2, .rodata2 and .bss2 sections will be initialized. -// -// INITIALIZE_TCM_SECTIONS -// -// If defined, the .data_tcm, .text_tcm, .rodata_tcm and .bss_tcm sections -// will be initialized. -// -// INITIALIZE_USER_SECTIONS -// -// If defined, the function InitializeUserMemorySections will be called prior -// to entering main in order to allow the user to initialize any user defined -// memory sections. -// -// FULL_LIBRARY -// -// If defined then -// - argc, argv are setup by the debug_getargs. -// - the exit symbol is defined and executes on return from main. -// - the exit symbol calls destructors, atexit functions and then debug_exit. -// -// If not defined then -// - argc and argv are zero. -// - the exit symbol is defined, executes on return from main and loops -// - -#ifndef APP_ENTRY_POINT -#define APP_ENTRY_POINT main -#endif - -#ifndef ARGSSPACE -#define ARGSSPACE 128 -#endif - .syntax unified - - .global _start - .extern APP_ENTRY_POINT - .global exit - .weak exit - -#ifdef INITIALIZE_USER_SECTIONS - .extern InitializeUserMemorySections -#endif - - .section .init, "ax" - .code 16 - .align 2 - .thumb_func - -_start: - /* Set up main stack if size > 0 */ - ldr r1, =__stack_end__ - ldr r0, =__stack_start__ - subs r2, r1, r0 - beq 1f -#ifdef __ARM_EABI__ - movs r2, #0x7 - bics r1, r2 -#endif - mov sp, r1 -#ifdef INITIALIZE_STACK - movs r2, #0xCC - ldr r0, =__stack_start__ - bl memory_set -#endif -1: - - /* Set up process stack if size > 0 */ - ldr r1, =__stack_process_end__ - ldr r0, =__stack_process_start__ - subs r2, r1, r0 - beq 1f -#ifdef __ARM_EABI__ - movs r2, #0x7 - bics r1, r2 -#endif - msr psp, r1 - movs r2, #2 - msr control, r2 -#ifdef INITIALIZE_STACK - movs r2, #0xCC - bl memory_set -#endif -1: - - /* Copy initialized memory sections into RAM (if necessary). */ - ldr r0, =__data_load_start__ - ldr r1, =__data_start__ - ldr r2, =__data_end__ - bl memory_copy - ldr r0, =__text_load_start__ - ldr r1, =__text_start__ - ldr r2, =__text_end__ - bl memory_copy - ldr r0, =__fast_load_start__ - ldr r1, =__fast_start__ - ldr r2, =__fast_end__ - bl memory_copy - ldr r0, =__ctors_load_start__ - ldr r1, =__ctors_start__ - ldr r2, =__ctors_end__ - bl memory_copy - ldr r0, =__dtors_load_start__ - ldr r1, =__dtors_start__ - ldr r2, =__dtors_end__ - bl memory_copy - ldr r0, =__rodata_load_start__ - ldr r1, =__rodata_start__ - ldr r2, =__rodata_end__ - bl memory_copy - ldr r0, =__tdata_load_start__ - ldr r1, =__tdata_start__ - ldr r2, =__tdata_end__ - bl memory_copy -#ifdef INITIALIZE_SECONDARY_SECTIONS - ldr r0, =__data2_load_start__ - ldr r1, =__data2_start__ - ldr r2, =__data2_end__ - bl memory_copy - ldr r0, =__text2_load_start__ - ldr r1, =__text2_start__ - ldr r2, =__text2_end__ - bl memory_copy - ldr r0, =__rodata2_load_start__ - ldr r1, =__rodata2_start__ - ldr r2, =__rodata2_end__ - bl memory_copy -#endif /* #ifdef INITIALIZE_SECONDARY_SECTIONS */ -#ifdef INITIALIZE_TCM_SECTIONS - ldr r0, =__data_tcm_load_start__ - ldr r1, =__data_tcm_start__ - ldr r2, =__data_tcm_end__ - bl memory_copy - ldr r0, =__text_tcm_load_start__ - ldr r1, =__text_tcm_start__ - ldr r2, =__text_tcm_end__ - bl memory_copy - ldr r0, =__rodata_tcm_load_start__ - ldr r1, =__rodata_tcm_start__ - ldr r2, =__rodata_tcm_end__ - bl memory_copy -#endif /* #ifdef INITIALIZE_TCM_SECTIONS */ - - /* Zero the bss. */ - ldr r0, =__bss_start__ - ldr r1, =__bss_end__ - movs r2, #0 - bl memory_set - ldr r0, =__tbss_start__ - ldr r1, =__tbss_end__ - movs r2, #0 - bl memory_set -#ifdef INITIALIZE_SECONDARY_SECTIONS - ldr r0, =__bss2_start__ - ldr r1, =__bss2_end__ - mov r2, #0 - bl memory_set -#endif /* #ifdef INITIALIZE_SECONDARY_SECTIONS */ -#ifdef INITIALIZE_TCM_SECTIONS - ldr r0, =__bss_tcm_start__ - ldr r1, =__bss_tcm_end__ - mov r2, #0 - bl memory_set -#endif /* #ifdef INITIALIZE_TCM_SECTIONS */ - - /* Initialize the heap */ - ldr r0, = __heap_start__ - ldr r1, = __heap_end__ - subs r1, r1, r0 - cmp r1, #8 - blt 1f - movs r2, #0 - str r2, [r0] - adds r0, r0, #4 - str r1, [r0] -1: - -#ifdef INITIALIZE_USER_SECTIONS - ldr r2, =InitializeUserMemorySections - blx r2 -#endif - - /* Call constructors */ - ldr r0, =__ctors_start__ - ldr r1, =__ctors_end__ -ctor_loop: - cmp r0, r1 - beq ctor_end - ldr r2, [r0] - adds r0, #4 - push {r0-r1} - blx r2 - pop {r0-r1} - b ctor_loop -ctor_end: - - /* Setup initial call frame */ - movs r0, #0 - mov lr, r0 - mov r12, sp - - .type start, function -start: - /* Jump to application entry point */ -#ifdef FULL_LIBRARY - movs r0, #ARGSSPACE - ldr r1, =args - ldr r2, =debug_getargs - blx r2 - ldr r1, =args -#else - movs r0, #0 - movs r1, #0 -#endif - ldr r2, =APP_ENTRY_POINT - blx r2 - - .thumb_func -exit: -#ifdef FULL_LIBRARY - mov r5, r0 // save the exit parameter/return result - - /* Call destructors */ - ldr r0, =__dtors_start__ - ldr r1, =__dtors_end__ -dtor_loop: - cmp r0, r1 - beq dtor_end - ldr r2, [r0] - add r0, #4 - push {r0-r1} - blx r2 - pop {r0-r1} - b dtor_loop -dtor_end: - - /* Call atexit functions */ - ldr r2, =_execute_at_exit_fns - blx r2 - - /* Call debug_exit with return result/exit parameter */ - mov r0, r5 - ldr r2, =debug_exit - blx r2 -#endif - - /* Returned from application entry point, loop forever. */ -exit_loop: - b exit_loop - - .thumb_func -memory_copy: - cmp r0, r1 - beq 2f - subs r2, r2, r1 - beq 2f -1: - ldrb r3, [r0] - adds r0, r0, #1 - strb r3, [r1] - adds r1, r1, #1 - subs r2, r2, #1 - bne 1b -2: - bx lr - - .thumb_func -memory_set: - cmp r0, r1 - beq 1f - strb r2, [r0] - adds r0, r0, #1 - b memory_set -1: - bx lr - - // default C/C++ library helpers - -.macro HELPER helper_name - .section .text.\helper_name, "ax", %progbits - .global \helper_name - .weak \helper_name -\helper_name: - .thumb_func -.endm - -.macro JUMPTO name -#if defined(__thumb__) && !defined(__thumb2__) - mov r12, r0 - ldr r0, =\name - push {r0} - mov r0, r12 - pop {pc} -#else - b \name -#endif -.endm - -HELPER __aeabi_read_tp - ldr r0, =__tbss_start__-8 - bx lr -HELPER __heap_lock - bx lr -HELPER __heap_unlock - bx lr -HELPER __printf_lock - bx lr -HELPER __printf_unlock - bx lr -HELPER __scanf_lock - bx lr -HELPER __scanf_unlock - bx lr -HELPER __debug_io_lock - bx lr -HELPER __debug_io_unlock - bx lr -HELPER abort - b . -HELPER __assert - b . -HELPER __aeabi_assert - b . -HELPER __cxa_pure_virtual - b . -HELPER __cxa_guard_acquire - ldr r3, [r0] -#if defined(__thumb__) && !defined(__thumb2__) - movs r0, #1 - tst r3, r0 -#else - tst r3, #1 -#endif - beq 1f - movs r0, #0 - bx lr -1: - movs r0, #1 - bx lr -HELPER __cxa_guard_release - movs r3, #1 - str r3, [r0] - bx lr -HELPER __cxa_guard_abort - bx lr -HELPER __sync_synchronize - bx lr -HELPER __getchar - JUMPTO debug_getchar -HELPER __putchar - JUMPTO debug_putchar -HELPER __open - JUMPTO debug_fopen -HELPER __close - JUMPTO debug_fclose -HELPER __write - mov r3, r0 - mov r0, r1 - movs r1, #1 - JUMPTO debug_fwrite -HELPER __read - mov r3, r0 - mov r0, r1 - movs r1, #1 - JUMPTO debug_fread -HELPER __seek - push {r4, lr} - mov r4, r0 - bl debug_fseek - cmp r0, #0 - bne 1f - mov r0, r4 - bl debug_ftell - pop {r4, pc} -1: - ldr r0, =-1 - pop {r4, pc} - // char __user_locale_name_buffer[]; - .section .bss.__user_locale_name_buffer, "aw", %nobits - .global __user_locale_name_buffer - .weak __user_locale_name_buffer - __user_locale_name_buffer: - .word 0x0 - -#ifdef FULL_LIBRARY - .bss -args: - .space ARGSSPACE -#endif - - /* Setup attibutes of stack and heap sections so they don't take up room in the elf file */ - .section .stack, "wa", %nobits - .section .stack_process, "wa", %nobits - .section .heap, "wa", %nobits - From 859a721b41654a2212f50d0423162aa344e5ef2f Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 Dec 2025 18:11:08 +0700 Subject: [PATCH 68/90] remove git submodules from uf2 version --- CMakeLists.txt | 101 +++++++++++++++++++++---------------------------- Makefile | 4 +- src/screen.c | 6 +-- 3 files changed, 47 insertions(+), 64 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ae9b9cf..401acc2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,40 +20,26 @@ endif () include(${CMAKE_CURRENT_LIST_DIR}/cmake/toolchain/arm_gcc.cmake) - -project(Adafruit_nRF52_Bootloader C ASM) - set(NRFX_DIR ${CMAKE_CURRENT_LIST_DIR}/lib/nrfx) set(SDK11_DIR ${CMAKE_CURRENT_LIST_DIR}/lib/sdk11/components) set(SDK_DIR ${CMAKE_CURRENT_LIST_DIR}/lib/sdk/components) set(SOFTDEVICE_DIR ${CMAKE_CURRENT_LIST_DIR}/lib/softdevice) +set(MBR_HEX ${SOFTDEVICE_DIR}/mbr/hex/mbr_nrf52_2.4.1_mbr.hex) set(TINYUSB_DIR ${CMAKE_CURRENT_LIST_DIR}/lib/tinyusb/src) set(UF2CONV_PY ${CMAKE_CURRENT_LIST_DIR}/lib/uf2/utils/uf2conv.py) set(UF2_FAMILY_ID_BOOTLOADER 0xd663823c) +#------------------- +# Bootloader +#------------------- if (NOT DEFINED CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "") set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING "Build type" FORCE) endif () -#------------------- -# Bootloader -#------------------- +project(Adafruit_nRF52_Bootloader C ASM) set(CMAKE_EXECUTABLE_SUFFIX .elf) -add_executable(bootloader) - -# SD_VERSION can be overwritten by board.cmake -if(NOT DEFINED SD_VERSION) - if(MCU_VARIANT STREQUAL "nrf52833") - set(SD_VERSION 7.3.0) - else() - set(SD_VERSION 6.1.1) - endif() -endif () - -set(MBR_HEX ${SOFTDEVICE_DIR}/mbr/hex/mbr_nrf52_2.4.1_mbr.hex) - -target_sources(bootloader PUBLIC +add_executable(bootloader # src src/dfu_ble_svc.c src/dfu_init.c @@ -86,7 +72,7 @@ target_sources(bootloader PUBLIC ${SDK_DIR}/libraries/hci/hci_slip.c ${SDK_DIR}/libraries/hci/hci_transport.c ${SDK_DIR}/libraries/util/nrf_assert.c - # ASM + # startup ${NRFX_DIR}/mdk/gcc_startup_${MCU_VARIANT}.S ) target_include_directories(bootloader PUBLIC @@ -122,28 +108,9 @@ target_include_directories(bootloader PUBLIC ${SOFTDEVICE_DIR}/mbr/headers ) -# Debug option +# Debug linker file if (CMAKE_BUILD_TYPE STREQUAL "Debug") - # TODO not work yet, also need to add segger rtt, DFU_APP_DATA_RESERVED=0, BOOTLOADER_REGION_START=0xED000 set(LD_FILE ${CMAKE_CURRENT_LIST_DIR}/linker/${MCU_VARIANT}_debug.ld) - - target_sources(bootloader PUBLIC - lib/SEGGER_RTT/RTT/SEGGER_RTT.c - ) - target_include_directories(bootloader PUBLIC - lib/SEGGER_RTT/RTT - ) - target_compile_definitions(bootloader PUBLIC - CFG_DEBUG - SEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL - DFU_APP_DATA_RESERVED=0 - ) - - if (MCU_VARIANT STREQUAL "nrf52840") - target_compile_definitions(bootloader PUBLIC BOOTLOADER_REGION_START=0xEA000) - else () - target_compile_definitions(bootloader PUBLIC BOOTLOADER_REGION_START=0x6D000) - endif () else () set(LD_FILE ${CMAKE_CURRENT_LIST_DIR}/linker/${MCU_VARIANT}.ld) endif () @@ -222,6 +189,16 @@ endif () # MCU Variant differences # Supported are: nrf52 (nrf52832), nrf52833, nrf52840 #---------------------------------------------------- + +# SD_VERSION can be overwritten by board.cmake +if(NOT DEFINED SD_VERSION) + if(MCU_VARIANT STREQUAL "nrf52833") + set(SD_VERSION 7.3.0) + else() + set(SD_VERSION 6.1.1) + endif() +endif () + if (MCU_VARIANT STREQUAL "nrf52") set(SD_NAME s132) set(DFU_DEV_REV 0xADAF) @@ -246,17 +223,31 @@ else () message(FATAL_ERROR "MCU_VARIANT ${MCU_VARIANT} is unknown") endif () -string(TOUPPER ${SD_NAME} SD_NAME_UPPER) -target_compile_definitions(bootloader PUBLIC ${SD_NAME_UPPER}) - set(SD_FILENAME ${SD_NAME}_nrf52_${SD_VERSION}) set(SD_HEX ${SOFTDEVICE_DIR}/${SD_FILENAME}/${SD_FILENAME}_softdevice.hex) +string(TOUPPER ${SD_NAME} SD_NAME_UPPER) +target_compile_definitions(bootloader PUBLIC ${SD_NAME_UPPER}) target_include_directories(bootloader PUBLIC ${SOFTDEVICE_DIR}/${SD_FILENAME}/${SD_FILENAME}_API/include ) -if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug") +# debug build +if (CMAKE_BUILD_TYPE STREQUAL "Debug") + # TODO not work yet, also need to add segger rtt, DFU_APP_DATA_RESERVED=0, BOOTLOADER_REGION_START=0xED000 + target_sources(bootloader PUBLIC lib/SEGGER_RTT/RTT/SEGGER_RTT.c) + target_include_directories(bootloader PUBLIC lib/SEGGER_RTT/RTT) + target_compile_definitions(bootloader PUBLIC + CFG_DEBUG + SEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL + DFU_APP_DATA_RESERVED=0 + ) + if (MCU_VARIANT STREQUAL "nrf52840") + target_compile_definitions(bootloader PUBLIC BOOTLOADER_REGION_START=0xEA000) + else () + target_compile_definitions(bootloader PUBLIC BOOTLOADER_REGION_START=0x6D000) + endif () +else () target_compile_definitions(bootloader PUBLIC DFU_APP_DATA_RESERVED=${DFU_APP_DATA_RESERVED}) endif () @@ -273,13 +264,6 @@ endif() execute_process(COMMAND git describe --dirty --always --tags OUTPUT_VARIABLE GIT_VERSION) string(STRIP ${GIT_VERSION} GIT_VERSION) -execute_process(COMMAND bash "-c" "git submodule status | cut -d\" \" -f3,4 | paste -s -d\" \" -" - OUTPUT_VARIABLE GIT_SUBMODULE_VERSIONS - ) -string(STRIP ${GIT_SUBMODULE_VERSIONS} GIT_SUBMODULE_VERSIONS) -string(REPLACE ../ "" GIT_SUBMODULE_VERSIONS ${GIT_SUBMODULE_VERSIONS}) -string(REPLACE lib/ "" GIT_SUBMODULE_VERSIONS ${GIT_SUBMODULE_VERSIONS}) - string(REPLACE "-" ";" RELEASE_VERSION ${GIT_VERSION}) list(GET RELEASE_VERSION 0 RELEASE_VERSION) string(REPLACE "." ";" RELEASE_VERSION ${RELEASE_VERSION}) @@ -288,11 +272,10 @@ 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}") -cmake_print_variables(GIT_VERSION GIT_SUBMODULE_VERSIONS MK_BOOTLOADER_VERSION) +cmake_print_variables(GIT_VERSION MK_BOOTLOADER_VERSION) target_compile_definitions(bootloader PUBLIC - UF2_VERSION_BASE="${GIT_VERSION}" - UF2_VERSION="${GIT_VERSION} - ${GIT_SUBMODULE_VERSIONS}" + UF2_VERSION="${GIT_VERSION}" BLEDIS_FW_VERSION="${GIT_VERSION} ${SD_NAME} ${SD_VERSION}" MK_BOOTLOADER_VERSION=${MK_BOOTLOADER_VERSION} ) @@ -324,11 +307,11 @@ add_custom_target(flash-uf2 add_custom_target(flash-sd DEPENDS flash-mbr - COMMAND ${NRFJPROG} --program ${SD_HEX} --verify --sectorerase -f nrf52 --reset + COMMAND ${NRFJPROG} --program ${SD_HEX} --verify --sectorerase -f nrf52 ) add_custom_target(flash-mbr - COMMAND ${NRFJPROG} --program ${MBR_HEX} --verify --sectorerase -f nrf52 --reset + COMMAND ${NRFJPROG} --program ${MBR_HEX} --verify --sectorerase -f nrf52 ) add_custom_target(flash-erase @@ -336,7 +319,9 @@ add_custom_target(flash-erase ) add_custom_target(flash-all - DEPENDS flash-erase flash-sd flash-bootloader + DEPENDS bootloader flash-erase + COMMAND ${NRFJPROG} --program ${SD_HEX} --verify --sectorerase -f nrf52 + COMMAND ${NRFJPROG} --program $ --verify --sectoranduicrerase -f nrf52 --reset ) # flash skip crc magic ( app valid = 0x0001, crc = 0x0000 ) diff --git a/Makefile b/Makefile index 326a709..dba3c83 100644 --- a/Makefile +++ b/Makefile @@ -41,7 +41,6 @@ else endif GIT_VERSION := $(shell git describe --dirty --always --tags) -GIT_SUBMODULE_VERSIONS := $(shell git submodule status | cut -d" " -f3,4 | paste -s -d" " -) # compiled file name OUT_NAME = $(BOARD)_bootloader-$(GIT_VERSION) @@ -324,8 +323,7 @@ ifneq ($(USE_NFCT),yes) endif CFLAGS += -DSOFTDEVICE_PRESENT -CFLAGS += -DUF2_VERSION_BASE='"$(GIT_VERSION)"' -CFLAGS += -DUF2_VERSION='"$(GIT_VERSION) $(GIT_SUBMODULE_VERSIONS)"' +CFLAGS += -DUF2_VERSION='"$(GIT_VERSION)"' CFLAGS += -DBLEDIS_FW_VERSION='"$(GIT_VERSION) $(SD_NAME) $(SD_VERSION)"' _VER = $(subst ., ,$(word 1, $(subst -, ,$(GIT_VERSION)))) diff --git a/src/screen.c b/src/screen.c index 8931b55..f51330a 100644 --- a/src/screen.c +++ b/src/screen.c @@ -242,12 +242,12 @@ void screen_draw_drag(void) { drawBar(52, 55, COLOR_BLUE); drawBar(107, 14, COLOR_ORANGE); - // Center UF2_PRODUCT_NAME and UF2_VERSION_BASE. + // Center UF2_PRODUCT_NAME and UF2_VERSION. int name_x = (DISPLAY_WIDTH - CHAR4_KERNED_WIDTH * (int) strlen(DISPLAY_TITLE)) / 2; print4(name_x >= 0 ? name_x : 0, 5, COLOR_WHITE, DISPLAY_TITLE); - int version_x = (DISPLAY_WIDTH - 6 * (int) strlen(UF2_VERSION_BASE)) / 2; - print(version_x >= 0 ? version_x : 0, 40, COLOR_PURPLE, UF2_VERSION_BASE); + int version_x = (DISPLAY_WIDTH - 6 * (int) strlen(UF2_VERSION)) / 2; + print(version_x >= 0 ? version_x : 0, 40, COLOR_PURPLE, UF2_VERSION); // TODO the reset should be center as well print(23, 110, 1, "circuitpython.org"); From 24768bcd9a97367e349a965fd131de8f002c143a Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 Dec 2025 22:50:49 +0700 Subject: [PATCH 69/90] clean up --- .clang-format | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 6 ++-- src/main.c | 67 ++++++++++++++++------------------ 3 files changed, 133 insertions(+), 39 deletions(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..2cd0e15 --- /dev/null +++ b/.clang-format @@ -0,0 +1,99 @@ +--- +Language: Cpp +BasedOnStyle: LLVM +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false +AlignConsecutiveBitFields: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false +AlignConsecutiveDeclarations: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false +AlignConsecutiveMacros: + Enabled: true + AcrossEmptyLines: true + AcrossComments: false +AlignConsecutiveShortCaseStatements: + Enabled: true + AcrossEmptyLines: true + AcrossComments: true + AlignCaseColons: false +AlignEscapedNewlines: LeftWithLastLine +AlignOperands: true +AlignTrailingComments: + Kind: Always + OverEmptyLines: 2 +AllowAllArgumentsOnNextLine: false +AllowAllConstructorInitializersOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: Empty +AllowShortCaseExpressionOnASingleLine: true +AllowShortCaseLabelsOnASingleLine: false +AllowShortEnumsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: Never +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: true +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: true + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BracedInitializerIndentWidth: 2 +BreakBeforeBinaryOperators: None +BreakConstructorInitializers: AfterColon +BreakConstructorInitializersBeforeComma: false +ContinuationIndentWidth: 2 +ColumnLimit: 120 +ConstructorInitializerAllOnOneLineOrOnePerLine: false +Cpp11BracedListStyle: true +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^<.*' + Priority: 1 + - Regex: '^".*' + Priority: 2 + - Regex: '.*' + Priority: 3 +IncludeIsMainRegex: '([-_](test|unittest))?$' +IndentPPDirectives: BeforeHash +InsertBraces: true +IndentCaseLabels: true +InsertNewlineAtEOF: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 2 +NamespaceIndentation: All +PenaltyBreakBeforeFirstCallParameter: 1000000 +PenaltyBreakOpenParenthesis: 1000000 +PPIndentWidth: 2 +QualifierAlignment: Custom +QualifierOrder: ['static', 'const', 'volatile', 'restrict', 'type'] +SpaceAfterTemplateKeyword: false +SpaceBeforeRangeBasedForLoopColon: false +SpaceInEmptyParentheses: false +SpacesInAngles: false +SpacesInConditionalStatement: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SortIncludes: false +TabWidth: 2 +... diff --git a/README.md b/README.md index 4c7066f..8fda77a 100644 --- a/README.md +++ b/README.md @@ -137,7 +137,7 @@ make BOARD=feather_nrf52840_express all For the list of supported boards, run `make` without `BOARD=` : ``` -$ make +make You must provide a BOARD parameter with 'BOARD=' Supported boards are: feather_nrf52840_express feather_nrf52840_express pca10056 Makefile:90: *** BOARD not defined. Stop @@ -213,7 +213,7 @@ make BOARD=feather_nrf52840_express flash-mbr If you get the following error ... ``` -$ make BOARD=feather_nrf52840_express all +make BOARD=feather_nrf52840_express all Compiling file: main.c /bin/sh: /usr/bin/arm-none-eabi-gcc: No such file or directory make: *** [_build/main.o] Error 127 @@ -222,7 +222,7 @@ make: *** [_build/main.o] Error 127 ... you may need to pass the location of the GCC ARM toolchain binaries to `make` using the variable `CROSS_COMPILE` as below: ``` -$ make CROSS_COMPILE=/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/arm-none-eabi- BOARD=feather_nrf52832 all +make CROSS_COMPILE=/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/arm-none-eabi- BOARD=feather_nrf52832 all ``` For other compile errors, check the gcc version with `arm-none-eabi-gcc --version` to insure it is at least 9.x. diff --git a/src/main.c b/src/main.c index a4c0a70..9ebc9e9 100644 --- a/src/main.c +++ b/src/main.c @@ -39,13 +39,8 @@ #include #include "nrfx.h" -#include "nrf_clock.h" #include "nrfx_power.h" -#include "nrfx_pwm.h" - -#include "nordic_common.h" #include "sdk_common.h" -#include "dfu_transport.h" #include "bootloader.h" #include "bootloader_util.h" @@ -53,10 +48,7 @@ #include "nrf_soc.h" #include "nrf_nvic.h" #include "app_error.h" -#include "nrf_gpio.h" #include "ble.h" -#include "nrf.h" -#include "ble_hci.h" #include "app_scheduler.h" #include "nrf_error.h" @@ -64,13 +56,10 @@ #include "pstorage_platform.h" #include "nrf_mbr.h" -#include "pstorage.h" -#include "nrfx_nvmc.h" #ifdef NRF_USBD #include "uf2/uf2.h" -#include "nrf_usbd.h" #include "tusb.h" void usb_init(bool cdc_only); @@ -250,14 +239,17 @@ static void check_dfu_mode(void) { (((*dbl_reset_mem) == DFU_DBL_RESET_MAGIC) && reason_reset_pin); // Clear GPREGRET if it is our values - if (dfu_start || dfu_skip) NRF_POWER->GPREGRET = 0; + if (dfu_start || dfu_skip) { + NRF_POWER->GPREGRET = 0; + } // skip dfu entirely - if (dfu_skip) return; + if (dfu_skip) { + return; + } /*------------- Determine DFU mode (Serial, OTA, FRESET or normal) -------------*/ - // DFU button pressed - dfu_start = dfu_start || button_pressed(BUTTON_DFU); + dfu_start = dfu_start || button_pressed(BUTTON_DFU); // DFU button pressed // DFU + FRESET are pressed --> OTA _ota_dfu = _ota_dfu || (button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET)); @@ -265,16 +257,16 @@ static void check_dfu_mode(void) { bool const valid_app = bootloader_app_is_valid(); bool const just_start_app = valid_app && !dfu_start && (*dbl_reset_mem) == DFU_DBL_RESET_APP; - if (!just_start_app && APP_ASKS_FOR_SINGLE_TAP_RESET()) dfu_start = 1; + if (!just_start_app && APP_ASKS_FOR_SINGLE_TAP_RESET()) { + dfu_start = 1; + } // App mode: Double Reset detection or DFU startup for nrf52832 if (!(just_start_app || dfu_start || !valid_app)) { #ifdef NRF52832_XXAA /* Even DFU is not active, we still force an 1000 ms dfu serial mode when startup * to support auto programming from Arduino IDE - * - * Note: Double Reset WONT work with nrf52832 since all its SRAM got cleared with GPIO reset. - */ + * Note: Double Reset WONT work with nrf52832 since all its SRAM got cleared with GPIO reset. */ bootloader_dfu_start(false, DFU_SERIAL_STARTUP_INTERVAL, false); #else // Note: RESETREAS is not clear by bootloader, it should be cleared by application upon init() @@ -323,6 +315,10 @@ static void check_dfu_mode(void) { } } +//--------------------------------------------------------------------+ +// BLE +//--------------------------------------------------------------------+ + // Initializes the SoftDevice by following SD specs section // "Master Boot Record and SoftDevice initializaton procedure" static uint32_t ble_stack_init(void) { @@ -389,23 +385,6 @@ static uint32_t ble_stack_init(void) { return NRF_SUCCESS; } -//--------------------------------------------------------------------+ -// Error Handler -//--------------------------------------------------------------------+ -void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) { - volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ - if ((*ARM_CM_DHCSR) & 1UL) __asm("BKPT #0\n"); /* Only halt mcu if debugger is attached */ - NVIC_SystemReset(); -} - -void assert_nrf_callback(uint16_t line_num, uint8_t const* p_file_name) { - app_error_fault_handler(0xDEADBEEF, 0, 0); -} - -/*------------------------------------------------------------------*/ -/* SoftDevice Event handler - *------------------------------------------------------------------*/ - // Process BLE event from SD uint32_t proc_ble(void) { __ALIGN(4) uint8_t ev_buf[BLE_EVT_LEN_MAX(BLEGATT_ATT_MTU_MAX)]; @@ -479,6 +458,22 @@ void SD_EVT_IRQHandler(void) { app_sched_event_put(NULL, 0, proc_sd_task); } +//--------------------------------------------------------------------+ +// Error Handler +//--------------------------------------------------------------------+ +void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) { + volatile uint32_t *ARM_CM_DHCSR = ((volatile uint32_t *)0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ + if ((*ARM_CM_DHCSR) & 1UL) { + __asm("BKPT #0\n"); /* Only halt mcu if debugger is attached */ + } + NVIC_SystemReset(); +} + +void assert_nrf_callback(uint16_t line_num, const uint8_t *p_file_name) { + app_error_fault_handler(0xDEADBEEF, 0, 0); +} + + //--------------------------------------------------------------------+ // RTT printf retarget for Debug //--------------------------------------------------------------------+ From f5ab453f75dbd2b1f6dde58611f5907b40e206b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Jos=C3=A9=20Tagle?= Date: Thu, 15 Jan 2026 00:31:39 -0300 Subject: [PATCH 70/90] Allow BLE characteristics to support both WriteWithoutResponse (for compatibility with Nordic DFU apps) and WriteWithResponse (for improved reliability) --- lib/sdk11/components/ble/ble_services/ble_dfu/ble_dfu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/sdk11/components/ble/ble_services/ble_dfu/ble_dfu.c b/lib/sdk11/components/ble/ble_services/ble_dfu/ble_dfu.c index ea716cb..2a4ede8 100644 --- a/lib/sdk11/components/ble/ble_services/ble_dfu/ble_dfu.c +++ b/lib/sdk11/components/ble/ble_services/ble_dfu/ble_dfu.c @@ -17,6 +17,7 @@ #include #include "sdk_common.h" +#define DFU_PKT_ENABLE_WR_WO_RESPONSE_ONLY 0 /**< Enable Write Without Response on Data Endpoint ONLY (otherwise both With and Without response will be supported)*/ #define MAX_DFU_PKT_LEN 20 /**< Maximum length (in bytes) of the DFU Packet characteristic. */ #define PKT_START_DFU_PARAM_LEN 2 /**< Length (in bytes) of the parameters for Packet Start DFU Request. */ #define PKT_INIT_DFU_PARAM_LEN 2 /**< Length (in bytes) of the parameters for Packet Init DFU Request. */ @@ -57,7 +58,12 @@ static uint32_t dfu_pkt_char_add(ble_dfu_t * const p_dfu) memset(&char_md, 0, sizeof(char_md)); +#if DFU_PKT_ENABLE_WR_WO_RESPONSE_ONLY char_md.char_props.write_wo_resp = 1; +#else + char_md.char_props.write = 1; // For those improved apps that can take advantage of ACK + char_md.char_props.write_wo_resp = 1; // Nordic IOS DFU app REQUIRES Write Without Response */ +#endif char_md.p_char_user_desc = NULL; char_md.p_char_pf = NULL; char_md.p_user_desc_md = NULL; From 2910556adc5960618ca8adf5c5b919f6669feb83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Jos=C3=A9=20Tagle?= Date: Thu, 15 Jan 2026 00:36:14 -0300 Subject: [PATCH 71/90] Wait until notification queue has enough room so no notifications of completed operations to the DFU app are lost --- .../ble/ble_services/ble_dfu/ble_dfu.c | 122 ++++++++++-------- 1 file changed, 70 insertions(+), 52 deletions(-) diff --git a/lib/sdk11/components/ble/ble_services/ble_dfu/ble_dfu.c b/lib/sdk11/components/ble/ble_services/ble_dfu/ble_dfu.c index 2a4ede8..685fdea 100644 --- a/lib/sdk11/components/ble/ble_services/ble_dfu/ble_dfu.c +++ b/lib/sdk11/components/ble/ble_services/ble_dfu/ble_dfu.c @@ -561,29 +561,35 @@ uint32_t ble_dfu_bytes_rcvd_report(ble_dfu_t * p_dfu, uint32_t num_of_firmware_b return NRF_ERROR_INVALID_STATE; } - ble_gatts_hvx_params_t hvx_params; - uint16_t index = 0; + uint32_t err_code; + do { - // Encode the Op Code. - m_notif_buffer[index++] = OP_CODE_RESPONSE; + ble_gatts_hvx_params_t hvx_params; + uint16_t index = 0; + + // Encode the Op Code. + m_notif_buffer[index++] = OP_CODE_RESPONSE; + + // Encode the Reqest Op Code. + m_notif_buffer[index++] = OP_CODE_IMAGE_SIZE_REQ; + + // Encode the Response Value. + m_notif_buffer[index++] = (uint8_t)BLE_DFU_RESP_VAL_SUCCESS; + + index += uint32_encode(num_of_firmware_bytes_rcvd, &m_notif_buffer[index]); + + memset(&hvx_params, 0, sizeof(hvx_params)); + + hvx_params.handle = p_dfu->dfu_ctrl_pt_handles.value_handle; + hvx_params.type = BLE_GATT_HVX_NOTIFICATION; + hvx_params.offset = 0; + hvx_params.p_len = &index; + hvx_params.p_data = m_notif_buffer; + + err_code = sd_ble_gatts_hvx(p_dfu->conn_handle, &hvx_params); + } while (err_code == NRF_ERROR_RESOURCES); - // Encode the Reqest Op Code. - m_notif_buffer[index++] = OP_CODE_IMAGE_SIZE_REQ; - - // Encode the Response Value. - m_notif_buffer[index++] = (uint8_t)BLE_DFU_RESP_VAL_SUCCESS; - - index += uint32_encode(num_of_firmware_bytes_rcvd, &m_notif_buffer[index]); - - memset(&hvx_params, 0, sizeof(hvx_params)); - - hvx_params.handle = p_dfu->dfu_ctrl_pt_handles.value_handle; - hvx_params.type = BLE_GATT_HVX_NOTIFICATION; - hvx_params.offset = 0; - hvx_params.p_len = &index; - hvx_params.p_data = m_notif_buffer; - - return sd_ble_gatts_hvx(p_dfu->conn_handle, &hvx_params); + return err_code; } @@ -599,22 +605,28 @@ uint32_t ble_dfu_pkts_rcpt_notify(ble_dfu_t * p_dfu, uint32_t num_of_firmware_by return NRF_ERROR_INVALID_STATE; } - ble_gatts_hvx_params_t hvx_params; - uint16_t index = 0; + uint32_t err_code; + do { - m_notif_buffer[index++] = OP_CODE_PKT_RCPT_NOTIF; + ble_gatts_hvx_params_t hvx_params; + uint16_t index = 0; + + m_notif_buffer[index++] = OP_CODE_PKT_RCPT_NOTIF; + + index += uint32_encode(num_of_firmware_bytes_rcvd, &m_notif_buffer[index]); + + memset(&hvx_params, 0, sizeof(hvx_params)); + + hvx_params.handle = p_dfu->dfu_ctrl_pt_handles.value_handle; + hvx_params.type = BLE_GATT_HVX_NOTIFICATION; + hvx_params.offset = 0; + hvx_params.p_len = &index; + hvx_params.p_data = m_notif_buffer; - index += uint32_encode(num_of_firmware_bytes_rcvd, &m_notif_buffer[index]); + err_code = sd_ble_gatts_hvx(p_dfu->conn_handle, &hvx_params); + } while (err_code == NRF_ERROR_RESOURCES); - memset(&hvx_params, 0, sizeof(hvx_params)); - - hvx_params.handle = p_dfu->dfu_ctrl_pt_handles.value_handle; - hvx_params.type = BLE_GATT_HVX_NOTIFICATION; - hvx_params.offset = 0; - hvx_params.p_len = &index; - hvx_params.p_data = m_notif_buffer; - - return sd_ble_gatts_hvx(p_dfu->conn_handle, &hvx_params); + return err_code; } @@ -632,24 +644,30 @@ uint32_t ble_dfu_response_send(ble_dfu_t * p_dfu, return NRF_ERROR_INVALID_STATE; } - ble_gatts_hvx_params_t hvx_params; - uint16_t index = 0; + uint32_t err_code; + do { - m_notif_buffer[index++] = OP_CODE_RESPONSE; + ble_gatts_hvx_params_t hvx_params; + uint16_t index = 0; + + m_notif_buffer[index++] = OP_CODE_RESPONSE; + + // Encode the Request Op code + m_notif_buffer[index++] = (uint8_t)dfu_proc; + + // Encode the Response Value. + m_notif_buffer[index++] = (uint8_t)resp_val; + + memset(&hvx_params, 0, sizeof(hvx_params)); + + hvx_params.handle = p_dfu->dfu_ctrl_pt_handles.value_handle; + hvx_params.type = BLE_GATT_HVX_NOTIFICATION; + hvx_params.offset = 0; + hvx_params.p_len = &index; + hvx_params.p_data = m_notif_buffer; + + err_code = sd_ble_gatts_hvx(p_dfu->conn_handle, &hvx_params); + } while (err_code == NRF_ERROR_RESOURCES); - // Encode the Request Op code - m_notif_buffer[index++] = (uint8_t)dfu_proc; - - // Encode the Response Value. - m_notif_buffer[index++] = (uint8_t)resp_val; - - memset(&hvx_params, 0, sizeof(hvx_params)); - - hvx_params.handle = p_dfu->dfu_ctrl_pt_handles.value_handle; - hvx_params.type = BLE_GATT_HVX_NOTIFICATION; - hvx_params.offset = 0; - hvx_params.p_len = &index; - hvx_params.p_data = m_notif_buffer; - - return sd_ble_gatts_hvx(p_dfu->conn_handle, &hvx_params); + return err_code; } From b5ddc1879e062621d927c263e13bd593ba51d801 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Jos=C3=A9=20Tagle?= Date: Thu, 15 Jan 2026 00:41:16 -0300 Subject: [PATCH 72/90] Fix improper processing of Flash WRITE/ERASE completion notifications that was causing the DFU firmware update to sometimes crash --- .../components/drivers_nrf/pstorage/pstorage_raw.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/sdk11/components/drivers_nrf/pstorage/pstorage_raw.c b/lib/sdk11/components/drivers_nrf/pstorage/pstorage_raw.c index f9404fe..a6ac067 100644 --- a/lib/sdk11/components/drivers_nrf/pstorage/pstorage_raw.c +++ b/lib/sdk11/components/drivers_nrf/pstorage/pstorage_raw.c @@ -280,6 +280,10 @@ static void app_notify(uint32_t result, cmd_queue_element_t * p_elem) */ void pstorage_sys_event_handler(uint32_t sys_evt) { + // Do not bother processing events we are not interested in + if (sys_evt != NRF_EVT_FLASH_OPERATION_SUCCESS && + sys_evt != NRF_EVT_FLASH_OPERATION_ERROR) return; + uint32_t retval = NRF_SUCCESS; // The event shall only be processed if requested by this module. @@ -339,6 +343,7 @@ void pstorage_sys_event_handler(uint32_t sys_evt) * @brief Function for processing of commands and issuing flash access request to the SoftDevice. * * @return The return value received from SoftDevice. + * @remark This function is only called when m_cmd_queue.flash_access == false */ static uint32_t cmd_process(void) { @@ -352,6 +357,9 @@ static uint32_t cmd_process(void) storage_addr = p_cmd->storage_addr.block_id; + // Let's assume we will do a flash access + m_cmd_queue.flash_access = true; + switch (p_cmd->op_code) { case PSTORAGE_STORE_OP_CODE: @@ -396,9 +404,10 @@ static uint32_t cmd_process(void) break; } - if (retval == NRF_SUCCESS) + // An error means we will not do it + if (retval != NRF_SUCCESS) { - m_cmd_queue.flash_access = true; + m_cmd_queue.flash_access = false; } return retval; From 04d029a5bd9ccc367faee2c8a4d0bac5b886e7ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Jos=C3=A9=20Tagle?= Date: Thu, 15 Jan 2026 00:43:27 -0300 Subject: [PATCH 73/90] Allow overriding device name in DFU mode --- .../components/libraries/bootloader_dfu/dfu_transport_ble.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c b/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c index 2715dce..35d9ba4 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c @@ -47,7 +47,9 @@ enum { BLE_CONN_CFG_HIGH_BANDWIDTH = 1 }; #define BLE_HANDLE_MAX 0xFFFF /**< Max handle value is BLE. */ // limit of 8 chars +#ifndef DEVICE_NAME #define DEVICE_NAME "AdaDFU" /**< Name of device. Will be included in the advertising data. */ +#endif #define MIN_CONN_INTERVAL (uint16_t)(MSEC_TO_UNITS(10, UNIT_1_25_MS)) /**< Minimum acceptable connection interval (11.25 milliseconds). */ #define MAX_CONN_INTERVAL (uint16_t)(MSEC_TO_UNITS(30, UNIT_1_25_MS)) /**< Maximum acceptable connection interval (15 milliseconds). */ From 36422ba612fca418bad9044eab63047d8fe345ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Jos=C3=A9=20Tagle?= Date: Thu, 15 Jan 2026 00:46:27 -0300 Subject: [PATCH 74/90] Speedup FLASH writes by temporarily increasing BLE stack local latency --- .../bootloader_dfu/dfu_transport_ble.c | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c b/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c index 35d9ba4..63767e4 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c @@ -55,6 +55,7 @@ enum { BLE_CONN_CFG_HIGH_BANDWIDTH = 1 }; #define MAX_CONN_INTERVAL (uint16_t)(MSEC_TO_UNITS(30, UNIT_1_25_MS)) /**< Maximum acceptable connection interval (15 milliseconds). */ #define SLAVE_LATENCY 0 /**< Slave latency. */ #define CONN_SUP_TIMEOUT (4 * 100) /**< Connection supervisory timeout (4 seconds). */ +#define SPEEDUP_FLASH_WRITES 1 /**< Speedup FLASH writes by changing Softdevice local latency */ #define APP_ADV_INTERVAL MSEC_TO_UNITS(25, UNIT_0_625_MS) /**< The advertising interval (25 ms.). */ #define APP_ADV_TIMEOUT BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED /**< The advertising timeout in units of seconds. This is set to @ref BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED so that the advertisement is done as long as there there is a call to @ref dfu_transport_close function.*/ @@ -210,6 +211,34 @@ static ble_dfu_resp_val_t nrf_err_code_translate(uint32_t err_c } } +static void prioritize_ble_over_flash_writes(void) +{ +#ifdef SPEEDUP_FLASH_WRITES + // We set the local latency to 0: That will revert latency to the negotiated one with the host. + // That will increase throughput to the maximum possible + ble_opt_t opt; + varclr(&opt); + opt.gap_opt.local_conn_latency.conn_handle = m_conn_handle;/**< Connection Handle */ + opt.gap_opt.local_conn_latency.requested_latency = 0; /**< Requested local connection latency. */ + opt.gap_opt.local_conn_latency.p_actual_latency = NULL; /**< Pointer to storage for the actual local connection latency (can be set to NULL to skip return value). */ + sd_ble_opt_set(BLE_GAP_OPT_LOCAL_CONN_LATENCY, &opt); +#endif +} + +static void prioritize_flash_writes_over_ble(void) +{ +#ifdef SPEEDUP_FLASH_WRITES + // We set the local latency to the maximum possible: That will make FLASH writes faster, as BLE comms will + // be delayed (even losing RXd packets, but this is the same as a poor connection and will be handled by + // the protocol itself) + ble_opt_t opt; + varclr(&opt); + opt.gap_opt.local_conn_latency.conn_handle = m_conn_handle;/**< Connection Handle */ + opt.gap_opt.local_conn_latency.requested_latency = 50; /**< Requested local connection latency. */ + opt.gap_opt.local_conn_latency.p_actual_latency = NULL; /**< Pointer to storage for the actual local connection latency (can be set to NULL to skip return value). */ + sd_ble_opt_set(BLE_GAP_OPT_LOCAL_CONN_LATENCY, &opt); +#endif +} /**@brief Function for handling the callback events from the dfu module. * Callbacks are expected when \ref dfu_data_pkt_handle has been executed. @@ -228,6 +257,9 @@ static void dfu_cb_handler(uint32_t packet, uint32_t result, uint8_t * p_data) case DATA_PACKET: if (result != NRF_SUCCESS) { + // Restore latency to the negotiated one + prioritize_ble_over_flash_writes(); + // Disconnect from peer. if (IS_CONNECTED()) { @@ -244,6 +276,9 @@ static void dfu_cb_handler(uint32_t packet, uint32_t result, uint8_t * p_data) // If the callback matches final data packet received then the peer is notified. if (mp_final_packet == p_data) { + // Restore latency to the negotiated one + prioritize_ble_over_flash_writes(); + // Notify the DFU Controller about the success of the procedure. err_code = ble_dfu_response_send(&m_dfu, BLE_DFU_RECEIVE_APP_PROCEDURE, @@ -254,6 +289,10 @@ static void dfu_cb_handler(uint32_t packet, uint32_t result, uint8_t * p_data) break; case START_PACKET: + + // Restore latency to the negotiated one + prioritize_ble_over_flash_writes(); + // Translate the err_code returned by the above function to DFU Response Value. resp_val = nrf_err_code_translate(result, BLE_DFU_START_PROCEDURE); @@ -326,9 +365,15 @@ static void start_data_process(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt) start_packet.bl_image_size = uint32_decode(p_length_data + BL_IMAGE_SIZE_OFFSET); start_packet.app_image_size = uint32_decode(p_length_data + APP_IMAGE_SIZE_OFFSET); + // Prioritize FLASH writes over BLE comms + prioritize_flash_writes_over_ble(); + err_code = dfu_start_pkt_handle(&update_packet); if (err_code != NRF_SUCCESS) { + // Prioritize BLE over flash writes + prioritize_ble_over_flash_writes(); + // Translate the err_code returned by the above function to DFU Response Value. ble_dfu_resp_val_t resp_val; From d28c2e08717b4f48423185bc15760d79b4a201ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Jos=C3=A9=20Tagle?= Date: Thu, 15 Jan 2026 01:03:53 -0300 Subject: [PATCH 75/90] Enable negotiation of MTU sizes above 20. This will significatively increase DFU write speed --- .../ble/ble_services/ble_dfu/ble_dfu.c | 16 ++++----- .../bootloader_dfu/dfu_transport_ble.c | 35 +++++++++++++++---- src/main.c | 32 ++++++++++++++--- src/sdk_config.h | 2 +- 4 files changed, 65 insertions(+), 20 deletions(-) diff --git a/lib/sdk11/components/ble/ble_services/ble_dfu/ble_dfu.c b/lib/sdk11/components/ble/ble_services/ble_dfu/ble_dfu.c index 685fdea..a630971 100644 --- a/lib/sdk11/components/ble/ble_services/ble_dfu/ble_dfu.c +++ b/lib/sdk11/components/ble/ble_services/ble_dfu/ble_dfu.c @@ -17,14 +17,14 @@ #include #include "sdk_common.h" -#define DFU_PKT_ENABLE_WR_WO_RESPONSE_ONLY 0 /**< Enable Write Without Response on Data Endpoint ONLY (otherwise both With and Without response will be supported)*/ -#define MAX_DFU_PKT_LEN 20 /**< Maximum length (in bytes) of the DFU Packet characteristic. */ -#define PKT_START_DFU_PARAM_LEN 2 /**< Length (in bytes) of the parameters for Packet Start DFU Request. */ -#define PKT_INIT_DFU_PARAM_LEN 2 /**< Length (in bytes) of the parameters for Packet Init DFU Request. */ -#define PKT_RCPT_NOTIF_REQ_LEN 3 /**< Length (in bytes) of the Packet Receipt Notification Request. */ -#define MAX_PKTS_RCPT_NOTIF_LEN 6 /**< Maximum length (in bytes) of the Packets Receipt Notification. */ -#define MAX_RESPONSE_LEN 7 /**< Maximum length (in bytes) of the response to a Control Point command. */ -#define MAX_NOTIF_BUFFER_LEN MAX(MAX_PKTS_RCPT_NOTIF_LEN, MAX_RESPONSE_LEN) /**< Maximum length (in bytes) of the buffer needed by DFU Service while sending notifications to peer. */ +#define DFU_PKT_ENABLE_WR_WO_RESPONSE_ONLY 0 /**< Enable Write Without Response on Data Endpoint ONLY (otherwise both With and Without response will be supported)*/ +#define MAX_DFU_PKT_LEN 244 /**< Maximum length (in bytes) of the DFU Packet characteristic. */ +#define PKT_START_DFU_PARAM_LEN 2 /**< Length (in bytes) of the parameters for Packet Start DFU Request. */ +#define PKT_INIT_DFU_PARAM_LEN 2 /**< Length (in bytes) of the parameters for Packet Init DFU Request. */ +#define PKT_RCPT_NOTIF_REQ_LEN 3 /**< Length (in bytes) of the Packet Receipt Notification Request. */ +#define MAX_PKTS_RCPT_NOTIF_LEN 6 /**< Maximum length (in bytes) of the Packets Receipt Notification. */ +#define MAX_RESPONSE_LEN 7 /**< Maximum length (in bytes) of the response to a Control Point command. */ +#define MAX_NOTIF_BUFFER_LEN MAX(MAX_PKTS_RCPT_NOTIF_LEN, MAX_RESPONSE_LEN) /**< Maximum length (in bytes) of the buffer needed by DFU Service while sending notifications to peer. */ enum { diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c b/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c index 63767e4..06017a9 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c @@ -36,8 +36,7 @@ #include "sdk_common.h" -#define BLEGAP_EVENT_LENGTH 6 -#define BLEGATT_ATT_MTU_MAX 23 +#define BLEGATT_ATT_MTU_MAX 247 enum { BLE_CONN_CFG_HIGH_BANDWIDTH = 1 }; #define DFU_REV_MAJOR 0x00 /** DFU Major revision number to be exposed. */ @@ -51,15 +50,15 @@ enum { BLE_CONN_CFG_HIGH_BANDWIDTH = 1 }; #define DEVICE_NAME "AdaDFU" /**< Name of device. Will be included in the advertising data. */ #endif -#define MIN_CONN_INTERVAL (uint16_t)(MSEC_TO_UNITS(10, UNIT_1_25_MS)) /**< Minimum acceptable connection interval (11.25 milliseconds). */ +#define MIN_CONN_INTERVAL (uint16_t)(MSEC_TO_UNITS(15, UNIT_1_25_MS)) /**< Minimum acceptable connection interval (11.25 milliseconds). */ #define MAX_CONN_INTERVAL (uint16_t)(MSEC_TO_UNITS(30, UNIT_1_25_MS)) /**< Maximum acceptable connection interval (15 milliseconds). */ #define SLAVE_LATENCY 0 /**< Slave latency. */ -#define CONN_SUP_TIMEOUT (4 * 100) /**< Connection supervisory timeout (4 seconds). */ +#define CONN_SUP_TIMEOUT MSEC_TO_UNITS(8000, UNIT_10_MS) /**< Connection supervisory timeout (4 seconds). */ #define SPEEDUP_FLASH_WRITES 1 /**< Speedup FLASH writes by changing Softdevice local latency */ #define APP_ADV_INTERVAL MSEC_TO_UNITS(25, UNIT_0_625_MS) /**< The advertising interval (25 ms.). */ #define APP_ADV_TIMEOUT BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED /**< The advertising timeout in units of seconds. This is set to @ref BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED so that the advertisement is done as long as there there is a call to @ref dfu_transport_close function.*/ -#define APP_DIRECTED_ADV_TIMEOUT 50 /**< number of direct advertisement (each lasting 1.28seconds). */ +#define APP_DIRECTED_ADV_TIMEOUT 50 /**< number of direct advertisement (each lasting 1.28seconds). */ #define PEER_ADDRESS_TYPE_INVALID 0xFF /**< Value indicating that no valid peer address exists. This will be the case when a private resolvable address is used in which case there is no address available but instead an IRK is present. */ #define PEER_ADDRESS_TYPE_INVALID 0xFF /**< Value indicating that no valid peer address exists. This will be the case when a private resolvable address is used in which case there is no address available but instead an IRK is present. */ @@ -790,8 +789,22 @@ static void on_ble_evt(ble_evt_t * p_ble_evt) switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: - m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; - m_is_advertising = false; + { + m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; + m_is_advertising = false; + + // Force changing the slave latency to try to improve transfer throughput (bandwidth) + // But Android and IOS will override it with their minimum supported value + ble_gap_conn_params_t p_conn_params; + p_conn_params.min_conn_interval = p_ble_evt->evt.gap_evt.params.connected.conn_params.min_conn_interval; + p_conn_params.max_conn_interval = p_ble_evt->evt.gap_evt.params.connected.conn_params.max_conn_interval; + p_conn_params.slave_latency = SLAVE_LATENCY; + p_conn_params.conn_sup_timeout = p_ble_evt->evt.gap_evt.params.connected.conn_params.conn_sup_timeout; + + err_code = sd_ble_gap_conn_param_update(m_conn_handle, &p_conn_params); + APP_ERROR_CHECK(err_code); + + } break; case BLE_GAP_EVT_DISCONNECTED: @@ -821,6 +834,9 @@ static void on_ble_evt(ble_evt_t * p_ble_evt) break; + case BLE_GAP_EVT_CONN_PARAM_UPDATE: + break; + case BLE_GAP_EVT_SEC_PARAMS_REQUEST: { ble_gap_sec_keyset_t keys; @@ -947,6 +963,11 @@ static void on_ble_evt(ble_evt_t * p_ble_evt) case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: { uint16_t att_mtu = MIN(p_ble_evt->evt.gatts_evt.params.exchange_mtu_request.client_rx_mtu, BLEGATT_ATT_MTU_MAX); + + // Round it to a multiple of 4 plus 3 bytes, as we need data packets to be multiple of 4 bytes + att_mtu &= 0xFFFCU; + att_mtu |= 3; + PRINTF("GAP ATT MTU is changed to %d\r\n", att_mtu); APP_ERROR_CHECK( sd_ble_gatts_exchange_mtu_reply(m_conn_handle, att_mtu) ); } diff --git a/src/main.c b/src/main.c index 9ebc9e9..0011640 100644 --- a/src/main.c +++ b/src/main.c @@ -115,8 +115,11 @@ extern void tusb_hal_nrf_power_event(uint32_t event); #define APP_ASKS_FOR_SINGLE_TAP_RESET() (*((uint32_t*)(DFU_BANK_0_REGION_START + 0x200)) == 0x87eeb07c) // These value must be the same with one in dfu_transport_ble.c -#define BLEGAP_EVENT_LENGTH 6 -#define BLEGATT_ATT_MTU_MAX 23 +#define BLEGAP_EVENT_LENGTH 12 +#define BLEGATT_ATT_MTU_MAX 247 +#define BLEGATTS_HVN_QSIZE 12 +#define BLEGATTC_WRCMD_QSIZE 2 + enum { BLE_CONN_CFG_HIGH_BANDWIDTH = 1 }; @@ -371,11 +374,23 @@ static uint32_t ble_stack_init(void) { blecfg.conn_cfg.params.gap_conn_cfg.event_length = BLEGAP_EVENT_LENGTH; sd_ble_cfg_set(BLE_CONN_CFG_GAP, &blecfg, ram_start); + // HVN queue size + varclr(&blecfg); + blecfg.conn_cfg.conn_cfg_tag = BLE_CONN_CFG_HIGH_BANDWIDTH; + blecfg.conn_cfg.params.gatts_conn_cfg.hvn_tx_queue_size = BLEGATTS_HVN_QSIZE; + sd_ble_cfg_set(BLE_CONN_CFG_GATTS, &blecfg, ram_start); + + // WRITE COMMAND queue size + varclr(&blecfg); + blecfg.conn_cfg.conn_cfg_tag = BLE_CONN_CFG_HIGH_BANDWIDTH; + blecfg.conn_cfg.params.gattc_conn_cfg.write_cmd_tx_queue_size = BLEGATTC_WRCMD_QSIZE; + sd_ble_cfg_set(BLE_CONN_CFG_GATTC, &blecfg, ram_start); + // Enable BLE stack. // Note: Interrupt state (enabled, forwarding) is not work properly if not enable ble sd_ble_enable(&ram_start); -#if 0 +#if BLEGATT_ATT_MTU_MAX > 23 ble_opt_t opt; varclr(&opt); opt.common_opt.conn_evt_ext.enable = 1; // enable Data Length Extension @@ -401,10 +416,19 @@ uint32_t proc_ble(void) { if (NRF_SUCCESS == err) { switch (evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: + { + // Try to enable 2M phy,if phone allows it + ble_gap_phys_t const phys = + { + .rx_phys = BLE_GAP_PHY_AUTO, + .tx_phys = BLE_GAP_PHY_AUTO, + }; + sd_ble_gap_phy_update(evt->evt.gap_evt.conn_handle, &phys); + _ota_connected = true; led_state(STATE_BLE_CONNECTED); break; - + } case BLE_GAP_EVT_DISCONNECTED: _ota_connected = false; led_state(STATE_BLE_DISCONNECTED); diff --git a/src/sdk_config.h b/src/sdk_config.h index 50e8196..bef8bc7 100644 --- a/src/sdk_config.h +++ b/src/sdk_config.h @@ -66,7 +66,7 @@ #define HCI_MEM_POOL_ENABLED 1 #define HCI_TX_BUF_SIZE 600 // not used #define HCI_RX_BUF_SIZE 600 -#define HCI_RX_BUF_QUEUE_SIZE 8 // must be power of 2 +#define HCI_RX_BUF_QUEUE_SIZE 16 // must be power of 2 //========================================================== // UART_ENABLED - nrf_drv_uart - UART/UARTE peripheral driver From ca46deb0a24a1888809e9067d7a684dbb2d13397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Jos=C3=A9=20Tagle?= Date: Thu, 15 Jan 2026 01:14:50 -0300 Subject: [PATCH 76/90] Factor out FLASH erase procedure (non OTA), fix FLASH write procedure (non OTA), use them instead of repeating code --- .../bootloader_dfu/dfu_single_bank.c | 131 +++++++++--------- src/flash_nrf5x.c | 96 +++++++++---- src/flash_nrf5x.h | 3 +- 3 files changed, 132 insertions(+), 98 deletions(-) diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c b/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c index fa69ec8..ee2d342 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c @@ -88,31 +88,24 @@ static void pstorage_callback_handler(pstorage_handle_t * p_handle, */ static void dfu_prepare_func_app_erase(uint32_t image_size) { - mp_storage_handle_active = &m_storage_handle_app; + mp_storage_handle_active = &m_storage_handle_app; - // Doing a SoftDevice update thus current application must be cleared to ensure enough space - // for new SoftDevice. - m_dfu_state = DFU_STATE_PREPARING; + // Doing a SoftDevice update thus current application must be cleared to ensure enough space + // for new SoftDevice. + m_dfu_state = DFU_STATE_PREPARING; - if ( is_ota() ) - { - uint32_t err_code = pstorage_clear(&m_storage_handle_app, m_image_size); - APP_ERROR_CHECK(err_code); - } - else - { - uint32_t const page_count = NRFX_CEIL_DIV(m_image_size, CODE_PAGE_SIZE); - - for ( uint32_t i = 0; i < page_count; i++ ) + if ( is_ota() ) { - uint32_t const addr = DFU_BANK_0_REGION_START + i * CODE_PAGE_SIZE; - PRINTF("Erase 0x%08lX\r\n", addr); - nrfx_nvmc_page_erase(addr); + uint32_t err_code = pstorage_clear(&m_storage_handle_app, m_image_size); + APP_ERROR_CHECK(err_code); } + else + { + flash_nrf5x_erase(DFU_BANK_0_REGION_START, m_image_size); - // invoke complete callback - pstorage_callback_handler(&m_storage_handle_app, PSTORAGE_CLEAR_OP_CODE, NRF_SUCCESS, NULL, 0); - } + // invoke complete callback + pstorage_callback_handler(&m_storage_handle_app, PSTORAGE_CLEAR_OP_CODE, NRF_SUCCESS, NULL, 0); + } } @@ -136,14 +129,14 @@ static void dfu_cleared_func_app(void) uint32_t offset_calculate(uint32_t sd_image_size) { uint32_t offset = 0; - + if (m_start_packet.sd_image_size > DFU_BANK_0_REGION_START) { uint32_t page_mask = (CODE_PAGE_SIZE - 1); uint32_t diff = m_start_packet.sd_image_size - DFU_BANK_0_REGION_START; - + offset = diff & ~page_mask; - + // Align offset to next page if image size is not page sized. if ((diff & page_mask) > 0) { @@ -189,8 +182,7 @@ static uint32_t dfu_activate_sd(void) */ static uint32_t dfu_activate_app(void) { - uint32_t err_code = NRF_SUCCESS; - dfu_update_status_t update_status; + dfu_update_status_t update_status = { 0 }; memset(&update_status, 0, sizeof(dfu_update_status_t )); update_status.status_code = DFU_UPDATE_APP_COMPLETE; @@ -199,7 +191,7 @@ static uint32_t dfu_activate_app(void) bootloader_dfu_update_process(update_status); - return err_code; + return NRF_SUCCESS; } @@ -213,7 +205,7 @@ static uint32_t dfu_activate_app(void) */ static uint32_t dfu_activate_bl(void) { - dfu_update_status_t update_status; + dfu_update_status_t update_status = {0}; update_status.status_code = DFU_UPDATE_BOOT_COMPLETE; update_status.app_crc = m_image_crc; @@ -267,7 +259,7 @@ uint32_t dfu_start_pkt_handle(dfu_update_packet_t * p_packet) // - SoftDevice // - Bootloader // - SoftDevice with Bootloader - if (IS_UPDATING_APP(m_start_packet) && + if (IS_UPDATING_APP(m_start_packet) && (IS_UPDATING_SD(m_start_packet) || IS_UPDATING_BL(m_start_packet))) { // App update is only supported independently. @@ -284,7 +276,7 @@ uint32_t dfu_start_pkt_handle(dfu_update_packet_t * p_packet) m_image_size = m_start_packet.sd_image_size + m_start_packet.bl_image_size + m_start_packet.app_image_size; - + if (m_start_packet.bl_image_size > DFU_BL_IMAGE_MAX_SIZE) { return NRF_ERROR_DATA_SIZE; @@ -296,7 +288,7 @@ uint32_t dfu_start_pkt_handle(dfu_update_packet_t * p_packet) } m_functions.prepare = dfu_prepare_func_app_erase; m_functions.cleared = dfu_cleared_func_app; - + if (IS_UPDATING_SD(m_start_packet)) { m_functions.activate = dfu_activate_sd; @@ -358,13 +350,13 @@ uint32_t dfu_data_pkt_handle(dfu_update_packet_t * p_packet) if ( is_ota() ) { - err_code = pstorage_store(mp_storage_handle_active, (uint8_t *)p_data, data_length, m_data_received); - VERIFY_SUCCESS(err_code); + err_code = pstorage_store(mp_storage_handle_active, (uint8_t *)p_data, data_length, m_data_received); + VERIFY_SUCCESS(err_code); } else { - flash_nrf5x_write(DFU_BANK_0_REGION_START + m_data_received, p_data, data_length, false); - pstorage_callback_handler(mp_storage_handle_active, PSTORAGE_STORE_OP_CODE, NRF_SUCCESS, (uint8_t *) p_data, data_length); + flash_nrf5x_write(DFU_BANK_0_REGION_START + m_data_received, p_data, data_length, false); + pstorage_callback_handler(mp_storage_handle_active, PSTORAGE_STORE_OP_CODE, NRF_SUCCESS, (uint8_t *) p_data, data_length); } m_data_received += data_length; @@ -376,10 +368,10 @@ uint32_t dfu_data_pkt_handle(dfu_update_packet_t * p_packet) } else { - if ( !is_ota() ) flash_nrf5x_flush(false); + if ( !is_ota() ) flash_nrf5x_flush(false); - // The entire image has been received. Return NRF_SUCCESS. - err_code = NRF_SUCCESS; + // The entire image has been received. Return NRF_SUCCESS. + err_code = NRF_SUCCESS; } break; @@ -395,14 +387,14 @@ uint32_t dfu_data_pkt_handle(dfu_update_packet_t * p_packet) uint32_t dfu_init_pkt_complete(void) { uint32_t err_code = NRF_ERROR_INVALID_STATE; - + // DFU initialization has been done and a start packet has been received. if (IMAGE_WRITE_IN_PROGRESS()) { // Image write is already in progress. Cannot handle an init packet now. return NRF_ERROR_INVALID_STATE; } - + if (m_dfu_state == DFU_STATE_RX_INIT_PKT) { err_code = dfu_init_prevalidate(m_init_packet, m_init_packet_length, m_start_packet.dfu_update_mode); @@ -513,7 +505,7 @@ uint32_t dfu_image_activate() void dfu_reset(void) { - dfu_update_status_t update_status; + dfu_update_status_t update_status = { 0 }; update_status.status_code = DFU_RESET; @@ -547,13 +539,13 @@ static uint32_t dfu_copy_sd(uint32_t * src, uint32_t * dst, uint32_t len) } -static uint32_t dfu_sd_img_block_swap(uint32_t * src, - uint32_t * dst, - uint32_t len, +static uint32_t dfu_sd_img_block_swap(uint32_t * src, + uint32_t * dst, + uint32_t len, uint32_t block_size) { // It is neccesarry to swap the new SoftDevice in 3 rounds to ensure correct copy of data - // and verifucation of data in case power reset occurs during write to flash. + // and verification of data in case power reset occurs during write to flash. // To ensure the robustness of swapping the images are compared backwards till start of // image swap. If the back is identical everything is swapped. uint32_t err_code = dfu_compare_block(src, dst, len); @@ -564,9 +556,9 @@ static uint32_t dfu_sd_img_block_swap(uint32_t * src, if ((uint32_t)dst > SOFTDEVICE_REGION_START) { - err_code = dfu_sd_img_block_swap((uint32_t *)((uint32_t)src - block_size), - (uint32_t *)((uint32_t)dst - block_size), - block_size, + err_code = dfu_sd_img_block_swap((uint32_t *)((uint32_t)src - block_size), + (uint32_t *)((uint32_t)dst - block_size), + block_size, block_size); VERIFY_SUCCESS(err_code); } @@ -588,37 +580,37 @@ uint32_t dfu_sd_image_swap(void) { return NRF_SUCCESS; } - + if ((SOFTDEVICE_REGION_START + boot_settings.sd_image_size) > boot_settings.sd_image_start) { uint32_t err_code; uint32_t sd_start = SOFTDEVICE_REGION_START; uint32_t block_size = (boot_settings.sd_image_start - sd_start) / 2; - + /* ##### FIX START ##### */ - block_size &= ~(uint32_t)(CODE_PAGE_SIZE - 1); - /* ##### FIX END ##### */ - + block_size &= ~(uint32_t)(CODE_PAGE_SIZE - 1); + /* ##### FIX END ##### */ + uint32_t image_end = boot_settings.sd_image_start + boot_settings.sd_image_size; uint32_t img_block_start = boot_settings.sd_image_start + 2 * block_size; uint32_t sd_block_start = sd_start + 2 * block_size; - + if (SD_SIZE_GET(MBR_SIZE) < boot_settings.sd_image_size) { // This will clear a page thus ensuring the old image is invalidated before swapping. - err_code = dfu_copy_sd((uint32_t *)(sd_start + block_size), - (uint32_t *)(sd_start + block_size), + err_code = dfu_copy_sd((uint32_t *)(sd_start + block_size), + (uint32_t *)(sd_start + block_size), sizeof(uint32_t)); VERIFY_SUCCESS(err_code); err_code = dfu_copy_sd((uint32_t *)sd_start, (uint32_t *)sd_start, sizeof(uint32_t)); VERIFY_SUCCESS(err_code); } - - return dfu_sd_img_block_swap((uint32_t *)img_block_start, - (uint32_t *)sd_block_start, - image_end - img_block_start, + + return dfu_sd_img_block_swap((uint32_t *)img_block_start, + (uint32_t *)sd_block_start, + image_end - img_block_start, block_size); } else @@ -626,7 +618,7 @@ uint32_t dfu_sd_image_swap(void) if (boot_settings.sd_image_size != 0) { return dfu_copy_sd((uint32_t *)boot_settings.sd_image_start, - (uint32_t *)SOFTDEVICE_REGION_START, + (uint32_t *)SOFTDEVICE_REGION_START, boot_settings.sd_image_size); } } @@ -646,7 +638,7 @@ uint32_t dfu_bl_image_swap(void) { uint32_t bl_image_start = (bootloader_settings.sd_image_size == 0) ? DFU_BANK_0_REGION_START : - bootloader_settings.sd_image_start + + bootloader_settings.sd_image_start + bootloader_settings.sd_image_size; sd_mbr_cmd.command = SD_MBR_COMMAND_COPY_BL; @@ -695,17 +687,18 @@ uint32_t dfu_sd_image_validate(void) { return NRF_SUCCESS; } - + if ((SOFTDEVICE_REGION_START + bootloader_settings.sd_image_size) > bootloader_settings.sd_image_start) { uint32_t sd_start = SOFTDEVICE_REGION_START; uint32_t block_size = (bootloader_settings.sd_image_start - sd_start) / 2; - uint32_t image_end = bootloader_settings.sd_image_start + + uint32_t image_end = bootloader_settings.sd_image_start + bootloader_settings.sd_image_size; /* ##### FIX START ##### */ - block_size &= ~(uint32_t)(CODE_PAGE_SIZE - 1); - /* ##### FIX END ##### */ + block_size &= ~(uint32_t)(CODE_PAGE_SIZE - 1); + /* ##### FIX END ##### */ + uint32_t img_block_start = bootloader_settings.sd_image_start + 2 * block_size; uint32_t sd_block_start = sd_start + 2 * block_size; @@ -714,12 +707,12 @@ uint32_t dfu_sd_image_validate(void) return NRF_ERROR_NULL; } - return dfu_sd_img_block_swap((uint32_t *)img_block_start, - (uint32_t *)sd_block_start, - image_end - img_block_start, + return dfu_sd_img_block_swap((uint32_t *)img_block_start, + (uint32_t *)sd_block_start, + image_end - img_block_start, block_size); } - + sd_mbr_cmd.command = SD_MBR_COMMAND_COMPARE; sd_mbr_cmd.params.compare.ptr1 = (uint32_t *)SOFTDEVICE_REGION_START; sd_mbr_cmd.params.compare.ptr2 = (uint32_t *)bootloader_settings.sd_image_start; diff --git a/src/flash_nrf5x.c b/src/flash_nrf5x.c index 12c6797..ddea500 100644 --- a/src/flash_nrf5x.c +++ b/src/flash_nrf5x.c @@ -26,48 +26,88 @@ #include "nrf_sdm.h" #include "flash_nrf5x.h" #include "boards.h" +#include "dfu_types.h" -#define FLASH_PAGE_SIZE 4096 #define FLASH_CACHE_INVALID_ADDR 0xffffffff static uint32_t _fl_addr = FLASH_CACHE_INVALID_ADDR; -static uint8_t _fl_buf[FLASH_PAGE_SIZE] __attribute__((aligned(4))); +static uint8_t _fl_buf[CODE_PAGE_SIZE] __attribute__((aligned(4))); + +void flash_nrf5x_erase (uint32_t dst, uint32_t len) +{ + uint32_t page_addr = dst & ~(CODE_PAGE_SIZE - 1); + uint32_t const page_count = NRFX_CEIL_DIV(len, CODE_PAGE_SIZE); + for ( uint32_t i = 0; i < page_count; i++ ) + { + uint32_t const addr = page_addr + i * CODE_PAGE_SIZE; + PRINTF("Erase 0x%08lX\r\n", addr); + nrfx_nvmc_page_erase(addr); + } +} + void flash_nrf5x_flush (bool need_erase) { - if ( _fl_addr == FLASH_CACHE_INVALID_ADDR ) return; + if ( _fl_addr == FLASH_CACHE_INVALID_ADDR ) + return; - // skip the write if contents matches - if ( memcmp(_fl_buf, (void *) _fl_addr, FLASH_PAGE_SIZE) != 0 ) - { - // - nRF52832 dfu via uart can miss incoming byte when erasing because cpu is blocked for > 2ms. - // Since dfu_prepare_func_app_erase() already erase the page for us, we can skip it here. - // - nRF52840 dfu serial/uf2 are USB-based which are DMA and should have no problems. - // - // Note: MSC uf2 does not erase page in advance like dfu serial - if ( need_erase ) + // skip the write if contents matches + if ( memcmp(_fl_buf, (void *) _fl_addr, CODE_PAGE_SIZE) != 0 ) { - PRINTF("Erase and "); - nrfx_nvmc_page_erase(_fl_addr); + // - nRF52832 dfu via uart can miss incoming byte when erasing because cpu is blocked for > 2ms. + // Since dfu_prepare_func_app_erase() already erase the page for us, we can skip it here. + // - nRF52840 dfu serial/uf2 are USB-based which are DMA and should have no problems. + // + // Note: MSC uf2 does not erase page in advance like dfu serial + if ( need_erase ) + { + PRINTF("Erase and "); + nrfx_nvmc_page_erase(_fl_addr); + } + + PRINTF("Write 0x%08lX\r\n", _fl_addr); + nrfx_nvmc_words_write(_fl_addr, (uint32_t *) _fl_buf, CODE_PAGE_SIZE / 4); } - PRINTF("Write 0x%08lX\r\n", _fl_addr); - nrfx_nvmc_words_write(_fl_addr, (uint32_t *) _fl_buf, FLASH_PAGE_SIZE / 4); - } - - _fl_addr = FLASH_CACHE_INVALID_ADDR; + _fl_addr = FLASH_CACHE_INVALID_ADDR; } -void flash_nrf5x_write (uint32_t dst, void const *src, int len, bool need_erase) +void flash_nrf5x_write (uint32_t dst, void const *src, uint32_t len, bool need_erase) { - uint32_t newAddr = dst & ~(FLASH_PAGE_SIZE - 1); + // While something to write... + while (len > 0) { - if ( newAddr != _fl_addr ) - { - flash_nrf5x_flush(need_erase); - _fl_addr = newAddr; - memcpy(_fl_buf, (void *) newAddr, FLASH_PAGE_SIZE); - } - memcpy(_fl_buf + (dst & (FLASH_PAGE_SIZE - 1)), src, len); + // Align to start of page + uint32_t page_addr = dst & ~(CODE_PAGE_SIZE - 1); + + // If page changed, write modified contents + if ( page_addr != _fl_addr ) + { + flash_nrf5x_flush(need_erase); + + // Remember new page + _fl_addr = page_addr; + + // And read its contents + memcpy(_fl_buf, (void *) page_addr, CODE_PAGE_SIZE); + } + + // Compute the write offset into the current page + uint32_t offset_in_page = dst & (CODE_PAGE_SIZE - 1); + + // Compute how many bytes remaining to complete the page + uint32_t bytes_to_end = CODE_PAGE_SIZE - offset_in_page; + + // Limit the count to the available bytes in the current page + uint32_t max_bytes = bytes_to_end < len ? bytes_to_end : len; + + // Copy contents to our buffer + memcpy(_fl_buf + offset_in_page, src, max_bytes); + + // Update variables + len -= max_bytes; + dst += max_bytes; + src = (void const *) ((uint8_t*)src + max_bytes); + }; } diff --git a/src/flash_nrf5x.h b/src/flash_nrf5x.h index 9ab4619..d3fbb49 100644 --- a/src/flash_nrf5x.h +++ b/src/flash_nrf5x.h @@ -34,7 +34,8 @@ extern "C" { #endif -void flash_nrf5x_write (uint32_t dst, void const *src, int len, bool need_erase); +void flash_nrf5x_erase (uint32_t dst, uint32_t len); +void flash_nrf5x_write (uint32_t dst, void const *src, uint32_t len, bool need_erase); void flash_nrf5x_flush (bool need_erase); #ifdef __cplusplus From efe383d0905dafe9119d5834f31092759cb06f20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Jos=C3=A9=20Tagle?= Date: Thu, 15 Jan 2026 01:19:15 -0300 Subject: [PATCH 77/90] Add DFU mode exit timeout of 3 minutes. If the user enters DFU mode BUT does nothing, in about 3 minutes, the bootloader will exit and start executing the user application --- .../bootloader_dfu/dfu_bank_internal.h | 2 + .../bootloader_dfu/dfu_single_bank.c | 87 ++++++++++++++++++- 2 files changed, 86 insertions(+), 3 deletions(-) diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_bank_internal.h b/lib/sdk11/components/libraries/bootloader_dfu/dfu_bank_internal.h index 03d20f6..f84d111 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_bank_internal.h +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_bank_internal.h @@ -40,6 +40,8 @@ typedef enum DFU_STATE_WAIT_4_ACTIVATE /**< State for: waiting for dfu_image_activate(). */ } dfu_state_t; +#define DFU_TIMEOUT_INTERVAL APP_TIMER_TICKS(360000) /**< DFU timeout interval in milliseconds. */ + #define IS_UPDATING_SD(START_PKT) ((START_PKT).dfu_update_mode & DFU_UPDATE_SD) /**< Macro for determining if a SoftDevice update is ongoing. */ #define IS_UPDATING_BL(START_PKT) ((START_PKT).dfu_update_mode & DFU_UPDATE_BL) /**< Macro for determining if a Bootloader update is ongoing. */ #define IS_UPDATING_APP(START_PKT) ((START_PKT).dfu_update_mode & DFU_UPDATE_APP) /**< Macro for determining if a Application update is ongoing. */ diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c b/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c index ee2d342..a01e0ba 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c @@ -35,6 +35,9 @@ static uint8_t m_init_packet[64]; /**< Init packet static uint8_t m_init_packet_length; /**< Length of init packet received. */ static uint16_t m_image_crc; /**< Calculated CRC of the image received. */ +APP_TIMER_DEF(m_dfu_timer_id); /**< Application timer id. */ +static bool m_dfu_timed_out = false; /**< Boolean flag value for tracking DFU timer timeout state. */ + static pstorage_handle_t m_storage_handle_app; /**< Pstorage handle for the application area (bank 0). Bank used when updating a SoftDevice w/wo bootloader. Handle also used when swapping received application from bank 1 to bank 0. */ static pstorage_handle_t * mp_storage_handle_active; /**< Pointer to the pstorage handle for the active bank for receiving of data packets. */ @@ -80,6 +83,47 @@ static void pstorage_callback_handler(pstorage_handle_t * p_handle, APP_ERROR_CHECK(result); } + +/**@brief Function for handling the DFU timeout. + * + * @param[in] p_context The timeout context. + */ +static void dfu_timeout_handler(void * p_context) +{ + UNUSED_PARAMETER(p_context); + dfu_update_status_t update_status; + + m_dfu_timed_out = true; + update_status.status_code = DFU_TIMEOUT; + + bootloader_dfu_update_process(update_status); +} + + +/**@brief Function for restarting the DFU Timer. + * + * @details This function will stop and restart the DFU timer. This function will be called by the + * functions handling any DFU packet received from the peer that is transferring a firmware + * image. + */ +static uint32_t dfu_timer_restart(void) +{ + if (m_dfu_timed_out) + { + // The DFU timer had already timed out. + return NRF_ERROR_INVALID_STATE; + } + + uint32_t err_code = app_timer_stop(m_dfu_timer_id); + APP_ERROR_CHECK(err_code); + + err_code = app_timer_start(m_dfu_timer_id, DFU_TIMEOUT_INTERVAL, NULL); + APP_ERROR_CHECK(err_code); + + return err_code; +} + + /**@brief Function for preparing of flash before receiving SoftDevice image. * * @details This function will erase current application area to ensure sufficient amount of @@ -236,6 +280,16 @@ uint32_t dfu_init(void) m_storage_handle_app.block_id = DFU_BANK_0_REGION_START; + // Create the timer to monitor the activity by the peer doing the firmware update. + err_code = app_timer_create(&m_dfu_timer_id, + APP_TIMER_MODE_SINGLE_SHOT, + dfu_timeout_handler); + APP_ERROR_CHECK(err_code); + + // Start the DFU timer. + err_code = app_timer_start(m_dfu_timer_id, DFU_TIMEOUT_INTERVAL, NULL); + APP_ERROR_CHECK(err_code); + m_data_received = 0; m_dfu_state = DFU_STATE_IDLE; @@ -251,6 +305,8 @@ void dfu_register_callback(dfu_callback_t callback_handler) uint32_t dfu_start_pkt_handle(dfu_update_packet_t * p_packet) { + uint32_t err_code; + m_start_packet = *(p_packet->params.start_packet); // Check that the requested update procedure is supported. @@ -304,6 +360,10 @@ uint32_t dfu_start_pkt_handle(dfu_update_packet_t * p_packet) if ( DFU_STATE_IDLE != m_dfu_state ) return NRF_ERROR_INVALID_STATE; + // Valid peer activity detected. Hence restart the DFU timer. + err_code = dfu_timer_restart(); + VERIFY_SUCCESS(err_code); + m_functions.prepare(m_image_size); return NRF_SUCCESS; @@ -346,6 +406,10 @@ uint32_t dfu_data_pkt_handle(dfu_update_packet_t * p_packet) return NRF_ERROR_DATA_SIZE; } + // Valid peer activity detected. Hence restart the DFU timer. + err_code = dfu_timer_restart(); + VERIFY_SUCCESS(err_code); + p_data = (uint32_t *)p_packet->params.data_packet.p_data_packet; if ( is_ota() ) @@ -413,6 +477,7 @@ uint32_t dfu_init_pkt_complete(void) uint32_t dfu_init_pkt_handle(dfu_update_packet_t * p_packet) { + uint32_t err_code = NRF_SUCCESS; uint32_t length; switch (m_dfu_state) @@ -430,6 +495,10 @@ uint32_t dfu_init_pkt_handle(dfu_update_packet_t * p_packet) return NRF_ERROR_INVALID_STATE; } + // Valid peer activity detected. Hence restart the DFU timer. + err_code = dfu_timer_restart(); + VERIFY_SUCCESS(err_code); + length = p_packet->params.data_packet.packet_length * sizeof(uint32_t); if ((m_init_packet_length + length) > sizeof(m_init_packet)) { @@ -469,9 +538,16 @@ uint32_t dfu_image_validate() { m_dfu_state = DFU_STATE_VALIDATE; - err_code = dfu_init_postvalidate((uint8_t *)mp_storage_handle_active->block_id, m_image_size); - VERIFY_SUCCESS(err_code); - m_dfu_state = DFU_STATE_WAIT_4_ACTIVATE; + // Valid peer activity detected. Hence restart the DFU timer. + err_code = dfu_timer_restart(); + if (err_code == NRF_SUCCESS) + { + err_code = dfu_init_postvalidate((uint8_t *)mp_storage_handle_active->block_id, + m_image_size); + VERIFY_SUCCESS(err_code); + + m_dfu_state = DFU_STATE_WAIT_4_ACTIVATE; + } } break; @@ -491,6 +567,11 @@ uint32_t dfu_image_activate() switch (m_dfu_state) { case DFU_STATE_WAIT_4_ACTIVATE: + + // Stop the DFU Timer because the peer activity need not be monitored any longer. + err_code = app_timer_stop(m_dfu_timer_id); + APP_ERROR_CHECK(err_code); + err_code = m_functions.activate(); break; From 450ce3b3c6b0c480c34f60b62b994496626bba59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Jos=C3=A9=20Tagle?= Date: Thu, 15 Jan 2026 01:22:12 -0300 Subject: [PATCH 78/90] Definitions for DUAL BANKED firmware updates (storing 2 copies of the firmware, so if a firmware update fails, the bootloader can revert to the previously working firmware) --- lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h b/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h index 4148e1c..f86a684 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h @@ -74,8 +74,12 @@ static inline bool is_sd_existed(void) #endif #define DFU_IMAGE_MAX_SIZE_FULL (DFU_REGION_TOTAL_SIZE - DFU_APP_DATA_RESERVED) /**< Maximum size of an application, excluding save data from the application. */ +#define DFU_IMAGE_MAX_SIZE_BANKED (((DFU_IMAGE_MAX_SIZE_FULL) - \ + (DFU_IMAGE_MAX_SIZE_FULL % (2 * CODE_PAGE_SIZE)))/2) /**< Maximum size of an application, excluding save data from the application. */ + #define DFU_BL_IMAGE_MAX_SIZE (BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS - BOOTLOADER_REGION_START) /**< Maximum size of a bootloader, excluding save data from the current bootloader. */ #define DFU_BANK_0_REGION_START CODE_REGION_1_START /**< Bank 0 region start. */ +#define DFU_BANK_1_REGION_START (DFU_BANK_0_REGION_START + DFU_IMAGE_MAX_SIZE_BANKED) /**< Bank 1 region start. */ #define EMPTY_FLASH_MASK 0xFFFFFFFF /**< Bit mask that defines an empty address in flash. */ From 88eab38a6c8692c3a4902639148013373de1e303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Jos=C3=A9=20Tagle?= Date: Thu, 15 Jan 2026 01:26:03 -0300 Subject: [PATCH 79/90] Allow flashing of a SINGLE BANK bootloader after a DUAL BANKED bootloader was installed. Without this patch, the SINGLE BANK bootloader will end in a continuous loop and no recovery without a JTAG programmer is possible --- .../bootloader_dfu/dfu_single_bank.c | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c b/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c index a01e0ba..6017e1f 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c @@ -731,27 +731,38 @@ uint32_t dfu_bl_image_swap(void) return NRF_SUCCESS; } - uint32_t dfu_bl_image_validate(void) { bootloader_settings_t bootloader_settings; - sd_mbr_command_t sd_mbr_cmd; + + sd_mbr_command_t sd_mbr_cmd_1; + sd_mbr_command_t sd_mbr_cmd_2; bootloader_settings_get(&bootloader_settings); if (bootloader_settings.bl_image_size != 0) { - uint32_t bl_image_start = (bootloader_settings.sd_image_size == 0) ? + uint32_t bl_image_start_1 = (bootloader_settings.sd_image_size == 0) ? DFU_BANK_0_REGION_START : bootloader_settings.sd_image_start + bootloader_settings.sd_image_size; - sd_mbr_cmd.command = SD_MBR_COMMAND_COMPARE; - sd_mbr_cmd.params.compare.ptr1 = (uint32_t *)BOOTLOADER_REGION_START; - sd_mbr_cmd.params.compare.ptr2 = (uint32_t *)(bl_image_start); - sd_mbr_cmd.params.compare.len = bootloader_settings.bl_image_size / sizeof(uint32_t); + sd_mbr_cmd_1.command = SD_MBR_COMMAND_COMPARE; + sd_mbr_cmd_1.params.compare.ptr1 = (uint32_t *)BOOTLOADER_REGION_START; + sd_mbr_cmd_1.params.compare.ptr2 = (uint32_t *)(bl_image_start_1); + sd_mbr_cmd_1.params.compare.len = bootloader_settings.bl_image_size / sizeof(uint32_t); - return sd_mbr_command(&sd_mbr_cmd); + uint32_t bl_image_start_2 = (bootloader_settings.sd_image_size == 0) ? + DFU_BANK_1_REGION_START : + bootloader_settings.sd_image_start + + bootloader_settings.sd_image_size; + + sd_mbr_cmd_2.command = SD_MBR_COMMAND_COMPARE; + sd_mbr_cmd_2.params.compare.ptr1 = (uint32_t *)BOOTLOADER_REGION_START; + sd_mbr_cmd_2.params.compare.ptr2 = (uint32_t *)(bl_image_start_2); + sd_mbr_cmd_2.params.compare.len = bootloader_settings.bl_image_size / sizeof(uint32_t); + + return sd_mbr_command(&sd_mbr_cmd_1) && sd_mbr_command(&sd_mbr_cmd_2); } return NRF_SUCCESS; } From d8c27bb7fd9dd0a167af2437431964bcfbb97568 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Jos=C3=A9=20Tagle?= Date: Thu, 15 Jan 2026 01:31:36 -0300 Subject: [PATCH 80/90] If there is no application in FLASH, or flash was corrupted, make sure to restart in DFU mode --- src/main.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/main.c b/src/main.c index 0011640..1111220 100644 --- a/src/main.c +++ b/src/main.c @@ -48,7 +48,10 @@ #include "nrf_soc.h" #include "nrf_nvic.h" #include "app_error.h" +#include "nrf_gpio.h" #include "ble.h" +#include "nrf.h" +#include "ble_hci.h" #include "app_scheduler.h" #include "nrf_error.h" @@ -56,10 +59,13 @@ #include "pstorage_platform.h" #include "nrf_mbr.h" +#include "pstorage.h" +#include "nrfx_nvmc.h" #ifdef NRF_USBD #include "uf2/uf2.h" +#include "nrf_usbd.h" #include "tusb.h" void usb_init(bool cdc_only); @@ -218,6 +224,9 @@ int main(void) { bootloader_app_start(); } + // No application was loaded, reset the system with the OTA DFU update + NRF_POWER->GPREGRET = 0xA8; + NVIC_SystemReset(); } @@ -242,17 +251,14 @@ static void check_dfu_mode(void) { (((*dbl_reset_mem) == DFU_DBL_RESET_MAGIC) && reason_reset_pin); // Clear GPREGRET if it is our values - if (dfu_start || dfu_skip) { - NRF_POWER->GPREGRET = 0; - } + if (dfu_start || dfu_skip) NRF_POWER->GPREGRET = 0; // skip dfu entirely - if (dfu_skip) { - return; - } + if (dfu_skip) return; /*------------- Determine DFU mode (Serial, OTA, FRESET or normal) -------------*/ - dfu_start = dfu_start || button_pressed(BUTTON_DFU); // DFU button pressed + // DFU button pressed + dfu_start = dfu_start || button_pressed(BUTTON_DFU); // DFU + FRESET are pressed --> OTA _ota_dfu = _ota_dfu || (button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET)); @@ -260,16 +266,16 @@ static void check_dfu_mode(void) { bool const valid_app = bootloader_app_is_valid(); bool const just_start_app = valid_app && !dfu_start && (*dbl_reset_mem) == DFU_DBL_RESET_APP; - if (!just_start_app && APP_ASKS_FOR_SINGLE_TAP_RESET()) { - dfu_start = 1; - } + if (!just_start_app && APP_ASKS_FOR_SINGLE_TAP_RESET()) dfu_start = 1; // App mode: Double Reset detection or DFU startup for nrf52832 if (!(just_start_app || dfu_start || !valid_app)) { #ifdef NRF52832_XXAA /* Even DFU is not active, we still force an 1000 ms dfu serial mode when startup * to support auto programming from Arduino IDE - * Note: Double Reset WONT work with nrf52832 since all its SRAM got cleared with GPIO reset. */ + * + * Note: Double Reset WONT work with nrf52832 since all its SRAM got cleared with GPIO reset. + */ bootloader_dfu_start(false, DFU_SERIAL_STARTUP_INTERVAL, false); #else // Note: RESETREAS is not clear by bootloader, it should be cleared by application upon init() From f20bfe9f633bd7aa209a2a84c36d9866f3a144f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Jos=C3=A9=20Tagle?= Date: Thu, 15 Jan 2026 01:40:51 -0300 Subject: [PATCH 81/90] Add DUAL_BANK functionality (disabled by default, can be enabled passing DUAL_BANK=1 to the Makefile in the make command line --- Makefile | 13 +- .../libraries/bootloader_dfu/dfu_dual_bank.c | 891 ++++++++++++++++++ src/main.c | 5 + 3 files changed, 905 insertions(+), 4 deletions(-) create mode 100644 lib/sdk11/components/libraries/bootloader_dfu/dfu_dual_bank.c diff --git a/Makefile b/Makefile index dba3c83..48a4d4d 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,11 @@ #------------------------------------------------------------------------------ # CONFIGURE -# - SDK_PATH : path to SDK directory +# - SDK_PATH : path to SDK directory # -# - SD_NAME : e.g s132, s140 -# - SD_VERSION : SoftDevice version e.g 6.0.0 -# - SD_HEX : to bootloader hex binary +# - SD_NAME : e.g s132, s140 +# - SD_VERSION : SoftDevice version e.g 6.0.0 +# - SD_HEX : to bootloader hex binary +# - DUALBANK_FW : If bootloader will implement a dual bank feature to allow autorecover from failed #------------------------------------------------------------------------------ # local customization @@ -163,7 +164,11 @@ C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/bootloader_settings.c C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/bootloader_util.c C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/dfu_transport_serial.c C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/dfu_transport_ble.c +ifeq ($(DUALBANK_FW), 1) +C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/dfu_dual_bank.c +else C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/dfu_single_bank.c +endif C_SRC += $(SDK11_PATH)/ble/ble_services/ble_dfu/ble_dfu.c C_SRC += $(SDK11_PATH)/ble/ble_services/ble_dis/ble_dis.c C_SRC += $(SDK11_PATH)/drivers_nrf/pstorage/pstorage_raw.c diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_dual_bank.c b/lib/sdk11/components/libraries/bootloader_dfu/dfu_dual_bank.c new file mode 100644 index 0000000..4516e4f --- /dev/null +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_dual_bank.c @@ -0,0 +1,891 @@ +/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. + * + */ + +#include +#include "dfu.h" +#include +#include "dfu_bank_internal.h" +#include "nrf.h" +#include "nrf_sdm.h" +#include "app_error.h" +#include "app_timer.h" +#include "bootloader.h" +#include "bootloader_types.h" +#include "pstorage.h" +#include "nrf_mbr.h" +#include "dfu_init.h" +#include "sdk_common.h" + +static dfu_state_t m_dfu_state; /**< Current DFU state. */ +static uint32_t m_image_size; /**< Size of the image that will be transmitted. */ + +static dfu_start_packet_t m_start_packet; /**< Start packet received for this update procedure. Contains update mode and image sizes information to be used for image transfer. */ +static uint8_t m_init_packet[128]; /**< Init packet, can hold CRC, Hash, Signed Hash and similar, for image validation, integrety check and authorization checking. */ +static uint8_t m_init_packet_length; /**< Length of init packet received. */ +static uint16_t m_image_crc; /**< Calculated CRC of the image received. */ + +APP_TIMER_DEF(m_dfu_timer_id); /**< Application timer id. */ +static bool m_dfu_timed_out = false; /**< Boolean flag value for tracking DFU timer timeout state. */ + +static pstorage_handle_t m_storage_handle_swap; /**< Pstorage handle for the swap area (bank 1). Bank used when updating an application or bootloader without SoftDevice. */ +static pstorage_handle_t m_storage_handle_app; /**< Pstorage handle for the application area (bank 0). Bank used when updating a SoftDevice w/wo bootloader. Handle also used when swapping received application from bank 1 to bank 0. */ +static pstorage_handle_t * mp_storage_handle_active; /**< Pointer to the pstorage handle for the active bank for receiving of data packets. */ + +static dfu_callback_t m_data_pkt_cb; /**< Callback from DFU Bank module for notification of asynchronous operation such as flash prepare. */ +static dfu_bank_func_t m_functions; /**< Structure holding operations for the selected update process. */ + + +/**@brief Function for handling callbacks from pstorage module. + * + * @details Handles pstorage results for clear and storage operation. For detailed description of + * the parameters provided with the callback, please refer to \ref pstorage_ntf_cb_t. + */ +static void pstorage_callback_handler(pstorage_handle_t * p_handle, + uint8_t op_code, + uint32_t result, + uint8_t * p_data, + uint32_t data_len) +{ + switch (op_code) + { + case PSTORAGE_STORE_OP_CODE: + if ((m_dfu_state == DFU_STATE_RX_DATA_PKT) && (m_data_pkt_cb != NULL)) + { + m_data_pkt_cb(DATA_PACKET, result, p_data); + } + break; + + case PSTORAGE_CLEAR_OP_CODE: + if (m_dfu_state == DFU_STATE_PREPARING) + { + m_functions.cleared(); + m_dfu_state = DFU_STATE_RDY; + if (m_data_pkt_cb != NULL) + { + m_data_pkt_cb(START_PACKET, result, p_data); + } + } + break; + + default: + break; + } + APP_ERROR_CHECK(result); +} + + +/**@brief Function for handling the DFU timeout. + * + * @param[in] p_context The timeout context. + */ +static void dfu_timeout_handler(void * p_context) +{ + UNUSED_PARAMETER(p_context); + dfu_update_status_t update_status = {0}; + + m_dfu_timed_out = true; + update_status.status_code = DFU_TIMEOUT; + + bootloader_dfu_update_process(update_status); +} + + +/**@brief Function for restarting the DFU Timer. + * + * @details This function will stop and restart the DFU timer. This function will be called by the + * functions handling any DFU packet received from the peer that is transferring a firmware + * image. + */ +static uint32_t dfu_timer_restart(void) +{ + if (m_dfu_timed_out) + { + // The DFU timer had already timed out. + return NRF_ERROR_INVALID_STATE; + } + + uint32_t err_code = app_timer_stop(m_dfu_timer_id); + APP_ERROR_CHECK(err_code); + + err_code = app_timer_start(m_dfu_timer_id, DFU_TIMEOUT_INTERVAL, NULL); + APP_ERROR_CHECK(err_code); + + return err_code; +} + + +/**@brief Function for preparing of flash before receiving SoftDevice image. + * + * @details This function will erase current application area to ensure sufficient amount of + * storage for the SoftDevice image. Upon erase complete a callback will be done. + * See \ref dfu_bank_prepare_t for further details. + */ +static void dfu_prepare_func_app_erase(uint32_t image_size) +{ + mp_storage_handle_active = &m_storage_handle_app; + + // Doing a SoftDevice update thus current application must be cleared to ensure enough space + // for new SoftDevice. + m_dfu_state = DFU_STATE_PREPARING; + + if ( is_ota() ) + { + uint32_t err_code = pstorage_clear(&m_storage_handle_app, m_image_size); + APP_ERROR_CHECK(err_code); + } + else + { + flash_nrf5x_erase(DFU_BANK_0_REGION_START, m_image_size); + + // invoke complete callback + pstorage_callback_handler(&m_storage_handle_app, PSTORAGE_CLEAR_OP_CODE, NRF_SUCCESS, NULL, 0); + } +} + + +/**@brief Function for preparing swap before receiving application or bootloader image. + * + * @details This function will erase current swap area to ensure flash is ready for storage of the + * Application or Bootloader image. Upon erase complete a callback will be done. + * See \ref dfu_bank_prepare_t for further details. + */ +static void dfu_prepare_func_swap_erase(uint32_t image_size) +{ + mp_storage_handle_active = &m_storage_handle_swap; + + m_dfu_state = DFU_STATE_PREPARING; + + if ( is_ota() ) + { + uint32_t err_code = pstorage_clear(&m_storage_handle_swap, image_size); + APP_ERROR_CHECK(err_code); + } + else + { + flash_nrf5x_erase(DFU_BANK_1_REGION_START, image_size); + + // invoke complete callback + pstorage_callback_handler(&m_storage_handle_swap, PSTORAGE_CLEAR_OP_CODE, NRF_SUCCESS, NULL, 0); + } +} + + +/**@brief Function for handling behaviour when clear operation has completed. + */ +static void dfu_cleared_func_swap(void) +{ + // Do nothing. +} + + +/**@brief Function for handling behaviour when clear operation has completed. + */ +static void dfu_cleared_func_app(void) +{ + dfu_update_status_t update_status = { 0 }; + update_status.status_code = DFU_BANK_0_ERASED; + bootloader_dfu_update_process(update_status); +} + + +/**@brief Function for calculating storage offset for receiving SoftDevice image. + * + * @details When a new SoftDevice is received it will be temporary stored in flash before moved to + * address 0x0. In order to succesfully validate transfer and relocation it is important + * that temporary image and final installed image does not ovwerlap hence an offset must + * be calculated in case new image is larger than currently installed SoftDevice. + */ +uint32_t offset_calculate(uint32_t sd_image_size) +{ + uint32_t offset = 0; + + if (m_start_packet.sd_image_size > DFU_BANK_0_REGION_START) + { + uint32_t page_mask = (CODE_PAGE_SIZE - 1); + uint32_t diff = m_start_packet.sd_image_size - DFU_BANK_0_REGION_START; + + offset = diff & ~page_mask; + + // Align offset to next page if image size is not page sized. + if ((diff & page_mask) > 0) + { + offset += CODE_PAGE_SIZE; + } + } + + return offset; +} + + +/**@brief Function for activating received SoftDevice image. + * + * @note This function will not move the SoftDevice image. + * The bootloader settings will be marked as SoftDevice update complete and the swapping of + * current SoftDevice will occur after system reset. + * + * @return NRF_SUCCESS on success. + */ +static uint32_t dfu_activate_sd(void) +{ + dfu_update_status_t update_status = {0}; + + update_status.status_code = DFU_UPDATE_SD_COMPLETE; + update_status.app_crc = m_image_crc; + update_status.sd_image_start = DFU_BANK_0_REGION_START; + update_status.sd_size = m_start_packet.sd_image_size; + update_status.bl_size = m_start_packet.bl_image_size; + update_status.app_size = m_start_packet.app_image_size; + + bootloader_dfu_update_process(update_status); + + return NRF_SUCCESS; +} + + +/**@brief Function for activating received Application image. + * + * @details This function will move the received application image fram swap (bank 1) to + * application area (bank 0). + * + * @return NRF_SUCCESS on success. Error code otherwise. + */ +static uint32_t dfu_activate_app(void) +{ + uint32_t err_code = NRF_SUCCESS; + + // Erase BANK 0. + if ( is_ota() ) + { + err_code = pstorage_clear(&m_storage_handle_app, m_start_packet.app_image_size); + APP_ERROR_CHECK(err_code); + + err_code = pstorage_store(&m_storage_handle_app, + (uint8_t *)m_storage_handle_swap.block_id, + m_start_packet.app_image_size, + 0); + } + else + { + flash_nrf5x_erase(DFU_BANK_0_REGION_START, m_start_packet.app_image_size); + pstorage_callback_handler(&m_storage_handle_app, PSTORAGE_CLEAR_OP_CODE, NRF_SUCCESS, NULL, 0); + + flash_nrf5x_write(DFU_BANK_0_REGION_START, (uint8_t *)DFU_BANK_1_REGION_START, m_start_packet.app_image_size, false); + flash_nrf5x_flush(false); + pstorage_callback_handler(&m_storage_handle_app, PSTORAGE_STORE_OP_CODE, NRF_SUCCESS, (uint8_t *) DFU_BANK_1_REGION_START, m_start_packet.app_image_size); + } + + if (err_code == NRF_SUCCESS) + { + dfu_update_status_t update_status = { 0 }; + + memset(&update_status, 0, sizeof(dfu_update_status_t )); + update_status.status_code = DFU_UPDATE_APP_COMPLETE; + update_status.app_crc = m_image_crc; + update_status.app_size = m_start_packet.app_image_size; + + bootloader_dfu_update_process(update_status); + } + + return err_code; +} + + +/**@brief Function for activating received Bootloader image. + * + * @note This function will not move the bootloader image. + * The bootloader settings will be marked as Bootloader update complete and the swapping of + * current bootloader will occur after system reset. + * + * @return NRF_SUCCESS on success. + */ +static uint32_t dfu_activate_bl(void) +{ + dfu_update_status_t update_status = {0}; + + update_status.status_code = DFU_UPDATE_BOOT_COMPLETE; + update_status.app_crc = m_image_crc; + update_status.sd_size = m_start_packet.sd_image_size; + update_status.bl_size = m_start_packet.bl_image_size; + update_status.app_size = m_start_packet.app_image_size; + + bootloader_dfu_update_process(update_status); + + return NRF_SUCCESS; +} + + +uint32_t dfu_init(void) +{ + uint32_t err_code; + pstorage_module_param_t storage_module_param = {.cb = pstorage_callback_handler}; + + m_init_packet_length = 0; + m_image_crc = 0; + + err_code = pstorage_register(&storage_module_param, &m_storage_handle_app); + if (err_code != NRF_SUCCESS) + { + m_dfu_state = DFU_STATE_INIT_ERROR; + return err_code; + } + + m_storage_handle_app.block_id = DFU_BANK_0_REGION_START; + m_storage_handle_swap = m_storage_handle_app; + m_storage_handle_swap.block_id = DFU_BANK_1_REGION_START; + + // Create the timer to monitor the activity by the peer doing the firmware update. + err_code = app_timer_create(&m_dfu_timer_id, + APP_TIMER_MODE_SINGLE_SHOT, + dfu_timeout_handler); + APP_ERROR_CHECK(err_code); + + // Start the DFU timer. + err_code = app_timer_start(m_dfu_timer_id, DFU_TIMEOUT_INTERVAL, NULL); + APP_ERROR_CHECK(err_code); + + m_data_received = 0; + m_dfu_state = DFU_STATE_IDLE; + + return NRF_SUCCESS; +} + + +void dfu_register_callback(dfu_callback_t callback_handler) +{ + m_data_pkt_cb = callback_handler; +} + + +uint32_t dfu_start_pkt_handle(dfu_update_packet_t * p_packet) +{ + uint32_t err_code; + + m_start_packet = *(p_packet->params.start_packet); + + // Check that the requested update procedure is supported. + // Currently the following combinations are allowed: + // - Application + // - SoftDevice + // - Bootloader + // - SoftDevice with Bootloader + if (IS_UPDATING_APP(m_start_packet) && + (IS_UPDATING_SD(m_start_packet) || IS_UPDATING_BL(m_start_packet))) + { + // App update is only supported independently. + return NRF_ERROR_NOT_SUPPORTED; + } + + if (!(IS_WORD_SIZED(m_start_packet.sd_image_size) && + IS_WORD_SIZED(m_start_packet.bl_image_size) && + IS_WORD_SIZED(m_start_packet.app_image_size))) + { + // Image_sizes are not a multiple of 4 (word size). + return NRF_ERROR_NOT_SUPPORTED; + } + + m_image_size = m_start_packet.sd_image_size + m_start_packet.bl_image_size + + m_start_packet.app_image_size; + + if (m_start_packet.bl_image_size > DFU_BL_IMAGE_MAX_SIZE) + { + return NRF_ERROR_DATA_SIZE; + } + + if (IS_UPDATING_SD(m_start_packet)) + { + if (m_image_size > (DFU_IMAGE_MAX_SIZE_FULL)) + { + return NRF_ERROR_DATA_SIZE; + } + m_functions.prepare = dfu_prepare_func_app_erase; + m_functions.cleared = dfu_cleared_func_app; + m_functions.activate = dfu_activate_sd; + } + else + { + if (m_image_size > DFU_IMAGE_MAX_SIZE_BANKED) + { + return NRF_ERROR_DATA_SIZE; + } + + m_functions.prepare = dfu_prepare_func_swap_erase; + m_functions.cleared = dfu_cleared_func_swap; + if (IS_UPDATING_BL(m_start_packet)) + { + m_functions.activate = dfu_activate_bl; + } + else + { + m_functions.activate = dfu_activate_app; + } + } + + if ( DFU_STATE_IDLE != m_dfu_state ) + return NRF_ERROR_INVALID_STATE; + + // Valid peer activity detected. Hence restart the DFU timer. + err_code = dfu_timer_restart(); + VERIFY_SUCCESS(err_code); + + m_functions.prepare(m_image_size); + + return NRF_SUCCESS; +} + + +uint32_t dfu_data_pkt_handle(dfu_update_packet_t * p_packet) +{ + uint32_t data_length; + uint32_t err_code; + uint32_t * p_data; + + VERIFY_PARAM_NOT_NULL(p_packet); + + // Check pointer alignment. + if (!is_word_aligned(p_packet->params.data_packet.p_data_packet)) + { + // The p_data_packet is not word aligned address. + return NRF_ERROR_INVALID_ADDR; + } + + switch (m_dfu_state) + { + case DFU_STATE_RDY: + case DFU_STATE_RX_INIT_PKT: + return NRF_ERROR_INVALID_STATE; + + case DFU_STATE_RX_DATA_PKT: + data_length = p_packet->params.data_packet.packet_length * sizeof(uint32_t); + + if ((m_data_received + data_length) > m_image_size) + { + // The caller is trying to write more bytes into the flash than the size provided to + // the dfu_image_size_set function. This is treated as a serious error condition and + // an unrecoverable one. Hence point the variable mp_app_write_address to the top of + // the flash area. This will ensure that all future application data packet writes + // will be blocked because of the above check. + m_data_received = 0xFFFFFFFF; + + return NRF_ERROR_DATA_SIZE; + } + + // Valid peer activity detected. Hence restart the DFU timer. + err_code = dfu_timer_restart(); + VERIFY_SUCCESS(err_code); + + p_data = (uint32_t *)p_packet->params.data_packet.p_data_packet; + + if ( is_ota() ) + { + err_code = pstorage_store(mp_storage_handle_active, (uint8_t *)p_data, data_length, m_data_received); + VERIFY_SUCCESS(err_code); + } + else + { + flash_nrf5x_write( + (mp_storage_handle_active == &m_storage_handle_app + ? DFU_BANK_0_REGION_START + : DFU_BANK_1_REGION_START) + + m_data_received, p_data, data_length, false); + pstorage_callback_handler(mp_storage_handle_active, PSTORAGE_STORE_OP_CODE, NRF_SUCCESS, (uint8_t *) p_data, data_length); + } + + m_data_received += data_length; + + if (m_data_received != m_image_size) + { + // The entire image is not received yet. More data is expected. + err_code = NRF_ERROR_INVALID_LENGTH; + } + else + { + if ( !is_ota() ) flash_nrf5x_flush(false); + + // The entire image has been received. Return NRF_SUCCESS. + err_code = NRF_SUCCESS; + } + break; + + default: + err_code = NRF_ERROR_INVALID_STATE; + break; + } + + return err_code; +} + + +uint32_t dfu_init_pkt_complete(void) +{ + uint32_t err_code = NRF_ERROR_INVALID_STATE; + + // DFU initialization has been done and a start packet has been received. + if (IMAGE_WRITE_IN_PROGRESS()) + { + // Image write is already in progress. Cannot handle an init packet now. + return NRF_ERROR_INVALID_STATE; + } + + if (m_dfu_state == DFU_STATE_RX_INIT_PKT) + { + err_code = dfu_init_prevalidate(m_init_packet, m_init_packet_length, m_start_packet.dfu_update_mode); + if (err_code == NRF_SUCCESS) + { + m_dfu_state = DFU_STATE_RX_DATA_PKT; + } + else + { + m_init_packet_length = 0; + } + } + return err_code; +} + + +uint32_t dfu_init_pkt_handle(dfu_update_packet_t * p_packet) +{ + uint32_t err_code = NRF_SUCCESS; + uint32_t length; + + switch (m_dfu_state) + { + case DFU_STATE_RDY: + m_dfu_state = DFU_STATE_RX_INIT_PKT; + // When receiving init packet in state ready just update and fall through this case. + /* FALLTHRU */ + + case DFU_STATE_RX_INIT_PKT: + // DFU initialization has been done and a start packet has been received. + if (IMAGE_WRITE_IN_PROGRESS()) + { + // Image write is already in progress. Cannot handle an init packet now. + return NRF_ERROR_INVALID_STATE; + } + + // Valid peer activity detected. Hence restart the DFU timer. + err_code = dfu_timer_restart(); + VERIFY_SUCCESS(err_code); + + length = p_packet->params.data_packet.packet_length * sizeof(uint32_t); + if ((m_init_packet_length + length) > sizeof(m_init_packet)) + { + return NRF_ERROR_INVALID_LENGTH; + } + + memcpy(&m_init_packet[m_init_packet_length], + &p_packet->params.data_packet.p_data_packet[0], + length); + m_init_packet_length += length; + break; + + default: + // Either the start packet was not received or dfu_init function was not called before. + return NRF_ERROR_INVALID_STATE; + } + + return NRF_SUCCESS; +} + + +uint32_t dfu_image_validate() +{ + uint32_t err_code; + + switch (m_dfu_state) + { + case DFU_STATE_RX_DATA_PKT: + // Check if the application image write has finished. + if (m_data_received != m_image_size) + { + // Image not yet fully transfered by the peer or the peer has attempted to write + // too much data. Hence the validation should fail. + err_code = NRF_ERROR_INVALID_STATE; + } + else + { + m_dfu_state = DFU_STATE_VALIDATE; + + // Valid peer activity detected. Hence restart the DFU timer. + err_code = dfu_timer_restart(); + if (err_code == NRF_SUCCESS) + { + err_code = dfu_init_postvalidate((uint8_t *)mp_storage_handle_active->block_id, + m_image_size); + VERIFY_SUCCESS(err_code); + + m_dfu_state = DFU_STATE_WAIT_4_ACTIVATE; + } + } + break; + + default: + err_code = NRF_ERROR_INVALID_STATE; + break; + } + + return err_code; +} + + +uint32_t dfu_image_activate() +{ + uint32_t err_code; + + switch (m_dfu_state) + { + case DFU_STATE_WAIT_4_ACTIVATE: + + // Stop the DFU Timer because the peer activity need not be monitored any longer. + err_code = app_timer_stop(m_dfu_timer_id); + APP_ERROR_CHECK(err_code); + + err_code = m_functions.activate(); + break; + + default: + err_code = NRF_ERROR_INVALID_STATE; + break; + } + + return err_code; +} + + +void dfu_reset(void) +{ + dfu_update_status_t update_status = { 0 }; + + update_status.status_code = DFU_RESET; + + bootloader_dfu_update_process(update_status); +} + + +static uint32_t dfu_compare_block(uint32_t * ptr1, uint32_t * ptr2, uint32_t len) +{ + sd_mbr_command_t sd_mbr_cmd; + + sd_mbr_cmd.command = SD_MBR_COMMAND_COMPARE; + sd_mbr_cmd.params.compare.ptr1 = ptr1; + sd_mbr_cmd.params.compare.ptr2 = ptr2; + sd_mbr_cmd.params.compare.len = len / sizeof(uint32_t); + + return sd_mbr_command(&sd_mbr_cmd); +} + + +static uint32_t dfu_copy_sd(uint32_t * src, uint32_t * dst, uint32_t len) +{ + sd_mbr_command_t sd_mbr_cmd; + + sd_mbr_cmd.command = SD_MBR_COMMAND_COPY_SD; + sd_mbr_cmd.params.copy_sd.src = src; + sd_mbr_cmd.params.copy_sd.dst = dst; + sd_mbr_cmd.params.copy_sd.len = len / sizeof(uint32_t); + + return sd_mbr_command(&sd_mbr_cmd); +} + + +static uint32_t dfu_sd_img_block_swap(uint32_t * src, + uint32_t * dst, + uint32_t len, + uint32_t block_size) +{ + // It is neccesarry to swap the new SoftDevice in 3 rounds to ensure correct copy of data + // and verifucation of data in case power reset occurs during write to flash. + // To ensure the robustness of swapping the images are compared backwards till start of + // image swap. If the back is identical everything is swapped. + uint32_t err_code = dfu_compare_block(src, dst, len); + if (err_code == NRF_SUCCESS) + { + return err_code; + } + + if ((uint32_t)dst > SOFTDEVICE_REGION_START) + { + err_code = dfu_sd_img_block_swap((uint32_t *)((uint32_t)src - block_size), + (uint32_t *)((uint32_t)dst - block_size), + block_size, + block_size); + VERIFY_SUCCESS(err_code); + } + + err_code = dfu_copy_sd(src, dst, len); + VERIFY_SUCCESS(err_code); + + return dfu_compare_block(src, dst, len); +} + + +uint32_t dfu_sd_image_swap(void) +{ + bootloader_settings_t boot_settings; + + bootloader_settings_get(&boot_settings); + + if (boot_settings.sd_image_size == 0) + { + return NRF_SUCCESS; + } + + if ((SOFTDEVICE_REGION_START + boot_settings.sd_image_size) > boot_settings.sd_image_start) + { + uint32_t err_code; + uint32_t sd_start = SOFTDEVICE_REGION_START; + uint32_t block_size = (boot_settings.sd_image_start - sd_start) / 2; + + /* ##### FIX START ##### */ + block_size &= ~(uint32_t)(CODE_PAGE_SIZE - 1); + /* ##### FIX END ##### */ + + uint32_t image_end = boot_settings.sd_image_start + boot_settings.sd_image_size; + + uint32_t img_block_start = boot_settings.sd_image_start + 2 * block_size; + uint32_t sd_block_start = sd_start + 2 * block_size; + + if (SD_SIZE_GET(MBR_SIZE) < boot_settings.sd_image_size) + { + // This will clear a page thus ensuring the old image is invalidated before swapping. + err_code = dfu_copy_sd((uint32_t *)(sd_start + block_size), + (uint32_t *)(sd_start + block_size), + sizeof(uint32_t)); + VERIFY_SUCCESS(err_code); + + err_code = dfu_copy_sd((uint32_t *)sd_start, (uint32_t *)sd_start, sizeof(uint32_t)); + VERIFY_SUCCESS(err_code); + } + + return dfu_sd_img_block_swap((uint32_t *)img_block_start, + (uint32_t *)sd_block_start, + image_end - img_block_start, + block_size); + } + else + { + if (boot_settings.sd_image_size != 0) + { + return dfu_copy_sd((uint32_t *)boot_settings.sd_image_start, + (uint32_t *)SOFTDEVICE_REGION_START, + boot_settings.sd_image_size); + } + } + + return NRF_SUCCESS; +} + + +uint32_t dfu_bl_image_swap(void) +{ + bootloader_settings_t bootloader_settings; + sd_mbr_command_t sd_mbr_cmd; + + bootloader_settings_get(&bootloader_settings); + + if (bootloader_settings.bl_image_size != 0) + { + uint32_t bl_image_start = (bootloader_settings.sd_image_size == 0) ? + DFU_BANK_1_REGION_START : + bootloader_settings.sd_image_start + + bootloader_settings.sd_image_size; + + sd_mbr_cmd.command = SD_MBR_COMMAND_COPY_BL; + sd_mbr_cmd.params.copy_bl.bl_src = (uint32_t *)(bl_image_start); + sd_mbr_cmd.params.copy_bl.bl_len = bootloader_settings.bl_image_size / sizeof(uint32_t); + + return sd_mbr_command(&sd_mbr_cmd); + } + return NRF_SUCCESS; +} + + +uint32_t dfu_bl_image_validate(void) +{ + bootloader_settings_t bootloader_settings;\ + + sd_mbr_command_t sd_mbr_cmd_1; + sd_mbr_command_t sd_mbr_cmd_2; + + bootloader_settings_get(&bootloader_settings); + + if (bootloader_settings.bl_image_size != 0) + { + uint32_t bl_image_start_1 = (bootloader_settings.sd_image_size == 0) ? + DFU_BANK_0_REGION_START : + bootloader_settings.sd_image_start + + bootloader_settings.sd_image_size; + + sd_mbr_cmd_1.command = SD_MBR_COMMAND_COMPARE; + sd_mbr_cmd_1.params.compare.ptr1 = (uint32_t *)BOOTLOADER_REGION_START; + sd_mbr_cmd_1.params.compare.ptr2 = (uint32_t *)(bl_image_start_1); + sd_mbr_cmd_1.params.compare.len = bootloader_settings.bl_image_size / sizeof(uint32_t); + + uint32_t bl_image_start_2 = (bootloader_settings.sd_image_size == 0) ? + DFU_BANK_1_REGION_START : + bootloader_settings.sd_image_start + + bootloader_settings.sd_image_size; + + sd_mbr_cmd_2.command = SD_MBR_COMMAND_COMPARE; + sd_mbr_cmd_2.params.compare.ptr1 = (uint32_t *)BOOTLOADER_REGION_START; + sd_mbr_cmd_2.params.compare.ptr2 = (uint32_t *)(bl_image_start_2); + sd_mbr_cmd_2.params.compare.len = bootloader_settings.bl_image_size / sizeof(uint32_t); + + return sd_mbr_command(&sd_mbr_cmd_1) && sd_mbr_command(&sd_mbr_cmd_2); + } + return NRF_SUCCESS; +} + + +uint32_t dfu_sd_image_validate(void) +{ + bootloader_settings_t bootloader_settings; + sd_mbr_command_t sd_mbr_cmd; + + bootloader_settings_get(&bootloader_settings); + + if (bootloader_settings.sd_image_size == 0) + { + return NRF_SUCCESS; + } + + if ((SOFTDEVICE_REGION_START + bootloader_settings.sd_image_size) > bootloader_settings.sd_image_start) + { + uint32_t sd_start = SOFTDEVICE_REGION_START; + uint32_t block_size = (bootloader_settings.sd_image_start - sd_start) / 2; + uint32_t image_end = bootloader_settings.sd_image_start + + bootloader_settings.sd_image_size; + + /* ##### FIX START ##### */ + block_size &= ~(uint32_t)(CODE_PAGE_SIZE - 1); + /* ##### FIX END ##### */ + + uint32_t img_block_start = bootloader_settings.sd_image_start + 2 * block_size; + uint32_t sd_block_start = sd_start + 2 * block_size; + + if (SD_SIZE_GET(MBR_SIZE) < bootloader_settings.sd_image_size) + { + return NRF_ERROR_NULL; + } + + return dfu_sd_img_block_swap((uint32_t *)img_block_start, + (uint32_t *)sd_block_start, + image_end - img_block_start, + block_size); + } + + sd_mbr_cmd.command = SD_MBR_COMMAND_COMPARE; + sd_mbr_cmd.params.compare.ptr1 = (uint32_t *)SOFTDEVICE_REGION_START; + sd_mbr_cmd.params.compare.ptr2 = (uint32_t *)bootloader_settings.sd_image_start; + sd_mbr_cmd.params.compare.len = bootloader_settings.sd_image_size / sizeof(uint32_t); + + return sd_mbr_command(&sd_mbr_cmd); +} diff --git a/src/main.c b/src/main.c index 1111220..3909651 100644 --- a/src/main.c +++ b/src/main.c @@ -39,8 +39,13 @@ #include #include "nrfx.h" +#include "nrf_clock.h" #include "nrfx_power.h" +#include "nrfx_pwm.h" + +#include "nordic_common.h" #include "sdk_common.h" +#include "dfu_transport.h" #include "bootloader.h" #include "bootloader_util.h" From c8af92c4d8af6ea6836025b36e0552078d399b7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Jos=C3=A9=20Tagle?= Date: Thu, 15 Jan 2026 01:53:57 -0300 Subject: [PATCH 82/90] Implement signed firmware verification: If enabled (Disabled by default), the bootloader will reject and not flash any firmware that is not digitally signed with the proper key --- .gitmodules | 3 + Makefile | 49 ++- .../bootloader_dfu/dfu_single_bank.c | 2 +- src/dfu_init.c | 287 ++++++++++++------ src/main.c | 4 + src/usb/tusb_config.h | 2 + src/usb/usb.c | 2 + src/usb/usb_desc.c | 16 + 8 files changed, 269 insertions(+), 96 deletions(-) diff --git a/.gitmodules b/.gitmodules index bd80adc..f8d4023 100644 --- a/.gitmodules +++ b/.gitmodules @@ -8,3 +8,6 @@ path = lib/uf2 url = https://github.com/microsoft/uf2.git +[submodule "lib/tinycrypt"] + path = lib/tinycrypt + url = https://github.com/intel/tinycrypt diff --git a/Makefile b/Makefile index 48a4d4d..45dc1df 100644 --- a/Makefile +++ b/Makefile @@ -5,9 +5,15 @@ # - SD_NAME : e.g s132, s140 # - SD_VERSION : SoftDevice version e.g 6.0.0 # - SD_HEX : to bootloader hex binary +# - SIGNED_FW : if bootloader will ONLY accept signed firmware +# - SIGNED_FW_QX : Qx for signed firmware verification +# - SIGNED_FW_QY : Qy for signed firmware verification # - DUALBANK_FW : If bootloader will implement a dual bank feature to allow autorecover from failed +# - FORCE_UF2 : if SIGNED_FW is 1, will force to include UF2 support (UNSECURE, UF2 does NOT validate signature!) #------------------------------------------------------------------------------ +PYTHON = python + # local customization -include Makefile.user @@ -17,6 +23,7 @@ SDK_PATH = lib/sdk/components SDK11_PATH = lib/sdk11/components TUSB_PATH = lib/tinyusb/src +TCRYPT_PATH = lib/tinycrypt/lib NRFX_PATH = lib/nrfx SD_PATH = lib/softdevice/$(SD_FILENAME) @@ -150,6 +157,15 @@ C_SRC += \ src/screen.c \ src/images.c \ +# if using a signed firmware +ifeq ($(SIGNED_FW), 1) +C_SRC += \ + $(TCRYPT_PATH)/source/sha256.c \ + $(TCRYPT_PATH)/source/ecc.c \ + $(TCRYPT_PATH)/source/ecc_dsa.c \ + $(TCRYPT_PATH)/source/utils.c +endif + # all files in boards C_SRC += src/boards/boards.c @@ -202,10 +218,10 @@ C_SRC += src/boards/$(BOARD)/pinconfig.c # USB Application ( MSC + UF2 ) C_SRC += \ - src/usb/msc_uf2.c \ src/usb/usb_desc.c \ - src/usb/usb.c \ - src/usb/uf2/ghostfat.c + src/usb/msc_uf2.c \ + src/usb/uf2/ghostfat.c \ + src/usb/usb.c # TinyUSB stack C_SRC += \ @@ -216,9 +232,9 @@ C_SRC += \ $(TUSB_PATH)/class/cdc/cdc_device.c \ $(TUSB_PATH)/class/msc/msc_device.c \ $(TUSB_PATH)/tusb.c - endif + #------------------------------------------------------------------------------ # Assembly Files #------------------------------------------------------------------------------ @@ -236,6 +252,11 @@ IPATH += \ src/cmsis/include \ src/usb \ $(TUSB_PATH) + +ifeq ($(SIGNED_FW), 1) +IPATH += \ + $(TCRYPT_PATH)/include +endif # nrfx IPATH += \ @@ -331,6 +352,16 @@ CFLAGS += -DSOFTDEVICE_PRESENT CFLAGS += -DUF2_VERSION='"$(GIT_VERSION)"' CFLAGS += -DBLEDIS_FW_VERSION='"$(GIT_VERSION) $(SD_NAME) $(SD_VERSION)"' +ifeq ($(SIGNED_FW), 1) +CFLAGS += -DSIGNED_FW +CFLAGS += -DSIGNED_FW_QX='$(SIGNED_FW_QX)' +CFLAGS += -DSIGNED_FW_QY='$(SIGNED_FW_QY)' +endif + +ifeq ($(FORCE_UF2), 1) +CFLAGS += -DFORCE_UF2 +endif + _VER = $(subst ., ,$(word 1, $(subst -, ,$(GIT_VERSION)))) CFLAGS += -DMK_BOOTLOADER_VERSION='($(word 1,$(_VER)) << 16) + ($(word 2,$(_VER)) << 8) + $(word 3,$(_VER))' @@ -354,9 +385,9 @@ CFLAGS += -DDFU_APP_DATA_RESERVED=$(DFU_APP_DATA_RESERVED) # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105523 # Fixes for gcc version 12, 13 and 14. -ifneq (,$(filter 12.% 13.% 14.%,$(shell $(CC) -dumpversion 2>/dev/null))) +#ifneq (,$(filter 12.% 13.% 14.%,$(shell $(CC) -dumpversion 2>/dev/null))) CFLAGS += --param=min-pagesize=0 -endif +#endif #------------------------------------------------------------------------------ # Linker Flags @@ -449,17 +480,17 @@ $(BUILD)/$(OUT_NAME).hex: $(BUILD)/$(OUT_NAME).out # Hex file with mbr (still no SD) $(BUILD)/$(OUT_NAME)_nosd.hex: $(BUILD)/$(OUT_NAME).hex @echo Create $(notdir $@) - @python3 tools/hexmerge.py --overlap=replace -o $@ $< $(MBR_HEX) + @$(PYTHON) tools/hexmerge.py --overlap=replace -o $@ $< $(MBR_HEX) # Bootolader self-update uf2 $(BUILD)/update-$(OUT_NAME)_nosd.uf2: $(BUILD)/$(OUT_NAME)_nosd.hex @echo Create $(notdir $@) - @python3 lib/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID_BOOTLOADER) -c -o $@ $^ + $(PYTHON) lib/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID_BOOTLOADER) -c -o $@ $^ # merge bootloader and sd hex together $(BUILD)/$(MERGED_FILE).hex: $(BUILD)/$(OUT_NAME).hex @echo Create $(notdir $@) - @python3 tools/hexmerge.py -o $@ $< $(SD_HEX) + @$(PYTHON) tools/hexmerge.py -o $@ $< $(SD_HEX) # Create pkg zip file for bootloader+SD combo to use with DFU CDC $(BUILD)/$(MERGED_FILE).zip: $(BUILD)/$(OUT_NAME).hex diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c b/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c index 6017e1f..bf003c6 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c @@ -31,7 +31,7 @@ static dfu_state_t m_dfu_state; /**< Current DFU static uint32_t m_image_size; /**< Size of the image that will be transmitted. */ static dfu_start_packet_t m_start_packet; /**< Start packet received for this update procedure. Contains update mode and image sizes information to be used for image transfer. */ -static uint8_t m_init_packet[64]; /**< Init packet, can hold CRC, Hash, Signed Hash and similar, for image validation, integrety check and authorization checking. */ +static uint8_t m_init_packet[128]; /**< Init packet, can hold CRC, Hash, Signed Hash and similar, for image validation, integrety check and authorization checking. */ static uint8_t m_init_packet_length; /**< Length of init packet received. */ static uint16_t m_image_crc; /**< Calculated CRC of the image received. */ diff --git a/src/dfu_init.c b/src/dfu_init.c index e19cffa..c848d26 100644 --- a/src/dfu_init.c +++ b/src/dfu_init.c @@ -66,16 +66,24 @@ * If the init packet is signed by a trusted source, it must be decrypted before it can be * processed. */ - + #include "dfu_init.h" #include #include #include #include "nrf_error.h" + +#ifndef SIGNED_FW #include "crc16.h" +#else +#include +#include +#include +#include +#endif /* ADAFRUIT - * - All firmware init data must has Device Type ADAFRUIT_DEVICE_TYPE (nrf52832 and nrf52840) + * - All firmware init data must have Device Type ADAFRUIT_DEVICE_TYPE (nrf52832 and nrf52840) * - SD + Bootloader upgrade must have correct Device Revision to make sure bootloader is not flashed * on the wrong device (e.g flah nRF52832's bootloader on nRF52840 board and vice versa) * - nrf52832 dev-rev is 0xADAF @@ -93,7 +101,52 @@ #error Unknown MCU #endif +#ifdef SIGNED_FW +// The following is the layout of the extended init packet if using image length and sha256 to validate image +// and NIST P-256 + SHA256 to sign the init_package including the extended part +#define DFU_INIT_PACKET_POS_EXT_IDENTIFIER 0 //< Position of the identifier for the ext package +#define DFU_INIT_PACKET_POS_EXT_IMAGE_LENGTH 4 //< Position of the image length +#define DFU_INIT_PACKET_POS_EXT_IMAGE_HASH256 8 //< Position of the 256 +#define DFU_INIT_PACKET_POS_EXT_INIT_SIGNATURE_R 40 //< Position of the Signature R +#define DFU_INIT_PACKET_POS_EXT_INIT_SIGNATURE_S 72 //< Position of the Signature S +#define DFU_INIT_PACKET_EXT_LENGTH_SIGNED 40 //< Length of the extended init packet that is part of the signed data +#define DFU_INIT_PACKET_EXT_BEGIN + +#define DFU_SHA256_DIGEST_LENGTH 32 //< Length of SHA-256 digest +#define DFU_SIGNATURE_R_LENGTH 32 //< Length of the signature part r +#define DFU_SIGNATURE_S_LENGTH 32 //< Length of the signature part s + +#define DFU_INIT_PACKET_USES_CRC16 (0) +#define DFU_INIT_PACKET_USES_HASH (1) +#define DFU_INIT_PACKET_USES_ECDS (2) + +#if !defined(SIGNED_FW_QX) || !defined(SIGNED_FW_QY) +# error Missing definitions for SIGNED_FW_QX and/or SIGNED_FW_QY required for signed firmware verification +#endif + +/** @snippet [DFU BLE Signing public key curve points] */ +static const uint8_t pk[] = { + /* x-coord : static uint8_t Qx[] = {*/ + SIGNED_FW_QX + /* 0x39, 0xb0, 0x58, 0x3d, 0x27, 0x07, 0x91, 0x38, + 0x6a, 0xa3, 0x36, 0x0f, 0xa2, 0xb5, 0x86, 0x7e, + 0xae, 0xba, 0xf7, 0xa3, 0xf4, 0x81, 0x5f, 0x78, + 0x02, 0xf2, 0xa1, 0x21, 0xd5, 0x21, 0x84, 0x12 */ + /* };*/ + , + /* y-coord : static uint8_t Qy[] = {*/ + SIGNED_FW_QY + /* 0x4a, 0x0d, 0xfe, 0xa4, 0x77, 0x50, 0xb1, 0xb5, 0x26, 0xc0, 0x9d, 0xdd, 0xf0, 0x24, 0x90, 0x57, 0x6c, 0x64, 0x3b, 0xd3, 0xdf, 0x92, 0x3b, 0xb3, 0x47, 0x97, 0x83, 0xd4, 0xfc, 0x76, 0xf5, 0x9d */ + /* };*/ +}; +/** @snippet [DFU BLE Signing public key curve points] */ + +// Helper macros for stringification +//#define VSTRINGIFY(...) #__VA_ARGS__ +//#define TO_STRING(...) VSTRINGIFY(__VA_ARGS__) +//#pragma message ("Qx: " TO_STRING(SIGNED_FW_QX)) +//#pragma message ("Qy: " TO_STRING(SIGNED_FW_QY)) #define DFU_INIT_PACKET_EXT_LENGTH_MIN 2 //< Minimum length of the extended init packet. The extended init packet may contain a CRC, a HASH, or other data. This value must be changed according to the requirements of the system. The template uses a minimum value of two in order to hold a CRC. */ #define DFU_INIT_PACKET_EXT_LENGTH_MAX 10 //< Maximum length of the extended init packet. The extended init packet may contain a CRC, a HASH, or other data. This value must be changed according to the requirements of the system. The template uses a maximum value of 10 in order to hold a CRC and any padded data on transport layer without overflow. */ @@ -101,114 +154,176 @@ static uint8_t m_extended_packet[DFU_INIT_PACKET_EXT_LENGTH_MAX]; //< Data array for storage of the extended data received. The extended data follows the normal init data of type \ref dfu_init_packet_t. Extended data can be used for a CRC, hash, signature, or other data. */ static uint8_t m_extended_packet_length; //< Length of the extended data received with init packet. */ - uint32_t dfu_init_prevalidate(uint8_t * p_init_data, uint32_t init_data_len, uint8_t image_type) { - uint32_t i = 0; - - // In order to support signing or encryption then any init packet decryption function / library - // should be called from here or implemented at this location. + uint32_t i = 0; + + // In order to support signing or encryption then any init packet decryption function / library + // should be called from here or implemented at this location. - // Length check to ensure valid data are parsed. - if (init_data_len < sizeof(dfu_init_packet_t)) - { - return NRF_ERROR_INVALID_LENGTH; - } + // Length check to ensure valid data are parsed. + if (init_data_len < sizeof(dfu_init_packet_t)) + { + return NRF_ERROR_INVALID_LENGTH; + } - // Current template uses clear text data so they can be casted for pre-check. - dfu_init_packet_t * p_init_packet = (dfu_init_packet_t *)p_init_data; + // Current template uses clear text data so they can be casted for pre-check. + dfu_init_packet_t * p_init_packet = (dfu_init_packet_t *)p_init_data; - m_extended_packet_length = ((uint32_t)p_init_data + init_data_len) - - (uint32_t)&p_init_packet->softdevice[p_init_packet->softdevice_len]; - if (m_extended_packet_length < DFU_INIT_PACKET_EXT_LENGTH_MIN) - { - return NRF_ERROR_INVALID_LENGTH; - } + m_extended_packet_length = ((uint32_t)p_init_data + init_data_len) - + (uint32_t)&p_init_packet->softdevice[p_init_packet->softdevice_len]; + if (m_extended_packet_length < DFU_INIT_PACKET_EXT_LENGTH_MIN) + { + return NRF_ERROR_INVALID_LENGTH; + } - if (((uint32_t)p_init_data + init_data_len) < - (uint32_t)&p_init_packet->softdevice[p_init_packet->softdevice_len]) - { - return NRF_ERROR_INVALID_LENGTH; - } + if (((uint32_t)p_init_data + init_data_len) < + (uint32_t)&p_init_packet->softdevice[p_init_packet->softdevice_len]) + { + return NRF_ERROR_INVALID_LENGTH; + } - memcpy(m_extended_packet, - &p_init_packet->softdevice[p_init_packet->softdevice_len], - m_extended_packet_length); + memcpy(m_extended_packet, + &p_init_packet->softdevice[p_init_packet->softdevice_len], + m_extended_packet_length); - /** [DFU init application version] */ - // To support application versioning, this check should be updated. - // This template allows for any application to be installed. However, - // customers can place a revision number at the bottom of the application - // to be verified by the bootloader. This can be done at a location - // relative to the application, for example the application start - // address + 0x0100. - /** [DFU init application version] */ - - // First check to verify the image to be transfered matches the device type. - // If no Device type is present in DFU_DEVICE_INFO then any image will be accepted. + /** [DFU init application version] */ + // To support application versioning, this check should be updated. + // This template allows for any application to be installed. However, + // customers can place a revision number at the bottom of the application + // to be verified by the bootloader. This can be done at a location + // relative to the application, for example the application start + // address + 0x0100. + /** [DFU init application version] */ + + // First check to verify the image to be transfered matches the device type. + // If no Device type is present in DFU_DEVICE_INFO then any image will be accepted. // if ((DFU_DEVICE_INFO->device_type != DFU_DEVICE_TYPE_EMPTY) && // (p_init_packet->device_type != DFU_DEVICE_INFO->device_type)) // { // return NRF_ERROR_INVALID_DATA; // } - - // Second check to verify the image to be transfered matches the device revision. - // If no Device revision is present in DFU_DEVICE_INFO then any image will be accepted. - // if ((DFU_DEVICE_INFO->device_rev != DFU_DEVICE_REVISION_EMPTY) && - // (p_init_packet->device_rev != DFU_DEVICE_INFO->device_rev)) + + // Second check to verify the image to be transfered matches the device revision. + // If no Device revision is present in DFU_DEVICE_INFO then any image will be accepted. + // if ((DFU_DEVICE_INFO->device_rev != DFU_DEVICE_REVISION_EMPTY) && + // (p_init_packet->device_rev != DFU_DEVICE_INFO->device_rev)) - if ( p_init_packet->device_type != ADAFRUIT_DEVICE_TYPE ) - { - return NRF_ERROR_FORBIDDEN; - } + if ( p_init_packet->device_type != ADAFRUIT_DEVICE_TYPE ) + { + return NRF_ERROR_FORBIDDEN; + } - // Adafruit unlock code must match to upgrade SoftDevice and/or Bootloader - if ( image_type & (DFU_UPDATE_SD | DFU_UPDATE_BL) ) - { - if (p_init_packet->device_rev != ADAFRUIT_DEV_REV) - { - return NRF_ERROR_FORBIDDEN; - } - } + // Adafruit unlock code must match to upgrade SoftDevice and/or Bootloader + if ( image_type & (DFU_UPDATE_SD | DFU_UPDATE_BL) ) + { + if (p_init_packet->device_rev != ADAFRUIT_DEV_REV) + { + return NRF_ERROR_FORBIDDEN; + } + } - // Third check: Check the array of supported SoftDevices by this application. - // If the installed SoftDevice does not match any SoftDevice in the list then an - // error is returned. - while (i < p_init_packet->softdevice_len) - { - if (p_init_packet->softdevice[i] == DFU_SOFTDEVICE_ANY || - p_init_packet->softdevice[i++] == SD_FWID_GET(MBR_SIZE)) - { - return NRF_SUCCESS; - } - } - - // No matching SoftDevice found - Return NRF_ERROR_INVALID_DATA. - return NRF_ERROR_INVALID_DATA; + // Third check: Check the array of supported SoftDevices by this application. + // If the installed SoftDevice does not match any SoftDevice in the list then an + // error is returned. + while (i < p_init_packet->softdevice_len) + { + if (p_init_packet->softdevice[i] == DFU_SOFTDEVICE_ANY || + p_init_packet->softdevice[i] == SD_FWID_GET(MBR_SIZE)) + { + // Found a match. Break the loop. + break; + } + ++i; + } + + // No matching SoftDevice found - Return NRF_ERROR_INVALID_DATA. + if (i >= p_init_packet->softdevice_len) + return NRF_ERROR_INVALID_DATA; + +#ifndef SIGNED_FW + return NRF_SUCCESS; +#else + // Check that we have the correct identifier indicating that ECDS is used + if(*(uint32_t*)&m_extended_packet[DFU_INIT_PACKET_POS_EXT_IDENTIFIER] != DFU_INIT_PACKET_USES_ECDS) + { + return NRF_ERROR_INVALID_DATA; + } + + uint8_t* msg = p_init_data; + size_t msg_len = (init_data_len - m_extended_packet_length) + DFU_INIT_PACKET_EXT_LENGTH_SIGNED; + + // Create a sha256 digest + struct tc_sha256_state_struct state = {0}; + uint8_t digest[TC_SHA256_DIGEST_SIZE]; + if (tc_sha256_init(&state) != TC_CRYPTO_SUCCESS) return NRF_ERROR_INVALID_DATA; + if (tc_sha256_update(&state,msg,msg_len) != TC_CRYPTO_SUCCESS) return NRF_ERROR_INVALID_DATA; + if (tc_sha256_final(digest,&state) != TC_CRYPTO_SUCCESS) return NRF_ERROR_INVALID_DATA; + + // And verify signature + const struct uECC_Curve_t * curve = uECC_secp256r1(); + if (uECC_valid_public_key(pk, curve) != 0) + return NRF_ERROR_INVALID_DATA; + + if (uECC_valid_public_key(pk, curve) != 0) + return NRF_ERROR_INVALID_DATA; + + unsigned char* sig = &m_extended_packet[DFU_INIT_PACKET_POS_EXT_INIT_SIGNATURE_R]; +# if (DFU_INIT_PACKET_POS_EXT_INIT_SIGNATURE_S - DFU_INIT_PACKET_POS_EXT_INIT_SIGNATURE_R) != DFU_SIGNATURE_R_LENGTH +# error Incorrect layout: r and s must be contiguous! +# endif + + return uECC_verify(pk, digest, sizeof(digest), sig, curve) == 1 ? NRF_SUCCESS : NRF_ERROR_INVALID_DATA; +#endif } uint32_t dfu_init_postvalidate(uint8_t * p_image, uint32_t image_len) { - uint16_t image_crc; - uint16_t received_crc; - - // In order to support hashing (and signing) then the (decrypted) hash should be fetched and - // the corresponding hash should be calculated over the image at this location. - // If hashing (or signing) is added to the system then the CRC validation should be removed. +#ifndef SIGNED_FW + uint16_t image_crc; + uint16_t received_crc; + + // calculate CRC from active block. + image_crc = crc16_compute(p_image, image_len, NULL); - // calculate CRC from active block. - image_crc = crc16_compute(p_image, image_len, NULL); + // Decode the received CRC from extended data. + received_crc = uint16_decode((uint8_t *)&m_extended_packet[0]); - // Decode the received CRC from extended data. - received_crc = uint16_decode((uint8_t *)&m_extended_packet[0]); + // Compare the received and calculated CRC. + if (image_crc != received_crc) + { + return NRF_ERROR_INVALID_DATA; + } - // Compare the received and calculated CRC. - if (image_crc != received_crc) - { - return NRF_ERROR_INVALID_DATA; - } + return NRF_SUCCESS; + +#else + + // Compare image size received with signed init_packet data + if(image_len != *(uint32_t*)&m_extended_packet[DFU_INIT_PACKET_POS_EXT_IMAGE_LENGTH]) + { + return NRF_ERROR_INVALID_DATA; + } - return NRF_SUCCESS; + uint8_t image_digest[DFU_SHA256_DIGEST_LENGTH]; + uint8_t * received_digest; + + // Create a sha256 digest + struct tc_sha256_state_struct state = {0}; + if (tc_sha256_init(&state) != TC_CRYPTO_SUCCESS) return NRF_ERROR_INVALID_DATA; + if (tc_sha256_update(&state, p_image, image_len) != TC_CRYPTO_SUCCESS) return NRF_ERROR_INVALID_DATA; + if (tc_sha256_final(image_digest, &state) != TC_CRYPTO_SUCCESS) return NRF_ERROR_INVALID_DATA; + + received_digest = &m_extended_packet[DFU_INIT_PACKET_POS_EXT_IMAGE_HASH256]; + + // Compare the received and calculated digests. + if (memcmp(&image_digest[0], received_digest, DFU_SHA256_DIGEST_LENGTH) != 0) + { + return NRF_ERROR_INVALID_DATA; + } + + return NRF_SUCCESS; +#endif } diff --git a/src/main.c b/src/main.c index 3909651..a5110ba 100644 --- a/src/main.c +++ b/src/main.c @@ -411,6 +411,10 @@ static uint32_t ble_stack_init(void) { return NRF_SUCCESS; } +/*------------------------------------------------------------------*/ +/* SoftDevice Event handler + *------------------------------------------------------------------*/ + // Process BLE event from SD uint32_t proc_ble(void) { __ALIGN(4) uint8_t ev_buf[BLE_EVT_LEN_MAX(BLEGATT_ATT_MTU_MAX)]; diff --git a/src/usb/tusb_config.h b/src/usb/tusb_config.h index b76c87b..e75a63d 100644 --- a/src/usb/tusb_config.h +++ b/src/usb/tusb_config.h @@ -53,7 +53,9 @@ //------------- Class enabled -------------// #define CFG_TUD_CDC 1 +#if !defined(SIGNED_FW) || defined(FORCE_UF2) #define CFG_TUD_MSC 1 +#endif /*------------------------------------------------------------------*/ /* CLASS DRIVER diff --git a/src/usb/usb.c b/src/usb/usb.c index 30d91c0..331a9f9 100644 --- a/src/usb/usb.c +++ b/src/usb/usb.c @@ -94,7 +94,9 @@ void usb_init(bool cdc_only) { } usb_desc_init(cdc_only); +#if !defined(SIGNED_FW) || defined(FORCE_UF2) uf2_init(); +#endif tusb_init(); #ifdef DISPLAY_PIN_SCK diff --git a/src/usb/usb_desc.c b/src/usb/usb_desc.c index ac1a8ac..25c9b1d 100644 --- a/src/usb/usb_desc.c +++ b/src/usb/usb_desc.c @@ -30,11 +30,15 @@ enum { STRID_PRODUCT , STRID_SERIAL , STRID_CDC , +#if !defined(SIGNED_FW) || defined(FORCE_UF2) STRID_MSC +#endif }; +#if !defined(SIGNED_FW) || defined(FORCE_UF2) // CDC + MSC or CDC only mode static bool _cdc_only = false; +#endif // Serial is 64-bit DeviceID -> 16 chars len static char desc_str_serial[1+16]; @@ -84,6 +88,7 @@ enum { ITF_NUM_TOTAL }; +#if !defined(SIGNED_FW) || defined(FORCE_UF2) uint8_t desc_configuration_cdc_msc[] = { // Interface count, string index, total length, attribute, power in mA @@ -95,6 +100,7 @@ uint8_t desc_configuration_cdc_msc[] = // Interface number, string index, EP Out & EP In address, EP size TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, STRID_MSC, 0x03, 0x83, 64), }; +#endif uint8_t desc_configuration_cdc_only[] = { @@ -112,19 +118,27 @@ uint8_t desc_configuration_cdc_only[] = uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { (void) index; // for multiple configurations +#if !defined(SIGNED_FW) || defined(FORCE_UF2) return _cdc_only ? desc_configuration_cdc_only : desc_configuration_cdc_msc; +#else + return desc_configuration_cdc_only; +#endif } // Enumerate as CDC + MSC or CDC only void usb_desc_init(bool cdc_only) { +#if !defined(SIGNED_FW) || defined(FORCE_UF2) _cdc_only = cdc_only; if ( cdc_only ) { +#endif // Change PID to CDC only desc_device.idProduct = USB_DESC_CDC_ONLY_PID; +#if !defined(SIGNED_FW) || defined(FORCE_UF2) } +#endif // Create Serial string descriptor uint8_t const* device_id = (uint8_t const*) &NRF_FICR->DEVICEID; @@ -154,7 +168,9 @@ char const* string_desc_arr [] = BLEDIS_MODEL, // 2: Product desc_str_serial, // 3: Serials, should use chip ID "nRF Serial", // 4: CDC Interface +#if !defined(SIGNED_FW) || defined(FORCE_UF2) "nRF UF2", // 5: MSC Interface +#endif }; // up to 64 unicode characters From 01290c728bfca9ba48779844cf37117c5f9add2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Jos=C3=A9=20Tagle?= Date: Thu, 15 Jan 2026 02:35:05 -0300 Subject: [PATCH 83/90] Improved documentation on dual bank and signed bootloader --- README.md | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8fda77a..611c63d 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,8 @@ In addition, there is also lots of other 3rd-party boards which are added by oth - Self-upgradable via Serial and OTA - DFU using UF2 (https://github.com/Microsoft/uf2) (application only) - Auto-enter DFU briefly on startup for DTR auto-reset trick (832 only) +- Supports dual bank firmware updates (disabled by default) +- Supports signed firmware updates (disabled by default) ## How to use @@ -101,7 +103,7 @@ Pre-builtin binaries are available on GitHub [releases](https://github.com/adafr Note: The bootloader can be downgraded. Since the binary release is a merged version of both bootloader and the Nordic SoftDevice, you can freely upgrade/downgrade to any version you like. -## How to compile and build +## How to compile and build You should only continue if you are looking to develop bootloader for your own. You must have have a J-Link available to "unbrick" your device. @@ -206,6 +208,57 @@ To flash MBR only make BOARD=feather_nrf52840_express flash-mbr ``` +### Dual bank firmware support: + +This bootloader can split the FLASH memory into 2 partitions, one for the last successfully uploaded firmware, and the other for the new firmware that is being uploaded. In case the firmware upload fails, the bootloader will revert to the last working firmware version. The only drawback is that the maximum firmware size is half of the device FLASH size: That is why it is disabled by default. +You can enable this feature by passing DUALBANK_FW=1 to the make process while compiling the bootloader + +### Signed firmware support: +This bootloader can validate that the uploaded firmware is digitally signed, and refuse to install unsigned or signed with the improper key firmware. Because this will make Arduino uploads stop working (because they are not digitally signed), this feature is disabled by default. +But if you want to ensure noone else is allowed to upload firmware to your device, this option is probably what you want to enable. + +To create a signing key, you will need the adafruit-nrfutil utility. First, generate a signing key and store at given path by using + +``` +adafruit-nrfutil keys --gen-key stored_key.pem +``` + +This command will create a signing key and store it in the file stored_key.pem. STORE THIS FILE IN A SAFE PLACE, as without it, you won't be able to sign your firmware packages, and the bootloader will refuse to flash them!! + +Now, you must show the verification key (that is calculated from the signing key): + +``` +adafruit-nrfutil keys --show-vk code stored_key.pem +``` + +This command will read your signing key (from the file stored_key.pem) and display C source code with the Qx and Qy arrays: Something along the lines + +``` +static uint8_t Qx[] = { ... }; +static uint8_t Qy[] = { ... }; +``` + +You must save thw Qx and Qy values, remove all spaces, an pass them to the make command line +``` +make BOARD=feather_nrf52840_express SIGNED_FW=1 SIGNED_FW_QX='Qx values' SIGNED_FW_QY='Qy values' +``` + +And replace Qx values with the Qx array values, and the Qy values with the Qy array values. That will create a bootloader that ONLY accepts firmware signed with the stored_key.pem signing key. Take into account that the option SIGNED_FW=1 is what enables to build a bootloader that enforces signing, and will ALSO result in disabling UF2 support, as UF2 format does NOT support signing keys. There is an option (only for testing!) called FORCE_UF2 that will FORCE UF2 support on bootloaders that enforce firmware security. It is there to bypass security so you can test a secure bootloader and have a way to recover it something goes wrong, but should NEVER be used if you want to enforce security + +Finally, to create a signed firmware application/bootloader update package, you can use, for example + +``` +adafruit-nrfutil dfu genpkg --dev-type 0x0052 --sd-req 0x0123 --application "application.hex" --key-file "stored_key.pem" "application_package.zip" +``` + +Please, use full paths for all files. The examples omit them for clarity! + +And, to upload it to your device, + +``` +adafruit-nrfutil.exe --verbose dfu serial -pkg "application_package.zip" -p /dev/tty0 -b 115200 +``` + ### Common makefile problems #### `arm-none-eabi-gcc`: No such file or directory From 33070836f9a98311f02ddf522f0dbe88a150ee83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Jos=C3=A9=20Tagle?= Date: Thu, 15 Jan 2026 02:38:13 -0300 Subject: [PATCH 84/90] Add missing tinycrypt dependency --- lib/tinycrypt | 1 + 1 file changed, 1 insertion(+) create mode 160000 lib/tinycrypt diff --git a/lib/tinycrypt b/lib/tinycrypt new file mode 160000 index 0000000..cf24c90 --- /dev/null +++ b/lib/tinycrypt @@ -0,0 +1 @@ +Subproject commit cf24c907a61c01bc2c4e1ee0ae24457c27a840a2 From 0623a20120da328edec15600d0f4947d3339a7da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Jos=C3=A9=20Tagle?= Date: Thu, 15 Jan 2026 02:51:01 -0300 Subject: [PATCH 85/90] Fixed compilation --- src/dfu_init.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/dfu_init.c b/src/dfu_init.c index c848d26..ae6244f 100644 --- a/src/dfu_init.c +++ b/src/dfu_init.c @@ -148,8 +148,12 @@ static const uint8_t pk[] = { //#pragma message ("Qx: " TO_STRING(SIGNED_FW_QX)) //#pragma message ("Qy: " TO_STRING(SIGNED_FW_QY)) -#define DFU_INIT_PACKET_EXT_LENGTH_MIN 2 //< Minimum length of the extended init packet. The extended init packet may contain a CRC, a HASH, or other data. This value must be changed according to the requirements of the system. The template uses a minimum value of two in order to hold a CRC. */ -#define DFU_INIT_PACKET_EXT_LENGTH_MAX 10 //< Maximum length of the extended init packet. The extended init packet may contain a CRC, a HASH, or other data. This value must be changed according to the requirements of the system. The template uses a maximum value of 10 in order to hold a CRC and any padded data on transport layer without overflow. */ +_Static_assert(sizeof(pk) == 64, "Public key must be 64 bytes in size"); + +#endif + +#define DFU_INIT_PACKET_EXT_LENGTH_MIN 2 //< Minimum length of the extended init packet. Init packet and CRC16 +#define DFU_INIT_PACKET_EXT_LENGTH_MAX 104 //< Identifier (4 bytes) + Image length (4 bytes) + SHA-256 digest (32 bytes) + NIST P-256 using SHA-256 (64 bytes) static uint8_t m_extended_packet[DFU_INIT_PACKET_EXT_LENGTH_MAX]; //< Data array for storage of the extended data received. The extended data follows the normal init data of type \ref dfu_init_packet_t. Extended data can be used for a CRC, hash, signature, or other data. */ static uint8_t m_extended_packet_length; //< Length of the extended data received with init packet. */ From 6b5158a6827b22d49cbf4ed684a13be0e01d6ecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Jos=C3=A9=20Tagle?= Date: Thu, 15 Jan 2026 15:31:16 -0300 Subject: [PATCH 86/90] Removed redundant call to verify if the supplied public key is valid --- src/dfu_init.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/dfu_init.c b/src/dfu_init.c index ae6244f..612fed9 100644 --- a/src/dfu_init.c +++ b/src/dfu_init.c @@ -269,9 +269,6 @@ uint32_t dfu_init_prevalidate(uint8_t * p_init_data, uint32_t init_data_len, uin if (uECC_valid_public_key(pk, curve) != 0) return NRF_ERROR_INVALID_DATA; - if (uECC_valid_public_key(pk, curve) != 0) - return NRF_ERROR_INVALID_DATA; - unsigned char* sig = &m_extended_packet[DFU_INIT_PACKET_POS_EXT_INIT_SIGNATURE_R]; # if (DFU_INIT_PACKET_POS_EXT_INIT_SIGNATURE_S - DFU_INIT_PACKET_POS_EXT_INIT_SIGNATURE_R) != DFU_SIGNATURE_R_LENGTH # error Incorrect layout: r and s must be contiguous! From 16477539d9ec7d40e57eaa8d571239bf9b77b8d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Jos=C3=A9=20Tagle?= Date: Thu, 15 Jan 2026 15:43:59 -0300 Subject: [PATCH 87/90] Fix autodetection of workarounds for GCC 12.x 13.x and 14.x under Windows --- Makefile | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 45dc1df..0c9ccd6 100644 --- a/Makefile +++ b/Makefile @@ -41,6 +41,15 @@ SD_HEX = $(SD_PATH)/$(SD_FILENAME)_softdevice.hex MBR_HEX = lib/softdevice/mbr/hex/mbr_nrf52_2.4.1_mbr.hex +# Detect the operating system +# The "OS" environment variable on Windows is always "Windows_NT" +# when running under a modern shell like cmd.exe or powershell +ifeq ($(OS),Windows_NT) + NULL_DEVICE = NUL +else + NULL_DEVICE = /dev/null +endif + # linker by MCU eg. nrf52840.ld ifeq ($(DEBUG), 1) LD_FILE = linker/$(MCU_SUB_VARIANT)_debug.ld @@ -385,9 +394,9 @@ CFLAGS += -DDFU_APP_DATA_RESERVED=$(DFU_APP_DATA_RESERVED) # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105523 # Fixes for gcc version 12, 13 and 14. -#ifneq (,$(filter 12.% 13.% 14.%,$(shell $(CC) -dumpversion 2>/dev/null))) +ifneq (,$(filter 12.% 13.% 14.%,$(shell $(CC) -dumpversion 2>$(NULL_DEVICE)))) CFLAGS += --param=min-pagesize=0 -#endif +endif #------------------------------------------------------------------------------ # Linker Flags From 827edd212b9560cd8994576848b76f85da3aad1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Jos=C3=A9=20Tagle?= Date: Thu, 15 Jan 2026 19:14:41 -0300 Subject: [PATCH 88/90] Bumped SLAVE_LATENCY to 4. Does not make any difference in our tests, but https://stackoverflow.com/questions/32588325/ios-bluetooth-le-code-6-the-connection-has-timed-out-unexpectedly suggests this is the best to solve the ConnectionTimedOutUnexpectedly on IOS --- .../components/libraries/bootloader_dfu/dfu_transport_ble.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c b/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c index 06017a9..08893d0 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c @@ -52,7 +52,7 @@ enum { BLE_CONN_CFG_HIGH_BANDWIDTH = 1 }; #define MIN_CONN_INTERVAL (uint16_t)(MSEC_TO_UNITS(15, UNIT_1_25_MS)) /**< Minimum acceptable connection interval (11.25 milliseconds). */ #define MAX_CONN_INTERVAL (uint16_t)(MSEC_TO_UNITS(30, UNIT_1_25_MS)) /**< Maximum acceptable connection interval (15 milliseconds). */ -#define SLAVE_LATENCY 0 /**< Slave latency. */ +#define SLAVE_LATENCY 4 /**< Slave latency. */ #define CONN_SUP_TIMEOUT MSEC_TO_UNITS(8000, UNIT_10_MS) /**< Connection supervisory timeout (4 seconds). */ #define SPEEDUP_FLASH_WRITES 1 /**< Speedup FLASH writes by changing Softdevice local latency */ From 3e87e079213cc09a37df5059690bf61856c16a71 Mon Sep 17 00:00:00 2001 From: Ha Thach Date: Wed, 21 Jan 2026 09:06:12 +0700 Subject: [PATCH 89/90] fix typo Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- README.md | 2 +- .../libraries/bootloader_dfu/dfu_dual_bank.c | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 611c63d..583f6d3 100644 --- a/README.md +++ b/README.md @@ -238,7 +238,7 @@ static uint8_t Qx[] = { ... }; static uint8_t Qy[] = { ... }; ``` -You must save thw Qx and Qy values, remove all spaces, an pass them to the make command line +You must save the Qx and Qy values, remove all spaces, and pass them to the make command line ``` make BOARD=feather_nrf52840_express SIGNED_FW=1 SIGNED_FW_QX='Qx values' SIGNED_FW_QY='Qy values' ``` diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_dual_bank.c b/lib/sdk11/components/libraries/bootloader_dfu/dfu_dual_bank.c index 4516e4f..1bbeffa 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_dual_bank.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_dual_bank.c @@ -29,7 +29,7 @@ static dfu_state_t m_dfu_state; /**< Current DFU static uint32_t m_image_size; /**< Size of the image that will be transmitted. */ static dfu_start_packet_t m_start_packet; /**< Start packet received for this update procedure. Contains update mode and image sizes information to be used for image transfer. */ -static uint8_t m_init_packet[128]; /**< Init packet, can hold CRC, Hash, Signed Hash and similar, for image validation, integrety check and authorization checking. */ +static uint8_t m_init_packet[128]; /**< Init packet, can hold CRC, Hash, Signed Hash and similar, for image validation, integrity check and authorization checking. */ static uint8_t m_init_packet_length; /**< Length of init packet received. */ static uint16_t m_image_crc; /**< Calculated CRC of the image received. */ @@ -200,8 +200,8 @@ static void dfu_cleared_func_app(void) /**@brief Function for calculating storage offset for receiving SoftDevice image. * * @details When a new SoftDevice is received it will be temporary stored in flash before moved to - * address 0x0. In order to succesfully validate transfer and relocation it is important - * that temporary image and final installed image does not ovwerlap hence an offset must + * address 0x0. In order to successfully validate transfer and relocation it is important + * that temporary image and final installed image does not overlap hence an offset must * be calculated in case new image is larger than currently installed SoftDevice. */ uint32_t offset_calculate(uint32_t sd_image_size) @@ -253,7 +253,7 @@ static uint32_t dfu_activate_sd(void) /**@brief Function for activating received Application image. * - * @details This function will move the received application image fram swap (bank 1) to + * @details This function will move the received application image from swap (bank 1) to * application area (bank 0). * * @return NRF_SUCCESS on success. Error code otherwise. @@ -606,7 +606,7 @@ uint32_t dfu_image_validate() // Check if the application image write has finished. if (m_data_received != m_image_size) { - // Image not yet fully transfered by the peer or the peer has attempted to write + // Image not yet fully transferred by the peer or the peer has attempted to write // too much data. Hence the validation should fail. err_code = NRF_ERROR_INVALID_STATE; } @@ -701,8 +701,8 @@ static uint32_t dfu_sd_img_block_swap(uint32_t * src, uint32_t len, uint32_t block_size) { - // It is neccesarry to swap the new SoftDevice in 3 rounds to ensure correct copy of data - // and verifucation of data in case power reset occurs during write to flash. + // It is necessary to swap the new SoftDevice in 3 rounds to ensure correct copy of data + // and verification of data in case power reset occurs during write to flash. // To ensure the robustness of swapping the images are compared backwards till start of // image swap. If the back is identical everything is swapped. uint32_t err_code = dfu_compare_block(src, dst, len); @@ -810,7 +810,7 @@ uint32_t dfu_bl_image_swap(void) uint32_t dfu_bl_image_validate(void) { - bootloader_settings_t bootloader_settings;\ + bootloader_settings_t bootloader_settings; sd_mbr_command_t sd_mbr_cmd_1; sd_mbr_command_t sd_mbr_cmd_2; From 3c4470889b52052e9b420aa536adc5f43f412898 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 23 Jan 2026 14:30:58 +0700 Subject: [PATCH 90/90] minor clean up and fix dfu_bl_image_validate() return nrf error code --- CMakeLists.txt | 49 ++++++++++++++- README.md | 6 +- .../ble/ble_services/ble_dfu/ble_dfu.c | 11 +--- .../libraries/bootloader_dfu/dfu_dual_bank.c | 7 ++- .../bootloader_dfu/dfu_single_bank.c | 7 ++- .../bootloader_dfu/dfu_transport_ble.c | 61 +++++++++---------- src/main.c | 46 +++++++------- src/sdk_config.h | 8 ++- src/usb/usb.c | 2 +- src/usb/usb_desc.c | 17 +++--- 10 files changed, 132 insertions(+), 82 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 401acc2..5b50cfd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,13 @@ set(SDK_DIR ${CMAKE_CURRENT_LIST_DIR}/lib/sdk/components) set(SOFTDEVICE_DIR ${CMAKE_CURRENT_LIST_DIR}/lib/softdevice) set(MBR_HEX ${SOFTDEVICE_DIR}/mbr/hex/mbr_nrf52_2.4.1_mbr.hex) set(TINYUSB_DIR ${CMAKE_CURRENT_LIST_DIR}/lib/tinyusb/src) +set(TCRYPT_DIR ${CMAKE_CURRENT_LIST_DIR}/lib/tinycrypt/lib) + +option(SIGNED_FW "Enable signed firmware verification" OFF) +option(DUALBANK_FW "Enable dual bank DFU support" OFF) +option(FORCE_UF2 "Force UF2 support even with SIGNED_FW" OFF) +set(SIGNED_FW_QX "" CACHE STRING "Public key Qx (comma-separated bytes)") +set(SIGNED_FW_QY "" CACHE STRING "Public key Qy (comma-separated bytes)") set(UF2CONV_PY ${CMAKE_CURRENT_LIST_DIR}/lib/uf2/utils/uf2conv.py) set(UF2_FAMILY_ID_BOOTLOADER 0xd663823c) @@ -58,7 +65,6 @@ add_executable(bootloader ${SDK11_DIR}/libraries/bootloader_dfu/bootloader_util.c ${SDK11_DIR}/libraries/bootloader_dfu/dfu_transport_serial.c ${SDK11_DIR}/libraries/bootloader_dfu/dfu_transport_ble.c - ${SDK11_DIR}/libraries/bootloader_dfu/dfu_single_bank.c ${SDK11_DIR}/ble/ble_services/ble_dfu/ble_dfu.c ${SDK11_DIR}/ble/ble_services/ble_dis/ble_dis.c ${SDK11_DIR}/drivers_nrf/pstorage/pstorage_raw.c @@ -75,6 +81,30 @@ add_executable(bootloader # startup ${NRFX_DIR}/mdk/gcc_startup_${MCU_VARIANT}.S ) + +if (DUALBANK_FW) + target_sources(bootloader PUBLIC + ${SDK11_DIR}/libraries/bootloader_dfu/dfu_dual_bank.c + ) +else () + target_sources(bootloader PUBLIC + ${SDK11_DIR}/libraries/bootloader_dfu/dfu_single_bank.c + ) +endif () + +if (SIGNED_FW) + target_sources(bootloader PUBLIC + ${TCRYPT_DIR}/source/sha256.c + ${TCRYPT_DIR}/source/ecc.c + ${TCRYPT_DIR}/source/ecc_dsa.c + ${TCRYPT_DIR}/source/utils.c + ) + + target_include_directories(bootloader PUBLIC + ${TCRYPT_DIR}/include + ) +endif () + target_include_directories(bootloader PUBLIC src src/boards @@ -149,6 +179,23 @@ target_compile_definitions(bootloader PUBLIC __STARTUP_CLEAR_BSS ) +if (SIGNED_FW) + if (SIGNED_FW_QX STREQUAL "" OR SIGNED_FW_QY STREQUAL "") + message(FATAL_ERROR "SIGNED_FW requires SIGNED_FW_QX and SIGNED_FW_QY to be set") + endif () + string(REPLACE " " "" SIGNED_FW_QX_STR "${SIGNED_FW_QX}") + string(REPLACE " " "" SIGNED_FW_QY_STR "${SIGNED_FW_QY}") + target_compile_definitions(bootloader PUBLIC + SIGNED_FW + "SIGNED_FW_QX=${SIGNED_FW_QX_STR}" + "SIGNED_FW_QY=${SIGNED_FW_QY_STR}" + ) +endif () + +if (FORCE_UF2) + target_compile_definitions(bootloader PUBLIC FORCE_UF2) +endif () + if (TRACE_ETM STREQUAL "1") # ENABLE_TRACE will cause system_nrf5x.c to set up ETM trace target_compile_definitions(bootloader PUBLIC ENABLE_TRACE) diff --git a/README.md b/README.md index 583f6d3..8d16b37 100644 --- a/README.md +++ b/README.md @@ -28,13 +28,17 @@ In addition, there is also lots of other 3rd-party boards which are added by oth ## Features -- DFU over Serial and OTA ( application, Bootloader+SD ) +- DFU over Serial and OTA (application, Bootloader+SD) - Self-upgradable via Serial and OTA - DFU using UF2 (https://github.com/Microsoft/uf2) (application only) - Auto-enter DFU briefly on startup for DTR auto-reset trick (832 only) - Supports dual bank firmware updates (disabled by default) - Supports signed firmware updates (disabled by default) +Note: For OTA, `Packet Receipt Notification` (PRN) must be 8 or less, which can be configured in nRF DFU. Otherwise, the +bootloader will run out of +memory. + ## How to use There are two pins, `DFU` and `FRST` that bootloader will check upon reset/power: diff --git a/lib/sdk11/components/ble/ble_services/ble_dfu/ble_dfu.c b/lib/sdk11/components/ble/ble_services/ble_dfu/ble_dfu.c index a630971..a79e4cb 100644 --- a/lib/sdk11/components/ble/ble_services/ble_dfu/ble_dfu.c +++ b/lib/sdk11/components/ble/ble_services/ble_dfu/ble_dfu.c @@ -17,8 +17,7 @@ #include #include "sdk_common.h" -#define DFU_PKT_ENABLE_WR_WO_RESPONSE_ONLY 0 /**< Enable Write Without Response on Data Endpoint ONLY (otherwise both With and Without response will be supported)*/ -#define MAX_DFU_PKT_LEN 244 /**< Maximum length (in bytes) of the DFU Packet characteristic. */ +#define MAX_DFU_PKT_LEN (BLEGATT_ATT_MTU_MAX - 3) /**< Maximum length (in bytes) of the DFU Packet characteristic. */ #define PKT_START_DFU_PARAM_LEN 2 /**< Length (in bytes) of the parameters for Packet Start DFU Request. */ #define PKT_INIT_DFU_PARAM_LEN 2 /**< Length (in bytes) of the parameters for Packet Init DFU Request. */ #define PKT_RCPT_NOTIF_REQ_LEN 3 /**< Length (in bytes) of the Packet Receipt Notification Request. */ @@ -58,12 +57,8 @@ static uint32_t dfu_pkt_char_add(ble_dfu_t * const p_dfu) memset(&char_md, 0, sizeof(char_md)); -#if DFU_PKT_ENABLE_WR_WO_RESPONSE_ONLY - char_md.char_props.write_wo_resp = 1; -#else - char_md.char_props.write = 1; // For those improved apps that can take advantage of ACK - char_md.char_props.write_wo_resp = 1; // Nordic IOS DFU app REQUIRES Write Without Response */ -#endif + char_md.char_props.write = 1; // For those improved apps that can take advantage of ACK + char_md.char_props.write_wo_resp = 1; // Nordic IOS DFU app REQUIRES Write Without Response */ char_md.p_char_user_desc = NULL; char_md.p_char_pf = NULL; char_md.p_user_desc_md = NULL; diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_dual_bank.c b/lib/sdk11/components/libraries/bootloader_dfu/dfu_dual_bank.c index 1bbeffa..94feef1 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_dual_bank.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_dual_bank.c @@ -829,6 +829,11 @@ uint32_t dfu_bl_image_validate(void) sd_mbr_cmd_1.params.compare.ptr2 = (uint32_t *)(bl_image_start_1); sd_mbr_cmd_1.params.compare.len = bootloader_settings.bl_image_size / sizeof(uint32_t); + uint32_t err_code = sd_mbr_command(&sd_mbr_cmd_1); + if (err_code != NRF_SUCCESS) { + return err_code; + } + uint32_t bl_image_start_2 = (bootloader_settings.sd_image_size == 0) ? DFU_BANK_1_REGION_START : bootloader_settings.sd_image_start + @@ -839,7 +844,7 @@ uint32_t dfu_bl_image_validate(void) sd_mbr_cmd_2.params.compare.ptr2 = (uint32_t *)(bl_image_start_2); sd_mbr_cmd_2.params.compare.len = bootloader_settings.bl_image_size / sizeof(uint32_t); - return sd_mbr_command(&sd_mbr_cmd_1) && sd_mbr_command(&sd_mbr_cmd_2); + return sd_mbr_command(&sd_mbr_cmd_2); } return NRF_SUCCESS; } diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c b/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c index bf003c6..5a4677f 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c @@ -752,6 +752,11 @@ uint32_t dfu_bl_image_validate(void) sd_mbr_cmd_1.params.compare.ptr2 = (uint32_t *)(bl_image_start_1); sd_mbr_cmd_1.params.compare.len = bootloader_settings.bl_image_size / sizeof(uint32_t); + uint32_t err_code = sd_mbr_command(&sd_mbr_cmd_1); + if (err_code != NRF_SUCCESS) { + return err_code; + } + uint32_t bl_image_start_2 = (bootloader_settings.sd_image_size == 0) ? DFU_BANK_1_REGION_START : bootloader_settings.sd_image_start + @@ -762,7 +767,7 @@ uint32_t dfu_bl_image_validate(void) sd_mbr_cmd_2.params.compare.ptr2 = (uint32_t *)(bl_image_start_2); sd_mbr_cmd_2.params.compare.len = bootloader_settings.bl_image_size / sizeof(uint32_t); - return sd_mbr_command(&sd_mbr_cmd_1) && sd_mbr_command(&sd_mbr_cmd_2); + return sd_mbr_command(&sd_mbr_cmd_2); } return NRF_SUCCESS; } diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c b/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c index 08893d0..be6b672 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c @@ -35,10 +35,6 @@ #include "nrf_delay.h" #include "sdk_common.h" - -#define BLEGATT_ATT_MTU_MAX 247 -enum { BLE_CONN_CFG_HIGH_BANDWIDTH = 1 }; - #define DFU_REV_MAJOR 0x00 /** DFU Major revision number to be exposed. */ #define DFU_REV_MINOR 0x08 /** DFU Minor revision number to be exposed. */ #define DFU_REVISION ((DFU_REV_MAJOR << 8) | DFU_REV_MINOR) /** DFU Revision number to be exposed. Combined of major and minor versions. */ @@ -54,7 +50,7 @@ enum { BLE_CONN_CFG_HIGH_BANDWIDTH = 1 }; #define MAX_CONN_INTERVAL (uint16_t)(MSEC_TO_UNITS(30, UNIT_1_25_MS)) /**< Maximum acceptable connection interval (15 milliseconds). */ #define SLAVE_LATENCY 4 /**< Slave latency. */ #define CONN_SUP_TIMEOUT MSEC_TO_UNITS(8000, UNIT_10_MS) /**< Connection supervisory timeout (4 seconds). */ -#define SPEEDUP_FLASH_WRITES 1 /**< Speedup FLASH writes by changing Softdevice local latency */ +#define SPEEDUP_FLASH_WRITES 1 /**< Speedup FLASH writes by changing Softdevice local latency */ #define APP_ADV_INTERVAL MSEC_TO_UNITS(25, UNIT_0_625_MS) /**< The advertising interval (25 ms.). */ #define APP_ADV_TIMEOUT BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED /**< The advertising timeout in units of seconds. This is set to @ref BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED so that the advertisement is done as long as there there is a call to @ref dfu_transport_close function.*/ @@ -77,8 +73,9 @@ enum { BLE_CONN_CFG_HIGH_BANDWIDTH = 1 }; #define IS_CONNECTED() (m_conn_handle != BLE_CONN_HANDLE_INVALID) /**< Macro to determine if the device is in connected state. */ -#define APP_FEATURE_NOT_SUPPORTED BLE_GATT_STATUS_ATTERR_APP_BEGIN + 2 /**< Reply when unsupported features are requested. */ -#define SD_IMAGE_SIZE_OFFSET 0 /**< Offset in start packet for the size information for SoftDevice. */ +#define APP_FEATURE_NOT_SUPPORTED \ + (BLE_GATT_STATUS_ATTERR_APP_BEGIN + 2) /**< Reply when unsupported features are requested. */ +#define SD_IMAGE_SIZE_OFFSET 0 /**< Offset in start packet for the size information for SoftDevice. */ #define BL_IMAGE_SIZE_OFFSET 4 /**< Offset in start packet for the size information for bootloader. */ #define APP_IMAGE_SIZE_OFFSET 8 /**< Offset in start packet for the size information for application. */ @@ -210,35 +207,35 @@ static ble_dfu_resp_val_t nrf_err_code_translate(uint32_t err_c } } -static void prioritize_ble_over_flash_writes(void) -{ #ifdef SPEEDUP_FLASH_WRITES - // We set the local latency to 0: That will revert latency to the negotiated one with the host. - // That will increase throughput to the maximum possible - ble_opt_t opt; - varclr(&opt); - opt.gap_opt.local_conn_latency.conn_handle = m_conn_handle;/**< Connection Handle */ - opt.gap_opt.local_conn_latency.requested_latency = 0; /**< Requested local connection latency. */ - opt.gap_opt.local_conn_latency.p_actual_latency = NULL; /**< Pointer to storage for the actual local connection latency (can be set to NULL to skip return value). */ - sd_ble_opt_set(BLE_GAP_OPT_LOCAL_CONN_LATENCY, &opt); -#endif +static void prioritize_ble_over_flash_writes(void) { + // We set the local latency to 0: That will revert latency to the negotiated one with the host. + // That will increase throughput to the maximum possible + ble_opt_t opt; + varclr(&opt); + opt.gap_opt.local_conn_latency.conn_handle = m_conn_handle; /**< Connection Handle */ + opt.gap_opt.local_conn_latency.requested_latency = 0; /**< Requested local connection latency. */ + opt.gap_opt.local_conn_latency.p_actual_latency = + NULL; /**< Pointer to storage for the actual local connection latency (can be set to NULL to skip return value). */ + sd_ble_opt_set(BLE_GAP_OPT_LOCAL_CONN_LATENCY, &opt); } -static void prioritize_flash_writes_over_ble(void) -{ -#ifdef SPEEDUP_FLASH_WRITES - // We set the local latency to the maximum possible: That will make FLASH writes faster, as BLE comms will - // be delayed (even losing RXd packets, but this is the same as a poor connection and will be handled by - // the protocol itself) - ble_opt_t opt; - varclr(&opt); - opt.gap_opt.local_conn_latency.conn_handle = m_conn_handle;/**< Connection Handle */ - opt.gap_opt.local_conn_latency.requested_latency = 50; /**< Requested local connection latency. */ - opt.gap_opt.local_conn_latency.p_actual_latency = NULL; /**< Pointer to storage for the actual local connection latency (can be set to NULL to skip return value). */ - sd_ble_opt_set(BLE_GAP_OPT_LOCAL_CONN_LATENCY, &opt); -#endif +static void prioritize_flash_writes_over_ble(void) { + // We set the local latency to the maximum possible: That will make FLASH writes faster, as BLE comms will + // be delayed (even losing RXd packets, but this is the same as a poor connection and will be handled by + // the protocol itself) + ble_opt_t opt; + varclr(&opt); + opt.gap_opt.local_conn_latency.conn_handle = m_conn_handle; /**< Connection Handle */ + opt.gap_opt.local_conn_latency.requested_latency = 50; /**< Requested local connection latency. */ + opt.gap_opt.local_conn_latency.p_actual_latency = + NULL; /**< Pointer to storage for the actual local connection latency (can be set to NULL to skip return value). */ + sd_ble_opt_set(BLE_GAP_OPT_LOCAL_CONN_LATENCY, &opt); } - +#else + #define prioritize_ble_over_flash_writes() + #define prioritize_flash_writes_over_ble() +#endif /**@brief Function for handling the callback events from the dfu module. * Callbacks are expected when \ref dfu_data_pkt_handle has been executed. * diff --git a/src/main.c b/src/main.c index a5110ba..d428fd7 100644 --- a/src/main.c +++ b/src/main.c @@ -43,9 +43,7 @@ #include "nrfx_power.h" #include "nrfx_pwm.h" -#include "nordic_common.h" #include "sdk_common.h" -#include "dfu_transport.h" #include "bootloader.h" #include "bootloader_util.h" @@ -65,7 +63,6 @@ #include "pstorage_platform.h" #include "nrf_mbr.h" #include "pstorage.h" -#include "nrfx_nvmc.h" #ifdef NRF_USBD @@ -125,15 +122,9 @@ extern void tusb_hal_nrf_power_event(uint32_t event); // DFU_DBL_RESET magic is used to determined which mode is entered #define APP_ASKS_FOR_SINGLE_TAP_RESET() (*((uint32_t*)(DFU_BANK_0_REGION_START + 0x200)) == 0x87eeb07c) -// These value must be the same with one in dfu_transport_ble.c #define BLEGAP_EVENT_LENGTH 12 -#define BLEGATT_ATT_MTU_MAX 247 #define BLEGATTS_HVN_QSIZE 12 -#define BLEGATTC_WRCMD_QSIZE 2 - -enum { - BLE_CONN_CFG_HIGH_BANDWIDTH = 1 -}; +#define BLEGATTC_WRCMD_QSIZE 2 //--------------------------------------------------------------------+ // @@ -230,8 +221,8 @@ int main(void) { } // No application was loaded, reset the system with the OTA DFU update - NRF_POWER->GPREGRET = 0xA8; - + NRF_POWER->GPREGRET = DFU_MAGIC_OTA_RESET; + NVIC_SystemReset(); } @@ -256,14 +247,17 @@ static void check_dfu_mode(void) { (((*dbl_reset_mem) == DFU_DBL_RESET_MAGIC) && reason_reset_pin); // Clear GPREGRET if it is our values - if (dfu_start || dfu_skip) NRF_POWER->GPREGRET = 0; + if (dfu_start || dfu_skip) { + NRF_POWER->GPREGRET = 0; + } // skip dfu entirely - if (dfu_skip) return; + if (dfu_skip) { + return; + } /*------------- Determine DFU mode (Serial, OTA, FRESET or normal) -------------*/ - // DFU button pressed - dfu_start = dfu_start || button_pressed(BUTTON_DFU); + dfu_start = dfu_start || button_pressed(BUTTON_DFU); // DFU button pressed // DFU + FRESET are pressed --> OTA _ota_dfu = _ota_dfu || (button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET)); @@ -271,16 +265,16 @@ static void check_dfu_mode(void) { bool const valid_app = bootloader_app_is_valid(); bool const just_start_app = valid_app && !dfu_start && (*dbl_reset_mem) == DFU_DBL_RESET_APP; - if (!just_start_app && APP_ASKS_FOR_SINGLE_TAP_RESET()) dfu_start = 1; + if (!just_start_app && APP_ASKS_FOR_SINGLE_TAP_RESET()) { + dfu_start = 1; + } // App mode: Double Reset detection or DFU startup for nrf52832 if (!(just_start_app || dfu_start || !valid_app)) { #ifdef NRF52832_XXAA /* Even DFU is not active, we still force an 1000 ms dfu serial mode when startup * to support auto programming from Arduino IDE - * - * Note: Double Reset WONT work with nrf52832 since all its SRAM got cleared with GPIO reset. - */ + * Note: Double Reset WONT work with nrf52832 since all its SRAM got cleared with GPIO reset. */ bootloader_dfu_start(false, DFU_SERIAL_STARTUP_INTERVAL, false); #else // Note: RESETREAS is not clear by bootloader, it should be cleared by application upon init() @@ -414,7 +408,8 @@ static uint32_t ble_stack_init(void) { /*------------------------------------------------------------------*/ /* SoftDevice Event handler *------------------------------------------------------------------*/ - +extern void ble_evt_dispatch(ble_evt_t *p_ble_evt); + // Process BLE event from SD uint32_t proc_ble(void) { __ALIGN(4) uint8_t ev_buf[BLE_EVT_LEN_MAX(BLEGATT_ATT_MTU_MAX)]; @@ -430,8 +425,7 @@ uint32_t proc_ble(void) { // Handle valid event, ignore error if (NRF_SUCCESS == err) { switch (evt->header.evt_id) { - case BLE_GAP_EVT_CONNECTED: - { + case BLE_GAP_EVT_CONNECTED: { // Try to enable 2M phy,if phone allows it ble_gap_phys_t const phys = { @@ -444,6 +438,7 @@ uint32_t proc_ble(void) { led_state(STATE_BLE_CONNECTED); break; } + case BLE_GAP_EVT_DISCONNECTED: _ota_connected = false; led_state(STATE_BLE_DISCONNECTED); @@ -454,7 +449,6 @@ uint32_t proc_ble(void) { } // from dfu_transport_ble - extern void ble_evt_dispatch(ble_evt_t* p_ble_evt); ble_evt_dispatch(evt); } @@ -475,7 +469,9 @@ uint32_t proc_soc(void) { (soc_evt == NRF_EVT_POWER_USB_POWER_READY) ? NRFX_POWER_USB_EVT_READY : (soc_evt == NRF_EVT_POWER_USB_REMOVED) ? NRFX_POWER_USB_EVT_REMOVED : -1; - if (usbevt >= 0) tusb_hal_nrf_power_event((uint32_t) usbevt); + if (usbevt >= 0) { + tusb_hal_nrf_power_event((uint32_t)usbevt); + } #endif } diff --git a/src/sdk_config.h b/src/sdk_config.h index bef8bc7..b61b1f0 100644 --- a/src/sdk_config.h +++ b/src/sdk_config.h @@ -38,8 +38,6 @@ * */ - - #ifndef SDK_CONFIG_H #define SDK_CONFIG_H @@ -119,6 +117,12 @@ #define CRC16_ENABLED 1 #define NRF_STRERROR_ENABLED 1 +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ +#define BLEGATT_ATT_MTU_MAX 247 +#define BLE_CONN_CFG_HIGH_BANDWIDTH 1 + #endif //SDK_CONFIG_H diff --git a/src/usb/usb.c b/src/usb/usb.c index 331a9f9..ecc881b 100644 --- a/src/usb/usb.c +++ b/src/usb/usb.c @@ -94,7 +94,7 @@ void usb_init(bool cdc_only) { } usb_desc_init(cdc_only); -#if !defined(SIGNED_FW) || defined(FORCE_UF2) +#if CFG_TUD_MSC uf2_init(); #endif tusb_init(); diff --git a/src/usb/usb_desc.c b/src/usb/usb_desc.c index 25c9b1d..4db68ec 100644 --- a/src/usb/usb_desc.c +++ b/src/usb/usb_desc.c @@ -30,9 +30,7 @@ enum { STRID_PRODUCT , STRID_SERIAL , STRID_CDC , -#if !defined(SIGNED_FW) || defined(FORCE_UF2) STRID_MSC -#endif }; #if !defined(SIGNED_FW) || defined(FORCE_UF2) @@ -88,7 +86,7 @@ enum { ITF_NUM_TOTAL }; -#if !defined(SIGNED_FW) || defined(FORCE_UF2) +#if CFG_TUD_MSC uint8_t desc_configuration_cdc_msc[] = { // Interface count, string index, total length, attribute, power in mA @@ -118,7 +116,7 @@ uint8_t desc_configuration_cdc_only[] = uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { (void) index; // for multiple configurations -#if !defined(SIGNED_FW) || defined(FORCE_UF2) +#if CFG_TUD_MSC return _cdc_only ? desc_configuration_cdc_only : desc_configuration_cdc_msc; #else return desc_configuration_cdc_only; @@ -128,17 +126,16 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index) // Enumerate as CDC + MSC or CDC only void usb_desc_init(bool cdc_only) { -#if !defined(SIGNED_FW) || defined(FORCE_UF2) - _cdc_only = cdc_only; + (void)cdc_only; // for non MSC build +#if CFG_TUD_MSC + _cdc_only = cdc_only; if ( cdc_only ) - { #endif + { // Change PID to CDC only desc_device.idProduct = USB_DESC_CDC_ONLY_PID; -#if !defined(SIGNED_FW) || defined(FORCE_UF2) } -#endif // Create Serial string descriptor uint8_t const* device_id = (uint8_t const*) &NRF_FICR->DEVICEID; @@ -168,7 +165,7 @@ char const* string_desc_arr [] = BLEDIS_MODEL, // 2: Product desc_str_serial, // 3: Serials, should use chip ID "nRF Serial", // 4: CDC Interface -#if !defined(SIGNED_FW) || defined(FORCE_UF2) +#if CFG_TUD_MSC "nRF UF2", // 5: MSC Interface #endif };