diff --git a/.github/workflows/githubci.yml b/.github/workflows/githubci.yml
index a683845..22fc553 100644
--- a/.github/workflows/githubci.yml
+++ b/.github/workflows/githubci.yml
@@ -23,10 +23,7 @@ jobs:
- name: Install Toolchains
run: |
- pip3 install adafruit-nrfutil uritemplate requests
- wget https://www.nordicsemi.com/api/sitecore/Products/DownloadPlatform --post-data=fileid=8F19D314130548209E75EFFADD9348DB -O cli-tools.tar
- tar -xv -f cli-tools.tar
- echo "::add-path::$GITHUB_WORKSPACE/mergehex"
+ pip3 install adafruit-nrfutil uritemplate requests intelhex
npm install --global xpm
xpm install --global @xpack-dev-tools/arm-none-eabi-gcc@latest
echo "::add-path::`echo $HOME/opt/xPacks/@xpack-dev-tools/arm-none-eabi-gcc/*/.content/bin`"
diff --git a/.gitignore b/.gitignore
index 702c907..67a7f32 100644
--- a/.gitignore
+++ b/.gitignore
@@ -51,10 +51,11 @@ Module.symvers
Mkfile.old
dkms.conf
-src/segger/Output
-_build-*/
+segger/Output
+_build/
bin/
*.emSession
*.jlink
+.idea/
TAGS
diff --git a/.gitmodules b/.gitmodules
index 8acbe85..bd80adc 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,6 +1,10 @@
-[submodule "tinyusb"]
+[submodule "lib/tinyusb"]
path = lib/tinyusb
url = https://github.com/hathach/tinyusb.git
[submodule "lib/nrfx"]
path = lib/nrfx
url = https://github.com/NordicSemiconductor/nrfx.git
+[submodule "lib/uf2"]
+ path = lib/uf2
+ url = https://github.com/microsoft/uf2.git
+
diff --git a/Makefile b/Makefile
index 1ff8a65..627e3ae 100644
--- a/Makefile
+++ b/Makefile
@@ -17,8 +17,10 @@ SD_VERSION = 6.1.1
SD_FILENAME = $(SD_NAME)_nrf52_$(SD_VERSION)
SD_HEX = $(SD_PATH)/$(SD_FILENAME)_softdevice.hex
-# linker by MCU and SoftDevice eg. nrf52840_s140_v6.ld
-LD_FILE = linker/$(MCU_SUB_VARIANT)_$(SD_NAME)_v$(word 1, $(subst ., ,$(SD_VERSION))).ld
+MBR_HEX = lib/softdevice/mbr/hex/mbr_nrf52_2.4.1_mbr.hex
+
+# linker by MCU eg. nrf52840.ld
+LD_FILE = linker/$(MCU_SUB_VARIANT).ld
GIT_VERSION = $(shell git describe --dirty --always --tags)
GIT_SUBMODULE_VERSIONS = $(shell git submodule status | cut -d' ' -f3,4 | paste -s -d" " -)
@@ -93,6 +95,9 @@ endif
# all files in src
C_SRC += $(wildcard src/*.c)
+# all files in boards
+C_SRC += $(wildcard src/boards/*.c)
+
# all sources files in specific board
C_SRC += $(wildcard src/boards/$(BOARD)/*.c)
@@ -162,11 +167,10 @@ ASM_SRC = $(NRFX_PATH)/mdk/gcc_startup_$(MCU_SUB_VARIANT).S
# src
IPATH += src
+IPATH += src/boards
IPATH += src/boards/$(BOARD)
-
IPATH += src/cmsis/include
IPATH += src/usb
-IPATH += src/boards
IPATH += $(TUSB_PATH)
# nrfx
@@ -196,17 +200,17 @@ IPATH += $(SDK_PATH)/drivers_nrf/delay
IPATH += $(SD_PATH)/$(SD_FILENAME)_API/include
IPATH += $(SD_PATH)/$(SD_FILENAME)_API/include/nrf52
-INC_PATHS = $(addprefix -I,$(IPATH))
-
#------------------------------------------------------------------------------
# Compiler Flags
#------------------------------------------------------------------------------
-# Debugging/Optimization
+# Debug option use RTT for printf
ifeq ($(DEBUG), 1)
- CFLAGS += -Og -ggdb
-else
- CFLAGS += -Os
+ RTT_SRC = lib/SEGGER_RTT
+
+ CFLAGS += -ggdb -DCFG_DEBUG -DSEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL
+ IPATH += $(RTT_SRC)/RTT
+ C_SRC += $(RTT_SRC)/RTT/SEGGER_RTT.c
endif
#flags common to all targets
@@ -216,6 +220,7 @@ CFLAGS += \
-mcpu=cortex-m4 \
-mfloat-abi=hard \
-mfpu=fpv4-sp-d16 \
+ -Os \
-ffunction-sections \
-fdata-sections \
-fno-builtin \
@@ -249,7 +254,7 @@ CFLAGS += -DCONFIG_NFCT_PINS_AS_GPIOS
CFLAGS += -DSOFTDEVICE_PRESENT
CFLAGS += -DDFU_APP_DATA_RESERVED=7*4096
-CFLAGS += -DUF2_VERSION='"$(GIT_VERSION) $(GIT_SUBMODULE_VERSIONS) $(SD_NAME) $(SD_VERSION)"'
+CFLAGS += -DUF2_VERSION='"$(GIT_VERSION) $(GIT_SUBMODULE_VERSIONS)"'
CFLAGS += -DBLEDIS_FW_VERSION='"$(GIT_VERSION) $(SD_NAME) $(SD_VERSION)"'
_VER = $(subst ., ,$(word 1, $(subst -, ,$(GIT_VERSION))))
@@ -289,6 +294,8 @@ vpath %.S $(ASM_PATHS)
OBJECTS = $(C_OBJECTS) $(ASM_OBJECTS)
+INC_PATHS = $(addprefix -I,$(IPATH))
+
#------------------------------------------------------------------------------
# BUILD TARGETS
#------------------------------------------------------------------------------
@@ -306,40 +313,11 @@ endif
.PHONY: all clean flash dfu-flash sd gdbflash gdb
# default target to build
-all: $(BUILD)/$(OUT_FILE)-nosd.out $(BUILD)/$(MERGED_FILE).hex
-
-#------------------- Flash target -------------------
-
-check_defined = \
- $(strip $(foreach 1,$1, \
- $(call __check_defined,$1,$(strip $(value 2)))))
-__check_defined = \
- $(if $(value $1),, \
- $(error Undefined make flag: $1$(if $2, ($2))))
-
-# Flash the compiled
-flash: $(BUILD)/$(OUT_FILE)-nosd.hex
- @echo Flashing: $<
- $(NRFJPROG) --program $< --sectoranduicrerase -f nrf52 --reset
-
-dfu-flash: $(BUILD)/$(MERGED_FILE).zip
- @:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyACM0)
- $(NRFUTIL) --verbose dfu serial --package $< -p $(SERIAL) -b 115200 --singlebank --touch 1200
-
-sd:
- @echo Flashing: $(SD_HEX)
- $(NRFJPROG) --program $(SD_HEX) -f nrf52 --chiperase --reset
-
-gdbflash: $(BUILD)/$(MERGED_FILE).hex
- @echo Flashing: $<
- @$(GDB_BMP) -nx --batch -ex 'load $<' -ex 'compare-sections' -ex 'kill'
-
-gdb: $(BUILD)/$(OUT_FILE)-nosd.out
- $(GDB_BMP) $<
+all: $(BUILD)/$(OUT_FILE).out $(BUILD)/$(OUT_FILE)-nosd.hex $(BUILD)/$(OUT_FILE)-nosd.uf2 $(BUILD)/$(MERGED_FILE).hex $(BUILD)/$(MERGED_FILE).zip
#------------------- Compile rules -------------------
-## Create build directories
+# Create build directories
$(BUILD):
@$(MK) $@
@@ -357,26 +335,73 @@ $(BUILD)/%.o: %.S
@$(CC) -x assembler-with-cpp $(ASFLAGS) $(INC_PATHS) -c -o $@ $<
# Link
-$(BUILD)/$(OUT_FILE)-nosd.out: $(BUILD) $(OBJECTS)
- @echo LD $(OUT_FILE)-nosd.out
+$(BUILD)/$(OUT_FILE).out: $(BUILD) $(OBJECTS)
+ @echo LD $(notdir $@)
@$(CC) -o $@ $(LDFLAGS) $(OBJECTS) -Wl,--start-group $(LIBS) -Wl,--end-group
@$(SIZE) $@
#------------------- Binary generator -------------------
-## Create binary .hex file from the .out file
-$(BUILD)/$(OUT_FILE)-nosd.hex: $(BUILD)/$(OUT_FILE)-nosd.out
- @echo CR $(OUT_FILE)-nosd.hex
+# Create hex file (no sd, no mbr)
+$(BUILD)/$(OUT_FILE).hex: $(BUILD)/$(OUT_FILE).out
+ @echo Create $(notdir $@)
@$(OBJCOPY) -O ihex $< $@
+# Hex file with mbr (still no SD)
+$(BUILD)/$(OUT_FILE)-nosd.hex: $(BUILD)/$(OUT_FILE).hex
+ @echo Create $(notdir $@)
+ @python3 tools/hexmerge.py --overlap=replace -o $@ $< $(MBR_HEX)
+
+# Bootolader only uf2
+$(BUILD)/$(OUT_FILE)-nosd.uf2: $(BUILD)/$(OUT_FILE)-nosd.hex
+ @echo Create $(notdir $@)
+ @python3 lib/uf2/utils/uf2conv.py -f 0xd663823c -c -o $@ $^
+
# merge bootloader and sd hex together
-$(BUILD)/$(MERGED_FILE).hex: $(BUILD)/$(OUT_FILE)-nosd.hex
- @echo CR $(MERGED_FILE).hex
- @mergehex -q -m $< $(SD_HEX) -o $@
+$(BUILD)/$(MERGED_FILE).hex: $(BUILD)/$(OUT_FILE).hex
+ @echo Create $(notdir $@)
+ @python3 tools/hexmerge.py -o $@ $< $(SD_HEX)
-## Create pkg zip file for bootloader+SD combo to use with DFU Serial
-.PHONY: genpkg
-genpkg: $(BUILD)/$(MERGED_FILE).zip
-
-$(BUILD)/$(MERGED_FILE).zip: $(BUILD)/$(OUT_FILE)-nosd.hex
+# Create pkg zip file for bootloader+SD combo to use with DFU CDC
+$(BUILD)/$(MERGED_FILE).zip: $(BUILD)/$(OUT_FILE).hex
@$(NRFUTIL) dfu genpkg --dev-type 0x0052 --dev-revision $(DFU_DEV_REV) --bootloader $< --softdevice $(SD_HEX) $@
+
+#------------------- Flash target -------------------
+
+check_defined = \
+ $(strip $(foreach 1,$1, \
+ $(call __check_defined,$1,$(strip $(value 2)))))
+__check_defined = \
+ $(if $(value $1),, \
+ $(error Undefined make flag: $1$(if $2, ($2))))
+
+# Flash the compiled
+flash: $(BUILD)/$(OUT_FILE)-nosd.hex
+ @echo Flashing: $(notdir $<)
+ $(NRFJPROG) --program $< --sectoranduicrerase -f nrf52 --reset
+
+# dfu using CDC interface
+dfu-flash: $(BUILD)/$(MERGED_FILE).zip
+ @:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyACM0)
+ $(NRFUTIL) --verbose dfu serial --package $< -p $(SERIAL) -b 115200 --singlebank --touch 1200
+
+erase:
+ @echo Erasing flash
+ $(NRFJPROG) -f nrf52 --eraseall
+
+# flash SD only
+sd:
+ @echo Flashing: $(SD_HEX)
+ $(NRFJPROG) --program $(SD_HEX) -f nrf52 --sectorerase --reset
+
+# flash MBR only
+mbr:
+ @echo Flashing: $(MBR_HEX)
+ $(NRFJPROG) --program $(MBR_HEX) -f nrf52 --sectorerase --reset
+
+gdbflash: $(BUILD)/$(MERGED_FILE).hex
+ @echo Flashing: $<
+ @$(GDB_BMP) -nx --batch -ex 'load $<' -ex 'compare-sections' -ex 'kill'
+
+gdb: $(BUILD)/$(OUT_FILE).out
+ $(GDB_BMP) $<
diff --git a/README.md b/README.md
index 6c65816..0a86a9d 100644
--- a/README.md
+++ b/README.md
@@ -20,33 +20,20 @@ This is a CDC/DFU/UF2 bootloader for nRF52 boards.
- Particle Xenon
UF2 is an easy-to-use bootloader that appears as a flash drive. You can just copy `.uf2`-format
-application images to the flash drive to load new firmware.
-See https://github.com/Microsoft/uf2 and https://github.com/adafruit/uf2-samdx1
-for more information.
+application images to the flash drive to load new firmware. See https://github.com/Microsoft/uf2 and https://github.com/adafruit/uf2-samdx1 for more information.
-[adafruit-nrfutil](https://github.com/adafruit/Adafruit_nRF52_nrfutil),
-a modified version of [Nordic nrfutil](https://github.com/NordicSemiconductor/pc-nrfutil),
-is required to perform DFU.
-Install `python3` if it is not installed already and run this command to install adafruit-nrfutil from PyPi:
+[adafruit-nrfutil](https://github.com/adafruit/Adafruit_nRF52_nrfutil), a modified version of [Nordic nrfutil](https://github.com/NordicSemiconductor/pc-nrfutil), is required to perform DFU. Install `python3` if it is not installed already and run this command to install adafruit-nrfutil from PyPi:
```
$ pip3 install --user adafruit-nrfutil
```
-This repository depends on the following submodules:
-
-- [tinyusb](https://github.com/hathach/tinyusb)
-- [nrfx](https://github.com/NordicSemiconductor/nrfx)
-
-Note that `tinyusb` also includes `nrfx` as a submodule, so you need
-to initialize and update submodules with the `--recursive`` flag.
-
Clone this repo with following commands, or fork it for your own development
```
git clone https://github.com/adafruit/Adafruit_nRF52_Bootloader
cd Adafruit_nRF52_Bootloader
-git submodule update --init --recursive
+git submodule update --init
```
## Features
@@ -63,7 +50,7 @@ There are two pins, `DFU` and `FRST` that bootloader will check upon reset/power
- `Double Reset` Reset twice within 500 ms will enter DFU with UF2 and CDC support (only works with nRF52840)
- `DFU = LOW` and `FRST = HIGH`: Enter bootloader with UF2 and CDC support
- `DFU = LOW` and `FRST = LOW`: Enter bootloader with OTA, to upgrade with a mobile application such as Nordic nrfConnect/Toolbox
-- `DFU = HIGH` and `FRST = LOW`: Factory Reset mode: erase firmware application and its data
+- `DFU = HIGH` and `FRST = LOW`: Factory Reset mode: erase firmware application and its data
- `DFU = HIGH` and `FRST = HIGH`: Go to application code if it is present, otherwise enter DFU with UF2
- The `GPREGRET` register can also be set to force the bootloader can enter any of above modes (plus a CDC-only mode for Arduino).
`GPREGRET` is set by the application before performing a soft reset.
@@ -92,6 +79,12 @@ To create a UF2 image from a .hex file:
uf2conv.py firmware.hex -c -f 0xADA52840
```
+To create a UF2 image for bootloader from a .hex file using separated family of **0xd663823c**
+
+```
+uf2conv.py bootloader.hex -c -f 0xd663823c
+```
+
## Burn & Upgrade with pre-built binaries
You can burn and/or upgrade the bootloader with either a J-link or DFU (serial) to a specific pre-built binary version
@@ -111,6 +104,7 @@ Prerequisites
- ARM GCC
- Nordic's [nRF5x Command Line Tools](https://www.nordicsemi.com/Software-and-Tools/Development-Tools/nRF-Command-Line-Tools)
+- [Python IntelHex](https://pypi.org/project/IntelHex/)
To build:
@@ -164,10 +158,17 @@ the variable `CROSS_COMPILE` as below:
$ make CROSS_COMPILE=/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/arm-none-eabi- BOARD=feather_nrf52832 all
```
-#### 2. `mergehex: No such file or directory`
+#### 2. `ModuleNotFoundError: No module named 'intelhex'`
+
+Install python-intelhex with
+
+```
+pip install intelhex
+```
+
+
+
-Make sure that `mergehex` is available from the command-line. This binary is
-part of Nordic's nRF5x Command Line Tools.
#### 3. `make: nrfjprog: No such file or directory`
diff --git a/lib/SEGGER_RTT/License.txt b/lib/SEGGER_RTT/License.txt
new file mode 100644
index 0000000..e1f5f89
--- /dev/null
+++ b/lib/SEGGER_RTT/License.txt
@@ -0,0 +1,34 @@
+Important - Read carefully:
+
+SEGGER RTT - Real Time Transfer for embedded targets
+
+All rights reserved.
+
+SEGGER strongly recommends to not make any changes
+to or modify the source code of this software in order to stay
+compatible with the RTT protocol and J-Link.
+
+Redistribution and use in source and binary forms, with or
+without modification, are permitted provided that the following
+condition is met:
+
+o Redistributions of source code must retain the above copyright
+ notice, this condition and the following disclaimer.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
+
+
+(c) 2014 - 2016 SEGGER Microcontroller GmbH
+www.segger.com
diff --git a/lib/SEGGER_RTT/README.txt b/lib/SEGGER_RTT/README.txt
new file mode 100644
index 0000000..49ec655
--- /dev/null
+++ b/lib/SEGGER_RTT/README.txt
@@ -0,0 +1,20 @@
+README.txt for the SEGGER RTT Implementation Pack.
+
+Included files:
+===============
+Root Directory
+ - Examples
+ - Main_RTT_InputEchoApp.c - Sample application which echoes input on Channel 0.
+ - Main_RTT_MenuApp.c - Sample application to demonstrate RTT bi-directional functionality.
+ - Main_RTT_PrintfTest.c - Sample application to test RTT small printf implementation.
+ - Main_RTT_SpeedTestApp.c - Sample application for measuring RTT performance. embOS needed.
+ - RTT
+ - SEGGER_RTT.c - The RTT implementation.
+ - SEGGER_RTT.h - Header for RTT implementation.
+ - SEGGER_RTT_Conf.h - Pre-processor configuration for the RTT implementation.
+ - SEGGER_RTT_Printf.c - Simple implementation of printf to write formatted strings via RTT.
+ - Syscalls
+ - RTT_Syscalls_GCC.c - Low-level syscalls to retarget printf() to RTT with GCC / Newlib.
+ - RTT_Syscalls_IAR.c - Low-level syscalls to retarget printf() to RTT with IAR compiler.
+ - RTT_Syscalls_KEIL.c - Low-level syscalls to retarget printf() to RTT with KEIL/uVision compiler.
+ - RTT_Syscalls_SES.c - Low-level syscalls to retarget printf() to RTT with SEGGER Embedded Studio.
diff --git a/lib/SEGGER_RTT/RTT/SEGGER_RTT.c b/lib/SEGGER_RTT/RTT/SEGGER_RTT.c
new file mode 100644
index 0000000..3ad2b1a
--- /dev/null
+++ b/lib/SEGGER_RTT/RTT/SEGGER_RTT.c
@@ -0,0 +1,2005 @@
+/*********************************************************************
+* SEGGER Microcontroller GmbH *
+* The Embedded Experts *
+**********************************************************************
+* *
+* (c) 1995 - 2019 SEGGER Microcontroller GmbH *
+* *
+* www.segger.com Support: support@segger.com *
+* *
+**********************************************************************
+* *
+* SEGGER RTT * Real Time Transfer for embedded targets *
+* *
+**********************************************************************
+* *
+* All rights reserved. *
+* *
+* SEGGER strongly recommends to not make any changes *
+* to or modify the source code of this software in order to stay *
+* compatible with the RTT protocol and J-Link. *
+* *
+* Redistribution and use in source and binary forms, with or *
+* without modification, are permitted provided that the following *
+* condition is met: *
+* *
+* o Redistributions of source code must retain the above copyright *
+* notice, this condition and the following disclaimer. *
+* *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
+* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
+* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
+* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
+* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
+* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
+* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
+* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
+* DAMAGE. *
+* *
+**********************************************************************
+---------------------------END-OF-HEADER------------------------------
+File : SEGGER_RTT.c
+Purpose : Implementation of SEGGER real-time transfer (RTT) which
+ allows real-time communication on targets which support
+ debugger memory accesses while the CPU is running.
+Revision: $Rev: 17697 $
+
+Additional information:
+ Type "int" is assumed to be 32-bits in size
+ H->T Host to target communication
+ T->H Target to host communication
+
+ RTT channel 0 is always present and reserved for Terminal usage.
+ Name is fixed to "Terminal"
+
+ Effective buffer size: SizeOfBuffer - 1
+
+ WrOff == RdOff: Buffer is empty
+ WrOff == (RdOff - 1): Buffer is full
+ WrOff > RdOff: Free space includes wrap-around
+ WrOff < RdOff: Used space includes wrap-around
+ (WrOff == (SizeOfBuffer - 1)) && (RdOff == 0):
+ Buffer full and wrap-around after next byte
+
+
+----------------------------------------------------------------------
+*/
+
+#include "SEGGER_RTT.h"
+
+#include // for memcpy
+
+/*********************************************************************
+*
+* Configuration, default values
+*
+**********************************************************************
+*/
+
+#ifndef BUFFER_SIZE_UP
+ #define BUFFER_SIZE_UP 1024 // Size of the buffer for terminal output of target, up to host
+#endif
+
+#ifndef BUFFER_SIZE_DOWN
+ #define BUFFER_SIZE_DOWN 16 // Size of the buffer for terminal input to target from host (Usually keyboard input)
+#endif
+
+#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS
+ #define SEGGER_RTT_MAX_NUM_UP_BUFFERS 2 // Number of up-buffers (T->H) available on this target
+#endif
+
+#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS
+ #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 2 // Number of down-buffers (H->T) available on this target
+#endif
+
+#ifndef SEGGER_RTT_BUFFER_SECTION
+ #if defined(SEGGER_RTT_SECTION)
+ #define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION
+ #endif
+#endif
+
+#ifndef SEGGER_RTT_ALIGNMENT
+ #define SEGGER_RTT_ALIGNMENT 0
+#endif
+
+#ifndef SEGGER_RTT_BUFFER_ALIGNMENT
+ #define SEGGER_RTT_BUFFER_ALIGNMENT 0
+#endif
+
+#ifndef SEGGER_RTT_MODE_DEFAULT
+ #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP
+#endif
+
+#ifndef SEGGER_RTT_LOCK
+ #define SEGGER_RTT_LOCK()
+#endif
+
+#ifndef SEGGER_RTT_UNLOCK
+ #define SEGGER_RTT_UNLOCK()
+#endif
+
+#ifndef STRLEN
+ #define STRLEN(a) strlen((a))
+#endif
+
+#ifndef STRCPY
+ #define STRCPY(pDest, pSrc, NumBytes) strcpy((pDest), (pSrc))
+#endif
+
+#ifndef SEGGER_RTT_MEMCPY_USE_BYTELOOP
+ #define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0
+#endif
+
+#ifndef SEGGER_RTT_MEMCPY
+ #ifdef MEMCPY
+ #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) MEMCPY((pDest), (pSrc), (NumBytes))
+ #else
+ #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) memcpy((pDest), (pSrc), (NumBytes))
+ #endif
+#endif
+
+#ifndef MIN
+ #define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef MAX
+ #define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+//
+// For some environments, NULL may not be defined until certain headers are included
+//
+#ifndef NULL
+ #define NULL 0
+#endif
+
+/*********************************************************************
+*
+* Defines, fixed
+*
+**********************************************************************
+*/
+#if (defined __ICCARM__) || (defined __ICCRX__)
+ #define RTT_PRAGMA(P) _Pragma(#P)
+#endif
+
+#if SEGGER_RTT_ALIGNMENT || SEGGER_RTT_BUFFER_ALIGNMENT
+ #if (defined __GNUC__)
+ #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment)))
+ #elif (defined __ICCARM__) || (defined __ICCRX__)
+ #define PRAGMA(A) _Pragma(#A)
+#define SEGGER_RTT_ALIGN(Var, Alignment) RTT_PRAGMA(data_alignment=Alignment) \
+ Var
+ #elif (defined __CC_ARM)
+ #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment)))
+ #else
+ #error "Alignment not supported for this compiler."
+ #endif
+#else
+ #define SEGGER_RTT_ALIGN(Var, Alignment) Var
+#endif
+
+#if defined(SEGGER_RTT_SECTION) || defined (SEGGER_RTT_BUFFER_SECTION)
+ #if (defined __GNUC__)
+ #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section))) Var
+ #elif (defined __ICCARM__) || (defined __ICCRX__)
+#define SEGGER_RTT_PUT_SECTION(Var, Section) RTT_PRAGMA(location=Section) \
+ Var
+ #elif (defined __CC_ARM)
+ #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section), zero_init)) Var
+ #else
+ #error "Section placement not supported for this compiler."
+ #endif
+#else
+ #define SEGGER_RTT_PUT_SECTION(Var, Section) Var
+#endif
+
+
+#if SEGGER_RTT_ALIGNMENT
+ #define SEGGER_RTT_CB_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_ALIGNMENT)
+#else
+ #define SEGGER_RTT_CB_ALIGN(Var) Var
+#endif
+
+#if SEGGER_RTT_BUFFER_ALIGNMENT
+ #define SEGGER_RTT_BUFFER_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_BUFFER_ALIGNMENT)
+#else
+ #define SEGGER_RTT_BUFFER_ALIGN(Var) Var
+#endif
+
+
+#if defined(SEGGER_RTT_SECTION)
+ #define SEGGER_RTT_PUT_CB_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_SECTION)
+#else
+ #define SEGGER_RTT_PUT_CB_SECTION(Var) Var
+#endif
+
+#if defined(SEGGER_RTT_BUFFER_SECTION)
+ #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_BUFFER_SECTION)
+#else
+ #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) Var
+#endif
+
+/*********************************************************************
+*
+* Static const data
+*
+**********************************************************************
+*/
+
+static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+/*********************************************************************
+*
+* Static data
+*
+**********************************************************************
+*/
+//
+// RTT Control Block and allocate buffers for channel 0
+//
+SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT));
+
+SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acUpBuffer [BUFFER_SIZE_UP]));
+SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acDownBuffer[BUFFER_SIZE_DOWN]));
+
+static unsigned char _ActiveTerminal;
+
+/*********************************************************************
+*
+* Static functions
+*
+**********************************************************************
+*/
+
+/*********************************************************************
+*
+* _DoInit()
+*
+* Function description
+* Initializes the control block an buffers.
+* May only be called via INIT() to avoid overriding settings.
+*
+*/
+#define INIT() do { \
+ if (_SEGGER_RTT.acID[0] == '\0') { _DoInit(); } \
+ } while (0)
+static void _DoInit(void) {
+ SEGGER_RTT_CB* p;
+ //
+ // Initialize control block
+ //
+ p = &_SEGGER_RTT;
+ p->MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS;
+ p->MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS;
+ //
+ // Initialize up buffer 0
+ //
+ p->aUp[0].sName = "Terminal";
+ p->aUp[0].pBuffer = _acUpBuffer;
+ p->aUp[0].SizeOfBuffer = sizeof(_acUpBuffer);
+ p->aUp[0].RdOff = 0u;
+ p->aUp[0].WrOff = 0u;
+ p->aUp[0].Flags = SEGGER_RTT_MODE_DEFAULT;
+ //
+ // Initialize down buffer 0
+ //
+ p->aDown[0].sName = "Terminal";
+ p->aDown[0].pBuffer = _acDownBuffer;
+ p->aDown[0].SizeOfBuffer = sizeof(_acDownBuffer);
+ p->aDown[0].RdOff = 0u;
+ p->aDown[0].WrOff = 0u;
+ p->aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT;
+ //
+ // Finish initialization of the control block.
+ // Copy Id string in three steps to make sure "SEGGER RTT" is not found
+ // in initializer memory (usually flash) by J-Link
+ //
+ STRCPY(&p->acID[7], "RTT", 9);
+ STRCPY(&p->acID[0], "SEGGER", 7);
+ p->acID[6] = ' ';
+}
+
+/*********************************************************************
+*
+* _WriteBlocking()
+*
+* Function description
+* Stores a specified number of characters in SEGGER RTT ring buffer
+* and updates the associated write pointer which is periodically
+* read by the host.
+* The caller is responsible for managing the write chunk sizes as
+* _WriteBlocking() will block until all data has been posted successfully.
+*
+* Parameters
+* pRing Ring buffer to post to.
+* pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
+* NumBytes Number of bytes to be stored in the SEGGER RTT control block.
+*
+* Return value
+* >= 0 - Number of bytes written into buffer.
+*/
+static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing, const char* pBuffer, unsigned NumBytes) {
+ unsigned NumBytesToWrite;
+ unsigned NumBytesWritten;
+ unsigned RdOff;
+ unsigned WrOff;
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
+ char* pDst;
+#endif
+ //
+ // Write data to buffer and handle wrap-around if necessary
+ //
+ NumBytesWritten = 0u;
+ WrOff = pRing->WrOff;
+ do {
+ RdOff = pRing->RdOff; // May be changed by host (debug probe) in the meantime
+ if (RdOff > WrOff) {
+ NumBytesToWrite = RdOff - WrOff - 1u;
+ } else {
+ NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u);
+ }
+ NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff)); // Number of bytes that can be written until buffer wrap-around
+ NumBytesToWrite = MIN(NumBytesToWrite, NumBytes);
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
+ pDst = pRing->pBuffer + WrOff;
+ NumBytesWritten += NumBytesToWrite;
+ NumBytes -= NumBytesToWrite;
+ WrOff += NumBytesToWrite;
+ while (NumBytesToWrite--) {
+ *pDst++ = *pBuffer++;
+ };
+#else
+ SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite);
+ NumBytesWritten += NumBytesToWrite;
+ pBuffer += NumBytesToWrite;
+ NumBytes -= NumBytesToWrite;
+ WrOff += NumBytesToWrite;
+#endif
+ if (WrOff == pRing->SizeOfBuffer) {
+ WrOff = 0u;
+ }
+ pRing->WrOff = WrOff;
+ } while (NumBytes);
+ //
+ return NumBytesWritten;
+}
+
+/*********************************************************************
+*
+* _WriteNoCheck()
+*
+* Function description
+* Stores a specified number of characters in SEGGER RTT ring buffer
+* and updates the associated write pointer which is periodically
+* read by the host.
+* It is callers responsibility to make sure data actually fits in buffer.
+*
+* Parameters
+* pRing Ring buffer to post to.
+* pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
+* NumBytes Number of bytes to be stored in the SEGGER RTT control block.
+*
+* Notes
+* (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking
+*/
+static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsigned NumBytes) {
+ unsigned NumBytesAtOnce;
+ unsigned WrOff;
+ unsigned Rem;
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
+ char* pDst;
+#endif
+
+ WrOff = pRing->WrOff;
+ Rem = pRing->SizeOfBuffer - WrOff;
+ if (Rem > NumBytes) {
+ //
+ // All data fits before wrap around
+ //
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
+ pDst = pRing->pBuffer + WrOff;
+ WrOff += NumBytes;
+ while (NumBytes--) {
+ *pDst++ = *pData++;
+ };
+ pRing->WrOff = WrOff;
+#else
+ SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytes);
+ pRing->WrOff = WrOff + NumBytes;
+#endif
+ } else {
+ //
+ // We reach the end of the buffer, so need to wrap around
+ //
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
+ pDst = pRing->pBuffer + WrOff;
+ NumBytesAtOnce = Rem;
+ while (NumBytesAtOnce--) {
+ *pDst++ = *pData++;
+ };
+ pDst = pRing->pBuffer;
+ NumBytesAtOnce = NumBytes - Rem;
+ while (NumBytesAtOnce--) {
+ *pDst++ = *pData++;
+ };
+ pRing->WrOff = NumBytes - Rem;
+#else
+ NumBytesAtOnce = Rem;
+ SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytesAtOnce);
+ NumBytesAtOnce = NumBytes - Rem;
+ SEGGER_RTT_MEMCPY(pRing->pBuffer, pData + Rem, NumBytesAtOnce);
+ pRing->WrOff = NumBytesAtOnce;
+#endif
+ }
+}
+
+/*********************************************************************
+*
+* _PostTerminalSwitch()
+*
+* Function description
+* Switch terminal to the given terminal ID. It is the caller's
+* responsibility to ensure the terminal ID is correct and there is
+* enough space in the buffer for this to complete successfully.
+*
+* Parameters
+* pRing Ring buffer to post to.
+* TerminalId Terminal ID to switch to.
+*/
+static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) {
+ unsigned char ac[2];
+
+ ac[0] = 0xFFu;
+ ac[1] = _aTerminalId[TerminalId]; // Caller made already sure that TerminalId does not exceed our terminal limit
+ _WriteBlocking(pRing, (const char*)ac, 2u);
+}
+
+/*********************************************************************
+*
+* _GetAvailWriteSpace()
+*
+* Function description
+* Returns the number of bytes that can be written to the ring
+* buffer without blocking.
+*
+* Parameters
+* pRing Ring buffer to check.
+*
+* Return value
+* Number of bytes that are free in the buffer.
+*/
+static unsigned _GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP* pRing) {
+ unsigned RdOff;
+ unsigned WrOff;
+ unsigned r;
+ //
+ // Avoid warnings regarding volatile access order. It's not a problem
+ // in this case, but dampen compiler enthusiasm.
+ //
+ RdOff = pRing->RdOff;
+ WrOff = pRing->WrOff;
+ if (RdOff <= WrOff) {
+ r = pRing->SizeOfBuffer - 1u - WrOff + RdOff;
+ } else {
+ r = RdOff - WrOff - 1u;
+ }
+ return r;
+}
+
+/*********************************************************************
+*
+* Public code
+*
+**********************************************************************
+*/
+/*********************************************************************
+*
+* SEGGER_RTT_ReadUpBufferNoLock()
+*
+* Function description
+* Reads characters from SEGGER real-time-terminal control block
+* which have been previously stored by the application.
+* Do not lock against interrupts and multiple access.
+* Used to do the same operation that J-Link does, to transfer
+* RTT data via other channels, such as TCP/IP or UART.
+*
+* Parameters
+* BufferIndex Index of Up-buffer to be used.
+* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-up-buffer to.
+* BufferSize Size of the target application buffer.
+*
+* Return value
+* Number of bytes that have been read.
+*
+* Additional information
+* This function must not be called when J-Link might also do RTT.
+*/
+unsigned SEGGER_RTT_ReadUpBufferNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) {
+ unsigned NumBytesRem;
+ unsigned NumBytesRead;
+ unsigned RdOff;
+ unsigned WrOff;
+ unsigned char* pBuffer;
+ SEGGER_RTT_BUFFER_UP* pRing;
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
+ const char* pSrc;
+#endif
+ //
+ INIT();
+ pRing = &_SEGGER_RTT.aUp[BufferIndex];
+ pBuffer = (unsigned char*)pData;
+ RdOff = pRing->RdOff;
+ WrOff = pRing->WrOff;
+ NumBytesRead = 0u;
+ //
+ // Read from current read position to wrap-around of buffer, first
+ //
+ if (RdOff > WrOff) {
+ NumBytesRem = pRing->SizeOfBuffer - RdOff;
+ NumBytesRem = MIN(NumBytesRem, BufferSize);
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
+ pSrc = pRing->pBuffer + RdOff;
+ NumBytesRead += NumBytesRem;
+ BufferSize -= NumBytesRem;
+ RdOff += NumBytesRem;
+ while (NumBytesRem--) {
+ *pBuffer++ = *pSrc++;
+ };
+#else
+ SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem);
+ NumBytesRead += NumBytesRem;
+ pBuffer += NumBytesRem;
+ BufferSize -= NumBytesRem;
+ RdOff += NumBytesRem;
+#endif
+ //
+ // Handle wrap-around of buffer
+ //
+ if (RdOff == pRing->SizeOfBuffer) {
+ RdOff = 0u;
+ }
+ }
+ //
+ // Read remaining items of buffer
+ //
+ NumBytesRem = WrOff - RdOff;
+ NumBytesRem = MIN(NumBytesRem, BufferSize);
+ if (NumBytesRem > 0u) {
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
+ pSrc = pRing->pBuffer + RdOff;
+ NumBytesRead += NumBytesRem;
+ BufferSize -= NumBytesRem;
+ RdOff += NumBytesRem;
+ while (NumBytesRem--) {
+ *pBuffer++ = *pSrc++;
+ };
+#else
+ SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem);
+ NumBytesRead += NumBytesRem;
+ pBuffer += NumBytesRem;
+ BufferSize -= NumBytesRem;
+ RdOff += NumBytesRem;
+#endif
+ }
+ //
+ // Update read offset of buffer
+ //
+ if (NumBytesRead) {
+ pRing->RdOff = RdOff;
+ }
+ //
+ return NumBytesRead;
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_ReadNoLock()
+*
+* Function description
+* Reads characters from SEGGER real-time-terminal control block
+* which have been previously stored by the host.
+* Do not lock against interrupts and multiple access.
+*
+* Parameters
+* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal").
+* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to.
+* BufferSize Size of the target application buffer.
+*
+* Return value
+* Number of bytes that have been read.
+*/
+unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) {
+ unsigned NumBytesRem;
+ unsigned NumBytesRead;
+ unsigned RdOff;
+ unsigned WrOff;
+ unsigned char* pBuffer;
+ SEGGER_RTT_BUFFER_DOWN* pRing;
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
+ const char* pSrc;
+#endif
+ //
+ INIT();
+ pRing = &_SEGGER_RTT.aDown[BufferIndex];
+ pBuffer = (unsigned char*)pData;
+ RdOff = pRing->RdOff;
+ WrOff = pRing->WrOff;
+ NumBytesRead = 0u;
+ //
+ // Read from current read position to wrap-around of buffer, first
+ //
+ if (RdOff > WrOff) {
+ NumBytesRem = pRing->SizeOfBuffer - RdOff;
+ NumBytesRem = MIN(NumBytesRem, BufferSize);
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
+ pSrc = pRing->pBuffer + RdOff;
+ NumBytesRead += NumBytesRem;
+ BufferSize -= NumBytesRem;
+ RdOff += NumBytesRem;
+ while (NumBytesRem--) {
+ *pBuffer++ = *pSrc++;
+ };
+#else
+ SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem);
+ NumBytesRead += NumBytesRem;
+ pBuffer += NumBytesRem;
+ BufferSize -= NumBytesRem;
+ RdOff += NumBytesRem;
+#endif
+ //
+ // Handle wrap-around of buffer
+ //
+ if (RdOff == pRing->SizeOfBuffer) {
+ RdOff = 0u;
+ }
+ }
+ //
+ // Read remaining items of buffer
+ //
+ NumBytesRem = WrOff - RdOff;
+ NumBytesRem = MIN(NumBytesRem, BufferSize);
+ if (NumBytesRem > 0u) {
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
+ pSrc = pRing->pBuffer + RdOff;
+ NumBytesRead += NumBytesRem;
+ BufferSize -= NumBytesRem;
+ RdOff += NumBytesRem;
+ while (NumBytesRem--) {
+ *pBuffer++ = *pSrc++;
+ };
+#else
+ SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem);
+ NumBytesRead += NumBytesRem;
+ pBuffer += NumBytesRem;
+ BufferSize -= NumBytesRem;
+ RdOff += NumBytesRem;
+#endif
+ }
+ if (NumBytesRead) {
+ pRing->RdOff = RdOff;
+ }
+ //
+ return NumBytesRead;
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_ReadUpBuffer
+*
+* Function description
+* Reads characters from SEGGER real-time-terminal control block
+* which have been previously stored by the application.
+* Used to do the same operation that J-Link does, to transfer
+* RTT data via other channels, such as TCP/IP or UART.
+*
+* Parameters
+* BufferIndex Index of Up-buffer to be used.
+* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-up-buffer to.
+* BufferSize Size of the target application buffer.
+*
+* Return value
+* Number of bytes that have been read.
+*
+* Additional information
+* This function must not be called when J-Link might also do RTT.
+* This function locks against all other RTT operations. I.e. during
+* the read operation, writing is also locked.
+* If only one consumer reads from the up buffer,
+* call sEGGER_RTT_ReadUpBufferNoLock() instead.
+*/
+unsigned SEGGER_RTT_ReadUpBuffer(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) {
+ unsigned NumBytesRead;
+ //
+ SEGGER_RTT_LOCK();
+ //
+ // Call the non-locking read function
+ //
+ NumBytesRead = SEGGER_RTT_ReadUpBufferNoLock(BufferIndex, pBuffer, BufferSize);
+ //
+ // Finish up.
+ //
+ SEGGER_RTT_UNLOCK();
+ //
+ return NumBytesRead;
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_Read
+*
+* Function description
+* Reads characters from SEGGER real-time-terminal control block
+* which have been previously stored by the host.
+*
+* Parameters
+* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal").
+* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to.
+* BufferSize Size of the target application buffer.
+*
+* Return value
+* Number of bytes that have been read.
+*/
+unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) {
+ unsigned NumBytesRead;
+ //
+ SEGGER_RTT_LOCK();
+ //
+ // Call the non-locking read function
+ //
+ NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize);
+ //
+ // Finish up.
+ //
+ SEGGER_RTT_UNLOCK();
+ //
+ return NumBytesRead;
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_WriteWithOverwriteNoLock
+*
+* Function description
+* Stores a specified number of characters in SEGGER RTT
+* control block.
+* SEGGER_RTT_WriteWithOverwriteNoLock does not lock the application
+* and overwrites data if the data does not fit into the buffer.
+*
+* Parameters
+* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
+* pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
+* NumBytes Number of bytes to be stored in the SEGGER RTT control block.
+*
+* Notes
+* (1) If there is not enough space in the "Up"-buffer, data is overwritten.
+* (2) For performance reasons this function does not call Init()
+* and may only be called after RTT has been initialized.
+* Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
+* (3) Do not use SEGGER_RTT_WriteWithOverwriteNoLock if a J-Link
+* connection reads RTT data.
+*/
+void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
+ const char* pData;
+ SEGGER_RTT_BUFFER_UP* pRing;
+ unsigned Avail;
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
+ char* pDst;
+#endif
+
+ pData = (const char *)pBuffer;
+ //
+ // Get "to-host" ring buffer and copy some elements into local variables.
+ //
+ pRing = &_SEGGER_RTT.aUp[BufferIndex];
+ //
+ // Check if we will overwrite data and need to adjust the RdOff.
+ //
+ if (pRing->WrOff == pRing->RdOff) {
+ Avail = pRing->SizeOfBuffer - 1u;
+ } else if ( pRing->WrOff < pRing->RdOff) {
+ Avail = pRing->RdOff - pRing->WrOff - 1u;
+ } else {
+ Avail = pRing->RdOff - pRing->WrOff - 1u + pRing->SizeOfBuffer;
+ }
+ if (NumBytes > Avail) {
+ pRing->RdOff += (NumBytes - Avail);
+ while (pRing->RdOff >= pRing->SizeOfBuffer) {
+ pRing->RdOff -= pRing->SizeOfBuffer;
+ }
+ }
+ //
+ // Write all data, no need to check the RdOff, but possibly handle multiple wrap-arounds
+ //
+ Avail = pRing->SizeOfBuffer - pRing->WrOff;
+ do {
+ if (Avail > NumBytes) {
+ //
+ // Last round
+ //
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
+ pDst = pRing->pBuffer + pRing->WrOff;
+ Avail = NumBytes;
+ while (NumBytes--) {
+ *pDst++ = *pData++;
+ };
+ pRing->WrOff += Avail;
+#else
+ SEGGER_RTT_MEMCPY(pRing->pBuffer + pRing->WrOff, pData, NumBytes);
+ pRing->WrOff += NumBytes;
+#endif
+ break;
+ } else {
+ //
+ // Wrap-around necessary, write until wrap-around and reset WrOff
+ //
+#if SEGGER_RTT_MEMCPY_USE_BYTELOOP
+ pDst = pRing->pBuffer + pRing->WrOff;
+ NumBytes -= Avail;
+ while (Avail--) {
+ *pDst++ = *pData++;
+ };
+ pRing->WrOff = 0;
+#else
+ SEGGER_RTT_MEMCPY(pRing->pBuffer + pRing->WrOff, pData, Avail);
+ pData += Avail;
+ pRing->WrOff = 0;
+ NumBytes -= Avail;
+#endif
+ Avail = (pRing->SizeOfBuffer - 1);
+ }
+ } while (NumBytes);
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_WriteSkipNoLock
+*
+* Function description
+* Stores a specified number of characters in SEGGER RTT
+* control block which is then read by the host.
+* SEGGER_RTT_WriteSkipNoLock does not lock the application and
+* skips all data, if the data does not fit into the buffer.
+*
+* Parameters
+* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
+* pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
+* NumBytes Number of bytes to be stored in the SEGGER RTT control block.
+* MUST be > 0!!!
+* This is done for performance reasons, so no initial check has do be done.
+*
+* Return value
+* 1: Data has been copied
+* 0: No space, data has not been copied
+*
+* Notes
+* (1) If there is not enough space in the "Up"-buffer, all data is dropped.
+* (2) For performance reasons this function does not call Init()
+* and may only be called after RTT has been initialized.
+* Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
+*/
+#if (RTT_USE_ASM == 0)
+unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
+ const char* pData;
+ SEGGER_RTT_BUFFER_UP* pRing;
+ unsigned Avail;
+ unsigned RdOff;
+ unsigned WrOff;
+ unsigned Rem;
+ //
+ // Cases:
+ // 1) RdOff <= WrOff => Space until wrap-around is sufficient
+ // 2) RdOff <= WrOff => Space after wrap-around needed (copy in 2 chunks)
+ // 3) RdOff < WrOff => No space in buf
+ // 4) RdOff > WrOff => Space is sufficient
+ // 5) RdOff > WrOff => No space in buf
+ //
+ // 1) is the most common case for large buffers and assuming that J-Link reads the data fast enough
+ //
+ pData = (const char *)pBuffer;
+ pRing = &_SEGGER_RTT.aUp[BufferIndex];
+ RdOff = pRing->RdOff;
+ WrOff = pRing->WrOff;
+ if (RdOff <= WrOff) { // Case 1), 2) or 3)
+ Avail = pRing->SizeOfBuffer - WrOff - 1u; // Space until wrap-around (assume 1 byte not usable for case that RdOff == 0)
+ if (Avail >= NumBytes) { // Case 1)?
+CopyStraight:
+ memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
+ pRing->WrOff = WrOff + NumBytes;
+ return 1;
+ }
+ Avail += RdOff; // Space incl. wrap-around
+ if (Avail >= NumBytes) { // Case 2? => If not, we have case 3) (does not fit)
+ Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer
+ memcpy(pRing->pBuffer + WrOff, pData, Rem); // Copy 1st chunk
+ NumBytes -= Rem;
+ //
+ // Special case: First check that assumed RdOff == 0 calculated that last element before wrap-around could not be used
+ // But 2nd check (considering space until wrap-around and until RdOff) revealed that RdOff is not 0, so we can use the last element
+ // In this case, we may use a copy straight until buffer end anyway without needing to copy 2 chunks
+ // Therefore, check if 2nd memcpy is necessary at all
+ //
+ if (NumBytes) {
+ memcpy(pRing->pBuffer, pData + Rem, NumBytes);
+ }
+ pRing->WrOff = NumBytes;
+ return 1;
+ }
+ } else { // Potential case 4)
+ Avail = RdOff - WrOff - 1u;
+ if (Avail >= NumBytes) { // Case 4)? => If not, we have case 5) (does not fit)
+ goto CopyStraight;
+ }
+ }
+ return 0; // No space in buffer
+}
+#endif
+
+/*********************************************************************
+*
+* SEGGER_RTT_WriteDownBufferNoLock
+*
+* Function description
+* Stores a specified number of characters in SEGGER RTT
+* control block inside a buffer.
+* SEGGER_RTT_WriteDownBufferNoLock does not lock the application.
+* Used to do the same operation that J-Link does, to transfer
+* RTT data from other channels, such as TCP/IP or UART.
+*
+* Parameters
+* BufferIndex Index of "Down"-buffer to be used.
+* pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
+* NumBytes Number of bytes to be stored in the SEGGER RTT control block.
+*
+* Return value
+* Number of bytes which have been stored in the "Down"-buffer.
+*
+* Notes
+* (1) Data is stored according to buffer flags.
+* (2) For performance reasons this function does not call Init()
+* and may only be called after RTT has been initialized.
+* Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
+*
+* Additional information
+* This function must not be called when J-Link might also do RTT.
+*/
+unsigned SEGGER_RTT_WriteDownBufferNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
+ unsigned Status;
+ unsigned Avail;
+ const char* pData;
+ SEGGER_RTT_BUFFER_UP* pRing;
+
+ pData = (const char *)pBuffer;
+ //
+ // Get "to-target" ring buffer.
+ // It is save to cast that to a "to-host" buffer. Up and Down buffer differ in volatility of offsets that might be modified by J-Link.
+ //
+ pRing = (SEGGER_RTT_BUFFER_UP*)&_SEGGER_RTT.aDown[BufferIndex];
+ //
+ // How we output depends upon the mode...
+ //
+ switch (pRing->Flags) {
+ case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
+ //
+ // If we are in skip mode and there is no space for the whole
+ // of this output, don't bother.
+ //
+ Avail = _GetAvailWriteSpace(pRing);
+ if (Avail < NumBytes) {
+ Status = 0u;
+ } else {
+ Status = NumBytes;
+ _WriteNoCheck(pRing, pData, NumBytes);
+ }
+ break;
+ case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
+ //
+ // If we are in trim mode, trim to what we can output without blocking.
+ //
+ Avail = _GetAvailWriteSpace(pRing);
+ Status = Avail < NumBytes ? Avail : NumBytes;
+ _WriteNoCheck(pRing, pData, Status);
+ break;
+ case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
+ //
+ // If we are in blocking mode, output everything.
+ //
+ Status = _WriteBlocking(pRing, pData, NumBytes);
+ break;
+ default:
+ Status = 0u;
+ break;
+ }
+ //
+ // Finish up.
+ //
+ return Status;
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_WriteNoLock
+*
+* Function description
+* Stores a specified number of characters in SEGGER RTT
+* control block which is then read by the host.
+* SEGGER_RTT_WriteNoLock does not lock the application.
+*
+* Parameters
+* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
+* pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
+* NumBytes Number of bytes to be stored in the SEGGER RTT control block.
+*
+* Return value
+* Number of bytes which have been stored in the "Up"-buffer.
+*
+* Notes
+* (1) Data is stored according to buffer flags.
+* (2) For performance reasons this function does not call Init()
+* and may only be called after RTT has been initialized.
+* Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
+*/
+unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
+ unsigned Status;
+ unsigned Avail;
+ const char* pData;
+ SEGGER_RTT_BUFFER_UP* pRing;
+
+ pData = (const char *)pBuffer;
+ //
+ // Get "to-host" ring buffer.
+ //
+ pRing = &_SEGGER_RTT.aUp[BufferIndex];
+ //
+ // How we output depends upon the mode...
+ //
+ switch (pRing->Flags) {
+ case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
+ //
+ // If we are in skip mode and there is no space for the whole
+ // of this output, don't bother.
+ //
+ Avail = _GetAvailWriteSpace(pRing);
+ if (Avail < NumBytes) {
+ Status = 0u;
+ } else {
+ Status = NumBytes;
+ _WriteNoCheck(pRing, pData, NumBytes);
+ }
+ break;
+ case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
+ //
+ // If we are in trim mode, trim to what we can output without blocking.
+ //
+ Avail = _GetAvailWriteSpace(pRing);
+ Status = Avail < NumBytes ? Avail : NumBytes;
+ _WriteNoCheck(pRing, pData, Status);
+ break;
+ case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
+ //
+ // If we are in blocking mode, output everything.
+ //
+ Status = _WriteBlocking(pRing, pData, NumBytes);
+ break;
+ default:
+ Status = 0u;
+ break;
+ }
+ //
+ // Finish up.
+ //
+ return Status;
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_WriteDownBuffer
+*
+* Function description
+* Stores a specified number of characters in SEGGER RTT control block in a buffer.
+*
+* Parameters
+* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
+* pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
+* NumBytes Number of bytes to be stored in the SEGGER RTT control block.
+*
+* Return value
+* Number of bytes which have been stored in the "Down"-buffer.
+*
+* Notes
+* (1) Data is stored according to buffer flags.
+*
+* Additional information
+* This function must not be called when J-Link might also do RTT.
+* This function locks against all other RTT operations. I.e. during
+* the write operation, writing from the application is also locked.
+* If only one consumer writes to the down buffer,
+* call SEGGER_RTT_WriteDownBufferNoLock() instead.
+*/
+unsigned SEGGER_RTT_WriteDownBuffer(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
+ unsigned Status;
+ //
+ INIT();
+ SEGGER_RTT_LOCK();
+ //
+ // Call the non-locking write function
+ //
+ Status = SEGGER_RTT_WriteDownBufferNoLock(BufferIndex, pBuffer, NumBytes);
+ //
+ // Finish up.
+ //
+ SEGGER_RTT_UNLOCK();
+ //
+ return Status;
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_Write
+*
+* Function description
+* Stores a specified number of characters in SEGGER RTT
+* control block which is then read by the host.
+*
+* Parameters
+* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
+* pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
+* NumBytes Number of bytes to be stored in the SEGGER RTT control block.
+*
+* Return value
+* Number of bytes which have been stored in the "Up"-buffer.
+*
+* Notes
+* (1) Data is stored according to buffer flags.
+*/
+unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
+ unsigned Status;
+ //
+ INIT();
+ SEGGER_RTT_LOCK();
+ //
+ // Call the non-locking write function
+ //
+ Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes);
+ //
+ // Finish up.
+ //
+ SEGGER_RTT_UNLOCK();
+ //
+ return Status;
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_WriteString
+*
+* Function description
+* Stores string in SEGGER RTT control block.
+* This data is read by the host.
+*
+* Parameters
+* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
+* s Pointer to string.
+*
+* Return value
+* Number of bytes which have been stored in the "Up"-buffer.
+*
+* Notes
+* (1) Data is stored according to buffer flags.
+* (2) String passed to this function has to be \0 terminated
+* (3) \0 termination character is *not* stored in RTT buffer
+*/
+unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) {
+ unsigned Len;
+
+ Len = STRLEN(s);
+ return SEGGER_RTT_Write(BufferIndex, s, Len);
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_PutCharSkipNoLock
+*
+* Function description
+* Stores a single character/byte in SEGGER RTT buffer.
+* SEGGER_RTT_PutCharSkipNoLock does not lock the application and
+* skips the byte, if it does not fit into the buffer.
+*
+* Parameters
+* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
+* c Byte to be stored.
+*
+* Return value
+* Number of bytes which have been stored in the "Up"-buffer.
+*
+* Notes
+* (1) If there is not enough space in the "Up"-buffer, the character is dropped.
+* (2) For performance reasons this function does not call Init()
+* and may only be called after RTT has been initialized.
+* Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
+*/
+
+unsigned SEGGER_RTT_PutCharSkipNoLock(unsigned BufferIndex, char c) {
+ SEGGER_RTT_BUFFER_UP* pRing;
+ unsigned WrOff;
+ unsigned Status;
+ //
+ // Get "to-host" ring buffer.
+ //
+ pRing = &_SEGGER_RTT.aUp[BufferIndex];
+ //
+ // Get write position and handle wrap-around if necessary
+ //
+ WrOff = pRing->WrOff + 1;
+ if (WrOff == pRing->SizeOfBuffer) {
+ WrOff = 0;
+ }
+ //
+ // Output byte if free space is available
+ //
+ if (WrOff != pRing->RdOff) {
+ pRing->pBuffer[pRing->WrOff] = c;
+ pRing->WrOff = WrOff;
+ Status = 1;
+ } else {
+ Status = 0;
+ }
+ //
+ return Status;
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_PutCharSkip
+*
+* Function description
+* Stores a single character/byte in SEGGER RTT buffer.
+*
+* Parameters
+* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
+* c Byte to be stored.
+*
+* Return value
+* Number of bytes which have been stored in the "Up"-buffer.
+*
+* Notes
+* (1) If there is not enough space in the "Up"-buffer, the character is dropped.
+*/
+
+unsigned SEGGER_RTT_PutCharSkip(unsigned BufferIndex, char c) {
+ SEGGER_RTT_BUFFER_UP* pRing;
+ unsigned WrOff;
+ unsigned Status;
+ //
+ // Prepare
+ //
+ INIT();
+ SEGGER_RTT_LOCK();
+ //
+ // Get "to-host" ring buffer.
+ //
+ pRing = &_SEGGER_RTT.aUp[BufferIndex];
+ //
+ // Get write position and handle wrap-around if necessary
+ //
+ WrOff = pRing->WrOff + 1;
+ if (WrOff == pRing->SizeOfBuffer) {
+ WrOff = 0;
+ }
+ //
+ // Output byte if free space is available
+ //
+ if (WrOff != pRing->RdOff) {
+ pRing->pBuffer[pRing->WrOff] = c;
+ pRing->WrOff = WrOff;
+ Status = 1;
+ } else {
+ Status = 0;
+ }
+ //
+ // Finish up.
+ //
+ SEGGER_RTT_UNLOCK();
+ //
+ return Status;
+}
+
+ /*********************************************************************
+*
+* SEGGER_RTT_PutChar
+*
+* Function description
+* Stores a single character/byte in SEGGER RTT buffer.
+*
+* Parameters
+* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
+* c Byte to be stored.
+*
+* Return value
+* Number of bytes which have been stored in the "Up"-buffer.
+*
+* Notes
+* (1) Data is stored according to buffer flags.
+*/
+
+unsigned SEGGER_RTT_PutChar(unsigned BufferIndex, char c) {
+ SEGGER_RTT_BUFFER_UP* pRing;
+ unsigned WrOff;
+ unsigned Status;
+ //
+ // Prepare
+ //
+ INIT();
+ SEGGER_RTT_LOCK();
+ //
+ // Get "to-host" ring buffer.
+ //
+ pRing = &_SEGGER_RTT.aUp[BufferIndex];
+ //
+ // Get write position and handle wrap-around if necessary
+ //
+ WrOff = pRing->WrOff + 1;
+ if (WrOff == pRing->SizeOfBuffer) {
+ WrOff = 0;
+ }
+ //
+ // Wait for free space if mode is set to blocking
+ //
+ if (pRing->Flags == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) {
+ while (WrOff == pRing->RdOff) {
+ ;
+ }
+ }
+ //
+ // Output byte if free space is available
+ //
+ if (WrOff != pRing->RdOff) {
+ pRing->pBuffer[pRing->WrOff] = c;
+ pRing->WrOff = WrOff;
+ Status = 1;
+ } else {
+ Status = 0;
+ }
+ //
+ // Finish up.
+ //
+ SEGGER_RTT_UNLOCK();
+ //
+ return Status;
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_GetKey
+*
+* Function description
+* Reads one character from the SEGGER RTT buffer.
+* Host has previously stored data there.
+*
+* Return value
+* < 0 - No character available (buffer empty).
+* >= 0 - Character which has been read. (Possible values: 0 - 255)
+*
+* Notes
+* (1) This function is only specified for accesses to RTT buffer 0.
+*/
+int SEGGER_RTT_GetKey(void) {
+ char c;
+ int r;
+
+ r = (int)SEGGER_RTT_Read(0u, &c, 1u);
+ if (r == 1) {
+ r = (int)(unsigned char)c;
+ } else {
+ r = -1;
+ }
+ return r;
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_WaitKey
+*
+* Function description
+* Waits until at least one character is avaible in the SEGGER RTT buffer.
+* Once a character is available, it is read and this function returns.
+*
+* Return value
+* >=0 - Character which has been read.
+*
+* Notes
+* (1) This function is only specified for accesses to RTT buffer 0
+* (2) This function is blocking if no character is present in RTT buffer
+*/
+int SEGGER_RTT_WaitKey(void) {
+ int r;
+
+ do {
+ r = SEGGER_RTT_GetKey();
+ } while (r < 0);
+ return r;
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_HasKey
+*
+* Function description
+* Checks if at least one character for reading is available in the SEGGER RTT buffer.
+*
+* Return value
+* == 0 - No characters are available to read.
+* == 1 - At least one character is available.
+*
+* Notes
+* (1) This function is only specified for accesses to RTT buffer 0
+*/
+int SEGGER_RTT_HasKey(void) {
+ unsigned RdOff;
+ int r;
+
+ INIT();
+ RdOff = _SEGGER_RTT.aDown[0].RdOff;
+ if (RdOff != _SEGGER_RTT.aDown[0].WrOff) {
+ r = 1;
+ } else {
+ r = 0;
+ }
+ return r;
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_HasData
+*
+* Function description
+* Check if there is data from the host in the given buffer.
+*
+* Return value:
+* ==0: No data
+* !=0: Data in buffer
+*
+*/
+unsigned SEGGER_RTT_HasData(unsigned BufferIndex) {
+ SEGGER_RTT_BUFFER_DOWN* pRing;
+ unsigned v;
+
+ pRing = &_SEGGER_RTT.aDown[BufferIndex];
+ v = pRing->WrOff;
+ return v - pRing->RdOff;
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_HasDataUp
+*
+* Function description
+* Check if there is data remaining to be sent in the given buffer.
+*
+* Return value:
+* ==0: No data
+* !=0: Data in buffer
+*
+*/
+unsigned SEGGER_RTT_HasDataUp(unsigned BufferIndex) {
+ SEGGER_RTT_BUFFER_UP* pRing;
+ unsigned v;
+
+ pRing = &_SEGGER_RTT.aUp[BufferIndex];
+ v = pRing->RdOff;
+ return pRing->WrOff - v;
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_AllocDownBuffer
+*
+* Function description
+* Run-time configuration of the next down-buffer (H->T).
+* The next buffer, which is not used yet is configured.
+* This includes: Buffer address, size, name, flags, ...
+*
+* Parameters
+* sName Pointer to a constant name string.
+* pBuffer Pointer to a buffer to be used.
+* BufferSize Size of the buffer.
+* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message).
+*
+* Return value
+* >= 0 - O.K. Buffer Index
+* < 0 - Error
+*/
+int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
+ int BufferIndex;
+
+ INIT();
+ SEGGER_RTT_LOCK();
+ BufferIndex = 0;
+ do {
+ if (_SEGGER_RTT.aDown[BufferIndex].pBuffer == NULL) {
+ break;
+ }
+ BufferIndex++;
+ } while (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers);
+ if (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers) {
+ _SEGGER_RTT.aDown[BufferIndex].sName = sName;
+ _SEGGER_RTT.aDown[BufferIndex].pBuffer = (char*)pBuffer;
+ _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
+ _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u;
+ _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u;
+ _SEGGER_RTT.aDown[BufferIndex].Flags = Flags;
+ } else {
+ BufferIndex = -1;
+ }
+ SEGGER_RTT_UNLOCK();
+ return BufferIndex;
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_AllocUpBuffer
+*
+* Function description
+* Run-time configuration of the next up-buffer (T->H).
+* The next buffer, which is not used yet is configured.
+* This includes: Buffer address, size, name, flags, ...
+*
+* Parameters
+* sName Pointer to a constant name string.
+* pBuffer Pointer to a buffer to be used.
+* BufferSize Size of the buffer.
+* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message).
+*
+* Return value
+* >= 0 - O.K. Buffer Index
+* < 0 - Error
+*/
+int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
+ int BufferIndex;
+
+ INIT();
+ SEGGER_RTT_LOCK();
+ BufferIndex = 0;
+ do {
+ if (_SEGGER_RTT.aUp[BufferIndex].pBuffer == NULL) {
+ break;
+ }
+ BufferIndex++;
+ } while (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers);
+ if (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers) {
+ _SEGGER_RTT.aUp[BufferIndex].sName = sName;
+ _SEGGER_RTT.aUp[BufferIndex].pBuffer = (char*)pBuffer;
+ _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
+ _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u;
+ _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u;
+ _SEGGER_RTT.aUp[BufferIndex].Flags = Flags;
+ } else {
+ BufferIndex = -1;
+ }
+ SEGGER_RTT_UNLOCK();
+ return BufferIndex;
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_ConfigUpBuffer
+*
+* Function description
+* Run-time configuration of a specific up-buffer (T->H).
+* Buffer to be configured is specified by index.
+* This includes: Buffer address, size, name, flags, ...
+*
+* Parameters
+* BufferIndex Index of the buffer to configure.
+* sName Pointer to a constant name string.
+* pBuffer Pointer to a buffer to be used.
+* BufferSize Size of the buffer.
+* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message).
+*
+* Return value
+* >= 0 - O.K.
+* < 0 - Error
+*
+* Additional information
+* Buffer 0 is configured on compile-time.
+* May only be called once per buffer.
+* Buffer name and flags can be reconfigured using the appropriate functions.
+*/
+int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
+ int r;
+
+ INIT();
+ if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
+ SEGGER_RTT_LOCK();
+ if (BufferIndex > 0u) {
+ _SEGGER_RTT.aUp[BufferIndex].sName = sName;
+ _SEGGER_RTT.aUp[BufferIndex].pBuffer = (char*)pBuffer;
+ _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
+ _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u;
+ _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u;
+ }
+ _SEGGER_RTT.aUp[BufferIndex].Flags = Flags;
+ SEGGER_RTT_UNLOCK();
+ r = 0;
+ } else {
+ r = -1;
+ }
+ return r;
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_ConfigDownBuffer
+*
+* Function description
+* Run-time configuration of a specific down-buffer (H->T).
+* Buffer to be configured is specified by index.
+* This includes: Buffer address, size, name, flags, ...
+*
+* Parameters
+* BufferIndex Index of the buffer to configure.
+* sName Pointer to a constant name string.
+* pBuffer Pointer to a buffer to be used.
+* BufferSize Size of the buffer.
+* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message).
+*
+* Return value
+* >= 0 O.K.
+* < 0 Error
+*
+* Additional information
+* Buffer 0 is configured on compile-time.
+* May only be called once per buffer.
+* Buffer name and flags can be reconfigured using the appropriate functions.
+*/
+int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
+ int r;
+
+ INIT();
+ if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
+ SEGGER_RTT_LOCK();
+ if (BufferIndex > 0u) {
+ _SEGGER_RTT.aDown[BufferIndex].sName = sName;
+ _SEGGER_RTT.aDown[BufferIndex].pBuffer = (char*)pBuffer;
+ _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize;
+ _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u;
+ _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u;
+ }
+ _SEGGER_RTT.aDown[BufferIndex].Flags = Flags;
+ SEGGER_RTT_UNLOCK();
+ r = 0;
+ } else {
+ r = -1;
+ }
+ return r;
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_SetNameUpBuffer
+*
+* Function description
+* Run-time configuration of a specific up-buffer name (T->H).
+* Buffer to be configured is specified by index.
+*
+* Parameters
+* BufferIndex Index of the buffer to renamed.
+* sName Pointer to a constant name string.
+*
+* Return value
+* >= 0 O.K.
+* < 0 Error
+*/
+int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) {
+ int r;
+
+ INIT();
+ if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
+ SEGGER_RTT_LOCK();
+ _SEGGER_RTT.aUp[BufferIndex].sName = sName;
+ SEGGER_RTT_UNLOCK();
+ r = 0;
+ } else {
+ r = -1;
+ }
+ return r;
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_SetNameDownBuffer
+*
+* Function description
+* Run-time configuration of a specific Down-buffer name (T->H).
+* Buffer to be configured is specified by index.
+*
+* Parameters
+* BufferIndex Index of the buffer to renamed.
+* sName Pointer to a constant name string.
+*
+* Return value
+* >= 0 O.K.
+* < 0 Error
+*/
+int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) {
+ int r;
+
+ INIT();
+ if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
+ SEGGER_RTT_LOCK();
+ _SEGGER_RTT.aDown[BufferIndex].sName = sName;
+ SEGGER_RTT_UNLOCK();
+ r = 0;
+ } else {
+ r = -1;
+ }
+ return r;
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_SetFlagsUpBuffer
+*
+* Function description
+* Run-time configuration of specific up-buffer flags (T->H).
+* Buffer to be configured is specified by index.
+*
+* Parameters
+* BufferIndex Index of the buffer.
+* Flags Flags to set for the buffer.
+*
+* Return value
+* >= 0 O.K.
+* < 0 Error
+*/
+int SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex, unsigned Flags) {
+ int r;
+
+ INIT();
+ if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
+ SEGGER_RTT_LOCK();
+ _SEGGER_RTT.aUp[BufferIndex].Flags = Flags;
+ SEGGER_RTT_UNLOCK();
+ r = 0;
+ } else {
+ r = -1;
+ }
+ return r;
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_SetFlagsDownBuffer
+*
+* Function description
+* Run-time configuration of specific Down-buffer flags (T->H).
+* Buffer to be configured is specified by index.
+*
+* Parameters
+* BufferIndex Index of the buffer to renamed.
+* Flags Flags to set for the buffer.
+*
+* Return value
+* >= 0 O.K.
+* < 0 Error
+*/
+int SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex, unsigned Flags) {
+ int r;
+
+ INIT();
+ if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) {
+ SEGGER_RTT_LOCK();
+ _SEGGER_RTT.aDown[BufferIndex].Flags = Flags;
+ SEGGER_RTT_UNLOCK();
+ r = 0;
+ } else {
+ r = -1;
+ }
+ return r;
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_Init
+*
+* Function description
+* Initializes the RTT Control Block.
+* Should be used in RAM targets, at start of the application.
+*
+*/
+void SEGGER_RTT_Init (void) {
+ _DoInit();
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_SetTerminal
+*
+* Function description
+* Sets the terminal to be used for output on channel 0.
+*
+* Parameters
+* TerminalId Index of the terminal.
+*
+* Return value
+* >= 0 O.K.
+* < 0 Error (e.g. if RTT is configured for non-blocking mode and there was no space in the buffer to set the new terminal Id)
+*/
+int SEGGER_RTT_SetTerminal (unsigned char TerminalId) {
+ unsigned char ac[2];
+ SEGGER_RTT_BUFFER_UP* pRing;
+ unsigned Avail;
+ int r;
+ //
+ INIT();
+ //
+ r = 0;
+ ac[0] = 0xFFu;
+ if (TerminalId < sizeof(_aTerminalId)) { // We only support a certain number of channels
+ ac[1] = _aTerminalId[TerminalId];
+ pRing = &_SEGGER_RTT.aUp[0]; // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed
+ SEGGER_RTT_LOCK(); // Lock to make sure that no other task is writing into buffer, while we are and number of free bytes in buffer does not change downwards after checking and before writing
+ if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) {
+ _ActiveTerminal = TerminalId;
+ _WriteBlocking(pRing, (const char*)ac, 2u);
+ } else { // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes
+ Avail = _GetAvailWriteSpace(pRing);
+ if (Avail >= 2) {
+ _ActiveTerminal = TerminalId; // Only change active terminal in case of success
+ _WriteNoCheck(pRing, (const char*)ac, 2u);
+ } else {
+ r = -1;
+ }
+ }
+ SEGGER_RTT_UNLOCK();
+ } else {
+ r = -1;
+ }
+ return r;
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_TerminalOut
+*
+* Function description
+* Writes a string to the given terminal
+* without changing the terminal for channel 0.
+*
+* Parameters
+* TerminalId Index of the terminal.
+* s String to be printed on the terminal.
+*
+* Return value
+* >= 0 - Number of bytes written.
+* < 0 - Error.
+*
+*/
+int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s) {
+ int Status;
+ unsigned FragLen;
+ unsigned Avail;
+ SEGGER_RTT_BUFFER_UP* pRing;
+ //
+ INIT();
+ //
+ // Validate terminal ID.
+ //
+ if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels
+ //
+ // Get "to-host" ring buffer.
+ //
+ pRing = &_SEGGER_RTT.aUp[0];
+ //
+ // Need to be able to change terminal, write data, change back.
+ // Compute the fixed and variable sizes.
+ //
+ FragLen = STRLEN(s);
+ //
+ // How we output depends upon the mode...
+ //
+ SEGGER_RTT_LOCK();
+ Avail = _GetAvailWriteSpace(pRing);
+ switch (pRing->Flags & SEGGER_RTT_MODE_MASK) {
+ case SEGGER_RTT_MODE_NO_BLOCK_SKIP:
+ //
+ // If we are in skip mode and there is no space for the whole
+ // of this output, don't bother switching terminals at all.
+ //
+ if (Avail < (FragLen + 4u)) {
+ Status = 0;
+ } else {
+ _PostTerminalSwitch(pRing, TerminalId);
+ Status = (int)_WriteBlocking(pRing, s, FragLen);
+ _PostTerminalSwitch(pRing, _ActiveTerminal);
+ }
+ break;
+ case SEGGER_RTT_MODE_NO_BLOCK_TRIM:
+ //
+ // If we are in trim mode and there is not enough space for everything,
+ // trim the output but always include the terminal switch. If no room
+ // for terminal switch, skip that totally.
+ //
+ if (Avail < 4u) {
+ Status = -1;
+ } else {
+ _PostTerminalSwitch(pRing, TerminalId);
+ Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u));
+ _PostTerminalSwitch(pRing, _ActiveTerminal);
+ }
+ break;
+ case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL:
+ //
+ // If we are in blocking mode, output everything.
+ //
+ _PostTerminalSwitch(pRing, TerminalId);
+ Status = (int)_WriteBlocking(pRing, s, FragLen);
+ _PostTerminalSwitch(pRing, _ActiveTerminal);
+ break;
+ default:
+ Status = -1;
+ break;
+ }
+ //
+ // Finish up.
+ //
+ SEGGER_RTT_UNLOCK();
+ } else {
+ Status = -1;
+ }
+ return Status;
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_GetAvailWriteSpace
+*
+* Function description
+* Returns the number of bytes available in the ring buffer.
+*
+* Parameters
+* BufferIndex Index of the up buffer.
+*
+* Return value
+* Number of bytes that are free in the selected up buffer.
+*/
+unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex){
+ return _GetAvailWriteSpace(&_SEGGER_RTT.aUp[BufferIndex]);
+}
+
+
+/*********************************************************************
+*
+* SEGGER_RTT_GetBytesInBuffer()
+*
+* Function description
+* Returns the number of bytes currently used in the up buffer.
+*
+* Parameters
+* BufferIndex Index of the up buffer.
+*
+* Return value
+* Number of bytes that are used in the buffer.
+*/
+unsigned SEGGER_RTT_GetBytesInBuffer(unsigned BufferIndex) {
+ unsigned RdOff;
+ unsigned WrOff;
+ unsigned r;
+ //
+ // Avoid warnings regarding volatile access order. It's not a problem
+ // in this case, but dampen compiler enthusiasm.
+ //
+ RdOff = _SEGGER_RTT.aUp[BufferIndex].RdOff;
+ WrOff = _SEGGER_RTT.aUp[BufferIndex].WrOff;
+ if (RdOff <= WrOff) {
+ r = WrOff - RdOff;
+ } else {
+ r = _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer - (WrOff - RdOff);
+ }
+ return r;
+}
+
+/*************************** End of file ****************************/
diff --git a/lib/SEGGER_RTT/RTT/SEGGER_RTT.h b/lib/SEGGER_RTT/RTT/SEGGER_RTT.h
new file mode 100644
index 0000000..3c04df5
--- /dev/null
+++ b/lib/SEGGER_RTT/RTT/SEGGER_RTT.h
@@ -0,0 +1,321 @@
+/*********************************************************************
+* SEGGER Microcontroller GmbH *
+* The Embedded Experts *
+**********************************************************************
+* *
+* (c) 1995 - 2019 SEGGER Microcontroller GmbH *
+* *
+* www.segger.com Support: support@segger.com *
+* *
+**********************************************************************
+* *
+* SEGGER RTT * Real Time Transfer for embedded targets *
+* *
+**********************************************************************
+* *
+* All rights reserved. *
+* *
+* SEGGER strongly recommends to not make any changes *
+* to or modify the source code of this software in order to stay *
+* compatible with the RTT protocol and J-Link. *
+* *
+* Redistribution and use in source and binary forms, with or *
+* without modification, are permitted provided that the following *
+* condition is met: *
+* *
+* o Redistributions of source code must retain the above copyright *
+* notice, this condition and the following disclaimer. *
+* *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
+* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
+* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
+* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
+* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
+* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
+* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
+* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
+* DAMAGE. *
+* *
+**********************************************************************
+---------------------------END-OF-HEADER------------------------------
+File : SEGGER_RTT.h
+Purpose : Implementation of SEGGER real-time transfer which allows
+ real-time communication on targets which support debugger
+ memory accesses while the CPU is running.
+Revision: $Rev: 17697 $
+----------------------------------------------------------------------
+*/
+
+#ifndef SEGGER_RTT_H
+#define SEGGER_RTT_H
+
+#include "SEGGER_RTT_Conf.h"
+
+
+
+/*********************************************************************
+*
+* Defines, defaults
+*
+**********************************************************************
+*/
+#ifndef RTT_USE_ASM
+ #if (defined __SES_ARM) // SEGGER Embedded Studio
+ #define _CC_HAS_RTT_ASM_SUPPORT 1
+ #elif (defined __CROSSWORKS_ARM) // Rowley Crossworks
+ #define _CC_HAS_RTT_ASM_SUPPORT 1
+ #elif (defined __GNUC__) // GCC
+ #define _CC_HAS_RTT_ASM_SUPPORT 1
+ #elif (defined __clang__) // Clang compiler
+ #define _CC_HAS_RTT_ASM_SUPPORT 1
+ #elif (defined __IASMARM__) // IAR assembler
+ #define _CC_HAS_RTT_ASM_SUPPORT 1
+ #elif (defined __ICCARM__) // IAR compiler
+ #define _CC_HAS_RTT_ASM_SUPPORT 1
+ #else
+ #define _CC_HAS_RTT_ASM_SUPPORT 0
+ #endif
+ #if (defined __ARM_ARCH_7M__) // Cortex-M3/4
+ #define _CORE_HAS_RTT_ASM_SUPPORT 1
+ #elif (defined __ARM_ARCH_7EM__) // Cortex-M7
+ #define _CORE_HAS_RTT_ASM_SUPPORT 1
+ #elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33
+ #define _CORE_HAS_RTT_ASM_SUPPORT 1
+ #elif (defined __ARM7M__) // IAR Cortex-M3/4
+ #if (__CORE__ == __ARM7M__)
+ #define _CORE_HAS_RTT_ASM_SUPPORT 1
+ #else
+ #define _CORE_HAS_RTT_ASM_SUPPORT 0
+ #endif
+ #elif (defined __ARM7EM__) // IAR Cortex-M7
+ #if (__CORE__ == __ARM7EM__)
+ #define _CORE_HAS_RTT_ASM_SUPPORT 1
+ #else
+ #define _CORE_HAS_RTT_ASM_SUPPORT 0
+ #endif
+ #else
+ #define _CORE_HAS_RTT_ASM_SUPPORT 0
+ #endif
+ //
+ // If IDE and core support the ASM version, enable ASM version by default
+ //
+ #if (_CC_HAS_RTT_ASM_SUPPORT && _CORE_HAS_RTT_ASM_SUPPORT)
+ #define RTT_USE_ASM (1)
+ #else
+ #define RTT_USE_ASM (0)
+ #endif
+#endif
+
+#ifndef SEGGER_RTT_ASM // defined when SEGGER_RTT.h is included from assembly file
+#include
+#include
+
+/*********************************************************************
+*
+* Defines, fixed
+*
+**********************************************************************
+*/
+
+/*********************************************************************
+*
+* Types
+*
+**********************************************************************
+*/
+
+//
+// Description for a circular buffer (also called "ring buffer")
+// which is used as up-buffer (T->H)
+//
+typedef struct {
+ const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4"
+ char* pBuffer; // Pointer to start of buffer
+ unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty.
+ unsigned WrOff; // Position of next item to be written by either target.
+ volatile unsigned RdOff; // Position of next item to be read by host. Must be volatile since it may be modified by host.
+ unsigned Flags; // Contains configuration flags
+} SEGGER_RTT_BUFFER_UP;
+
+//
+// Description for a circular buffer (also called "ring buffer")
+// which is used as down-buffer (H->T)
+//
+typedef struct {
+ const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4"
+ char* pBuffer; // Pointer to start of buffer
+ unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty.
+ volatile unsigned WrOff; // Position of next item to be written by host. Must be volatile since it may be modified by host.
+ unsigned RdOff; // Position of next item to be read by target (down-buffer).
+ unsigned Flags; // Contains configuration flags
+} SEGGER_RTT_BUFFER_DOWN;
+
+//
+// RTT control block which describes the number of buffers available
+// as well as the configuration for each buffer
+//
+//
+typedef struct {
+ char acID[16]; // Initialized to "SEGGER RTT"
+ int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2)
+ int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2)
+ SEGGER_RTT_BUFFER_UP aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS]; // Up buffers, transferring information up from target via debug probe to host
+ SEGGER_RTT_BUFFER_DOWN aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS]; // Down buffers, transferring information down from host via debug probe to target
+} SEGGER_RTT_CB;
+
+/*********************************************************************
+*
+* Global data
+*
+**********************************************************************
+*/
+extern SEGGER_RTT_CB _SEGGER_RTT;
+
+/*********************************************************************
+*
+* RTT API functions
+*
+**********************************************************************
+*/
+#ifdef __cplusplus
+ extern "C" {
+#endif
+int SEGGER_RTT_AllocDownBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
+int SEGGER_RTT_AllocUpBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
+int SEGGER_RTT_ConfigUpBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
+int SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
+int SEGGER_RTT_GetKey (void);
+unsigned SEGGER_RTT_HasData (unsigned BufferIndex);
+int SEGGER_RTT_HasKey (void);
+unsigned SEGGER_RTT_HasDataUp (unsigned BufferIndex);
+void SEGGER_RTT_Init (void);
+unsigned SEGGER_RTT_Read (unsigned BufferIndex, void* pBuffer, unsigned BufferSize);
+unsigned SEGGER_RTT_ReadNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize);
+int SEGGER_RTT_SetNameDownBuffer (unsigned BufferIndex, const char* sName);
+int SEGGER_RTT_SetNameUpBuffer (unsigned BufferIndex, const char* sName);
+int SEGGER_RTT_SetFlagsDownBuffer (unsigned BufferIndex, unsigned Flags);
+int SEGGER_RTT_SetFlagsUpBuffer (unsigned BufferIndex, unsigned Flags);
+int SEGGER_RTT_WaitKey (void);
+unsigned SEGGER_RTT_Write (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
+unsigned SEGGER_RTT_WriteNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
+unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
+unsigned SEGGER_RTT_ASM_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
+unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s);
+void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
+unsigned SEGGER_RTT_PutChar (unsigned BufferIndex, char c);
+unsigned SEGGER_RTT_PutCharSkip (unsigned BufferIndex, char c);
+unsigned SEGGER_RTT_PutCharSkipNoLock (unsigned BufferIndex, char c);
+unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex);
+unsigned SEGGER_RTT_GetBytesInBuffer (unsigned BufferIndex);
+//
+// Function macro for performance optimization
+//
+#define SEGGER_RTT_HASDATA(n) (_SEGGER_RTT.aDown[n].WrOff - _SEGGER_RTT.aDown[n].RdOff)
+
+#if RTT_USE_ASM
+ #define SEGGER_RTT_WriteSkipNoLock SEGGER_RTT_ASM_WriteSkipNoLock
+#endif
+
+/*********************************************************************
+*
+* RTT transfer functions to send RTT data via other channels.
+*
+**********************************************************************
+*/
+unsigned SEGGER_RTT_ReadUpBuffer (unsigned BufferIndex, void* pBuffer, unsigned BufferSize);
+unsigned SEGGER_RTT_ReadUpBufferNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize);
+unsigned SEGGER_RTT_WriteDownBuffer (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
+unsigned SEGGER_RTT_WriteDownBufferNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
+
+#define SEGGER_RTT_HASDATA_UP(n) (_SEGGER_RTT.aUp[n].WrOff - _SEGGER_RTT.aUp[n].RdOff)
+
+/*********************************************************************
+*
+* RTT "Terminal" API functions
+*
+**********************************************************************
+*/
+int SEGGER_RTT_SetTerminal (unsigned char TerminalId);
+int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s);
+
+/*********************************************************************
+*
+* RTT printf functions (require SEGGER_RTT_printf.c)
+*
+**********************************************************************
+*/
+int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...);
+int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList);
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif // ifndef(SEGGER_RTT_ASM)
+
+/*********************************************************************
+*
+* Defines
+*
+**********************************************************************
+*/
+
+//
+// Operating modes. Define behavior if buffer is full (not enough space for entire message)
+//
+#define SEGGER_RTT_MODE_NO_BLOCK_SKIP (0) // Skip. Do not block, output nothing. (Default)
+#define SEGGER_RTT_MODE_NO_BLOCK_TRIM (1) // Trim: Do not block, output as much as fits.
+#define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (2) // Block: Wait until there is space in the buffer.
+#define SEGGER_RTT_MODE_MASK (3)
+
+//
+// Control sequences, based on ANSI.
+// Can be used to control color, and clear the screen
+//
+#define RTT_CTRL_RESET "\x1B[0m" // Reset to default colors
+#define RTT_CTRL_CLEAR "\x1B[2J" // Clear screen, reposition cursor to top left
+
+#define RTT_CTRL_TEXT_BLACK "\x1B[2;30m"
+#define RTT_CTRL_TEXT_RED "\x1B[2;31m"
+#define RTT_CTRL_TEXT_GREEN "\x1B[2;32m"
+#define RTT_CTRL_TEXT_YELLOW "\x1B[2;33m"
+#define RTT_CTRL_TEXT_BLUE "\x1B[2;34m"
+#define RTT_CTRL_TEXT_MAGENTA "\x1B[2;35m"
+#define RTT_CTRL_TEXT_CYAN "\x1B[2;36m"
+#define RTT_CTRL_TEXT_WHITE "\x1B[2;37m"
+
+#define RTT_CTRL_TEXT_BRIGHT_BLACK "\x1B[1;30m"
+#define RTT_CTRL_TEXT_BRIGHT_RED "\x1B[1;31m"
+#define RTT_CTRL_TEXT_BRIGHT_GREEN "\x1B[1;32m"
+#define RTT_CTRL_TEXT_BRIGHT_YELLOW "\x1B[1;33m"
+#define RTT_CTRL_TEXT_BRIGHT_BLUE "\x1B[1;34m"
+#define RTT_CTRL_TEXT_BRIGHT_MAGENTA "\x1B[1;35m"
+#define RTT_CTRL_TEXT_BRIGHT_CYAN "\x1B[1;36m"
+#define RTT_CTRL_TEXT_BRIGHT_WHITE "\x1B[1;37m"
+
+#define RTT_CTRL_BG_BLACK "\x1B[24;40m"
+#define RTT_CTRL_BG_RED "\x1B[24;41m"
+#define RTT_CTRL_BG_GREEN "\x1B[24;42m"
+#define RTT_CTRL_BG_YELLOW "\x1B[24;43m"
+#define RTT_CTRL_BG_BLUE "\x1B[24;44m"
+#define RTT_CTRL_BG_MAGENTA "\x1B[24;45m"
+#define RTT_CTRL_BG_CYAN "\x1B[24;46m"
+#define RTT_CTRL_BG_WHITE "\x1B[24;47m"
+
+#define RTT_CTRL_BG_BRIGHT_BLACK "\x1B[4;40m"
+#define RTT_CTRL_BG_BRIGHT_RED "\x1B[4;41m"
+#define RTT_CTRL_BG_BRIGHT_GREEN "\x1B[4;42m"
+#define RTT_CTRL_BG_BRIGHT_YELLOW "\x1B[4;43m"
+#define RTT_CTRL_BG_BRIGHT_BLUE "\x1B[4;44m"
+#define RTT_CTRL_BG_BRIGHT_MAGENTA "\x1B[4;45m"
+#define RTT_CTRL_BG_BRIGHT_CYAN "\x1B[4;46m"
+#define RTT_CTRL_BG_BRIGHT_WHITE "\x1B[4;47m"
+
+
+#endif
+
+/*************************** End of file ****************************/
diff --git a/lib/SEGGER_RTT/RTT/SEGGER_RTT_ASM_ARMv7M.S b/lib/SEGGER_RTT/RTT/SEGGER_RTT_ASM_ARMv7M.S
new file mode 100644
index 0000000..78cde4d
--- /dev/null
+++ b/lib/SEGGER_RTT/RTT/SEGGER_RTT_ASM_ARMv7M.S
@@ -0,0 +1,235 @@
+/*********************************************************************
+* (c) SEGGER Microcontroller GmbH *
+* The Embedded Experts *
+* www.segger.com *
+**********************************************************************
+
+-------------------------- END-OF-HEADER -----------------------------
+
+File : SEGGER_RTT_ASM_ARMv7M.S
+Purpose : Assembler implementation of RTT functions for ARMv7M
+
+Additional information:
+ This module is written to be assembler-independent and works with
+ GCC and clang (Embedded Studio) and IAR.
+*/
+
+#define SEGGER_RTT_ASM // Used to control processed input from header file
+#include "SEGGER_RTT.h"
+
+/*********************************************************************
+*
+* Defines, fixed
+*
+**********************************************************************
+*/
+#define _CCIAR 0
+#define _CCCLANG 1
+
+#if (defined __SES_ARM) || (defined __GNUC__) || (defined __clang__)
+ #define _CC_TYPE _CCCLANG
+ #define _PUB_SYM .global
+ #define _EXT_SYM .extern
+ #define _END .end
+ #define _WEAK .weak
+ #define _THUMB_FUNC .thumb_func
+ #define _THUMB_CODE .code 16
+ #define _WORD .word
+ #define _SECTION(Sect, Type, AlignExp) .section Sect ##, "ax"
+ #define _ALIGN(Exp) .align Exp
+ #define _PLACE_LITS .ltorg
+ #define _DATA_SECT_START
+ #define _C_STARTUP _start
+ #define _STACK_END __stack_end__
+ #define _RAMFUNC
+ //
+ // .text => Link to flash
+ // .fast => Link to RAM
+ // OtherSect => Usually link to RAM
+ // Alignment is 2^x
+ //
+#elif defined (__IASMARM__)
+ #define _CC_TYPE _CCIAR
+ #define _PUB_SYM PUBLIC
+ #define _EXT_SYM EXTERN
+ #define _END END
+ #define _WEAK _WEAK
+ #define _THUMB_FUNC
+ #define _THUMB_CODE THUMB
+ #define _WORD DCD
+ #define _SECTION(Sect, Type, AlignExp) SECTION Sect ## : ## Type ## :REORDER:NOROOT ## (AlignExp)
+ #define _ALIGN(Exp) alignrom Exp
+ #define _PLACE_LITS
+ #define _DATA_SECT_START DATA
+ #define _C_STARTUP __iar_program_start
+ #define _STACK_END sfe(CSTACK)
+ #define _RAMFUNC SECTION_TYPE SHT_PROGBITS, SHF_WRITE | SHF_EXECINSTR
+ //
+ // .text => Link to flash
+ // .textrw => Link to RAM
+ // OtherSect => Usually link to RAM
+ // NOROOT => Allows linker to throw away the function, if not referenced
+ // Alignment is 2^x
+ //
+#endif
+
+#if (_CC_TYPE == _CCIAR)
+ NAME SEGGER_RTT_ASM_ARMv7M
+#else
+ .syntax unified
+#endif
+
+#if defined (RTT_USE_ASM) && (RTT_USE_ASM == 1)
+ #define SHT_PROGBITS 0x1
+
+/*********************************************************************
+*
+* Public / external symbols
+*
+**********************************************************************
+*/
+
+ _EXT_SYM __aeabi_memcpy
+ _EXT_SYM __aeabi_memcpy4
+ _EXT_SYM _SEGGER_RTT
+
+ _PUB_SYM SEGGER_RTT_ASM_WriteSkipNoLock
+
+/*********************************************************************
+*
+* SEGGER_RTT_WriteSkipNoLock
+*
+* Function description
+* Stores a specified number of characters in SEGGER RTT
+* control block which is then read by the host.
+* SEGGER_RTT_WriteSkipNoLock does not lock the application and
+* skips all data, if the data does not fit into the buffer.
+*
+* Parameters
+* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
+* pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
+* NumBytes Number of bytes to be stored in the SEGGER RTT control block.
+* MUST be > 0!!!
+* This is done for performance reasons, so no initial check has do be done.
+*
+* Return value
+* 1: Data has been copied
+* 0: No space, data has not been copied
+*
+* Notes
+* (1) If there is not enough space in the "Up"-buffer, all data is dropped.
+* (2) For performance reasons this function does not call Init()
+* and may only be called after RTT has been initialized.
+* Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
+*/
+ _SECTION(.text, CODE, 2)
+ _ALIGN(2)
+ _THUMB_FUNC
+SEGGER_RTT_ASM_WriteSkipNoLock: // unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pData, unsigned NumBytes) {
+ //
+ // Cases:
+ // 1) RdOff <= WrOff => Space until wrap-around is sufficient
+ // 2) RdOff <= WrOff => Space after wrap-around needed (copy in 2 chunks)
+ // 3) RdOff < WrOff => No space in buf
+ // 4) RdOff > WrOff => Space is sufficient
+ // 5) RdOff > WrOff => No space in buf
+ //
+ // 1) is the most common case for large buffers and assuming that J-Link reads the data fast enough
+ //
+ // Register usage:
+ // R0 Temporary needed as RdOff, register later on
+ // R1 pData
+ // R2
+ // R3 register. Hold free for subroutine calls
+ // R4
+ // R5 pRing->pBuffer
+ // R6 pRing (Points to active struct SEGGER_RTT_BUFFER_DOWN)
+ // R7 WrOff
+ //
+ PUSH {R4-R7}
+ ADD R3,R0,R0, LSL #+1
+ LDR.W R0,=_SEGGER_RTT // pRing = &_SEGGER_RTT.aUp[BufferIndex];
+ ADD R0,R0,R3, LSL #+3
+ ADD R6,R0,#+24
+ LDR R0,[R6, #+16] // RdOff = pRing->RdOff;
+ LDR R7,[R6, #+12] // WrOff = pRing->WrOff;
+ LDR R5,[R6, #+4] // pRing->pBuffer
+ CMP R7,R0
+ BCC.N _CheckCase4 // if (RdOff <= WrOff) { => Case 1), 2) or 3)
+ //
+ // Handling for case 1, later on identical to case 4
+ //
+ LDR R3,[R6, #+8] // Avail = pRing->SizeOfBuffer - WrOff - 1u; => Space until wrap-around (assume 1 byte not usable for case that RdOff == 0)
+ SUBS R4,R3,R7 // (Used in case we jump into case 2 afterwards)
+ SUBS R3,R4,#+1 //
+ CMP R3,R2
+ BCC.N _CheckCase2 // if (Avail >= NumBytes) { => Case 1)?
+_Case4:
+ ADDS R5,R7,R5 // pBuffer += WrOff
+ ADDS R0,R2,R7 // v = WrOff + NumBytes
+ //
+ // 2x unrolling for the copy loop that is used most of the time
+ // This is a special optimization for small SystemView packets and makes them even faster
+ //
+ _ALIGN(2)
+_LoopCopyStraight: // memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
+ LDRB R3,[R1], #+1
+ STRB R3,[R5], #+1 // *pDest++ = *pSrc++
+ SUBS R2,R2,#+1
+ BEQ _CSDone
+ LDRB R3,[R1], #+1
+ STRB R3,[R5], #+1 // *pDest++ = *pSrc++
+ SUBS R2,R2,#+1
+ BNE _LoopCopyStraight
+_CSDone:
+ STR R0,[R6, #+12] // pRing->WrOff = WrOff + NumBytes;
+ MOVS R0,#+1
+ POP {R4-R7}
+ BX LR // Return 1
+_CheckCase2:
+ ADDS R0,R0,R3 // Avail += RdOff; => Space incl. wrap-around
+ CMP R0,R2
+ BCC.N _Case3 // if (Avail >= NumBytes) { => Case 2? => If not, we have case 3) (does not fit)
+ //
+ // Handling for case 2
+ //
+ ADDS R0,R7,R5 // v = pRing->pBuffer + WrOff => Do not change pRing->pBuffer here because 2nd chunk needs org. value
+ SUBS R2,R2,R4 // NumBytes -= Rem; (Rem = pRing->SizeOfBuffer - WrOff; => Space until end of buffer)
+_LoopCopyBeforeWrapAround: // memcpy(pRing->pBuffer + WrOff, pData, Rem); => Copy 1st chunk
+ LDRB R3,[R1], #+1
+ STRB R3,[R0], #+1 // *pDest++ = *pSrc++
+ SUBS R4,R4,#+1
+ BNE _LoopCopyBeforeWrapAround
+ //
+ // Special case: First check that assumed RdOff == 0 calculated that last element before wrap-around could not be used
+ // But 2nd check (considering space until wrap-around and until RdOff) revealed that RdOff is not 0, so we can use the last element
+ // In this case, we may use a copy straight until buffer end anyway without needing to copy 2 chunks
+ // Therefore, check if 2nd memcpy is necessary at all
+ //
+ ADDS R4,R2,#+0 // Save (needed as counter in loop but must be written to after the loop). Also use this inst to update the flags to skip 2nd loop if possible
+ BEQ.N _No2ChunkNeeded // if (NumBytes) {
+_LoopCopyAfterWrapAround: // memcpy(pRing->pBuffer, pData + Rem, NumBytes);
+ LDRB R3,[R1], #+1 // pData already points to the next src byte due to copy loop increment before this loop
+ STRB R3,[R5], #+1 // *pDest++ = *pSrc++
+ SUBS R2,R2,#+1
+ BNE _LoopCopyAfterWrapAround
+_No2ChunkNeeded:
+ STR R4,[R6, #+12] // pRing->WrOff = NumBytes; => Must be written after copying data because J-Link may read control block asynchronously while writing into buffer
+ MOVS R0,#+1
+ POP {R4-R7}
+ BX LR // Return 1
+_CheckCase4:
+ SUBS R0,R0,R7
+ SUBS R0,R0,#+1 // Avail = RdOff - WrOff - 1u;
+ CMP R0,R2
+ BCS.N _Case4 // if (Avail >= NumBytes) { => Case 4) == 1) ? => If not, we have case 5) == 3) (does not fit)
+_Case3:
+ MOVS R0,#+0
+ POP {R4-R7}
+ BX LR // Return 0
+ _PLACE_LITS
+
+#endif // defined (RTT_USE_ASM) && (RTT_USE_ASM == 1)
+ _END
+
+/*************************** End of file ****************************/
diff --git a/lib/SEGGER_RTT/RTT/SEGGER_RTT_Conf.h b/lib/SEGGER_RTT/RTT/SEGGER_RTT_Conf.h
new file mode 100644
index 0000000..5e79d7e
--- /dev/null
+++ b/lib/SEGGER_RTT/RTT/SEGGER_RTT_Conf.h
@@ -0,0 +1,384 @@
+/*********************************************************************
+* SEGGER Microcontroller GmbH *
+* The Embedded Experts *
+**********************************************************************
+* *
+* (c) 1995 - 2019 SEGGER Microcontroller GmbH *
+* *
+* www.segger.com Support: support@segger.com *
+* *
+**********************************************************************
+* *
+* SEGGER RTT * Real Time Transfer for embedded targets *
+* *
+**********************************************************************
+* *
+* All rights reserved. *
+* *
+* SEGGER strongly recommends to not make any changes *
+* to or modify the source code of this software in order to stay *
+* compatible with the RTT protocol and J-Link. *
+* *
+* Redistribution and use in source and binary forms, with or *
+* without modification, are permitted provided that the following *
+* condition is met: *
+* *
+* o Redistributions of source code must retain the above copyright *
+* notice, this condition and the following disclaimer. *
+* *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
+* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
+* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
+* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
+* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
+* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
+* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
+* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
+* DAMAGE. *
+* *
+**********************************************************************
+---------------------------END-OF-HEADER------------------------------
+File : SEGGER_RTT_Conf.h
+Purpose : Implementation of SEGGER real-time transfer (RTT) which
+ allows real-time communication on targets which support
+ debugger memory accesses while the CPU is running.
+Revision: $Rev: 18601 $
+
+*/
+
+#ifndef SEGGER_RTT_CONF_H
+#define SEGGER_RTT_CONF_H
+
+#ifdef __IAR_SYSTEMS_ICC__
+ #include
+#endif
+
+/*********************************************************************
+*
+* Defines, configurable
+*
+**********************************************************************
+*/
+#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS
+ #define SEGGER_RTT_MAX_NUM_UP_BUFFERS (3) // Max. number of up-buffers (T->H) available on this target (Default: 3)
+#endif
+
+#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS
+ #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (3) // Max. number of down-buffers (H->T) available on this target (Default: 3)
+#endif
+
+#ifndef BUFFER_SIZE_UP
+ #define BUFFER_SIZE_UP (1024) // Size of the buffer for terminal output of target, up to host (Default: 1k)
+#endif
+
+#ifndef BUFFER_SIZE_DOWN
+ #define BUFFER_SIZE_DOWN (16) // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16)
+#endif
+
+#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE
+ #define SEGGER_RTT_PRINTF_BUFFER_SIZE (64u) // Size of buffer for RTT printf to bulk-send chars via RTT (Default: 64)
+#endif
+
+#ifndef SEGGER_RTT_MODE_DEFAULT
+ #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0)
+#endif
+
+/*********************************************************************
+*
+* RTT memcpy configuration
+*
+* memcpy() is good for large amounts of data,
+* but the overhead is big for small amounts, which are usually stored via RTT.
+* With SEGGER_RTT_MEMCPY_USE_BYTELOOP a simple byte loop can be used instead.
+*
+* SEGGER_RTT_MEMCPY() can be used to replace standard memcpy() in RTT functions.
+* This is may be required with memory access restrictions,
+* such as on Cortex-A devices with MMU.
+*/
+#ifndef SEGGER_RTT_MEMCPY_USE_BYTELOOP
+ #define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0 // 0: Use memcpy/SEGGER_RTT_MEMCPY, 1: Use a simple byte-loop
+#endif
+//
+// Example definition of SEGGER_RTT_MEMCPY to external memcpy with GCC toolchains and Cortex-A targets
+//
+//#if ((defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__)) && (defined (__ARM_ARCH_7A__))
+// #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) SEGGER_memcpy((pDest), (pSrc), (NumBytes))
+//#endif
+
+//
+// Target is not allowed to perform other RTT operations while string still has not been stored completely.
+// Otherwise we would probably end up with a mixed string in the buffer.
+// If using RTT from within interrupts, multiple tasks or multi processors, define the SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() function here.
+//
+// SEGGER_RTT_MAX_INTERRUPT_PRIORITY can be used in the sample lock routines on Cortex-M3/4.
+// Make sure to mask all interrupts which can send RTT data, i.e. generate SystemView events, or cause task switches.
+// When high-priority interrupts must not be masked while sending RTT data, SEGGER_RTT_MAX_INTERRUPT_PRIORITY needs to be adjusted accordingly.
+// (Higher priority = lower priority number)
+// Default value for embOS: 128u
+// Default configuration in FreeRTOS: configMAX_SYSCALL_INTERRUPT_PRIORITY: ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
+// In case of doubt mask all interrupts: 1 << (8 - BASEPRI_PRIO_BITS) i.e. 1 << 5 when 3 bits are implemented in NVIC
+// or define SEGGER_RTT_LOCK() to completely disable interrupts.
+//
+#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
+ #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) // Interrupt priority to lock on SEGGER_RTT_LOCK on Cortex-M3/4 (Default: 0x20)
+#endif
+
+/*********************************************************************
+*
+* RTT lock configuration for SEGGER Embedded Studio,
+* Rowley CrossStudio and GCC
+*/
+#if ((defined(__SES_ARM) || defined(__SES_RISCV) || defined(__CROSSWORKS_ARM) || defined(__GNUC__) || defined(__clang__)) && !defined (__CC_ARM) && !defined(WIN32))
+ #if (defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_8M_BASE__))
+ #define SEGGER_RTT_LOCK() { \
+ unsigned int LockState; \
+ __asm volatile ("mrs %0, primask \n\t" \
+ "movs r1, $1 \n\t" \
+ "msr primask, r1 \n\t" \
+ : "=r" (LockState) \
+ : \
+ : "r1" \
+ );
+
+ #define SEGGER_RTT_UNLOCK() __asm volatile ("msr primask, %0 \n\t" \
+ : \
+ : "r" (LockState) \
+ : \
+ ); \
+ }
+ #elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__))
+ #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
+ #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
+ #endif
+ #define SEGGER_RTT_LOCK() { \
+ unsigned int LockState; \
+ __asm volatile ("mrs %0, basepri \n\t" \
+ "mov r1, %1 \n\t" \
+ "msr basepri, r1 \n\t" \
+ : "=r" (LockState) \
+ : "i"(SEGGER_RTT_MAX_INTERRUPT_PRIORITY) \
+ : "r1" \
+ );
+
+ #define SEGGER_RTT_UNLOCK() __asm volatile ("msr basepri, %0 \n\t" \
+ : \
+ : "r" (LockState) \
+ : \
+ ); \
+ }
+
+ #elif defined(__ARM_ARCH_7A__)
+ #define SEGGER_RTT_LOCK() { \
+ unsigned int LockState; \
+ __asm volatile ("mrs r1, CPSR \n\t" \
+ "mov %0, r1 \n\t" \
+ "orr r1, r1, #0xC0 \n\t" \
+ "msr CPSR_c, r1 \n\t" \
+ : "=r" (LockState) \
+ : \
+ : "r1" \
+ );
+
+ #define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \
+ "mrs r1, CPSR \n\t" \
+ "bic r1, r1, #0xC0 \n\t" \
+ "and r0, r0, #0xC0 \n\t" \
+ "orr r1, r1, r0 \n\t" \
+ "msr CPSR_c, r1 \n\t" \
+ : \
+ : "r" (LockState) \
+ : "r0", "r1" \
+ ); \
+ }
+ #elif defined(__riscv) || defined(__riscv_xlen)
+ #define SEGGER_RTT_LOCK() { \
+ unsigned int LockState; \
+ __asm volatile ("csrr %0, mstatus \n\t" \
+ "csrci mstatus, 8 \n\t" \
+ "andi %0, %0, 8 \n\t" \
+ : "=r" (LockState) \
+ : \
+ : \
+ );
+
+ #define SEGGER_RTT_UNLOCK() __asm volatile ("csrr a1, mstatus \n\t" \
+ "or %0, %0, a1 \n\t" \
+ "csrs mstatus, %0 \n\t" \
+ : \
+ : "r" (LockState) \
+ : "a1" \
+ ); \
+ }
+ #else
+ #define SEGGER_RTT_LOCK()
+ #define SEGGER_RTT_UNLOCK()
+ #endif
+#endif
+
+/*********************************************************************
+*
+* RTT lock configuration for IAR EWARM
+*/
+#ifdef __ICCARM__
+ #if (defined (__ARM6M__) && (__CORE__ == __ARM6M__)) || \
+ (defined (__ARM8M_BASELINE__) && (__CORE__ == __ARM8M_BASELINE__))
+ #define SEGGER_RTT_LOCK() { \
+ unsigned int LockState; \
+ LockState = __get_PRIMASK(); \
+ __set_PRIMASK(1);
+
+ #define SEGGER_RTT_UNLOCK() __set_PRIMASK(LockState); \
+ }
+ #elif (defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) || \
+ (defined (__ARM7M__) && (__CORE__ == __ARM7M__)) || \
+ (defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__)) || \
+ (defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__))
+ #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
+ #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
+ #endif
+ #define SEGGER_RTT_LOCK() { \
+ unsigned int LockState; \
+ LockState = __get_BASEPRI(); \
+ __set_BASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY);
+
+ #define SEGGER_RTT_UNLOCK() __set_BASEPRI(LockState); \
+ }
+ #endif
+#endif
+
+/*********************************************************************
+*
+* RTT lock configuration for IAR RX
+*/
+#ifdef __ICCRX__
+ #define SEGGER_RTT_LOCK() { \
+ unsigned long LockState; \
+ LockState = __get_interrupt_state(); \
+ __disable_interrupt();
+
+ #define SEGGER_RTT_UNLOCK() __set_interrupt_state(LockState); \
+ }
+#endif
+
+/*********************************************************************
+*
+* RTT lock configuration for IAR RL78
+*/
+#ifdef __ICCRL78__
+ #define SEGGER_RTT_LOCK() { \
+ __istate_t LockState; \
+ LockState = __get_interrupt_state(); \
+ __disable_interrupt();
+
+ #define SEGGER_RTT_UNLOCK() __set_interrupt_state(LockState); \
+ }
+#endif
+
+/*********************************************************************
+*
+* RTT lock configuration for KEIL ARM
+*/
+#ifdef __CC_ARM
+ #if (defined __TARGET_ARCH_6S_M)
+ #define SEGGER_RTT_LOCK() { \
+ unsigned int LockState; \
+ register unsigned char PRIMASK __asm( "primask"); \
+ LockState = PRIMASK; \
+ PRIMASK = 1u; \
+ __schedule_barrier();
+
+ #define SEGGER_RTT_UNLOCK() PRIMASK = LockState; \
+ __schedule_barrier(); \
+ }
+ #elif (defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M))
+ #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
+ #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
+ #endif
+ #define SEGGER_RTT_LOCK() { \
+ unsigned int LockState; \
+ register unsigned char BASEPRI __asm( "basepri"); \
+ LockState = BASEPRI; \
+ BASEPRI = SEGGER_RTT_MAX_INTERRUPT_PRIORITY; \
+ __schedule_barrier();
+
+ #define SEGGER_RTT_UNLOCK() BASEPRI = LockState; \
+ __schedule_barrier(); \
+ }
+ #endif
+#endif
+
+/*********************************************************************
+*
+* RTT lock configuration for TI ARM
+*/
+#ifdef __TI_ARM__
+ #if defined (__TI_ARM_V6M0__)
+ #define SEGGER_RTT_LOCK() { \
+ unsigned int LockState; \
+ LockState = __get_PRIMASK(); \
+ __set_PRIMASK(1);
+
+ #define SEGGER_RTT_UNLOCK() __set_PRIMASK(LockState); \
+ }
+ #elif (defined (__TI_ARM_V7M3__) || defined (__TI_ARM_V7M4__))
+ #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
+ #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
+ #endif
+ #define SEGGER_RTT_LOCK() { \
+ unsigned int LockState; \
+ LockState = _set_interrupt_priority(SEGGER_RTT_MAX_INTERRUPT_PRIORITY);
+
+ #define SEGGER_RTT_UNLOCK() _set_interrupt_priority(LockState); \
+ }
+ #endif
+#endif
+
+/*********************************************************************
+*
+* RTT lock configuration for CCRX
+*/
+#ifdef __RX
+ #define SEGGER_RTT_LOCK() { \
+ unsigned long LockState; \
+ LockState = get_psw() & 0x010000; \
+ clrpsw_i();
+
+ #define SEGGER_RTT_UNLOCK() set_psw(get_psw() | LockState); \
+ }
+#endif
+
+/*********************************************************************
+*
+* RTT lock configuration for embOS Simulation on Windows
+* (Can also be used for generic RTT locking with embOS)
+*/
+#if defined(WIN32) || defined(SEGGER_RTT_LOCK_EMBOS)
+
+void OS_SIM_EnterCriticalSection(void);
+void OS_SIM_LeaveCriticalSection(void);
+
+#define SEGGER_RTT_LOCK() { \
+ OS_SIM_EnterCriticalSection();
+
+#define SEGGER_RTT_UNLOCK() OS_SIM_LeaveCriticalSection(); \
+ }
+#endif
+
+/*********************************************************************
+*
+* RTT lock configuration fallback
+*/
+#ifndef SEGGER_RTT_LOCK
+ #define SEGGER_RTT_LOCK() // Lock RTT (nestable) (i.e. disable interrupts)
+#endif
+
+#ifndef SEGGER_RTT_UNLOCK
+ #define SEGGER_RTT_UNLOCK() // Unlock RTT (nestable) (i.e. enable previous interrupt lock state)
+#endif
+
+#endif
+/*************************** End of file ****************************/
diff --git a/lib/SEGGER_RTT/RTT/SEGGER_RTT_printf.c b/lib/SEGGER_RTT/RTT/SEGGER_RTT_printf.c
new file mode 100644
index 0000000..4c996b4
--- /dev/null
+++ b/lib/SEGGER_RTT/RTT/SEGGER_RTT_printf.c
@@ -0,0 +1,500 @@
+/*********************************************************************
+* SEGGER Microcontroller GmbH *
+* The Embedded Experts *
+**********************************************************************
+* *
+* (c) 1995 - 2019 SEGGER Microcontroller GmbH *
+* *
+* www.segger.com Support: support@segger.com *
+* *
+**********************************************************************
+* *
+* SEGGER RTT * Real Time Transfer for embedded targets *
+* *
+**********************************************************************
+* *
+* All rights reserved. *
+* *
+* SEGGER strongly recommends to not make any changes *
+* to or modify the source code of this software in order to stay *
+* compatible with the RTT protocol and J-Link. *
+* *
+* Redistribution and use in source and binary forms, with or *
+* without modification, are permitted provided that the following *
+* condition is met: *
+* *
+* o Redistributions of source code must retain the above copyright *
+* notice, this condition and the following disclaimer. *
+* *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
+* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
+* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
+* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
+* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
+* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
+* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
+* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
+* DAMAGE. *
+* *
+**********************************************************************
+---------------------------END-OF-HEADER------------------------------
+File : SEGGER_RTT_printf.c
+Purpose : Replacement for printf to write formatted data via RTT
+Revision: $Rev: 17697 $
+----------------------------------------------------------------------
+*/
+#include "SEGGER_RTT.h"
+#include "SEGGER_RTT_Conf.h"
+
+/*********************************************************************
+*
+* Defines, configurable
+*
+**********************************************************************
+*/
+
+#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE
+ #define SEGGER_RTT_PRINTF_BUFFER_SIZE (64)
+#endif
+
+#include
+#include
+
+
+#define FORMAT_FLAG_LEFT_JUSTIFY (1u << 0)
+#define FORMAT_FLAG_PAD_ZERO (1u << 1)
+#define FORMAT_FLAG_PRINT_SIGN (1u << 2)
+#define FORMAT_FLAG_ALTERNATE (1u << 3)
+
+/*********************************************************************
+*
+* Types
+*
+**********************************************************************
+*/
+
+typedef struct {
+ char* pBuffer;
+ unsigned BufferSize;
+ unsigned Cnt;
+
+ int ReturnValue;
+
+ unsigned RTTBufferIndex;
+} SEGGER_RTT_PRINTF_DESC;
+
+/*********************************************************************
+*
+* Function prototypes
+*
+**********************************************************************
+*/
+
+/*********************************************************************
+*
+* Static code
+*
+**********************************************************************
+*/
+/*********************************************************************
+*
+* _StoreChar
+*/
+static void _StoreChar(SEGGER_RTT_PRINTF_DESC * p, char c) {
+ unsigned Cnt;
+
+ Cnt = p->Cnt;
+ if ((Cnt + 1u) <= p->BufferSize) {
+ *(p->pBuffer + Cnt) = c;
+ p->Cnt = Cnt + 1u;
+ p->ReturnValue++;
+ }
+ //
+ // Write part of string, when the buffer is full
+ //
+ if (p->Cnt == p->BufferSize) {
+ if (SEGGER_RTT_Write(p->RTTBufferIndex, p->pBuffer, p->Cnt) != p->Cnt) {
+ p->ReturnValue = -1;
+ } else {
+ p->Cnt = 0u;
+ }
+ }
+}
+
+/*********************************************************************
+*
+* _PrintUnsigned
+*/
+static void _PrintUnsigned(SEGGER_RTT_PRINTF_DESC * pBufferDesc, unsigned v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) {
+ static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+ unsigned Div;
+ unsigned Digit;
+ unsigned Number;
+ unsigned Width;
+ char c;
+
+ Number = v;
+ Digit = 1u;
+ //
+ // Get actual field width
+ //
+ Width = 1u;
+ while (Number >= Base) {
+ Number = (Number / Base);
+ Width++;
+ }
+ if (NumDigits > Width) {
+ Width = NumDigits;
+ }
+ //
+ // Print leading chars if necessary
+ //
+ if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) {
+ if (FieldWidth != 0u) {
+ if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && (NumDigits == 0u)) {
+ c = '0';
+ } else {
+ c = ' ';
+ }
+ while ((FieldWidth != 0u) && (Width < FieldWidth)) {
+ FieldWidth--;
+ _StoreChar(pBufferDesc, c);
+ if (pBufferDesc->ReturnValue < 0) {
+ break;
+ }
+ }
+ }
+ }
+ if (pBufferDesc->ReturnValue >= 0) {
+ //
+ // Compute Digit.
+ // Loop until Digit has the value of the highest digit required.
+ // Example: If the output is 345 (Base 10), loop 2 times until Digit is 100.
+ //
+ while (1) {
+ if (NumDigits > 1u) { // User specified a min number of digits to print? => Make sure we loop at least that often, before checking anything else (> 1 check avoids problems with NumDigits being signed / unsigned)
+ NumDigits--;
+ } else {
+ Div = v / Digit;
+ if (Div < Base) { // Is our divider big enough to extract the highest digit from value? => Done
+ break;
+ }
+ }
+ Digit *= Base;
+ }
+ //
+ // Output digits
+ //
+ do {
+ Div = v / Digit;
+ v -= Div * Digit;
+ _StoreChar(pBufferDesc, _aV2C[Div]);
+ if (pBufferDesc->ReturnValue < 0) {
+ break;
+ }
+ Digit /= Base;
+ } while (Digit);
+ //
+ // Print trailing spaces if necessary
+ //
+ if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == FORMAT_FLAG_LEFT_JUSTIFY) {
+ if (FieldWidth != 0u) {
+ while ((FieldWidth != 0u) && (Width < FieldWidth)) {
+ FieldWidth--;
+ _StoreChar(pBufferDesc, ' ');
+ if (pBufferDesc->ReturnValue < 0) {
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+/*********************************************************************
+*
+* _PrintInt
+*/
+static void _PrintInt(SEGGER_RTT_PRINTF_DESC * pBufferDesc, int v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) {
+ unsigned Width;
+ int Number;
+
+ Number = (v < 0) ? -v : v;
+
+ //
+ // Get actual field width
+ //
+ Width = 1u;
+ while (Number >= (int)Base) {
+ Number = (Number / (int)Base);
+ Width++;
+ }
+ if (NumDigits > Width) {
+ Width = NumDigits;
+ }
+ if ((FieldWidth > 0u) && ((v < 0) || ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN))) {
+ FieldWidth--;
+ }
+
+ //
+ // Print leading spaces if necessary
+ //
+ if ((((FormatFlags & FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u)) {
+ if (FieldWidth != 0u) {
+ while ((FieldWidth != 0u) && (Width < FieldWidth)) {
+ FieldWidth--;
+ _StoreChar(pBufferDesc, ' ');
+ if (pBufferDesc->ReturnValue < 0) {
+ break;
+ }
+ }
+ }
+ }
+ //
+ // Print sign if necessary
+ //
+ if (pBufferDesc->ReturnValue >= 0) {
+ if (v < 0) {
+ v = -v;
+ _StoreChar(pBufferDesc, '-');
+ } else if ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN) {
+ _StoreChar(pBufferDesc, '+');
+ } else {
+
+ }
+ if (pBufferDesc->ReturnValue >= 0) {
+ //
+ // Print leading zeros if necessary
+ //
+ if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u)) {
+ if (FieldWidth != 0u) {
+ while ((FieldWidth != 0u) && (Width < FieldWidth)) {
+ FieldWidth--;
+ _StoreChar(pBufferDesc, '0');
+ if (pBufferDesc->ReturnValue < 0) {
+ break;
+ }
+ }
+ }
+ }
+ if (pBufferDesc->ReturnValue >= 0) {
+ //
+ // Print number without sign
+ //
+ _PrintUnsigned(pBufferDesc, (unsigned)v, Base, NumDigits, FieldWidth, FormatFlags);
+ }
+ }
+ }
+}
+
+/*********************************************************************
+*
+* Public code
+*
+**********************************************************************
+*/
+/*********************************************************************
+*
+* SEGGER_RTT_vprintf
+*
+* Function description
+* Stores a formatted string in SEGGER RTT control block.
+* This data is read by the host.
+*
+* Parameters
+* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal")
+* sFormat Pointer to format string
+* pParamList Pointer to the list of arguments for the format string
+*
+* Return values
+* >= 0: Number of bytes which have been stored in the "Up"-buffer.
+* < 0: Error
+*/
+int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList) {
+ char c;
+ SEGGER_RTT_PRINTF_DESC BufferDesc;
+ int v;
+ unsigned NumDigits;
+ unsigned FormatFlags;
+ unsigned FieldWidth;
+ char acBuffer[SEGGER_RTT_PRINTF_BUFFER_SIZE];
+
+ BufferDesc.pBuffer = acBuffer;
+ BufferDesc.BufferSize = SEGGER_RTT_PRINTF_BUFFER_SIZE;
+ BufferDesc.Cnt = 0u;
+ BufferDesc.RTTBufferIndex = BufferIndex;
+ BufferDesc.ReturnValue = 0;
+
+ do {
+ c = *sFormat;
+ sFormat++;
+ if (c == 0u) {
+ break;
+ }
+ if (c == '%') {
+ //
+ // Filter out flags
+ //
+ FormatFlags = 0u;
+ v = 1;
+ do {
+ c = *sFormat;
+ switch (c) {
+ case '-': FormatFlags |= FORMAT_FLAG_LEFT_JUSTIFY; sFormat++; break;
+ case '0': FormatFlags |= FORMAT_FLAG_PAD_ZERO; sFormat++; break;
+ case '+': FormatFlags |= FORMAT_FLAG_PRINT_SIGN; sFormat++; break;
+ case '#': FormatFlags |= FORMAT_FLAG_ALTERNATE; sFormat++; break;
+ default: v = 0; break;
+ }
+ } while (v);
+ //
+ // filter out field with
+ //
+ FieldWidth = 0u;
+ do {
+ c = *sFormat;
+ if ((c < '0') || (c > '9')) {
+ break;
+ }
+ sFormat++;
+ FieldWidth = (FieldWidth * 10u) + ((unsigned)c - '0');
+ } while (1);
+
+ //
+ // Filter out precision (number of digits to display)
+ //
+ NumDigits = 0u;
+ c = *sFormat;
+ if (c == '.') {
+ sFormat++;
+ do {
+ c = *sFormat;
+ if ((c < '0') || (c > '9')) {
+ break;
+ }
+ sFormat++;
+ NumDigits = NumDigits * 10u + ((unsigned)c - '0');
+ } while (1);
+ }
+ //
+ // Filter out length modifier
+ //
+ c = *sFormat;
+ do {
+ if ((c == 'l') || (c == 'h')) {
+ sFormat++;
+ c = *sFormat;
+ } else {
+ break;
+ }
+ } while (1);
+ //
+ // Handle specifiers
+ //
+ switch (c) {
+ case 'c': {
+ char c0;
+ v = va_arg(*pParamList, int);
+ c0 = (char)v;
+ _StoreChar(&BufferDesc, c0);
+ break;
+ }
+ case 'd':
+ v = va_arg(*pParamList, int);
+ _PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags);
+ break;
+ case 'u':
+ v = va_arg(*pParamList, int);
+ _PrintUnsigned(&BufferDesc, (unsigned)v, 10u, NumDigits, FieldWidth, FormatFlags);
+ break;
+ case 'x':
+ case 'X':
+ v = va_arg(*pParamList, int);
+ _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, NumDigits, FieldWidth, FormatFlags);
+ break;
+ case 's':
+ {
+ const char * s = va_arg(*pParamList, const char *);
+ do {
+ c = *s;
+ s++;
+ if (c == '\0') {
+ break;
+ }
+ _StoreChar(&BufferDesc, c);
+ } while (BufferDesc.ReturnValue >= 0);
+ }
+ break;
+ case 'p':
+ v = va_arg(*pParamList, int);
+ _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, 8u, 8u, 0u);
+ break;
+ case '%':
+ _StoreChar(&BufferDesc, '%');
+ break;
+ default:
+ break;
+ }
+ sFormat++;
+ } else {
+ _StoreChar(&BufferDesc, c);
+ }
+ } while (BufferDesc.ReturnValue >= 0);
+
+ if (BufferDesc.ReturnValue > 0) {
+ //
+ // Write remaining data, if any
+ //
+ if (BufferDesc.Cnt != 0u) {
+ SEGGER_RTT_Write(BufferIndex, acBuffer, BufferDesc.Cnt);
+ }
+ BufferDesc.ReturnValue += (int)BufferDesc.Cnt;
+ }
+ return BufferDesc.ReturnValue;
+}
+
+/*********************************************************************
+*
+* SEGGER_RTT_printf
+*
+* Function description
+* Stores a formatted string in SEGGER RTT control block.
+* This data is read by the host.
+*
+* Parameters
+* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal")
+* sFormat Pointer to format string, followed by the arguments for conversion
+*
+* Return values
+* >= 0: Number of bytes which have been stored in the "Up"-buffer.
+* < 0: Error
+*
+* Notes
+* (1) Conversion specifications have following syntax:
+* %[flags][FieldWidth][.Precision]ConversionSpecifier
+* (2) Supported flags:
+* -: Left justify within the field width
+* +: Always print sign extension for signed conversions
+* 0: Pad with 0 instead of spaces. Ignored when using '-'-flag or precision
+* Supported conversion specifiers:
+* c: Print the argument as one char
+* d: Print the argument as a signed integer
+* u: Print the argument as an unsigned integer
+* x: Print the argument as an hexadecimal integer
+* s: Print the string pointed to by the argument
+* p: Print the argument as an 8-digit hexadecimal integer. (Argument shall be a pointer to void.)
+*/
+int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...) {
+ int r;
+ va_list ParamList;
+
+ va_start(ParamList, sFormat);
+ r = SEGGER_RTT_vprintf(BufferIndex, sFormat, &ParamList);
+ va_end(ParamList);
+ return r;
+}
+/*************************** End of file ****************************/
diff --git a/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_GCC.c b/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_GCC.c
new file mode 100644
index 0000000..da4a4b5
--- /dev/null
+++ b/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_GCC.c
@@ -0,0 +1,120 @@
+/*********************************************************************
+* SEGGER Microcontroller GmbH *
+* The Embedded Experts *
+**********************************************************************
+* *
+* (c) 1995 - 2019 SEGGER Microcontroller GmbH *
+* *
+* www.segger.com Support: support@segger.com *
+* *
+**********************************************************************
+* *
+* SEGGER RTT * Real Time Transfer for embedded targets *
+* *
+**********************************************************************
+* *
+* All rights reserved. *
+* *
+* SEGGER strongly recommends to not make any changes *
+* to or modify the source code of this software in order to stay *
+* compatible with the RTT protocol and J-Link. *
+* *
+* Redistribution and use in source and binary forms, with or *
+* without modification, are permitted provided that the following *
+* condition is met: *
+* *
+* o Redistributions of source code must retain the above copyright *
+* notice, this condition and the following disclaimer. *
+* *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
+* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
+* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
+* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
+* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
+* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
+* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
+* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
+* DAMAGE. *
+* *
+**********************************************************************
+---------------------------END-OF-HEADER------------------------------
+File : SEGGER_RTT_Syscalls_GCC.c
+Purpose : Low-level functions for using printf() via RTT in GCC.
+ To use RTT for printf output, include this file in your
+ application.
+Revision: $Rev: 17697 $
+----------------------------------------------------------------------
+*/
+#if (defined __GNUC__) && !(defined __SES_ARM) && !(defined __CROSSWORKS_ARM)
+
+#include // required for _write_r
+#include "SEGGER_RTT.h"
+
+
+/*********************************************************************
+*
+* Types
+*
+**********************************************************************
+*/
+//
+// If necessary define the _reent struct
+// to match the one passed by the used standard library.
+//
+struct _reent;
+
+/*********************************************************************
+*
+* Function prototypes
+*
+**********************************************************************
+*/
+int _write(int file, char *ptr, int len);
+int _write_r(struct _reent *r, int file, const void *ptr, int len);
+
+/*********************************************************************
+*
+* Global functions
+*
+**********************************************************************
+*/
+
+/*********************************************************************
+*
+* _write()
+*
+* Function description
+* Low-level write function.
+* libc subroutines will use this system routine for output to all files,
+* including stdout.
+* Write data via RTT.
+*/
+int _write(int file, char *ptr, int len) {
+ (void) file; /* Not used, avoid warning */
+ SEGGER_RTT_Write(0, ptr, len);
+ return len;
+}
+
+/*********************************************************************
+*
+* _write_r()
+*
+* Function description
+* Low-level reentrant write function.
+* libc subroutines will use this system routine for output to all files,
+* including stdout.
+* Write data via RTT.
+*/
+int _write_r(struct _reent *r, int file, const void *ptr, int len) {
+ (void) file; /* Not used, avoid warning */
+ (void) r; /* Not used, avoid warning */
+ SEGGER_RTT_Write(0, ptr, len);
+ return len;
+}
+
+#endif
+/****** End Of File *************************************************/
diff --git a/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_IAR.c b/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_IAR.c
new file mode 100644
index 0000000..4c76752
--- /dev/null
+++ b/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_IAR.c
@@ -0,0 +1,115 @@
+/*********************************************************************
+* SEGGER Microcontroller GmbH *
+* The Embedded Experts *
+**********************************************************************
+* *
+* (c) 1995 - 2019 SEGGER Microcontroller GmbH *
+* *
+* www.segger.com Support: support@segger.com *
+* *
+**********************************************************************
+* *
+* SEGGER RTT * Real Time Transfer for embedded targets *
+* *
+**********************************************************************
+* *
+* All rights reserved. *
+* *
+* SEGGER strongly recommends to not make any changes *
+* to or modify the source code of this software in order to stay *
+* compatible with the RTT protocol and J-Link. *
+* *
+* Redistribution and use in source and binary forms, with or *
+* without modification, are permitted provided that the following *
+* condition is met: *
+* *
+* o Redistributions of source code must retain the above copyright *
+* notice, this condition and the following disclaimer. *
+* *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
+* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
+* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
+* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
+* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
+* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
+* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
+* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
+* DAMAGE. *
+* *
+**********************************************************************
+---------------------------END-OF-HEADER------------------------------
+File : SEGGER_RTT_Syscalls_IAR.c
+Purpose : Low-level functions for using printf() via RTT in IAR.
+ To use RTT for printf output, include this file in your
+ application and set the Library Configuration to Normal.
+Revision: $Rev: 17697 $
+----------------------------------------------------------------------
+*/
+#ifdef __IAR_SYSTEMS_ICC__
+
+//
+// Since IAR EWARM V8 and EWRX V4, yfuns.h is considered as deprecated and LowLevelIOInterface.h
+// shall be used instead. To not break any compatibility with older compiler versions, we have a
+// version check in here.
+//
+#if ((defined __ICCARM__) && (__VER__ >= 8000000)) || ((defined __ICCRX__) && (__VER__ >= 400))
+ #include
+#else
+ #include
+#endif
+
+#include "SEGGER_RTT.h"
+#pragma module_name = "?__write"
+
+/*********************************************************************
+*
+* Function prototypes
+*
+**********************************************************************
+*/
+size_t __write(int handle, const unsigned char * buffer, size_t size);
+
+/*********************************************************************
+*
+* Global functions
+*
+**********************************************************************
+*/
+/*********************************************************************
+*
+* __write()
+*
+* Function description
+* Low-level write function.
+* Standard library subroutines will use this system routine
+* for output to all files, including stdout.
+* Write data via RTT.
+*/
+size_t __write(int handle, const unsigned char * buffer, size_t size) {
+ (void) handle; /* Not used, avoid warning */
+ SEGGER_RTT_Write(0, (const char*)buffer, size);
+ return size;
+}
+
+/*********************************************************************
+*
+* __write_buffered()
+*
+* Function description
+* Low-level write function.
+* Standard library subroutines will use this system routine
+* for output to all files, including stdout.
+* Write data via RTT.
+*/
+size_t __write_buffered(int handle, const unsigned char * buffer, size_t size) {
+ (void) handle; /* Not used, avoid warning */
+ SEGGER_RTT_Write(0, (const char*)buffer, size);
+ return size;
+}
+
+#endif
+/****** End Of File *************************************************/
diff --git a/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_KEIL.c b/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_KEIL.c
new file mode 100644
index 0000000..f7f5aed
--- /dev/null
+++ b/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_KEIL.c
@@ -0,0 +1,386 @@
+/*********************************************************************
+* SEGGER Microcontroller GmbH *
+* The Embedded Experts *
+**********************************************************************
+* *
+* (c) 1995 - 2019 SEGGER Microcontroller GmbH *
+* *
+* www.segger.com Support: support@segger.com *
+* *
+**********************************************************************
+* *
+* SEGGER RTT * Real Time Transfer for embedded targets *
+* *
+**********************************************************************
+* *
+* All rights reserved. *
+* *
+* SEGGER strongly recommends to not make any changes *
+* to or modify the source code of this software in order to stay *
+* compatible with the RTT protocol and J-Link. *
+* *
+* Redistribution and use in source and binary forms, with or *
+* without modification, are permitted provided that the following *
+* condition is met: *
+* *
+* o Redistributions of source code must retain the above copyright *
+* notice, this condition and the following disclaimer. *
+* *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
+* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
+* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
+* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
+* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
+* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
+* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
+* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
+* DAMAGE. *
+* *
+**********************************************************************
+---------------------------END-OF-HEADER------------------------------
+File : RTT_Syscalls_KEIL.c
+Purpose : Retargeting module for KEIL MDK-CM3.
+ Low-level functions for using printf() via RTT
+Revision: $Rev: 17697 $
+----------------------------------------------------------------------
+*/
+#ifdef __CC_ARM
+
+#include
+#include
+#include
+#include
+#include
+
+#include "SEGGER_RTT.h"
+/*********************************************************************
+*
+* #pragmas
+*
+**********************************************************************
+*/
+#pragma import(__use_no_semihosting)
+
+#ifdef _MICROLIB
+ #pragma import(__use_full_stdio)
+#endif
+
+/*********************************************************************
+*
+* Defines non-configurable
+*
+**********************************************************************
+*/
+
+/* Standard IO device handles - arbitrary, but any real file system handles must be
+ less than 0x8000. */
+#define STDIN 0x8001 // Standard Input Stream
+#define STDOUT 0x8002 // Standard Output Stream
+#define STDERR 0x8003 // Standard Error Stream
+
+/*********************************************************************
+*
+* Public const
+*
+**********************************************************************
+*/
+#if __ARMCC_VERSION < 5000000
+//const char __stdin_name[] = "STDIN";
+const char __stdout_name[] = "STDOUT";
+const char __stderr_name[] = "STDERR";
+#endif
+
+/*********************************************************************
+*
+* Public code
+*
+**********************************************************************
+*/
+
+/*********************************************************************
+*
+* _ttywrch
+*
+* Function description:
+* Outputs a character to the console
+*
+* Parameters:
+* c - character to output
+*
+*/
+void _ttywrch(int c) {
+ fputc(c, stdout); // stdout
+ fflush(stdout);
+}
+
+/*********************************************************************
+*
+* _sys_open
+*
+* Function description:
+* Opens the device/file in order to do read/write operations
+*
+* Parameters:
+* sName - sName of the device/file to open
+* OpenMode - This parameter is currently ignored
+*
+* Return value:
+* != 0 - Handle to the object to open, otherwise
+* == 0 -"device" is not handled by this module
+*
+*/
+FILEHANDLE _sys_open(const char * sName, int OpenMode) {
+ (void)OpenMode;
+ // Register standard Input Output devices.
+ if (strcmp(sName, __stdout_name) == 0) {
+ return (STDOUT);
+ } else if (strcmp(sName, __stderr_name) == 0) {
+ return (STDERR);
+ } else
+ return (0); // Not implemented
+}
+
+/*********************************************************************
+*
+* _sys_close
+*
+* Function description:
+* Closes the handle to the open device/file
+*
+* Parameters:
+* hFile - Handle to a file opened via _sys_open
+*
+* Return value:
+* 0 - device/file closed
+*
+*/
+int _sys_close(FILEHANDLE hFile) {
+ (void)hFile;
+ return 0; // Not implemented
+}
+
+/*********************************************************************
+*
+* _sys_write
+*
+* Function description:
+* Writes the data to an open handle.
+* Currently this function only outputs data to the console
+*
+* Parameters:
+* hFile - Handle to a file opened via _sys_open
+* pBuffer - Pointer to the data that shall be written
+* NumBytes - Number of bytes to write
+* Mode - The Mode that shall be used
+*
+* Return value:
+* Number of bytes *not* written to the file/device
+*
+*/
+int _sys_write(FILEHANDLE hFile, const unsigned char * pBuffer, unsigned NumBytes, int Mode) {
+ int r = 0;
+
+ (void)Mode;
+ if (hFile == STDOUT) {
+ SEGGER_RTT_Write(0, (const char*)pBuffer, NumBytes);
+ return 0;
+ }
+ return r;
+}
+
+/*********************************************************************
+*
+* _sys_read
+*
+* Function description:
+* Reads data from an open handle.
+* Currently this modules does nothing.
+*
+* Parameters:
+* hFile - Handle to a file opened via _sys_open
+* pBuffer - Pointer to buffer to store the read data
+* NumBytes - Number of bytes to read
+* Mode - The Mode that shall be used
+*
+* Return value:
+* Number of bytes read from the file/device
+*
+*/
+int _sys_read(FILEHANDLE hFile, unsigned char * pBuffer, unsigned NumBytes, int Mode) {
+ (void)hFile;
+ (void)pBuffer;
+ (void)NumBytes;
+ (void)Mode;
+ return (0); // Not implemented
+}
+
+/*********************************************************************
+*
+* _sys_istty
+*
+* Function description:
+* This function shall return whether the opened file
+* is a console device or not.
+*
+* Parameters:
+* hFile - Handle to a file opened via _sys_open
+*
+* Return value:
+* 1 - Device is a console
+* 0 - Device is not a console
+*
+*/
+int _sys_istty(FILEHANDLE hFile) {
+ if (hFile > 0x8000) {
+ return (1);
+ }
+ return (0); // Not implemented
+}
+
+/*********************************************************************
+*
+* _sys_seek
+*
+* Function description:
+* Seeks via the file to a specific position
+*
+* Parameters:
+* hFile - Handle to a file opened via _sys_open
+* Pos -
+*
+* Return value:
+* int -
+*
+*/
+int _sys_seek(FILEHANDLE hFile, long Pos) {
+ (void)hFile;
+ (void)Pos;
+ return (0); // Not implemented
+}
+
+/*********************************************************************
+*
+* _sys_ensure
+*
+* Function description:
+*
+*
+* Parameters:
+* hFile - Handle to a file opened via _sys_open
+*
+* Return value:
+* int -
+*
+*/
+int _sys_ensure(FILEHANDLE hFile) {
+ (void)hFile;
+ return (-1); // Not implemented
+}
+
+/*********************************************************************
+*
+* _sys_flen
+*
+* Function description:
+* Returns the length of the opened file handle
+*
+* Parameters:
+* hFile - Handle to a file opened via _sys_open
+*
+* Return value:
+* Length of the file
+*
+*/
+long _sys_flen(FILEHANDLE hFile) {
+ (void)hFile;
+ return (0); // Not implemented
+}
+
+/*********************************************************************
+*
+* _sys_tmpnam
+*
+* Function description:
+* This function converts the file number fileno for a temporary
+* file to a unique filename, for example, tmp0001.
+*
+* Parameters:
+* pBuffer - Pointer to a buffer to store the name
+* FileNum - file number to convert
+* MaxLen - Size of the buffer
+*
+* Return value:
+* 1 - Error
+* 0 - Success
+*
+*/
+int _sys_tmpnam(char * pBuffer, int FileNum, unsigned MaxLen) {
+ (void)pBuffer;
+ (void)FileNum;
+ (void)MaxLen;
+ return (1); // Not implemented
+}
+
+/*********************************************************************
+*
+* _sys_command_string
+*
+* Function description:
+* This function shall execute a system command.
+*
+* Parameters:
+* cmd - Pointer to the command string
+* len - Length of the string
+*
+* Return value:
+* == NULL - Command was not successfully executed
+* == sCmd - Command was passed successfully
+*
+*/
+char * _sys_command_string(char * cmd, int len) {
+ (void)len;
+ return cmd; // Not implemented
+}
+
+/*********************************************************************
+*
+* _sys_exit
+*
+* Function description:
+* This function is called when the application returns from main
+*
+* Parameters:
+* ReturnCode - Return code from the main function
+*
+*
+*/
+void _sys_exit(int ReturnCode) {
+ (void)ReturnCode;
+ while (1); // Not implemented
+}
+
+#if __ARMCC_VERSION >= 5000000
+/*********************************************************************
+*
+* stdout_putchar
+*
+* Function description:
+* Put a character to the stdout
+*
+* Parameters:
+* ch - Character to output
+*
+*
+*/
+int stdout_putchar(int ch) {
+ (void)ch;
+ return ch; // Not implemented
+}
+#endif
+
+#endif
+/*************************** End of file ****************************/
diff --git a/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_SES.c b/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_SES.c
new file mode 100644
index 0000000..5ce8457
--- /dev/null
+++ b/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_SES.c
@@ -0,0 +1,247 @@
+/*********************************************************************
+* SEGGER Microcontroller GmbH *
+* The Embedded Experts *
+**********************************************************************
+* *
+* (c) 1995 - 2019 SEGGER Microcontroller GmbH *
+* *
+* www.segger.com Support: support@segger.com *
+* *
+**********************************************************************
+* *
+* SEGGER RTT * Real Time Transfer for embedded targets *
+* *
+**********************************************************************
+* *
+* All rights reserved. *
+* *
+* SEGGER strongly recommends to not make any changes *
+* to or modify the source code of this software in order to stay *
+* compatible with the RTT protocol and J-Link. *
+* *
+* Redistribution and use in source and binary forms, with or *
+* without modification, are permitted provided that the following *
+* condition is met: *
+* *
+* o Redistributions of source code must retain the above copyright *
+* notice, this condition and the following disclaimer. *
+* *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
+* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
+* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
+* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
+* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
+* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
+* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
+* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
+* DAMAGE. *
+* *
+**********************************************************************
+---------------------------END-OF-HEADER------------------------------
+File : SEGGER_RTT_Syscalls_SES.c
+Purpose : Reimplementation of printf, puts and __getchar using RTT
+ in SEGGER Embedded Studio.
+ To use RTT for printf output, include this file in your
+ application.
+Revision: $Rev: 18539 $
+----------------------------------------------------------------------
+*/
+#if (defined __SES_ARM) || (defined __SES_RISCV) || (defined __CROSSWORKS_ARM)
+
+#include "SEGGER_RTT.h"
+#include
+#include
+#include "limits.h"
+#include "__libc.h"
+#include "__vfprintf.h"
+
+/*********************************************************************
+*
+* Defines, configurable
+*
+**********************************************************************
+*/
+//
+// Select string formatting implementation.
+//
+// RTT printf formatting
+// - Configurable stack usage. (SEGGER_RTT_PRINTF_BUFFER_SIZE in SEGGER_RTT_Conf.h)
+// - No maximum string length.
+// - Limited conversion specifiers and flags. (See SEGGER_RTT_printf.c)
+// Standard library printf formatting
+// - Configurable formatting capabilities.
+// - Full conversion specifier and flag support.
+// - Maximum string length has to be known or (slightly) slower character-wise output.
+//
+// #define PRINTF_USE_SEGGER_RTT_FORMATTING 0 // Use standard library formatting
+// #define PRINTF_USE_SEGGER_RTT_FORMATTING 1 // Use RTT formatting
+//
+#ifndef PRINTF_USE_SEGGER_RTT_FORMATTING
+ #define PRINTF_USE_SEGGER_RTT_FORMATTING 0
+#endif
+//
+// If using standard library formatting,
+// select maximum output string buffer size or character-wise output.
+//
+// #define PRINTF_BUFFER_SIZE 0 // Use character-wise output
+// #define PRINTF_BUFFER_SIZE 128 // Default maximum string length
+//
+#ifndef PRINTF_BUFFER_SIZE
+ #define PRINTF_BUFFER_SIZE 128
+#endif
+
+#if PRINTF_USE_SEGGER_RTT_FORMATTING // Use SEGGER RTT formatting implementation
+/*********************************************************************
+*
+* Function prototypes
+*
+**********************************************************************
+*/
+int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList);
+
+/*********************************************************************
+*
+* Global functions, printf
+*
+**********************************************************************
+*/
+/*********************************************************************
+*
+* printf()
+*
+* Function description
+* print a formatted string using RTT and SEGGER RTT formatting.
+*/
+int printf(const char *fmt,...) {
+ int n;
+ va_list args;
+
+ va_start (args, fmt);
+ n = SEGGER_RTT_vprintf(0, fmt, &args);
+ va_end(args);
+ return n;
+}
+
+#elif PRINTF_BUFFER_SIZE == 0 // Use standard library formatting with character-wise output
+
+/*********************************************************************
+*
+* Static functions
+*
+**********************************************************************
+*/
+static int _putchar(int x, __printf_tag_ptr ctx) {
+ (void)ctx;
+ SEGGER_RTT_Write(0, (char *)&x, 1);
+ return x;
+}
+
+/*********************************************************************
+*
+* Global functions, printf
+*
+**********************************************************************
+*/
+/*********************************************************************
+*
+* printf()
+*
+* Function description
+* print a formatted string character-wise, using RTT and standard
+* library formatting.
+*/
+int printf(const char *fmt, ...) {
+ int n;
+ va_list args;
+ __printf_t iod;
+
+ va_start(args, fmt);
+ iod.string = 0;
+ iod.maxchars = INT_MAX;
+ iod.output_fn = _putchar;
+ SEGGER_RTT_LOCK();
+ n = __vfprintf(&iod, fmt, args);
+ SEGGER_RTT_UNLOCK();
+ va_end(args);
+ return n;
+}
+
+#else // Use standard library formatting with static buffer
+
+/*********************************************************************
+*
+* Global functions, printf
+*
+**********************************************************************
+*/
+/*********************************************************************
+*
+* printf()
+*
+* Function description
+* print a formatted string using RTT and standard library formatting.
+*/
+int printf(const char *fmt,...) {
+ int n;
+ char aBuffer[PRINTF_BUFFER_SIZE];
+ va_list args;
+
+ va_start (args, fmt);
+ n = vsnprintf(aBuffer, sizeof(aBuffer), fmt, args);
+ if (n > (int)sizeof(aBuffer)) {
+ SEGGER_RTT_Write(0, aBuffer, sizeof(aBuffer));
+ } else if (n > 0) {
+ SEGGER_RTT_Write(0, aBuffer, n);
+ }
+ va_end(args);
+ return n;
+}
+#endif
+
+/*********************************************************************
+*
+* Global functions
+*
+**********************************************************************
+*/
+/*********************************************************************
+*
+* puts()
+*
+* Function description
+* print a string using RTT.
+*/
+int puts(const char *s) {
+ return SEGGER_RTT_WriteString(0, s);
+}
+
+/*********************************************************************
+*
+* __putchar()
+*
+* Function description
+* Write one character via RTT.
+*/
+int __putchar(int x, __printf_tag_ptr ctx) {
+ (void)ctx;
+ SEGGER_RTT_Write(0, (char *)&x, 1);
+ return x;
+}
+
+/*********************************************************************
+*
+* __getchar()
+*
+* Function description
+* Wait for and get a character via RTT.
+*/
+int __getchar() {
+ return SEGGER_RTT_WaitKey();
+}
+
+#endif
+/****** End Of File *************************************************/
diff --git a/lib/sdk/components/libraries/util/app_util_platform.c b/lib/sdk/components/libraries/util/app_util_platform.c
index bbe5856..ef8d831 100644
--- a/lib/sdk/components/libraries/util/app_util_platform.c
+++ b/lib/sdk/components/libraries/util/app_util_platform.c
@@ -39,10 +39,8 @@
*/
#include "app_util_platform.h"
-#ifdef SOFTDEVICE_PRESENT
/* Global nvic state instance, required by nrf_nvic.h */
nrf_nvic_state_t nrf_nvic_state;
-#endif
static uint32_t m_in_critical_region = 0;
diff --git a/lib/sdk/components/libraries/util/app_util_platform.h b/lib/sdk/components/libraries/util/app_util_platform.h
index 61db926..195f9dd 100644
--- a/lib/sdk/components/libraries/util/app_util_platform.h
+++ b/lib/sdk/components/libraries/util/app_util_platform.h
@@ -52,10 +52,8 @@
#include
#include "compiler_abstraction.h"
#include "nrf.h"
-#ifdef SOFTDEVICE_PRESENT
#include "nrf_soc.h"
#include "nrf_nvic.h"
-#endif
#include "nrf_assert.h"
#include "app_error.h"
diff --git a/lib/sdk11/components/ble/ble_services/ble_dis/ble_dis.c b/lib/sdk11/components/ble/ble_services/ble_dis/ble_dis.c
index 524b009..d6a719f 100644
--- a/lib/sdk11/components/ble/ble_services/ble_dis/ble_dis.c
+++ b/lib/sdk11/components/ble/ble_services/ble_dis/ble_dis.c
@@ -32,15 +32,18 @@
static uint16_t service_handle;
static ble_gatts_char_handles_t manufact_name_handles;
static ble_gatts_char_handles_t model_num_handles;
+static ble_gatts_char_handles_t fw_rev_handles;
+static ble_gatts_char_handles_t pnp_id_handles;
+
+#if 0
static ble_gatts_char_handles_t serial_num_handles;
static ble_gatts_char_handles_t hw_rev_handles;
-static ble_gatts_char_handles_t fw_rev_handles;
static ble_gatts_char_handles_t sw_rev_handles;
static ble_gatts_char_handles_t sys_id_handles;
static ble_gatts_char_handles_t reg_cert_data_list_handles;
-static ble_gatts_char_handles_t pnp_id_handles;
-
+#endif
+#if 0
/**@brief Function for encoding a System ID.
*
* @param[out] p_encoded_buffer Buffer where the encoded data will be written.
@@ -61,6 +64,7 @@ static void sys_id_encode(uint8_t * p_encoded_buffer, const ble_dis_sys_id_t * p
p_encoded_buffer[6] = (p_sys_id->organizationally_unique_id & 0x00FF00) >> 8;
p_encoded_buffer[7] = (p_sys_id->organizationally_unique_id & 0xFF0000) >> 16;
}
+#endif
/**@brief Function for encoding a PnP ID.
@@ -182,6 +186,8 @@ uint32_t ble_dis_init(const ble_dis_init_t * p_dis_init)
return err_code;
}
}
+
+#if 0
if (p_dis_init->serial_num_str.length > 0)
{
err_code = char_add(BLE_UUID_SERIAL_NUMBER_STRING_CHAR,
@@ -206,6 +212,8 @@ uint32_t ble_dis_init(const ble_dis_init_t * p_dis_init)
return err_code;
}
}
+#endif
+
if (p_dis_init->fw_rev_str.length > 0)
{
err_code = char_add(BLE_UUID_FIRMWARE_REVISION_STRING_CHAR,
@@ -218,6 +226,8 @@ uint32_t ble_dis_init(const ble_dis_init_t * p_dis_init)
return err_code;
}
}
+
+#if 0
if (p_dis_init->sw_rev_str.length > 0)
{
err_code = char_add(BLE_UUID_SOFTWARE_REVISION_STRING_CHAR,
@@ -230,6 +240,7 @@ uint32_t ble_dis_init(const ble_dis_init_t * p_dis_init)
return err_code;
}
}
+
if (p_dis_init->p_sys_id != NULL)
{
uint8_t encoded_sys_id[BLE_DIS_SYS_ID_LEN];
@@ -257,6 +268,8 @@ uint32_t ble_dis_init(const ble_dis_init_t * p_dis_init)
return err_code;
}
}
+#endif
+
if (p_dis_init->p_pnp_id != NULL)
{
uint8_t encoded_pnp_id[BLE_DIS_PNP_ID_LEN];
diff --git a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c
index 44465a3..748ccbc 100644
--- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c
+++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c
@@ -36,17 +36,6 @@
#include "tusb.h"
#endif
-#define APP_TIMER_PRESCALER 0
-
-#define IRQ_ENABLED 0x01 /**< Field identifying if an interrupt is enabled. */
-
-/**< Maximum number of interrupts available. (from IRQn_Type) */
-#if defined(NRF52832_XXAA)
- #define MAX_NUMBER_INTERRUPTS 39
-#elif defined(NRF52840_XXAA) || defined(NRF52833_XXAA)
- #define MAX_NUMBER_INTERRUPTS 48
-#endif
-
/**@brief Enumeration for specifying current bootloader status.
*/
typedef enum
@@ -118,7 +107,7 @@ static void wait_for_events(void)
// APP_ERROR_CHECK(err_code);
// Feed all Watchdog just in case application enable it
- // WDT cannot be disabled once started. It even last through soft reset (NVIC Reset)
+ // WDT cannot be disabled once started. It even last through NVIC soft reset
if ( nrf_wdt_started(NRF_WDT) )
{
for (uint8_t i=0; i<8; i++) nrf_wdt_reload_request_set(NRF_WDT, i);
@@ -147,37 +136,40 @@ static void wait_for_events(void)
}
-bool bootloader_app_is_valid(uint32_t app_addr)
+bool bootloader_app_is_valid(void)
{
- bootloader_settings_t const * p_bootloader_settings;
+ bool success = false;
+ uint32_t const app_addr = DFU_BANK_0_REGION_START;
- // There exists an application in CODE region 1.
- if (*((uint32_t *)app_addr) == EMPTY_FLASH_MASK)
+ bootloader_settings_t const *p_bootloader_settings;
+ bootloader_util_settings_get(&p_bootloader_settings);
+
+ enum { EMPTY_FLASH = 0xFFFFFFFFUL };
+
+ // Application is invalid if first 2 words are all 0xFFFFFFF
+ if ( *((uint32_t *)app_addr ) == EMPTY_FLASH &&
+ *((uint32_t *)(app_addr+4)) == EMPTY_FLASH )
+ {
+ return false;
+ }
+
+ // The application in CODE region 1 is flagged as valid during update.
+ if ( p_bootloader_settings->bank_0 == BANK_VALID_APP )
+ {
+ uint16_t image_crc = 0;
+
+ // A stored crc value of 0 indicates that CRC checking is not used.
+ if ( p_bootloader_settings->bank_0_crc != 0 )
{
- return false;
+ image_crc = crc16_compute((uint8_t*) app_addr,
+ p_bootloader_settings->bank_0_size,
+ NULL);
}
- bool success = false;
+ success = (image_crc == p_bootloader_settings->bank_0_crc);
+ }
- bootloader_util_settings_get(&p_bootloader_settings);
-
- // The application in CODE region 1 is flagged as valid during update.
- if (p_bootloader_settings->bank_0 == BANK_VALID_APP)
- {
- uint16_t image_crc = 0;
-
- // A stored crc value of 0 indicates that CRC checking is not used.
- if (p_bootloader_settings->bank_0_crc != 0)
- {
- image_crc = crc16_compute((uint8_t *)DFU_BANK_0_REGION_START,
- p_bootloader_settings->bank_0_size,
- NULL);
- }
-
- success = (image_crc == p_bootloader_settings->bank_0_crc);
- }
-
- return success;
+ return success;
}
@@ -351,49 +343,51 @@ uint32_t bootloader_dfu_start(bool ota, uint32_t timeout_ms)
return err_code;
}
-
-/**@brief Function for disabling all interrupts before jumping from bootloader to application.
- */
-static void interrupts_disable(void)
+void bootloader_app_start(void)
{
- uint32_t interrupt_setting_mask;
- uint32_t irq = 0; // We start from first interrupt, i.e. interrupt 0.
-
- // Fetch the current interrupt settings.
- interrupt_setting_mask = NVIC->ISER[0];
-
- for (; irq < MAX_NUMBER_INTERRUPTS; irq++)
- {
- if (interrupt_setting_mask & (IRQ_ENABLED << irq))
- {
- // The interrupt was enabled, and hence disable it.
- NVIC_DisableIRQ((IRQn_Type)irq);
- }
- }
-}
-
-
-void bootloader_app_start(uint32_t app_addr)
-{
- // If the applications CRC has been checked and passed, the magic number will be written and we
- // can start the application safely.
- APP_ERROR_CHECK ( sd_softdevice_disable() );
-
- interrupts_disable();
-
-#if 0 // may need set forward irq
- sd_mbr_command_t command =
- {
- .command = SD_MBR_COMMAND_IRQ_FORWARD_ADDRESS_SET,
- .params.irq_forward_address_set.address = MBR_SIZE,
- };
-
- sd_mbr_command(&command);
+ // 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
- APP_ERROR_CHECK( sd_softdevice_vector_table_base_set(CODE_REGION_1_START) );
+ uint32_t fwd_ret;
+ uint32_t app_addr;
- bootloader_util_app_start(CODE_REGION_1_START);
+ if ( is_sd_existed() )
+ {
+ PRINTF("SoftDevice exist\r\n");
+ // App starts after SoftDevice
+ app_addr = SD_SIZE_GET(MBR_SIZE);
+ fwd_ret = sd_softdevice_vector_table_base_set(app_addr);
+ }else
+ {
+ PRINTF("SoftDevice not exist\r\n");
+
+ // 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 )
+ {
+ PRINT_HEX(fwd_ret);
+
+ // MBR use first 4-bytes of SRAM to store foward address
+ *(uint32_t *)(0x20000000) = app_addr;
+ }
+
+ // jump to app
+ bootloader_util_app_start(app_addr);
}
diff --git a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.h b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.h
index 3a5fa42..9354ffe 100644
--- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.h
+++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.h
@@ -33,13 +33,10 @@
uint32_t bootloader_init(void);
/**@brief Function for validating application region in flash.
- *
- * @param[in] app_addr Address to the region in flash where the application is stored.
- *
* @retval true If Application region is valid.
* @retval false If Application region is not valid.
*/
-bool bootloader_app_is_valid(uint32_t app_addr);
+bool bootloader_app_is_valid(void);
/**@brief Function for starting the Device Firmware Update.
*
@@ -55,7 +52,7 @@ uint32_t bootloader_dfu_start(bool ota, uint32_t timeout_ms);
*
* @param[in] app_addr Address to the region where the application is stored.
*/
-void bootloader_app_start(uint32_t app_addr);
+void bootloader_app_start(void);
/**@brief Function for retrieving the bootloader settings.
*
@@ -92,6 +89,9 @@ uint32_t bootloader_dfu_sd_update_continue(void);
*/
uint32_t bootloader_dfu_sd_update_finalize(void);
+
+void bootloader_mbr_addrs_populate(void);
+
#endif // BOOTLOADER_H__
/**@} */
diff --git a/lib/sdk11/components/libraries/bootloader_dfu/bootloader_settings.c b/lib/sdk11/components/libraries/bootloader_dfu/bootloader_settings.c
index 439d7a0..c071020 100644
--- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader_settings.c
+++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader_settings.c
@@ -13,45 +13,23 @@
#include "bootloader_settings.h"
#include
#include
+#include "nrfx_nvmc.h"
-#if defined ( __CC_ARM )
+/**< This variable reserves a codepage for bootloader specific settings, to ensure the compiler doesn't locate any code or variables at his location. */
+__attribute__ ((section(".bootloaderSettings")))
+uint8_t m_boot_settings[CODE_PAGE_SIZE];
-uint8_t m_boot_settings[CODE_PAGE_SIZE] __attribute__((at(BOOTLOADER_SETTINGS_ADDRESS))) __attribute__((used)); /**< This variable reserves a codepage for bootloader specific settings, to ensure the compiler doesn't locate any code or variables at his location. */
-uint32_t m_uicr_bootloader_start_address __attribute__((at(NRF_UICR_BOOT_START_ADDRESS))) = BOOTLOADER_REGION_START; /**< This variable makes the linker script write the bootloader start address to the UICR register. This value will be written in the HEX file and thus written to UICR when the bootloader is flashed into the chip. */
+/**< This variable ensures that the linker script will write the bootloader start address to the UICR register. This value will be written in the HEX file and thus written to UICR when the bootloader is flashed into the chip. */
+ __attribute__ ((section(".uicrBootStartAddress")))
+volatile uint32_t m_uicr_bootloader_start_address = BOOTLOADER_REGION_START;
-#elif defined ( __GNUC__ )
-
-uint8_t m_boot_settings[CODE_PAGE_SIZE] __attribute__ ((section(".bootloaderSettings"))); /**< This variable reserves a codepage for bootloader specific settings, to ensure the compiler doesn't locate any code or variables at his location. */
-volatile uint32_t m_uicr_bootloader_start_address __attribute__ ((section(".uicrBootStartAddress"))) = BOOTLOADER_REGION_START; /**< This variable ensures that the linker script will write the bootloader start address to the UICR register. This value will be written in the HEX file and thus written to UICR when the bootloader is flashed into the chip. */
-
-#elif defined ( __ICCARM__ )
-
-__no_init uint8_t m_boot_settings[CODE_PAGE_SIZE] @ BOOTLOADER_SETTINGS_ADDRESS; /**< This variable reserves a codepage for bootloader specific settings, to ensure the compiler doesn't locate any code or variables at his location. */
-__root const uint32_t m_uicr_bootloader_start_address @ NRF_UICR_BOOT_START_ADDRESS = BOOTLOADER_REGION_START; /**< This variable ensures that the linker script will write the bootloader start address to the UICR register. This value will be written in the HEX file and thus written to UICR when the bootloader is flashed into the chip. */
-
-#endif
-
-#if defined(NRF52_SERIES)
-#if defined ( __CC_ARM )
-
-uint8_t m_mbr_params_page[CODE_PAGE_SIZE] __attribute__((at(BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS))) __attribute__((used)); /**< This variable reserves a codepage for mbr parameters, to ensure the compiler doesn't locate any code or variables at his location. */
-uint32_t m_uicr_mbr_params_page_address __attribute__((at(NRF_UICR_MBR_PARAMS_PAGE_ADDRESS)))
- = BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS; /**< This variable makes the linker script write the mbr parameters page address to the UICR register. This value will be written in the HEX file and thus written to the UICR when the bootloader is flashed into the chip */
-
-#elif defined (__GNUC__ )
-
-uint8_t m_mbr_params_page[CODE_PAGE_SIZE] __attribute__ ((section(".mbrParamsPage"))); /**< This variable reserves a codepage for mbr parameters, to ensure the compiler doesn't locate any code or variables at his location. */
-volatile uint32_t m_uicr_mbr_params_page_address __attribute__ ((section(".uicrMbrParamsPageAddress")))
- = BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS; /**< This variable makes the linker script write the mbr parameters page address to the UICR register. This value will be written in the HEX file and thus written to the UICR when the bootloader is flashed into the chip */
-
-#elif defined (__ICCARM__ )
-
-__no_init uint8_t m_mbr_params_page[CODE_PAGE_SIZE] @ BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS; /**< This variable reserves a codepage for bootloader specific settings, to ensure the compiler doesn't locate any code or variables at his location. */
-__root const uint32_t m_uicr_mbr_params_page_address @ NRF_UICR_MBR_PARAMS_PAGE_ADDRESS = BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS; /**< This variable ensures that the linker script will write the bootloader start address to the UICR register. This value will be written in the HEX file and thus written to UICR when the bootloader is flashed into the chip. */
-
-#endif
-#endif // NRF52_SERIES
+/**< This variable reserves a codepage for mbr parameters, to ensure the compiler doesn't locate any code or variables at his location. */
+ __attribute__ ((section(".mbrParamsPage")))
+uint8_t m_mbr_params_page[CODE_PAGE_SIZE];
+/**< This variable makes the linker script write the mbr parameters page address to the UICR register. This value will be written in the HEX file and thus written to the UICR when the bootloader is flashed into the chip */
+__attribute__ ((section(".uicrMbrParamsPageAddress")))
+volatile uint32_t m_uicr_mbr_params_page_address = BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS;
void bootloader_util_settings_get(const bootloader_settings_t ** pp_bootloader_settings)
{
@@ -61,3 +39,16 @@ void bootloader_util_settings_get(const bootloader_settings_t ** pp_bootloader_s
*pp_bootloader_settings = p_bootloader_settings;
}
+
+void bootloader_mbr_addrs_populate(void)
+{
+ if (*(const uint32_t *)MBR_BOOTLOADER_ADDR == 0xFFFFFFFF)
+ {
+ nrfx_nvmc_word_write(MBR_BOOTLOADER_ADDR, BOOTLOADER_REGION_START);
+ }
+
+ if (*(const uint32_t *)MBR_PARAM_PAGE_ADDR == 0xFFFFFFFF)
+ {
+ nrfx_nvmc_word_write(MBR_PARAM_PAGE_ADDR, BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS);
+ }
+}
diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_bank_internal.h b/lib/sdk11/components/libraries/bootloader_dfu/dfu_bank_internal.h
index 898264a..d4fda2a 100644
--- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_bank_internal.h
+++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_bank_internal.h
@@ -40,7 +40,6 @@ typedef enum
DFU_STATE_WAIT_4_ACTIVATE /**< State for: waiting for dfu_image_activate(). */
} dfu_state_t;
-#define APP_TIMER_PRESCALER 0 /**< Value of the RTC1 PRESCALER register. */
#define DFU_TIMEOUT_INTERVAL APP_TIMER_TICKS(300000) /**< DFU timeout interval in units of timer ticks. */
#define IS_UPDATING_SD(START_PKT) ((START_PKT).dfu_update_mode & DFU_UPDATE_SD) /**< Macro for determining if a SoftDevice update is ongoing. */
diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c b/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c
index 80d8293..1dbaf3b 100644
--- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c
+++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c
@@ -140,8 +140,7 @@ static void dfu_prepare_func_app_erase(uint32_t image_size)
if ( is_ota() )
{
- uint32_t err_code;
- err_code = pstorage_clear(&m_storage_handle_app, m_image_size);
+ uint32_t err_code = pstorage_clear(&m_storage_handle_app, m_image_size);
APP_ERROR_CHECK(err_code);
}
else
@@ -151,7 +150,9 @@ static void dfu_prepare_func_app_erase(uint32_t image_size)
for ( uint32_t i = 0; i < page_count; i++ )
{
- nrfx_nvmc_page_erase(DFU_BANK_0_REGION_START + i * CODE_PAGE_SIZE);
+ uint32_t const addr = DFU_BANK_0_REGION_START + i * CODE_PAGE_SIZE;
+ PRINTF("Erase 0x%08lX\r\n", addr);
+ nrfx_nvmc_page_erase(addr);
}
// invoke complete callback
diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c b/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c
index d731d31..3f253c4 100644
--- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c
+++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c
@@ -54,8 +54,6 @@ enum { BLE_CONN_CFG_HIGH_BANDWIDTH = 1 };
#define SLAVE_LATENCY 0 /**< Slave latency. */
#define CONN_SUP_TIMEOUT (4 * 100) /**< Connection supervisory timeout (4 seconds). */
-#define APP_TIMER_PRESCALER 0 /**< Value of the RTC1 PRESCALER register. */
-
#define APP_ADV_INTERVAL MSEC_TO_UNITS(25, UNIT_0_625_MS) /**< The advertising interval (25 ms.). */
#define APP_ADV_TIMEOUT BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED /**< The advertising timeout in units of seconds. This is set to @ref BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED so that the advertisement is done as long as there there is a call to @ref dfu_transport_close function.*/
#define APP_DIRECTED_ADV_TIMEOUT 50 /**< number of direct advertisement (each lasting 1.28seconds). */
@@ -738,7 +736,7 @@ static void on_ble_evt(ble_evt_t * p_ble_evt)
#ifdef CFG_DEBUG
extern const char* dbg_ble_event_str(uint16_t evt_id);
- ADALOG("BLE", dbg_ble_event_str(p_ble_evt->header.evt_id));
+ PRINTF("BLE %s\r\n", dbg_ble_event_str(p_ble_evt->header.evt_id));
#endif
switch (p_ble_evt->header.evt_id)
@@ -901,7 +899,7 @@ static void on_ble_evt(ble_evt_t * p_ble_evt)
case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST:
{
uint16_t att_mtu = MIN(p_ble_evt->evt.gatts_evt.params.exchange_mtu_request.client_rx_mtu, BLEGATT_ATT_MTU_MAX);
- ADALOG("GAP", "ATT MTU is changed to %d", att_mtu);
+ PRINTF("GAP ATT MTU is changed to %d\r\n", att_mtu);
APP_ERROR_CHECK( sd_ble_gatts_exchange_mtu_reply(m_conn_handle, att_mtu) );
}
break;
diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h b/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h
index 2ed7ba4..ecb8f98 100644
--- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h
+++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h
@@ -29,31 +29,38 @@
#include "nrf.h"
#include "app_util.h"
+#ifndef SD_MAGIC_NUMBER
+#define SD_MAGIC_NUMBER 0x51B1E5DB
+#endif
+
+static inline bool is_sd_existed(void)
+{
+ return *((uint32_t*)(SOFTDEVICE_INFO_STRUCT_ADDRESS+4)) == SD_MAGIC_NUMBER;
+}
+
#define NRF_UICR_BOOT_START_ADDRESS (NRF_UICR_BASE + 0x14) /**< Register where the bootloader start address is stored in the UICR register. */
#define NRF_UICR_MBR_PARAMS_PAGE_ADDRESS (NRF_UICR_BASE + 0x18) /**< Register where the mbr params page is stored in the UICR register. (Only in use in nRF52 MBR).*/
-#define CODE_REGION_1_START SD_SIZE_GET(MBR_SIZE) /**< This field should correspond to the size of Code Region 0, (which is identical to Start of Code Region 1), found in UICR.CLEN0 register. This value is used for compile safety, as the linker will fail if application expands into bootloader. Runtime, the bootloader will use the value found in UICR.CLEN0. */
+// Application address is either after MBR or SD (if existed)
+#define CODE_REGION_1_START (is_sd_existed() ? SD_SIZE_GET(MBR_SIZE) : MBR_SIZE) /**< This field should correspond to the size of Code Region 0, (which is identical to Start of Code Region 1), found in UICR.CLEN0 register. This value is used for compile safety, as the linker will fail if application expands into bootloader. Runtime, the bootloader will use the value found in UICR.CLEN0. */
+
#define SOFTDEVICE_REGION_START MBR_SIZE /**< This field should correspond to start address of the bootloader, found in UICR.RESERVED, 0x10001014, register. This value is used for sanity check, so the bootloader will fail immediately if this value differs from runtime value. The value is used to determine max application size for updating. */
#define CODE_PAGE_SIZE 0x1000 /**< Size of a flash codepage. Used for size of the reserved flash space in the bootloader region. Will be runtime checked against NRF_UICR->CODEPAGESIZE to ensure the region is correct. */
// Flash = 512 KB
#if defined(NRF52832_XXAA) || defined(NRF52833_XXAA)
-
-#define BOOTLOADER_REGION_START 0x00074000 /**< This field should correspond to start address of the bootloader, found in UICR.RESERVED, 0x10001014, register. This value is used for sanity check, so the bootloader will fail immediately if this value differs from runtime value. The value is used to determine max application size for updating. */
-#define BOOTLOADER_SETTINGS_ADDRESS 0x0007F000 /**< The field specifies the page location of the bootloader settings address. */
-#define BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS 0x0007E000 /**< The field specifies the page location of the mbr params page address. */
+ #define BOOTLOADER_REGION_START 0x00074000 /**< This field should correspond to start address of the bootloader, found in UICR.RESERVED, 0x10001014, register. This value is used for sanity check, so the bootloader will fail immediately if this value differs from runtime value. The value is used to determine max application size for updating. */
+ #define BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS 0x0007E000 /**< The field specifies the page location of the mbr params page address. */
+ #define BOOTLOADER_SETTINGS_ADDRESS 0x0007F000 /**< The field specifies the page location of the bootloader settings address. */
// Flash = 1024 KB
#elif defined(NRF52840_XXAA)
-
-#define BOOTLOADER_REGION_START 0x000F4000 /**< This field should correspond to start address of the bootloader, found in UICR.RESERVED, 0x10001014, register. This value is used for sanity check, so the bootloader will fail immediately if this value differs from runtime value. The value is used to determine max application size for updating. */
-#define BOOTLOADER_SETTINGS_ADDRESS 0x000FF000 /**< The field specifies the page location of the bootloader settings address. */
-#define BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS 0x000FE000 /**< The field specifies the page location of the mbr params page address. */
+ #define BOOTLOADER_REGION_START 0x000F4000 /**< This field should correspond to start address of the bootloader, found in UICR.RESERVED, 0x10001014, register. This value is used for sanity check, so the bootloader will fail immediately if this value differs from runtime value. The value is used to determine max application size for updating. */
+ #define BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS 0x000FE000 /**< The field specifies the page location of the mbr params page address. */
+ #define BOOTLOADER_SETTINGS_ADDRESS 0x000FF000 /**< The field specifies the page location of the bootloader settings address. */
#else
-
-#error No target defined
-
+ #error No target defined
#endif
#define DFU_REGION_TOTAL_SIZE (BOOTLOADER_REGION_START - CODE_REGION_1_START) /**< Total size of the region between SD and Bootloader. */
@@ -67,7 +74,7 @@
#define DFU_IMAGE_MAX_SIZE_BANKED (((DFU_IMAGE_MAX_SIZE_FULL) - \
(DFU_IMAGE_MAX_SIZE_FULL % (2 * CODE_PAGE_SIZE)))/2) /**< Maximum size of an application, excluding save data from the application. */
-#define DFU_BL_IMAGE_MAX_SIZE (BOOTLOADER_SETTINGS_ADDRESS - BOOTLOADER_REGION_START) /**< Maximum size of a bootloader, excluding save data from the current bootloader. */
+#define DFU_BL_IMAGE_MAX_SIZE (BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS - BOOTLOADER_REGION_START) /**< Maximum size of a bootloader, excluding save data from the current bootloader. */
#define DFU_BANK_0_REGION_START CODE_REGION_1_START /**< Bank 0 region start. */
#define DFU_BANK_1_REGION_START (DFU_BANK_0_REGION_START + DFU_IMAGE_MAX_SIZE_BANKED) /**< Bank 1 region start. */
@@ -131,7 +138,8 @@ typedef enum
DFU_UPDATE_BOOT_COMPLETE, /**< Status update complete.*/
DFU_BANK_0_ERASED, /**< Status bank 0 erased.*/
DFU_TIMEOUT, /**< Status timeout.*/
- DFU_RESET /**< Status Reset to indicate current update procedure has been aborted and system should reset. */
+ DFU_RESET, /**< Status Reset to indicate current update procedure has been aborted and system should reset. */
+ DFU_UF2_BOOTLOADER_COMPLETE
} dfu_update_status_code_t;
/**@brief Structure holding DFU complete event.
diff --git a/lib/softdevice/mbr/headers/nrf_mbr.h b/lib/softdevice/mbr/headers/nrf_mbr.h
new file mode 100644
index 0000000..389cc37
--- /dev/null
+++ b/lib/softdevice/mbr/headers/nrf_mbr.h
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2014 - 2017, 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.
+ */
+
+/**
+ @defgroup nrf_mbr_api Master Boot Record API
+ @{
+
+ @brief APIs for updating SoftDevice and BootLoader
+
+*/
+
+#ifndef NRF_MBR_H__
+#define NRF_MBR_H__
+
+#include "nrf_svc.h"
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @addtogroup NRF_MBR_DEFINES Defines
+ * @{ */
+
+/**@brief MBR SVC Base number. */
+#define MBR_SVC_BASE (0x18)
+
+/**@brief Page size in words. */
+#define MBR_PAGE_SIZE_IN_WORDS (1024)
+
+/** @brief The size that must be reserved for the MBR when a SoftDevice is written to flash.
+This is the offset where the first byte of the SoftDevice hex file is written. */
+#define MBR_SIZE (0x1000)
+
+/** @brief Location (in the flash memory) of the bootloader address. */
+#define MBR_BOOTLOADER_ADDR (0xFF8)
+
+/** @brief Location (in UICR) of the bootloader address. */
+#define MBR_UICR_BOOTLOADER_ADDR (&(NRF_UICR->NRFFW[0]))
+
+/** @brief Location (in the flash memory) of the address of the MBR parameter page. */
+#define MBR_PARAM_PAGE_ADDR (0xFFC)
+
+/** @brief Location (in UICR) of the address of the MBR parameter page. */
+#define MBR_UICR_PARAM_PAGE_ADDR (&(NRF_UICR->NRFFW[1]))
+
+
+/** @} */
+
+/** @addtogroup NRF_MBR_ENUMS Enumerations
+ * @{ */
+
+/**@brief nRF Master Boot Record API SVC numbers. */
+enum NRF_MBR_SVCS
+{
+ SD_MBR_COMMAND = MBR_SVC_BASE, /**< ::sd_mbr_command */
+};
+
+/**@brief Possible values for ::sd_mbr_command_t.command */
+enum NRF_MBR_COMMANDS
+{
+ SD_MBR_COMMAND_COPY_BL, /**< Copy a new BootLoader. @see ::sd_mbr_command_copy_bl_t*/
+ SD_MBR_COMMAND_COPY_SD, /**< Copy a new SoftDevice. @see ::sd_mbr_command_copy_sd_t*/
+ SD_MBR_COMMAND_INIT_SD, /**< Initialize forwarding interrupts to SD, and run reset function in SD. Does not require any parameters in ::sd_mbr_command_t params.*/
+ SD_MBR_COMMAND_COMPARE, /**< This command works like memcmp. @see ::sd_mbr_command_compare_t*/
+ SD_MBR_COMMAND_VECTOR_TABLE_BASE_SET, /**< Change the address the MBR starts after a reset. @see ::sd_mbr_command_vector_table_base_set_t*/
+ SD_MBR_COMMAND_RESERVED,
+ SD_MBR_COMMAND_IRQ_FORWARD_ADDRESS_SET, /**< Start forwarding all interrupts to this address. @see ::sd_mbr_command_irq_forward_address_set_t*/
+};
+
+/** @} */
+
+/** @addtogroup NRF_MBR_TYPES Types
+ * @{ */
+
+/**@brief This command copies part of a new SoftDevice
+ *
+ * The destination area is erased before copying.
+ * If dst is in the middle of a flash page, that whole flash page will be erased.
+ * If (dst+len) is in the middle of a flash page, that whole flash page will be erased.
+ *
+ * The user of this function is responsible for setting the BPROT registers.
+ *
+ * @retval ::NRF_SUCCESS indicates that the contents of the memory blocks where copied correctly.
+ * @retval ::NRF_ERROR_INTERNAL indicates that the contents of the memory blocks where not verified correctly after copying.
+ */
+typedef struct
+{
+ uint32_t *src; /**< Pointer to the source of data to be copied.*/
+ uint32_t *dst; /**< Pointer to the destination where the content is to be copied.*/
+ uint32_t len; /**< Number of 32 bit words to copy. Must be a multiple of @ref MBR_PAGE_SIZE_IN_WORDS words.*/
+} sd_mbr_command_copy_sd_t;
+
+
+/**@brief This command works like memcmp, but takes the length in words.
+ *
+ * @retval ::NRF_SUCCESS indicates that the contents of both memory blocks are equal.
+ * @retval ::NRF_ERROR_NULL indicates that the contents of the memory blocks are not equal.
+ */
+typedef struct
+{
+ uint32_t *ptr1; /**< Pointer to block of memory. */
+ uint32_t *ptr2; /**< Pointer to block of memory. */
+ uint32_t len; /**< Number of 32 bit words to compare.*/
+} sd_mbr_command_compare_t;
+
+
+/**@brief This command copies a new BootLoader.
+ *
+ * The MBR assumes that either @ref MBR_BOOTLOADER_ADDR or @ref MBR_UICR_BOOTLOADER_ADDR is set to
+ * the address where the bootloader will be copied. If both addresses are set, the MBR will prioritize
+ * @ref MBR_BOOTLOADER_ADDR.
+ *
+ * The bootloader destination is erased by this function.
+ * If (destination+bl_len) is in the middle of a flash page, that whole flash page will be erased.
+ *
+ * This command requires that @ref MBR_PARAM_PAGE_ADDR or @ref MBR_UICR_PARAM_PAGE_ADDR is set,
+ * see @ref sd_mbr_command.
+ *
+ * This command will use the flash protect peripheral (BPROT or ACL) to protect the flash that is
+ * not intended to be written.
+ *
+ * On success, this function will not return. It will start the new bootloader from reset-vector as normal.
+ *
+ * @retval ::NRF_ERROR_INTERNAL indicates an internal error that should not happen.
+ * @retval ::NRF_ERROR_FORBIDDEN if the bootloader address is not set.
+ * @retval ::NRF_ERROR_INVALID_LENGTH if parameters attempts to read or write outside flash area.
+ * @retval ::NRF_ERROR_NO_MEM No MBR parameter page is provided. See @ref sd_mbr_command.
+ */
+typedef struct
+{
+ uint32_t *bl_src; /**< Pointer to the source of the bootloader to be be copied.*/
+ uint32_t bl_len; /**< Number of 32 bit words to copy for BootLoader. */
+} sd_mbr_command_copy_bl_t;
+
+/**@brief Change the address the MBR starts after a reset
+ *
+ * Once this function has been called, this address is where the MBR will start to forward
+ * interrupts to after a reset.
+ *
+ * To restore default forwarding, this function should be called with @ref address set to 0. If a
+ * bootloader is present, interrupts will be forwarded to the bootloader. If not, interrupts will
+ * be forwarded to the SoftDevice.
+ *
+ * The location of a bootloader can be specified in @ref MBR_BOOTLOADER_ADDR or
+ * @ref MBR_UICR_BOOTLOADER_ADDR. If both addresses are set, the MBR will prioritize
+ * @ref MBR_BOOTLOADER_ADDR.
+ *
+ * This command requires that @ref MBR_PARAM_PAGE_ADDR or @ref MBR_UICR_PARAM_PAGE_ADDR is set,
+ * see @ref sd_mbr_command.
+ *
+ * On success, this function will not return. It will reset the device.
+ *
+ * @retval ::NRF_ERROR_INTERNAL indicates an internal error that should not happen.
+ * @retval ::NRF_ERROR_INVALID_ADDR if parameter address is outside of the flash size.
+ * @retval ::NRF_ERROR_NO_MEM No MBR parameter page is provided. See @ref sd_mbr_command.
+ */
+typedef struct
+{
+ uint32_t address; /**< The base address of the interrupt vector table for forwarded interrupts.*/
+} sd_mbr_command_vector_table_base_set_t;
+
+/**@brief Sets the base address of the interrupt vector table for interrupts forwarded from the MBR
+ *
+ * Unlike sd_mbr_command_vector_table_base_set_t, this function does not reset, and it does not
+ * change where the MBR starts after reset.
+ *
+ * @retval ::NRF_SUCCESS
+ */
+typedef struct
+{
+ uint32_t address; /**< The base address of the interrupt vector table for forwarded interrupts.*/
+} sd_mbr_command_irq_forward_address_set_t;
+
+/**@brief Input structure containing data used when calling ::sd_mbr_command
+ *
+ * Depending on what command value that is set, the corresponding params value type must also be
+ * set. See @ref NRF_MBR_COMMANDS for command types and corresponding params value type. If command
+ * @ref SD_MBR_COMMAND_INIT_SD is set, it is not necessary to set any values under params.
+ */
+typedef struct
+{
+ uint32_t command; /**< Type of command to be issued. See @ref NRF_MBR_COMMANDS. */
+ union
+ {
+ sd_mbr_command_copy_sd_t copy_sd; /**< Parameters for copy SoftDevice.*/
+ sd_mbr_command_compare_t compare; /**< Parameters for verify.*/
+ sd_mbr_command_copy_bl_t copy_bl; /**< Parameters for copy BootLoader. Requires parameter page. */
+ sd_mbr_command_vector_table_base_set_t base_set; /**< Parameters for vector table base set. Requires parameter page.*/
+ sd_mbr_command_irq_forward_address_set_t irq_forward_address_set; /**< Parameters for irq forward address set*/
+ } params; /**< Command parameters. */
+} sd_mbr_command_t;
+
+/** @} */
+
+/** @addtogroup NRF_MBR_FUNCTIONS Functions
+ * @{ */
+
+/**@brief Issue Master Boot Record commands
+ *
+ * Commands used when updating a SoftDevice and bootloader.
+ *
+ * The @ref SD_MBR_COMMAND_COPY_BL and @ref SD_MBR_COMMAND_VECTOR_TABLE_BASE_SET requires
+ * parameters to be retained by the MBR when resetting the IC. This is done in a separate flash
+ * page. The location of the flash page should be provided by the application in either
+ * @ref MBR_PARAM_PAGE_ADDR or @ref MBR_UICR_PARAM_PAGE_ADDR. If both addresses are set, the MBR
+ * will prioritize @ref MBR_PARAM_PAGE_ADDR. This page will be cleared by the MBR and is used to
+ * store the command before reset. When an address is specified, the page it refers to must not be
+ * used by the application. If no address is provided by the application, i.e. both
+ * @ref MBR_PARAM_PAGE_ADDR and @ref MBR_UICR_PARAM_PAGE_ADDR is 0xFFFFFFFF, MBR commands which use
+ * flash will be unavailable and return @ref NRF_ERROR_NO_MEM.
+ *
+ * @param[in] param Pointer to a struct describing the command.
+ *
+ * @note For a complete set of return values, see ::sd_mbr_command_copy_sd_t,
+ * ::sd_mbr_command_copy_bl_t, ::sd_mbr_command_compare_t,
+ * ::sd_mbr_command_vector_table_base_set_t, ::sd_mbr_command_irq_forward_address_set_t
+ *
+ * @retval ::NRF_ERROR_NO_MEM No MBR parameter page provided
+ * @retval ::NRF_ERROR_INVALID_PARAM if an invalid command is given.
+*/
+SVCALL(SD_MBR_COMMAND, uint32_t, sd_mbr_command(sd_mbr_command_t* param));
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+#endif // NRF_MBR_H__
+
+/**
+ @}
+*/
diff --git a/lib/softdevice/mbr/headers/nrf_svc.h b/lib/softdevice/mbr/headers/nrf_svc.h
new file mode 100644
index 0000000..231a54f
--- /dev/null
+++ b/lib/softdevice/mbr/headers/nrf_svc.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2012 - 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.
+ */
+
+#ifndef NRF_SVC__
+#define NRF_SVC__
+
+#include "stdint.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @brief Supervisor call declaration.
+ *
+ * A call to a function marked with @ref SVCALL, will trigger a Supervisor Call (SVC) Exception.
+ * The SVCs with SVC numbers 0x00-0x0F are forwared to the application. All other SVCs are handled by the SoftDevice.
+ *
+ * @param[in] number The SVC number to be used.
+ * @param[in] return_type The return type of the SVC function.
+ * @param[in] signature Function signature. The function can have at most four arguments.
+ */
+
+#ifdef SVCALL_AS_NORMAL_FUNCTION
+#define SVCALL(number, return_type, signature) return_type signature
+#else
+
+#ifndef SVCALL
+#if defined (__CC_ARM)
+#define SVCALL(number, return_type, signature) return_type __svc(number) signature
+#elif defined (__GNUC__)
+#ifdef __cplusplus
+#define GCC_CAST_CPP (uint16_t)
+#else
+#define GCC_CAST_CPP
+#endif
+#define SVCALL(number, return_type, signature) \
+ _Pragma("GCC diagnostic push") \
+ _Pragma("GCC diagnostic ignored \"-Wreturn-type\"") \
+ __attribute__((naked)) \
+ __attribute__((unused)) \
+ static return_type signature \
+ { \
+ __asm( \
+ "svc %0\n" \
+ "bx r14" : : "I" (GCC_CAST_CPP number) : "r0" \
+ ); \
+ } \
+ _Pragma("GCC diagnostic pop")
+
+#elif defined (__ICCARM__)
+#define PRAGMA(x) _Pragma(#x)
+#define SVCALL(number, return_type, signature) \
+PRAGMA(swi_number = (number)) \
+ __swi return_type signature;
+#else
+#define SVCALL(number, return_type, signature) return_type signature
+#endif
+#endif // SVCALL
+
+#endif // SVCALL_AS_NORMAL_FUNCTION
+
+#ifdef __cplusplus
+}
+#endif
+#endif // NRF_SVC__
diff --git a/lib/softdevice/mbr/hex/mbr_nrf52_2.4.1_licence-agreement.txt b/lib/softdevice/mbr/hex/mbr_nrf52_2.4.1_licence-agreement.txt
new file mode 100644
index 0000000..2308432
--- /dev/null
+++ b/lib/softdevice/mbr/hex/mbr_nrf52_2.4.1_licence-agreement.txt
@@ -0,0 +1,35 @@
+Copyright (c) 2007 - 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.
diff --git a/lib/softdevice/mbr/hex/mbr_nrf52_2.4.1_mbr.hex b/lib/softdevice/mbr/hex/mbr_nrf52_2.4.1_mbr.hex
new file mode 100644
index 0000000..ab97f54
--- /dev/null
+++ b/lib/softdevice/mbr/hex/mbr_nrf52_2.4.1_mbr.hex
@@ -0,0 +1,179 @@
+:020000040000FA
+:1000000000040020810A000015070000610A0000BA
+:100010001F07000029070000330700000000000050
+:10002000000000000000000000000000A50A000021
+:100030003D070000000000004707000051070000D6
+:100040005B070000650700006F07000079070000EC
+:10005000830700008D07000097070000A10700003C
+:10006000AB070000B5070000BF070000C90700008C
+:10007000D3070000DD070000E7070000F1070000DC
+:10008000FB070000050800000F0800001908000029
+:10009000230800002D080000370800004108000078
+:1000A0004B080000550800005F08000069080000C8
+:1000B000730800007D080000870800009108000018
+:1000C0009B080000A5080000AF080000B908000068
+:1000D000C3080000CD080000D7080000E1080000B8
+:1000E000EB080000F5080000FF0800000909000007
+:1000F000130900001D090000270900003109000054
+:100100003B0900001FB500F003F88DE80F001FBD8C
+:1001100000F0ACBC40F6FC7108684FF01022401CA7
+:1001200008D00868401C09D00868401C04D0086842
+:1001300000F037BA9069F5E79069F9E7704770B554
+:100140000B46010B184400F6FF70040B4FF0805073
+:100150000022090303692403406943431D1B104621
+:1001600000F048FA29462046BDE8704000F042BA47
+:10017000F0B54FF6FF734FF4B4751A466E1E11E0DA
+:10018000A94201D3344600E00C46091B30F8027B3B
+:10019000641E3B441A44F9D19CB204EB134394B25D
+:1001A00004EB12420029EBD198B200EB134002EBB2
+:1001B000124140EA0140F0BDF34992B00446D1E952
+:1001C0000001CDE91001FF224021684600F0F4FB58
+:1001D00094E80F008DE80F00684610A902E004C8FB
+:1001E00041F8042D8842FAD110216846FFF7C0FF7C
+:1001F0001090AA208DF8440000F099F9FFF78AFFCB
+:1002000040F6FC7420684FF01025401C0FD0206889
+:1002100010226946803000F078F92068401C08D030
+:100220002068082210A900F070F900F061F9A869AF
+:10023000EEE7A869F5E74FF080500369406940F6A2
+:10024000FC71434308684FF01022401C06D0086838
+:1002500000F58050834203D2092070479069F7E788
+:100260000868401C04D00868401C03D00020704778
+:100270009069F9E70420704770B504460068C34DE3
+:10028000072876D2DFE800F033041929631E250021
+:10029000D4E9026564682946304600F062F92A46CE
+:1002A0002146304600F031F9AA002146304600F0E0
+:1002B00057FB002800D0032070BD00F009FC4FF46C
+:1002C000805007E0201D00F040F90028F4D100F034
+:1002D000FFFB60682860002070BD241D94E80700C3
+:1002E000920000F03DFB0028F6D00E2070BDFFF715
+:1002F000A2FF0028FAD1D4E901034FF0805100EBAE
+:10030000830208694D69684382420ED840F6F8704E
+:1003100005684FF010226D1C09D0056805EB8305B8
+:100320000B6949694B439D4203D9092070BD55694A
+:10033000F4E70168491C03D00068401C02D003E0C8
+:100340005069FAE70F2070BD2046FFF735FFFFF731
+:1003500072FF0028F7D1201D00F0F7F80028F2D135
+:1003600060680028F0D100F0E2F8FFF7D3FE00F05B
+:10037000BFF8072070BD10B50C46182802D0012028
+:10038000086010BD2068FFF777FF206010BD41684E
+:10039000054609B1012700E0002740F6F8742068FF
+:1003A0004FF01026401C2BD02068AA68920000F065
+:1003B000D7FA38B3A86881002068401C27D020688D
+:1003C000FFF7BDFED7B12068401C22D026684FF051
+:1003D0008050AC686D68016942695143A9420DD9EA
+:1003E000016940694143A14208D92146304600F0E5
+:1003F000B8F822462946304600F087F800F078F831
+:100400007069D2E700F093F8FFF784FEF6E77069B1
+:10041000D6E77669DBE740F6FC7420684FF01026DB
+:10042000401C23D02068401C0CD02068401C1FD0EA
+:100430002568206805F18005401C1BD027683879A5
+:10044000AA2819D040F6F8700168491C42D001680A
+:10045000491C45D00168491C3ED001680968491C07
+:100460003ED00168491C39D000683EE0B069DAE747
+:10047000B569DEE7B769E2E710212846FFF778FEA5
+:100480003968814222D12068401C05D0D4F8001080
+:1004900001F18002C03107E0B169F9E730B108CA63
+:1004A00051F8040D984201D1012000E000208A4259
+:1004B000F4D158B1286810B1042803D0FEE72846CB
+:1004C000FFF765FF3149686808600EE0FFF722FE1C
+:1004D00000F00EF87169BBE77169BFE7706904E06D
+:1004E0004FF480500168491C01D000F0CBFAFEE7C0
+:1004F000BFF34F8F26480168264A01F4E06111439B
+:100500000160BFF34F8F00BFFDE72DE9F0411746B3
+:100510000D460646002406E03046296800F054F8EF
+:10052000641C2D1D361DBC42F6D3BDE8F08140F69B
+:10053000FC700168491C04D0D0F800004FF48051D1
+:10054000FDE54FF010208069F8E74FF080510A690F
+:10055000496900684A43824201D810207047002050
+:10056000704770B50C4605464FF4806608E0284693
+:1005700000F017F8B44205D3A4F5806405F5805562
+:10058000002CF4D170BD0000F40A0000000000202F
+:100590000CED00E00400FA05144801680029FCD0C5
+:1005A0007047134A0221116010490B68002BFCD0E0
+:1005B0000F4B1B1D186008680028FCD0002010603D
+:1005C00008680028FCD07047094B10B501221A605A
+:1005D000064A1468002CFCD0016010680028FCD08A
+:1005E0000020186010680028FCD010BD00E4014015
+:1005F00004E5014070B50C46054600F073F810B9EB
+:1006000000F07EF828B121462846BDE8704000F091
+:1006100007B821462846BDE8704000F037B8000012
+:100620007FB5002200920192029203920A0B000B06
+:100630006946012302440AE0440900F01F0651F80C
+:10064000245003FA06F6354341F82450401C8242F8
+:10065000F2D80D490868009A10430860081D016827
+:10066000019A1143016000F03DF800280AD00649C4
+:1006700010310868029A10430860091D0868039A3F
+:10068000104308607FBD00000006004030B50F4CED
+:10069000002200BF04EB0213D3F800582DB9D3F8A1
+:1006A000045815B9D3F808581DB1521C082AF1D3C3
+:1006B00030BD082AFCD204EB0212C2F80008C3F8CD
+:1006C00004180220C3F8080830BD000000E0014013
+:1006D0004FF08050D0F83001082801D0002070473A
+:1006E000012070474FF08050D0F83011062905D016
+:1006F000D0F83001401C01D0002070470120704725
+:100700004FF08050D0F830010A2801D00020704707
+:100710000120704708208F490968095808471020B0
+:100720008C4909680958084714208A4909680958FA
+:100730000847182087490968095808473020854923
+:100740000968095808473820824909680958084744
+:100750003C20804909680958084740207D490968BC
+:100760000958084744207B49096809580847482028
+:1007700078490968095808474C207649096809589A
+:10078000084750207349096809580847542071499F
+:1007900009680958084758206E49096809580847E8
+:1007A0005C206C4909680958084760206949096854
+:1007B00009580847642067490968095808476820AC
+:1007C00064490968095808476C2062490968095852
+:1007D000084770205F4909680958084774205D4937
+:1007E00009680958084778205A490968095808478C
+:1007F0007C205849096809580847802055490968EC
+:10080000095808478420534909680958084788202F
+:1008100050490968095808478C204E490968095809
+:10082000084790204B4909680958084794204949CE
+:10083000096809580847982046490968095808472F
+:100840009C204449096809580847A0204149096883
+:1008500009580847A4203F49096809580847A820B3
+:100860003C49096809580847AC203A4909680958C1
+:100870000847B0203749096809580847B420354966
+:10088000096809580847B8203249096809580847D3
+:10089000BC203049096809580847C0202D4909681B
+:1008A00009580847C4202B49096809580847C82037
+:1008B0002849096809580847CC2026490968095879
+:1008C0000847D0202349096809580847D4202149FE
+:1008D000096809580847D8201E4909680958084777
+:1008E000DC201C49096809580847E02019490968B3
+:1008F00009580847E4201749096809580847E820BB
+:100900001449096809580847EC2012490968095830
+:100910000847F0200F49096809580847F4200D4995
+:10092000096809580847F8200A490968095808471A
+:10093000FC2008490968095808475FF48070054998
+:10094000096809580847000003480449024A034B54
+:100950007047000000000020000B0000000B0000AA
+:1009600040EA010310B59B070FD1042A0DD310C82C
+:1009700008C9121F9C42F8D020BA19BA884201D97E
+:10098000012010BD4FF0FF3010BD1AB1D30703D0C6
+:10099000521C07E0002010BD10F8013B11F8014B7C
+:1009A0001B1B07D110F8013B11F8014B1B1B01D198
+:1009B000921EF1D1184610BD02F0FF0343EA032254
+:1009C00042EA024200F005B87047704770474FF0A6
+:1009D00000020429C0F0128010F0030C00F01B800C
+:1009E000CCF1040CBCF1020F18BF00F8012BA8BF1A
+:1009F00020F8022BA1EB0C0100F00DB85FEAC17CDE
+:100A000024BF00F8012B00F8012B48BF00F8012B90
+:100A100070474FF0000200B51346944696462039C1
+:100A200022BFA0E80C50A0E80C50B1F12001BFF4A7
+:100A3000F7AF090728BFA0E80C5048BF0CC05DF80D
+:100A400004EB890028BF40F8042B08BF704748BF5B
+:100A500020F8022B11F0804F18BF00F8012B7047CF
+:100A6000014B1B68DB6818470000002009480A4951
+:100A70007047FFF7FBFFFFF745FB00BD20BFFDE719
+:100A8000064B1847064A1060016881F308884068E1
+:100A900000470000000B0000000B000017040000DE
+:100AA000000000201EF0040F0CBFEFF30881EFF3ED
+:100AB0000981886902380078182803D100E0000015
+:100AC000074A1047074A12682C3212681047000084
+:100AD00000B5054B1B68054A9B58984700BD0000B0
+:100AE0007703000000000020F00A0000040000006E
+:100AF000001000000000000000FFFFFF0090D00386
+:0400000500000A816C
+:00000001FF
diff --git a/lib/tinyusb b/lib/tinyusb
index f2b761f..4e6aa0d 160000
--- a/lib/tinyusb
+++ b/lib/tinyusb
@@ -1 +1 @@
-Subproject commit f2b761fee98cf9d09500e2475861e51c6ee58e61
+Subproject commit 4e6aa0d81d2dbd23006d5a961938f6478049467a
diff --git a/lib/uf2 b/lib/uf2
new file mode 160000
index 0000000..adbb8c7
--- /dev/null
+++ b/lib/uf2
@@ -0,0 +1 @@
+Subproject commit adbb8c7260f938e810eb37f2287f8e1a055ff402
diff --git a/linker/nrf52_s132_v6.ld b/linker/nrf52.ld
similarity index 93%
rename from linker/nrf52_s132_v6.ld
rename to linker/nrf52.ld
index db8d06b..756e490 100644
--- a/linker/nrf52_s132_v6.ld
+++ b/linker/nrf52.ld
@@ -28,7 +28,7 @@ MEMORY
DBL_RESET (rwx) : ORIGIN = 0x20007F7C, LENGTH = 0x04
/** Location of non initialized RAM. Non initialized RAM is used for exchanging bond information
- * from application to bootloader when using buttonluss DFU OTA. */
+ * from application to bootloader when using buttonless DFU OTA. */
NOINIT (rwx) : ORIGIN = 0x20007F80, LENGTH = 0x80
diff --git a/linker/nrf52833_s140_v6.ld b/linker/nrf52833.ld
similarity index 94%
rename from linker/nrf52833_s140_v6.ld
rename to linker/nrf52833.ld
index d665d8a..46a23dc 100644
--- a/linker/nrf52833_s140_v6.ld
+++ b/linker/nrf52833.ld
@@ -29,7 +29,7 @@ MEMORY
DBL_RESET (rwx) : ORIGIN = 0x20007F7C, LENGTH = 0x04
/** Location of non initialized RAM. Non initialized RAM is used for exchanging bond information
- * from application to bootloader when using buttonluss DFU OTA. */
+ * from application to bootloader when using buttonless DFU OTA. */
NOINIT (rwx) : ORIGIN = 0x20007F80, LENGTH = 0x80
diff --git a/linker/nrf52840_s140_v6.ld b/linker/nrf52840.ld
similarity index 94%
rename from linker/nrf52840_s140_v6.ld
rename to linker/nrf52840.ld
index 3358c98..fcfa425 100644
--- a/linker/nrf52840_s140_v6.ld
+++ b/linker/nrf52840.ld
@@ -31,7 +31,7 @@ MEMORY
DBL_RESET (rwx) : ORIGIN = 0x20007F7C, LENGTH = 0x04
/** Location of non initialized RAM. Non initialized RAM is used for exchanging bond information
- * from application to bootloader when using buttonluss DFU OTA. */
+ * from application to bootloader when using buttonless DFU OTA. */
NOINIT (rwx) : ORIGIN = 0x20007F80, LENGTH = 0x80
diff --git a/segger/Adafruit_nRF52_Bootloader.emProject b/segger/Adafruit_nRF52_Bootloader.emProject
index d5e8133..8084a4d 100644
--- a/segger/Adafruit_nRF52_Bootloader.emProject
+++ b/segger/Adafruit_nRF52_Bootloader.emProject
@@ -19,13 +19,16 @@
arm_target_device_name="nRF52840_xxAA"
arm_target_interface_type="SWD"
build_treat_warnings_as_errors="Yes"
- c_preprocessor_definitions="__nRF_FAMILY;ARM_MATH_CM4;FLASH_PLACEMENT=1;NO_VTOR_CONFIG;MK_BOOTLOADER_VERSION=0x00020A;CONFIG_GPIO_AS_PINRESET;CONFIG_NFCT_PINS_AS_GPIOS;SOFTDEVICE_PRESENT;CFG_TUSB_DEBUG=2;UF2_VERSION="Segger";BLEDIS_FW_VERSION="Segger""
+ c_preprocessor_definitions="__nRF_FAMILY;ARM_MATH_CM4;FLASH_PLACEMENT=1;NO_VTOR_CONFIG;MK_BOOTLOADER_VERSION=0x00020A;CONFIG_GPIO_AS_PINRESET;CONFIG_NFCT_PINS_AS_GPIOS;SOFTDEVICE_PRESENT;UF2_VERSION="Segger";BLEDIS_FW_VERSION="Segger";DFU_APP_DATA_RESERVED=7*4096;CFG_DEBUG"
c_user_include_directories=".;../src/;../src/usb;../src/boards;../src/cmsis/include;$(tusbDir);$(nrfxDir);$(nrfxDir)/mdk;$(nrfxDir)/hal;$(nrfxDir)/drivers/include;$(nrfxDir)/drivers/src;$(sdDir)/include;$(sdDir)/include/nrf52;$(sdk11Dir)/drivers_nrf/pstorage;$(sdk11Dir)/ble/common/;$(sdk11Dir)/ble/ble_services/ble_dfu;$(sdk11Dir)/ble/ble_services/ble_dis;$(sdk11Dir)/libraries/bootloader_dfu;$(sdk11Dir)/libraries/bootloader_dfu/hci_transport;$(sdk11Dir)/libraries/util;$(sdkDir)/toolchain/cmsis/include;$(sdkDir)/device;$(sdkDir)/toolchain;$(sdkDir)/drivers_nrf/hal;$(sdkDir)/drivers_nrf/systick;$(sdkDir)/drivers_nrf/uart;$(sdkDir)/drivers_nrf/usbd;$(sdkDir)/drivers_nrf/common;$(sdkDir)/drivers_nrf/delay;$(sdkDir)/drivers_nrf/power;$(sdkDir)/drivers_nrf/clock;$(sdkDir)/libraries/util;$(sdkDir)/libraries/timer;$(sdkDir)/libraries/scheduler;$(sdkDir)/libraries/crc16;$(sdkDir)/libraries/util;$(sdkDir)/libraries/hci/config;$(sdkDir)/libraries/uart;$(sdkDir)/libraries/hci;$(sdkDir)/external/fprintf;$(sdkDir)/libraries/strerror;$(sdkDir)/libraries/atomic;$(sdkDir)/libraries/balloc;$(sdkDir)/libraries/experimental_log/src;$(sdkDir)/libraries/experimental_log;$(sdkDir)/libraries/experimental_section_vars;$(sdkDir)/libraries/experimental_memobj"
+ debug_initial_breakpoint_set_option="Never"
debug_register_definition_file="$(ProjectDir)/nrf52840_Registers.xml"
debug_target_connection="J-Link"
gcc_enable_all_warnings="No"
gcc_entry_point="Reset_Handler"
+ gcc_optimization_level="Debug"
linker_memory_map_file="$(ProjectDir)/nRF52840_xxAA_MemoryMap.xml"
+ linker_printf_width_precision_supported="Yes"
linker_section_placement_file="$(ProjectDir)/flash_placement.xml"
macros="DeviceHeaderFile=$(PackagesDir)/nRF/CMSIS/Device/Include/nrf.h;DeviceLibraryIdentifier=M4lf;DeviceSystemFile=$(PackagesDir)/nRF/CMSIS/Device/Source/system_nrf52840.c;DeviceVectorsFile=$(PackagesDir)/nRF/Source/ses_nrf52840_Vectors.s;DeviceFamily=nRF;Target=nRF52840_xxAA;Placement=Flash;sdkDir=../lib/sdk/components;sdk11Dir=../lib/sdk11/components;sdDir=../lib/softdevice/s140_nrf52_6.1.1/s140_nrf52_6.1.1_API;tusbDir=../lib/tinyusb/src;nrfxDir=../lib/nrfx"
project_directory=""
@@ -50,58 +53,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -377,14 +326,38 @@
c_user_include_directories="../src/boards/feather_nrf52832"
gcc_optimization_level="Debug"
linker_memory_map_file="nRF52832_xxAA_MemoryMap.xml" />
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
diff --git a/src/boards/aramcon_badge_2019/pinconfig.c b/src/boards/aramcon_badge_2019/pinconfig.c
new file mode 100644
index 0000000..a983e4a
--- /dev/null
+++ b/src/boards/aramcon_badge_2019/pinconfig.c
@@ -0,0 +1,19 @@
+#include "boards.h"
+#include "uf2/configkeys.h"
+
+__attribute__((used, section(".bootloaderConfig")))
+const uint32_t bootloaderConfig[] =
+{
+ /* CF2 START */
+ CFG_MAGIC0, CFG_MAGIC1, // magic
+ 5, 100, // used entries, total entries
+
+ 204, 0x100000, // FLASH_BYTES = 0x100000
+ 205, 0x40000, // RAM_BYTES = 0x40000
+ 208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2
+ 209, 0xada52840, // UF2_FAMILY = 0xada52840
+ 210, 0x20, // PINS_PORT_SIZE = PA_32
+
+ 0, 0, 0, 0, 0, 0, 0, 0
+ /* CF2 END */
+};
diff --git a/src/boards/arduino_nano_33_ble/pinconfig.c b/src/boards/arduino_nano_33_ble/pinconfig.c
new file mode 100644
index 0000000..a983e4a
--- /dev/null
+++ b/src/boards/arduino_nano_33_ble/pinconfig.c
@@ -0,0 +1,19 @@
+#include "boards.h"
+#include "uf2/configkeys.h"
+
+__attribute__((used, section(".bootloaderConfig")))
+const uint32_t bootloaderConfig[] =
+{
+ /* CF2 START */
+ CFG_MAGIC0, CFG_MAGIC1, // magic
+ 5, 100, // used entries, total entries
+
+ 204, 0x100000, // FLASH_BYTES = 0x100000
+ 205, 0x40000, // RAM_BYTES = 0x40000
+ 208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2
+ 209, 0xada52840, // UF2_FAMILY = 0xada52840
+ 210, 0x20, // PINS_PORT_SIZE = PA_32
+
+ 0, 0, 0, 0, 0, 0, 0, 0
+ /* CF2 END */
+};
diff --git a/src/boards.c b/src/boards/boards.c
similarity index 98%
rename from src/boards.c
rename to src/boards/boards.c
index b4d7ede..e1ab96d 100644
--- a/src/boards.c
+++ b/src/boards/boards.c
@@ -132,11 +132,6 @@ void SysTick_Handler(void)
}
-uint32_t tusb_hal_millis(void)
-{
- return ( ( ((uint64_t)app_timer_cnt_get())*1000*(APP_TIMER_CONFIG_RTC_FREQUENCY+1)) / APP_TIMER_CLOCK_FREQ );
-}
-
void pwm_teardown(NRF_PWM_Type* pwm )
{
pwm->TASKS_SEQSTART[0] = 0;
diff --git a/src/boards.h b/src/boards/boards.h
similarity index 87%
rename from src/boards.h
rename to src/boards/boards.h
index 595f232..edc7666 100644
--- a/src/boards.h
+++ b/src/boards/boards.h
@@ -33,6 +33,10 @@
#include "board.h"
+#ifndef UF2_VOLUME_LABEL
+#define UF2_VOLUME_LABEL "NRF52BOOT "
+#endif
+
#ifndef BUTTON_DFU
#define BUTTON_DFU BUTTON_1
#endif
@@ -105,18 +109,17 @@ bool is_ota(void);
//--------------------------------------------------------------------+
// DEBUG
//--------------------------------------------------------------------+
-//#define CFG_DEBUG
#ifdef CFG_DEBUG
#include
+#define PRINTF printf
#define PRINT_LOCATION() printf("%s: %d:\n", __PRETTY_FUNCTION__, __LINE__)
#define PRINT_MESS(x) printf("%s: %d: %s \n" , __FUNCTION__, __LINE__, (char*)(x))
-#define PRTNT_HEAP() if (CFG_DEBUG == 3) printf("\n%s: %d: Heap free: %d\n", __FUNCTION__, __LINE__, util_heap_get_free_size())
#define PRINT_STR(x) printf("%s: %d: " #x " = %s\n" , __FUNCTION__, __LINE__, (char*)(x) )
#define PRINT_INT(x) printf("%s: %d: " #x " = %ld\n" , __FUNCTION__, __LINE__, (uint32_t) (x) )
-#define PRINT_HEX(x) printf("%s: %d: " #x " = 0x%X\n" , __FUNCTION__, __LINE__, (uint32_t) (x) )
+#define PRINT_HEX(x) printf("%s: %d: " #x " = 0x%lX\n" , __FUNCTION__, __LINE__, (uint32_t) (x) )
#define PRINT_BUFFER(buf, n) \
do {\
@@ -126,25 +129,16 @@ bool is_ota(void);
printf("\n");\
}while(0)
-#define ADALOG(tag, ...) \
- do { \
- if ( tag ) printf("[%s] ", tag);\
- printf(__VA_ARGS__);\
- printf("\n");\
- }while(0)
-
#else
+#define PRINTF(...)
#define PRINT_LOCATION()
#define PRINT_MESS(x)
-#define PRTNT_HEAP()
#define PRINT_STR(x)
#define PRINT_INT(x)
#define PRINT_HEX(x)
#define PRINT_BUFFER(buf, n)
-#define ADALOG(...)
-
#endif
diff --git a/src/boards/circuitplayground_nrf52840/pinconfig.c b/src/boards/circuitplayground_nrf52840/pinconfig.c
new file mode 100644
index 0000000..a983e4a
--- /dev/null
+++ b/src/boards/circuitplayground_nrf52840/pinconfig.c
@@ -0,0 +1,19 @@
+#include "boards.h"
+#include "uf2/configkeys.h"
+
+__attribute__((used, section(".bootloaderConfig")))
+const uint32_t bootloaderConfig[] =
+{
+ /* CF2 START */
+ CFG_MAGIC0, CFG_MAGIC1, // magic
+ 5, 100, // used entries, total entries
+
+ 204, 0x100000, // FLASH_BYTES = 0x100000
+ 205, 0x40000, // RAM_BYTES = 0x40000
+ 208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2
+ 209, 0xada52840, // UF2_FAMILY = 0xada52840
+ 210, 0x20, // PINS_PORT_SIZE = PA_32
+
+ 0, 0, 0, 0, 0, 0, 0, 0
+ /* CF2 END */
+};
diff --git a/src/boards/clue_nrf52840/pinconfig.c b/src/boards/clue_nrf52840/pinconfig.c
new file mode 100644
index 0000000..a983e4a
--- /dev/null
+++ b/src/boards/clue_nrf52840/pinconfig.c
@@ -0,0 +1,19 @@
+#include "boards.h"
+#include "uf2/configkeys.h"
+
+__attribute__((used, section(".bootloaderConfig")))
+const uint32_t bootloaderConfig[] =
+{
+ /* CF2 START */
+ CFG_MAGIC0, CFG_MAGIC1, // magic
+ 5, 100, // used entries, total entries
+
+ 204, 0x100000, // FLASH_BYTES = 0x100000
+ 205, 0x40000, // RAM_BYTES = 0x40000
+ 208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2
+ 209, 0xada52840, // UF2_FAMILY = 0xada52840
+ 210, 0x20, // PINS_PORT_SIZE = PA_32
+
+ 0, 0, 0, 0, 0, 0, 0, 0
+ /* CF2 END */
+};
diff --git a/src/boards/electronut_labs_papyr/pinconfig.c b/src/boards/electronut_labs_papyr/pinconfig.c
new file mode 100644
index 0000000..a983e4a
--- /dev/null
+++ b/src/boards/electronut_labs_papyr/pinconfig.c
@@ -0,0 +1,19 @@
+#include "boards.h"
+#include "uf2/configkeys.h"
+
+__attribute__((used, section(".bootloaderConfig")))
+const uint32_t bootloaderConfig[] =
+{
+ /* CF2 START */
+ CFG_MAGIC0, CFG_MAGIC1, // magic
+ 5, 100, // used entries, total entries
+
+ 204, 0x100000, // FLASH_BYTES = 0x100000
+ 205, 0x40000, // RAM_BYTES = 0x40000
+ 208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2
+ 209, 0xada52840, // UF2_FAMILY = 0xada52840
+ 210, 0x20, // PINS_PORT_SIZE = PA_32
+
+ 0, 0, 0, 0, 0, 0, 0, 0
+ /* CF2 END */
+};
diff --git a/src/boards/feather_nrf52840_express/board.h b/src/boards/feather_nrf52840_express/board.h
index ca2527d..2477ea4 100644
--- a/src/boards/feather_nrf52840_express/board.h
+++ b/src/boards/feather_nrf52840_express/board.h
@@ -47,15 +47,6 @@
#define BUTTON_2 _PINNUM(0, 10)
#define BUTTON_PULL NRF_GPIO_PIN_PULLUP
-/*------------------------------------------------------------------*/
-/* UART (only used by nRF52832)
- *------------------------------------------------------------------*/
-#define RX_PIN_NUMBER 8
-#define TX_PIN_NUMBER 6
-#define CTS_PIN_NUMBER 0
-#define RTS_PIN_NUMBER 0
-#define HWFC false
-
//--------------------------------------------------------------------+
// BLE OTA
//--------------------------------------------------------------------+
diff --git a/src/boards/feather_nrf52840_express/pinconfig.c b/src/boards/feather_nrf52840_express/pinconfig.c
new file mode 100644
index 0000000..a983e4a
--- /dev/null
+++ b/src/boards/feather_nrf52840_express/pinconfig.c
@@ -0,0 +1,19 @@
+#include "boards.h"
+#include "uf2/configkeys.h"
+
+__attribute__((used, section(".bootloaderConfig")))
+const uint32_t bootloaderConfig[] =
+{
+ /* CF2 START */
+ CFG_MAGIC0, CFG_MAGIC1, // magic
+ 5, 100, // used entries, total entries
+
+ 204, 0x100000, // FLASH_BYTES = 0x100000
+ 205, 0x40000, // RAM_BYTES = 0x40000
+ 208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2
+ 209, 0xada52840, // UF2_FAMILY = 0xada52840
+ 210, 0x20, // PINS_PORT_SIZE = PA_32
+
+ 0, 0, 0, 0, 0, 0, 0, 0
+ /* CF2 END */
+};
diff --git a/src/boards/feather_nrf52840_sense/pinconfig.c b/src/boards/feather_nrf52840_sense/pinconfig.c
new file mode 100644
index 0000000..a983e4a
--- /dev/null
+++ b/src/boards/feather_nrf52840_sense/pinconfig.c
@@ -0,0 +1,19 @@
+#include "boards.h"
+#include "uf2/configkeys.h"
+
+__attribute__((used, section(".bootloaderConfig")))
+const uint32_t bootloaderConfig[] =
+{
+ /* CF2 START */
+ CFG_MAGIC0, CFG_MAGIC1, // magic
+ 5, 100, // used entries, total entries
+
+ 204, 0x100000, // FLASH_BYTES = 0x100000
+ 205, 0x40000, // RAM_BYTES = 0x40000
+ 208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2
+ 209, 0xada52840, // UF2_FAMILY = 0xada52840
+ 210, 0x20, // PINS_PORT_SIZE = PA_32
+
+ 0, 0, 0, 0, 0, 0, 0, 0
+ /* CF2 END */
+};
diff --git a/src/boards/itsybitsy_nrf52840_express/pinconfig.c b/src/boards/itsybitsy_nrf52840_express/pinconfig.c
new file mode 100644
index 0000000..a983e4a
--- /dev/null
+++ b/src/boards/itsybitsy_nrf52840_express/pinconfig.c
@@ -0,0 +1,19 @@
+#include "boards.h"
+#include "uf2/configkeys.h"
+
+__attribute__((used, section(".bootloaderConfig")))
+const uint32_t bootloaderConfig[] =
+{
+ /* CF2 START */
+ CFG_MAGIC0, CFG_MAGIC1, // magic
+ 5, 100, // used entries, total entries
+
+ 204, 0x100000, // FLASH_BYTES = 0x100000
+ 205, 0x40000, // RAM_BYTES = 0x40000
+ 208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2
+ 209, 0xada52840, // UF2_FAMILY = 0xada52840
+ 210, 0x20, // PINS_PORT_SIZE = PA_32
+
+ 0, 0, 0, 0, 0, 0, 0, 0
+ /* CF2 END */
+};
diff --git a/src/boards/mdk_nrf52840_dongle/board.h b/src/boards/mdk_nrf52840_dongle/board.h
index c45213e..6528451 100644
--- a/src/boards/mdk_nrf52840_dongle/board.h
+++ b/src/boards/mdk_nrf52840_dongle/board.h
@@ -58,6 +58,12 @@
//--------------------------------------------------------------------+
// USB
//--------------------------------------------------------------------+
+
+// Shared VID/PID with Feather nRF52840, will be disabled for building in the future
+#define USB_DESC_VID 0x239A
+#define USB_DESC_UF2_PID 0x0029
+#define USB_DESC_CDC_ONLY_PID 0x0029
+
#define UF2_PRODUCT_NAME "MDK nRF52840 USB Dongle"
#define UF2_VOLUME_LABEL "MDK840DONGL"
#define UF2_BOARD_ID "nRF52840-Dongle-v1"
diff --git a/src/boards/mdk_nrf52840_dongle/pinconfig.c b/src/boards/mdk_nrf52840_dongle/pinconfig.c
new file mode 100644
index 0000000..a983e4a
--- /dev/null
+++ b/src/boards/mdk_nrf52840_dongle/pinconfig.c
@@ -0,0 +1,19 @@
+#include "boards.h"
+#include "uf2/configkeys.h"
+
+__attribute__((used, section(".bootloaderConfig")))
+const uint32_t bootloaderConfig[] =
+{
+ /* CF2 START */
+ CFG_MAGIC0, CFG_MAGIC1, // magic
+ 5, 100, // used entries, total entries
+
+ 204, 0x100000, // FLASH_BYTES = 0x100000
+ 205, 0x40000, // RAM_BYTES = 0x40000
+ 208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2
+ 209, 0xada52840, // UF2_FAMILY = 0xada52840
+ 210, 0x20, // PINS_PORT_SIZE = PA_32
+
+ 0, 0, 0, 0, 0, 0, 0, 0
+ /* CF2 END */
+};
diff --git a/src/boards/metro_nrf52840_express/pinconfig.c b/src/boards/metro_nrf52840_express/pinconfig.c
new file mode 100644
index 0000000..a983e4a
--- /dev/null
+++ b/src/boards/metro_nrf52840_express/pinconfig.c
@@ -0,0 +1,19 @@
+#include "boards.h"
+#include "uf2/configkeys.h"
+
+__attribute__((used, section(".bootloaderConfig")))
+const uint32_t bootloaderConfig[] =
+{
+ /* CF2 START */
+ CFG_MAGIC0, CFG_MAGIC1, // magic
+ 5, 100, // used entries, total entries
+
+ 204, 0x100000, // FLASH_BYTES = 0x100000
+ 205, 0x40000, // RAM_BYTES = 0x40000
+ 208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2
+ 209, 0xada52840, // UF2_FAMILY = 0xada52840
+ 210, 0x20, // PINS_PORT_SIZE = PA_32
+
+ 0, 0, 0, 0, 0, 0, 0, 0
+ /* CF2 END */
+};
diff --git a/src/boards/ohs2020_badge/pinconfig.c b/src/boards/ohs2020_badge/pinconfig.c
new file mode 100644
index 0000000..a983e4a
--- /dev/null
+++ b/src/boards/ohs2020_badge/pinconfig.c
@@ -0,0 +1,19 @@
+#include "boards.h"
+#include "uf2/configkeys.h"
+
+__attribute__((used, section(".bootloaderConfig")))
+const uint32_t bootloaderConfig[] =
+{
+ /* CF2 START */
+ CFG_MAGIC0, CFG_MAGIC1, // magic
+ 5, 100, // used entries, total entries
+
+ 204, 0x100000, // FLASH_BYTES = 0x100000
+ 205, 0x40000, // RAM_BYTES = 0x40000
+ 208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2
+ 209, 0xada52840, // UF2_FAMILY = 0xada52840
+ 210, 0x20, // PINS_PORT_SIZE = PA_32
+
+ 0, 0, 0, 0, 0, 0, 0, 0
+ /* CF2 END */
+};
diff --git a/src/boards/particle_argon/board.h b/src/boards/particle_argon/board.h
index 467a7df..3f7078a 100644
--- a/src/boards/particle_argon/board.h
+++ b/src/boards/particle_argon/board.h
@@ -56,6 +56,12 @@
//--------------------------------------------------------------------+
// USB
//--------------------------------------------------------------------+
+
+// Shared VID/PID with Feather nRF52840, will be disabled for building in the future
+#define USB_DESC_VID 0x239A
+#define USB_DESC_UF2_PID 0x0029
+#define USB_DESC_CDC_ONLY_PID 0x0029
+
#define UF2_PRODUCT_NAME "Particle Argon"
#define UF2_VOLUME_LABEL "ARGONBOOT "
#define UF2_BOARD_ID "nRF52840-Argon-v1"
diff --git a/src/boards/particle_argon/pinconfig.c b/src/boards/particle_argon/pinconfig.c
new file mode 100644
index 0000000..a983e4a
--- /dev/null
+++ b/src/boards/particle_argon/pinconfig.c
@@ -0,0 +1,19 @@
+#include "boards.h"
+#include "uf2/configkeys.h"
+
+__attribute__((used, section(".bootloaderConfig")))
+const uint32_t bootloaderConfig[] =
+{
+ /* CF2 START */
+ CFG_MAGIC0, CFG_MAGIC1, // magic
+ 5, 100, // used entries, total entries
+
+ 204, 0x100000, // FLASH_BYTES = 0x100000
+ 205, 0x40000, // RAM_BYTES = 0x40000
+ 208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2
+ 209, 0xada52840, // UF2_FAMILY = 0xada52840
+ 210, 0x20, // PINS_PORT_SIZE = PA_32
+
+ 0, 0, 0, 0, 0, 0, 0, 0
+ /* CF2 END */
+};
diff --git a/src/boards/particle_boron/board.h b/src/boards/particle_boron/board.h
index b433cea..6db75be 100644
--- a/src/boards/particle_boron/board.h
+++ b/src/boards/particle_boron/board.h
@@ -56,6 +56,12 @@
//--------------------------------------------------------------------+
// USB
//--------------------------------------------------------------------+
+
+// Shared VID/PID with Feather nRF52840, will be disabled for building in the future
+#define USB_DESC_VID 0x239A
+#define USB_DESC_UF2_PID 0x0029
+#define USB_DESC_CDC_ONLY_PID 0x0029
+
#define UF2_PRODUCT_NAME "Particle Boron"
#define UF2_VOLUME_LABEL "BORONBOOT "
#define UF2_BOARD_ID "nRF52840-Boron-v1"
diff --git a/src/boards/particle_boron/pinconfig.c b/src/boards/particle_boron/pinconfig.c
new file mode 100644
index 0000000..a983e4a
--- /dev/null
+++ b/src/boards/particle_boron/pinconfig.c
@@ -0,0 +1,19 @@
+#include "boards.h"
+#include "uf2/configkeys.h"
+
+__attribute__((used, section(".bootloaderConfig")))
+const uint32_t bootloaderConfig[] =
+{
+ /* CF2 START */
+ CFG_MAGIC0, CFG_MAGIC1, // magic
+ 5, 100, // used entries, total entries
+
+ 204, 0x100000, // FLASH_BYTES = 0x100000
+ 205, 0x40000, // RAM_BYTES = 0x40000
+ 208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2
+ 209, 0xada52840, // UF2_FAMILY = 0xada52840
+ 210, 0x20, // PINS_PORT_SIZE = PA_32
+
+ 0, 0, 0, 0, 0, 0, 0, 0
+ /* CF2 END */
+};
diff --git a/src/boards/particle_xenon/board.h b/src/boards/particle_xenon/board.h
index 5fe2474..ac2c9a7 100644
--- a/src/boards/particle_xenon/board.h
+++ b/src/boards/particle_xenon/board.h
@@ -56,6 +56,12 @@
//--------------------------------------------------------------------+
// USB
//--------------------------------------------------------------------+
+
+// Shared VID/PID with Feather nRF52840, will be disabled for building in the future
+#define USB_DESC_VID 0x239A
+#define USB_DESC_UF2_PID 0x0029
+#define USB_DESC_CDC_ONLY_PID 0x0029
+
#define UF2_PRODUCT_NAME "Particle Xenon"
#define UF2_VOLUME_LABEL "XENONBOOT "
#define UF2_BOARD_ID "nRF52840-Xenon-v1"
diff --git a/src/boards/particle_xenon/pinconfig.c b/src/boards/particle_xenon/pinconfig.c
new file mode 100644
index 0000000..a983e4a
--- /dev/null
+++ b/src/boards/particle_xenon/pinconfig.c
@@ -0,0 +1,19 @@
+#include "boards.h"
+#include "uf2/configkeys.h"
+
+__attribute__((used, section(".bootloaderConfig")))
+const uint32_t bootloaderConfig[] =
+{
+ /* CF2 START */
+ CFG_MAGIC0, CFG_MAGIC1, // magic
+ 5, 100, // used entries, total entries
+
+ 204, 0x100000, // FLASH_BYTES = 0x100000
+ 205, 0x40000, // RAM_BYTES = 0x40000
+ 208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2
+ 209, 0xada52840, // UF2_FAMILY = 0xada52840
+ 210, 0x20, // PINS_PORT_SIZE = PA_32
+
+ 0, 0, 0, 0, 0, 0, 0, 0
+ /* CF2 END */
+};
diff --git a/src/boards/pca10056/board.h b/src/boards/pca10056/board.h
index a17d597..92ce346 100644
--- a/src/boards/pca10056/board.h
+++ b/src/boards/pca10056/board.h
@@ -50,6 +50,12 @@
//--------------------------------------------------------------------+
// USB
//--------------------------------------------------------------------+
+
+// Shared VID/PID with Feather nRF52840, will be disabled for building in the future
+#define USB_DESC_VID 0x239A
+#define USB_DESC_UF2_PID 0x0029
+#define USB_DESC_CDC_ONLY_PID 0x0029
+
#define UF2_PRODUCT_NAME "Nordic nRF52840 DK"
#define UF2_BOARD_ID "nRF52840-pca10056-v1"
#define UF2_INDEX_URL "https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK"
diff --git a/src/boards/pca10056/pinconfig.c b/src/boards/pca10056/pinconfig.c
new file mode 100644
index 0000000..a983e4a
--- /dev/null
+++ b/src/boards/pca10056/pinconfig.c
@@ -0,0 +1,19 @@
+#include "boards.h"
+#include "uf2/configkeys.h"
+
+__attribute__((used, section(".bootloaderConfig")))
+const uint32_t bootloaderConfig[] =
+{
+ /* CF2 START */
+ CFG_MAGIC0, CFG_MAGIC1, // magic
+ 5, 100, // used entries, total entries
+
+ 204, 0x100000, // FLASH_BYTES = 0x100000
+ 205, 0x40000, // RAM_BYTES = 0x40000
+ 208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2
+ 209, 0xada52840, // UF2_FAMILY = 0xada52840
+ 210, 0x20, // PINS_PORT_SIZE = PA_32
+
+ 0, 0, 0, 0, 0, 0, 0, 0
+ /* CF2 END */
+};
diff --git a/src/boards/pca10059/board.h b/src/boards/pca10059/board.h
index 6654b87..8b2d89d 100644
--- a/src/boards/pca10059/board.h
+++ b/src/boards/pca10059/board.h
@@ -53,6 +53,12 @@
//--------------------------------------------------------------------+
// USB
//--------------------------------------------------------------------+
+
+// Shared VID/PID with Feather nRF52840, will be disabled for building in the future
+#define USB_DESC_VID 0x239A
+#define USB_DESC_UF2_PID 0x0029
+#define USB_DESC_CDC_ONLY_PID 0x0029
+
#define UF2_PRODUCT_NAME "Nordic nRF52840 Dongle"
#define UF2_BOARD_ID "nRF52840-pca10059-v1"
#define UF2_INDEX_URL "https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-Dongle"
diff --git a/src/boards/pca10059/pinconfig.c b/src/boards/pca10059/pinconfig.c
new file mode 100644
index 0000000..a983e4a
--- /dev/null
+++ b/src/boards/pca10059/pinconfig.c
@@ -0,0 +1,19 @@
+#include "boards.h"
+#include "uf2/configkeys.h"
+
+__attribute__((used, section(".bootloaderConfig")))
+const uint32_t bootloaderConfig[] =
+{
+ /* CF2 START */
+ CFG_MAGIC0, CFG_MAGIC1, // magic
+ 5, 100, // used entries, total entries
+
+ 204, 0x100000, // FLASH_BYTES = 0x100000
+ 205, 0x40000, // RAM_BYTES = 0x40000
+ 208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2
+ 209, 0xada52840, // UF2_FAMILY = 0xada52840
+ 210, 0x20, // PINS_PORT_SIZE = PA_32
+
+ 0, 0, 0, 0, 0, 0, 0, 0
+ /* CF2 END */
+};
diff --git a/src/boards/pca10100/board.h b/src/boards/pca10100/board.h
index d82e2d1..743f175 100644
--- a/src/boards/pca10100/board.h
+++ b/src/boards/pca10100/board.h
@@ -50,6 +50,10 @@
//--------------------------------------------------------------------+
// USB
//--------------------------------------------------------------------+
+#define USB_DESC_VID 0x1915
+#define USB_DESC_UF2_PID 0x521F
+#define USB_DESC_CDC_ONLY_PID 0x521F
+
#define UF2_PRODUCT_NAME "Nordic nRF52833 DK"
#define UF2_BOARD_ID "nRF52833-pca10100-v1"
#define UF2_INDEX_URL "https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52833-DK"
diff --git a/src/boards/pca10100/pinconfig.c b/src/boards/pca10100/pinconfig.c
new file mode 100644
index 0000000..a983e4a
--- /dev/null
+++ b/src/boards/pca10100/pinconfig.c
@@ -0,0 +1,19 @@
+#include "boards.h"
+#include "uf2/configkeys.h"
+
+__attribute__((used, section(".bootloaderConfig")))
+const uint32_t bootloaderConfig[] =
+{
+ /* CF2 START */
+ CFG_MAGIC0, CFG_MAGIC1, // magic
+ 5, 100, // used entries, total entries
+
+ 204, 0x100000, // FLASH_BYTES = 0x100000
+ 205, 0x40000, // RAM_BYTES = 0x40000
+ 208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2
+ 209, 0xada52840, // UF2_FAMILY = 0xada52840
+ 210, 0x20, // PINS_PORT_SIZE = PA_32
+
+ 0, 0, 0, 0, 0, 0, 0, 0
+ /* CF2 END */
+};
diff --git a/src/boards/raytac_mdbt50q_rx/board.h b/src/boards/raytac_mdbt50q_rx/board.h
index 18b7c90..6da8b22 100644
--- a/src/boards/raytac_mdbt50q_rx/board.h
+++ b/src/boards/raytac_mdbt50q_rx/board.h
@@ -52,9 +52,11 @@
//--------------------------------------------------------------------+
// USB
//--------------------------------------------------------------------+
-#define USB_DESC_VID 0x239A
-#define USB_DESC_UF2_PID 0x0029
-#define USB_DESC_CDC_ONLY_PID 0x002A
+
+// Shared VID/PID with Feather nRF52840, will be disabled for building in the future
+#define USB_DESC_VID 0x239A
+#define USB_DESC_UF2_PID 0x0029
+#define USB_DESC_CDC_ONLY_PID 0x0029
//------------- UF2 -------------//
#define UF2_PRODUCT_NAME "Raytac MDBT50Q-RX"
diff --git a/src/boards/raytac_mdbt50q_rx/pinconfig.c b/src/boards/raytac_mdbt50q_rx/pinconfig.c
new file mode 100644
index 0000000..a983e4a
--- /dev/null
+++ b/src/boards/raytac_mdbt50q_rx/pinconfig.c
@@ -0,0 +1,19 @@
+#include "boards.h"
+#include "uf2/configkeys.h"
+
+__attribute__((used, section(".bootloaderConfig")))
+const uint32_t bootloaderConfig[] =
+{
+ /* CF2 START */
+ CFG_MAGIC0, CFG_MAGIC1, // magic
+ 5, 100, // used entries, total entries
+
+ 204, 0x100000, // FLASH_BYTES = 0x100000
+ 205, 0x40000, // RAM_BYTES = 0x40000
+ 208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2
+ 209, 0xada52840, // UF2_FAMILY = 0xada52840
+ 210, 0x20, // PINS_PORT_SIZE = PA_32
+
+ 0, 0, 0, 0, 0, 0, 0, 0
+ /* CF2 END */
+};
diff --git a/src/boards/waveshare_nrf52840_eval/pinconfig.c b/src/boards/waveshare_nrf52840_eval/pinconfig.c
new file mode 100644
index 0000000..a983e4a
--- /dev/null
+++ b/src/boards/waveshare_nrf52840_eval/pinconfig.c
@@ -0,0 +1,19 @@
+#include "boards.h"
+#include "uf2/configkeys.h"
+
+__attribute__((used, section(".bootloaderConfig")))
+const uint32_t bootloaderConfig[] =
+{
+ /* CF2 START */
+ CFG_MAGIC0, CFG_MAGIC1, // magic
+ 5, 100, // used entries, total entries
+
+ 204, 0x100000, // FLASH_BYTES = 0x100000
+ 205, 0x40000, // RAM_BYTES = 0x40000
+ 208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2
+ 209, 0xada52840, // UF2_FAMILY = 0xada52840
+ 210, 0x20, // PINS_PORT_SIZE = PA_32
+
+ 0, 0, 0, 0, 0, 0, 0, 0
+ /* CF2 END */
+};
diff --git a/src/dfu_ble_svc.c b/src/dfu_ble_svc.c
index a4a9d72..c34bec6 100644
--- a/src/dfu_ble_svc.c
+++ b/src/dfu_ble_svc.c
@@ -44,14 +44,17 @@
#include "crc16.h"
#if defined ( __CC_ARM )
-static dfu_ble_peer_data_t m_peer_data __attribute__((section("NoInit"), zero_init)); /**< This variable should be placed in a non initialized RAM section in order to be valid upon soft reset from application into bootloader. */
-static uint16_t m_peer_data_crc __attribute__((section("NoInit"), zero_init)); /**< CRC variable to ensure the integrity of the peer data provided. */
+ static dfu_ble_peer_data_t m_peer_data __attribute__((section("NoInit"), zero_init)); /**< This variable should be placed in a non initialized RAM section in order to be valid upon soft reset from application into bootloader. */
+ static uint16_t m_peer_data_crc __attribute__((section("NoInit"), zero_init)); /**< CRC variable to ensure the integrity of the peer data provided. */
+
#elif defined ( __GNUC__ )
-__attribute__((section(".noinit"))) static dfu_ble_peer_data_t m_peer_data; /**< This variable should be placed in a non initialized RAM section in order to be valid upon soft reset from application into bootloader. */
-__attribute__((section(".noinit"))) static uint16_t m_peer_data_crc; /**< CRC variable to ensure the integrity of the peer data provided. */
+ __attribute__((section(".noinit"))) static dfu_ble_peer_data_t m_peer_data; /**< This variable should be placed in a non initialized RAM section in order to be valid upon soft reset from application into bootloader. */
+ __attribute__((section(".noinit"))) static uint16_t m_peer_data_crc; /**< CRC variable to ensure the integrity of the peer data provided. */
+
#elif defined ( __ICCARM__ )
-__no_init static dfu_ble_peer_data_t m_peer_data @ 0x20003F80; /**< This variable should be placed in a non initialized RAM section in order to be valid upon soft reset from application into bootloader. */
-__no_init static uint16_t m_peer_data_crc @ 0x20003F80 + sizeof(dfu_ble_peer_data_t); /**< CRC variable to ensure the integrity of the peer data provided. */
+ __no_init static dfu_ble_peer_data_t m_peer_data @ 0x20003F80; /**< This variable should be placed in a non initialized RAM section in order to be valid upon soft reset from application into bootloader. */
+ __no_init static uint16_t m_peer_data_crc @ 0x20003F80 + sizeof(dfu_ble_peer_data_t); /**< CRC variable to ensure the integrity of the peer data provided. */
+
#endif
diff --git a/src/flash_nrf5x.c b/src/flash_nrf5x.c
index fe563ac..12c6797 100644
--- a/src/flash_nrf5x.c
+++ b/src/flash_nrf5x.c
@@ -37,6 +37,7 @@ void flash_nrf5x_flush (bool need_erase)
{
if ( _fl_addr == FLASH_CACHE_INVALID_ADDR ) return;
+ // skip the write if contents matches
if ( memcmp(_fl_buf, (void *) _fl_addr, FLASH_PAGE_SIZE) != 0 )
{
// - nRF52832 dfu via uart can miss incoming byte when erasing because cpu is blocked for > 2ms.
@@ -44,8 +45,13 @@ void flash_nrf5x_flush (bool need_erase)
// - nRF52840 dfu serial/uf2 are USB-based which are DMA and should have no problems.
//
// Note: MSC uf2 does not erase page in advance like dfu serial
- if ( need_erase ) nrfx_nvmc_page_erase(_fl_addr);
+ if ( need_erase )
+ {
+ PRINTF("Erase and ");
+ nrfx_nvmc_page_erase(_fl_addr);
+ }
+ PRINTF("Write 0x%08lX\r\n", _fl_addr);
nrfx_nvmc_words_write(_fl_addr, (uint32_t *) _fl_buf, FLASH_PAGE_SIZE / 4);
}
diff --git a/src/main.c b/src/main.c
index 5c974c1..6148298 100644
--- a/src/main.c
+++ b/src/main.c
@@ -83,6 +83,10 @@ void usb_teardown(void);
#endif
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+
/*
* Blinking patterns:
* - DFU Serial : LED Status blink
@@ -115,27 +119,16 @@ void usb_teardown(void);
// Allow for using reset button essentially to swap between application and bootloader.
// This is controlled by a flag in the app and is the behavior of CPX and all Arcade boards when using MakeCode.
-#define APP_ASKS_FOR_SINGLE_TAP_RESET() (*((uint32_t*)(USER_FLASH_START + 0x200)) == 0x87eeb07c)
+#define APP_ASKS_FOR_SINGLE_TAP_RESET() (*((uint32_t*)(DFU_BANK_0_REGION_START + 0x200)) == 0x87eeb07c)
// These value must be the same with one in dfu_transport_ble.c
#define BLEGAP_EVENT_LENGTH 6
#define BLEGATT_ATT_MTU_MAX 247
enum { BLE_CONN_CFG_HIGH_BANDWIDTH = 1 };
-// Adafruit for factory reset
-#define APPDATA_ADDR_START (BOOTLOADER_REGION_START-DFU_APP_DATA_RESERVED)
-
-#ifdef NRF52840_XXAA
- // Flash 1024 KB
- STATIC_ASSERT( APPDATA_ADDR_START == 0xED000);
-
-#else
- // Flash 512 KB
- STATIC_ASSERT( APPDATA_ADDR_START == 0x6D000);
-#endif
-
-
-void adafruit_factory_reset(void);
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
static uint32_t softdev_init(bool init_softdevice);
uint32_t* dbl_reset_mem = ((uint32_t*) DFU_DBL_RESET_MEM );
@@ -151,12 +144,23 @@ bool is_ota(void)
void softdev_mbr_init(void)
{
+ PRINTF("SD_MBR_COMMAND_INIT_SD\r\n");
sd_mbr_command_t com = { .command = SD_MBR_COMMAND_INIT_SD };
sd_mbr_command(&com);
}
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
int main(void)
{
+ PRINTF("Bootlaoder Start\r\n");
+
+ // Populate Boot Address and MBR Param into MBR if not already
+ // MBR_BOOTLOADER_ADDR/MBR_PARAM_PAGE_ADDR are used if available, else UICR registers are used
+ // Note: skip it for now since this will prevent us to change the size of bootloader in the future
+ // bootloader_mbr_addrs_populate();
+
// SD is already Initialized in case of BOOTLOADER_DFU_OTA_MAGIC
bool sd_inited = (NRF_POWER->GPREGRET == DFU_MAGIC_OTA_APPJUM);
@@ -174,11 +178,9 @@ int main(void)
if (dfu_start) NRF_POWER->GPREGRET = 0;
// Save bootloader version to pre-defined register, retrieved by application
+ // TODO move to CF2
BOOTLOADER_VERSION_REGISTER = (MK_BOOTLOADER_VERSION);
- // This check ensures that the defined fields in the bootloader corresponds with actual setting in the chip.
- APP_ERROR_CHECK_BOOL(*((uint32_t *)NRF_UICR_BOOT_START_ADDRESS) == BOOTLOADER_REGION_START);
-
board_init();
bootloader_init();
@@ -202,7 +204,7 @@ int main(void)
// DFU + FRESET are pressed --> OTA
_ota_dfu = _ota_dfu || ( button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) ) ;
- bool const valid_app = bootloader_app_is_valid(DFU_BANK_0_REGION_START);
+ bool const valid_app = bootloader_app_is_valid();
bool const just_start_app = valid_app && !dfu_start && (*dbl_reset_mem) == DFU_DBL_RESET_APP;
if (!just_start_app && APP_ASKS_FOR_SINGLE_TAP_RESET())
@@ -259,53 +261,43 @@ int main(void)
}
}
- // Adafruit Factory reset
- if ( !button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) )
- {
- adafruit_factory_reset();
- }
-
// Reset Board
board_teardown();
- // Jump to application if valid
- if (bootloader_app_is_valid(DFU_BANK_0_REGION_START) && !bootloader_dfu_sd_in_progress())
+ /* Jump to application if valid
+ * "Master Boot Record and SoftDevice initializaton procedure"
+ * - SD_MBR_COMMAND_INIT_SD (if not already)
+ * - sd_softdevice_disable()
+ * - sd_softdevice_vector_table_base_set(APP_ADDR)
+ * - jump to App reset
+ */
+
+ if (bootloader_app_is_valid() && !bootloader_dfu_sd_in_progress())
{
- // MBR must be init before start application
- if ( !sd_inited ) softdev_mbr_init();
+ PRINTF("App is valid\r\n");
+ if ( is_sd_existed() )
+ {
+ // MBR forward IRQ to SD (if not already)
+ if ( !sd_inited ) softdev_mbr_init();
+
+ // Make sure SD is disabled
+ sd_softdevice_disable();
+ }
// clear in case we kept DFU_DBL_RESET_APP there
(*dbl_reset_mem) = 0;
- // Select a bank region to use as application region.
- // @note: Only applications running from DFU_BANK_0_REGION_START is supported.
- bootloader_app_start(DFU_BANK_0_REGION_START);
+ // start application
+ bootloader_app_start();
}
NVIC_SystemReset();
}
-
-// Perform factory reset to erase Application + Data
-void adafruit_factory_reset(void)
-{
- led_state(STATE_FACTORY_RESET_STARTED);
-
- // clear all App Data if any
- if ( DFU_APP_DATA_RESERVED )
- {
- nrfx_nvmc_page_erase(APPDATA_ADDR_START);
- }
-
- // Only need to erase the 1st page of Application code to make it invalid
- nrfx_nvmc_page_erase(DFU_BANK_0_REGION_START);
-
- // back to normal
- led_state(STATE_FACTORY_RESET_FINISHED);
-}
-
/**
- * Initializes the SoftDevice and the BLE event interrupt.
+ * Initializes the SotdDevice by following SD specs section
+ * "Master Boot Record and SoftDevice initializaton procedure"
+ *
* @param[in] init_softdevice true if SoftDevice should be initialized. The SoftDevice must only
* be initialized if a chip reset has occured. Soft reset (jump ) from
* application must not reinitialize the SoftDevice.
@@ -314,7 +306,7 @@ static uint32_t softdev_init(bool init_softdevice)
{
if (init_softdevice) softdev_mbr_init();
- // map vector table to bootloader address
+ // Forward vector table to bootloader address so that we can handle BLE events
APP_ERROR_CHECK( sd_softdevice_vector_table_base_set(BOOTLOADER_REGION_START) );
// Enable Softdevice, Use Internal OSC to compatible with all boards
@@ -473,3 +465,29 @@ void SD_EVT_IRQHandler(void)
// Use App Scheduler to defer handling code in non-isr context
app_sched_event_put(NULL, 0, ada_sd_task);
}
+
+
+//--------------------------------------------------------------------+
+// RTT printf retarget for Debug
+//--------------------------------------------------------------------+
+#ifdef CFG_DEBUG
+
+#include "SEGGER_RTT.h"
+
+__attribute__ ((used))
+int _write (int fhdl, const void *buf, size_t count)
+{
+ (void) fhdl;
+ SEGGER_RTT_Write(0, (char*) buf, (int) count);
+ return count;
+}
+
+__attribute__ ((used))
+int _read (int fhdl, char *buf, size_t count)
+{
+ (void) fhdl;
+ return SEGGER_RTT_Read(0, buf, count);
+}
+
+
+#endif
diff --git a/src/usb/msc_uf2.c b/src/usb/msc_uf2.c
index 8b3d7dc..4b6817f 100644
--- a/src/usb/msc_uf2.c
+++ b/src/usb/msc_uf2.c
@@ -39,7 +39,7 @@
static WriteState _wr_state = { 0 };
void read_block(uint32_t block_no, uint8_t *data);
-int write_block(uint32_t block_no, uint8_t *data, bool quiet, WriteState *state);
+int write_block(uint32_t block_no, uint8_t *data, WriteState *state);
//--------------------------------------------------------------------+
// tinyusb callbacks
@@ -143,35 +143,93 @@ int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t*
(void) lun;
uint32_t count = 0;
- int wr_ret;
-
- while ( (count < bufsize) && ((wr_ret = write_block(lba, buffer, false, &_wr_state)) > 0) )
+ while ( count < bufsize )
{
+ // Consider non-uf2 block write as successful
+ // only break if write_block is busy with flashing (return 0)
+ if ( 0 == write_block(lba, buffer, &_wr_state) ) break;
+
lba++;
buffer += 512;
count += 512;
}
- // Consider non-uf2 block write as successful
- return (wr_ret < 0) ? bufsize : count;
+ return count;
}
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
void tud_msc_write10_complete_cb(uint8_t lun)
{
- // uf2 file writing is complete --> complete DFU process
- if ( _wr_state.numBlocks && (_wr_state.numWritten >= _wr_state.numBlocks) )
+ static bool first_write = true;
+
+ // abort the DFU, uf2 block failed integrity check
+ if ( _wr_state.aborted )
{
- led_state(STATE_WRITING_FINISHED);
+ // aborted and reset
+ PRINTF("Aborted\r\n");
dfu_update_status_t update_status;
-
memset(&update_status, 0, sizeof(dfu_update_status_t ));
- update_status.status_code = DFU_UPDATE_APP_COMPLETE;
- update_status.app_crc = 0; // skip CRC checking with uf2 upgrade
- update_status.app_size = _wr_state.numBlocks*256;
+ update_status.status_code = DFU_RESET;
bootloader_dfu_update_process(update_status);
+
+ led_state(STATE_WRITING_FINISHED);
+ }
+ else if ( _wr_state.numBlocks )
+ {
+ // Start LED writing pattern with first write
+ if (first_write)
+ {
+ first_write = false;
+ led_state(STATE_WRITING_STARTED);
+ }
+
+ // All block of uf2 file is complete --> complete DFU process
+ if (_wr_state.numWritten >= _wr_state.numBlocks)
+ {
+ dfu_update_status_t update_status;
+ memset(&update_status, 0, sizeof(dfu_update_status_t ));
+
+ if ( _wr_state.update_bootloader )
+ {
+ // update bootloader always end with reset
+ update_status.status_code = DFU_RESET;
+
+ // Location of current stored new bootloader
+ uint32_t * new_bootloader = (uint32_t *) BOOTLOADER_ADDR_NEW_RECIEVED;
+
+ PRINT_HEX(new_bootloader);
+
+ // skip if there is no bootloader change
+ if ( memcmp(new_bootloader, (uint8_t*) BOOTLOADER_ADDR_START, DFU_BL_IMAGE_MAX_SIZE) )
+ {
+ PRINTF("Coyping new bootloader\r\n");
+
+ sd_mbr_command_t command =
+ {
+ .command = SD_MBR_COMMAND_COPY_BL,
+ .params.copy_bl.bl_src = new_bootloader,
+ .params.copy_bl.bl_len = DFU_BL_IMAGE_MAX_SIZE/4 // size in words
+ };
+
+ // on success, COPY_BL won't return but run the new bootloader right away.
+ sd_mbr_command(&command);
+ }
+
+ PRINTF("bootloader update complete\r\n");
+ }else
+ {
+ // update App
+ update_status.status_code = DFU_UPDATE_APP_COMPLETE;
+
+ PRINTF("Application update complete\r\n");
+ }
+
+ bootloader_dfu_update_process(update_status);
+
+ led_state(STATE_WRITING_FINISHED);
+ }
}
}
@@ -181,7 +239,7 @@ void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_siz
{
(void) lun;
- *block_count = UF2_NUM_BLOCKS;
+ *block_count = CFG_UF2_NUM_BLOCKS;
*block_size = 512;
}
diff --git a/src/usb/tusb_config.h b/src/usb/tusb_config.h
index 22611b2..b76c87b 100644
--- a/src/usb/tusb_config.h
+++ b/src/usb/tusb_config.h
@@ -41,10 +41,7 @@
/*------------- RTOS -------------*/
#define CFG_TUSB_OS OPT_OS_NONE
-//#define CFG_TUD_TASK_PRIO 0
//#define CFG_TUD_TASK_QUEUE_SZ 16
-//#define CFG_TUD_TASK_STACK_SZ 150
-
//--------------------------------------------------------------------+
// DEVICE CONFIGURATION
@@ -52,7 +49,6 @@
//--------------------------------------------------------------------+
/*------------- Core -------------*/
-#define CFG_TUD_DESC_AUTO 0
#define CFG_TUD_ENDOINT0_SIZE 64
//------------- Class enabled -------------//
@@ -74,17 +70,9 @@
//--------------------------------------------------------------------+
// USB RAM PLACEMENT
//--------------------------------------------------------------------+
-#define CFG_TUSB_ATTR_USBRAM
+#define CFG_TUSB_MEM_SECTION
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
-
-#define BREAKPOINT_IGNORE_COUNT(n) \
- do {\
- static uint8_t ignore_count = 0;\
- ignore_count++;\
- if ( ignore_count > n ) verify_breakpoint();\
- }while(0)
-
#ifdef __cplusplus
}
#endif
diff --git a/src/usb/uf2/configkeys.h b/src/usb/uf2/configkeys.h
new file mode 100644
index 0000000..9c45b21
--- /dev/null
+++ b/src/usb/uf2/configkeys.h
@@ -0,0 +1,332 @@
+#ifndef __CONFIGKEYS_H
+#define __CONFIGKEYS_H 1
+
+#define CFG_MAGIC0 0x1e9e10f1
+#define CFG_MAGIC1 0x20227a79
+
+#define CFG_PIN_NAME_MSK 0xffff
+#define CFG_PIN_CONFIG_MSK 0xffff0000
+#define CFG_PIN_CONFIG_ACTIVE_LO 0x10000
+#define CFG_PIN_ACCELEROMETER_INT 1
+#define CFG_PIN_ACCELEROMETER_SCL 2
+#define CFG_PIN_ACCELEROMETER_SDA 3
+#define CFG_PIN_BTN_A 4
+#define CFG_PIN_BTN_B 5
+#define CFG_PIN_BTN_SLIDE 6
+#define CFG_PIN_DOTSTAR_CLOCK 7
+#define CFG_PIN_DOTSTAR_DATA 8
+#define CFG_PIN_FLASH_CS 9
+#define CFG_PIN_FLASH_MISO 10
+#define CFG_PIN_FLASH_MOSI 11
+#define CFG_PIN_FLASH_SCK 12
+#define CFG_PIN_LED 13
+#define CFG_PIN_LIGHT 14
+#define CFG_PIN_MICROPHONE 15
+#define CFG_PIN_MIC_CLOCK 16
+#define CFG_PIN_MIC_DATA 17
+#define CFG_PIN_MISO 18
+#define CFG_PIN_MOSI 19
+#define CFG_PIN_NEOPIXEL 20
+#define CFG_PIN_RX 21
+#define CFG_PIN_RXLED 22
+#define CFG_PIN_SCK 23
+#define CFG_PIN_SCL 24
+#define CFG_PIN_SDA 25
+#define CFG_PIN_SPEAKER_AMP 26
+#define CFG_PIN_TEMPERATURE 27
+#define CFG_PIN_TX 28
+#define CFG_PIN_TXLED 29
+#define CFG_PIN_IR_OUT 30
+#define CFG_PIN_IR_IN 31
+#define CFG_PIN_DISPLAY_SCK 32
+#define CFG_PIN_DISPLAY_MISO 33
+#define CFG_PIN_DISPLAY_MOSI 34
+#define CFG_PIN_DISPLAY_CS 35
+#define CFG_PIN_DISPLAY_DC 36
+#define CFG_DISPLAY_WIDTH 37
+#define CFG_DISPLAY_HEIGHT 38
+#define CFG_DISPLAY_CFG0 39
+#define CFG_DISPLAY_CFG1 40
+#define CFG_DISPLAY_CFG2 41
+#define CFG_DISPLAY_CFG3 42
+#define CFG_PIN_DISPLAY_RST 43
+#define CFG_PIN_DISPLAY_BL 44
+#define CFG_PIN_SERVO_1 45
+#define CFG_PIN_SERVO_2 46
+#define CFG_PIN_BTN_LEFT 47
+#define CFG_PIN_BTN_RIGHT 48
+#define CFG_PIN_BTN_UP 49
+#define CFG_PIN_BTN_DOWN 50
+#define CFG_PIN_BTN_MENU 51
+#define CFG_PIN_LED_R 52
+#define CFG_PIN_LED_G 53
+#define CFG_PIN_LED_B 54
+#define CFG_PIN_LED1 55
+#define CFG_PIN_LED2 56
+#define CFG_PIN_LED3 57
+#define CFG_PIN_LED4 58
+#define CFG_SPEAKER_VOLUME 59
+#define CFG_PIN_JACK_TX 60
+#define CFG_PIN_JACK_SENSE 61
+#define CFG_PIN_JACK_HPEN 62
+#define CFG_PIN_JACK_BZEN 63
+#define CFG_PIN_JACK_PWREN 64
+#define CFG_PIN_JACK_SND 65
+#define CFG_PIN_JACK_BUSLED 66
+#define CFG_PIN_JACK_COMMLED 67
+#define CFG_PIN_BTN_SOFT_RESET 69
+#define CFG_ACCELEROMETER_TYPE 70
+#define CFG_PIN_BTNMX_LATCH 71
+#define CFG_PIN_BTNMX_CLOCK 72
+#define CFG_PIN_BTNMX_DATA 73
+#define CFG_PIN_BTN_MENU2 74
+#define CFG_PIN_BATTSENSE 75
+#define CFG_PIN_VIBRATION 76
+#define CFG_PIN_PWREN 77
+#define CFG_DISPLAY_TYPE 78
+#define CFG_PIN_ROTARY_ENCODER_A 79
+#define CFG_PIN_ROTARY_ENCODER_B 80
+#define CFG_ACCELEROMETER_SPACE 81
+#define CFG_PIN_WIFI_MOSI 82
+#define CFG_PIN_WIFI_MISO 83
+#define CFG_PIN_WIFI_SCK 84
+#define CFG_PIN_WIFI_TX 85
+#define CFG_PIN_WIFI_RX 86
+#define CFG_PIN_WIFI_CS 87
+#define CFG_PIN_WIFI_BUSY 88
+#define CFG_PIN_WIFI_RESET 89
+#define CFG_PIN_WIFI_GPIO0 90
+#define CFG_PIN_WIFI_AT_TX 91
+#define CFG_PIN_WIFI_AT_RX 92
+#define CFG_PIN_USB_POWER 93
+#define CFG_PIN_A0 100
+#define CFG_PIN_A1 101
+#define CFG_PIN_A2 102
+#define CFG_PIN_A3 103
+#define CFG_PIN_A4 104
+#define CFG_PIN_A5 105
+#define CFG_PIN_A6 106
+#define CFG_PIN_A7 107
+#define CFG_PIN_A8 108
+#define CFG_PIN_A9 109
+#define CFG_PIN_A10 110
+#define CFG_PIN_A11 111
+#define CFG_PIN_A12 112
+#define CFG_PIN_A13 113
+#define CFG_PIN_A14 114
+#define CFG_PIN_A15 115
+#define CFG_PIN_A16 116
+#define CFG_PIN_A17 117
+#define CFG_PIN_A18 118
+#define CFG_PIN_A19 119
+#define CFG_PIN_A20 120
+#define CFG_PIN_A21 121
+#define CFG_PIN_A22 122
+#define CFG_PIN_A23 123
+#define CFG_PIN_A24 124
+#define CFG_PIN_A25 125
+#define CFG_PIN_A26 126
+#define CFG_PIN_A27 127
+#define CFG_PIN_A28 128
+#define CFG_PIN_A29 129
+#define CFG_PIN_A30 130
+#define CFG_PIN_A31 131
+#define CFG_PIN_D0 150
+#define CFG_PIN_D1 151
+#define CFG_PIN_D2 152
+#define CFG_PIN_D3 153
+#define CFG_PIN_D4 154
+#define CFG_PIN_D5 155
+#define CFG_PIN_D6 156
+#define CFG_PIN_D7 157
+#define CFG_PIN_D8 158
+#define CFG_PIN_D9 159
+#define CFG_PIN_D10 160
+#define CFG_PIN_D11 161
+#define CFG_PIN_D12 162
+#define CFG_PIN_D13 163
+#define CFG_PIN_D14 164
+#define CFG_PIN_D15 165
+#define CFG_PIN_D16 166
+#define CFG_PIN_D17 167
+#define CFG_PIN_D18 168
+#define CFG_PIN_D19 169
+#define CFG_PIN_D20 170
+#define CFG_PIN_D21 171
+#define CFG_PIN_D22 172
+#define CFG_PIN_D23 173
+#define CFG_PIN_D24 174
+#define CFG_PIN_D25 175
+#define CFG_PIN_D26 176
+#define CFG_PIN_D27 177
+#define CFG_PIN_D28 178
+#define CFG_PIN_D29 179
+#define CFG_PIN_D30 180
+#define CFG_PIN_D31 181
+#define CFG_NUM_NEOPIXELS 200
+#define CFG_NUM_DOTSTARS 201
+#define CFG_DEFAULT_BUTTON_MODE 202
+#define CFG_SWD_ENABLED 203
+#define CFG_FLASH_BYTES 204
+#define CFG_RAM_BYTES 205
+#define CFG_SYSTEM_HEAP_BYTES 206
+#define CFG_LOW_MEM_SIMULATION_KB 207
+#define CFG_BOOTLOADER_BOARD_ID 208
+#define CFG_UF2_FAMILY 209
+#define CFG_PINS_PORT_SIZE 210
+#define CFG_BOOTLOADER_PROTECTION 211
+#define CFG_POWER_DEEPSLEEP_TIMEOUT 212
+#define CFG_ANALOG_BUTTON_THRESHOLD 213
+#define CFG_CPU_MHZ 214
+#define CFG_CONTROLLER_LIGHT_MAX_BRIGHTNESS 215
+#define CFG_PIN_B0 300
+#define CFG_PIN_B1 301
+#define CFG_PIN_B2 302
+#define CFG_PIN_B3 303
+#define CFG_PIN_B4 304
+#define CFG_PIN_B5 305
+#define CFG_PIN_B6 306
+#define CFG_PIN_B7 307
+#define CFG_PIN_B8 308
+#define CFG_PIN_B9 309
+#define CFG_PIN_B10 310
+#define CFG_PIN_B11 311
+#define CFG_PIN_B12 312
+#define CFG_PIN_B13 313
+#define CFG_PIN_B14 314
+#define CFG_PIN_B15 315
+#define CFG_PIN_B16 316
+#define CFG_PIN_B17 317
+#define CFG_PIN_B18 318
+#define CFG_PIN_B19 319
+#define CFG_PIN_B20 320
+#define CFG_PIN_B21 321
+#define CFG_PIN_B22 322
+#define CFG_PIN_B23 323
+#define CFG_PIN_B24 324
+#define CFG_PIN_B25 325
+#define CFG_PIN_B26 326
+#define CFG_PIN_B27 327
+#define CFG_PIN_B28 328
+#define CFG_PIN_B29 329
+#define CFG_PIN_B30 330
+#define CFG_PIN_B31 331
+#define CFG_PIN_C0 350
+#define CFG_PIN_C1 351
+#define CFG_PIN_C2 352
+#define CFG_PIN_C3 353
+#define CFG_PIN_C4 354
+#define CFG_PIN_C5 355
+#define CFG_PIN_C6 356
+#define CFG_PIN_C7 357
+#define CFG_PIN_C8 358
+#define CFG_PIN_C9 359
+#define CFG_PIN_C10 360
+#define CFG_PIN_C11 361
+#define CFG_PIN_C12 362
+#define CFG_PIN_C13 363
+#define CFG_PIN_C14 364
+#define CFG_PIN_C15 365
+#define CFG_PIN_C16 366
+#define CFG_PIN_C17 367
+#define CFG_PIN_C18 368
+#define CFG_PIN_C19 369
+#define CFG_PIN_C20 370
+#define CFG_PIN_C21 371
+#define CFG_PIN_C22 372
+#define CFG_PIN_C23 373
+#define CFG_PIN_C24 374
+#define CFG_PIN_C25 375
+#define CFG_PIN_C26 376
+#define CFG_PIN_C27 377
+#define CFG_PIN_C28 378
+#define CFG_PIN_C29 379
+#define CFG_PIN_C30 380
+#define CFG_PIN_C31 381
+#define CFG_PIN_P0 400
+#define CFG_PIN_P1 401
+#define CFG_PIN_P2 402
+#define CFG_PIN_P3 403
+#define CFG_PIN_P4 404
+#define CFG_PIN_P5 405
+#define CFG_PIN_P6 406
+#define CFG_PIN_P7 407
+#define CFG_PIN_P8 408
+#define CFG_PIN_P9 409
+#define CFG_PIN_P10 410
+#define CFG_PIN_P11 411
+#define CFG_PIN_P12 412
+#define CFG_PIN_P13 413
+#define CFG_PIN_P14 414
+#define CFG_PIN_P15 415
+#define CFG_PIN_P16 416
+#define CFG_PIN_P17 417
+#define CFG_PIN_P18 418
+#define CFG_PIN_P19 419
+#define CFG_PIN_P20 420
+#define CFG_PIN_P21 421
+#define CFG_PIN_P22 422
+#define CFG_PIN_P23 423
+#define CFG_PIN_P24 424
+#define CFG_PIN_P25 425
+#define CFG_PIN_P26 426
+#define CFG_PIN_P27 427
+#define CFG_PIN_P28 428
+#define CFG_PIN_P29 429
+#define CFG_PIN_P30 430
+#define CFG_PIN_P31 431
+#define CFG_PIN_LORA_MISO 0x3e9
+#define CFG_PIN_LORA_MOSI 0x3ea
+#define CFG_PIN_LORA_SCK 0x3eb
+#define CFG_PIN_LORA_CS 0x3ec
+#define CFG_PIN_LORA_BOOT 0x3ed
+#define CFG_PIN_LORA_RESET 0x3ee
+#define CFG_PIN_IRRXLED 0x3ef
+#define CFG_PIN_IRTXLED 0x3f0
+#define CFG_PIN_LCD_RESET 0x3f1
+#define CFG_PIN_LCD_ENABLE 0x3f2
+#define CFG_PIN_LCD_DATALINE4 0x3f3
+#define CFG_PIN_LCD_DATALINE5 0x3f4
+#define CFG_PIN_LCD_DATALINE6 0x3f5
+#define CFG_PIN_LCD_DATALINE7 0x3f6
+#define CFG_NUM_LCD_COLUMNS 0x3f7
+#define CFG_NUM_LCD_ROWS 0x3f8
+
+#define ACCELEROMETER_TYPE_LIS3DH 0x32
+#define ACCELEROMETER_TYPE_LIS3DH_ALT 0x30
+#define ACCELEROMETER_TYPE_MMA8453 0x38
+#define ACCELEROMETER_TYPE_FXOS8700 0x3c
+#define ACCELEROMETER_TYPE_MMA8653 0x3a
+#define ACCELEROMETER_TYPE_MSA300 0x4c
+#define ACCELEROMETER_TYPE_MPU6050 0x68
+
+#define UF2_FAMILY_ATSAMD21 0x68ed2b88
+#define UF2_FAMILY_ATSAML21 0x1851780a
+#define UF2_FAMILY_ATSAMD51 0x55114460
+#define UF2_FAMILY_NRF52840 0x1b57745f
+#define UF2_FAMILY_STM32F103 0x5ee21072
+#define UF2_FAMILY_STM32F401 0x57755a57
+#define UF2_FAMILY_ATMEGA32 0x16573617
+#define UF2_FAMILY_CYPRESS_FX2 0x5a18069b
+
+#define PINS_PORT_SIZE_PA_16 0x10
+#define PINS_PORT_SIZE_PA_32 0x20
+#define PINS_PORT_SIZE_P0_16 0x1010
+#define PINS_PORT_SIZE_P0_32 0x1020
+
+#define DEFAULT_BUTTON_MODE_ACTIVE_HIGH_PULL_DOWN 0x11
+#define DEFAULT_BUTTON_MODE_ACTIVE_HIGH_PULL_UP 0x21
+#define DEFAULT_BUTTON_MODE_ACTIVE_HIGH_PULL_NONE 0x31
+#define DEFAULT_BUTTON_MODE_ACTIVE_LOW_PULL_DOWN 0x10
+#define DEFAULT_BUTTON_MODE_ACTIVE_LOW_PULL_UP 0x20
+#define DEFAULT_BUTTON_MODE_ACTIVE_LOW_PULL_NONE 0x30
+
+#define DISPLAY_TYPE_ST7735 0x1e37
+#define DISPLAY_TYPE_ILI9341 0x247d
+
+#define BTN_FLAG_ACTIVE_HIGH 0x110000
+#define BTN_FLAG_ACTIVE_LOW 0x200000
+#define BTN_OFFSET_ANALOG_PLUS 0x44c
+#define BTN_OFFSET_ANALOG_MINUS 0x4b0
+
+#endif // __CONFIGKEYS_H
diff --git a/src/usb/uf2/ghostfat.c b/src/usb/uf2/ghostfat.c
index e6a2c67..b2c4db6 100644
--- a/src/usb/uf2/ghostfat.c
+++ b/src/usb/uf2/ghostfat.c
@@ -1,15 +1,18 @@
#include "compile_date.h"
#include "uf2.h"
+#include "configkeys.h"
#include "flash_nrf5x.h"
#include
-
-#include "boards.h"
-#include "tusb.h"
+#include
#include "bootloader_settings.h"
#include "bootloader.h"
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+
typedef struct {
uint8_t JumpInstruction[3];
uint8_t OEMInfo[8];
@@ -55,18 +58,22 @@ struct TextFile {
char const *content;
};
-#define NUM_FAT_BLOCKS UF2_NUM_BLOCKS
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+
+#define NUM_FAT_BLOCKS CFG_UF2_NUM_BLOCKS
#define STR0(x) #x
#define STR(x) STR0(x)
-const char infoUf2File[] = //
+char infoUf2File[128*3] =
"UF2 Bootloader " UF2_VERSION "\r\n"
"Model: " UF2_PRODUCT_NAME "\r\n"
- "Board-ID: " UF2_BOARD_ID "\r\n"
- "Date: " __DATE__ "\r\n";
+ "Board-ID: " UF2_BOARD_ID "\r\n";
-const char indexFile[] = //
+const char indexFile[] =
"\n"
""
""
@@ -76,25 +83,24 @@ const char indexFile[] = //
""
"\n";
-// WARNING -- code presumes only one NULL .content for .UF2 file
-// and requires it be the last element of the array
static struct TextFile const info[] = {
{.name = "INFO_UF2TXT", .content = infoUf2File},
{.name = "INDEX HTM", .content = indexFile},
- {.name = "CURRENT UF2"},
+
+ // current.uf2 must be the last element and its content must be NULL
+ {.name = "CURRENT UF2", .content = NULL},
};
-// WARNING -- code presumes each non-UF2 file content fits in single sector
-// Cannot programmatically statically assert .content length
-// for each element above.
+// code presumes each non-UF2 file content fits in single sector
+// Cannot programmatically statically assert .content length
+// for each element above.
STATIC_ASSERT(ARRAY_SIZE(indexFile) < 512);
-#define NUM_FILES (ARRAY_SIZE(info))
-#define NUM_DIRENTRIES (NUM_FILES + 1) // Code adds volume label as first root directory entry
+#define NUM_FILES (ARRAY_SIZE(info))
+#define NUM_DIRENTRIES (NUM_FILES + 1) // Code adds volume label as first root directory entry
-
-#define UF2_SIZE (current_flash_size() * 2)
+#define UF2_SIZE ((USER_FLASH_END-USER_FLASH_START) * 2)
#define UF2_SECTORS (UF2_SIZE / 512)
#define UF2_FIRST_SECTOR (NUM_FILES + 1) // WARNING -- code presumes each non-UF2 file content fits in single sector
#define UF2_LAST_SECTOR (UF2_FIRST_SECTOR + UF2_SECTORS - 1)
@@ -135,50 +141,68 @@ static FAT_BootBlock const BootBlock = {
.FilesystemIdentifier = "FAT16 ",
};
-#define NRF_LOG_DEBUG(...)
-#define NRF_LOG_WARNING(...)
+// Use bootloaderConfig to detect BOOTLOADER ID when updating bootloader
+// This helps to prevent incorrect uf2 from other boards.
+extern const uint32_t bootloaderConfig[];
-// get current.uf2 flash size in bytes, round up to 256 bytes
-static uint32_t current_flash_size(void)
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+static inline bool is_uf2_block (UF2_Block const *bl)
{
- static uint32_t flash_sz = 0;
- uint32_t result = flash_sz; // presumes atomic 32-bit read/write and static result
-
- // only need to compute once
- if ( result == 0 )
- {
- // return 1 block of 256 bytes
- if ( !bootloader_app_is_valid(DFU_BANK_0_REGION_START) )
- {
- result = 256;
- }else
- {
- bootloader_settings_t const * boot_setting;
- bootloader_util_settings_get(&boot_setting);
-
- result = boot_setting->bank_0_size;
-
- // Copy size must be multiple of 256 bytes
- // else we will got an issue copying current.uf2
- if (result & 0xff)
- {
- result = (result & ~0xff) + 256;
- }
-
- // if bank0 size is not valid, happens when flashed with jlink
- // use maximum application size
- if ( (result == 0) || (result == 0xFFFFFFFFUL) )
- {
- result = FLASH_SIZE;
- }
- }
-
- flash_sz = result; // presumes atomic 32-bit read/write and static result
- }
-
- return flash_sz;
+ return (bl->magicStart0 == UF2_MAGIC_START0) && (bl->magicStart1 == UF2_MAGIC_START1) &&
+ (bl->magicEnd == UF2_MAGIC_END) &&
+ (bl->flags & UF2_FLAG_FAMILYID) && !(bl->flags & UF2_FLAG_NOFLASH) &&
+ (bl->payloadSize == 256) && !(bl->targetAddr & 0xff);
}
+// used when upgrading application
+static inline bool in_app_space (uint32_t addr)
+{
+ return USER_FLASH_START <= addr && addr < USER_FLASH_END;
+}
+
+// used when upgrading bootloader
+static inline bool in_bootloader_space (uint32_t addr)
+{
+ return BOOTLOADER_ADDR_START <= addr && addr < BOOTLOADER_ADDR_END;
+}
+
+// used when upgrading bootloader
+static inline bool in_uicr_space(uint32_t addr)
+{
+ return addr == 0x10001000;
+}
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+
+void uf2_init(void)
+{
+ strcat(infoUf2File, "SoftDevice: ");
+
+ if ( is_sd_existed() )
+ {
+ uint32_t const sd_id = SD_ID_GET(MBR_SIZE);
+ uint32_t const sd_version = SD_VERSION_GET(MBR_SIZE);
+
+ uint32_t const ver1 = sd_version / 1000000;
+ uint32_t const ver2 = (sd_version % 1000000)/1000;
+ uint32_t const ver3 = sd_version % 1000;
+
+ sprintf(infoUf2File + strlen(infoUf2File), "S%lu version %lu.%lu.%lu\r\n", sd_id, ver1, ver2, ver3);
+ }else
+ {
+ strcat(infoUf2File, "not found\r\n");
+ }
+
+ strcat(infoUf2File, "Date: " __DATE__ "\r\n");
+}
+
+/*------------------------------------------------------------------*/
+/* Read CURRENT.UF2
+ *------------------------------------------------------------------*/
void padded_memcpy (char *dst, char const *src, int len)
{
for ( int i = 0; i < len; ++i )
@@ -191,10 +215,6 @@ void padded_memcpy (char *dst, char const *src, int len)
}
}
-
-/*------------------------------------------------------------------*/
-/* Read
- *------------------------------------------------------------------*/
void read_block(uint32_t block_no, uint8_t *data) {
memset(data, 0, 512);
uint32_t sectionIdx = block_no;
@@ -255,9 +275,7 @@ void read_block(uint32_t block_no, uint8_t *data) {
d->updateTime = __DOSTIME__;
d->updateDate = __DOSDATE__;
d->startCluster = startCluster & 0xFF;
- // WARNING -- code presumes only one NULL .content for .UF2 file
- // and requires it be the last element of the array
- d->size = inf->content ? strlen(inf->content) : UF2_SIZE;
+ d->size = (inf->content ? strlen(inf->content) : UF2_SIZE);
}
} else {
@@ -267,17 +285,17 @@ void read_block(uint32_t block_no, uint8_t *data) {
} else { // generate the UF2 file data on-the-fly
sectionIdx -= NUM_FILES - 1;
uint32_t addr = USER_FLASH_START + sectionIdx * 256;
- if (addr < USER_FLASH_START+FLASH_SIZE) {
+ if (addr < CFG_UF2_FLASH_SIZE) {
UF2_Block *bl = (void *)data;
bl->magicStart0 = UF2_MAGIC_START0;
bl->magicStart1 = UF2_MAGIC_START1;
bl->magicEnd = UF2_MAGIC_END;
bl->blockNo = sectionIdx;
- bl->numBlocks = current_flash_size() / 256;
+ bl->numBlocks = (UF2_SIZE/2) / 256;
bl->targetAddr = addr;
bl->payloadSize = 256;
bl->flags = UF2_FLAG_FAMILYID;
- bl->familyID = UF2_FAMILY_ID;
+ bl->familyID = CFG_UF2_FAMILY_APP_ID;
memcpy(bl->data, (void *)addr, bl->payloadSize);
}
}
@@ -288,68 +306,217 @@ void read_block(uint32_t block_no, uint8_t *data) {
/* Write UF2
*------------------------------------------------------------------*/
-/** Write an block
- *
+/**
+ * Write an uf2 block wrapped by 512 sector.
* @return number of bytes processed, only 3 following values
* -1 : if not an uf2 block
* 512 : write is successful
* 0 : is busy with flashing, tinyusb stack will call write_block again with the same parameters later on
*/
-int write_block(uint32_t block_no, uint8_t *data, bool quiet, WriteState *state) {
- UF2_Block *bl = (void *)data;
+int write_block (uint32_t block_no, uint8_t *data, WriteState *state)
+{
+ UF2_Block *bl = (void*) data;
- NRF_LOG_DEBUG("Write magic: %x", bl->magicStart0);
-
- if (!is_uf2_block(bl)) {
- return -1;
- }
-
- // only accept block with same family id
- if ( UF2_FAMILY_ID && !((bl->flags & UF2_FLAG_FAMILYID) && (bl->familyID == UF2_FAMILY_ID)) ) {
- return -1;
- }
-
- if ((bl->flags & UF2_FLAG_NOFLASH) || bl->payloadSize > 256 || (bl->targetAddr & 0xff) ||
- bl->targetAddr < USER_FLASH_START || bl->targetAddr + bl->payloadSize > USER_FLASH_END) {
-
- NRF_LOG_WARNING("Skip block at %x", bl->targetAddr);
- // this happens when we're trying to re-flash CURRENT.UF2 file previously
- // copied from a device; we still want to count these blocks to reset properly
- } else {
- // logval("write block at", bl->targetAddr);
- NRF_LOG_DEBUG("Write block at %x", bl->targetAddr);
-
- static bool first_write = true;
- if ( first_write ) {
- first_write = false;
- led_state(STATE_WRITING_STARTED);
- }
+ if ( !is_uf2_block(bl) ) return -1;
+ switch ( bl->familyID )
+ {
+ case CFG_UF2_FAMILY_APP_ID:
+ /* Upgrading Application
+ *
+ * SoftDevice is considered as part of application and can be (or not) included in uf2.
+ *
+ * ------------- -------------
+ * | | | |
+ * | Bootloader | | Bootloader |
+ * BOOTLOADER_ADDR_START--|-------------| |-------------|
+ * | App Data | | App Data |
+ * USER_FLASH_END ---|-------------| |-------------|
+ * | | | |
+ * | | | New |
+ * | Application | ----> | Application |
+ * | | | |
+ * USER_FLASH_START--|-------------| |-------------|
+ * | MBR | | MBR |
+ * ------------- -------------
+ */
+ if ( in_app_space(bl->targetAddr) )
+ {
+ PRINTF("Write addr = 0x%08lX, block = %ld (%ld of %ld)\r\n", bl->targetAddr, bl->blockNo, state->numWritten, bl->numBlocks);
flash_nrf5x_write(bl->targetAddr, bl->data, bl->payloadSize, true);
+ }else if ( bl->targetAddr < USER_FLASH_START )
+ {
+ // do nothing if writing to MBR, occurs when SD hex is included
+ // keep going as successful write
+ PRINTF("skip writing to MBR\r\n");
+ }else
+ {
+ return -1;
+ }
+ break;
+
+ case CFG_UF2_FAMILY_BOOT_ID:
+ /* Upgrading Bootloader
+ *
+ * - For simplicity, the Bootloader Start Address is fixed for now.
+ *
+ * - Since SoftDevice is not part of Bootloader, it MUST NOT be included as part of uf2 file.
+ *
+ * - To prevent corruption/disconnection while transferring we don't directly write over Bootloader.
+ * Instead it is written to highest possible address in Application region. Once everything is received
+ * and verified, it is safely activated using MBR COPY BL command.
+ *
+ * - Along with bootloader code, UCIR (at 0x1000100) is also included containing
+ * 0x10001014 (bootloader address), and 0x10001018 (MBR Params address).
+ *
+ * Note: part of the existing application can be affected when updating bootloader.
+ * TODO May be worth to have some kind crc/application integrity checking
+ *
+ * ------------- ------------- -------------
+ * | | | | + | New |
+ * | Bootloader | | Bootloader | + | Bootloader |
+ * BOOTLOADER_ADDR_START--|-------------| |-------------| + |-------------|
+ * | App Data | | App Data | + | App Data |
+ * USER_FLASH_END --|-------------| | ---------- | + |------------ |
+ * | | | New |+ | |
+ * | | ---> | Bootloader | | |
+ * | | | ++++++ | | |
+ * | Application | | Application | | Application |
+ * | | | | | |
+ * | | | | | |
+ * USER_FLASH_START--|-------------| |-------------| |-------------|
+ * | MBR | | MBR | | MBR |
+ * ------------- ------------- -------------
+ */
+ PRINTF("addr = 0x%08lX, block = %ld (%ld of %ld)\r\n", bl->targetAddr, bl->blockNo, state->numWritten, bl->numBlocks);
+
+ state->update_bootloader = true;
+ if ( in_uicr_space(bl->targetAddr) )
+ {
+ /* UCIR contains bootloader & MBR address as follow:
+ * - 0x10001014 bootloader address
+ * - 0x10001018 MBR Params: mostly fixed
+ *
+ * Since the bootloader start address is fixed, we only use this for verification
+ */
+ uint32_t uicr_boot_addr;
+ uint32_t uicr_mbr_param;
+
+ memcpy(&uicr_boot_addr, bl->data + 0x14, 4);
+ memcpy(&uicr_mbr_param, bl->data + 0x18, 4);
+
+ // Check MBR params is fixed and prohibited to change and
+ // Bootloader address against its new size
+ if ( (uicr_boot_addr != BOOTLOADER_ADDR_START) ||
+ (uicr_mbr_param != BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS) )
+ {
+ PRINTF("Incorrect UICR value");
+ PRINT_HEX(uicr_boot_addr);
+ PRINT_HEX(uicr_mbr_param);
+
+ state->aborted = true;
+ return -1;
+ }
+
+ state->has_uicr = true;
+ }
+ else if ( in_bootloader_space(bl->targetAddr) )
+ {
+ // Bootloader CF2 config
+ if ( !state->boot_id_matches && (bl->targetAddr >= ((uint32_t) bootloaderConfig)) )
+ {
+ // check if bootloader ID matches current VID/PID
+ for (uint32_t i=0; i < bl->payloadSize; i += 8)
+ {
+ uint32_t key;
+ memcpy(&key, bl->data+i, 4);
+
+ if ( key == CFG_BOOTLOADER_BOARD_ID )
+ {
+ uint32_t value;
+ memcpy(&value, bl->data+i+4, 4);
+
+ PRINTF("Bootloader ID = 0x%08lX and ", value);
+ if ( value == ((USB_DESC_VID << 16) | USB_DESC_UF2_PID) )
+ {
+ PRINTF("matches our VID/PID\r\n");
+ state->boot_id_matches = true;
+ break;
+ }
+ else
+ {
+ PRINTF("DOES NOT mismatches our VID/PID\r\n");
+ state->aborted = true;
+ return -1;
+ }
+ }
+ }
+ }
+
+ // Offset to write the new bootloader address (skipping the App Data)
+ uint32_t const offset_addr = BOOTLOADER_ADDR_END-USER_FLASH_END;
+ flash_nrf5x_write(bl->targetAddr-offset_addr, bl->data, bl->payloadSize, true);
+ }
+#if 0 // don't allow bundle SoftDevice to prevent confusion
+ else if ( in_app_space(bl->targetAddr) )
+ {
+ // Should be Softdevice
+ flash_nrf5x_write(bl->targetAddr, bl->data, bl->payloadSize, true);
+ }
+#endif
+ else if ( bl->targetAddr < USER_FLASH_START )
+ {
+ PRINTF("skip writing to MBR\r\n");
+ }
+ else
+ {
+ state->aborted = true;
+ return -1;
+ }
+ break;
+
+ // unknown family ID
+ default: return -1;
+ }
+
+ //------------- Update written blocks -------------//
+ if ( bl->numBlocks )
+ {
+ // Update state num blocks if needed
+ if ( state->numBlocks != bl->numBlocks )
+ {
+ if ( bl->numBlocks >= MAX_BLOCKS || state->numBlocks )
+ state->numBlocks = 0xffffffff;
+ else
+ state->numBlocks = bl->numBlocks;
}
- if (state && bl->numBlocks) {
- if (state->numBlocks != bl->numBlocks) {
- if (bl->numBlocks >= MAX_BLOCKS || state->numBlocks)
- state->numBlocks = 0xffffffff;
- else
- state->numBlocks = bl->numBlocks;
- }
- if (bl->blockNo < MAX_BLOCKS) {
- uint8_t mask = 1 << (bl->blockNo % 8);
- uint32_t pos = bl->blockNo / 8;
- if (!(state->writtenMask[pos] & mask)) {
- // logval("incr", state->numWritten);
- state->writtenMask[pos] |= mask;
- state->numWritten++;
- }
- if (state->numWritten >= state->numBlocks) {
- // flush last blocks
- flash_nrf5x_flush(true);
- }
- }
- NRF_LOG_DEBUG("wr %d=%d (of %d)", state->numWritten, bl->blockNo, bl->numBlocks);
- }
+ if ( bl->blockNo < MAX_BLOCKS )
+ {
+ uint8_t const mask = 1 << (bl->blockNo % 8);
+ uint32_t const pos = bl->blockNo / 8;
- return 512;
+ // only increase written number with new write (possibly prevent overwriting from OS)
+ if ( !(state->writtenMask[pos] & mask) )
+ {
+ state->writtenMask[pos] |= mask;
+ state->numWritten++;
+ }
+
+ // flush last blocks
+ // TODO numWritten can be smaller than numBlocks if return early
+ if ( state->numWritten >= state->numBlocks )
+ {
+ flash_nrf5x_flush(true);
+
+ // Failed if update bootloader without UCIR value
+ if ( state->update_bootloader && !state->has_uicr )
+ {
+ state->aborted = true;
+ }
+ }
+ }
+ }
+
+ return 512;
}
diff --git a/src/usb/uf2/uf2.h b/src/usb/uf2/uf2.h
index 6edbb4f..081280c 100644
--- a/src/usb/uf2/uf2.h
+++ b/src/usb/uf2/uf2.h
@@ -35,28 +35,29 @@ SOFTWARE.
#include
#include
-#include "app_util.h"
-
-#include "dfu_types.h"
-
-#define SD_MAGIC_NUMBER 0x51b1e5db
-#define SD_MAGIC_OK() (*((uint32_t*)(SOFTDEVICE_INFO_STRUCT_ADDRESS+4)) == 0x51b1e5db)
-extern bool sdRunning;
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
// All entries are little endian.
-
-#define UF2_MAGIC_START0 0x0A324655UL // "UF2\n"
-#define UF2_MAGIC_START1 0x9E5D5157UL // Randomly selected
-#define UF2_MAGIC_END 0x0AB16F30UL // Ditto
+#define UF2_MAGIC_START0 0x0A324655UL // "UF2\n"
+#define UF2_MAGIC_START1 0x9E5D5157UL // Randomly selected
+#define UF2_MAGIC_END 0x0AB16F30UL // Ditto
// If set, the block is "comment" and should not be flashed to the device
-#define UF2_FLAG_NOFLASH 0x00000001
+#define UF2_FLAG_NOFLASH 0x00000001
#define UF2_FLAG_FAMILYID 0x00002000
-#define MAX_BLOCKS (FLASH_SIZE / 256 + 100)
+#define MAX_BLOCKS (CFG_UF2_FLASH_SIZE / 256 + 100)
typedef struct {
uint32_t numBlocks;
uint32_t numWritten;
+
+ bool aborted; // aborting update and reset
+ bool update_bootloader; // if updating bootloader (else app)
+ bool has_uicr; // if containing uicr data
+ bool boot_id_matches; // if bootloader id in cf2 config matches our VID/PID
+
uint8_t writtenMask[MAX_BLOCKS / 8 + 1];
} WriteState;
@@ -78,77 +79,6 @@ typedef struct {
uint32_t magicEnd;
} UF2_Block;
-typedef struct {
- uint8_t version;
- uint8_t ep_in;
- uint8_t ep_out;
- uint8_t reserved0;
- uint32_t cbw_tag;
- uint32_t blocks_remaining;
- uint8_t *buffer;
-} UF2_HandoverArgs;
-
-typedef void (*UF2_MSC_Handover_Handler)(UF2_HandoverArgs *handover);
-typedef void (*UF2_HID_Handover_Handler)(int ep);
-
-// this is required to be exactly 16 bytes long by the linker script
-typedef struct {
- void *reserved0;
- UF2_HID_Handover_Handler handoverHID;
- UF2_MSC_Handover_Handler handoverMSC;
- const char *info_uf2;
-} UF2_BInfo;
-
-#define UF2_BINFO ((UF2_BInfo *)(APP_START_ADDRESS - sizeof(UF2_BInfo)))
-
-static inline bool is_uf2_block(void *data) {
- UF2_Block *bl = (UF2_Block *)data;
- return bl->magicStart0 == UF2_MAGIC_START0 && bl->magicStart1 == UF2_MAGIC_START1 &&
- bl->magicEnd == UF2_MAGIC_END;
-}
-
-static inline bool in_uf2_bootloader_space(const void *addr) {
- return USER_FLASH_END <= (uint32_t)addr && (uint32_t)addr < FLASH_SIZE;
-}
-
-
-#ifdef UF2_DEFINE_HANDOVER
-static inline const char *uf2_info(void) {
- if (in_uf2_bootloader_space(UF2_BINFO->info_uf2))
- return UF2_BINFO->info_uf2;
- return "N/A";
-}
-
-static inline void hf2_handover(uint8_t ep) {
- const char *board_info = UF2_BINFO->info_uf2;
- UF2_HID_Handover_Handler fn = UF2_BINFO->handoverHID;
-
- if (in_uf2_bootloader_space(board_info) && in_uf2_bootloader_space((const void *)fn) &&
- ((uint32_t)fn & 1)) {
- // Pass control to bootloader; never returns
- fn(ep & 0xf);
- }
-}
-
-// the ep_in/ep_out are without the 0x80 mask
-// cbw_tag is in the same bit format as it came
-static inline void check_uf2_handover(uint8_t *buffer, uint32_t blocks_remaining, uint8_t ep_in,
- uint8_t ep_out, uint32_t cbw_tag) {
- if (!is_uf2_block(buffer))
- return;
-
- const char *board_info = UF2_BINFO->info_uf2;
- UF2_MSC_Handover_Handler fn = UF2_BINFO->handoverMSC;
-
- if (in_uf2_bootloader_space(board_info) && in_uf2_bootloader_space((const void *)fn) &&
- ((uint32_t)fn & 1)) {
- UF2_HandoverArgs hand = {
- 1, ep_in, ep_out, 0, cbw_tag, blocks_remaining, buffer,
- };
- // Pass control to bootloader; never returns
- fn(&hand);
- }
-}
-#endif
+void uf2_init(void);
#endif
diff --git a/src/usb/uf2/uf2cfg.h b/src/usb/uf2/uf2cfg.h
index a100f44..df06f24 100644
--- a/src/usb/uf2/uf2cfg.h
+++ b/src/usb/uf2/uf2cfg.h
@@ -1,17 +1,24 @@
#include "boards.h"
+#include "dfu_types.h"
-#define UF2_NUM_BLOCKS 8000 // at least 4,1 MB for FAT16
+// Family ID for updating Application
+#define CFG_UF2_FAMILY_APP_ID 0xADA52840
-#ifndef UF2_VOLUME_LABEL
-#define UF2_VOLUME_LABEL "NRF52BOOT "
-#endif
+// Family ID for updating Bootloader
+#define CFG_UF2_FAMILY_BOOT_ID 0xd663823c
-#define FLASH_SIZE (USER_FLASH_END-USER_FLASH_START) // Max flash size
+#define CFG_UF2_NUM_BLOCKS 8000 // at least 4,1 MB for FAT16
+#define CFG_UF2_FLASH_SIZE (1024*1024) // 1 MB
-// Only allow to write application TODO dynamic depending on SD size
-#define USER_FLASH_START 0x26000
-#define USER_FLASH_END 0xAD000 // Fat Fs start here
+// Application Address Space
+#define USER_FLASH_START MBR_SIZE // skip MBR included in SD hex
+#define USER_FLASH_END 0xAD000
-#define FLASH_PAGE_SIZE 4096
+// Bootloader start address
+#define BOOTLOADER_ADDR_START BOOTLOADER_REGION_START
-#define UF2_FAMILY_ID 0xADA52840
+// Bootloader end address
+#define BOOTLOADER_ADDR_END BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS
+
+// Address where new bootloader is written before activation (skip application data)
+#define BOOTLOADER_ADDR_NEW_RECIEVED (USER_FLASH_END-DFU_BL_IMAGE_MAX_SIZE)
diff --git a/src/usb/usb.c b/src/usb/usb.c
index 0115072..6a48483 100644
--- a/src/usb/usb.c
+++ b/src/usb/usb.c
@@ -24,16 +24,14 @@
#include "nrfx.h"
#include "nrfx_power.h"
-
-#ifdef SOFTDEVICE_PRESENT
#include "nrf_sdm.h"
#include "nrf_soc.h"
-#endif
#include "nrf_usbd.h"
#include "tusb.h"
#include "usb_desc.h"
+#include "uf2/uf2.h"
#include "boards.h"
//--------------------------------------------------------------------+
@@ -44,27 +42,39 @@
* We must call it within SD's SOC event handler, or set it as power event handler if SD is not enabled. */
extern void tusb_hal_nrf_power_event(uint32_t event);
+//--------------------------------------------------------------------+
+// Forward USB interrupt events to TinyUSB IRQ Handler
+//--------------------------------------------------------------------+
+void USBD_IRQHandler(void)
+{
+ tud_int_handler(0);
+}
+
//------------- IMPLEMENTATION -------------//
void usb_init(bool cdc_only)
{
+ // 0, 1 is reserved for SD
NVIC_SetPriority(USBD_IRQn, 2);
// USB power may already be ready at this time -> no event generated
// We need to invoke the handler based on the status initially
uint32_t usb_reg;
-#ifdef SOFTDEVICE_PRESENT
uint8_t sd_en = false;
- (void) sd_softdevice_is_enabled(&sd_en);
- if ( sd_en ) {
+ if ( is_sd_existed() )
+ {
+ sd_softdevice_is_enabled(&sd_en);
+ }
+
+ if ( sd_en )
+ {
sd_power_usbdetected_enable(true);
sd_power_usbpwrrdy_enable(true);
sd_power_usbremoved_enable(true);
sd_power_usbregstatus_get(&usb_reg);
}else
-#endif
{
// Power module init
const nrfx_power_config_t pwr_cfg = { 0 };
@@ -89,32 +99,16 @@ void usb_init(bool cdc_only)
usb_desc_init(cdc_only);
+ uf2_init();
+
// Init TinyUSB stack
tusb_init();
}
void usb_teardown(void)
{
- if ( NRF_USBD->ENABLE )
- {
- // Abort all transfers
-
- // Disable pull up
- nrf_usbd_pullup_disable(NRF_USBD);
-
- // Disable Interrupt
- NVIC_DisableIRQ(USBD_IRQn);
-
- // disable all interrupt
- NRF_USBD->INTENCLR = NRF_USBD->INTEN;
-
- nrf_usbd_disable(NRF_USBD);
- sd_clock_hfclk_release();
-
- sd_power_usbdetected_enable(false);
- sd_power_usbpwrrdy_enable(false);
- sd_power_usbremoved_enable(false);
- }
+ // Simulate an disconnect which cause pullup disable, USB perpheral disable and hclk disable
+ tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_REMOVED);
}
//--------------------------------------------------------------------+
diff --git a/src/usb/usb_desc.c b/src/usb/usb_desc.c
index 5d7779b..effc252 100644
--- a/src/usb/usb_desc.c
+++ b/src/usb/usb_desc.c
@@ -87,7 +87,7 @@ enum {
uint8_t const desc_configuration_cdc_msc[] =
{
// Interface count, string index, total length, attribute, power in mA
- TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
+ TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, ITF_STR_CDC, 0x81, 8, 0x02, 0x82, 64),
@@ -99,7 +99,7 @@ uint8_t const desc_configuration_cdc_msc[] =
uint8_t const desc_configuration_cdc_only[] =
{
// Interface count, string index, total length, attribute, power in mA
- TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL-1, 0, TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
+ TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL-1, 0, TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, ITF_STR_CDC, 0x81, 8, 0x02, 0x82, 64),
diff --git a/tools/build_all.py b/tools/build_all.py
index 24640f5..486afa8 100644
--- a/tools/build_all.py
+++ b/tools/build_all.py
@@ -18,7 +18,8 @@ build_separator = '-' * 74
# All supported boards
all_boards = []
for entry in os.scandir("src/boards"):
- all_boards.append(entry.name)
+ if entry.is_dir():
+ all_boards.append(entry.name)
all_boards.sort()
#sha, version = build_info.get_version_info()
@@ -34,7 +35,7 @@ for board in all_boards:
os.makedirs(bin_directory, exist_ok=True)
start_time = time.monotonic()
- make_result = subprocess.run("make -j 4 BOARD={} all genpkg".format(board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ make_result = subprocess.run("make -j 4 BOARD={} all".format(board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
build_duration = time.monotonic() - start_time
flash_size = "-"
@@ -55,9 +56,10 @@ for board in all_boards:
fail_count += 1
for entry in os.scandir("_build/build-{}".format(board)):
- for extension in ["zip", "hex"]:
- if entry.name.endswith(extension) and "nosd" not in entry.name:
- shutil.copy(entry.path, bin_directory)
+ for extension in ["zip", "hex", "uf2"]:
+ if entry.name.endswith(extension):
+ if ("nosd" in entry.name) or ("s140" in entry.name) or ("s132" in entry.name):
+ shutil.copy(entry.path, bin_directory)
print(build_format.format(board, success, "{:.2f}s".format(build_duration), flash_size, sram_size))
diff --git a/tools/hexmerge.py b/tools/hexmerge.py
new file mode 100755
index 0000000..9359662
--- /dev/null
+++ b/tools/hexmerge.py
@@ -0,0 +1,178 @@
+#!/usr/bin/python
+
+# Copyright (c) 2008-2018 Alexander Belchenko
+# 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 author nor the names
+# of its contributors may be used to endorse
+# or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+
+"""Merge content of several hex files into one file."""
+
+VERSION = '2.2.1'
+
+USAGE = '''hexmerge: merge content of hex files.
+Usage:
+ python hexmerge.py [options] FILES...
+
+Options:
+ -h, --help this help message.
+ -v, --version version info.
+ -o, --output=FILENAME output file name (emit output to stdout
+ if option is not specified)
+ -r, --range=START:END specify address range for output
+ (ascii hex value). Both values are inclusive.
+ Range can be in form 'START:' or ':END'.
+ --no-start-addr Don't write start addr to output file.
+ --overlap=METHOD What to do when data in files overlapped.
+ Supported variants:
+ * error -- stop and show error message (default)
+ * ignore -- keep data from first file that
+ contains data at overlapped address
+ * replace -- use data from last file that
+ contains data at overlapped address
+
+Arguments:
+ FILES list of hex files for merging
+ (use '-' to read content from stdin)
+
+You can specify address range for each file in the form:
+
+ filename:START:END
+
+See description of range option above.
+
+You can omit START or END, so supported variants are:
+
+ filename:START: read filename and use data starting from START addr
+ filename::END read filename and use data till END addr
+
+Use entire file content:
+
+ filename
+or
+ filename::
+'''
+
+import sys
+
+
+def main(args=None):
+ import getopt
+
+ output = None
+ start = None
+ end = None
+ write_start_addr = True
+ overlap = 'error'
+
+ if args is None:
+ args = sys.argv[1:]
+ try:
+ opts, args = getopt.gnu_getopt(args, 'hvo:r:',
+ ['help', 'version',
+ 'output=', 'range=',
+ 'no-start-addr', 'overlap=',
+ ])
+
+ for o,a in opts:
+ if o in ('-h', '--help'):
+ print(USAGE)
+ return 0
+ elif o in ('-v', '--version'):
+ print(VERSION)
+ return 0
+ elif o in ('-o', '--output'):
+ output = a
+ elif o in ("-r", "--range"):
+ try:
+ l = a.split(":")
+ if l[0] != '':
+ start = int(l[0], 16)
+ if l[1] != '':
+ end = int(l[1], 16)
+ except (ValueError, IndexError):
+ raise getopt.GetoptError('Bad range value(s)')
+ elif o == '--no-start-addr':
+ write_start_addr = False
+ elif o == '--overlap':
+ if a in ('error', 'ignore', 'replace'):
+ overlap = a
+ else:
+ raise getopt.GetoptError('Bad overlap value')
+
+ if len(args) == 0:
+ raise getopt.GetoptError('You should specify file list')
+
+ except getopt.GetoptError:
+ e = sys.exc_info()[1] # current exception
+ sys.stderr.write(str(e)+"\n")
+ sys.stderr.write(USAGE+"\n")
+ return 1
+
+ import intelhex
+ # TODO: move actual merge code into intelhex package as helper function
+ # and write couple of tests for it.
+ res = intelhex.IntelHex()
+
+ def end_addr_inclusive(addr):
+ if addr is not None:
+ return addr + 1
+ return addr
+
+ for f in args:
+ try:
+ fname, fstart, fend = intelhex._get_file_and_addr_range(f)
+ except intelhex._BadFileNotation:
+ sys.stderr.write('Bad argument: "%s"\n' % f)
+ sys.stderr.write(USAGE+"\n")
+ return 1
+ if fname == '-':
+ fname = sys.stdin
+ ih = intelhex.IntelHex(fname)
+ if (fstart, fend) != (None, None):
+ ih = ih[fstart:end_addr_inclusive(fend)]
+ try:
+ res.merge(ih, overlap)
+ except intelhex.AddressOverlapError:
+ e = sys.exc_info()[1] # current exception
+ sys.stderr.write('Merging: '+fname+"\n")
+ sys.stderr.write(str(e)+"\n")
+ return 1
+
+ if (start, end) != (None, None):
+ res = res[start:end_addr_inclusive(end)]
+ if output is None:
+ output = sys.stdout
+ res.write_hex_file(output, write_start_addr)
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())