From dec38b1ae49b60cda8ec147c26bc93d14b86436e Mon Sep 17 00:00:00 2001 From: gb88 Date: Tue, 12 Dec 2023 23:33:03 +0100 Subject: [PATCH 01/11] compatible bootloader with Adafruit nRF52 Core --- Dockerfile | 33 +- Makefile | 11 +- boards/Makefile.boards | 75 +- .../arduino-nano-33-ble/s140/include/config.h | 18 + boards/feather-express/s140/include/config.h | 18 + boards/generic/s140/include/config.h | 18 + boards/mdk-usb-dongle/s140/include/config.h | 18 + boards/mdk/s140/include/config.h | 18 + boards/particle-argon/s140/include/config.h | 18 + boards/particle-boron/s140/include/config.h | 18 + boards/particle-xenon/s140/include/config.h | 18 + boards/pca10056/s140/include/config.h | 18 + boards/pca10059/s140/include/config.h | 18 + boards/pitaya-go/s140/include/config.h | 18 + boards/secure_bootloader_gcc_nrf52.ld | 324 ++--- boards/secure_bootloader_gcc_nrf52_debug.ld | 8 +- .../sparkfun-pro-mini/s140/include/config.h | 18 + include/app_config.h | 2 +- include/sdk_config.h | 4 +- main.c | 92 +- .../bootloader/dfu/nrf_dfu_validation.c | 1096 +++++++++++++++++ .../libraries/bootloader/nrf_bootloader.c | 794 ++++++++++++ 22 files changed, 2402 insertions(+), 253 deletions(-) create mode 100644 boards/arduino-nano-33-ble/s140/include/config.h create mode 100644 boards/feather-express/s140/include/config.h create mode 100644 boards/generic/s140/include/config.h create mode 100644 boards/mdk-usb-dongle/s140/include/config.h create mode 100644 boards/mdk/s140/include/config.h create mode 100644 boards/particle-argon/s140/include/config.h create mode 100644 boards/particle-boron/s140/include/config.h create mode 100644 boards/particle-xenon/s140/include/config.h create mode 100644 boards/pca10056/s140/include/config.h create mode 100644 boards/pca10059/s140/include/config.h create mode 100644 boards/pitaya-go/s140/include/config.h create mode 100644 boards/sparkfun-pro-mini/s140/include/config.h create mode 100644 sdk/components/libraries/bootloader/dfu/nrf_dfu_validation.c create mode 100644 sdk/components/libraries/bootloader/nrf_bootloader.c diff --git a/Dockerfile b/Dockerfile index f6bbee6..032208a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,15 +1,16 @@ FROM ubuntu:20.04 LABEL maintainer="Charles R. Portwood II " -ENV GNU_INSTALL_ROOT="/root/gcc-arm-none-eabi-10.3-2021.10/bin/" -ENV NORDIC_SDK_PATH="/root/nrf_sdk/16.0.0" -ENV PATH="$PATH:/root/gcc-arm-none-eabi-10.3-2021.10/bin:/root/nrf-command-line-tools/bin:/root/.local/bin" +ENV GNU_INSTALL_ROOT="/root/gcc-arm-none-eabi-8-2018-q4-major/bin/" +ENV NORDIC_SDK_PATH="/root/nrf_sdk/15.3.0" +ENV PATH="$PATH:/root/gcc-arm-none-eabi-8-2018-q4-major/bin:/root/nrf-command-line-tools/bin:/root/.local/bin" ENV BOARD="" ENV DEBUG=0 ENV NRF_DFU_BL_ACCEPT_SAME_VERSION=1 ENV NRF_DFU_REQUIRE_SIGNED_APP_UPDATE=1 ENV NRF_BL_APP_SIGNATURE_CHECK_REQUIRED=0 +ENV NRF_DFU_BLE_ADV_NAME="KAIDYTH_DFU" VOLUME [ "/app" ] @@ -22,9 +23,9 @@ RUN apt update -qq && \ RUN pip3 install --user nrfutil # Install GCC ARM -ENV GCC_ARM_NAME_BZ="gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2" +ENV GCC_ARM_NAME_BZ="gcc-arm-none-eabi-8-2018-q4-major-linux.tar.bz2" RUN cd $HOME && \ - curl -L "https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu-rm/10.3-2021.10/gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2" -o ${GCC_ARM_NAME_BZ} && \ + curl -L "https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu-rm/8-2018q4/gcc-arm-none-eabi-8-2018-q4-major-linux.tar.bz2" -o ${GCC_ARM_NAME_BZ} && \ tar -xf ${GCC_ARM_NAME_BZ} && \ rm -rf ${GCC_ARM_NAME_BZ} @@ -35,19 +36,21 @@ RUN cd $HOME && \ # Install NRF SDK RUN cd $HOME && \ - mkdir -p $HOME/nrf_sdk/16.0.0 && \ - wget https://www.nordicsemi.com/-/media/Software-and-other-downloads/SDKs/nRF5/Binaries/nRF5SDK160098a08e2.zip -O nRF5_SDK_16.0.0_98a08e2.zip && \ - mv nRF5_SDK_16.0.0_98a08e2.zip $HOME/nrf_sdk/16.0.0 && \ - cd $HOME/nrf_sdk/16.0.0 && \ - unzip nRF5_SDK_16.0.0_98a08e2.zip > /dev/null 2>&1 && \ - rm -rf nRF5_SDK_16.0.0_98a08e2.zip + mkdir -p $HOME/nrf_sdk/15.3.0 && \ + wget https://www.nordicsemi.com/-/media/Software-and-other-downloads/SDKs/nRF5/Binaries/nRF5SDK153059ac345.zip -O nRF5_SDK_15.3.0_59ac345.zip && \ + mv nRF5_SDK_15.3.0_59ac345.zip $HOME/nrf_sdk/15.3.0 && \ + cd $HOME/nrf_sdk/15.3.0 && \ + unzip nRF5_SDK_15.3.0_59ac345.zip > /dev/null 2>&1 && \ + rm -rf nRF5_SDK_15.3.0_59ac345.zip && \ + mv nRF5_SDK_15.3.0_59ac345/* . && \ + rm -rf nRF5_SDK_15.3.0_59ac345 # Install micro-ecc -RUN cd $HOME/nrf_sdk/16.0.0/external/micro-ecc && \ +RUN cd $HOME/nrf_sdk/15.3.0/external/micro-ecc && \ git clone https://github.com/kmackay/micro-ecc && \ - chmod +x $HOME/nrf_sdk/16.0.0/external/micro-ecc/build_all.sh && \ - dos2unix $HOME/nrf_sdk/16.0.0/external/micro-ecc/build_all.sh && \ - ls -laht $HOME/nrf_sdk/16.0.0/external/micro-ecc/micro-ecc && \ + chmod +x $HOME/nrf_sdk/15.3.0/external/micro-ecc/build_all.sh && \ + dos2unix $HOME/nrf_sdk/15.3.0/external/micro-ecc/build_all.sh && \ + ls -laht $HOME/nrf_sdk/15.3.0/external/micro-ecc/micro-ecc && \ ./build_all.sh # Install diff --git a/Makefile b/Makefile index ede87ea..3ffb433 100644 --- a/Makefile +++ b/Makefile @@ -68,4 +68,13 @@ patch: ## Patches the files in the nordic SDK to support additional bootloader f if patch -p0 -s -f --dry-run --reject-file /dev/null $(NORDIC_SDK_PATH)/$${file} ./sdk/$${file}; then \ patch --forward --unified $(NORDIC_SDK_PATH)/$${file} ./sdk/$${file}; \ fi \ - done; \ No newline at end of file + done; + @for file in $(subst ./sdk/,,$(call rwildcard,./sdk/,*nrf_bootloader.c)); do \ + echo "Copying $$file to $(NORDIC_SDK_PATH)/$${file#./sdk/}"; \ + cp ./sdk/$$file $(NORDIC_SDK_PATH)/$${file#./sdk/}; \ + done; + @for file in $(subst ./sdk/,,$(call rwildcard,./sdk/,*nrf_dfu_validation.c)); do \ + echo "Copying $$file to $(NORDIC_SDK_PATH)/$${file#./sdk/}"; \ + cp ./sdk/$$file $(NORDIC_SDK_PATH)/$${file#./sdk/}; \ + done; + diff --git a/boards/Makefile.boards b/boards/Makefile.boards index 3dbd0d1..f6a34ac 100644 --- a/boards/Makefile.boards +++ b/boards/Makefile.boards @@ -3,16 +3,24 @@ TARGETS := nrf52840_xxaa OUTPUT_DIRECTORY := _build DEBUG ?= 0 -SD_REQ := 0xCA +SD_REQ := 0xB6 + +SECURE := secure + +ifeq ($(NRF_DFU_REQUIRE_SIGNED_APP_UPDATE), 0) +SECURE = unsecure +endif GIT_VERSION := $(shell git describe --always --tags) -BOARD_DIST := $(BOARD)_bootloader-$(GIT_VERSION) +BOARD_DIST := $(BOARD)_bootloader-$(GIT_VERSION)_$(SECURE) ifeq ($(DEBUG), 1) GIT_VERSION = $(shell git describe --dirty --always --tags) -BOARD_DIST := debug_$(BOARD)_bootloader-$(GIT_VERSION) +BOARD_DIST := debug_$(BOARD)_bootloader-$(GIT_VERSION)_$(SECURE) endif + + BUILD_NUMBER := 1 ifdef TRAVIS_TAG @@ -130,8 +138,7 @@ SRC_FILES += \ $(SDK_ROOT)/components/libraries/crypto/backend/oberon/oberon_backend_hash.c \ $(SDK_ROOT)/components/libraries/crypto/backend/oberon/oberon_backend_hmac.c \ $(SDK_ROOT)/components/libraries/bsp/bsp.c \ - $(SDK_ROOT)/components/libraries/timer/app_timer2.c \ - $(SDK_ROOT)/components/libraries/timer/drv_rtc.c \ + $(SDK_ROOT)/components/libraries/timer/app_timer.c \ $(SDK_ROOT)/components/libraries/sortlist/nrf_sortlist.c \ $(SDK_ROOT)/components/libraries/button/app_button.c \ $(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_gpiote.c \ @@ -194,6 +201,7 @@ INC_FOLDERS += \ $(PROJ_DIR) \ $(SDK_ROOT)/components/libraries/crypto/backend/nrf_sw \ $(SDK_ROOT)/modules/nrfx/mdk \ + $(BOARD_DIR)/include \ $(SDK_ROOT)/components/libraries/bootloader/ble_dfu \ $(SDK_ROOT)/components/softdevice/common \ $(SDK_ROOT)/external/nano-pb \ @@ -202,7 +210,6 @@ INC_FOLDERS += \ $(SDK_ROOT)/components/libraries/ringbuf \ $(SDK_ROOT)/integration/nrfx \ $(SDK_ROOT)/modules/nrfx/mdk \ - $(BOARD_DIR)/include \ $(SDK_ROOT)/integration/nrfx \ $(SDK_ROOT)/integration/nrfx/legacy \ $(SDK_ROOT)/external/segger_rtt \ @@ -224,7 +231,7 @@ INC_FOLDERS += \ # Libraries common to all targets LIB_FILES += \ - $(SDK_ROOT)/external/nrf_oberon/lib/cortex-m4/hard-float/liboberon_3.0.1.a \ + $(SDK_ROOT)/external/nrf_oberon/lib/cortex-m4/hard-float/liboberon_2.0.7.a \ $(SDK_ROOT)/external/nrf_cc310_bl/lib/cortex-m4/hard-float/libnrf_cc310_bl_0.9.12.a \ ifeq ($(DEBUG), 1) @@ -237,18 +244,17 @@ OPT += -flto # C flags common to all targets CFLAGS += $(OPT) -CFLAGS += -DAPP_TIMER_V2 -CFLAGS += -DAPP_TIMER_V2_RTC1_ENABLED CFLAGS += -DBLE_STACK_SUPPORT_REQD CFLAGS += -DFLOAT_ABI_HARD CFLAGS += -DNRF52840_XXAA CFLAGS += -DNRF_DFU_SETTINGS_VERSION=2 CFLAGS += -DNRF_DFU_SVCI_ENABLED -CFLAGS += -DNRF_SD_BLE_API_VERSION=7 +CFLAGS += -DNRF_SD_BLE_API_VERSION=6 CFLAGS += -DS140 CFLAGS += -DSOFTDEVICE_PRESENT CFLAGS += -DSVC_INTERFACE_CALL_AS_NORMAL_FUNCTION CFLAGS += -DCONFIG_GPIO_AS_PINRESET +#CFLAGS += -DNRF_DFU_BLE_ADV_NAME=\"$(NRF_DFU_BLE_ADV_NAME)\" CFLAGS += -DCONFIG_NFCT_PINS_AS_GPIOS CFLAGS += -mcpu=cortex-m4 CFLAGS += -mthumb -mabi=aapcs @@ -264,6 +270,24 @@ CFLAGS += -DDEBUG CFLAGS += -DNRF_DFU_DEBUG_VERSION endif +ifeq ($(NRF_DFU_REQUIRE_SIGNED_APP_UPDATE), 1) +CFLAGS += -DNRF_DFU_REQUIRE_SIGNED_APP_UPDATE=1 +else +CFLAGS += -DNRF_DFU_REQUIRE_SIGNED_APP_UPDATE=0 +endif + +ifeq ($(NRF_DFU_BL_ACCEPT_SAME_VERSION), 1) +CFLAGS += -DNRF_DFU_BL_ACCEPT_SAME_VERSION=1 +else +CFLAGS += -DNRF_DFU_BL_ACCEPT_SAME_VERSION=0 +endif + +ifeq ($(NRF_BL_APP_SIGNATURE_CHECK_REQUIRED), 1) +CFLAGS += -DNRF_BL_APP_SIGNATURE_CHECK_REQUIRED=1 +else +CFLAGS += -DNRF_BL_APP_SIGNATURE_CHECK_REQUIRED=0 +endif + ifeq ($(NRF_DFU_BL_ALLOW_DOWNGRADE), 1) CFLAGS += -DNRF_DFU_BL_ALLOW_DOWNGRADE=1 endif @@ -280,23 +304,40 @@ ASMFLAGS += -g3 ASMFLAGS += -mcpu=cortex-m4 ASMFLAGS += -mthumb -mabi=aapcs ASMFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 -ASMFLAGS += -DAPP_TIMER_V2 -ASMFLAGS += -DAPP_TIMER_V2_RTC1_ENABLED ASMFLAGS += -DBLE_STACK_SUPPORT_REQD ASMFLAGS += -DFLOAT_ABI_HARD ASMFLAGS += -DNRF52840_XXAA ASMFLAGS += -DNRF_DFU_SETTINGS_VERSION=2 ASMFLAGS += -DNRF_DFU_SVCI_ENABLED -ASMFLAGS += -DNRF_SD_BLE_API_VERSION=7 +ASMFLAGS += -DNRF_SD_BLE_API_VERSION=6 ASMFLAGS += -DS140 ASMFLAGS += -DSOFTDEVICE_PRESENT ASMFLAGS += -DSVC_INTERFACE_CALL_AS_NORMAL_FUNCTION ASMFLAGS += -DCONFIG_GPIO_AS_PINRESET +ASMFLAGS += -DNRF_DFU_BLE_ADV_NAME=\"$(NRF_DFU_BLE_ADV_NAME)\" ifeq ($(DEBUG),1) ASMFLAGS += -DBOOTLOADER_DEBUG ASMFLAGS += -DNRF_DFU_DEBUG_VERSION endif +ifeq ($(NRF_DFU_REQUIRE_SIGNED_APP_UPDATE), 1) +ASMFLAGS += -DNRF_DFU_REQUIRE_SIGNED_APP_UPDATE=1 +else +ASMFLAGS += -DNRF_DFU_REQUIRE_SIGNED_APP_UPDATE=0 +endif + +ifeq ($(NRF_DFU_BL_ACCEPT_SAME_VERSION), 1) +ASMFLAGS += -DNRF_DFU_BL_ACCEPT_SAME_VERSION=1 +else +ASMFLAGS += -DNRF_DFU_BL_ACCEPT_SAME_VERSION=0 +endif + +ifeq ($(NRF_BL_APP_SIGNATURE_CHECK_REQUIRED), 1) +ASMFLAGS += -DNRF_BL_APP_SIGNATURE_CHECK_REQUIRED=1 +else +ASMFLAGS += -DNRF_BL_APP_SIGNATURE_CHECK_REQUIRED=0 +endif + ifeq ($(NRF_DFU_BL_ALLOW_DOWNGRADE), 1) ASMFLAGS += -DNRF_DFU_BL_ALLOW_DOWNGRADE=1 endif @@ -347,8 +388,8 @@ endif # Flash softdevice flash_softdevice: dfu_package - @echo Flashing: s140_nrf52_7.0.1_softdevice.hex - nrfjprog -f nrf52 --program $(SDK_ROOT)/components/softdevice/s140/hex/s140_nrf52_7.0.1_softdevice.hex --sectorerase + @echo Flashing: s140_nrf52_6.1.1_softdevice.hex + nrfjprog -f nrf52 --program $(SDK_ROOT)/components/softdevice/s140/hex/s140_nrf52_6.1.1_softdevice.hex --sectorerase nrfjprog -f nrf52 --reset flash: dfu_package @@ -365,7 +406,7 @@ endif nrfutil dfu usb-serial -pkg $(OUTPUT_DIRECTORY)/$(BOARD_DIST)_s140.zip -p $(PORT) $(OUTPUT_DIRECTORY)/$(BOARD_DIST)_s140.zip: merge - nrfutil pkg generate --sd-req $(SD_REQ) --hw-version 52 --key-file $(PROJ_DIR)/private.pem --bootloader-version $(BUILD_NUMBER) --bootloader $(OUTPUT_DIRECTORY)/nrf52840_xxaa.hex --softdevice $(SDK_ROOT)/components/softdevice/s140/hex/s140_nrf52_7.0.1_softdevice.hex $(OUTPUT_DIRECTORY)/$(BOARD_DIST)_s140.zip + nrfutil pkg generate --sd-req $(SD_REQ) --hw-version 52 --key-file $(PROJ_DIR)/private.pem --bootloader-version $(BUILD_NUMBER) --bootloader $(OUTPUT_DIRECTORY)/nrf52840_xxaa.hex --softdevice $(SDK_ROOT)/components/softdevice/s140/hex/s140_nrf52_6.1.1_softdevice.hex $(OUTPUT_DIRECTORY)/$(BOARD_DIST)_s140.zip $(OUTPUT_DIRECTORY)/$(BOARD_DIST).zip: default nrfutil pkg generate --sd-req $(SD_REQ) --hw-version 52 --key-file $(PROJ_DIR)/private.pem --bootloader-version $(BUILD_NUMBER) --bootloader $(OUTPUT_DIRECTORY)/nrf52840_xxaa.hex $(OUTPUT_DIRECTORY)/$(BOARD_DIST).zip @@ -375,7 +416,7 @@ dfu_package: $(OUTPUT_DIRECTORY)/$(BOARD_DIST)_s140.zip $(OUTPUT_DIRECTORY)/$(BO # Merge application and softdevice merge: default @echo Merging application and softdevice... - mergehex -m $(OUTPUT_DIRECTORY)/nrf52840_xxaa.hex $(SDK_ROOT)/components/softdevice/s140/hex/s140_nrf52_7.0.1_softdevice.hex -o $(OUTPUT_DIRECTORY)/$(BOARD_DIST)_s140.hex + mergehex -m $(OUTPUT_DIRECTORY)/nrf52840_xxaa.hex $(SDK_ROOT)/components/softdevice/s140/hex/s140_nrf52_6.1.1_softdevice.hex -o $(OUTPUT_DIRECTORY)/$(BOARD_DIST)_s140.hex erase: nrfjprog -f nrf52 --eraseall diff --git a/boards/arduino-nano-33-ble/s140/include/config.h b/boards/arduino-nano-33-ble/s140/include/config.h new file mode 100644 index 0000000..6a3f6c1 --- /dev/null +++ b/boards/arduino-nano-33-ble/s140/include/config.h @@ -0,0 +1,18 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#ifndef NRF_DFU_BLE_ADV_NAME +#define NRF_DFU_BLE_ADV_NAME "KAIDYTH_DFU" +#endif + +//#define BLEDIS_MANUFACTURER "ddB0515" +//#define BLEDIS_MODEL "nano-33-ble" + +//#define APP_USBD_VID 0x239A +//#define APP_USBD_PID 0x0029 +#endif + +#ifndef NRF_DFU_BL_ALLOW_DOWNGRADE +#define NRF_DFU_BL_ALLOW_DOWNGRADE 1 +#endif + diff --git a/boards/feather-express/s140/include/config.h b/boards/feather-express/s140/include/config.h new file mode 100644 index 0000000..6a3f6c1 --- /dev/null +++ b/boards/feather-express/s140/include/config.h @@ -0,0 +1,18 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#ifndef NRF_DFU_BLE_ADV_NAME +#define NRF_DFU_BLE_ADV_NAME "KAIDYTH_DFU" +#endif + +//#define BLEDIS_MANUFACTURER "ddB0515" +//#define BLEDIS_MODEL "nano-33-ble" + +//#define APP_USBD_VID 0x239A +//#define APP_USBD_PID 0x0029 +#endif + +#ifndef NRF_DFU_BL_ALLOW_DOWNGRADE +#define NRF_DFU_BL_ALLOW_DOWNGRADE 1 +#endif + diff --git a/boards/generic/s140/include/config.h b/boards/generic/s140/include/config.h new file mode 100644 index 0000000..6a3f6c1 --- /dev/null +++ b/boards/generic/s140/include/config.h @@ -0,0 +1,18 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#ifndef NRF_DFU_BLE_ADV_NAME +#define NRF_DFU_BLE_ADV_NAME "KAIDYTH_DFU" +#endif + +//#define BLEDIS_MANUFACTURER "ddB0515" +//#define BLEDIS_MODEL "nano-33-ble" + +//#define APP_USBD_VID 0x239A +//#define APP_USBD_PID 0x0029 +#endif + +#ifndef NRF_DFU_BL_ALLOW_DOWNGRADE +#define NRF_DFU_BL_ALLOW_DOWNGRADE 1 +#endif + diff --git a/boards/mdk-usb-dongle/s140/include/config.h b/boards/mdk-usb-dongle/s140/include/config.h new file mode 100644 index 0000000..6a3f6c1 --- /dev/null +++ b/boards/mdk-usb-dongle/s140/include/config.h @@ -0,0 +1,18 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#ifndef NRF_DFU_BLE_ADV_NAME +#define NRF_DFU_BLE_ADV_NAME "KAIDYTH_DFU" +#endif + +//#define BLEDIS_MANUFACTURER "ddB0515" +//#define BLEDIS_MODEL "nano-33-ble" + +//#define APP_USBD_VID 0x239A +//#define APP_USBD_PID 0x0029 +#endif + +#ifndef NRF_DFU_BL_ALLOW_DOWNGRADE +#define NRF_DFU_BL_ALLOW_DOWNGRADE 1 +#endif + diff --git a/boards/mdk/s140/include/config.h b/boards/mdk/s140/include/config.h new file mode 100644 index 0000000..6a3f6c1 --- /dev/null +++ b/boards/mdk/s140/include/config.h @@ -0,0 +1,18 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#ifndef NRF_DFU_BLE_ADV_NAME +#define NRF_DFU_BLE_ADV_NAME "KAIDYTH_DFU" +#endif + +//#define BLEDIS_MANUFACTURER "ddB0515" +//#define BLEDIS_MODEL "nano-33-ble" + +//#define APP_USBD_VID 0x239A +//#define APP_USBD_PID 0x0029 +#endif + +#ifndef NRF_DFU_BL_ALLOW_DOWNGRADE +#define NRF_DFU_BL_ALLOW_DOWNGRADE 1 +#endif + diff --git a/boards/particle-argon/s140/include/config.h b/boards/particle-argon/s140/include/config.h new file mode 100644 index 0000000..6a3f6c1 --- /dev/null +++ b/boards/particle-argon/s140/include/config.h @@ -0,0 +1,18 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#ifndef NRF_DFU_BLE_ADV_NAME +#define NRF_DFU_BLE_ADV_NAME "KAIDYTH_DFU" +#endif + +//#define BLEDIS_MANUFACTURER "ddB0515" +//#define BLEDIS_MODEL "nano-33-ble" + +//#define APP_USBD_VID 0x239A +//#define APP_USBD_PID 0x0029 +#endif + +#ifndef NRF_DFU_BL_ALLOW_DOWNGRADE +#define NRF_DFU_BL_ALLOW_DOWNGRADE 1 +#endif + diff --git a/boards/particle-boron/s140/include/config.h b/boards/particle-boron/s140/include/config.h new file mode 100644 index 0000000..6a3f6c1 --- /dev/null +++ b/boards/particle-boron/s140/include/config.h @@ -0,0 +1,18 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#ifndef NRF_DFU_BLE_ADV_NAME +#define NRF_DFU_BLE_ADV_NAME "KAIDYTH_DFU" +#endif + +//#define BLEDIS_MANUFACTURER "ddB0515" +//#define BLEDIS_MODEL "nano-33-ble" + +//#define APP_USBD_VID 0x239A +//#define APP_USBD_PID 0x0029 +#endif + +#ifndef NRF_DFU_BL_ALLOW_DOWNGRADE +#define NRF_DFU_BL_ALLOW_DOWNGRADE 1 +#endif + diff --git a/boards/particle-xenon/s140/include/config.h b/boards/particle-xenon/s140/include/config.h new file mode 100644 index 0000000..6a3f6c1 --- /dev/null +++ b/boards/particle-xenon/s140/include/config.h @@ -0,0 +1,18 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#ifndef NRF_DFU_BLE_ADV_NAME +#define NRF_DFU_BLE_ADV_NAME "KAIDYTH_DFU" +#endif + +//#define BLEDIS_MANUFACTURER "ddB0515" +//#define BLEDIS_MODEL "nano-33-ble" + +//#define APP_USBD_VID 0x239A +//#define APP_USBD_PID 0x0029 +#endif + +#ifndef NRF_DFU_BL_ALLOW_DOWNGRADE +#define NRF_DFU_BL_ALLOW_DOWNGRADE 1 +#endif + diff --git a/boards/pca10056/s140/include/config.h b/boards/pca10056/s140/include/config.h new file mode 100644 index 0000000..6a3f6c1 --- /dev/null +++ b/boards/pca10056/s140/include/config.h @@ -0,0 +1,18 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#ifndef NRF_DFU_BLE_ADV_NAME +#define NRF_DFU_BLE_ADV_NAME "KAIDYTH_DFU" +#endif + +//#define BLEDIS_MANUFACTURER "ddB0515" +//#define BLEDIS_MODEL "nano-33-ble" + +//#define APP_USBD_VID 0x239A +//#define APP_USBD_PID 0x0029 +#endif + +#ifndef NRF_DFU_BL_ALLOW_DOWNGRADE +#define NRF_DFU_BL_ALLOW_DOWNGRADE 1 +#endif + diff --git a/boards/pca10059/s140/include/config.h b/boards/pca10059/s140/include/config.h new file mode 100644 index 0000000..6a3f6c1 --- /dev/null +++ b/boards/pca10059/s140/include/config.h @@ -0,0 +1,18 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#ifndef NRF_DFU_BLE_ADV_NAME +#define NRF_DFU_BLE_ADV_NAME "KAIDYTH_DFU" +#endif + +//#define BLEDIS_MANUFACTURER "ddB0515" +//#define BLEDIS_MODEL "nano-33-ble" + +//#define APP_USBD_VID 0x239A +//#define APP_USBD_PID 0x0029 +#endif + +#ifndef NRF_DFU_BL_ALLOW_DOWNGRADE +#define NRF_DFU_BL_ALLOW_DOWNGRADE 1 +#endif + diff --git a/boards/pitaya-go/s140/include/config.h b/boards/pitaya-go/s140/include/config.h new file mode 100644 index 0000000..6a3f6c1 --- /dev/null +++ b/boards/pitaya-go/s140/include/config.h @@ -0,0 +1,18 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#ifndef NRF_DFU_BLE_ADV_NAME +#define NRF_DFU_BLE_ADV_NAME "KAIDYTH_DFU" +#endif + +//#define BLEDIS_MANUFACTURER "ddB0515" +//#define BLEDIS_MODEL "nano-33-ble" + +//#define APP_USBD_VID 0x239A +//#define APP_USBD_PID 0x0029 +#endif + +#ifndef NRF_DFU_BL_ALLOW_DOWNGRADE +#define NRF_DFU_BL_ALLOW_DOWNGRADE 1 +#endif + diff --git a/boards/secure_bootloader_gcc_nrf52.ld b/boards/secure_bootloader_gcc_nrf52.ld index 496419a..2b7c1c3 100644 --- a/boards/secure_bootloader_gcc_nrf52.ld +++ b/boards/secure_bootloader_gcc_nrf52.ld @@ -1,162 +1,162 @@ -/* Linker script to configure memory regions. */ - -SEARCH_DIR(.) -GROUP(-lgcc -lc -lnosys) - -MEMORY -{ - FLASH (rx) : ORIGIN = 0xE0000, LENGTH = 0x11000 /** 68KB **/ - RAM (rwx) : ORIGIN = 0x20002AE8, LENGTH = 0x3D518 - uicr_bootloader_start_address (r) : ORIGIN = 0x00000FF8, LENGTH = 0x4 - bootloader_settings_page (r) : ORIGIN = 0x000FF000, LENGTH = 0x1000 - uicr_mbr_params_page (r) : ORIGIN = 0x00000FFC, LENGTH = 0x4 - mbr_params_page (r) : ORIGIN = 0x000FE000, LENGTH = 0x1000 - - DBL_RESET (rwx) : ORIGIN = 0x20002A90, LENGTH = 0x04 -} - -SECTIONS -{ - . = ALIGN(4); - .uicr_bootloader_start_address : - { - PROVIDE(__start_uicr_bootloader_start_address = .); - KEEP(*(SORT(.uicr_bootloader_start_address*))) - PROVIDE(__stop_uicr_bootloader_start_address = .); - } > uicr_bootloader_start_address - . = ALIGN(4); - .bootloader_settings_page(NOLOAD) : - { - PROVIDE(__start_bootloader_settings_page = .); - KEEP(*(SORT(.bootloader_settings_page*))) - PROVIDE(__stop_bootloader_settings_page = .); - } > bootloader_settings_page - . = ALIGN(4); - .uicr_mbr_params_page : - { - PROVIDE(__start_uicr_mbr_params_page = .); - KEEP(*(SORT(.uicr_mbr_params_page*))) - PROVIDE(__stop_uicr_mbr_params_page = .); - } > uicr_mbr_params_page - . = ALIGN(4); - .dbl_reset(NOLOAD) : - { - - } > DBL_RESET - .mbr_params_page(NOLOAD) : - { - PROVIDE(__start_mbr_params_page = .); - KEEP(*(SORT(.mbr_params_page*))) - PROVIDE(__stop_mbr_params_page = .); - } > mbr_params_page -} - -SECTIONS -{ - . = ALIGN(4); - .mem_section_dummy_ram : - { - } - .log_dynamic_data : - { - PROVIDE(__start_log_dynamic_data = .); - KEEP(*(SORT(.log_dynamic_data*))) - PROVIDE(__stop_log_dynamic_data = .); - } > RAM - .log_filter_data : - { - PROVIDE(__start_log_filter_data = .); - KEEP(*(SORT(.log_filter_data*))) - PROVIDE(__stop_log_filter_data = .); - } > RAM - .fs_data : - { - PROVIDE(__start_fs_data = .); - KEEP(*(.fs_data)) - PROVIDE(__stop_fs_data = .); - } > RAM - -} INSERT AFTER .data; - -SECTIONS -{ - .mem_section_dummy_rom : - { - } - .crypto_data : - { - PROVIDE(__start_crypto_data = .); - KEEP(*(SORT(.crypto_data*))) - PROVIDE(__stop_crypto_data = .); - } > FLASH - .nrf_queue : - { - PROVIDE(__start_nrf_queue = .); - KEEP(*(.nrf_queue)) - PROVIDE(__stop_nrf_queue = .); - } > FLASH - .dfu_trans : - { - PROVIDE(__start_dfu_trans = .); - KEEP(*(SORT(.dfu_trans*))) - PROVIDE(__stop_dfu_trans = .); - } > FLASH - .svc_data : - { - PROVIDE(__start_svc_data = .); - KEEP(*(.svc_data)) - PROVIDE(__stop_svc_data = .); - } > FLASH - .log_const_data : - { - PROVIDE(__start_log_const_data = .); - KEEP(*(SORT(.log_const_data*))) - PROVIDE(__stop_log_const_data = .); - } > FLASH - .nrf_balloc : - { - PROVIDE(__start_nrf_balloc = .); - KEEP(*(.nrf_balloc)) - PROVIDE(__stop_nrf_balloc = .); - } > FLASH - .log_backends : - { - PROVIDE(__start_log_backends = .); - KEEP(*(SORT(.log_backends*))) - PROVIDE(__stop_log_backends = .); - } > FLASH - .sdh_ble_observers : - { - PROVIDE(__start_sdh_ble_observers = .); - KEEP(*(SORT(.sdh_ble_observers*))) - PROVIDE(__stop_sdh_ble_observers = .); - } > FLASH - .sdh_req_observers : - { - PROVIDE(__start_sdh_req_observers = .); - KEEP(*(SORT(.sdh_req_observers*))) - PROVIDE(__stop_sdh_req_observers = .); - } > FLASH - .sdh_state_observers : - { - PROVIDE(__start_sdh_state_observers = .); - KEEP(*(SORT(.sdh_state_observers*))) - PROVIDE(__stop_sdh_state_observers = .); - } > FLASH - .sdh_stack_observers : - { - PROVIDE(__start_sdh_stack_observers = .); - KEEP(*(SORT(.sdh_stack_observers*))) - PROVIDE(__stop_sdh_stack_observers = .); - } > FLASH - .sdh_soc_observers : - { - PROVIDE(__start_sdh_soc_observers = .); - KEEP(*(SORT(.sdh_soc_observers*))) - PROVIDE(__stop_sdh_soc_observers = .); - } > FLASH - -} INSERT AFTER .text - - -INCLUDE "nrf_common.ld" +/* Linker script to configure memory regions. */ + +SEARCH_DIR(.) +GROUP(-lgcc -lc -lnosys) + +MEMORY +{ + FLASH (rx) : ORIGIN = 0xE0000, LENGTH = 0x186A0 /** 100KB **/ + RAM (rwx) : ORIGIN = 0x20006000, LENGTH = 0x3A000 + uicr_bootloader_start_address (r) : ORIGIN = 0x00000FF8, LENGTH = 0x4 + bootloader_settings_page (r) : ORIGIN = 0x000FF000, LENGTH = 0x1000 + uicr_mbr_params_page (r) : ORIGIN = 0x00000FFC, LENGTH = 0x4 + mbr_params_page (r) : ORIGIN = 0x000FE000, LENGTH = 0x1000 + + DBL_RESET (rwx) : ORIGIN = 0x20006000, LENGTH = 0x04 +} + +SECTIONS +{ + . = ALIGN(4); + .uicr_bootloader_start_address : + { + PROVIDE(__start_uicr_bootloader_start_address = .); + KEEP(*(SORT(.uicr_bootloader_start_address*))) + PROVIDE(__stop_uicr_bootloader_start_address = .); + } > uicr_bootloader_start_address + . = ALIGN(4); + .bootloader_settings_page(NOLOAD) : + { + PROVIDE(__start_bootloader_settings_page = .); + KEEP(*(SORT(.bootloader_settings_page*))) + PROVIDE(__stop_bootloader_settings_page = .); + } > bootloader_settings_page + . = ALIGN(4); + .uicr_mbr_params_page : + { + PROVIDE(__start_uicr_mbr_params_page = .); + KEEP(*(SORT(.uicr_mbr_params_page*))) + PROVIDE(__stop_uicr_mbr_params_page = .); + } > uicr_mbr_params_page + . = ALIGN(4); + .dbl_reset(NOLOAD) : + { + + } > DBL_RESET + .mbr_params_page(NOLOAD) : + { + PROVIDE(__start_mbr_params_page = .); + KEEP(*(SORT(.mbr_params_page*))) + PROVIDE(__stop_mbr_params_page = .); + } > mbr_params_page +} + +SECTIONS +{ + . = ALIGN(4); + .mem_section_dummy_ram : + { + } + .log_dynamic_data : + { + PROVIDE(__start_log_dynamic_data = .); + KEEP(*(SORT(.log_dynamic_data*))) + PROVIDE(__stop_log_dynamic_data = .); + } > RAM + .log_filter_data : + { + PROVIDE(__start_log_filter_data = .); + KEEP(*(SORT(.log_filter_data*))) + PROVIDE(__stop_log_filter_data = .); + } > RAM + .fs_data : + { + PROVIDE(__start_fs_data = .); + KEEP(*(.fs_data)) + PROVIDE(__stop_fs_data = .); + } > RAM + +} INSERT AFTER .data; + +SECTIONS +{ + .mem_section_dummy_rom : + { + } + .crypto_data : + { + PROVIDE(__start_crypto_data = .); + KEEP(*(SORT(.crypto_data*))) + PROVIDE(__stop_crypto_data = .); + } > FLASH + .nrf_queue : + { + PROVIDE(__start_nrf_queue = .); + KEEP(*(.nrf_queue)) + PROVIDE(__stop_nrf_queue = .); + } > FLASH + .dfu_trans : + { + PROVIDE(__start_dfu_trans = .); + KEEP(*(SORT(.dfu_trans*))) + PROVIDE(__stop_dfu_trans = .); + } > FLASH + .svc_data : + { + PROVIDE(__start_svc_data = .); + KEEP(*(.svc_data)) + PROVIDE(__stop_svc_data = .); + } > FLASH + .log_const_data : + { + PROVIDE(__start_log_const_data = .); + KEEP(*(SORT(.log_const_data*))) + PROVIDE(__stop_log_const_data = .); + } > FLASH + .nrf_balloc : + { + PROVIDE(__start_nrf_balloc = .); + KEEP(*(.nrf_balloc)) + PROVIDE(__stop_nrf_balloc = .); + } > FLASH + .log_backends : + { + PROVIDE(__start_log_backends = .); + KEEP(*(SORT(.log_backends*))) + PROVIDE(__stop_log_backends = .); + } > FLASH + .sdh_ble_observers : + { + PROVIDE(__start_sdh_ble_observers = .); + KEEP(*(SORT(.sdh_ble_observers*))) + PROVIDE(__stop_sdh_ble_observers = .); + } > FLASH + .sdh_req_observers : + { + PROVIDE(__start_sdh_req_observers = .); + KEEP(*(SORT(.sdh_req_observers*))) + PROVIDE(__stop_sdh_req_observers = .); + } > FLASH + .sdh_state_observers : + { + PROVIDE(__start_sdh_state_observers = .); + KEEP(*(SORT(.sdh_state_observers*))) + PROVIDE(__stop_sdh_state_observers = .); + } > FLASH + .sdh_stack_observers : + { + PROVIDE(__start_sdh_stack_observers = .); + KEEP(*(SORT(.sdh_stack_observers*))) + PROVIDE(__stop_sdh_stack_observers = .); + } > FLASH + .sdh_soc_observers : + { + PROVIDE(__start_sdh_soc_observers = .); + KEEP(*(SORT(.sdh_soc_observers*))) + PROVIDE(__stop_sdh_soc_observers = .); + } > FLASH + +} INSERT AFTER .text + + +INCLUDE "nrf_common.ld" diff --git a/boards/secure_bootloader_gcc_nrf52_debug.ld b/boards/secure_bootloader_gcc_nrf52_debug.ld index 811daf4..6d8df3b 100644 --- a/boards/secure_bootloader_gcc_nrf52_debug.ld +++ b/boards/secure_bootloader_gcc_nrf52_debug.ld @@ -6,13 +6,13 @@ GROUP(-lgcc -lc -lnosys) MEMORY { FLASH (rx) : ORIGIN = 0xE0000, LENGTH = 0x186A0 /** 100KB **/ - RAM (rwx) : ORIGIN = 0x20002AE8, LENGTH = 0x3D518 + RAM (rwx) : ORIGIN = 0x20006000, LENGTH = 0x3A000 uicr_bootloader_start_address (r) : ORIGIN = 0x00000FF8, LENGTH = 0x4 bootloader_settings_page (r) : ORIGIN = 0x000FF000, LENGTH = 0x1000 uicr_mbr_params_page (r) : ORIGIN = 0x00000FFC, LENGTH = 0x4 mbr_params_page (r) : ORIGIN = 0x000FE000, LENGTH = 0x1000 - - DBL_RESET (rwx) : ORIGIN = 0x20002A90, LENGTH = 0x04 + + DBL_RESET (rwx) : ORIGIN = 0x20006000, LENGTH = 0x04 } SECTIONS @@ -159,4 +159,4 @@ SECTIONS } INSERT AFTER .text -INCLUDE "nrf_common.ld" +INCLUDE "nrf_common.ld" \ No newline at end of file diff --git a/boards/sparkfun-pro-mini/s140/include/config.h b/boards/sparkfun-pro-mini/s140/include/config.h new file mode 100644 index 0000000..6a3f6c1 --- /dev/null +++ b/boards/sparkfun-pro-mini/s140/include/config.h @@ -0,0 +1,18 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#ifndef NRF_DFU_BLE_ADV_NAME +#define NRF_DFU_BLE_ADV_NAME "KAIDYTH_DFU" +#endif + +//#define BLEDIS_MANUFACTURER "ddB0515" +//#define BLEDIS_MODEL "nano-33-ble" + +//#define APP_USBD_VID 0x239A +//#define APP_USBD_PID 0x0029 +#endif + +#ifndef NRF_DFU_BL_ALLOW_DOWNGRADE +#define NRF_DFU_BL_ALLOW_DOWNGRADE 1 +#endif + diff --git a/include/app_config.h b/include/app_config.h index 4a824af..71b9819 100644 --- a/include/app_config.h +++ b/include/app_config.h @@ -4,7 +4,7 @@ #ifdef __cplusplus extern "C" { #endif - +#include "config.h" #define _PINNUM(port, pin) ((port)*32 + (pin)) #ifndef NRF_DFU_BL_ACCEPT_SAME_VERSION diff --git a/include/sdk_config.h b/include/sdk_config.h index 5f2739e..51ed616 100644 --- a/include/sdk_config.h +++ b/include/sdk_config.h @@ -43,7 +43,6 @@ #ifndef SDK_CONFIG_H #define SDK_CONFIG_H // <<< Use Configuration Wizard in Context Menu >>>\n - #include "app_config.h" // nRF_Bootloader @@ -1346,6 +1345,7 @@ #define NRF_DFU_BLE_ADV_NAME "KAIDYTH_DFU" #endif + // NRF_DFU_BLE_ADV_INTERVAL - Advertising interval (in units of 0.625 ms) #ifndef NRF_DFU_BLE_ADV_INTERVAL #define NRF_DFU_BLE_ADV_INTERVAL 40 @@ -4174,7 +4174,7 @@ // APP_USBD_CONFIG_LOG_ENABLED - Enable logging in the module. //========================================================== #ifndef APP_USBD_CONFIG_LOG_ENABLED -#define APP_USBD_CONFIG_LOG_ENABLED 0 +#define APP_USBD_CONFIG_LOG_ENABLED 4 #endif // APP_USBD_CONFIG_LOG_LEVEL - Default Severity level diff --git a/main.c b/main.c index a54ab7e..737d15d 100644 --- a/main.c +++ b/main.c @@ -125,26 +125,25 @@ static void dfu_observer(nrf_dfu_evt_type_t evt_type) case NRF_DFU_EVT_DFU_FAILED: case NRF_DFU_EVT_DFU_ABORTED: case NRF_DFU_EVT_DFU_INITIALIZED: - if (LEDS_NUMBER > 0) { - bsp_board_led_on(BSP_BOARD_LED_0); - if (LEDS_NUMBER <= 2) { - bsp_indication_set(BSP_INDICATE_ADVERTISING_DIRECTED); - } else { - bsp_board_led_on(BSP_BOARD_LED_2); - bsp_board_led_off(BSP_BOARD_LED_1); - } - } + if (LEDS_NUMBER > 0) { + bsp_indication_set(BSP_INDICATE_ADVERTISING_WHITELIST); + } break; case NRF_DFU_EVT_TRANSPORT_ACTIVATED: - if (LEDS_NUMBER > 2) { - bsp_board_led_off(BSP_BOARD_LED_0); - bsp_board_led_off(BSP_BOARD_LED_1); - bsp_board_led_on(BSP_BOARD_LED_2); - bsp_indication_set(BSP_INDICATE_ADVERTISING_DIRECTED); - } + if (LEDS_NUMBER > 0) { + bsp_indication_set(BSP_INDICATE_ADVERTISING_WHITELIST); + } break; case NRF_DFU_EVT_DFU_STARTED: + if (LEDS_NUMBER > 0) { + bsp_indication_set(BSP_INDICATE_BONDING); + } break; + case NRF_DFU_EVT_DFU_COMPLETED: + if (LEDS_NUMBER > 1) { + bsp_board_led_on(BSP_BOARD_LED_1); + } + break; default: break; } @@ -172,29 +171,6 @@ static void kaidyth_bsp_init(void) NRF_LOG_DEBUG("Kaidyth DFU: BSP initialized"); } -/**@brief Double reset handling */ -static void double_reset(void) -{ - // Don't run the double reset check if we're already in DFU mode - uint8_t gpregret0 = nrf_power_gpregret_get(); - if (gpregret0 != BOOTLOADER_DFU_START) { - // Go into DFU mode if the magic double reset memory block is set - if ((*dblrst_mem) == DFU_DBLRST_MAGIC) { - NRF_LOG_INFO("Kaidyth DFU: DBLRST: Double Reset detected, preparing to reboot into DFU mode."); - nrf_power_gpregret_set(BOOTLOADER_DFU_START); - do_reset(); - } - - // Indicate we want to do a double reset - (*dblrst_mem) = DFU_DBLRST_MAGIC; - - // Wait 500ms for a second reset to occur - // If a second reset doesn't occur, the memory register will be zerod - NRFX_DELAY_US(DFU_DBLRST_DELAY * 1000); - } - - (*dblrst_mem) = 0; -} /**@brief Bootstrapping setup for custom functionality */ static void kaidyth_bootstrap(void) @@ -203,9 +179,23 @@ static void kaidyth_bootstrap(void) bsp_board_init(BSP_INIT_LEDS); } - double_reset(); + // double_reset(); + // + //button_pressed(BUTTON_DFU) + // nrf_power_gpregret_set(BOOTLOADER_DFU_START); + if (BUTTONS_NUMBER > 0) + { + nrf_gpio_cfg_input(BUTTON_1,BUTTON_PULL); + nrf_delay_ms(50); + if(nrf_gpio_pin_read(BUTTON_1) == BUTTONS_ACTIVE_STATE) + nrf_power_gpregret_set(BOOTLOADER_DFU_START); + } timers_init(); kaidyth_bsp_init(); + if (LEDS_NUMBER > 2) { + bsp_board_led_on(BSP_BOARD_LED_2); + } + } /**@brief Function for application main entry. */ @@ -225,18 +215,18 @@ int main(void) NRF_LOG_INFO("Kaidyth DFU: Inside main"); kaidyth_bootstrap(); - - // Initiate the bootloader - ret_val = nrf_bootloader_init(dfu_observer); - APP_ERROR_CHECK(ret_val); - - // Either there was no DFU functionality enabled in this project or the DFU module detected - // no ongoing DFU operation and found a valid main application. - // Boot the main application. - nrf_bootloader_app_start(); - - // Should never be reached. - NRF_LOG_INFO("Kaidyth DFU: After main"); + + // Initiate the bootloader + ret_val = nrf_bootloader_init(dfu_observer); + APP_ERROR_CHECK(ret_val); + + // Either there was no DFU functionality enabled in this project or the DFU module detected + // no ongoing DFU operation and found a valid main application. + // Boot the main application. + nrf_bootloader_app_start(); + + // Should never be reached. + NRF_LOG_INFO("Kaidyth DFU: After main"); } /** diff --git a/sdk/components/libraries/bootloader/dfu/nrf_dfu_validation.c b/sdk/components/libraries/bootloader/dfu/nrf_dfu_validation.c new file mode 100644 index 0000000..ad34061 --- /dev/null +++ b/sdk/components/libraries/bootloader/dfu/nrf_dfu_validation.c @@ -0,0 +1,1096 @@ +/** + * 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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 Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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. + * + */ +#include +#include "nrf_dfu_types.h" +#include "nrf_dfu_settings.h" +#include "nrf_dfu_utils.h" +#include "nrf_dfu_flash.h" +#include "nrf_bootloader_info.h" +#include "pb.h" +#include "pb_common.h" +#include "pb_decode.h" +#include "dfu-cc.pb.h" +#include "crc32.h" +#include "nrf_crypto.h" +#include "nrf_crypto_shared.h" +#include "nrf_assert.h" +#include "nrf_dfu_validation.h" +#include "nrf_dfu_ver_validation.h" +#include "nrf_strerror.h" + +#define NRF_LOG_MODULE_NAME nrf_dfu_validation +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +NRF_LOG_MODULE_REGISTER(); + +#ifndef DFU_REQUIRES_SOFTDEVICE +#if !defined(BLE_STACK_SUPPORT_REQD) && !defined(ANT_STACK_SUPPORT_REQD) +#define DFU_REQUIRES_SOFTDEVICE 0 +#else +#define DFU_REQUIRES_SOFTDEVICE 1 +#endif +#endif + +#define EXT_ERR(err) (nrf_dfu_result_t)((uint32_t)NRF_DFU_RES_CODE_EXT_ERROR + (uint32_t)err) + +/* Whether a complete init command has been received and prevalidated, but the firmware + * is not yet fully transferred. This value will also be correct after reset. + */ +static bool m_valid_init_cmd_present = false; +static dfu_packet_t m_packet = DFU_PACKET_INIT_DEFAULT; +static uint8_t* m_init_packet_data_ptr = 0; +static uint32_t m_init_packet_data_len = 0; +static pb_istream_t m_pb_stream; + +static dfu_init_command_t const * mp_init = NULL; + +__ALIGN(4) extern const uint8_t pk[64]; + +/** @brief Value length structure holding the public key. + * + * @details The pk value pointed to is the public key present in dfu_public_key.c + */ +static nrf_crypto_ecc_public_key_t m_public_key; + +/** @brief Structure to hold a signature + */ +static nrf_crypto_ecdsa_secp256r1_signature_t m_signature; + +/** @brief Structure to hold the hash for signature verification + */ +static nrf_crypto_hash_sha256_digest_t m_sig_hash; + +/** @brief Structure to hold the hash for the firmware image + */ +static nrf_crypto_hash_sha256_digest_t m_fw_hash; + +/** @brief Whether nrf_crypto and local keys have been initialized. + */ +static bool m_crypto_initialized = false; + +/** @brief Flag used by parser code to indicate that the init command has been found to be invalid. + */ +static bool m_init_packet_valid = false; + +static void pb_decoding_callback(pb_istream_t *str, + uint32_t tag, + pb_wire_type_t wire_type, + void *iter) +{ + pb_field_iter_t* p_iter = (pb_field_iter_t *) iter; + + // Match the beginning of the init command. + if (p_iter->pos->ptr == &dfu_init_command_fields[0]) + { + uint8_t * ptr = (uint8_t *)str->state; + uint32_t size = str->bytes_left; + + if (m_init_packet_data_ptr != NULL || m_init_packet_data_len != 0) + { + m_init_packet_valid = false; + return; + } + + // Remove tag. + while (*ptr & 0x80) + { + ptr++; + size--; + } + ptr++; + size--; + + // Store the info in init_packet_data. + m_init_packet_data_ptr = ptr; + m_init_packet_data_len = size; + m_init_packet_valid = true; + + NRF_LOG_DEBUG("PB: Init packet data len: %d", size); + } +} + +/** @brief Function for decoding byte stream into variable. + * + * @retval true If the stored init command was successfully decoded. + * @retval false If there was no stored init command, or the decoding failed. + */ +static bool stored_init_cmd_decode(void) +{ + m_pb_stream = pb_istream_from_buffer(s_dfu_settings.init_command, + s_dfu_settings.progress.command_size); + + dfu_init_command_t * p_init; + + // Attach our callback to follow the field decoding. + m_pb_stream.decoding_callback = pb_decoding_callback; + + m_init_packet_valid = false; + m_init_packet_data_ptr = NULL; + m_init_packet_data_len = 0; + memset(&m_packet, 0, sizeof(m_packet)); + + if (!pb_decode(&m_pb_stream, dfu_packet_fields, &m_packet)) + { + NRF_LOG_ERROR("Handler: Invalid protocol buffer m_pb_stream"); + return false; + } + + if (!m_init_packet_valid || (m_packet.has_signed_command && m_packet.has_command)) + { + NRF_LOG_ERROR("Handler: Invalid init command."); + return false; + } + else if (m_packet.has_signed_command && m_packet.signed_command.command.has_init) + { + p_init = &m_packet.signed_command.command.init; + + m_pb_stream = pb_istream_from_buffer(m_init_packet_data_ptr, m_init_packet_data_len); + memset(p_init, 0, sizeof(dfu_init_command_t)); + + if (!pb_decode(&m_pb_stream, dfu_init_command_fields, p_init)) + { + NRF_LOG_ERROR("Handler: Invalid protocol buffer m_pb_stream (init command)"); + return false; + } + } + else if (m_packet.has_command && m_packet.command.has_init) + { + p_init = &m_packet.command.init; + } + else + { + return false; + } + + mp_init = p_init; + + return true; +} + + +static void crypto_init(void) +{ + ret_code_t err_code; + uint8_t pk_copy[sizeof(pk)]; + + if (m_crypto_initialized) + { + return; + } + + err_code = nrf_crypto_init(); + ASSERT(err_code == NRF_SUCCESS); + UNUSED_PARAMETER(err_code); + + // Convert public key to big-endian format for use in nrf_crypto. + nrf_crypto_internal_double_swap_endian(pk_copy, pk, sizeof(pk) / 2); + + err_code = nrf_crypto_ecc_public_key_from_raw(&g_nrf_crypto_ecc_secp256r1_curve_info, + &m_public_key, + pk_copy, + sizeof(pk)); + ASSERT(err_code == NRF_SUCCESS); + UNUSED_PARAMETER(err_code); + + m_crypto_initialized = true; +} + + +void nrf_dfu_validation_init(void) +{ + // If the command is stored to flash, init command was valid. + if ((s_dfu_settings.progress.command_size != 0) && + stored_init_cmd_decode()) + { + m_valid_init_cmd_present = true; + } + else + { + m_valid_init_cmd_present = false; + } +} + + +static void dfu_progress_reset(void) +{ + memset(s_dfu_settings.init_command, 0xFF, INIT_COMMAND_MAX_SIZE); // Remove the last init command + memset(&s_dfu_settings.progress, 0, sizeof(dfu_progress_t)); + s_dfu_settings.write_offset = 0; +} + + +nrf_dfu_result_t nrf_dfu_validation_init_cmd_create(uint32_t size) +{ + nrf_dfu_result_t ret_val = NRF_DFU_RES_CODE_SUCCESS; + if (size == 0) + { + ret_val = NRF_DFU_RES_CODE_INVALID_PARAMETER; + } + else if (size > INIT_COMMAND_MAX_SIZE) + { + ret_val = NRF_DFU_RES_CODE_INSUFFICIENT_RESOURCES; + } + else + { + // Set DFU to uninitialized. + m_valid_init_cmd_present = false; + + // Reset all progress. + dfu_progress_reset(); + + // Set the init command size. + s_dfu_settings.progress.command_size = size; + } + return ret_val; +} + + +nrf_dfu_result_t nrf_dfu_validation_init_cmd_append(uint8_t const * p_data, uint32_t length) +{ + nrf_dfu_result_t ret_val = NRF_DFU_RES_CODE_SUCCESS; + if ((length + s_dfu_settings.progress.command_offset) > s_dfu_settings.progress.command_size) + { + NRF_LOG_ERROR("Init command larger than expected."); + ret_val = NRF_DFU_RES_CODE_INVALID_PARAMETER; + } + else + { + // Copy the received data to RAM, update offset and calculate CRC. + memcpy(&s_dfu_settings.init_command[s_dfu_settings.progress.command_offset], + p_data, + length); + + s_dfu_settings.progress.command_offset += length; + s_dfu_settings.progress.command_crc = crc32_compute(p_data, + length, + &s_dfu_settings.progress.command_crc); + } + return ret_val; +} + + +void nrf_dfu_validation_init_cmd_status_get(uint32_t * p_offset, + uint32_t * p_crc, + uint32_t * p_max_size) +{ + *p_offset = s_dfu_settings.progress.command_offset; + *p_crc = s_dfu_settings.progress.command_crc; + *p_max_size = INIT_COMMAND_MAX_SIZE; +} + + +bool nrf_dfu_validation_init_cmd_present(void) +{ + return m_valid_init_cmd_present; +} + + +// Function determines if init command signature is obligatory. +static bool signature_required(dfu_fw_type_t fw_type_to_be_updated) +{ + bool result = true; + if(NRF_DFU_REQUIRE_SIGNED_APP_UPDATE) + { + // DFU_FW_TYPE_EXTERNAL_APPLICATION and bootloader updates always require + // signature check + if ((!DFU_REQUIRES_SOFTDEVICE && (fw_type_to_be_updated == DFU_FW_TYPE_SOFTDEVICE)) || + (fw_type_to_be_updated == DFU_FW_TYPE_APPLICATION)) + { + result = NRF_DFU_REQUIRE_SIGNED_APP_UPDATE; + } + } + else + { + return false; + } + return result; +} + + +// Function to perform signature check if required. +static nrf_dfu_result_t nrf_dfu_validation_signature_check(dfu_signature_type_t signature_type, + uint8_t const * p_signature, + uint32_t signature_len, + uint8_t const * p_data, + uint32_t data_len) +{ + ret_code_t err_code; + size_t hash_len = NRF_CRYPTO_HASH_SIZE_SHA256; + + nrf_crypto_hash_context_t hash_context = {0}; + nrf_crypto_ecdsa_verify_context_t verify_context = {0}; + + crypto_init(); + + NRF_LOG_INFO("Signature required. Checking signature.") + if (p_signature == NULL) + { + NRF_LOG_WARNING("No signature found."); + return EXT_ERR(NRF_DFU_EXT_ERROR_SIGNATURE_MISSING); + } + + if (signature_type != DFU_SIGNATURE_TYPE_ECDSA_P256_SHA256) + { + NRF_LOG_INFO("Invalid signature type"); + return EXT_ERR(NRF_DFU_EXT_ERROR_WRONG_SIGNATURE_TYPE); + } + + NRF_LOG_INFO("Calculating hash (len: %d)", data_len); + err_code = nrf_crypto_hash_calculate(&hash_context, + &g_nrf_crypto_hash_sha256_info, + p_data, + data_len, + m_sig_hash, + &hash_len); + if (err_code != NRF_SUCCESS) + { + return NRF_DFU_RES_CODE_OPERATION_FAILED; + } + + if (sizeof(m_signature) != signature_len) + { + return NRF_DFU_RES_CODE_OPERATION_FAILED; + } + + // Prepare the signature received over the air. + memcpy(m_signature, p_signature, signature_len); + + // Calculate the signature. + NRF_LOG_INFO("Verify signature"); + + // The signature is in little-endian format. Change it to big-endian format for nrf_crypto use. + nrf_crypto_internal_double_swap_endian_in_place(m_signature, sizeof(m_signature) / 2); + + err_code = nrf_crypto_ecdsa_verify(&verify_context, + &m_public_key, + m_sig_hash, + hash_len, + m_signature, + sizeof(m_signature)); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Signature failed (err_code: 0x%x)", err_code); + NRF_LOG_DEBUG("Signature:"); + NRF_LOG_HEXDUMP_DEBUG(m_signature, sizeof(m_signature)); + NRF_LOG_DEBUG("Hash:"); + NRF_LOG_HEXDUMP_DEBUG(m_sig_hash, hash_len); + NRF_LOG_DEBUG("Public Key:"); + NRF_LOG_HEXDUMP_DEBUG(pk, sizeof(pk)); + NRF_LOG_FLUSH(); + + return NRF_DFU_RES_CODE_INVALID_OBJECT; + } + + NRF_LOG_INFO("Image verified"); + return NRF_DFU_RES_CODE_SUCCESS; +} + + +// Function to calculate the total size of the firmware(s) in the update. +static nrf_dfu_result_t update_data_size_get(dfu_init_command_t const * p_init, uint32_t * p_size) +{ + nrf_dfu_result_t ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_INIT_COMMAND_INVALID); + uint32_t fw_sz = 0; + + if ((p_init->type == DFU_FW_TYPE_APPLICATION || + p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION) && + (p_init->has_app_size == true)) + { + fw_sz = p_init->app_size; + } + else + { + if ((p_init->type & DFU_FW_TYPE_SOFTDEVICE) && (p_init->has_sd_size == true)) + { + fw_sz = p_init->sd_size; + } + + if ((p_init->type & DFU_FW_TYPE_BOOTLOADER) && (p_init->has_bl_size == true)) + { + if (p_init->bl_size <= BOOTLOADER_SIZE) + { + fw_sz += p_init->bl_size; + } + else + { + NRF_LOG_ERROR("BL size (%d) over limit (%d)", p_init->bl_size, BOOTLOADER_SIZE); + fw_sz = 0; + ret_val = NRF_DFU_RES_CODE_INSUFFICIENT_RESOURCES; + } + } + } + + if (fw_sz) + { + *p_size = fw_sz; + ret_val = NRF_DFU_RES_CODE_SUCCESS; + } + else + { + NRF_LOG_ERROR("Init packet does not contain valid firmware size"); + } + + return ret_val; +} + + +/** + * @brief Function to check if single bank update should be used. + * + * @param new_fw_type Firmware type. + */ +static bool use_single_bank(dfu_fw_type_t new_fw_type) +{ + bool result = false; + + // DFU_FW_TYPE_EXTERNAL_APPLICATION never uses single bank + if (((new_fw_type == DFU_FW_TYPE_APPLICATION) || + (new_fw_type == DFU_FW_TYPE_SOFTDEVICE)) && + NRF_DFU_SINGLE_BANK_APP_UPDATES) + { + result = true; + } + + return result; +} + + +// Function to determine whether the new firmware needs a SoftDevice to be present. +static bool update_requires_softdevice(dfu_init_command_t const * p_init) +{ + return ((p_init->sd_req_count > 0) && (p_init->sd_req[0] != SD_REQ_APP_OVERWRITES_SD)); +} + + +// Function to determine whether the SoftDevice can be removed during the update or not. +static bool keep_softdevice(dfu_init_command_t const * p_init) +{ + UNUSED_PARAMETER(p_init); // It's unused when DFU_REQUIRES_SOFTDEVICE is true. + return DFU_REQUIRES_SOFTDEVICE || update_requires_softdevice(p_init); +} + + +/**@brief Function to determine where to temporarily store the incoming firmware. + * This also checks whether the update will fit, and deletes existing + * firmware to make room for the new firmware. + * + * @param[in] p_init Init command. + * @param[in] fw_size The size of the incoming firmware. + * @param[out] p_addr The address at which to initially store the firmware. + * + * @retval NRF_DFU_RES_CODE_SUCCESS If the size check passed and + * an address was found. + * @retval NRF_DFU_RES_CODE_INSUFFICIENT_RESOURCES If the size check failed. + */ +static nrf_dfu_result_t update_data_addr_get(dfu_init_command_t const * p_init, + uint32_t fw_size, + uint32_t * p_addr) +{ + nrf_dfu_result_t ret_val = NRF_DFU_RES_CODE_SUCCESS; + ret_code_t err_code = nrf_dfu_cache_prepare(fw_size, + use_single_bank(p_init->type), + NRF_DFU_FORCE_DUAL_BANK_APP_UPDATES, + keep_softdevice(p_init)); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Can't find room for update"); + ret_val = NRF_DFU_RES_CODE_INSUFFICIENT_RESOURCES; + } + else + { + *p_addr = nrf_dfu_bank1_start_addr(); + NRF_LOG_DEBUG("Write address set to 0x%08x", *p_addr); + } + return ret_val; +} + + +nrf_dfu_result_t nrf_dfu_validation_prevalidate(void) +{ + nrf_dfu_result_t ret_val = NRF_DFU_RES_CODE_SUCCESS; + dfu_command_t const * p_command = &m_packet.command; + dfu_signature_type_t signature_type = DFU_SIGNATURE_TYPE_MIN; + uint8_t const * p_signature = NULL; + uint32_t signature_len = 0; + + if (m_packet.has_signed_command) + { + p_command = &m_packet.signed_command.command; + signature_type = m_packet.signed_command.signature_type; + p_signature = m_packet.signed_command.signature.bytes; + signature_len = m_packet.signed_command.signature.size; + } + + // Validate signature. + if (signature_required(p_command->init.type)) + { + ret_val = nrf_dfu_validation_signature_check(signature_type, + p_signature, + signature_len, + m_init_packet_data_ptr, + m_init_packet_data_len); + } + + // Validate versions. + if (ret_val == NRF_DFU_RES_CODE_SUCCESS) + { + ret_val = nrf_dfu_ver_validation_check(&p_command->init); + } + + if (ret_val != NRF_DFU_RES_CODE_SUCCESS) + { + NRF_LOG_WARNING("Prevalidation failed."); + NRF_LOG_DEBUG("Init command:"); + NRF_LOG_HEXDUMP_DEBUG(m_init_packet_data_ptr, m_init_packet_data_len); + } + + return ret_val; +} + + +nrf_dfu_result_t nrf_dfu_validation_init_cmd_execute(uint32_t * p_dst_data_addr, + uint32_t * p_data_len) +{ + nrf_dfu_result_t ret_val = NRF_DFU_RES_CODE_SUCCESS; + + if (s_dfu_settings.progress.command_offset != s_dfu_settings.progress.command_size) + { + // The object wasn't the right (requested) size. + NRF_LOG_ERROR("Execute with faulty offset"); + ret_val = NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED; + } + else if (m_valid_init_cmd_present) + { + *p_dst_data_addr = nrf_dfu_bank1_start_addr(); + ret_val = update_data_size_get(mp_init, p_data_len); + } + else if (stored_init_cmd_decode()) + { + // Will only get here if init command was received since last reset. + // An init command should not be written to flash until after it's been checked here. + ret_val = nrf_dfu_validation_prevalidate(); + + *p_dst_data_addr = 0; + *p_data_len = 0; + + // Get size of binary. + if (ret_val == NRF_DFU_RES_CODE_SUCCESS) + { + ret_val = update_data_size_get(mp_init, p_data_len); + } + + // Get address where to flash the binary. + if (ret_val == NRF_DFU_RES_CODE_SUCCESS) + { + ret_val = update_data_addr_get(mp_init, *p_data_len, p_dst_data_addr); + } + + // Set flag validating the init command. + if (ret_val == NRF_DFU_RES_CODE_SUCCESS) + { + m_valid_init_cmd_present = true; + } + else + { + dfu_progress_reset(); + } + } + else + { + NRF_LOG_ERROR("Failed to decode init packet"); + ret_val = NRF_DFU_RES_CODE_INVALID_OBJECT; + } + + return ret_val; +} + + +// Function to check the hash received in the init command against the received firmware. +// little_endian specifies the endianness of @p p_hash. +static bool nrf_dfu_validation_hash_ok(uint8_t const * p_hash, uint32_t src_addr, uint32_t data_len, bool little_endian) +{ + ret_code_t err_code; + bool result = true; + uint8_t hash_be[NRF_CRYPTO_HASH_SIZE_SHA256]; + size_t hash_len = NRF_CRYPTO_HASH_SIZE_SHA256; + + nrf_crypto_hash_context_t hash_context = {0}; + + crypto_init(); + + if (little_endian) + { + // Convert to hash to big-endian format for use in nrf_crypto. + nrf_crypto_internal_swap_endian(hash_be, + p_hash, + NRF_CRYPTO_HASH_SIZE_SHA256); + p_hash = hash_be; + } + + NRF_LOG_DEBUG("Hash verification. start address: 0x%x, size: 0x%x", + src_addr, + data_len); + + err_code = nrf_crypto_hash_calculate(&hash_context, + &g_nrf_crypto_hash_sha256_info, + (uint8_t*)src_addr, + data_len, + m_fw_hash, + &hash_len); + + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Could not run hash verification (err_code 0x%x).", err_code); + result = false; + } + else if (memcmp(m_fw_hash, p_hash, NRF_CRYPTO_HASH_SIZE_SHA256) != 0) + { + NRF_LOG_WARNING("Hash verification failed."); + NRF_LOG_DEBUG("Expected FW hash:") + NRF_LOG_HEXDUMP_DEBUG(p_hash, NRF_CRYPTO_HASH_SIZE_SHA256); + NRF_LOG_DEBUG("Actual FW hash:") + NRF_LOG_HEXDUMP_DEBUG(m_fw_hash, NRF_CRYPTO_HASH_SIZE_SHA256); + NRF_LOG_FLUSH(); + + result = false; + } + + return result; +} + + +// Function to check the hash received in the init command against the received firmware. +bool fw_hash_ok(dfu_init_command_t const * p_init, uint32_t fw_start_addr, uint32_t fw_size) +{ + ASSERT(p_init != NULL); + return nrf_dfu_validation_hash_ok((uint8_t *)p_init->hash.hash.bytes, fw_start_addr, fw_size, true); +} + + +// Function to check whether the update contains a SoftDevice and, if so, if it is of a different +// major version than the existing SoftDevice. +static bool is_major_softdevice_update(uint32_t new_sd_addr) +{ + // True if there is no SD right now, but there is a new one coming. This counts as a major update. + bool result = !SD_PRESENT && (SD_MAGIC_NUMBER_GET(new_sd_addr) == SD_MAGIC_NUMBER); + + if (SD_PRESENT && (SD_MAGIC_NUMBER_GET(new_sd_addr) == SD_MAGIC_NUMBER)) + { + // Both SoftDevices are present. + uint32_t current_SD_major = SD_MAJOR_VERSION_EXTRACT(SD_VERSION_GET(MBR_SIZE)); + uint32_t new_SD_major = SD_MAJOR_VERSION_EXTRACT(SD_VERSION_GET(new_sd_addr)); + + result = (current_SD_major != new_SD_major); + + NRF_LOG_INFO("SoftDevice update is a %s version update. Current: %d. New: %d.", + result ? "major" : "minor", + current_SD_major, + new_SD_major); + } + + return result; +} + + +/**@brief Validate the SoftDevice size and magic number in structure found at 0x2000 in received SoftDevice. + * + * @param[in] sd_start_addr Start address of received SoftDevice. + * @param[in] sd_size Size of received SoftDevice in bytes. + */ +static bool softdevice_info_ok(uint32_t sd_start_addr, uint32_t sd_size) +{ + bool result = true; + + if (SD_MAGIC_NUMBER_GET(sd_start_addr) != SD_MAGIC_NUMBER) + { + NRF_LOG_ERROR("The SoftDevice does not contain the magic number identifying it as a SoftDevice."); + result = false; + } + else if (SD_SIZE_GET(sd_start_addr) < ALIGN_TO_PAGE(sd_size + MBR_SIZE)) + { + // The size in the info struct should be rounded up to a page boundary + // and be larger than the actual size + the size of the MBR. + NRF_LOG_ERROR("The SoftDevice size in the info struct is too small compared with the size reported in the init command."); + result = false; + } + + return result; +} + + +static bool boot_validation_extract(boot_validation_t * p_boot_validation, + dfu_init_command_t const * p_init, + uint32_t index, + uint32_t start_addr, + uint32_t data_len, + boot_validation_type_t default_type) +{ + ret_code_t err_code; + size_t hash_len = NRF_CRYPTO_HASH_SIZE_SHA256; + + nrf_crypto_hash_context_t hash_context = {0}; + + memset(p_boot_validation, 0, sizeof(boot_validation_t)); + p_boot_validation->type = (p_init->boot_validation_count > index) + ? (boot_validation_type_t)p_init->boot_validation[index].type + : default_type; // default + + switch(p_boot_validation->type) + { + case NO_VALIDATION: + break; + + case VALIDATE_CRC: + *(uint32_t *)&p_boot_validation->bytes[0] = crc32_compute((uint8_t *)start_addr, data_len, NULL); + break; + + case VALIDATE_SHA256: + err_code = nrf_crypto_hash_calculate(&hash_context, + &g_nrf_crypto_hash_sha256_info, + (uint8_t*)start_addr, + data_len, + p_boot_validation->bytes, + &hash_len); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("nrf_crypto_hash_calculate() failed with error %s", nrf_strerror_get(err_code)); + return false; + } + break; + + case VALIDATE_ECDSA_P256_SHA256: + memcpy(p_boot_validation->bytes, p_init->boot_validation[index].bytes.bytes, p_init->boot_validation[index].bytes.size); + break; + + default: + NRF_LOG_ERROR("Invalid boot validation type: %d", p_boot_validation->type); + return false; + } + + return nrf_dfu_validation_boot_validate(p_boot_validation, start_addr, data_len); +} + + +// The is_trusted argument specifies whether the function should have side effects. +static bool postvalidate_app(dfu_init_command_t const * p_init, uint32_t src_addr, uint32_t data_len, bool is_trusted) +{ + boot_validation_t boot_validation; + + ASSERT(p_init->type == DFU_FW_TYPE_APPLICATION); + + if (!boot_validation_extract(&boot_validation, p_init, 0, src_addr, data_len, VALIDATE_CRC)) + { + return false; + } +#if !NRF_DFU_IN_APP + else if (NRF_BL_APP_SIGNATURE_CHECK_REQUIRED && + (boot_validation.type != VALIDATE_ECDSA_P256_SHA256)) + { + NRF_LOG_WARNING("The boot validation of the app must be a signature check."); + return false; + } +#endif + + if (!is_trusted) + { + return true; + } + + memcpy(&s_dfu_settings.boot_validation_app, &boot_validation, sizeof(boot_validation)); + + s_dfu_settings.bank_1.bank_code = NRF_DFU_BANK_VALID_APP; + + NRF_LOG_DEBUG("Invalidating old application in bank 0."); + s_dfu_settings.bank_0.bank_code = NRF_DFU_BANK_INVALID; + + if (!DFU_REQUIRES_SOFTDEVICE && !update_requires_softdevice(p_init)) + { + // App does not need SD, so it should be placed where SD is. + nrf_dfu_softdevice_invalidate(); + } + + if (!NRF_DFU_DEBUG || + (NRF_DFU_DEBUG && (p_init->has_is_debug == false || p_init->is_debug == false))) + { + s_dfu_settings.app_version = p_init->fw_version; + } + + return true; +} + + +// Function to check a received SoftDevice or Bootloader firmware, or both, +// before it is copied into place. +// The is_trusted argument specifies whether the function should have side effects. +static bool postvalidate_sd_bl(dfu_init_command_t const * p_init, + bool with_sd, + bool with_bl, + uint32_t start_addr, + uint32_t data_len, + bool is_trusted) +{ + boot_validation_t boot_validation_sd = {NO_VALIDATION}; + boot_validation_t boot_validation_bl = {NO_VALIDATION}; + uint32_t bl_start = start_addr; + uint32_t bl_size = data_len; + + ASSERT(with_sd || with_bl); + + if (with_sd) + { + if (!softdevice_info_ok(start_addr, p_init->sd_size)) + { + return false; + } + + if (is_major_softdevice_update(start_addr)) + { + NRF_LOG_WARNING("Invalidating app because it is incompatible with the SoftDevice."); + if (DFU_REQUIRES_SOFTDEVICE && !with_bl) + { + NRF_LOG_ERROR("Major SD update but no BL. Abort to avoid incapacitating the BL."); + return false; + } + } + + if (!boot_validation_extract(&boot_validation_sd, p_init, 0, start_addr, p_init->sd_size, VALIDATE_CRC)) + { + return false; + } + + bl_start += p_init->sd_size; + bl_size -= p_init->sd_size; + } + if (with_bl) + { + if (!boot_validation_extract(&boot_validation_bl, p_init, 0, bl_start, bl_size, NO_VALIDATION)) + { + return false; + } + else if (boot_validation_bl.type != NO_VALIDATION) + { + NRF_LOG_WARNING("Boot validation of bootloader is not supported and will be ignored."); + } + } + + if (!is_trusted) + { + return true; + } + + if (with_sd) + { + if (is_major_softdevice_update(start_addr)) + { + // Invalidate app since it may not be compatible with new SD. + nrf_dfu_bank_invalidate(&s_dfu_settings.bank_0); + } + + memcpy(&s_dfu_settings.boot_validation_softdevice, &boot_validation_sd, sizeof(boot_validation_sd)); + + // Mark the update as valid. + s_dfu_settings.bank_1.bank_code = with_bl ? NRF_DFU_BANK_VALID_SD_BL + : NRF_DFU_BANK_VALID_SD; + + s_dfu_settings.sd_size = p_init->sd_size; + } + else + { + s_dfu_settings.bank_1.bank_code = NRF_DFU_BANK_VALID_BL; + } + + + if (with_bl) + { + memcpy(&s_dfu_settings.boot_validation_bootloader, &boot_validation_bl, sizeof(boot_validation_bl)); + + if (!NRF_DFU_DEBUG || + (NRF_DFU_DEBUG && (p_init->has_is_debug == false || p_init->is_debug == false))) + { + // If the update contains a bootloader, update the version. + // Unless the update is a debug packet. + s_dfu_settings.bootloader_version = p_init->fw_version; + } + } + + return true; +} + + +bool nrf_dfu_validation_boot_validate(boot_validation_t const * p_validation, uint32_t data_addr, uint32_t data_len) +{ + uint8_t const * p_data = (uint8_t*) data_addr; + switch(p_validation->type) + { + case NO_VALIDATION: + return true; + + case VALIDATE_CRC: + { + uint32_t current_crc = *(uint32_t *)p_validation->bytes; + uint32_t crc = crc32_compute(p_data, data_len, NULL); + + if (crc != current_crc) + { + // CRC does not match with what is stored. + NRF_LOG_DEBUG("CRC check of app failed. Return %d", NRF_DFU_DEBUG); + return NRF_DFU_DEBUG; + } + return true; + } + + case VALIDATE_SHA256: + return nrf_dfu_validation_hash_ok(p_validation->bytes, data_addr, data_len, false); + + case VALIDATE_ECDSA_P256_SHA256: + { + nrf_dfu_result_t res_code = nrf_dfu_validation_signature_check( + DFU_SIGNATURE_TYPE_ECDSA_P256_SHA256, + p_validation->bytes, + NRF_CRYPTO_ECDSA_SECP256R1_SIGNATURE_SIZE, + p_data, + data_len); + return (res_code == NRF_DFU_RES_CODE_SUCCESS); + } + + default: + ASSERT(false); + return false; + } +} + + +nrf_dfu_result_t postvalidate(uint32_t data_addr, uint32_t data_len, bool is_trusted) +{ + nrf_dfu_result_t ret_val = NRF_DFU_RES_CODE_SUCCESS; + dfu_init_command_t const * p_init = mp_init; + + if (!fw_hash_ok(p_init, data_addr, data_len)) + { + ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_VERIFICATION_FAILED); + } + else + { + if (p_init->type == DFU_FW_TYPE_APPLICATION) + { + if (!postvalidate_app(p_init, data_addr, data_len, is_trusted)) + { + ret_val = NRF_DFU_RES_CODE_INVALID_OBJECT; + } + } +#if NRF_DFU_SUPPORTS_EXTERNAL_APP + else if (p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION) + { + if (!is_trusted) + { + // This function must be implemented externally + ret_val = nrf_dfu_validation_post_external_app_execute(p_init, is_trusted); + } + else + { + s_dfu_settings.bank_1.bank_code = NRF_DFU_BANK_VALID_EXT_APP; + } + } +#endif // NRF_DFU_SUPPORTS_EXTERNAL_APP + else + { + bool with_sd = p_init->type & DFU_FW_TYPE_SOFTDEVICE; + bool with_bl = p_init->type & DFU_FW_TYPE_BOOTLOADER; + + if (!postvalidate_sd_bl(p_init, with_sd, with_bl, data_addr, data_len, is_trusted)) + { + ret_val = NRF_DFU_RES_CODE_INVALID_OBJECT; + if (is_trusted && with_sd && !DFU_REQUIRES_SOFTDEVICE && + (data_addr == nrf_dfu_softdevice_start_address())) + { + nrf_dfu_softdevice_invalidate(); + } + } + } + } + + if (!is_trusted) + { + if (ret_val == NRF_DFU_RES_CODE_SUCCESS) + { + s_dfu_settings.bank_current = NRF_DFU_CURRENT_BANK_1; + } + else + { + dfu_progress_reset(); + } + } + else + { + if (ret_val == NRF_DFU_RES_CODE_SUCCESS) + { + // Mark the update as complete and valid. + s_dfu_settings.bank_1.image_crc = crc32_compute((uint8_t *)data_addr, data_len, NULL); + s_dfu_settings.bank_1.image_size = data_len; + } + else + { + nrf_dfu_bank_invalidate(&s_dfu_settings.bank_1); + } + + dfu_progress_reset(); + s_dfu_settings.progress.update_start_address = data_addr; + } + + return ret_val; +} + + +nrf_dfu_result_t nrf_dfu_validation_post_data_execute(uint32_t data_addr, uint32_t data_len) +{ + return postvalidate(data_addr, data_len, false); +} + + +nrf_dfu_result_t nrf_dfu_validation_activation_prepare(uint32_t data_addr, uint32_t data_len) +{ + return postvalidate(data_addr, data_len, true); +} + + +bool nrf_dfu_validation_valid_external_app(void) +{ + return s_dfu_settings.bank_1.bank_code == NRF_DFU_BANK_VALID_EXT_APP; +} diff --git a/sdk/components/libraries/bootloader/nrf_bootloader.c b/sdk/components/libraries/bootloader/nrf_bootloader.c new file mode 100644 index 0000000..dd5e506 --- /dev/null +++ b/sdk/components/libraries/bootloader/nrf_bootloader.c @@ -0,0 +1,794 @@ +/** + * Copyright (c) 2016 - 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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 Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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. + * + */ +#include "nrf_bootloader.h" +#include "nrf_dfu_ble.h" +#include "compiler_abstraction.h" +#include "nrf.h" +#include "nrf_sdh.h" +#include "boards.h" +#include "sdk_config.h" +#include "nrf_power.h" +#include "nrf_delay.h" +#include "app_timer.h" +#include "app_usbd_core.h" +#include "app_usbd.h" +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +#include "nrf_dfu.h" +#include "nrf_error.h" +#include "nrf_dfu_settings.h" +#include "nrf_dfu_utils.h" +#include "nrf_dfu_transport.h" +#include "nrf_bootloader_wdt.h" +#include "nrf_bootloader_info.h" +#include "nrf_bootloader_app_start.h" +#include "nrf_bootloader_fw_activation.h" +#include "nrf_bootloader_dfu_timers.h" +#include "app_scheduler.h" +#include "nrf_dfu_validation.h" + +/**@brief Enumeration for specifying current bootloader status. + */ +typedef enum +{ + BOOTLOADER_UPDATING, /**< Bootloader status for indicating that an update is in progress. */ + BOOTLOADER_TIMEOUT, /**< Bootloader status field for indicating that a timeout has occured and current update process should be aborted. */ +} bootloader_status_t; + +static bootloader_status_t m_update_status = BOOTLOADER_UPDATING; /**< Current update status for the bootloader module to ensure correct behaviour when updating settings and when update completes. */ +static bool dfu_startup_packet_received = false; + +static nrf_dfu_observer_t m_user_observer; //= 100) || (NRF_BL_DFU_INACTIVITY_TIMEOUT_MS == 0), + "NRF_BL_DFU_INACTIVITY_TIMEOUT_MS must be 100 ms or more, or 0 to indicate that it is disabled."); + +#if defined(NRF_LOG_BACKEND_FLASH_START_PAGE) +STATIC_ASSERT(NRF_LOG_BACKEND_FLASH_START_PAGE != 0, + "If nrf_log flash backend is used it cannot use space after code because it would collide with settings page."); +#endif + +/**@brief Weak implemenation of nrf_dfu_init + * + * @note This function will be overridden if nrf_dfu.c is + * compiled and linked with the project + */ + #if (__LINT__ != 1) +__WEAK uint32_t nrf_dfu_init(nrf_dfu_observer_t observer) +{ + NRF_LOG_DEBUG("in weak nrf_dfu_init"); + return NRF_SUCCESS; +} +#endif + + +/**@brief Weak implementation of nrf_dfu_init + * + * @note This function must be overridden in application if + * user-specific initialization is needed. + */ +__WEAK uint32_t nrf_dfu_init_user(void) +{ + NRF_LOG_DEBUG("in weak nrf_dfu_init_user"); + return NRF_SUCCESS; +} + +#if NRF_BL_DFU_ALLOW_UPDATE_FROM_APP +static void flash_write_callback(void * p_context) +{ + UNUSED_PARAMETER(p_context); + m_flash_write_done = true; +} +#endif + +static void do_reset(void * p_context) +{ + UNUSED_PARAMETER(p_context); + + NRF_LOG_FINAL_FLUSH(); + +#if NRF_MODULE_ENABLED(NRF_LOG_BACKEND_RTT) + // To allow the buffer to be flushed by the host. + nrf_delay_ms(100); +#endif + + NVIC_SystemReset(); +} + + +static void bootloader_reset(bool do_backup) +{ + NRF_LOG_DEBUG("Resetting bootloader."); + + if (do_backup) + { + m_flash_write_done = false; + nrf_dfu_settings_backup(do_reset); + } + else + { + do_reset(NULL); + } +} + + +static void inactivity_timeout(void) +{ + NRF_LOG_INFO("Inactivity timeout."); + bootloader_reset(true); +} + +static void inactivity_reboot_timeout(void) +{ + if(!dfu_startup_packet_received) + { + m_update_status = BOOTLOADER_TIMEOUT; + NRF_LOG_INFO("DFU startup timeout."); + } + +} + + +/**@brief Function for handling DFU events. + */ +static void dfu_observer(nrf_dfu_evt_type_t evt_type) +{ + switch (evt_type) + { + case NRF_DFU_EVT_DFU_STARTED: + case NRF_DFU_EVT_OBJECT_RECEIVED: + dfu_startup_packet_received = true; + nrf_bootloader_dfu_inactivity_timer_restart( + NRF_BOOTLOADER_MS_TO_TICKS(NRF_BL_DFU_INACTIVITY_TIMEOUT_MS), + inactivity_timeout); + break; + case NRF_DFU_EVT_DFU_COMPLETED: + case NRF_DFU_EVT_DFU_ABORTED: + bootloader_reset(true); + break; + default: + break; + } + + if (m_user_observer) + { + m_user_observer(evt_type); + } +} + + +/**@brief Function for initializing the event scheduler. + */ +static void scheduler_init(void) +{ + APP_SCHED_INIT(SCHED_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE); +} + + +/**@brief Suspend the CPU until an interrupt occurs. + */ +static void wait_for_event(void) +{ +#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD) + (void)sd_app_evt_wait(); +#else + // Wait for an event. + __WFE(); + // Clear the internal event register. + __SEV(); + __WFE(); +#endif +} + + +/**@brief Continually sleep and process tasks whenever woken. + */ +static void loop_forever(void) +{ + while (true) + { + //feed the watchdog if enabled. + nrf_bootloader_wdt_feed(); + + app_sched_execute(); + + if (!NRF_LOG_PROCESS()) + { + wait_for_event(); + } + } +} + +/**@brief Function for initializing button used to enter DFU mode. + */ +static void dfu_enter_button_init(void) +{ + nrf_gpio_cfg_sense_input(NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN, + BUTTON_PULL, + NRF_GPIO_PIN_SENSE_LOW); +} + + +static bool crc_on_valid_app_required(void) +{ + bool ret = true; + if (NRF_BL_APP_CRC_CHECK_SKIPPED_ON_SYSTEMOFF_RESET && + (nrf_power_resetreas_get() & NRF_POWER_RESETREAS_OFF_MASK)) + { + nrf_power_resetreas_clear(NRF_POWER_RESETREAS_OFF_MASK); + ret = false; + } + else if (NRF_BL_APP_CRC_CHECK_SKIPPED_ON_GPREGRET2 && + ((nrf_power_gpregret2_get() & BOOTLOADER_DFU_GPREGRET2_MASK) == BOOTLOADER_DFU_GPREGRET2) + && (nrf_power_gpregret2_get() & BOOTLOADER_DFU_SKIP_CRC_BIT_MASK)) + { + nrf_power_gpregret2_set(nrf_power_gpregret2_get() & ~BOOTLOADER_DFU_SKIP_CRC); + ret = false; + } + else + { + } + + return ret; +} + + + +static bool boot_validate(boot_validation_t const * p_validation, uint32_t data_addr, uint32_t data_len, bool do_crc) +{ + if (!do_crc && (p_validation->type == VALIDATE_CRC)) + { + return true; + } + return nrf_dfu_validation_boot_validate(p_validation, data_addr, data_len); +} + + +/** @brief Function for checking if the main application is valid. + * + * @details This function checks if there is a valid application + * located at Bank 0. + * + * @param[in] do_crc Perform CRC check on application. Only CRC checks + can be skipped. For other boot validation types, + this parameter is ignored. + * + * @retval true If a valid application has been detected. + * @retval false If there is no valid application. + */ +static bool app_is_valid(bool do_crc) +{ + if (s_dfu_settings.bank_0.bank_code != NRF_DFU_BANK_VALID_APP) + { + NRF_LOG_INFO("Boot validation failed. No valid app to boot."); + return false; + } + else if (NRF_BL_APP_SIGNATURE_CHECK_REQUIRED && + (s_dfu_settings.boot_validation_app.type != VALIDATE_ECDSA_P256_SHA256)) + { + NRF_LOG_WARNING("Boot validation failed. The boot validation of the app must be a signature check."); + return false; + } + else if (SD_PRESENT && !boot_validate(&s_dfu_settings.boot_validation_softdevice, MBR_SIZE, s_dfu_settings.sd_size, do_crc)) + { + NRF_LOG_WARNING("Boot validation failed. SoftDevice is present but invalid."); + return false; + } + else if (!boot_validate(&s_dfu_settings.boot_validation_app, nrf_dfu_bank0_start_addr(), s_dfu_settings.bank_0.image_size, do_crc)) + { + NRF_LOG_WARNING("Boot validation failed. App is invalid."); + return false; + } + // The bootloader itself is not checked, since a self-check of this kind gives little to no benefit + // compared to the cost incurred on each bootup. + + NRF_LOG_DEBUG("App is valid"); + return true; +} + + + +/**@brief Function for clearing all DFU enter flags that + * preserve state during reset. + * + * @details This is used to make sure that each of these flags + * is checked only once after reset. + */ +static void dfu_enter_flags_clear(void) +{ + if (NRF_BL_DFU_ENTER_METHOD_PINRESET && + (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk)) + { + // Clear RESETPIN flag. + NRF_POWER->RESETREAS |= POWER_RESETREAS_RESETPIN_Msk; + } + + if (NRF_BL_DFU_ENTER_METHOD_GPREGRET && + ((nrf_power_gpregret_get() & BOOTLOADER_DFU_GPREGRET_MASK) == BOOTLOADER_DFU_GPREGRET) + && (nrf_power_gpregret_get() & BOOTLOADER_DFU_START_BIT_MASK)) + { + // Clear DFU mark in GPREGRET register. + nrf_power_gpregret_set(nrf_power_gpregret_get() & ~BOOTLOADER_DFU_START); + } + + if (NRF_BL_DFU_ENTER_METHOD_BUTTONLESS && + (s_dfu_settings.enter_buttonless_dfu == 1)) + { + // Clear DFU flag in flash settings. + s_dfu_settings.enter_buttonless_dfu = 0; + APP_ERROR_CHECK(nrf_dfu_settings_write(NULL)); + } +} + + +/**@brief Function for checking whether to enter DFU mode or not. + */ +static bool dfu_enter_check(void) +{ + if (!app_is_valid(crc_on_valid_app_required())) + { + NRF_LOG_DEBUG("DFU mode because app is not valid."); + return true; + } + + if (NRF_BL_DFU_ENTER_METHOD_BUTTON && + (nrf_gpio_pin_read(NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN) == 0)) + { + NRF_LOG_DEBUG("DFU mode requested via button."); + return true; + } + + if (NRF_BL_DFU_ENTER_METHOD_PINRESET && + (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk)) + { + NRF_LOG_DEBUG("DFU mode requested via pin-reset."); + return true; + } + + if (NRF_BL_DFU_ENTER_METHOD_GPREGRET && + (nrf_power_gpregret_get() & BOOTLOADER_DFU_START)) + { + NRF_LOG_DEBUG("DFU mode requested via GPREGRET."); + return true; + } + + if (NRF_BL_DFU_ENTER_METHOD_BUTTONLESS && + (s_dfu_settings.enter_buttonless_dfu == 1)) + { + NRF_LOG_DEBUG("DFU mode requested via bootloader settings."); + return true; + } + + return false; +} + + +#if NRF_BL_DFU_ALLOW_UPDATE_FROM_APP +static void postvalidate(void) +{ + NRF_LOG_INFO("Postvalidating update after reset."); + nrf_dfu_validation_init(); + + if (nrf_dfu_validation_init_cmd_present()) + { + uint32_t firmware_start_addr; + uint32_t firmware_size; + + // Execute a previously received init packed. Subsequent executes will have no effect. + if (nrf_dfu_validation_init_cmd_execute(&firmware_start_addr, &firmware_size) == NRF_DFU_RES_CODE_SUCCESS) + { + if (nrf_dfu_validation_prevalidate() == NRF_DFU_RES_CODE_SUCCESS) + { + if (nrf_dfu_validation_activation_prepare(firmware_start_addr, firmware_size) == NRF_DFU_RES_CODE_SUCCESS) + { + NRF_LOG_INFO("Postvalidation successful."); + } + } + } + } + + s_dfu_settings.bank_current = NRF_DFU_CURRENT_BANK_0; + UNUSED_RETURN_VALUE(nrf_dfu_settings_write_and_backup(flash_write_callback)); +} +#endif + +/** + * @brief Function for aborting current application/bootloader jump to to other app/bootloader. + * + * @details This functions will use the address provide to swap the stack pointer and then load + * the address of the reset handler to be executed. It will check current system mode + * (thread/handler) and if in thread mode it will reset into other application. + * If in handler mode \ref isr_abort will be executed to ensure correct exit of handler + * mode and jump into reset handler of other application. + * + * @param[in] start_addr Start address of other application. This address must point to the + initial stack pointer of the application. + * + * @note This function will never return but issue a reset into provided application. + */ +#if defined ( __CC_ARM ) +__asm static void bootloader_util_reset(uint32_t start_addr) +{ + LDR R5, [R0] ; Get App initial MSP for bootloader. + MSR MSP, R5 ; Set the main stack pointer to the applications MSP. + LDR R0, [R0, #0x04] ; Load Reset handler into R0. This will be first argument to branch instruction (BX). + + MOVS R4, #0xFF ; Load ones to R4. + SXTB R4, R4 ; Sign extend R4 to obtain 0xFFFFFFFF instead of 0xFF. + MRS R5, IPSR ; Load IPSR to R5 to check for handler or thread mode. + CMP R5, #0x00 ; Compare, if 0 then we are in thread mode and can continue to reset handler of bootloader. + BNE isr_abort ; If not zero we need to exit current ISR and jump to reset handler of bootloader. + + MOV LR, R4 ; Clear the link register and set to ones to ensure no return, R4 = 0xFFFFFFFF. + BX R0 ; Branch to reset handler of bootloader. + +isr_abort + ; R4 contains ones from line above. Will be popped as R12 when exiting ISR (Cleaning up the registers). + MOV R5, R4 ; Fill with ones before jumping to reset handling. We be popped as LR when exiting ISR. Ensures no return to application. + MOV R6, R0 ; Move address of reset handler to R6. Will be popped as PC when exiting ISR. Ensures the reset handler will be executed when exist ISR. + MOVS r7, #0x21 ; Move MSB reset value of xPSR to R7. Will be popped as xPSR when exiting ISR. xPSR is 0x21000000 thus MSB is 0x21. + REV r7, r7 ; Reverse byte order to put 0x21 as MSB. + PUSH {r4-r7} ; Push everything to new stack to allow interrupt handler to fetch it on exiting the ISR. + + MOVS R4, #0x00 ; Fill with zeros before jumping to reset handling. We be popped as R0 when exiting ISR (Cleaning up of the registers). + MOVS R5, #0x00 ; Fill with zeros before jumping to reset handling. We be popped as R1 when exiting ISR (Cleaning up of the registers). + MOVS R6, #0x00 ; Fill with zeros before jumping to reset handling. We be popped as R2 when exiting ISR (Cleaning up of the registers). + MOVS R7, #0x00 ; Fill with zeros before jumping to reset handling. We be popped as R3 when exiting ISR (Cleaning up of the registers). + PUSH {r4-r7} ; Push zeros (R4-R7) to stack to prepare for exiting the interrupt routine. + + MOVS R0, #0xF9 ; Move the execution return command into register, 0xFFFFFFF9. + SXTB R0, R0 ; Sign extend R0 to obtain 0xFFFFFFF9 instead of 0xF9. + BX R0 ; No return - Handler mode will be exited. Stack will be popped and execution will continue in reset handler initializing other application. + ALIGN +} +#elif defined ( __GNUC__ ) +static inline void bootloader_util_reset (uint32_t start_addr) __attribute__ ((optimize("-fomit-frame-pointer"))); +static inline void bootloader_util_reset(uint32_t start_addr) +{ + __asm volatile( + "ldr r0, [%0]\t\n" // Get App initial MSP for bootloader. + "msr msp, r0\t\n" // Set the main stack pointer to the applications MSP. + "ldr r0, [%0, #0x04]\t\n" // Load Reset handler into R0. + + "movs r4, #0xFF\t\n" // Move ones to R4. + "sxtb r4, r4\t\n" // Sign extend R4 to obtain 0xFFFFFFFF instead of 0xFF. + + "mrs r5, IPSR\t\n" // Load IPSR to R5 to check for handler or thread mode. + "cmp r5, #0x00\t\n" // Compare, if 0 then we are in thread mode and can continue to reset handler of bootloader. + "bne isr_abort\t\n" // If not zero we need to exit current ISR and jump to reset handler of bootloader. + + "mov lr, r4\t\n" // Clear the link register and set to ones to ensure no return. + "bx r0\t\n" // Branch to reset handler of bootloader. + + "isr_abort: \t\n" + + "mov r5, r4\t\n" // Fill with ones before jumping to reset handling. Will be popped as LR when exiting ISR. Ensures no return to application. + "mov r6, r0\t\n" // Move address of reset handler to R6. Will be popped as PC when exiting ISR. Ensures the reset handler will be executed when exist ISR. + "movs r7, #0x21\t\n" // Move MSB reset value of xPSR to R7. Will be popped as xPSR when exiting ISR. xPSR is 0x21000000 thus MSB is 0x21. + "rev r7, r7\t\n" // Reverse byte order to put 0x21 as MSB. + "push {r4-r7}\t\n" // Push everything to new stack to allow interrupt handler to fetch it on exiting the ISR. + + "movs r4, #0x00\t\n" // Fill with zeros before jumping to reset handling. We be popped as R0 when exiting ISR (Cleaning up of the registers). + "movs r5, #0x00\t\n" // Fill with zeros before jumping to reset handling. We be popped as R1 when exiting ISR (Cleaning up of the registers). + "movs r6, #0x00\t\n" // Fill with zeros before jumping to reset handling. We be popped as R2 when exiting ISR (Cleaning up of the registers). + "movs r7, #0x00\t\n" // Fill with zeros before jumping to reset handling. We be popped as R3 when exiting ISR (Cleaning up of the registers). + "push {r4-r7}\t\n" // Push zeros (R4-R7) to stack to prepare for exiting the interrupt routine. + + "movs r0, #0xF9\t\n" // Move the execution return command into register, 0xFFFFFFF9. + "sxtb r0, r0\t\n" // Sign extend R0 to obtain 0xFFFFFFF9 instead of 0xF9. + "bx r0\t\n" // No return - Handler mode will be exited. Stack will be popped and execution will continue in reset handler initializing other application. + ".align\t\n" + :: "r" (start_addr) // Argument list for the gcc assembly. start_addr is %0. + : "r0", "r4", "r5", "r6", "r7" // List of register maintained manually. + ); +} +#elif defined ( __ICCARM__ ) +static inline void bootloader_util_reset(uint32_t start_addr) +{ + asm("ldr r5, [%0]\n" // Get App initial MSP for bootloader. + "msr msp, r5\n" // Set the main stack pointer to the applications MSP. + "ldr r0, [%0, #0x04]\n" // Load Reset handler into R0. + + "movs r4, #0x00\n" // Load zero into R4. + "mvns r4, r4\n" // Invert R4 to ensure it contain ones. + + "mrs r5, IPSR\n" // Load IPSR to R5 to check for handler or thread mode + "cmp r5, #0x00\n" // Compare, if 0 then we are in thread mode and can continue to reset handler of bootloader. + "bne.n isr_abort\n" // If not zero we need to exit current ISR and jump to reset handler of bootloader. + + "mov lr, r4\n" // Clear the link register and set to ones to ensure no return. + "bx r0\n" // Branch to reset handler of bootloader. + + "isr_abort: \n" + // R4 contains ones from line above. We be popped as R12 when exiting ISR (Cleaning up the registers). + "mov r5, r4\n" // Fill with ones before jumping to reset handling. Will be popped as LR when exiting ISR. Ensures no return to application. + "mov r6, r0\n" // Move address of reset handler to R6. Will be popped as PC when exiting ISR. Ensures the reset handler will be executed when exist ISR. + "movs r7, #0x21\n" // Move MSB reset value of xPSR to R7. Will be popped as xPSR when exiting ISR. xPSR is 0x21000000 thus MSB is 0x21. + "rev r7, r7\n" // Reverse byte order to put 0x21 as MSB. + "push {r4-r7}\n" // Push everything to new stack to allow interrupt handler to fetch it on exiting the ISR. + + "movs r4, #0x00\n" // Fill with zeros before jumping to reset handling. We be popped as R0 when exiting ISR (Cleaning up of the registers). + "movs r5, #0x00\n" // Fill with zeros before jumping to reset handling. We be popped as R1 when exiting ISR (Cleaning up of the registers). + "movs r6, #0x00\n" // Fill with zeros before jumping to reset handling. We be popped as R2 when exiting ISR (Cleaning up of the registers). + "movs r7, #0x00\n" // Fill with zeros before jumping to reset handling. We be popped as R3 when exiting ISR (Cleaning up of the registers). + "push {r4-r7}\n" // Push zeros (R4-R7) to stack to prepare for exiting the interrupt routine. + + "movs r0, #0x06\n" // Load 0x06 into R6 to prepare for exec return command. + "mvns r0, r0\n" // Invert 0x06 to obtain EXEC_RETURN, 0xFFFFFFF9. + "bx r0\n" // No return - Handler mode will be exited. Stack will be popped and execution will continue in reset handler initializing other application. + :: "r" (start_addr) // Argument list for the IAR assembly. start_addr is %0. + : "r0", "r4", "r5", "r6", "r7"); // List of register maintained manually. +} +#else +#error Compiler not supported. +#endif + + + +ret_code_t nrf_bootloader_init(nrf_dfu_observer_t observer) +{ + NRF_LOG_DEBUG("In nrf_bootloader_init"); + + ret_code_t ret_val; + nrf_bootloader_fw_activation_result_t activation_result; + uint32_t initial_timeout; + bool dfu_enter = false; + + m_user_observer = observer; + + if (NRF_BL_DFU_ENTER_METHOD_BUTTON) + { + dfu_enter_button_init(); + } + + ret_val = nrf_dfu_settings_init(false); + if (ret_val != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + + #if NRF_BL_DFU_ALLOW_UPDATE_FROM_APP + // Postvalidate if DFU has signaled that update is ready. + if (s_dfu_settings.bank_current == NRF_DFU_CURRENT_BANK_1) + { + postvalidate(); + } + #endif + + // Check if an update needs to be activated and activate it. + activation_result = nrf_bootloader_fw_activate(); + + switch (activation_result) + { + case ACTIVATION_NONE: + initial_timeout = NRF_BOOTLOADER_MS_TO_TICKS(NRF_BL_DFU_INACTIVITY_TIMEOUT_MS); + dfu_enter = dfu_enter_check(); + break; + + case ACTIVATION_SUCCESS_EXPECT_ADDITIONAL_UPDATE: + initial_timeout = NRF_BOOTLOADER_MS_TO_TICKS(NRF_BL_DFU_CONTINUATION_TIMEOUT_MS); + dfu_enter = true; + break; + + case ACTIVATION_SUCCESS: + bootloader_reset(true); + NRF_LOG_ERROR("Unreachable"); + return NRF_ERROR_INTERNAL; // Should not reach this. + + case ACTIVATION_ERROR: + default: + return NRF_ERROR_INTERNAL; + } + + if (dfu_enter) + { + nrf_bootloader_wdt_init(); + scheduler_init(); + dfu_enter_flags_clear(); + + // Call user-defined init function if implemented + ret_val = nrf_dfu_init_user(); + if (ret_val != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + + nrf_bootloader_dfu_inactivity_timer_restart(initial_timeout, inactivity_timeout); + + ret_val = nrf_dfu_init(dfu_observer); + if (ret_val != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + + NRF_LOG_DEBUG("Enter main loop"); + loop_forever(); // This function will never return. + NRF_LOG_ERROR("Unreachable"); + } + else + { + + // Check for only 3 second if is possible to update by usb + nrf_bootloader_wdt_init(); + scheduler_init(); + dfu_enter_flags_clear(); + + // Call user-defined init function if implemented + ret_val = nrf_dfu_init_user(); + if (ret_val != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + + nrf_bootloader_dfu_inactivity_timer_restart(NRF_BOOTLOADER_MS_TO_TICKS(3000), inactivity_reboot_timeout); + + ret_val = nrf_dfu_init(dfu_observer); + if (ret_val != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + for ( ;; ) + { + // feed the watchdog if enabled. + nrf_bootloader_wdt_feed(); + app_sched_execute(); + + if (!NRF_LOG_PROCESS()) + { + wait_for_event(); + } + if (m_update_status == BOOTLOADER_TIMEOUT) + { + // When update has completed or a timeout/reset occured we will return. + break; + } + } + sd_softdevice_disable(); + // Close all transport + //nrf_dfu_transports_close(NULL); + + + //app_timer_stop_all(); + //app_usbd_stop(); // this would trigger an Assert, + + //app_usbd_uninit(); + + // Disable all interrupts + NVIC->ICER[0]=0xFFFFFFFF; + NVIC->ICPR[0]=0xFFFFFFFF; + #if defined(__NRF_NVIC_ISER_COUNT) && __NRF_NVIC_ISER_COUNT == 2 + NVIC->ICER[1]=0xFFFFFFFF; + NVIC->ICPR[1]=0xFFFFFFFF; + #endif + + uint32_t fwd_ret; + uint32_t app_addr; + + if ( *((uint32_t*)(SOFTDEVICE_INFO_STRUCT_ADDRESS+4)) == 0x51B1E5DB) + { + // App starts after SoftDevice + app_addr = SD_SIZE_GET(MBR_SIZE); + fwd_ret = sd_softdevice_vector_table_base_set(app_addr); + } + else + { + + // App starts right after MBR + app_addr = MBR_SIZE; + sd_mbr_command_t command = + { + .command = SD_MBR_COMMAND_IRQ_FORWARD_ADDRESS_SET, + .params.irq_forward_address_set.address = app_addr, + }; + + fwd_ret = sd_mbr_command(&command); + } + + // unlikely failed to forward vector table, manually set forward address + if ( fwd_ret != NRF_SUCCESS ) + { + // MBR use first 4-bytes of SRAM to store foward address + *(uint32_t *)(0x20000000) = app_addr; + } + //nrf_drv_usbd_stop(); + //nrf_drv_usbd_disable(); + //app_usbd_stop(); + NRF_LOG_INFO("STOP"); + NRF_USBD->USBPULLUP = 0; + nrf_delay_ms(20); + NRF_USBD->USBPULLUP = 1; + NRF_LOG_INFO("DELAY"); + //app_usbd_class_remove_all(); + NRF_LOG_INFO("REMOVE"); + while (NRF_LOG_PROCESS()); + // disable interrupt to prevent race condition + //dcd_int_disable(rhport); + + // disable all non-control (bulk + interrupt) endpoints + /*NRF_USBD->INTENCLR |= 0xFF3FC; + for ( uint8_t ep = 1; ep < 8; ep++ ) + { + NRF_USBD->TASKS_STARTEPIN[ep] = 0; + NRF_USBD->TASKS_STARTEPOUT[ep] = 0; + }*/ + + + // disable both ISO + /*NRF_USBD->INTENCLR = (0x1UL << 21) | (0x1UL << 20) | (0x1UL << 11); + NRF_USBD->ISOSPLIT = 0x0000UL; + + NRF_USBD->TASKS_STARTISOIN = 0; + NRF_USBD->TASKS_STARTISOOUT = 0;*/ + + //tu_memclr(_dcd.xfer[EP_ISO_NUM], 2*sizeof(xfer_td_t)); + + // de-activate all non-control + /*NRF_USBD->EPOUTEN = 1UL; + NRF_USBD->EPINEN = 1UL;*/ + + //dcd_int_enable(rhport); + //app_usbd_uninit(); + //app_usbd_stop(); + /*nrf_delay_ms(20); + app_usbd_disable(); + nrf_delay_ms(20);*/ + //app_usbd_enable(); + // jump to app + while (NRF_LOG_PROCESS()); + //ble_dfu_transport_close(NULL); + //nrf_sdh_enable_request(); + //nrf_dfu_transports_close(&usb_dfu_transport); + bootloader_util_reset(app_addr); + } + + // Should not be reached. + return NRF_ERROR_INTERNAL; +} From b211ae51bc85c0e88cb9a510a8f98ad1f00efb60 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 29 Dec 2023 10:23:50 +0000 Subject: [PATCH 02/11] s132 --- Dockerfile | 1 + Makefile | 27 +- boards/s132/Makefile.boards | 431 ++++++++++++ .../s140 => s132/bmd_350_a_r}/Makefile | 3 +- boards/s132/bmd_350_a_r/include/config.h | 15 + .../s132/bmd_350_a_r/include/custom_board.h | 70 ++ boards/s132/secure_bootloader_gcc_nrf52.ld | 162 +++++ .../s132/secure_bootloader_gcc_nrf52_debug.ld | 162 +++++ boards/{ => s140}/Makefile.boards | 4 +- .../arduino-nano-33-ble}/Makefile | 2 +- .../arduino-nano-33-ble}/include/config.h | 0 .../include/custom_board.h | 0 boards/s140/ecg_nrf52_v2_4/Makefile | 5 + boards/s140/ecg_nrf52_v2_4/include/config.h | 17 + .../ecg_nrf52_v2_4/include/custom_board.h | 71 ++ .../s140 => s140/feather-express}/Makefile | 2 +- .../feather-express}/include/config.h | 0 .../feather-express}/include/custom_board.h | 0 boards/s140/generic/Makefile | 4 + .../s140 => s140/generic}/include/config.h | 0 .../generic}/include/custom_board.h | 0 .../s140 => s140/mdk-usb-dongle}/Makefile | 2 +- .../mdk-usb-dongle}/include/config.h | 0 .../mdk-usb-dongle}/include/custom_board.h | 0 boards/{mdk/s140 => s140/mdk}/Makefile | 2 +- .../{mdk/s140 => s140/mdk}/include/config.h | 0 .../s140 => s140/mdk}/include/custom_board.h | 0 .../s140 => s140/particle-argon}/Makefile | 2 +- .../particle-argon}/include/config.h | 0 .../particle-argon}/include/custom_board.h | 0 .../s140 => s140/particle-boron}/Makefile | 2 +- .../particle-boron}/include/config.h | 0 .../particle-boron}/include/custom_board.h | 0 .../s140 => s140/particle-xenon}/Makefile | 2 +- .../particle-xenon}/include/config.h | 0 .../particle-xenon}/include/custom_board.h | 0 .../{pca10056/s140 => s140/pca10056}/Makefile | 2 +- .../s140 => s140/pca10056}/include/config.h | 0 .../{pca10059/s140 => s140/pca10059}/Makefile | 2 +- .../s140 => s140/pca10059}/include/config.h | 0 .../s140 => s140/pitaya-go}/Makefile | 2 +- .../s140 => s140/pitaya-go}/include/config.h | 0 .../pitaya-go}/include/custom_board.h | 0 .../{ => s140}/secure_bootloader_gcc_nrf52.ld | 0 .../secure_bootloader_gcc_nrf52_debug.ld | 0 .../s140 => s140/sparkfun-pro-mini}/Makefile | 2 +- .../sparkfun-pro-mini}/include/config.h | 0 .../sparkfun-pro-mini}/include/custom_board.h | 0 include/sdk_config.h | 6 +- .../bootloader/s132/nrf_bootloader.c | 660 ++++++++++++++++++ .../bootloader/{ => s140}/nrf_bootloader.c | 0 51 files changed, 1630 insertions(+), 30 deletions(-) create mode 100644 boards/s132/Makefile.boards rename boards/{generic/s140 => s132/bmd_350_a_r}/Makefile (63%) create mode 100644 boards/s132/bmd_350_a_r/include/config.h create mode 100644 boards/s132/bmd_350_a_r/include/custom_board.h create mode 100644 boards/s132/secure_bootloader_gcc_nrf52.ld create mode 100644 boards/s132/secure_bootloader_gcc_nrf52_debug.ld rename boards/{ => s140}/Makefile.boards (99%) rename boards/{arduino-nano-33-ble/s140 => s140/arduino-nano-33-ble}/Makefile (89%) rename boards/{arduino-nano-33-ble/s140 => s140/arduino-nano-33-ble}/include/config.h (100%) rename boards/{arduino-nano-33-ble/s140 => s140/arduino-nano-33-ble}/include/custom_board.h (100%) create mode 100644 boards/s140/ecg_nrf52_v2_4/Makefile create mode 100644 boards/s140/ecg_nrf52_v2_4/include/config.h create mode 100644 boards/s140/ecg_nrf52_v2_4/include/custom_board.h rename boards/{particle-xenon/s140 => s140/feather-express}/Makefile (85%) rename boards/{feather-express/s140 => s140/feather-express}/include/config.h (100%) rename boards/{feather-express/s140 => s140/feather-express}/include/custom_board.h (100%) create mode 100644 boards/s140/generic/Makefile rename boards/{generic/s140 => s140/generic}/include/config.h (100%) rename boards/{generic/s140 => s140/generic}/include/custom_board.h (100%) rename boards/{mdk-usb-dongle/s140 => s140/mdk-usb-dongle}/Makefile (85%) rename boards/{mdk-usb-dongle/s140 => s140/mdk-usb-dongle}/include/config.h (100%) rename boards/{mdk-usb-dongle/s140 => s140/mdk-usb-dongle}/include/custom_board.h (100%) rename boards/{mdk/s140 => s140/mdk}/Makefile (89%) rename boards/{mdk/s140 => s140/mdk}/include/config.h (100%) rename boards/{mdk/s140 => s140/mdk}/include/custom_board.h (100%) rename boards/{particle-boron/s140 => s140/particle-argon}/Makefile (85%) rename boards/{particle-argon/s140 => s140/particle-argon}/include/config.h (100%) rename boards/{particle-argon/s140 => s140/particle-argon}/include/custom_board.h (100%) rename boards/{feather-express/s140 => s140/particle-boron}/Makefile (85%) rename boards/{particle-boron/s140 => s140/particle-boron}/include/config.h (100%) rename boards/{particle-boron/s140 => s140/particle-boron}/include/custom_board.h (100%) rename boards/{particle-argon/s140 => s140/particle-xenon}/Makefile (85%) rename boards/{particle-xenon/s140 => s140/particle-xenon}/include/config.h (100%) rename boards/{particle-xenon/s140 => s140/particle-xenon}/include/custom_board.h (100%) rename boards/{pca10056/s140 => s140/pca10056}/Makefile (85%) rename boards/{pca10056/s140 => s140/pca10056}/include/config.h (100%) rename boards/{pca10059/s140 => s140/pca10059}/Makefile (85%) rename boards/{pca10059/s140 => s140/pca10059}/include/config.h (100%) rename boards/{pitaya-go/s140 => s140/pitaya-go}/Makefile (89%) rename boards/{pitaya-go/s140 => s140/pitaya-go}/include/config.h (100%) rename boards/{pitaya-go/s140 => s140/pitaya-go}/include/custom_board.h (100%) rename boards/{ => s140}/secure_bootloader_gcc_nrf52.ld (100%) rename boards/{ => s140}/secure_bootloader_gcc_nrf52_debug.ld (100%) rename boards/{sparkfun-pro-mini/s140 => s140/sparkfun-pro-mini}/Makefile (85%) rename boards/{sparkfun-pro-mini/s140 => s140/sparkfun-pro-mini}/include/config.h (100%) rename boards/{sparkfun-pro-mini/s140 => s140/sparkfun-pro-mini}/include/custom_board.h (100%) create mode 100644 sdk/components/libraries/bootloader/s132/nrf_bootloader.c rename sdk/components/libraries/bootloader/{ => s140}/nrf_bootloader.c (100%) diff --git a/Dockerfile b/Dockerfile index 032208a..14c0506 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,6 +6,7 @@ ENV NORDIC_SDK_PATH="/root/nrf_sdk/15.3.0" ENV PATH="$PATH:/root/gcc-arm-none-eabi-8-2018-q4-major/bin:/root/nrf-command-line-tools/bin:/root/.local/bin" ENV BOARD="" +ENV SOFTDEVICE="" ENV DEBUG=0 ENV NRF_DFU_BL_ACCEPT_SAME_VERSION=1 ENV NRF_DFU_REQUIRE_SIGNED_APP_UPDATE=1 diff --git a/Makefile b/Makefile index 3ffb433..16a6046 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,12 @@ BOARD ?= +SOFTDEVICE ?= BOARD_LIST := $(sort $(subst /,,$(subst boards/,,$(dir $(wildcard boards/*/))))) rwildcard = $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d)) default: check-env ## Builds the bootloaded for selected board ifneq ($(filter $(BOARD),$(BOARD_LIST)),) - $(MAKE) merge -C boards/$(BOARD)/s140 + $(MAKE) merge -C boards/$(SOFTDEVICE)/$(BOARD) else $(error Run `make` with a board specified: ($(BOARD_LIST))) endif @@ -17,19 +18,19 @@ help: ## Lists all available commands and a brief description. all: check-env $(BOARD_LIST) ## Builds the bootloader for all boards $(BOARD_LIST): ## Builds the bootloader for the specified board - $(MAKE) -C boards/$@/s140 + $(MAKE) -C boards/$(SOFTDEVICE)/$@ flash: default ## Builds and flashes the bootloader over nrfjprog - $(MAKE) flash -C boards/$(BOARD)/s140 + $(MAKE) flash -C boards/$(SOFTDEVICE)/$(BOARD) clean_build: clean ## Builds and creates a DFU .zip package - $(MAKE) -C boards/$(BOARD)/s140 dfu_package + $(MAKE) -C boards/$(SOFTDEVICE)/$(BOARD) dfu_package clean_flash: clean_build ## Performs a clean build and flashes it via jLink - $(MAKE) -C boards/$(BOARD)/s140 erase flash + $(MAKE) -C boards/$(SOFTDEVICE)/$(BOARD) erase flash usb_flash: check_port default ## Flashes the .zip over USB - $(MAKE) -C boards/$(BOARD)/s140 usb_flash + $(MAKE) -C boards/$(SOFTDEVICE)/$(BOARD) usb_flash check_port: ifndef PORT @@ -38,13 +39,13 @@ endif clean: check-env patch ## Cleans the environment for the specified board ifneq ($(filter $(BOARD),$(BOARD_LIST)),) - @cd boards/$(BOARD)/s140 && $(MAKE) clean + @cd boards/$(SOFTDEVICE)/$(BOARD) && $(MAKE) clean @rm -rf $(BOARD).hex - @rm -f $(BOARD)_s140.zip - @rm -f debug_$(BOARD)_s140.zip + @rm -f $(BOARD)_$(SOFTDEVICE).zip + @rm -f debug_$(BOARD)_$(SOFTDEVICE).zip else @for board in $(BOARD_LIST); do \ - cd boards/$$board/s140 && $(MAKE) clean; \ + cd boards/$(SOFTDEVICE)/$$board && $(MAKE) clean; \ cd ../../..; \ done @rm -f *.hex @@ -69,9 +70,9 @@ patch: ## Patches the files in the nordic SDK to support additional bootloader f patch --forward --unified $(NORDIC_SDK_PATH)/$${file} ./sdk/$${file}; \ fi \ done; - @for file in $(subst ./sdk/,,$(call rwildcard,./sdk/,*nrf_bootloader.c)); do \ - echo "Copying $$file to $(NORDIC_SDK_PATH)/$${file#./sdk/}"; \ - cp ./sdk/$$file $(NORDIC_SDK_PATH)/$${file#./sdk/}; \ + @for file in $(subst ./sdk/,,$(call rwildcard,./sdk/,*/$(SOFTDEVICE)/nrf_bootloader.c)); do \ + echo "Copying $$file to $(NORDIC_SDK_PATH)/components/libraries/bootloader/nrf_bootloader.c"; \ + cp ./sdk/$$file $(NORDIC_SDK_PATH)/components/libraries/bootloader/nrf_bootloader.c; \ done; @for file in $(subst ./sdk/,,$(call rwildcard,./sdk/,*nrf_dfu_validation.c)); do \ echo "Copying $$file to $(NORDIC_SDK_PATH)/$${file#./sdk/}"; \ diff --git a/boards/s132/Makefile.boards b/boards/s132/Makefile.boards new file mode 100644 index 0000000..09a44c6 --- /dev/null +++ b/boards/s132/Makefile.boards @@ -0,0 +1,431 @@ +PROJECT_NAME := secure_bootloader_ble_s132 +TARGETS := nrf52832_xxaa +OUTPUT_DIRECTORY := _build + +DEBUG ?= 0 +SD_REQ := 0xB6 + +SECURE := secure + +ifeq ($(NRF_DFU_REQUIRE_SIGNED_APP_UPDATE), 0) +SECURE = unsecure +endif + +GIT_VERSION := $(shell git describe --always --tags) +BOARD_DIST := $(BOARD)_bootloader-$(GIT_VERSION)_$(SECURE) + +ifeq ($(DEBUG), 1) +GIT_VERSION = $(shell git describe --dirty --always --tags) +BOARD_DIST := debug_$(BOARD)_bootloader-$(GIT_VERSION)_$(SECURE) +endif + + + +BUILD_NUMBER := 1 + +ifdef TRAVIS_TAG +BUILD_NUMBER := $(shell python $(TRAVIS_BUILD_DIR)/blver.py --toHex=$(TRAVIS_TAG)) +$(info HEX_REVISION=$(BUILD_NUMBER)) +endif + +SDK_ROOT := $(NORDIC_SDK_PATH) +PROJ_DIR := $(CURDIR)/../../.. +BOARD_DIR := $(CURDIR) +BOARD_NAME := $(notdir $(patsubst %/,%,$(dir $(CURDIR)))) +OUTPUT_DIRECTORY := $(PROJ_DIR)/_build_$(BOARD_NAME) + +ifeq ($(DEBUG), 1) +$(OUTPUT_DIRECTORY)/nrf52832_xxaa.out: \ + LINKER_SCRIPT := $(BOARD_DIR)/../secure_bootloader_gcc_nrf52_debug.ld +else +$(OUTPUT_DIRECTORY)/nrf52832_xxaa.out: \ + LINKER_SCRIPT := $(BOARD_DIR)/../secure_bootloader_gcc_nrf52.ld +endif + +# Source files common to all targets +SRC_FILES += \ + $(SDK_ROOT)/modules/nrfx/mdk/gcc_startup_nrf52.S \ + $(SDK_ROOT)/components/libraries/log/src/nrf_log_default_backends.c \ + $(SDK_ROOT)/components/libraries/log/src/nrf_log_frontend.c \ + $(SDK_ROOT)/components/libraries/log/src/nrf_log_str_formatter.c \ + $(SDK_ROOT)/components/libraries/util/app_error_weak.c \ + $(SDK_ROOT)/components/libraries/scheduler/app_scheduler.c \ + $(SDK_ROOT)/components/libraries/util/app_util_platform.c \ + $(SDK_ROOT)/components/libraries/util/app_util_platform.c \ + $(SDK_ROOT)/components/libraries/crc32/crc32.c \ + $(SDK_ROOT)/components/libraries/mem_manager/mem_manager.c \ + $(SDK_ROOT)/components/libraries/util/nrf_assert.c \ + $(SDK_ROOT)/components/libraries/atomic_fifo/nrf_atfifo.c \ + $(SDK_ROOT)/components/libraries/atomic/nrf_atomic.c \ + $(SDK_ROOT)/components/libraries/balloc/nrf_balloc.c \ + $(SDK_ROOT)/external/fprintf/nrf_fprintf.c \ + $(SDK_ROOT)/external/fprintf/nrf_fprintf_format.c \ + $(SDK_ROOT)/components/libraries/fstorage/nrf_fstorage.c \ + $(SDK_ROOT)/components/libraries/fstorage/nrf_fstorage_nvmc.c \ + $(SDK_ROOT)/components/libraries/fstorage/nrf_fstorage_sd.c \ + $(SDK_ROOT)/components/libraries/memobj/nrf_memobj.c \ + $(SDK_ROOT)/components/libraries/queue/nrf_queue.c \ + $(SDK_ROOT)/components/libraries/ringbuf/nrf_ringbuf.c \ + $(SDK_ROOT)/components/libraries/experimental_section_vars/nrf_section_iter.c \ + $(SDK_ROOT)/components/libraries/strerror/nrf_strerror.c \ + $(SDK_ROOT)/components/libraries/sha256/sha256.c \ + $(SDK_ROOT)/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecc.c \ + $(SDK_ROOT)/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecdh.c \ + $(SDK_ROOT)/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecdsa.c \ + $(SDK_ROOT)/components/libraries/slip/slip.c \ + $(SDK_ROOT)/integration/nrfx/legacy/nrf_drv_clock.c \ + $(SDK_ROOT)/integration/nrfx/legacy/nrf_drv_power.c \ + $(SDK_ROOT)/modules/nrfx/hal/nrf_nvmc.c \ + $(SDK_ROOT)/modules/nrfx/soc/nrfx_atomic.c \ + $(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_clock.c \ + $(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_power.c \ + $(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_systick.c \ + $(SDK_ROOT)/modules/nrfx/mdk/system_nrf52.c \ + $(SDK_ROOT)/components/boards/boards.c \ + $(SDK_ROOT)/components/softdevice/common/nrf_sdh.c \ + $(SDK_ROOT)/components/softdevice/common/nrf_sdh_ble.c \ + $(SDK_ROOT)/components/softdevice/common/nrf_sdh_soc.c \ + $(SDK_ROOT)/modules/nrfx/hal/nrf_nvmc.c \ + $(SDK_ROOT)/modules/nrfx/soc/nrfx_atomic.c \ + $(SDK_ROOT)/components/libraries/crypto/nrf_crypto_ecc.c \ + $(SDK_ROOT)/components/libraries/crypto/nrf_crypto_ecdsa.c \ + $(SDK_ROOT)/components/libraries/crypto/nrf_crypto_hash.c \ + $(SDK_ROOT)/components/libraries/crypto/nrf_crypto_init.c \ + $(SDK_ROOT)/components/libraries/crypto/nrf_crypto_shared.c \ + $(PROJ_DIR)/dfu_public_key.c \ + $(PROJ_DIR)/main.c \ + $(SDK_ROOT)/components/libraries/bootloader/dfu/nrf_dfu_svci.c \ + $(SDK_ROOT)/components/libraries/bootloader/dfu/nrf_dfu_svci_handler.c \ + $(SDK_ROOT)/components/libraries/svc/nrf_svc_handler.c \ + $(SDK_ROOT)/components/libraries/bootloader/nrf_bootloader.c \ + $(SDK_ROOT)/components/libraries/bootloader/nrf_bootloader_app_start.c \ + $(SDK_ROOT)/components/libraries/bootloader/nrf_bootloader_app_start_final.c \ + $(SDK_ROOT)/components/libraries/bootloader/nrf_bootloader_dfu_timers.c \ + $(SDK_ROOT)/components/libraries/bootloader/nrf_bootloader_fw_activation.c \ + $(SDK_ROOT)/components/libraries/bootloader/nrf_bootloader_info.c \ + $(SDK_ROOT)/components/libraries/bootloader/nrf_bootloader_wdt.c \ + $(SDK_ROOT)/external/nano-pb/pb_common.c \ + $(SDK_ROOT)/external/nano-pb/pb_decode.c \ + $(SDK_ROOT)/components/libraries/crypto/backend/nrf_sw/nrf_sw_backend_hash.c \ + $(SDK_ROOT)/components/libraries/bootloader/dfu/dfu-cc.pb.c \ + $(SDK_ROOT)/components/libraries/bootloader/dfu/nrf_dfu.c \ + $(SDK_ROOT)/components/libraries/bootloader/ble_dfu/nrf_dfu_ble.c \ + $(SDK_ROOT)/components/libraries/bootloader/dfu/nrf_dfu_flash.c \ + $(SDK_ROOT)/components/libraries/bootloader/dfu/nrf_dfu_handling_error.c \ + $(SDK_ROOT)/components/libraries/bootloader/dfu/nrf_dfu_mbr.c \ + $(SDK_ROOT)/components/libraries/bootloader/dfu/nrf_dfu_req_handler.c \ + $(SDK_ROOT)/components/libraries/bootloader/dfu/nrf_dfu_settings.c \ + $(SDK_ROOT)/components/libraries/bootloader/dfu/nrf_dfu_settings_svci.c \ + $(SDK_ROOT)/components/libraries/bootloader/dfu/nrf_dfu_transport.c \ + $(SDK_ROOT)/components/libraries/bootloader/dfu/nrf_dfu_utils.c \ + $(SDK_ROOT)/components/libraries/bootloader/dfu/nrf_dfu_validation.c \ + $(SDK_ROOT)/components/libraries/bootloader/dfu/nrf_dfu_ver_validation.c \ + $(SDK_ROOT)/components/libraries/bootloader/serial_dfu/nrf_dfu_serial.c \ + $(SDK_ROOT)/external/utf_converter/utf.c \ + $(SDK_ROOT)/components/ble/common/ble_srv_common.c \ + $(SDK_ROOT)/components/libraries/crypto/backend/oberon/oberon_backend_chacha_poly_aead.c \ + $(SDK_ROOT)/components/libraries/crypto/backend/oberon/oberon_backend_ecc.c \ + $(SDK_ROOT)/components/libraries/crypto/backend/oberon/oberon_backend_ecdh.c \ + $(SDK_ROOT)/components/libraries/crypto/backend/oberon/oberon_backend_ecdsa.c \ + $(SDK_ROOT)/components/libraries/crypto/backend/oberon/oberon_backend_eddsa.c \ + $(SDK_ROOT)/components/libraries/crypto/backend/oberon/oberon_backend_hash.c \ + $(SDK_ROOT)/components/libraries/crypto/backend/oberon/oberon_backend_hmac.c \ + $(SDK_ROOT)/components/libraries/bsp/bsp.c \ + $(SDK_ROOT)/components/libraries/timer/app_timer.c \ + $(SDK_ROOT)/components/libraries/sortlist/nrf_sortlist.c \ + $(SDK_ROOT)/components/libraries/button/app_button.c \ + $(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_gpiote.c \ + $(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_pwm.c \ + +ifeq ($(DEBUG), 1) +SRC_FILES += \ + $(SDK_ROOT)/components/libraries/log/src/nrf_log_backend_rtt.c \ + $(SDK_ROOT)/components/libraries/log/src/nrf_log_backend_serial.c \ + $(SDK_ROOT)/external/segger_rtt/SEGGER_RTT.c \ + $(SDK_ROOT)/external/segger_rtt/SEGGER_RTT_Syscalls_GCC.c \ + $(SDK_ROOT)/external/segger_rtt/SEGGER_RTT_printf.c \ + +endif +# Include folders common to all targets +INC_FOLDERS += \ + $(SDK_ROOT)/components/libraries/crypto/backend/micro_ecc \ + $(SDK_ROOT)/components/libraries/memobj \ + $(SDK_ROOT)/components/softdevice/s132/headers/nrf52 \ + $(SDK_ROOT)/components/libraries/sha256 \ + $(SDK_ROOT)/components/libraries/crc32 \ + $(SDK_ROOT)/components/libraries/experimental_section_vars \ + $(SDK_ROOT)/components/libraries/mem_manager \ + $(SDK_ROOT)/components/libraries/fstorage \ + $(SDK_ROOT)/components/libraries/util \ + $(SDK_ROOT)/modules/nrfx/hal \ + $(SDK_ROOT)/modules/nrfx \ + $(SDK_ROOT)/external/nrf_oberon/include \ + $(SDK_ROOT)/components/libraries/crypto/backend/oberon \ + $(SDK_ROOT)/components/libraries/crypto/backend/cifra \ + $(SDK_ROOT)/components/libraries/atomic \ + $(SDK_ROOT)/integration/nrfx \ + $(SDK_ROOT)/components/libraries/crypto/backend/cc310_bl \ + $(SDK_ROOT)/external/nrf_cc310/include \ + $(SDK_ROOT)/components/libraries/log/src \ + $(SDK_ROOT)/components/libraries/bootloader/dfu \ + $(SDK_ROOT)/components/ble/common \ + $(SDK_ROOT)/components/libraries/delay \ + $(SDK_ROOT)/components/libraries/svc \ + $(SDK_ROOT)/components/libraries/stack_info \ + $(SDK_ROOT)/components/libraries/crypto/backend/nrf_hw \ + $(SDK_ROOT)/components/libraries/log \ + $(SDK_ROOT)/components/libraries/sortlist \ + $(SDK_ROOT)/external/nrf_oberon \ + $(SDK_ROOT)/components/libraries/strerror \ + $(SDK_ROOT)/components/libraries/crypto/backend/mbedtls \ + $(SDK_ROOT)/components/boards \ + $(SDK_ROOT)/components/libraries/crypto/backend/cc310 \ + $(SDK_ROOT)/components/libraries/bootloader \ + $(SDK_ROOT)/components/softdevice/s132/headers \ + $(SDK_ROOT)/components/libraries/crypto \ + $(SDK_ROOT)/external/micro-ecc/micro-ecc \ + $(PROJ_DIR)/include \ + $(SDK_ROOT)/components/libraries/crypto/backend/optiga \ + $(SDK_ROOT)/components/libraries/scheduler \ + $(SDK_ROOT)/external/nrf_cc310_bl/include \ + $(SDK_ROOT)/modules/nrfx/drivers/include \ + $(SDK_ROOT)/external/fprintf \ + $(SDK_ROOT)/components/toolchain/cmsis/include \ + $(SDK_ROOT)/components/libraries/balloc \ + $(SDK_ROOT)/components/libraries/atomic_fifo \ + $(PROJ_DIR) \ + $(SDK_ROOT)/components/libraries/crypto/backend/nrf_sw \ + $(SDK_ROOT)/modules/nrfx/mdk \ + $(BOARD_DIR)/include \ + $(SDK_ROOT)/components/libraries/bootloader/ble_dfu \ + $(SDK_ROOT)/components/softdevice/common \ + $(SDK_ROOT)/external/nano-pb \ + $(SDK_ROOT)/components/libraries/queue \ + $(SDK_ROOT)/components/libraries/mutex \ + $(SDK_ROOT)/components/libraries/ringbuf \ + $(SDK_ROOT)/integration/nrfx \ + $(SDK_ROOT)/modules/nrfx/mdk \ + $(SDK_ROOT)/integration/nrfx \ + $(SDK_ROOT)/integration/nrfx/legacy \ + $(SDK_ROOT)/external/segger_rtt \ + $(SDK_ROOT)/components/libraries/slip \ + $(SDK_ROOT)/components/libraries/queue \ + $(SDK_ROOT)/components/libraries/mutex \ + $(SDK_ROOT)/components/libraries/ringbuf \ + $(SDK_ROOT)/external/utf_converter \ + $(SDK_ROOT)/components/libraries/bsp \ + $(SDK_ROOT)/components/libraries/button \ + $(SDK_ROOT)/components/libraries/timer \ + $(SDK_ROOT)/components/libraries/button \ + $(SDK_ROOT)/integration/nrfx/legacy \ + $(SDK_ROOT)/modules/nrfx/drivers/include \ + $(SDK_ROOT)/components/libraries/pwm \ + +# Libraries common to all targets +LIB_FILES += \ + $(SDK_ROOT)/external/nrf_oberon/lib/cortex-m4/hard-float/liboberon_2.0.7.a \ + $(SDK_ROOT)/external/micro-ecc/nrf52hf_armgcc/armgcc/micro_ecc_lib_nrf52.a \ + +ifeq ($(DEBUG), 1) +OPT = -Og -g3 +else +OPT = -O3 -g3 +endif + +OPT += -flto + +# C flags common to all targets +CFLAGS += $(OPT) +CFLAGS += -DBLE_STACK_SUPPORT_REQD +CFLAGS += -DFLOAT_ABI_HARD +CFLAGS += -DNRF52 +CFLAGS += -DNRF52832_XXAA +CFLAGS += -DNRF_DFU_SETTINGS_VERSION=2 +CFLAGS += -DNRF_DFU_SVCI_ENABLED +CFLAGS += -DNRF_SD_BLE_API_VERSION=6 +CFLAGS += -DS132 +CFLAGS += -DSOFTDEVICE_PRESENT +CFLAGS += -DSVC_INTERFACE_CALL_AS_NORMAL_FUNCTION +CFLAGS += -DuECC_ENABLE_VLI_API=0 +CFLAGS += -DuECC_OPTIMIZATION_LEVEL=3 +CFLAGS += -DuECC_SQUARE_FUNC=0 +CFLAGS += -DuECC_SUPPORT_COMPRESSED_POINT=0 +CFLAGS += -DuECC_VLI_NATIVE_LITTLE_ENDIAN=1 +CFLAGS += -DCONFIG_GPIO_AS_PINRESET +#CFLAGS += -DNRF_DFU_BLE_ADV_NAME=\"$(NRF_DFU_BLE_ADV_NAME)\" +CFLAGS += -DCONFIG_NFCT_PINS_AS_GPIOS +CFLAGS += -mcpu=cortex-m4 +CFLAGS += -mthumb -mabi=aapcs +CFLAGS += -Wall -Werror +CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 +# keep every function in a separate section, this allows linker to discard unused ones +CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing +CFLAGS += -fno-builtin -fshort-enums +ifeq ($(DEBUG),1) +CFLAGS += -DBOOTLOADER_DEBUG +CFLAGS += -DDEBUG_NRF +CFLAGS += -DDEBUG +CFLAGS += -DNRF_DFU_DEBUG_VERSION +endif + +ifeq ($(NRF_DFU_REQUIRE_SIGNED_APP_UPDATE), 1) +CFLAGS += -DNRF_DFU_REQUIRE_SIGNED_APP_UPDATE=1 +else +CFLAGS += -DNRF_DFU_REQUIRE_SIGNED_APP_UPDATE=0 +endif + +ifeq ($(NRF_DFU_BL_ACCEPT_SAME_VERSION), 1) +CFLAGS += -DNRF_DFU_BL_ACCEPT_SAME_VERSION=1 +else +CFLAGS += -DNRF_DFU_BL_ACCEPT_SAME_VERSION=0 +endif + +ifeq ($(NRF_BL_APP_SIGNATURE_CHECK_REQUIRED), 1) +CFLAGS += -DNRF_BL_APP_SIGNATURE_CHECK_REQUIRED=1 +else +CFLAGS += -DNRF_BL_APP_SIGNATURE_CHECK_REQUIRED=0 +endif + +ifeq ($(NRF_DFU_BL_ALLOW_DOWNGRADE), 1) +CFLAGS += -DNRF_DFU_BL_ALLOW_DOWNGRADE=1 +endif + +ifeq ($(BOARD_USE_SF_CLOCK), 1) +CFLAGS += -DBOARD_USE_SF_CLOCK=1 +endif + +# C++ flags common to all targets +CXXFLAGS += $(OPT) + +# Assembler flags common to all targets +ASMFLAGS += -g3 +ASMFLAGS += -mcpu=cortex-m4 +ASMFLAGS += -mthumb -mabi=aapcs +ASMFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 +ASMFLAGS += -DBLE_STACK_SUPPORT_REQD +ASMFLAGS += -DFLOAT_ABI_HARD +ASMFLAGS += -DNRF52 +ASMFLAGS += -DNRF52832_XXAA +ASMFLAGS += -DNRF_DFU_SETTINGS_VERSION=2 +ASMFLAGS += -DNRF_DFU_SVCI_ENABLED +ASMFLAGS += -DNRF_SD_BLE_API_VERSION=6 +ASMFLAGS += -DS132 +ASMFLAGS += -DSOFTDEVICE_PRESENT +ASMFLAGS += -DSVC_INTERFACE_CALL_AS_NORMAL_FUNCTION +ASMFLAGS += -DuECC_ENABLE_VLI_API=0 +ASMFLAGS += -DuECC_OPTIMIZATION_LEVEL=3 +ASMFLAGS += -DuECC_SQUARE_FUNC=0 +ASMFLAGS += -DuECC_SUPPORT_COMPRESSED_POINT=0 +ASMFLAGS += -DuECC_VLI_NATIVE_LITTLE_ENDIAN=1 +ASMFLAGS += -DCONFIG_GPIO_AS_PINRESET +ASMFLAGS += -DNRF_DFU_BLE_ADV_NAME=\"$(NRF_DFU_BLE_ADV_NAME)\" +ifeq ($(DEBUG),1) +ASMFLAGS += -DBOOTLOADER_DEBUG +ASMFLAGS += -DNRF_DFU_DEBUG_VERSION +endif + +ifeq ($(NRF_DFU_REQUIRE_SIGNED_APP_UPDATE), 1) +ASMFLAGS += -DNRF_DFU_REQUIRE_SIGNED_APP_UPDATE=1 +else +ASMFLAGS += -DNRF_DFU_REQUIRE_SIGNED_APP_UPDATE=0 +endif + +ifeq ($(NRF_DFU_BL_ACCEPT_SAME_VERSION), 1) +ASMFLAGS += -DNRF_DFU_BL_ACCEPT_SAME_VERSION=1 +else +ASMFLAGS += -DNRF_DFU_BL_ACCEPT_SAME_VERSION=0 +endif + +ifeq ($(NRF_BL_APP_SIGNATURE_CHECK_REQUIRED), 1) +ASMFLAGS += -DNRF_BL_APP_SIGNATURE_CHECK_REQUIRED=1 +else +ASMFLAGS += -DNRF_BL_APP_SIGNATURE_CHECK_REQUIRED=0 +endif + +ifeq ($(NRF_DFU_BL_ALLOW_DOWNGRADE), 1) +ASMFLAGS += -DNRF_DFU_BL_ALLOW_DOWNGRADE=1 +endif + +ifeq ($(BOARD_USE_SF_CLOCK), 1) +ASMFLAGS += -DBOARD_USE_SF_CLOCK=1 +endif + +# Linker flags +LDFLAGS += $(OPT) +LDFLAGS += -mthumb -mabi=aapcs -L$(SDK_ROOT)/modules/nrfx/mdk -T$(LINKER_SCRIPT) +LDFLAGS += -mcpu=cortex-m4 +LDFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 +# let linker dump unused sections +LDFLAGS += -Wl,--gc-sections +# use newlib in nano version +LDFLAGS += --specs=nano.specs + +nrf52832_xxaa: CFLAGS += -D__HEAP_SIZE=0 +nrf52832_xxaa: ASMFLAGS += -D__HEAP_SIZE=0 + +# Add standard libraries at the very end of the linker input, after all objects +# that may need symbols provided by these libraries. +LIB_FILES += -lc -lnosys -lm + + +.PHONY: default help + +# Default target - first one defined +default: nrf52832_xxaa + +TEMPLATE_PATH := $(SDK_ROOT)/components/toolchain/gcc + +include $(TEMPLATE_PATH)/Makefile.common + +$(foreach target, $(TARGETS), $(call define_target, $(target))) + +.PHONY: flash_all flash_bootloader flash_softdevice erase + +# Flash the program +flash_bootloader: default + @echo Flashing: $$(OUTPUT_DIRECTORY)/$(BOARD_DIST).hex + nrfjprog -f nrf52 --program $(OUTPUT_DIRECTORY)/nrf52832_xxaa.hex --sectoranduicrerase +ifeq ($(BOARD), "pca10059") + nrfjprog --memwr 0x10001304 --val 0xFFFFFFFD +endif + nrfjprog -f nrf52 --reset + +# Flash softdevice +flash_softdevice: dfu_package + @echo Flashing: s132_nrf52_6.1.1_softdevice.hex + nrfjprog -f nrf52 --program $(SDK_ROOT)/components/softdevice/s132/hex/s132_nrf52_6.1.1_softdevice.hex --sectorerase + nrfjprog -f nrf52 --reset + +flash: dfu_package + @echo Flashing: $(OUTPUT_DIRECTORY)/$(BOARD_DIST).hex + nrfjprog -f nrf52 --program $(OUTPUT_DIRECTORY)/$(BOARD_DIST)_s132.hex --sectoranduicrerase +ifeq ($(BOARD), "pca10059") + nrfjprog --memwr 0x10001304 --val 0xFFFFFFFD +endif + +usb_flash: $(OUTPUT_DIRECTORY)/$(BOARD_DIST)_s132.zip +ifndef PORT + $(error PORT must be defined to perform usb serial flashing) +endif + nrfutil dfu usb-serial -pkg $(OUTPUT_DIRECTORY)/$(BOARD_DIST)_s132.zip -p $(PORT) + +$(OUTPUT_DIRECTORY)/$(BOARD_DIST)_s132.zip: merge + nrfutil pkg generate --sd-req $(SD_REQ) --hw-version 52 --key-file $(PROJ_DIR)/private.pem --bootloader-version $(BUILD_NUMBER) --bootloader $(OUTPUT_DIRECTORY)/nrf52832_xxaa.hex --softdevice $(SDK_ROOT)/components/softdevice/s132/hex/s132_nrf52_6.1.1_softdevice.hex $(OUTPUT_DIRECTORY)/$(BOARD_DIST)_s132.zip + +$(OUTPUT_DIRECTORY)/$(BOARD_DIST).zip: default + nrfutil pkg generate --sd-req $(SD_REQ) --hw-version 52 --key-file $(PROJ_DIR)/private.pem --bootloader-version $(BUILD_NUMBER) --bootloader $(OUTPUT_DIRECTORY)/nrf52832_xxaa.hex $(OUTPUT_DIRECTORY)/$(BOARD_DIST).zip + +dfu_package: $(OUTPUT_DIRECTORY)/$(BOARD_DIST)_s132.zip $(OUTPUT_DIRECTORY)/$(BOARD_DIST).zip + +# Merge application and softdevice +merge: default + @echo Merging application and softdevice... + mergehex -m $(OUTPUT_DIRECTORY)/nrf52832_xxaa.hex $(SDK_ROOT)/components/softdevice/s132/hex/s132_nrf52_6.1.1_softdevice.hex -o $(OUTPUT_DIRECTORY)/$(BOARD_DIST)_s132.hex + +erase: + nrfjprog -f nrf52 --eraseall + +SDK_CONFIG_FILE := ../config/sdk_config.h +CMSIS_CONFIG_TOOL := $(SDK_ROOT)/external_tools/cmsisconfig/CMSIS_Configuration_Wizard.jar +sdk_config: + java -jar $(CMSIS_CONFIG_TOOL) $(SDK_CONFIG_FILE) diff --git a/boards/generic/s140/Makefile b/boards/s132/bmd_350_a_r/Makefile similarity index 63% rename from boards/generic/s140/Makefile rename to boards/s132/bmd_350_a_r/Makefile index e9c8b5e..40802af 100644 --- a/boards/generic/s140/Makefile +++ b/boards/s132/bmd_350_a_r/Makefile @@ -1,4 +1,5 @@ -include ../../Makefile.boards +include ../Makefile.boards CFLAGS += -DBOARD_CUSTOM + ASMFLAGS += -DBOARD_CUSTOM diff --git a/boards/s132/bmd_350_a_r/include/config.h b/boards/s132/bmd_350_a_r/include/config.h new file mode 100644 index 0000000..e4d75f6 --- /dev/null +++ b/boards/s132/bmd_350_a_r/include/config.h @@ -0,0 +1,15 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#ifndef NRF_DFU_BLE_ADV_NAME +#define NRF_DFU_BLE_ADV_NAME "TRIGGER_DFU" +#endif + +#define BLEDIS_MANUFACTURER "Man" +#define BLEDIS_MODEL "nRF52832 Board" + +#ifndef NRF_DFU_BL_ALLOW_DOWNGRADE +#define NRF_DFU_BL_ALLOW_DOWNGRADE 1 +#endif +#endif + diff --git a/boards/s132/bmd_350_a_r/include/custom_board.h b/boards/s132/bmd_350_a_r/include/custom_board.h new file mode 100644 index 0000000..c15eb79 --- /dev/null +++ b/boards/s132/bmd_350_a_r/include/custom_board.h @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2023-Giovanni Bonomini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of the 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 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 CUSTOM_BOARD_H +#define CUSTOM_BOARD_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nrf_gpio.h" + +#define LEDS_NUMBER 1 +/* +GREEN 12 0.12 +*/ + +#define LED_1 NRF_GPIO_PIN_MAP(0,12) + +#define LEDS_ACTIVE_STATE 1 + +#define LEDS_LIST { LED_1 } + +#define LEDS_INV_MASK LEDS_MASK + +#define BSP_LED_0 LED_1 + +#define BUTTONS_NUMBER 2 + +#define BUTTON_1 NRF_GPIO_PIN_MAP(0,13) + +#define BUTTON_2 NRF_GPIO_PIN_MAP(0,14) + +#define BUTTON_PULL NRF_GPIO_PIN_NOPULL +#define BUTTONS_ACTIVE_STATE 1 + +#define BUTTONS_LIST { BUTTON_1, BUTTON_2 } + +#define BSP_BUTTON_0 BUTTON_1 +#define BSP_BUTTON_1 BUTTON_2 + +#ifdef __cplusplus +} +#endif + +#endif // CUSTOM_BOARD_H diff --git a/boards/s132/secure_bootloader_gcc_nrf52.ld b/boards/s132/secure_bootloader_gcc_nrf52.ld new file mode 100644 index 0000000..a4ca69e --- /dev/null +++ b/boards/s132/secure_bootloader_gcc_nrf52.ld @@ -0,0 +1,162 @@ +/* Linker script to configure memory regions. */ + +SEARCH_DIR(.) +GROUP(-lgcc -lc -lnosys) + +MEMORY +{ + FLASH (rx) : ORIGIN = 0xE0000, LENGTH = 0x186A0 /** 100KB **/ + RAM (rwx) : ORIGIN = 0x20003600, LENGTH = 0xCA00 + uicr_bootloader_start_address (r) : ORIGIN = 0x00000FF8, LENGTH = 0x4 + bootloader_settings_page (r) : ORIGIN = 0x0007F000, LENGTH = 0x1000 + uicr_mbr_params_page (r) : ORIGIN = 0x00000FFC, LENGTH = 0x4 + mbr_params_page (r) : ORIGIN = 0x0007E000, LENGTH = 0x1000 + + DBL_RESET (rwx) : ORIGIN = 0x20006000, LENGTH = 0x04 +} + +SECTIONS +{ + . = ALIGN(4); + .uicr_bootloader_start_address : + { + PROVIDE(__start_uicr_bootloader_start_address = .); + KEEP(*(SORT(.uicr_bootloader_start_address*))) + PROVIDE(__stop_uicr_bootloader_start_address = .); + } > uicr_bootloader_start_address + . = ALIGN(4); + .bootloader_settings_page(NOLOAD) : + { + PROVIDE(__start_bootloader_settings_page = .); + KEEP(*(SORT(.bootloader_settings_page*))) + PROVIDE(__stop_bootloader_settings_page = .); + } > bootloader_settings_page + . = ALIGN(4); + .uicr_mbr_params_page : + { + PROVIDE(__start_uicr_mbr_params_page = .); + KEEP(*(SORT(.uicr_mbr_params_page*))) + PROVIDE(__stop_uicr_mbr_params_page = .); + } > uicr_mbr_params_page + . = ALIGN(4); + .dbl_reset(NOLOAD) : + { + + } > DBL_RESET + .mbr_params_page(NOLOAD) : + { + PROVIDE(__start_mbr_params_page = .); + KEEP(*(SORT(.mbr_params_page*))) + PROVIDE(__stop_mbr_params_page = .); + } > mbr_params_page +} + +SECTIONS +{ + . = ALIGN(4); + .mem_section_dummy_ram : + { + } + .log_dynamic_data : + { + PROVIDE(__start_log_dynamic_data = .); + KEEP(*(SORT(.log_dynamic_data*))) + PROVIDE(__stop_log_dynamic_data = .); + } > RAM + .log_filter_data : + { + PROVIDE(__start_log_filter_data = .); + KEEP(*(SORT(.log_filter_data*))) + PROVIDE(__stop_log_filter_data = .); + } > RAM + .fs_data : + { + PROVIDE(__start_fs_data = .); + KEEP(*(.fs_data)) + PROVIDE(__stop_fs_data = .); + } > RAM + +} INSERT AFTER .data; + +SECTIONS +{ + .mem_section_dummy_rom : + { + } + .crypto_data : + { + PROVIDE(__start_crypto_data = .); + KEEP(*(SORT(.crypto_data*))) + PROVIDE(__stop_crypto_data = .); + } > FLASH + .nrf_queue : + { + PROVIDE(__start_nrf_queue = .); + KEEP(*(.nrf_queue)) + PROVIDE(__stop_nrf_queue = .); + } > FLASH + .dfu_trans : + { + PROVIDE(__start_dfu_trans = .); + KEEP(*(SORT(.dfu_trans*))) + PROVIDE(__stop_dfu_trans = .); + } > FLASH + .svc_data : + { + PROVIDE(__start_svc_data = .); + KEEP(*(.svc_data)) + PROVIDE(__stop_svc_data = .); + } > FLASH + .log_const_data : + { + PROVIDE(__start_log_const_data = .); + KEEP(*(SORT(.log_const_data*))) + PROVIDE(__stop_log_const_data = .); + } > FLASH + .nrf_balloc : + { + PROVIDE(__start_nrf_balloc = .); + KEEP(*(.nrf_balloc)) + PROVIDE(__stop_nrf_balloc = .); + } > FLASH + .log_backends : + { + PROVIDE(__start_log_backends = .); + KEEP(*(SORT(.log_backends*))) + PROVIDE(__stop_log_backends = .); + } > FLASH + .sdh_ble_observers : + { + PROVIDE(__start_sdh_ble_observers = .); + KEEP(*(SORT(.sdh_ble_observers*))) + PROVIDE(__stop_sdh_ble_observers = .); + } > FLASH + .sdh_req_observers : + { + PROVIDE(__start_sdh_req_observers = .); + KEEP(*(SORT(.sdh_req_observers*))) + PROVIDE(__stop_sdh_req_observers = .); + } > FLASH + .sdh_state_observers : + { + PROVIDE(__start_sdh_state_observers = .); + KEEP(*(SORT(.sdh_state_observers*))) + PROVIDE(__stop_sdh_state_observers = .); + } > FLASH + .sdh_stack_observers : + { + PROVIDE(__start_sdh_stack_observers = .); + KEEP(*(SORT(.sdh_stack_observers*))) + PROVIDE(__stop_sdh_stack_observers = .); + } > FLASH + .sdh_soc_observers : + { + PROVIDE(__start_sdh_soc_observers = .); + KEEP(*(SORT(.sdh_soc_observers*))) + PROVIDE(__stop_sdh_soc_observers = .); + } > FLASH + +} INSERT AFTER .text + + +INCLUDE "nrf_common.ld" diff --git a/boards/s132/secure_bootloader_gcc_nrf52_debug.ld b/boards/s132/secure_bootloader_gcc_nrf52_debug.ld new file mode 100644 index 0000000..a4ca69e --- /dev/null +++ b/boards/s132/secure_bootloader_gcc_nrf52_debug.ld @@ -0,0 +1,162 @@ +/* Linker script to configure memory regions. */ + +SEARCH_DIR(.) +GROUP(-lgcc -lc -lnosys) + +MEMORY +{ + FLASH (rx) : ORIGIN = 0xE0000, LENGTH = 0x186A0 /** 100KB **/ + RAM (rwx) : ORIGIN = 0x20003600, LENGTH = 0xCA00 + uicr_bootloader_start_address (r) : ORIGIN = 0x00000FF8, LENGTH = 0x4 + bootloader_settings_page (r) : ORIGIN = 0x0007F000, LENGTH = 0x1000 + uicr_mbr_params_page (r) : ORIGIN = 0x00000FFC, LENGTH = 0x4 + mbr_params_page (r) : ORIGIN = 0x0007E000, LENGTH = 0x1000 + + DBL_RESET (rwx) : ORIGIN = 0x20006000, LENGTH = 0x04 +} + +SECTIONS +{ + . = ALIGN(4); + .uicr_bootloader_start_address : + { + PROVIDE(__start_uicr_bootloader_start_address = .); + KEEP(*(SORT(.uicr_bootloader_start_address*))) + PROVIDE(__stop_uicr_bootloader_start_address = .); + } > uicr_bootloader_start_address + . = ALIGN(4); + .bootloader_settings_page(NOLOAD) : + { + PROVIDE(__start_bootloader_settings_page = .); + KEEP(*(SORT(.bootloader_settings_page*))) + PROVIDE(__stop_bootloader_settings_page = .); + } > bootloader_settings_page + . = ALIGN(4); + .uicr_mbr_params_page : + { + PROVIDE(__start_uicr_mbr_params_page = .); + KEEP(*(SORT(.uicr_mbr_params_page*))) + PROVIDE(__stop_uicr_mbr_params_page = .); + } > uicr_mbr_params_page + . = ALIGN(4); + .dbl_reset(NOLOAD) : + { + + } > DBL_RESET + .mbr_params_page(NOLOAD) : + { + PROVIDE(__start_mbr_params_page = .); + KEEP(*(SORT(.mbr_params_page*))) + PROVIDE(__stop_mbr_params_page = .); + } > mbr_params_page +} + +SECTIONS +{ + . = ALIGN(4); + .mem_section_dummy_ram : + { + } + .log_dynamic_data : + { + PROVIDE(__start_log_dynamic_data = .); + KEEP(*(SORT(.log_dynamic_data*))) + PROVIDE(__stop_log_dynamic_data = .); + } > RAM + .log_filter_data : + { + PROVIDE(__start_log_filter_data = .); + KEEP(*(SORT(.log_filter_data*))) + PROVIDE(__stop_log_filter_data = .); + } > RAM + .fs_data : + { + PROVIDE(__start_fs_data = .); + KEEP(*(.fs_data)) + PROVIDE(__stop_fs_data = .); + } > RAM + +} INSERT AFTER .data; + +SECTIONS +{ + .mem_section_dummy_rom : + { + } + .crypto_data : + { + PROVIDE(__start_crypto_data = .); + KEEP(*(SORT(.crypto_data*))) + PROVIDE(__stop_crypto_data = .); + } > FLASH + .nrf_queue : + { + PROVIDE(__start_nrf_queue = .); + KEEP(*(.nrf_queue)) + PROVIDE(__stop_nrf_queue = .); + } > FLASH + .dfu_trans : + { + PROVIDE(__start_dfu_trans = .); + KEEP(*(SORT(.dfu_trans*))) + PROVIDE(__stop_dfu_trans = .); + } > FLASH + .svc_data : + { + PROVIDE(__start_svc_data = .); + KEEP(*(.svc_data)) + PROVIDE(__stop_svc_data = .); + } > FLASH + .log_const_data : + { + PROVIDE(__start_log_const_data = .); + KEEP(*(SORT(.log_const_data*))) + PROVIDE(__stop_log_const_data = .); + } > FLASH + .nrf_balloc : + { + PROVIDE(__start_nrf_balloc = .); + KEEP(*(.nrf_balloc)) + PROVIDE(__stop_nrf_balloc = .); + } > FLASH + .log_backends : + { + PROVIDE(__start_log_backends = .); + KEEP(*(SORT(.log_backends*))) + PROVIDE(__stop_log_backends = .); + } > FLASH + .sdh_ble_observers : + { + PROVIDE(__start_sdh_ble_observers = .); + KEEP(*(SORT(.sdh_ble_observers*))) + PROVIDE(__stop_sdh_ble_observers = .); + } > FLASH + .sdh_req_observers : + { + PROVIDE(__start_sdh_req_observers = .); + KEEP(*(SORT(.sdh_req_observers*))) + PROVIDE(__stop_sdh_req_observers = .); + } > FLASH + .sdh_state_observers : + { + PROVIDE(__start_sdh_state_observers = .); + KEEP(*(SORT(.sdh_state_observers*))) + PROVIDE(__stop_sdh_state_observers = .); + } > FLASH + .sdh_stack_observers : + { + PROVIDE(__start_sdh_stack_observers = .); + KEEP(*(SORT(.sdh_stack_observers*))) + PROVIDE(__stop_sdh_stack_observers = .); + } > FLASH + .sdh_soc_observers : + { + PROVIDE(__start_sdh_soc_observers = .); + KEEP(*(SORT(.sdh_soc_observers*))) + PROVIDE(__stop_sdh_soc_observers = .); + } > FLASH + +} INSERT AFTER .text + + +INCLUDE "nrf_common.ld" diff --git a/boards/Makefile.boards b/boards/s140/Makefile.boards similarity index 99% rename from boards/Makefile.boards rename to boards/s140/Makefile.boards index f6a34ac..bce84d8 100644 --- a/boards/Makefile.boards +++ b/boards/s140/Makefile.boards @@ -36,10 +36,10 @@ OUTPUT_DIRECTORY := $(PROJ_DIR)/_build_$(BOARD_NAME) ifeq ($(DEBUG), 1) $(OUTPUT_DIRECTORY)/nrf52840_xxaa.out: \ - LINKER_SCRIPT := $(BOARD_DIR)/../../secure_bootloader_gcc_nrf52_debug.ld + LINKER_SCRIPT := $(BOARD_DIR)/../secure_bootloader_gcc_nrf52_debug.ld else $(OUTPUT_DIRECTORY)/nrf52840_xxaa.out: \ - LINKER_SCRIPT := $(BOARD_DIR)/../../secure_bootloader_gcc_nrf52.ld + LINKER_SCRIPT := $(BOARD_DIR)/../secure_bootloader_gcc_nrf52.ld endif # Source files common to all targets diff --git a/boards/arduino-nano-33-ble/s140/Makefile b/boards/s140/arduino-nano-33-ble/Makefile similarity index 89% rename from boards/arduino-nano-33-ble/s140/Makefile rename to boards/s140/arduino-nano-33-ble/Makefile index 914e1e4..bb860f6 100644 --- a/boards/arduino-nano-33-ble/s140/Makefile +++ b/boards/s140/arduino-nano-33-ble/Makefile @@ -1,4 +1,4 @@ -include ../../Makefile.boards +include ../Makefile.boards CFLAGS += -DBOARD_CUSTOM diff --git a/boards/arduino-nano-33-ble/s140/include/config.h b/boards/s140/arduino-nano-33-ble/include/config.h similarity index 100% rename from boards/arduino-nano-33-ble/s140/include/config.h rename to boards/s140/arduino-nano-33-ble/include/config.h diff --git a/boards/arduino-nano-33-ble/s140/include/custom_board.h b/boards/s140/arduino-nano-33-ble/include/custom_board.h similarity index 100% rename from boards/arduino-nano-33-ble/s140/include/custom_board.h rename to boards/s140/arduino-nano-33-ble/include/custom_board.h diff --git a/boards/s140/ecg_nrf52_v2_4/Makefile b/boards/s140/ecg_nrf52_v2_4/Makefile new file mode 100644 index 0000000..40802af --- /dev/null +++ b/boards/s140/ecg_nrf52_v2_4/Makefile @@ -0,0 +1,5 @@ +include ../Makefile.boards + +CFLAGS += -DBOARD_CUSTOM + +ASMFLAGS += -DBOARD_CUSTOM diff --git a/boards/s140/ecg_nrf52_v2_4/include/config.h b/boards/s140/ecg_nrf52_v2_4/include/config.h new file mode 100644 index 0000000..044a870 --- /dev/null +++ b/boards/s140/ecg_nrf52_v2_4/include/config.h @@ -0,0 +1,17 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#ifndef NRF_DFU_BLE_ADV_NAME +#define NRF_DFU_BLE_ADV_NAME "ECG_DFU" +#endif +#define BLEDIS_MANUFACTURER "ddB0515" +#define BLEDIS_MODEL "nRF52840 BBoard" + +#define APP_USBD_VID 0x239A +#define APP_USBD_PID 0x0029 +#endif + +#ifndef NRF_DFU_BL_ALLOW_DOWNGRADE +#define NRF_DFU_BL_ALLOW_DOWNGRADE 1 +#endif + diff --git a/boards/s140/ecg_nrf52_v2_4/include/custom_board.h b/boards/s140/ecg_nrf52_v2_4/include/custom_board.h new file mode 100644 index 0000000..1fe3201 --- /dev/null +++ b/boards/s140/ecg_nrf52_v2_4/include/custom_board.h @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2023-Giovanni Bonomini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of the 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 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 CUSTOM_BOARD_H +#define CUSTOM_BOARD_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nrf_gpio.h" + +#define LEDS_NUMBER 3 +/* +GREEN 45 1.13 +RED 37 1.05 +BLUE 46 1.14 +*/ +#define LED_1 NRF_GPIO_PIN_MAP(1,14) +#define LED_2 NRF_GPIO_PIN_MAP(1,5) +#define LED_3 NRF_GPIO_PIN_MAP(1,13) + +#define LEDS_ACTIVE_STATE 1 + +#define LEDS_LIST { LED_1, LED_2, LED_3 } + +#define LEDS_INV_MASK LEDS_MASK + +#define BSP_LED_0 LED_1 +#define BSP_LED_1 LED_2 +#define BSP_LED_2 LED_3 + +#define BUTTONS_NUMBER 1 + +#define BUTTON_1 NRF_GPIO_PIN_MAP(1,10) +#define BUTTON_PULL NRF_GPIO_PIN_NOPULL +#define BUTTONS_ACTIVE_STATE 1 + +#define BUTTONS_LIST { BUTTON_1 } + +#define BSP_BUTTON_0 BUTTON_1 + +#ifdef __cplusplus +} +#endif + +#endif // CUSTOM_BOARD_H diff --git a/boards/particle-xenon/s140/Makefile b/boards/s140/feather-express/Makefile similarity index 85% rename from boards/particle-xenon/s140/Makefile rename to boards/s140/feather-express/Makefile index 01165fe..2e0d715 100644 --- a/boards/particle-xenon/s140/Makefile +++ b/boards/s140/feather-express/Makefile @@ -1,4 +1,4 @@ -include ../../Makefile.boards +include ../Makefile.boards CFLAGS += -DBOARD_CUSTOM diff --git a/boards/feather-express/s140/include/config.h b/boards/s140/feather-express/include/config.h similarity index 100% rename from boards/feather-express/s140/include/config.h rename to boards/s140/feather-express/include/config.h diff --git a/boards/feather-express/s140/include/custom_board.h b/boards/s140/feather-express/include/custom_board.h similarity index 100% rename from boards/feather-express/s140/include/custom_board.h rename to boards/s140/feather-express/include/custom_board.h diff --git a/boards/s140/generic/Makefile b/boards/s140/generic/Makefile new file mode 100644 index 0000000..c72618e --- /dev/null +++ b/boards/s140/generic/Makefile @@ -0,0 +1,4 @@ +include ../Makefile.boards + +CFLAGS += -DBOARD_CUSTOM +ASMFLAGS += -DBOARD_CUSTOM diff --git a/boards/generic/s140/include/config.h b/boards/s140/generic/include/config.h similarity index 100% rename from boards/generic/s140/include/config.h rename to boards/s140/generic/include/config.h diff --git a/boards/generic/s140/include/custom_board.h b/boards/s140/generic/include/custom_board.h similarity index 100% rename from boards/generic/s140/include/custom_board.h rename to boards/s140/generic/include/custom_board.h diff --git a/boards/mdk-usb-dongle/s140/Makefile b/boards/s140/mdk-usb-dongle/Makefile similarity index 85% rename from boards/mdk-usb-dongle/s140/Makefile rename to boards/s140/mdk-usb-dongle/Makefile index 1f6dbfb..ed3e42d 100644 --- a/boards/mdk-usb-dongle/s140/Makefile +++ b/boards/s140/mdk-usb-dongle/Makefile @@ -1,4 +1,4 @@ -include ../../Makefile.boards +include ../Makefile.boards CFLAGS += -DBOARD_CUSTOM diff --git a/boards/mdk-usb-dongle/s140/include/config.h b/boards/s140/mdk-usb-dongle/include/config.h similarity index 100% rename from boards/mdk-usb-dongle/s140/include/config.h rename to boards/s140/mdk-usb-dongle/include/config.h diff --git a/boards/mdk-usb-dongle/s140/include/custom_board.h b/boards/s140/mdk-usb-dongle/include/custom_board.h similarity index 100% rename from boards/mdk-usb-dongle/s140/include/custom_board.h rename to boards/s140/mdk-usb-dongle/include/custom_board.h diff --git a/boards/mdk/s140/Makefile b/boards/s140/mdk/Makefile similarity index 89% rename from boards/mdk/s140/Makefile rename to boards/s140/mdk/Makefile index bb4c9b5..00d79ab 100644 --- a/boards/mdk/s140/Makefile +++ b/boards/s140/mdk/Makefile @@ -1,4 +1,4 @@ -include ../../Makefile.boards +include ../Makefile.boards CFLAGS += -DBOARD_CUSTOM diff --git a/boards/mdk/s140/include/config.h b/boards/s140/mdk/include/config.h similarity index 100% rename from boards/mdk/s140/include/config.h rename to boards/s140/mdk/include/config.h diff --git a/boards/mdk/s140/include/custom_board.h b/boards/s140/mdk/include/custom_board.h similarity index 100% rename from boards/mdk/s140/include/custom_board.h rename to boards/s140/mdk/include/custom_board.h diff --git a/boards/particle-boron/s140/Makefile b/boards/s140/particle-argon/Makefile similarity index 85% rename from boards/particle-boron/s140/Makefile rename to boards/s140/particle-argon/Makefile index 01165fe..2e0d715 100644 --- a/boards/particle-boron/s140/Makefile +++ b/boards/s140/particle-argon/Makefile @@ -1,4 +1,4 @@ -include ../../Makefile.boards +include ../Makefile.boards CFLAGS += -DBOARD_CUSTOM diff --git a/boards/particle-argon/s140/include/config.h b/boards/s140/particle-argon/include/config.h similarity index 100% rename from boards/particle-argon/s140/include/config.h rename to boards/s140/particle-argon/include/config.h diff --git a/boards/particle-argon/s140/include/custom_board.h b/boards/s140/particle-argon/include/custom_board.h similarity index 100% rename from boards/particle-argon/s140/include/custom_board.h rename to boards/s140/particle-argon/include/custom_board.h diff --git a/boards/feather-express/s140/Makefile b/boards/s140/particle-boron/Makefile similarity index 85% rename from boards/feather-express/s140/Makefile rename to boards/s140/particle-boron/Makefile index 01165fe..2e0d715 100644 --- a/boards/feather-express/s140/Makefile +++ b/boards/s140/particle-boron/Makefile @@ -1,4 +1,4 @@ -include ../../Makefile.boards +include ../Makefile.boards CFLAGS += -DBOARD_CUSTOM diff --git a/boards/particle-boron/s140/include/config.h b/boards/s140/particle-boron/include/config.h similarity index 100% rename from boards/particle-boron/s140/include/config.h rename to boards/s140/particle-boron/include/config.h diff --git a/boards/particle-boron/s140/include/custom_board.h b/boards/s140/particle-boron/include/custom_board.h similarity index 100% rename from boards/particle-boron/s140/include/custom_board.h rename to boards/s140/particle-boron/include/custom_board.h diff --git a/boards/particle-argon/s140/Makefile b/boards/s140/particle-xenon/Makefile similarity index 85% rename from boards/particle-argon/s140/Makefile rename to boards/s140/particle-xenon/Makefile index 01165fe..2e0d715 100644 --- a/boards/particle-argon/s140/Makefile +++ b/boards/s140/particle-xenon/Makefile @@ -1,4 +1,4 @@ -include ../../Makefile.boards +include ../Makefile.boards CFLAGS += -DBOARD_CUSTOM diff --git a/boards/particle-xenon/s140/include/config.h b/boards/s140/particle-xenon/include/config.h similarity index 100% rename from boards/particle-xenon/s140/include/config.h rename to boards/s140/particle-xenon/include/config.h diff --git a/boards/particle-xenon/s140/include/custom_board.h b/boards/s140/particle-xenon/include/custom_board.h similarity index 100% rename from boards/particle-xenon/s140/include/custom_board.h rename to boards/s140/particle-xenon/include/custom_board.h diff --git a/boards/pca10056/s140/Makefile b/boards/s140/pca10056/Makefile similarity index 85% rename from boards/pca10056/s140/Makefile rename to boards/s140/pca10056/Makefile index e79c888..231c98c 100644 --- a/boards/pca10056/s140/Makefile +++ b/boards/s140/pca10056/Makefile @@ -1,4 +1,4 @@ -include ../../Makefile.boards +include ../Makefile.boards CFLAGS += -DBOARD_PCA10056 diff --git a/boards/pca10056/s140/include/config.h b/boards/s140/pca10056/include/config.h similarity index 100% rename from boards/pca10056/s140/include/config.h rename to boards/s140/pca10056/include/config.h diff --git a/boards/pca10059/s140/Makefile b/boards/s140/pca10059/Makefile similarity index 85% rename from boards/pca10059/s140/Makefile rename to boards/s140/pca10059/Makefile index 8b72874..6c2e12b 100644 --- a/boards/pca10059/s140/Makefile +++ b/boards/s140/pca10059/Makefile @@ -1,4 +1,4 @@ -include ../../Makefile.boards +include ../Makefile.boards CFLAGS += -DBOARD_PCA10059 diff --git a/boards/pca10059/s140/include/config.h b/boards/s140/pca10059/include/config.h similarity index 100% rename from boards/pca10059/s140/include/config.h rename to boards/s140/pca10059/include/config.h diff --git a/boards/pitaya-go/s140/Makefile b/boards/s140/pitaya-go/Makefile similarity index 89% rename from boards/pitaya-go/s140/Makefile rename to boards/s140/pitaya-go/Makefile index c575141..35fb6c8 100644 --- a/boards/pitaya-go/s140/Makefile +++ b/boards/s140/pitaya-go/Makefile @@ -1,4 +1,4 @@ -include ../../Makefile.boards +include ../Makefile.boards CFLAGS += -DBOARD_CUSTOM diff --git a/boards/pitaya-go/s140/include/config.h b/boards/s140/pitaya-go/include/config.h similarity index 100% rename from boards/pitaya-go/s140/include/config.h rename to boards/s140/pitaya-go/include/config.h diff --git a/boards/pitaya-go/s140/include/custom_board.h b/boards/s140/pitaya-go/include/custom_board.h similarity index 100% rename from boards/pitaya-go/s140/include/custom_board.h rename to boards/s140/pitaya-go/include/custom_board.h diff --git a/boards/secure_bootloader_gcc_nrf52.ld b/boards/s140/secure_bootloader_gcc_nrf52.ld similarity index 100% rename from boards/secure_bootloader_gcc_nrf52.ld rename to boards/s140/secure_bootloader_gcc_nrf52.ld diff --git a/boards/secure_bootloader_gcc_nrf52_debug.ld b/boards/s140/secure_bootloader_gcc_nrf52_debug.ld similarity index 100% rename from boards/secure_bootloader_gcc_nrf52_debug.ld rename to boards/s140/secure_bootloader_gcc_nrf52_debug.ld diff --git a/boards/sparkfun-pro-mini/s140/Makefile b/boards/s140/sparkfun-pro-mini/Makefile similarity index 85% rename from boards/sparkfun-pro-mini/s140/Makefile rename to boards/s140/sparkfun-pro-mini/Makefile index 4307ec8..2e988ba 100644 --- a/boards/sparkfun-pro-mini/s140/Makefile +++ b/boards/s140/sparkfun-pro-mini/Makefile @@ -1,4 +1,4 @@ -include ../../Makefile.boards +include ../Makefile.boards CFLAGS += -DBOARD_CUSTOM diff --git a/boards/sparkfun-pro-mini/s140/include/config.h b/boards/s140/sparkfun-pro-mini/include/config.h similarity index 100% rename from boards/sparkfun-pro-mini/s140/include/config.h rename to boards/s140/sparkfun-pro-mini/include/config.h diff --git a/boards/sparkfun-pro-mini/s140/include/custom_board.h b/boards/s140/sparkfun-pro-mini/include/custom_board.h similarity index 100% rename from boards/sparkfun-pro-mini/s140/include/custom_board.h rename to boards/s140/sparkfun-pro-mini/include/custom_board.h diff --git a/include/sdk_config.h b/include/sdk_config.h index 51ed616..1dc1ea5 100644 --- a/include/sdk_config.h +++ b/include/sdk_config.h @@ -463,7 +463,7 @@ // The CC310 hardware-accelerated cryptography backend with reduced functionality and footprint (only available on nRF52840). //========================================================== #ifndef NRF_CRYPTO_BACKEND_CC310_BL_ENABLED -#define NRF_CRYPTO_BACKEND_CC310_BL_ENABLED 1 +#define NRF_CRYPTO_BACKEND_CC310_BL_ENABLED 0 #endif // NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP224R1_ENABLED - Enable the secp224r1 elliptic curve support using CC310_BL. @@ -947,7 +947,7 @@ // NRF_CRYPTO_BACKEND_MICRO_ECC_ENABLED - Enable the micro-ecc backend. //========================================================== #ifndef NRF_CRYPTO_BACKEND_MICRO_ECC_ENABLED -#define NRF_CRYPTO_BACKEND_MICRO_ECC_ENABLED 0 +#define NRF_CRYPTO_BACKEND_MICRO_ECC_ENABLED 1 #endif // NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP192R1_ENABLED - Enable secp192r1 (NIST 192-bit) curve @@ -1010,7 +1010,7 @@ // The nRF SW cryptography backend (only used in bootloader context). //========================================================== #ifndef NRF_CRYPTO_BACKEND_NRF_SW_ENABLED -#define NRF_CRYPTO_BACKEND_NRF_SW_ENABLED 0 +#define NRF_CRYPTO_BACKEND_NRF_SW_ENABLED 1 #endif // NRF_CRYPTO_BACKEND_NRF_SW_HASH_SHA256_ENABLED - nRF SW hash backend support for SHA-256 diff --git a/sdk/components/libraries/bootloader/s132/nrf_bootloader.c b/sdk/components/libraries/bootloader/s132/nrf_bootloader.c new file mode 100644 index 0000000..22824de --- /dev/null +++ b/sdk/components/libraries/bootloader/s132/nrf_bootloader.c @@ -0,0 +1,660 @@ +/** + * Copyright (c) 2016 - 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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 Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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. + * + */ +#include "nrf_bootloader.h" +#include "nrf_dfu_ble.h" +#include "compiler_abstraction.h" +#include "nrf.h" +#include "nrf_sdh.h" +#include "boards.h" +#include "sdk_config.h" +#include "nrf_power.h" +#include "nrf_delay.h" +#include "app_timer.h" +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +#include "nrf_dfu.h" +#include "nrf_error.h" +#include "nrf_dfu_settings.h" +#include "nrf_dfu_utils.h" +#include "nrf_dfu_transport.h" +#include "nrf_bootloader_wdt.h" +#include "nrf_bootloader_info.h" +#include "nrf_bootloader_app_start.h" +#include "nrf_bootloader_fw_activation.h" +#include "nrf_bootloader_dfu_timers.h" +#include "app_scheduler.h" +#include "nrf_dfu_validation.h" + +/**@brief Enumeration for specifying current bootloader status. + */ +static bool dfu_startup_packet_received = false; + +static nrf_dfu_observer_t m_user_observer; //= 100) || (NRF_BL_DFU_INACTIVITY_TIMEOUT_MS == 0), + "NRF_BL_DFU_INACTIVITY_TIMEOUT_MS must be 100 ms or more, or 0 to indicate that it is disabled."); + +#if defined(NRF_LOG_BACKEND_FLASH_START_PAGE) +STATIC_ASSERT(NRF_LOG_BACKEND_FLASH_START_PAGE != 0, + "If nrf_log flash backend is used it cannot use space after code because it would collide with settings page."); +#endif + +/**@brief Weak implemenation of nrf_dfu_init + * + * @note This function will be overridden if nrf_dfu.c is + * compiled and linked with the project + */ + #if (__LINT__ != 1) +__WEAK uint32_t nrf_dfu_init(nrf_dfu_observer_t observer) +{ + NRF_LOG_DEBUG("in weak nrf_dfu_init"); + return NRF_SUCCESS; +} +#endif + + +/**@brief Weak implementation of nrf_dfu_init + * + * @note This function must be overridden in application if + * user-specific initialization is needed. + */ +__WEAK uint32_t nrf_dfu_init_user(void) +{ + NRF_LOG_DEBUG("in weak nrf_dfu_init_user"); + return NRF_SUCCESS; +} + +#if NRF_BL_DFU_ALLOW_UPDATE_FROM_APP +static void flash_write_callback(void * p_context) +{ + UNUSED_PARAMETER(p_context); + m_flash_write_done = true; +} +#endif + +static void do_reset(void * p_context) +{ + UNUSED_PARAMETER(p_context); + + NRF_LOG_FINAL_FLUSH(); + +#if NRF_MODULE_ENABLED(NRF_LOG_BACKEND_RTT) + // To allow the buffer to be flushed by the host. + nrf_delay_ms(100); +#endif + + NVIC_SystemReset(); +} + + +static void bootloader_reset(bool do_backup) +{ + NRF_LOG_DEBUG("Resetting bootloader."); + + if (do_backup) + { + m_flash_write_done = false; + nrf_dfu_settings_backup(do_reset); + } + else + { + do_reset(NULL); + } +} + +static void flash_write_callback(void * p_context) +{ + UNUSED_PARAMETER(p_context); + m_flash_write_done = true; +} + +static void inactivity_timeout(void) +{ + NRF_LOG_INFO("Inactivity timeout."); + bootloader_reset(true); +} + +/**@brief Function for handling DFU events. + */ +static void dfu_observer(nrf_dfu_evt_type_t evt_type) +{ + switch (evt_type) + { + case NRF_DFU_EVT_DFU_STARTED: + case NRF_DFU_EVT_OBJECT_RECEIVED: + dfu_startup_packet_received = true; + nrf_bootloader_dfu_inactivity_timer_restart( + NRF_BOOTLOADER_MS_TO_TICKS(NRF_BL_DFU_INACTIVITY_TIMEOUT_MS), + inactivity_timeout); + break; + case NRF_DFU_EVT_DFU_COMPLETED: + case NRF_DFU_EVT_DFU_ABORTED: + bootloader_reset(true); + break; + default: + break; + } + + if (m_user_observer) + { + m_user_observer(evt_type); + } +} + + +/**@brief Function for initializing the event scheduler. + */ +static void scheduler_init(void) +{ + APP_SCHED_INIT(SCHED_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE); +} + + +/**@brief Suspend the CPU until an interrupt occurs. + */ +static void wait_for_event(void) +{ +#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD) + (void)sd_app_evt_wait(); +#else + // Wait for an event. + __WFE(); + // Clear the internal event register. + __SEV(); + __WFE(); +#endif +} + + +/**@brief Continually sleep and process tasks whenever woken. + */ +static void loop_forever(void) +{ + while (true) + { + //feed the watchdog if enabled. + nrf_bootloader_wdt_feed(); + + app_sched_execute(); + + if (!NRF_LOG_PROCESS()) + { + wait_for_event(); + } + } +} + +/**@brief Function for initializing button used to enter DFU mode. + */ +static void dfu_enter_button_init(void) +{ + nrf_gpio_cfg_sense_input(NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN, + BUTTON_PULL, + NRF_GPIO_PIN_SENSE_LOW); +} + + +static bool crc_on_valid_app_required(void) +{ + bool ret = true; + if (NRF_BL_APP_CRC_CHECK_SKIPPED_ON_SYSTEMOFF_RESET && + (nrf_power_resetreas_get() & NRF_POWER_RESETREAS_OFF_MASK)) + { + nrf_power_resetreas_clear(NRF_POWER_RESETREAS_OFF_MASK); + ret = false; + } + else if (NRF_BL_APP_CRC_CHECK_SKIPPED_ON_GPREGRET2 && + ((nrf_power_gpregret2_get() & BOOTLOADER_DFU_GPREGRET2_MASK) == BOOTLOADER_DFU_GPREGRET2) + && (nrf_power_gpregret2_get() & BOOTLOADER_DFU_SKIP_CRC_BIT_MASK)) + { + nrf_power_gpregret2_set(nrf_power_gpregret2_get() & ~BOOTLOADER_DFU_SKIP_CRC); + ret = false; + } + else + { + } + + return ret; +} + + + +static bool boot_validate(boot_validation_t const * p_validation, uint32_t data_addr, uint32_t data_len, bool do_crc) +{ + if (!do_crc && (p_validation->type == VALIDATE_CRC)) + { + return true; + } + return nrf_dfu_validation_boot_validate(p_validation, data_addr, data_len); +} + + +/** @brief Function for checking if the main application is valid. + * + * @details This function checks if there is a valid application + * located at Bank 0. + * + * @param[in] do_crc Perform CRC check on application. Only CRC checks + can be skipped. For other boot validation types, + this parameter is ignored. + * + * @retval true If a valid application has been detected. + * @retval false If there is no valid application. + */ +static bool app_is_valid(bool do_crc) +{ + if (s_dfu_settings.bank_0.bank_code != NRF_DFU_BANK_VALID_APP) + { + NRF_LOG_INFO("Boot validation failed. No valid app to boot."); + return false; + } + else if (NRF_BL_APP_SIGNATURE_CHECK_REQUIRED && + (s_dfu_settings.boot_validation_app.type != VALIDATE_ECDSA_P256_SHA256)) + { + NRF_LOG_WARNING("Boot validation failed. The boot validation of the app must be a signature check."); + return false; + } + else if (SD_PRESENT && !boot_validate(&s_dfu_settings.boot_validation_softdevice, MBR_SIZE, s_dfu_settings.sd_size, do_crc)) + { + NRF_LOG_WARNING("Boot validation failed. SoftDevice is present but invalid."); + return false; + } + else if (!boot_validate(&s_dfu_settings.boot_validation_app, nrf_dfu_bank0_start_addr(), s_dfu_settings.bank_0.image_size, do_crc)) + { + NRF_LOG_WARNING("Boot validation failed. App is invalid."); + return false; + } + // The bootloader itself is not checked, since a self-check of this kind gives little to no benefit + // compared to the cost incurred on each bootup. + + NRF_LOG_DEBUG("App is valid"); + return true; +} + + + +/**@brief Function for clearing all DFU enter flags that + * preserve state during reset. + * + * @details This is used to make sure that each of these flags + * is checked only once after reset. + */ +static void dfu_enter_flags_clear(void) +{ + if (NRF_BL_DFU_ENTER_METHOD_PINRESET && + (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk)) + { + // Clear RESETPIN flag. + NRF_POWER->RESETREAS |= POWER_RESETREAS_RESETPIN_Msk; + } + + if (NRF_BL_DFU_ENTER_METHOD_GPREGRET && + ((nrf_power_gpregret_get() & BOOTLOADER_DFU_GPREGRET_MASK) == BOOTLOADER_DFU_GPREGRET) + && (nrf_power_gpregret_get() & BOOTLOADER_DFU_START_BIT_MASK)) + { + // Clear DFU mark in GPREGRET register. + nrf_power_gpregret_set(nrf_power_gpregret_get() & ~BOOTLOADER_DFU_START); + } + + if (NRF_BL_DFU_ENTER_METHOD_BUTTONLESS && + (s_dfu_settings.enter_buttonless_dfu == 1)) + { + // Clear DFU flag in flash settings. + s_dfu_settings.enter_buttonless_dfu = 0; + APP_ERROR_CHECK(nrf_dfu_settings_write(NULL)); + } +} + + +/**@brief Function for checking whether to enter DFU mode or not. + */ +static bool dfu_enter_check(void) +{ + if (!app_is_valid(crc_on_valid_app_required())) + { + NRF_LOG_DEBUG("DFU mode because app is not valid."); + return true; + } + + if (NRF_BL_DFU_ENTER_METHOD_BUTTON && + (nrf_gpio_pin_read(NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN) == 0)) + { + NRF_LOG_DEBUG("DFU mode requested via button."); + return true; + } + + if (NRF_BL_DFU_ENTER_METHOD_PINRESET && + (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk)) + { + NRF_LOG_DEBUG("DFU mode requested via pin-reset."); + return true; + } + + if (NRF_BL_DFU_ENTER_METHOD_GPREGRET && + (nrf_power_gpregret_get() & BOOTLOADER_DFU_START)) + { + NRF_LOG_DEBUG("DFU mode requested via GPREGRET."); + return true; + } + + if (NRF_BL_DFU_ENTER_METHOD_BUTTONLESS && + (s_dfu_settings.enter_buttonless_dfu == 1)) + { + NRF_LOG_DEBUG("DFU mode requested via bootloader settings."); + return true; + } + + return false; +} + + +#if NRF_BL_DFU_ALLOW_UPDATE_FROM_APP +static void postvalidate(void) +{ + NRF_LOG_INFO("Postvalidating update after reset."); + nrf_dfu_validation_init(); + + if (nrf_dfu_validation_init_cmd_present()) + { + uint32_t firmware_start_addr; + uint32_t firmware_size; + + // Execute a previously received init packed. Subsequent executes will have no effect. + if (nrf_dfu_validation_init_cmd_execute(&firmware_start_addr, &firmware_size) == NRF_DFU_RES_CODE_SUCCESS) + { + if (nrf_dfu_validation_prevalidate() == NRF_DFU_RES_CODE_SUCCESS) + { + if (nrf_dfu_validation_activation_prepare(firmware_start_addr, firmware_size) == NRF_DFU_RES_CODE_SUCCESS) + { + NRF_LOG_INFO("Postvalidation successful."); + } + } + } + } + + s_dfu_settings.bank_current = NRF_DFU_CURRENT_BANK_0; + UNUSED_RETURN_VALUE(nrf_dfu_settings_write_and_backup(flash_write_callback)); +} +#endif + +/** + * @brief Function for aborting current application/bootloader jump to to other app/bootloader. + * + * @details This functions will use the address provide to swap the stack pointer and then load + * the address of the reset handler to be executed. It will check current system mode + * (thread/handler) and if in thread mode it will reset into other application. + * If in handler mode \ref isr_abort will be executed to ensure correct exit of handler + * mode and jump into reset handler of other application. + * + * @param[in] start_addr Start address of other application. This address must point to the + initial stack pointer of the application. + * + * @note This function will never return but issue a reset into provided application. + */ +#if defined ( __CC_ARM ) +__asm static void bootloader_util_reset(uint32_t start_addr) +{ + LDR R5, [R0] ; Get App initial MSP for bootloader. + MSR MSP, R5 ; Set the main stack pointer to the applications MSP. + LDR R0, [R0, #0x04] ; Load Reset handler into R0. This will be first argument to branch instruction (BX). + + MOVS R4, #0xFF ; Load ones to R4. + SXTB R4, R4 ; Sign extend R4 to obtain 0xFFFFFFFF instead of 0xFF. + MRS R5, IPSR ; Load IPSR to R5 to check for handler or thread mode. + CMP R5, #0x00 ; Compare, if 0 then we are in thread mode and can continue to reset handler of bootloader. + BNE isr_abort ; If not zero we need to exit current ISR and jump to reset handler of bootloader. + + MOV LR, R4 ; Clear the link register and set to ones to ensure no return, R4 = 0xFFFFFFFF. + BX R0 ; Branch to reset handler of bootloader. + +isr_abort + ; R4 contains ones from line above. Will be popped as R12 when exiting ISR (Cleaning up the registers). + MOV R5, R4 ; Fill with ones before jumping to reset handling. We be popped as LR when exiting ISR. Ensures no return to application. + MOV R6, R0 ; Move address of reset handler to R6. Will be popped as PC when exiting ISR. Ensures the reset handler will be executed when exist ISR. + MOVS r7, #0x21 ; Move MSB reset value of xPSR to R7. Will be popped as xPSR when exiting ISR. xPSR is 0x21000000 thus MSB is 0x21. + REV r7, r7 ; Reverse byte order to put 0x21 as MSB. + PUSH {r4-r7} ; Push everything to new stack to allow interrupt handler to fetch it on exiting the ISR. + + MOVS R4, #0x00 ; Fill with zeros before jumping to reset handling. We be popped as R0 when exiting ISR (Cleaning up of the registers). + MOVS R5, #0x00 ; Fill with zeros before jumping to reset handling. We be popped as R1 when exiting ISR (Cleaning up of the registers). + MOVS R6, #0x00 ; Fill with zeros before jumping to reset handling. We be popped as R2 when exiting ISR (Cleaning up of the registers). + MOVS R7, #0x00 ; Fill with zeros before jumping to reset handling. We be popped as R3 when exiting ISR (Cleaning up of the registers). + PUSH {r4-r7} ; Push zeros (R4-R7) to stack to prepare for exiting the interrupt routine. + + MOVS R0, #0xF9 ; Move the execution return command into register, 0xFFFFFFF9. + SXTB R0, R0 ; Sign extend R0 to obtain 0xFFFFFFF9 instead of 0xF9. + BX R0 ; No return - Handler mode will be exited. Stack will be popped and execution will continue in reset handler initializing other application. + ALIGN +} +#elif defined ( __GNUC__ ) +static inline void bootloader_util_reset (uint32_t start_addr) __attribute__ ((optimize("-fomit-frame-pointer"))); +static inline void bootloader_util_reset(uint32_t start_addr) +{ + __asm volatile( + "ldr r0, [%0]\t\n" // Get App initial MSP for bootloader. + "msr msp, r0\t\n" // Set the main stack pointer to the applications MSP. + "ldr r0, [%0, #0x04]\t\n" // Load Reset handler into R0. + + "movs r4, #0xFF\t\n" // Move ones to R4. + "sxtb r4, r4\t\n" // Sign extend R4 to obtain 0xFFFFFFFF instead of 0xFF. + + "mrs r5, IPSR\t\n" // Load IPSR to R5 to check for handler or thread mode. + "cmp r5, #0x00\t\n" // Compare, if 0 then we are in thread mode and can continue to reset handler of bootloader. + "bne isr_abort\t\n" // If not zero we need to exit current ISR and jump to reset handler of bootloader. + + "mov lr, r4\t\n" // Clear the link register and set to ones to ensure no return. + "bx r0\t\n" // Branch to reset handler of bootloader. + + "isr_abort: \t\n" + + "mov r5, r4\t\n" // Fill with ones before jumping to reset handling. Will be popped as LR when exiting ISR. Ensures no return to application. + "mov r6, r0\t\n" // Move address of reset handler to R6. Will be popped as PC when exiting ISR. Ensures the reset handler will be executed when exist ISR. + "movs r7, #0x21\t\n" // Move MSB reset value of xPSR to R7. Will be popped as xPSR when exiting ISR. xPSR is 0x21000000 thus MSB is 0x21. + "rev r7, r7\t\n" // Reverse byte order to put 0x21 as MSB. + "push {r4-r7}\t\n" // Push everything to new stack to allow interrupt handler to fetch it on exiting the ISR. + + "movs r4, #0x00\t\n" // Fill with zeros before jumping to reset handling. We be popped as R0 when exiting ISR (Cleaning up of the registers). + "movs r5, #0x00\t\n" // Fill with zeros before jumping to reset handling. We be popped as R1 when exiting ISR (Cleaning up of the registers). + "movs r6, #0x00\t\n" // Fill with zeros before jumping to reset handling. We be popped as R2 when exiting ISR (Cleaning up of the registers). + "movs r7, #0x00\t\n" // Fill with zeros before jumping to reset handling. We be popped as R3 when exiting ISR (Cleaning up of the registers). + "push {r4-r7}\t\n" // Push zeros (R4-R7) to stack to prepare for exiting the interrupt routine. + + "movs r0, #0xF9\t\n" // Move the execution return command into register, 0xFFFFFFF9. + "sxtb r0, r0\t\n" // Sign extend R0 to obtain 0xFFFFFFF9 instead of 0xF9. + "bx r0\t\n" // No return - Handler mode will be exited. Stack will be popped and execution will continue in reset handler initializing other application. + ".align\t\n" + :: "r" (start_addr) // Argument list for the gcc assembly. start_addr is %0. + : "r0", "r4", "r5", "r6", "r7" // List of register maintained manually. + ); +} +#elif defined ( __ICCARM__ ) +static inline void bootloader_util_reset(uint32_t start_addr) +{ + asm("ldr r5, [%0]\n" // Get App initial MSP for bootloader. + "msr msp, r5\n" // Set the main stack pointer to the applications MSP. + "ldr r0, [%0, #0x04]\n" // Load Reset handler into R0. + + "movs r4, #0x00\n" // Load zero into R4. + "mvns r4, r4\n" // Invert R4 to ensure it contain ones. + + "mrs r5, IPSR\n" // Load IPSR to R5 to check for handler or thread mode + "cmp r5, #0x00\n" // Compare, if 0 then we are in thread mode and can continue to reset handler of bootloader. + "bne.n isr_abort\n" // If not zero we need to exit current ISR and jump to reset handler of bootloader. + + "mov lr, r4\n" // Clear the link register and set to ones to ensure no return. + "bx r0\n" // Branch to reset handler of bootloader. + + "isr_abort: \n" + // R4 contains ones from line above. We be popped as R12 when exiting ISR (Cleaning up the registers). + "mov r5, r4\n" // Fill with ones before jumping to reset handling. Will be popped as LR when exiting ISR. Ensures no return to application. + "mov r6, r0\n" // Move address of reset handler to R6. Will be popped as PC when exiting ISR. Ensures the reset handler will be executed when exist ISR. + "movs r7, #0x21\n" // Move MSB reset value of xPSR to R7. Will be popped as xPSR when exiting ISR. xPSR is 0x21000000 thus MSB is 0x21. + "rev r7, r7\n" // Reverse byte order to put 0x21 as MSB. + "push {r4-r7}\n" // Push everything to new stack to allow interrupt handler to fetch it on exiting the ISR. + + "movs r4, #0x00\n" // Fill with zeros before jumping to reset handling. We be popped as R0 when exiting ISR (Cleaning up of the registers). + "movs r5, #0x00\n" // Fill with zeros before jumping to reset handling. We be popped as R1 when exiting ISR (Cleaning up of the registers). + "movs r6, #0x00\n" // Fill with zeros before jumping to reset handling. We be popped as R2 when exiting ISR (Cleaning up of the registers). + "movs r7, #0x00\n" // Fill with zeros before jumping to reset handling. We be popped as R3 when exiting ISR (Cleaning up of the registers). + "push {r4-r7}\n" // Push zeros (R4-R7) to stack to prepare for exiting the interrupt routine. + + "movs r0, #0x06\n" // Load 0x06 into R6 to prepare for exec return command. + "mvns r0, r0\n" // Invert 0x06 to obtain EXEC_RETURN, 0xFFFFFFF9. + "bx r0\n" // No return - Handler mode will be exited. Stack will be popped and execution will continue in reset handler initializing other application. + :: "r" (start_addr) // Argument list for the IAR assembly. start_addr is %0. + : "r0", "r4", "r5", "r6", "r7"); // List of register maintained manually. +} +#else +#error Compiler not supported. +#endif + + + +ret_code_t nrf_bootloader_init(nrf_dfu_observer_t observer) +{ + NRF_LOG_DEBUG("In nrf_bootloader_init"); + + ret_code_t ret_val; + nrf_bootloader_fw_activation_result_t activation_result; + uint32_t initial_timeout; + bool dfu_enter = false; + + m_user_observer = observer; + + if (NRF_BL_DFU_ENTER_METHOD_BUTTON) + { + dfu_enter_button_init(); + } + + ret_val = nrf_dfu_settings_init(false); + if (ret_val != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + + #if NRF_BL_DFU_ALLOW_UPDATE_FROM_APP + // Postvalidate if DFU has signaled that update is ready. + if (s_dfu_settings.bank_current == NRF_DFU_CURRENT_BANK_1) + { + postvalidate(); + } + #endif + + // Check if an update needs to be activated and activate it. + activation_result = nrf_bootloader_fw_activate(); + + switch (activation_result) + { + case ACTIVATION_NONE: + initial_timeout = NRF_BOOTLOADER_MS_TO_TICKS(NRF_BL_DFU_INACTIVITY_TIMEOUT_MS); + dfu_enter = dfu_enter_check(); + break; + + case ACTIVATION_SUCCESS_EXPECT_ADDITIONAL_UPDATE: + initial_timeout = NRF_BOOTLOADER_MS_TO_TICKS(NRF_BL_DFU_CONTINUATION_TIMEOUT_MS); + dfu_enter = true; + break; + + case ACTIVATION_SUCCESS: + bootloader_reset(true); + NRF_LOG_ERROR("Unreachable"); + return NRF_ERROR_INTERNAL; // Should not reach this. + + case ACTIVATION_ERROR: + default: + return NRF_ERROR_INTERNAL; + } + + if (dfu_enter) + { + nrf_bootloader_wdt_init(); + scheduler_init(); + dfu_enter_flags_clear(); + + // Call user-defined init function if implemented + ret_val = nrf_dfu_init_user(); + if (ret_val != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + + nrf_bootloader_dfu_inactivity_timer_restart(initial_timeout, inactivity_timeout); + + ret_val = nrf_dfu_init(dfu_observer); + if (ret_val != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + + NRF_LOG_DEBUG("Enter main loop"); + loop_forever(); // This function will never return. + NRF_LOG_ERROR("Unreachable"); + } + else + { + // Erase additional data like peer data or advertisement name + ret_val = nrf_dfu_settings_additional_erase(); + if (ret_val != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + + m_flash_write_done = false; + nrf_dfu_settings_backup(flash_write_callback); + ASSERT(m_flash_write_done); + + nrf_bootloader_app_start(); + NRF_LOG_ERROR("Unreachable"); + } + + // Should not be reached. + return NRF_ERROR_INTERNAL; +} diff --git a/sdk/components/libraries/bootloader/nrf_bootloader.c b/sdk/components/libraries/bootloader/s140/nrf_bootloader.c similarity index 100% rename from sdk/components/libraries/bootloader/nrf_bootloader.c rename to sdk/components/libraries/bootloader/s140/nrf_bootloader.c From ce3418088b01c7b4b0d4041af8df5c7d602bcd58 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 9 Jan 2024 21:44:12 +0000 Subject: [PATCH 03/11] clk conf --- Dockerfile | 4 ++ boards/s132/Makefile.boards | 3 +- boards/s132/bmd_350_a_r/include/config.h | 42 +++++++++++++++++++ boards/s132/secure_bootloader_gcc_nrf52.ld | 4 +- .../s132/secure_bootloader_gcc_nrf52_debug.ld | 4 +- main.c | 4 ++ 6 files changed, 55 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index 14c0506..fc810e9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,6 +12,10 @@ ENV NRF_DFU_BL_ACCEPT_SAME_VERSION=1 ENV NRF_DFU_REQUIRE_SIGNED_APP_UPDATE=1 ENV NRF_BL_APP_SIGNATURE_CHECK_REQUIRED=0 ENV NRF_DFU_BLE_ADV_NAME="KAIDYTH_DFU" +ENV NRF_SDH_CLOCK_LF_SRC=0 +ENV NRF_SDH_CLOCK_LF_RC_CTIV=0 +ENV NRF_SDH_CLOCK_LF_RC_TEMP_CTIV=0 + VOLUME [ "/app" ] diff --git a/boards/s132/Makefile.boards b/boards/s132/Makefile.boards index 09a44c6..3228aca 100644 --- a/boards/s132/Makefile.boards +++ b/boards/s132/Makefile.boards @@ -3,7 +3,7 @@ TARGETS := nrf52832_xxaa OUTPUT_DIRECTORY := _build DEBUG ?= 0 -SD_REQ := 0xB6 +SD_REQ := 0xB7 SECURE := secure @@ -74,7 +74,6 @@ SRC_FILES += \ $(SDK_ROOT)/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecdsa.c \ $(SDK_ROOT)/components/libraries/slip/slip.c \ $(SDK_ROOT)/integration/nrfx/legacy/nrf_drv_clock.c \ - $(SDK_ROOT)/integration/nrfx/legacy/nrf_drv_power.c \ $(SDK_ROOT)/modules/nrfx/hal/nrf_nvmc.c \ $(SDK_ROOT)/modules/nrfx/soc/nrfx_atomic.c \ $(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_clock.c \ diff --git a/boards/s132/bmd_350_a_r/include/config.h b/boards/s132/bmd_350_a_r/include/config.h index e4d75f6..49dd492 100644 --- a/boards/s132/bmd_350_a_r/include/config.h +++ b/boards/s132/bmd_350_a_r/include/config.h @@ -8,6 +8,48 @@ #define BLEDIS_MANUFACTURER "Man" #define BLEDIS_MODEL "nRF52832 Board" +// NRF_SDH_CLOCK_LF_SRC - SoftDevice clock source. + +// <0=> NRF_CLOCK_LF_SRC_RC +// <1=> NRF_CLOCK_LF_SRC_XTAL +// <2=> NRF_CLOCK_LF_SRC_SYNTH + +#ifndef NRF_SDH_CLOCK_LF_SRC +#define NRF_SDH_CLOCK_LF_SRC 0 +#endif + +// NRF_SDH_CLOCK_LF_RC_CTIV - SoftDevice calibration timer interval. +#ifndef NRF_SDH_CLOCK_LF_RC_CTIV +#define NRF_SDH_CLOCK_LF_RC_CTIV 16 +#endif + +// NRF_SDH_CLOCK_LF_RC_TEMP_CTIV - SoftDevice calibration timer interval under constant temperature. +// How often (in number of calibration intervals) the RC oscillator shall be calibrated +// if the temperature has not changed. + +#ifndef NRF_SDH_CLOCK_LF_RC_TEMP_CTIV +#define NRF_SDH_CLOCK_LF_RC_TEMP_CTIV 16 +#endif + +// NRF_SDH_CLOCK_LF_ACCURACY - External clock accuracy used in the LL to compute timing. + +// <0=> NRF_CLOCK_LF_ACCURACY_250_PPM +// <1=> NRF_CLOCK_LF_ACCURACY_500_PPM +// <2=> NRF_CLOCK_LF_ACCURACY_150_PPM +// <3=> NRF_CLOCK_LF_ACCURACY_100_PPM +// <4=> NRF_CLOCK_LF_ACCURACY_75_PPM +// <5=> NRF_CLOCK_LF_ACCURACY_50_PPM +// <6=> NRF_CLOCK_LF_ACCURACY_30_PPM +// <7=> NRF_CLOCK_LF_ACCURACY_20_PPM +// <8=> NRF_CLOCK_LF_ACCURACY_10_PPM +// <9=> NRF_CLOCK_LF_ACCURACY_5_PPM +// <10=> NRF_CLOCK_LF_ACCURACY_2_PPM +// <11=> NRF_CLOCK_LF_ACCURACY_1_PPM + +#ifndef NRF_SDH_CLOCK_LF_ACCURACY +#define NRF_SDH_CLOCK_LF_ACCURACY 1 +#endif + #ifndef NRF_DFU_BL_ALLOW_DOWNGRADE #define NRF_DFU_BL_ALLOW_DOWNGRADE 1 #endif diff --git a/boards/s132/secure_bootloader_gcc_nrf52.ld b/boards/s132/secure_bootloader_gcc_nrf52.ld index a4ca69e..beb062b 100644 --- a/boards/s132/secure_bootloader_gcc_nrf52.ld +++ b/boards/s132/secure_bootloader_gcc_nrf52.ld @@ -5,8 +5,8 @@ GROUP(-lgcc -lc -lnosys) MEMORY { - FLASH (rx) : ORIGIN = 0xE0000, LENGTH = 0x186A0 /** 100KB **/ - RAM (rwx) : ORIGIN = 0x20003600, LENGTH = 0xCA00 + FLASH (rx) : ORIGIN = 0x00065000, LENGTH = 0x19000 /** 100KB **/ + RAM (rwx) : ORIGIN = 0x20003600, LENGTH = 0x20010000 - 0x20003600 uicr_bootloader_start_address (r) : ORIGIN = 0x00000FF8, LENGTH = 0x4 bootloader_settings_page (r) : ORIGIN = 0x0007F000, LENGTH = 0x1000 uicr_mbr_params_page (r) : ORIGIN = 0x00000FFC, LENGTH = 0x4 diff --git a/boards/s132/secure_bootloader_gcc_nrf52_debug.ld b/boards/s132/secure_bootloader_gcc_nrf52_debug.ld index a4ca69e..beb062b 100644 --- a/boards/s132/secure_bootloader_gcc_nrf52_debug.ld +++ b/boards/s132/secure_bootloader_gcc_nrf52_debug.ld @@ -5,8 +5,8 @@ GROUP(-lgcc -lc -lnosys) MEMORY { - FLASH (rx) : ORIGIN = 0xE0000, LENGTH = 0x186A0 /** 100KB **/ - RAM (rwx) : ORIGIN = 0x20003600, LENGTH = 0xCA00 + FLASH (rx) : ORIGIN = 0x00065000, LENGTH = 0x19000 /** 100KB **/ + RAM (rwx) : ORIGIN = 0x20003600, LENGTH = 0x20010000 - 0x20003600 uicr_bootloader_start_address (r) : ORIGIN = 0x00000FF8, LENGTH = 0x4 bootloader_settings_page (r) : ORIGIN = 0x0007F000, LENGTH = 0x1000 uicr_mbr_params_page (r) : ORIGIN = 0x00000FFC, LENGTH = 0x4 diff --git a/main.c b/main.c index 737d15d..711f29c 100644 --- a/main.c +++ b/main.c @@ -105,6 +105,10 @@ void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) { NRF_LOG_ERROR("Kaidyth DFU: Received a fault! id: 0x%08x, pc: 0x%08x, info: 0x%08x", id, pc, info); + assert_info_t * p_info = (assert_info_t *) 0x2000FF50; + NRF_LOG_ERROR("ASSERTION FAILED at %s:%u", + p_info->p_file_name, + p_info->line_num); on_error(); } From 0cecaf5caaf4bebcc69954d4f2f725a06558cdd2 Mon Sep 17 00:00:00 2001 From: gb88 Date: Fri, 12 Jan 2024 14:21:45 +0000 Subject: [PATCH 04/11] fix ram error --- boards/s132/secure_bootloader_gcc_nrf52.ld | 2 +- boards/s132/secure_bootloader_gcc_nrf52_debug.ld | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/boards/s132/secure_bootloader_gcc_nrf52.ld b/boards/s132/secure_bootloader_gcc_nrf52.ld index beb062b..9a5b2e4 100644 --- a/boards/s132/secure_bootloader_gcc_nrf52.ld +++ b/boards/s132/secure_bootloader_gcc_nrf52.ld @@ -6,7 +6,7 @@ GROUP(-lgcc -lc -lnosys) MEMORY { FLASH (rx) : ORIGIN = 0x00065000, LENGTH = 0x19000 /** 100KB **/ - RAM (rwx) : ORIGIN = 0x20003600, LENGTH = 0x20010000 - 0x20003600 + RAM (rwx) : ORIGIN = 0x20002A98, LENGTH = 0x20010000 - 0x20002A98 uicr_bootloader_start_address (r) : ORIGIN = 0x00000FF8, LENGTH = 0x4 bootloader_settings_page (r) : ORIGIN = 0x0007F000, LENGTH = 0x1000 uicr_mbr_params_page (r) : ORIGIN = 0x00000FFC, LENGTH = 0x4 diff --git a/boards/s132/secure_bootloader_gcc_nrf52_debug.ld b/boards/s132/secure_bootloader_gcc_nrf52_debug.ld index beb062b..9a5b2e4 100644 --- a/boards/s132/secure_bootloader_gcc_nrf52_debug.ld +++ b/boards/s132/secure_bootloader_gcc_nrf52_debug.ld @@ -6,7 +6,7 @@ GROUP(-lgcc -lc -lnosys) MEMORY { FLASH (rx) : ORIGIN = 0x00065000, LENGTH = 0x19000 /** 100KB **/ - RAM (rwx) : ORIGIN = 0x20003600, LENGTH = 0x20010000 - 0x20003600 + RAM (rwx) : ORIGIN = 0x20002A98, LENGTH = 0x20010000 - 0x20002A98 uicr_bootloader_start_address (r) : ORIGIN = 0x00000FF8, LENGTH = 0x4 bootloader_settings_page (r) : ORIGIN = 0x0007F000, LENGTH = 0x1000 uicr_mbr_params_page (r) : ORIGIN = 0x00000FFC, LENGTH = 0x4 From 54dfee822b0cc7bd6b76270710d4cfc88346d59a Mon Sep 17 00:00:00 2001 From: gb88 Date: Fri, 12 Jan 2024 15:52:14 +0000 Subject: [PATCH 05/11] fix button --- boards/s132/bmd_350_a_r/include/custom_board.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/s132/bmd_350_a_r/include/custom_board.h b/boards/s132/bmd_350_a_r/include/custom_board.h index c15eb79..50afb5d 100644 --- a/boards/s132/bmd_350_a_r/include/custom_board.h +++ b/boards/s132/bmd_350_a_r/include/custom_board.h @@ -55,7 +55,7 @@ GREEN 12 0.12 #define BUTTON_2 NRF_GPIO_PIN_MAP(0,14) -#define BUTTON_PULL NRF_GPIO_PIN_NOPULL +#define BUTTON_PULL NRF_GPIO_PIN_PULLDOWN #define BUTTONS_ACTIVE_STATE 1 #define BUTTONS_LIST { BUTTON_1, BUTTON_2 } From 4da378bb89d6179b51274a459abcc4c13b8747d0 Mon Sep 17 00:00:00 2001 From: gb88 Date: Thu, 1 Feb 2024 23:21:36 +0000 Subject: [PATCH 06/11] before jumo --- sdk/components/libraries/bootloader/s132/nrf_bootloader.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sdk/components/libraries/bootloader/s132/nrf_bootloader.c b/sdk/components/libraries/bootloader/s132/nrf_bootloader.c index 22824de..e6b827e 100644 --- a/sdk/components/libraries/bootloader/s132/nrf_bootloader.c +++ b/sdk/components/libraries/bootloader/s132/nrf_bootloader.c @@ -640,7 +640,7 @@ ret_code_t nrf_bootloader_init(nrf_dfu_observer_t observer) } else { - // Erase additional data like peer data or advertisement name + // Erase additional data like peer data or advertisement name ret_val = nrf_dfu_settings_additional_erase(); if (ret_val != NRF_SUCCESS) { @@ -650,7 +650,8 @@ ret_code_t nrf_bootloader_init(nrf_dfu_observer_t observer) m_flash_write_done = false; nrf_dfu_settings_backup(flash_write_callback); ASSERT(m_flash_write_done); - + NRF_LOG_DEBUG("Try to start app"); + // loop_forever(); // This function will never return. nrf_bootloader_app_start(); NRF_LOG_ERROR("Unreachable"); } From 03297291433287beef91744cfe980ae8028872bf Mon Sep 17 00:00:00 2001 From: gb88 Date: Sat, 10 Feb 2024 14:36:18 +0000 Subject: [PATCH 07/11] test --- main.c | 7 ++- .../bootloader/s132/nrf_bootloader.c | 52 +++++++++++++++++-- 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/main.c b/main.c index 711f29c..a82b4f8 100644 --- a/main.c +++ b/main.c @@ -187,7 +187,12 @@ static void kaidyth_bootstrap(void) // //button_pressed(BUTTON_DFU) // nrf_power_gpregret_set(BOOTLOADER_DFU_START); - if (BUTTONS_NUMBER > 0) + //avoid to enter into bootloader mode if the pin used is for wake up + uint32_t reset_reason = 0; + reset_reason = NRF_POWER->RESETREAS; + //clear register + NRF_POWER->RESETREAS = NRF_POWER->RESETREAS; + if (BUTTONS_NUMBER > 0 && ((reset_reason & 0x10000) != 0x10000)) { nrf_gpio_cfg_input(BUTTON_1,BUTTON_PULL); nrf_delay_ms(50); diff --git a/sdk/components/libraries/bootloader/s132/nrf_bootloader.c b/sdk/components/libraries/bootloader/s132/nrf_bootloader.c index e6b827e..b77c098 100644 --- a/sdk/components/libraries/bootloader/s132/nrf_bootloader.c +++ b/sdk/components/libraries/bootloader/s132/nrf_bootloader.c @@ -640,20 +640,64 @@ ret_code_t nrf_bootloader_init(nrf_dfu_observer_t observer) } else { + NRF_LOG_ERROR("Stato 0"); + // Erase additional data like peer data or advertisement name ret_val = nrf_dfu_settings_additional_erase(); if (ret_val != NRF_SUCCESS) { return NRF_ERROR_INTERNAL; } + NRF_LOG_ERROR("Stato 1"); m_flash_write_done = false; nrf_dfu_settings_backup(flash_write_callback); ASSERT(m_flash_write_done); - NRF_LOG_DEBUG("Try to start app"); - // loop_forever(); // This function will never return. - nrf_bootloader_app_start(); - NRF_LOG_ERROR("Unreachable"); + NRF_LOG_ERROR("1"); + // Disable all interrupts + /* NVIC->ICER[0]=0xFFFFFFFF; + NVIC->ICPR[0]=0xFFFFFFFF; + #if defined(__NRF_NVIC_ISER_COUNT) && __NRF_NVIC_ISER_COUNT == 2 + NVIC->ICER[1]=0xFFFFFFFF; + NVIC->ICPR[1]=0xFFFFFFFF; + #endif + + uint32_t fwd_ret; + uint32_t app_addr; + + if ( *((uint32_t*)(SOFTDEVICE_INFO_STRUCT_ADDRESS+4)) == 0x51B1E5DB) + { + // App starts after SoftDevice + app_addr = SD_SIZE_GET(MBR_SIZE); + fwd_ret = sd_softdevice_vector_table_base_set(app_addr); + } + else + { + // App starts right after MBR + app_addr = MBR_SIZE; + sd_mbr_command_t command = + { + .command = SD_MBR_COMMAND_IRQ_FORWARD_ADDRESS_SET, + .params.irq_forward_address_set.address = app_addr, + }; + + fwd_ret = sd_mbr_command(&command); + } + + // unlikely failed to forward vector table, manually set forward address + if ( fwd_ret != NRF_SUCCESS ) + { + // MBR use first 4-bytes of SRAM to store foward address + *(uint32_t *)(0x20000000) = app_addr; + } + NRF_LOG_ERROR("QUI"); + while (NRF_LOG_PROCESS()); + NRF_LOG_DEBUG("Try to start app");*/ + //loop_forever(); // This function will never return. + //bootloader_util_reset(app_addr); + + nrf_bootloader_app_start(); + NRF_LOG_ERROR("Unreachable"); } // Should not be reached. From 6c8c7606460c84d0acc9a7c55396a326671f5808 Mon Sep 17 00:00:00 2001 From: gb88 Date: Wed, 6 Mar 2024 18:48:26 +0000 Subject: [PATCH 08/11] fix dfu with wdt --- Makefile | 4 + .../bootloader/ble_dfu/nrf_dfu_ble.c | 1262 +++++++++++++++++ 2 files changed, 1266 insertions(+) create mode 100644 sdk/components/libraries/bootloader/ble_dfu/nrf_dfu_ble.c diff --git a/Makefile b/Makefile index 16a6046..2c17868 100644 --- a/Makefile +++ b/Makefile @@ -78,4 +78,8 @@ patch: ## Patches the files in the nordic SDK to support additional bootloader f echo "Copying $$file to $(NORDIC_SDK_PATH)/$${file#./sdk/}"; \ cp ./sdk/$$file $(NORDIC_SDK_PATH)/$${file#./sdk/}; \ done; + @for file in $(subst ./sdk/,,$(call rwildcard,./sdk/,*nrf_dfu_ble.c)); do \ + echo "Copying $$file to $(NORDIC_SDK_PATH)/$${file#./sdk/}"; \ + cp ./sdk/$$file $(NORDIC_SDK_PATH)/$${file#./sdk/}; \ + done; diff --git a/sdk/components/libraries/bootloader/ble_dfu/nrf_dfu_ble.c b/sdk/components/libraries/bootloader/ble_dfu/nrf_dfu_ble.c new file mode 100644 index 0000000..382e064 --- /dev/null +++ b/sdk/components/libraries/bootloader/ble_dfu/nrf_dfu_ble.c @@ -0,0 +1,1262 @@ +/** + * Copyright (c) 2016 - 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, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, 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 Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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. + * + */ +#include "nrf_dfu_ble.h" + +#include +#include "sdk_common.h" +#include "nrf_dfu_transport.h" +#include "nrf_dfu_types.h" +#include "nrf_dfu_req_handler.h" +#include "nrf_dfu_handling_error.h" +#include "nrf_sdm.h" +#include "nrf_dfu_mbr.h" +#include "nrf_bootloader_info.h" +#include "ble.h" +#include "nrf_drv_clock.h" +#include "ble_srv_common.h" +#include "ble_hci.h" +#include "nrf_sdh.h" +#include "nrf_sdh_ble.h" +#include "nrf_balloc.h" +#include "nrf_delay.h" +#include "nrf_dfu_settings.h" +#include "nrf_dfu_ble.h" + +#define NRF_LOG_MODULE_NAME nrf_dfu_ble +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#ifndef NRF_DFU_BLE_ADV_INTERVAL +#define NRF_DFU_BLE_ADV_INTERVAL 40 /* 40 * 0,625ms = 25ms */ +#warning "sdk_config.h is not up to date." +#endif + +#define APP_BLE_CONN_CFG_TAG 1 /**< A tag identifying the SoftDevice BLE configuration. */ + +#define APP_ADV_DATA_HEADER_SIZE 9 /**< Size of encoded advertisement data header (not including device name). */ +#define APP_ADV_DURATION BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED /**< The advertising duration in units of 10 milliseconds. 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 GATT_HEADER_LEN 3 /**< GATT header length. */ +#define GATT_PAYLOAD(mtu) ((mtu) - GATT_HEADER_LEN) /**< Length of the ATT payload for a given ATT MTU. */ +#define MAX_DFU_PKT_LEN (NRF_SDH_BLE_GATT_MAX_MTU_SIZE - GATT_HEADER_LEN) /**< Maximum length (in bytes) of the DFU Packet characteristic (3 bytes are used for the GATT opcode and handle). */ +#define MAX_RESPONSE_LEN 17 /**< Maximum length (in bytes) of the response to a Control Point command. */ +#define RESPONSE_HEADER_LEN 3 /**< The length of the header of a response. I.E. the index of the opcode-specific payload. */ + +#define DFU_BLE_FLAG_INITIALIZED (1 << 0) /**< Flag to check if the DFU service was initialized by the application.*/ +#define DFU_BLE_FLAG_USE_ADV_NAME (1 << 1) /**< Flag to indicate that advertisement name is to be used. */ +#define DFU_BLE_RESETTING_SOON (1 << 2) /**< Flag to indicate that the device will reset soon. */ + +#define BLE_OBSERVER_PRIO 2 /**< BLE observer priority. Controls the priority for BLE event handler. */ + +#if (NRF_DFU_BLE_BUFFERS_OVERRIDE) +/* If selected, use the override value. */ +#define MAX_DFU_BUFFERS NRF_DFU_BLE_BUFFERS +#else +#define MAX_DFU_BUFFERS ((CODE_PAGE_SIZE / MAX_DFU_PKT_LEN) + 1) +#endif + +#if (NRF_DFU_BLE_REQUIRES_BONDS) && (!NRF_SDH_BLE_SERVICE_CHANGED) +#error NRF_DFU_BLE_REQUIRES_BONDS requires NRF_SDH_BLE_SERVICE_CHANGED. \ + Please update the SoftDevice BLE stack configuration in sdk_config.h +#endif + +#if (MAX_DFU_PKT_LEN % 4) +#error Payload length should be a multiple of four. \ + Payload length is set to NRF_SDH_BLE_GATT_MAX_MTU_SIZE - 3. +#endif + + +DFU_TRANSPORT_REGISTER(nrf_dfu_transport_t const ble_dfu_transport) = +{ + .init_func = ble_dfu_transport_init, + .close_func = ble_dfu_transport_close, +}; + +#if (NRF_DFU_BLE_REQUIRES_BONDS) +static nrf_dfu_peer_data_t m_peer_data; +#else +static nrf_dfu_adv_name_t m_adv_name; +#endif + +static uint32_t m_flags; +static ble_dfu_t m_dfu; /**< Structure used to identify the Device Firmware Update service. */ +static uint16_t m_pkt_notif_target; /**< Number of packets of firmware data to be received before transmitting the next Packet Receipt Notification to the DFU Controller. */ +static uint16_t m_pkt_notif_target_cnt; /**< Number of packets of firmware data received after sending last Packet Receipt Notification or since the receipt of a @ref BLE_DFU_PKT_RCPT_NOTIF_ENABLED event from the DFU service, which ever occurs later.*/ +static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< Handle of the current connection. */ +static uint8_t m_adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; /**< Advertising handle used to identify an advertising set. */ +static nrf_dfu_observer_t m_observer; /**< Observer function called on certain events. */ + +static ble_gap_conn_params_t const m_gap_conn_params = +{ + .min_conn_interval = NRF_DFU_BLE_MIN_CONN_INTERVAL, + .max_conn_interval = NRF_DFU_BLE_MAX_CONN_INTERVAL, + /* This value is expressed in units of 10 ms, rather than 1 ms. */ + .conn_sup_timeout = NRF_DFU_BLE_CONN_SUP_TIMEOUT_MS / 10, + .slave_latency = 0, +}; + +NRF_BALLOC_DEF(m_buffer_pool, MAX_DFU_PKT_LEN, MAX_DFU_BUFFERS); + + +/**@brief Function for the Advertising functionality initialization. + * + * @details Encodes the required advertising data and passes it to the stack. + * The advertising data encoded here is specific for DFU. + */ +static uint32_t advertising_init(uint8_t adv_flags, ble_gap_adv_params_t const * const p_adv_params) +{ + uint32_t err_code; + uint16_t actual_device_name_length = BLE_GAP_ADV_SET_DATA_SIZE_MAX - APP_ADV_DATA_HEADER_SIZE; + + /* This needs to be static because of SoftDevice API requirements. */ + static uint8_t m_enc_advdata[BLE_GAP_ADV_SET_DATA_SIZE_MAX]; + + ble_gap_adv_data_t m_adv_data = + { + .adv_data = + { + .p_data = m_enc_advdata, + .len = APP_ADV_DATA_HEADER_SIZE, + } + }; + + /* Encode flags. */ + m_enc_advdata[0] = 0x2; + m_enc_advdata[1] = BLE_GAP_AD_TYPE_FLAGS; + m_enc_advdata[2] = adv_flags; + + /* Encode 'more available' UUID list. */ + m_enc_advdata[3] = 0x3; + m_enc_advdata[4] = BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE; + m_enc_advdata[5] = LSB_16(BLE_DFU_SERVICE_UUID); + m_enc_advdata[6] = MSB_16(BLE_DFU_SERVICE_UUID); + + /* Get GAP device name and length. */ + err_code = sd_ble_gap_device_name_get(&m_enc_advdata[9], &actual_device_name_length); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + // Set GAP device in advertising data. + m_enc_advdata[7] = actual_device_name_length + 1; // (actual_length + ADV_AD_TYPE_FIELD_SIZE(1)) + m_enc_advdata[8] = BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME; + + m_adv_data.adv_data.len += actual_device_name_length; + + return sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, p_adv_params); +} + + +/**@brief Function for starting advertising. + */ +static uint32_t advertising_start(void) +{ + uint32_t err_code; + uint8_t adv_flag = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; + + ble_gap_adv_params_t adv_params = + { + .properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED, + .p_peer_addr = NULL, + .filter_policy = BLE_GAP_ADV_FP_ANY, + .interval = NRF_DFU_BLE_ADV_INTERVAL, + .duration = APP_ADV_DURATION, + .primary_phy = BLE_GAP_PHY_1MBPS, + }; + + NRF_LOG_DEBUG("Advertising..."); + +#if (NRF_DFU_BLE_REQUIRES_BONDS) + ble_gap_irk_t empty_irk = {{0}}; + + if (memcmp(m_peer_data.ble_id.id_info.irk, empty_irk.irk, sizeof(ble_gap_irk_t)) != 0) + { + adv_flag = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED; + adv_params.filter_policy = BLE_GAP_ADV_FP_FILTER_CONNREQ; + + ble_gap_addr_t const * const p_gap_addr = &m_peer_data.ble_id.id_addr_info; + ble_gap_id_key_t const * const p_gap_id_key = &m_peer_data.ble_id; + + err_code = sd_ble_gap_whitelist_set(&p_gap_addr, 1); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_WARNING("sd_ble_gap_whitelist_set() returned %s", + NRF_LOG_ERROR_STRING_GET(err_code)); + } + + err_code = sd_ble_gap_device_identities_set(&p_gap_id_key, NULL, 1); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_WARNING("sd_ble_gap_device_identities_set() returned %s", + NRF_LOG_ERROR_STRING_GET(err_code)); + } + } +#endif /* NRF_DFU_BLE_REQUIRES_BONDS */ + + err_code = advertising_init(adv_flag, &adv_params); + VERIFY_SUCCESS(err_code); + + err_code = sd_ble_gap_adv_stop(m_adv_handle); + UNUSED_RETURN_VALUE(err_code); + + return sd_ble_gap_adv_start(m_adv_handle, APP_BLE_CONN_CFG_TAG); +} + + +static bool is_cccd_configured(ble_dfu_t * p_dfu) +{ + uint8_t cccd_val_buf[BLE_CCCD_VALUE_LEN]; + + ble_gatts_value_t gatts_value = + { + .len = BLE_CCCD_VALUE_LEN, + .p_value = cccd_val_buf + }; + + /* Check the CCCD Value of DFU Control Point. */ + uint32_t err_code = sd_ble_gatts_value_get(m_conn_handle, + p_dfu->dfu_ctrl_pt_handles.cccd_handle, + &gatts_value); + VERIFY_SUCCESS(err_code); + + return ble_srv_is_notification_enabled(cccd_val_buf); +} + + +static ret_code_t response_send(uint8_t * p_buf, uint16_t len) +{ + ble_gatts_hvx_params_t hvx_params = + { + .handle = m_dfu.dfu_ctrl_pt_handles.value_handle, + .type = BLE_GATT_HVX_NOTIFICATION, + .p_data = (uint8_t *)(p_buf), + .p_len = &len, + }; + + return sd_ble_gatts_hvx(m_conn_handle, &hvx_params); +} + + +#if (NRF_DFU_BLE_REQUIRES_BONDS) +static uint32_t service_changed_send(void) +{ + uint32_t err_code; + + NRF_LOG_DEBUG("Sending Service Changed indication"); + + err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, + m_peer_data.sys_serv_attr, + sizeof(m_peer_data.sys_serv_attr), + BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS); + VERIFY_SUCCESS(err_code); + + err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, + NULL, + 0, + BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS); + VERIFY_SUCCESS(err_code); + + err_code = sd_ble_gatts_service_changed(m_conn_handle, m_dfu.service_handle, 0xFFFF); + + if ( (err_code == BLE_ERROR_INVALID_CONN_HANDLE) + || (err_code == NRF_ERROR_INVALID_STATE) + || (err_code == NRF_ERROR_BUSY)) + { + /* These errors can be expected when trying to send a Service Changed indication */ + /* if the CCCD is not set to indicate. Thus, set the returning error code to success. */ + NRF_LOG_WARNING("Client did not have the Service Changed indication set to enabled." + "Error: 0x%08x", err_code); + err_code = NRF_SUCCESS; + } + + return err_code; +} +#endif + + +/**@brief Function for encoding the beginning of a response. + * + * @param[inout] p_buffer The buffer to encode into. + * @param[in] op_code The opcode of the response. + * @param[in] result The result of the operation. + * + * @return The length added to the buffer. + */ +static uint32_t response_prepare(uint8_t * p_buffer, uint8_t op_code, uint8_t result) +{ + ASSERT(p_buffer); + p_buffer[0] = NRF_DFU_OP_RESPONSE; + p_buffer[1] = op_code; + p_buffer[2] = result; + return RESPONSE_HEADER_LEN; +} + + +/**@brief Function for encoding a select object response into a buffer. + * + * The select object response consists of a maximum object size, a firmware offset, and a CRC value. + * + * @param[inout] p_buffer The buffer to encode the response into. + * @param[in] max_size The maximum object size value to encode. + * @param[in] fw_offset The firmware offset value to encode. + * @param[in] crc The CRC value to encode. + * + * @return The length added to the buffer. + */ +static uint32_t response_select_obj_add(uint8_t * p_buffer, + uint32_t max_size, + uint32_t fw_offset, + uint32_t crc) +{ + uint16_t offset = uint32_encode(max_size, &p_buffer[RESPONSE_HEADER_LEN]); + offset += uint32_encode(fw_offset, &p_buffer[RESPONSE_HEADER_LEN + offset]); + offset += uint32_encode(crc, &p_buffer[RESPONSE_HEADER_LEN + offset]); + return offset; +} + + +/**@brief Function for encoding a CRC response into a buffer. + * + * The CRC response consists of a firmware offset and a CRC value. + * + * @param[inout] p_buffer The buffer to encode the response into. + * @param[in] fw_offset The firmware offset value to encode. + * @param[in] crc The CRC value to encode. + * + * @return The length added to the buffer. + */ +static uint32_t response_crc_add(uint8_t * p_buffer, uint32_t fw_offset, uint32_t crc) +{ + uint16_t offset = uint32_encode(fw_offset, &p_buffer[RESPONSE_HEADER_LEN]); + offset += uint32_encode(crc, &p_buffer[RESPONSE_HEADER_LEN + offset]); + return offset; +} + + +/**@brief Function for appending an extended error code to the response buffer. + * + * @param[inout] p_buffer The buffer to append the extended error code to. + * @param[in] result The error code to append. + * @param[in] buf_offset The current length of the buffer. + * + * @return The length added to the buffer. + */ +static uint32_t response_ext_err_payload_add(uint8_t * p_buffer, uint8_t result, uint32_t buf_offset) +{ + p_buffer[buf_offset] = ext_error_get(); + (void) ext_error_set(NRF_DFU_EXT_ERROR_NO_ERROR); + return 1; +} + + +static void ble_dfu_req_handler_callback(nrf_dfu_response_t * p_res, void * p_context) +{ + ASSERT(p_res); + ASSERT(p_context); + + uint8_t len = 0; + uint8_t buffer[MAX_RESPONSE_LEN] = {0}; + + if (p_res->request == NRF_DFU_OP_OBJECT_WRITE) + { + --m_pkt_notif_target_cnt; + if ((m_pkt_notif_target == 0) || (m_pkt_notif_target_cnt && m_pkt_notif_target > 0)) + { + return; + } + + /* Reply with a CRC message and reset the packet counter. */ + m_pkt_notif_target_cnt = m_pkt_notif_target; + + p_res->request = NRF_DFU_OP_CRC_GET; + } + + len += response_prepare(buffer, p_res->request, p_res->result); + + if (p_res->result != NRF_DFU_RES_CODE_SUCCESS) + { + NRF_LOG_WARNING("DFU request %d failed with error: 0x%x", p_res->request, p_res->result); + + if (p_res->result == NRF_DFU_RES_CODE_EXT_ERROR) + { + len += response_ext_err_payload_add(buffer, p_res->result, len); + } + + (void) response_send(buffer, len); + return; + } + + switch (p_res->request) + { + case NRF_DFU_OP_OBJECT_CREATE: + case NRF_DFU_OP_OBJECT_EXECUTE: + break; + + case NRF_DFU_OP_OBJECT_SELECT: + { + len += response_select_obj_add(buffer, + p_res->select.max_size, + p_res->select.offset, + p_res->select.crc); + } break; + + case NRF_DFU_OP_OBJECT_WRITE: + { + len += response_crc_add(buffer, p_res->write.offset, p_res->write.crc); + } break; + + case NRF_DFU_OP_CRC_GET: + { + len += response_crc_add(buffer, p_res->crc.offset, p_res->crc.crc); + } break; + + default: + { + // No action. + } break; + } + + (void) response_send(buffer, len); +} + + +/**@brief Function for handling a Write event on the Control Point characteristic. + * + * @param[in] p_dfu DFU Service Structure. + * @param[in] p_ble_write_evt Pointer to the write event received from BLE stack. + * + * @return NRF_SUCCESS on successful processing of control point write. Otherwise an error code. + */ +static uint32_t on_ctrl_pt_write(ble_dfu_t * p_dfu, ble_gatts_evt_write_t const * p_ble_write_evt) +{ + //lint -save -e415 -e416 : Out-of-bounds access on p_ble_write_evt->data + nrf_dfu_request_t request = + { + .request = (nrf_dfu_op_t)(p_ble_write_evt->data[0]), + .p_context = p_dfu, + .callback.response = ble_dfu_req_handler_callback, + }; + + switch (request.request) + { + case NRF_DFU_OP_OBJECT_SELECT: + { + /* Set object type to read info about */ + request.select.object_type = p_ble_write_evt->data[1]; + } break; + + case NRF_DFU_OP_OBJECT_CREATE: + { + /* Reset the packet receipt notification on create object */ + m_pkt_notif_target_cnt = m_pkt_notif_target; + + request.create.object_type = p_ble_write_evt->data[1]; + request.create.object_size = uint32_decode(&(p_ble_write_evt->data[2])); + + if (request.create.object_type == NRF_DFU_OBJ_TYPE_COMMAND) + { + /* Activity on the current transport. Close all except the current one. */ + (void) nrf_dfu_transports_close(&ble_dfu_transport); + } + } break; + + case NRF_DFU_OP_RECEIPT_NOTIF_SET: + { + NRF_LOG_DEBUG("Set receipt notif"); + + m_pkt_notif_target = uint16_decode(&(p_ble_write_evt->data[1])); + m_pkt_notif_target_cnt = m_pkt_notif_target; + } break; + + default: + break; + } + //lint -restore : Out-of-bounds access + + return nrf_dfu_req_handler_on_req(&request); +} + + +/**@brief Function for handling the @ref BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST event from the + * SoftDevice. + * + * @param[in] p_dfu DFU Service Structure. + * @param[in] p_ble_evt Pointer to the event received from BLE stack. + */ +static bool on_rw_authorize_req(ble_dfu_t * p_dfu, ble_evt_t const * p_ble_evt) +{ + uint32_t err_code; + + ble_gatts_evt_rw_authorize_request_t const * p_authorize_request; + ble_gatts_evt_write_t const * p_ble_write_evt; + + p_authorize_request = &(p_ble_evt->evt.gatts_evt.params.authorize_request); + p_ble_write_evt = &(p_ble_evt->evt.gatts_evt.params.authorize_request.request.write); + + if ( (p_authorize_request->type != BLE_GATTS_AUTHORIZE_TYPE_WRITE) + || (p_authorize_request->request.write.handle != p_dfu->dfu_ctrl_pt_handles.value_handle) + || (p_authorize_request->request.write.op != BLE_GATTS_OP_WRITE_REQ)) + { + return false; + } + + ble_gatts_rw_authorize_reply_params_t auth_reply = + { + .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, + .params.write.update = 1, + .params.write.offset = p_ble_write_evt->offset, + .params.write.len = p_ble_write_evt->len, + .params.write.p_data = p_ble_write_evt->data, + }; + + if (!is_cccd_configured(p_dfu)) + { + /* Send an error response to the peer indicating that the CCCD is improperly configured. */ + auth_reply.params.write.gatt_status = BLE_GATT_STATUS_ATTERR_CPS_CCCD_CONFIG_ERROR; + + /* Ignore response of auth reply */ + (void) sd_ble_gatts_rw_authorize_reply(m_conn_handle, &auth_reply); + return false; + } + else + { + auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; + + err_code = sd_ble_gatts_rw_authorize_reply(m_conn_handle, &auth_reply); + return err_code == NRF_SUCCESS ? true : false; + } +} + + +static void on_flash_write(void * p_buf) +{ + NRF_LOG_DEBUG("Freeing buffer %p", p_buf); + nrf_balloc_free(&m_buffer_pool, p_buf); +} + + +/**@brief Function for handling the @ref BLE_GATTS_EVT_WRITE event from the SoftDevice. + * + * @param[in] p_dfu DFU Service Structure. + * @param[in] p_ble_evt Pointer to the event received from BLE stack. + */ +static void on_write(ble_dfu_t * p_dfu, ble_evt_t const * p_ble_evt) +{ + ble_gatts_evt_write_t const * const p_write_evt = &p_ble_evt->evt.gatts_evt.params.write; + + if (p_write_evt->handle != p_dfu->dfu_pkt_handles.value_handle) + { + return; + } + + /* Allocate a buffer to receive data. */ + uint8_t * p_balloc_buf = nrf_balloc_alloc(&m_buffer_pool); + if (p_balloc_buf == NULL) + { + /* Operations are retried by the host; do not give up here. */ + NRF_LOG_WARNING("cannot allocate memory buffer!"); + return; + } + + NRF_LOG_DEBUG("Buffer %p acquired, len %d (%d)", + p_balloc_buf, p_write_evt->len, MAX_DFU_PKT_LEN); + + /* Copy payload into buffer. */ + memcpy(p_balloc_buf, p_write_evt->data, p_write_evt->len); + + /* Set up the request. */ + nrf_dfu_request_t request = + { + .request = NRF_DFU_OP_OBJECT_WRITE, + .p_context = p_dfu, + .callback = + { + .response = ble_dfu_req_handler_callback, + .write = on_flash_write, + } + }; + + /* Set up the request buffer. */ + request.write.p_data = p_balloc_buf; + request.write.len = p_write_evt->len; + + /* Schedule handling of the request. */ + ret_code_t rc = nrf_dfu_req_handler_on_req(&request); + if (rc != NRF_SUCCESS) + { + /* The error is logged in nrf_dfu_req_handler_on_req(). + * Free the buffer. + */ + (void) nrf_balloc_free(&m_buffer_pool, p_balloc_buf); + } +} + + +/**@brief Function for the Application's SoftDevice event handler. + * + * @param[in] p_ble_evt SoftDevice event. + */ +static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) +{ + uint32_t err_code; + ble_gap_evt_t const * const p_gap = &p_ble_evt->evt.gap_evt; + + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_CONNECTED: + { + NRF_LOG_DEBUG("Connected"); + + m_conn_handle = p_gap->conn_handle; + + if (m_observer) + { + m_observer(NRF_DFU_EVT_TRANSPORT_ACTIVATED); + } + + err_code = sd_ble_gap_conn_param_update(m_conn_handle, &m_gap_conn_params); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Failure to update connection parameters: 0x%x", err_code); + } + } break; + + case BLE_GAP_EVT_DISCONNECTED: + { + m_conn_handle = BLE_CONN_HANDLE_INVALID; + + /* Restart advertising so that the DFU Controller can reconnect if possible. */ + if (!(m_flags & DFU_BLE_RESETTING_SOON)) + { + err_code = advertising_start(); + APP_ERROR_CHECK(err_code); + } + + if (m_observer) + { + m_observer(NRF_DFU_EVT_TRANSPORT_DEACTIVATED); + } + } break; + + case BLE_GATTS_EVT_WRITE: + { + on_write(&m_dfu, p_ble_evt); + } break; + + case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: + { + uint16_t const mtu_requested = + p_ble_evt->evt.gatts_evt.params.exchange_mtu_request.client_rx_mtu; + + /* If the requested MTU is smaller than the maximum, we can accept with the given + * stack configuration, and the payload is not word-aligned, reply with a smaller MTU + * that has a word-aligned payload. This ensures that the length of data we write to + * flash is a multiple of the word size. + */ + uint16_t mtu_reply; + + if (mtu_requested < NRF_SDH_BLE_GATT_MAX_MTU_SIZE) + { + /* Round the payload size down to a multiple of 4 so it is word-aligned. */ + if (GATT_PAYLOAD(mtu_requested) % 4) + { + mtu_reply = GATT_PAYLOAD(mtu_requested) - 4; + mtu_reply = ALIGN_NUM(4, mtu_reply); + /* Add the header len to the MTU. */ + mtu_reply += GATT_HEADER_LEN; + } + else + { + mtu_reply = mtu_requested; + } + } + else + { + mtu_reply = NRF_SDH_BLE_GATT_MAX_MTU_SIZE; + } + + NRF_LOG_DEBUG("Received BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST (request: %d, reply: %d).", + mtu_requested, mtu_reply); + + err_code = sd_ble_gatts_exchange_mtu_reply(m_conn_handle, mtu_reply); + APP_ERROR_CHECK(err_code); + } break; +#ifndef S112 + case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST: + { + NRF_LOG_DEBUG("Received BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST."); + + ble_gap_data_length_params_t const dlp = + { + .max_rx_octets = BLE_GAP_DATA_LENGTH_AUTO, + .max_tx_octets = BLE_GAP_DATA_LENGTH_AUTO, + }; + + err_code = sd_ble_gap_data_length_update(p_ble_evt->evt.gatts_evt.conn_handle, + &dlp, NULL); + APP_ERROR_CHECK(err_code); + } break; + + case BLE_GAP_EVT_DATA_LENGTH_UPDATE: + { + NRF_LOG_DEBUG("Received BLE_GAP_EVT_DATA_LENGTH_UPDATE (%u, max_rx_time %u).", + p_gap->params.data_length_update.effective_params.max_rx_octets, + p_gap->params.data_length_update.effective_params.max_rx_time_us); + } break; +#endif + + case BLE_GAP_EVT_SEC_PARAMS_REQUEST: + { + NRF_LOG_DEBUG("Received BLE_GAP_EVT_SEC_PARAMS_REQUEST"); + + uint16_t cccd; + ble_gatts_value_t gatts_value = + { + .len = BLE_CCCD_VALUE_LEN, + .p_value = (uint8_t*)&cccd + }; + + err_code = sd_ble_gatts_value_get(m_conn_handle, + BLE_UUID_GATT_CHARACTERISTIC_SERVICE_CHANGED, + &gatts_value); + APP_ERROR_CHECK(err_code); + + NRF_LOG_DEBUG("CCCD for service changed is 0x%04x", cccd); + + err_code = sd_ble_gap_sec_params_reply(m_conn_handle, + BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, + NULL, + NULL); + APP_ERROR_CHECK(err_code); + } break; + + case BLE_GAP_EVT_CONN_PARAM_UPDATE: + { + NRF_LOG_DEBUG("Received BLE_GAP_EVT_CONN_PARAM_UPDATE"); + + ble_gap_conn_params_t const * p_conn = + &p_gap->params.conn_param_update.conn_params; + + NRF_LOG_DEBUG("max_conn_interval: %d", p_conn->max_conn_interval); + NRF_LOG_DEBUG("min_conn_interval: %d", p_conn->min_conn_interval); + NRF_LOG_DEBUG("slave_latency: %d", p_conn->slave_latency); + NRF_LOG_DEBUG("conn_sup_timeout: %d", p_conn->conn_sup_timeout); + } break; + +#ifndef S112 + case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: + { + NRF_LOG_DEBUG("Received BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST"); + + err_code = sd_ble_gap_conn_param_update(m_conn_handle, + &p_gap->params.conn_param_update_request.conn_params); + + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Failure to update connection parameter request: 0x%x", err_code); + } + + APP_ERROR_CHECK(err_code); + } break; +#endif + + case BLE_GAP_EVT_PHY_UPDATE: + { + NRF_LOG_DEBUG("Received BLE_GAP_EVT_PHY_UPDATE (RX:%d, TX:%d, status:%d)", + p_gap->params.phy_update.rx_phy, + p_gap->params.phy_update.tx_phy, + p_gap->params.phy_update.status); + break; + } + + case BLE_GAP_EVT_PHY_UPDATE_REQUEST: + { + NRF_LOG_DEBUG("Received BLE_GAP_EVT_PHY_UPDATE_REQUEST."); + + ble_gap_phys_t const phys = + { + .rx_phys = BLE_GAP_PHY_AUTO, + .tx_phys = BLE_GAP_PHY_AUTO, + }; + + err_code = sd_ble_gap_phy_update(p_gap->conn_handle, &phys); + APP_ERROR_CHECK(err_code); + } break; + + case BLE_GATTS_EVT_TIMEOUT: + { + if (p_ble_evt->evt.gatts_evt.params.timeout.src == BLE_GATT_TIMEOUT_SRC_PROTOCOL) + { + err_code = sd_ble_gap_disconnect(m_conn_handle, + BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + APP_ERROR_CHECK(err_code); + } + } break; + + case BLE_EVT_USER_MEM_REQUEST: + { + err_code = sd_ble_user_mem_reply(m_conn_handle, NULL); + APP_ERROR_CHECK(err_code); + } break; + + case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: + { + if (p_ble_evt->evt.gatts_evt.params.authorize_request.type + != BLE_GATTS_AUTHORIZE_TYPE_INVALID) + { + if (on_rw_authorize_req(&m_dfu, p_ble_evt)) + { + err_code = on_ctrl_pt_write(&m_dfu, + &(p_ble_evt->evt.gatts_evt.params.authorize_request.request.write)); + + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Could not handle on_ctrl_pt_write. err_code: 0x%04x", err_code); + } + } + } + } break; + + case BLE_GAP_EVT_SEC_INFO_REQUEST: + { + NRF_LOG_DEBUG("Received BLE_GAP_EVT_SEC_INFO_REQUEST"); + + ble_gap_enc_info_t * p_enc_info = NULL; + ble_gap_irk_t * p_id_info = NULL; + + #if (NRF_DFU_BLE_REQUIRES_BONDS) + /* If there is a match in diversifier, then set the correct keys. */ + if (p_gap->params.sec_info_request.master_id.ediv == + m_peer_data.enc_key.master_id.ediv) + { + p_enc_info = &m_peer_data.enc_key.enc_info; + } + p_id_info = &m_peer_data.ble_id.id_info; + #endif + + err_code = sd_ble_gap_sec_info_reply(p_gap->conn_handle, p_enc_info, p_id_info, NULL); + APP_ERROR_CHECK(err_code); + } break; + + case BLE_GAP_EVT_CONN_SEC_UPDATE: + case BLE_GATTS_EVT_SYS_ATTR_MISSING: + { + #if (NRF_DFU_BLE_REQUIRES_BONDS) + err_code = service_changed_send(); + #else + err_code = sd_ble_gatts_sys_attr_set(p_gap->conn_handle, NULL, 0, 0); + #endif + APP_ERROR_CHECK(err_code); + NRF_LOG_DEBUG("Finished handling conn sec update"); + } break; + + default: + /* No implementation needed. */ + break; + } +} + + +#if (!NRF_DFU_BLE_REQUIRES_BONDS) +static uint32_t gap_address_change(void) +{ + uint32_t err_code; + ble_gap_addr_t addr; + + err_code = sd_ble_gap_addr_get(&addr); + VERIFY_SUCCESS(err_code); + + /* Increase the BLE address by one when advertising openly. */ + addr.addr[0] += 1; + + err_code = sd_ble_gap_addr_set(&addr); + VERIFY_SUCCESS(err_code); + + return NRF_SUCCESS; +} +#endif + + +/**@brief Function for initializing GAP. + * + * @details This function sets up all necessary GAP (Generic Access Profile) parameters of + * the device. It also sets the permissions and appearance. + */ +static uint32_t gap_params_init(void) +{ + uint32_t err_code; + ble_gap_conn_sec_mode_t sec_mode; + uint8_t const * device_name; + uint32_t name_len; + + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); + +#if (!NRF_DFU_BLE_REQUIRES_BONDS) + + err_code = gap_address_change(); + VERIFY_SUCCESS(err_code); + + if ((m_flags & DFU_BLE_FLAG_USE_ADV_NAME) != 0) + { + NRF_LOG_DEBUG("Setting adv name: %s, length: %d", m_adv_name.name, m_adv_name.len); + device_name = m_adv_name.name; + name_len = m_adv_name.len; + } + else +#endif + { + NRF_LOG_DEBUG("Using default advertising name"); + device_name = (uint8_t const *)(NRF_DFU_BLE_ADV_NAME); + name_len = strlen(NRF_DFU_BLE_ADV_NAME); + } + + err_code = sd_ble_gap_device_name_set(&sec_mode, device_name, name_len); + VERIFY_SUCCESS(err_code); + + err_code = sd_ble_gap_ppcp_set(&m_gap_conn_params); + return err_code; +} + + +static uint32_t ble_stack_init() +{ + ret_code_t err_code; + uint32_t ram_start = 0; + + /* Register as a BLE event observer to receive BLE events. */ + NRF_SDH_BLE_OBSERVER(m_ble_evt_observer, BLE_OBSERVER_PRIO, ble_evt_handler, NULL); + +#if (!defined(NRF_DFU_BLE_SKIP_SD_INIT)) || (NRF_DFU_BLE_SKIP_SD_INIT == 0) + err_code = nrf_dfu_mbr_init_sd(); + VERIFY_SUCCESS(err_code); + + NRF_LOG_DEBUG("Setting up vector table: 0x%08x", BOOTLOADER_START_ADDR); + err_code = sd_softdevice_vector_table_base_set(BOOTLOADER_START_ADDR); + VERIFY_SUCCESS(err_code); +#endif + + NRF_LOG_DEBUG("Enabling SoftDevice."); + err_code = nrf_sdh_enable_request(); + VERIFY_SUCCESS(err_code); + + /* Fetch the start address of the application RAM. */ + err_code = nrf_sdh_ble_app_ram_start_get(&ram_start); + VERIFY_SUCCESS(err_code); + + NRF_LOG_DEBUG("Configuring BLE stack."); + err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start); + VERIFY_SUCCESS(err_code); + + /* Enable the BLE stack. */ + NRF_LOG_DEBUG("Enabling the BLE stack."); + return nrf_sdh_ble_enable(&ram_start); +} + + +/**@brief Function for adding DFU Packet characteristic to the BLE Stack. + * + * @param[in] p_dfu DFU Service structure. + * + * @return NRF_SUCCESS on success. Otherwise an error code. + */ +static uint32_t dfu_pkt_char_add(ble_dfu_t * const p_dfu) +{ + ble_gatts_char_md_t char_md = + { + .char_props.write_wo_resp = 1, + }; + + ble_uuid_t char_uuid = + { + .type = p_dfu->uuid_type, + .uuid = BLE_DFU_PKT_CHAR_UUID, + }; + + ble_gatts_attr_md_t attr_md = + { + .vloc = BLE_GATTS_VLOC_STACK, + .vlen = 1, + .write_perm = + { + .sm = 1, + #if NRF_DFU_BLE_REQUIRES_BONDS + .lv = 2, + #else + .lv = 1, + #endif + } + }; + + ble_gatts_attr_t attr_char_value = + { + .p_uuid = &char_uuid, + .p_attr_md = &attr_md, + .max_len = MAX_DFU_PKT_LEN, + }; + + return sd_ble_gatts_characteristic_add(p_dfu->service_handle, + &char_md, + &attr_char_value, + &p_dfu->dfu_pkt_handles); +} + + +/**@brief Function for adding DFU Control Point characteristic to the BLE Stack. + * + * @param[in] p_dfu DFU Service structure. + * + * @return NRF_SUCCESS on success. Otherwise an error code. + */ +static uint32_t dfu_ctrl_pt_add(ble_dfu_t * const p_dfu) +{ + ble_gatts_char_md_t char_md = + { + .char_props.write = 1, + .char_props.notify = 1, + }; + + ble_uuid_t char_uuid = + { + .type = p_dfu->uuid_type, + .uuid = BLE_DFU_CTRL_PT_UUID, + }; + + ble_gatts_attr_md_t attr_md = + { + .vloc = BLE_GATTS_VLOC_STACK, + .wr_auth = 1, + .vlen = 1, + .write_perm = + { + .sm = 1, + #if NRF_DFU_BLE_REQUIRES_BONDS + .lv = 2, + #else + .lv = 1, + #endif + }, + }; + + ble_gatts_attr_t attr_char_value = + { + .p_uuid = &char_uuid, + .p_attr_md = &attr_md, + .max_len = BLE_GATT_ATT_MTU_DEFAULT, + }; + + return sd_ble_gatts_characteristic_add(p_dfu->service_handle, + &char_md, + &attr_char_value, + &p_dfu->dfu_ctrl_pt_handles); +} + + +/**@brief Function for checking if the CCCD of DFU Control point is configured for Notification. + * + * @details This function checks if the CCCD of DFU Control Point characteristic is configured + * for Notification by the DFU Controller. + * + * @param[in] p_dfu DFU Service structure. + * + * @return True if the CCCD of DFU Control Point characteristic is configured for Notification. + * False otherwise. + */ +uint32_t ble_dfu_init(ble_dfu_t * p_dfu) +{ + ASSERT(p_dfu != NULL); + + ble_uuid_t service_uuid; + uint32_t err_code; + + m_conn_handle = BLE_CONN_HANDLE_INVALID; + + BLE_UUID_BLE_ASSIGN(service_uuid, BLE_DFU_SERVICE_UUID); + + err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, + &service_uuid, + &(p_dfu->service_handle)); + VERIFY_SUCCESS(err_code); + + ble_uuid128_t const base_uuid128 = + { + { + 0x50, 0xEA, 0xDA, 0x30, 0x88, 0x83, 0xB8, 0x9F, + 0x60, 0x4F, 0x15, 0xF3, 0x00, 0x00, 0xC9, 0x8E + } + }; + + err_code = sd_ble_uuid_vs_add(&base_uuid128, &p_dfu->uuid_type); + VERIFY_SUCCESS(err_code); + + err_code = dfu_pkt_char_add(p_dfu); + VERIFY_SUCCESS(err_code); + + err_code = dfu_ctrl_pt_add(p_dfu); + VERIFY_SUCCESS(err_code); + + return NRF_SUCCESS; +} + + +uint32_t ble_dfu_transport_init(nrf_dfu_observer_t observer) +{ + uint32_t err_code = NRF_SUCCESS; + + if (m_flags & DFU_BLE_FLAG_INITIALIZED) + { + return err_code; + } + + NRF_LOG_DEBUG("Initializing BLE DFU transport"); + + m_observer = observer; + + err_code = nrf_balloc_init(&m_buffer_pool); + UNUSED_RETURN_VALUE(err_code); + + err_code = ble_stack_init(); + VERIFY_SUCCESS(err_code); + +#if (NRF_DFU_BLE_REQUIRES_BONDS) + /* Copy out the peer data if bonds are required */ + if (nrf_dfu_settings_peer_data_is_valid()) + { + NRF_LOG_DEBUG("Copying peer data"); + + err_code = nrf_dfu_settings_peer_data_copy(&m_peer_data); + UNUSED_RETURN_VALUE(err_code); + } + else + { + APP_ERROR_HANDLER(NRF_ERROR_INTERNAL); + } +#else + /* Copy out the new advertisement name when bonds are not required and the name is set. */ + if (nrf_dfu_settings_adv_name_is_valid()) + { + err_code = nrf_dfu_settings_adv_name_copy(&m_adv_name); + UNUSED_RETURN_VALUE(err_code); + + /* Set flags for advertisement name that is to be used */ + m_flags |= DFU_BLE_FLAG_USE_ADV_NAME; + } + else + { + NRF_LOG_DEBUG("No advertising name found"); + } +#endif + + err_code = gap_params_init(); + VERIFY_SUCCESS(err_code); + + /* Initialize the Device Firmware Update Service. */ + err_code = ble_dfu_init(&m_dfu); + VERIFY_SUCCESS(err_code); + + err_code = advertising_start(); + VERIFY_SUCCESS(err_code); + + m_flags |= DFU_BLE_FLAG_INITIALIZED; + + NRF_LOG_DEBUG("BLE DFU transport initialized."); + + return NRF_SUCCESS; +} + + +uint32_t ble_dfu_transport_close(nrf_dfu_transport_t const * p_exception) +{ + uint32_t err_code = NRF_SUCCESS; + + if ((m_flags & DFU_BLE_FLAG_INITIALIZED) && (p_exception != &ble_dfu_transport)) + { + NRF_LOG_DEBUG("Shutting down BLE transport."); + + if (m_conn_handle != BLE_CONN_HANDLE_INVALID) + { + NRF_LOG_DEBUG("Disconnecting."); + + /* Set flag to prevent advertisement from starting */ + m_flags |= DFU_BLE_RESETTING_SOON; + + /* Disconnect from the peer. */ + err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + VERIFY_SUCCESS(err_code); + + /* Wait a bit for the disconnect event to be sent on air. */ + nrf_delay_ms(200); + } + else + { + err_code = sd_ble_gap_adv_stop(m_adv_handle); + UNUSED_RETURN_VALUE(err_code); + } + nrf_drv_clock_lfclk_request(NULL); + err_code = nrf_sdh_disable_request(); + if (err_code == NRF_SUCCESS) + { + NRF_LOG_DEBUG("BLE transport shut down."); + } + } + + return err_code; +} + +uint32_t ble_dfu_transport_disconnect(void) +{ + uint32_t err_code = NRF_SUCCESS; + + if (m_flags & DFU_BLE_FLAG_INITIALIZED) + { + NRF_LOG_DEBUG("Disconnect from BLE peer."); + + if (m_conn_handle != BLE_CONN_HANDLE_INVALID) + { + NRF_LOG_DEBUG("Disconnecting."); + + /* Disconnect from the peer. */ + err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + VERIFY_SUCCESS(err_code); + } + } + + return err_code; +} From 1f11329ee3296bf0f8321b3e19abfb13ea1058bb Mon Sep 17 00:00:00 2001 From: gb88 Date: Tue, 12 Mar 2024 21:06:52 +0000 Subject: [PATCH 09/11] old board --- boards/s140/ecg_nrf52_v2_3/Makefile | 5 ++ boards/s140/ecg_nrf52_v2_3/include/config.h | 17 +++++ .../ecg_nrf52_v2_3/include/custom_board.h | 71 +++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 boards/s140/ecg_nrf52_v2_3/Makefile create mode 100644 boards/s140/ecg_nrf52_v2_3/include/config.h create mode 100644 boards/s140/ecg_nrf52_v2_3/include/custom_board.h diff --git a/boards/s140/ecg_nrf52_v2_3/Makefile b/boards/s140/ecg_nrf52_v2_3/Makefile new file mode 100644 index 0000000..40802af --- /dev/null +++ b/boards/s140/ecg_nrf52_v2_3/Makefile @@ -0,0 +1,5 @@ +include ../Makefile.boards + +CFLAGS += -DBOARD_CUSTOM + +ASMFLAGS += -DBOARD_CUSTOM diff --git a/boards/s140/ecg_nrf52_v2_3/include/config.h b/boards/s140/ecg_nrf52_v2_3/include/config.h new file mode 100644 index 0000000..440ae3a --- /dev/null +++ b/boards/s140/ecg_nrf52_v2_3/include/config.h @@ -0,0 +1,17 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#ifndef NRF_DFU_BLE_ADV_NAME +#define NRF_DFU_BLE_ADV_NAME "ECG_DFU" +#endif +#define BLEDIS_MANUFACTURER "ddB0515" +#define BLEDIS_MODEL "nRF52840 Board" + +#define APP_USBD_VID 0x239A +#define APP_USBD_PID 0x0029 +#endif + +#ifndef NRF_DFU_BL_ALLOW_DOWNGRADE +#define NRF_DFU_BL_ALLOW_DOWNGRADE 1 +#endif + diff --git a/boards/s140/ecg_nrf52_v2_3/include/custom_board.h b/boards/s140/ecg_nrf52_v2_3/include/custom_board.h new file mode 100644 index 0000000..bfd1a8b --- /dev/null +++ b/boards/s140/ecg_nrf52_v2_3/include/custom_board.h @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2023-Giovanni Bonomini + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of the 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 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 CUSTOM_BOARD_H +#define CUSTOM_BOARD_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nrf_gpio.h" + +#define LEDS_NUMBER 3 +/* +GREEN 45 1.13 +RED 47 1.15 +BLUE 46 1.14 +*/ +#define LED_1 NRF_GPIO_PIN_MAP(1,14) +#define LED_2 NRF_GPIO_PIN_MAP(1,15) +#define LED_3 NRF_GPIO_PIN_MAP(1,13) + +#define LEDS_ACTIVE_STATE 1 + +#define LEDS_LIST { LED_1, LED_2, LED_3 } + +#define LEDS_INV_MASK LEDS_MASK + +#define BSP_LED_0 LED_1 +#define BSP_LED_1 LED_2 +#define BSP_LED_2 LED_3 + +#define BUTTONS_NUMBER 1 + +#define BUTTON_1 NRF_GPIO_PIN_MAP(1,10) +#define BUTTON_PULL NRF_GPIO_PIN_NOPULL +#define BUTTONS_ACTIVE_STATE 1 + +#define BUTTONS_LIST { BUTTON_1 } + +#define BSP_BUTTON_0 BUTTON_1 + +#ifdef __cplusplus +} +#endif + +#endif // CUSTOM_BOARD_H From f817a3a54083c085b154a9a4522e52667cb6ca4d Mon Sep 17 00:00:00 2001 From: gb88 Date: Mon, 25 Mar 2024 23:22:43 +0000 Subject: [PATCH 10/11] delete delay --- main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.c b/main.c index a82b4f8..edd0f2a 100644 --- a/main.c +++ b/main.c @@ -195,7 +195,7 @@ static void kaidyth_bootstrap(void) if (BUTTONS_NUMBER > 0 && ((reset_reason & 0x10000) != 0x10000)) { nrf_gpio_cfg_input(BUTTON_1,BUTTON_PULL); - nrf_delay_ms(50); + //nrf_delay_ms(50); if(nrf_gpio_pin_read(BUTTON_1) == BUTTONS_ACTIVE_STATE) nrf_power_gpregret_set(BOOTLOADER_DFU_START); } From 4dd234aad6e3e0c3f76df01a9be473bb11ff06de Mon Sep 17 00:00:00 2001 From: gb88 Date: Tue, 26 Mar 2024 11:26:47 +0000 Subject: [PATCH 11/11] errata 173 --- main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.c b/main.c index edd0f2a..878f07e 100644 --- a/main.c +++ b/main.c @@ -195,7 +195,7 @@ static void kaidyth_bootstrap(void) if (BUTTONS_NUMBER > 0 && ((reset_reason & 0x10000) != 0x10000)) { nrf_gpio_cfg_input(BUTTON_1,BUTTON_PULL); - //nrf_delay_ms(50); + nrf_delay_us(100); if(nrf_gpio_pin_read(BUTTON_1) == BUTTONS_ACTIVE_STATE) nrf_power_gpregret_set(BOOTLOADER_DFU_START); }