From be87aac09d5d9b3ff96c986486cf00e99467757f Mon Sep 17 00:00:00 2001 From: Yihui Xiong Date: Mon, 3 Feb 2020 03:08:59 +0000 Subject: [PATCH 01/61] step to no softdevice --- .../components/libraries/util/app_util_platform.c | 2 -- .../components/libraries/util/app_util_platform.h | 2 -- .../components/libraries/bootloader_dfu/bootloader.c | 12 +++++++++--- .../components/libraries/bootloader_dfu/dfu_types.h | 5 ++++- src/main.c | 3 ++- src/usb/uf2/uf2.h | 2 -- src/usb/uf2/uf2cfg.h | 5 +++++ src/usb/usb.c | 3 +++ 8 files changed, 23 insertions(+), 11 deletions(-) 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/libraries/bootloader_dfu/bootloader.c b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c index 2ad777f..b177aa6 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c @@ -169,7 +169,7 @@ bool bootloader_app_is_valid(uint32_t app_addr) // 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, + image_crc = crc16_compute((uint8_t *)app_addr, p_bootloader_settings->bank_0_size, NULL); } @@ -375,9 +375,11 @@ static void interrupts_disable(void) void bootloader_app_start(uint32_t app_addr) { +#ifdef SOFTDEVICE_PRESENT // 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() ); +#endif interrupts_disable(); @@ -391,9 +393,13 @@ void bootloader_app_start(uint32_t app_addr) sd_mbr_command(&command); #endif - APP_ERROR_CHECK( sd_softdevice_vector_table_base_set(CODE_REGION_1_START) ); +#ifdef SOFTDEVICE_PRESENT + APP_ERROR_CHECK( sd_softdevice_vector_table_base_set(app_addr) ); +#else + SCB->VTOR = app_addr; +#endif - bootloader_util_app_start(CODE_REGION_1_START); + bootloader_util_app_start(app_addr); } diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h b/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h index 2ed7ba4..9cc7727 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h @@ -29,10 +29,13 @@ #include "nrf.h" #include "app_util.h" +#define SD_MAGIC_NUMBER 0x51b1e5db +#define SD_MAGIC_OK() (*((uint32_t*)(SOFTDEVICE_INFO_STRUCT_ADDRESS+4)) == 0x51b1e5db) + #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. */ +#define CODE_REGION_1_START (SD_MAGIC_OK() ? 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. */ diff --git a/src/main.c b/src/main.c index 5a74640..f134c8a 100644 --- a/src/main.c +++ b/src/main.c @@ -258,9 +258,10 @@ int main(void) // Jump to application if valid if (bootloader_app_is_valid(DFU_BANK_0_REGION_START) && !bootloader_dfu_sd_in_progress()) { +#ifdef SOFTDEVICE_PRESENT // MBR must be init before start application if ( !sd_inited ) softdev_mbr_init(); - +#endif // 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); diff --git a/src/usb/uf2/uf2.h b/src/usb/uf2/uf2.h index 6edbb4f..788b99b 100644 --- a/src/usb/uf2/uf2.h +++ b/src/usb/uf2/uf2.h @@ -39,8 +39,6 @@ SOFTWARE. #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. diff --git a/src/usb/uf2/uf2cfg.h b/src/usb/uf2/uf2cfg.h index a100f44..55fb588 100644 --- a/src/usb/uf2/uf2cfg.h +++ b/src/usb/uf2/uf2cfg.h @@ -9,7 +9,12 @@ #define FLASH_SIZE (USER_FLASH_END-USER_FLASH_START) // Max flash size // Only allow to write application TODO dynamic depending on SD size +#ifdef SOFTDEVICE_PRESENT #define USER_FLASH_START 0x26000 +#else +#define USER_FLASH_START 0x1000 +#endif + #define USER_FLASH_END 0xAD000 // Fat Fs start here #define FLASH_PAGE_SIZE 4096 diff --git a/src/usb/usb.c b/src/usb/usb.c index 0115072..ab6b39d 100644 --- a/src/usb/usb.c +++ b/src/usb/usb.c @@ -109,11 +109,14 @@ void usb_teardown(void) NRF_USBD->INTENCLR = NRF_USBD->INTEN; nrf_usbd_disable(NRF_USBD); + +#if defined(SOFTDEVICE_PRESENT) sd_clock_hfclk_release(); sd_power_usbdetected_enable(false); sd_power_usbpwrrdy_enable(false); sd_power_usbremoved_enable(false); +#endif } } From c467875ca3ce4104b306f2a2649574b60114db57 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 26 Mar 2020 13:06:44 +0700 Subject: [PATCH 02/61] clean up --- .../components/libraries/bootloader_dfu/bootloader.c | 9 +++------ .../libraries/bootloader_dfu/dfu_bank_internal.h | 1 - .../libraries/bootloader_dfu/dfu_transport_ble.c | 2 -- src/boards/feather_nrf52840_express/board.h | 9 --------- src/main.c | 11 ++++++++++- src/usb/msc_uf2.c | 4 ++-- src/usb/uf2/ghostfat.c | 4 +--- src/usb/uf2/uf2.h | 9 ++++----- 8 files changed, 20 insertions(+), 29 deletions(-) diff --git a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c index 44465a3..75641e9 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c @@ -36,10 +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 @@ -118,7 +114,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); @@ -362,9 +358,10 @@ static void interrupts_disable(void) // Fetch the current interrupt settings. interrupt_setting_mask = NVIC->ISER[0]; + // TODO 48 exceed 32 bit, should be ISER[1] for (; irq < MAX_NUMBER_INTERRUPTS; irq++) { - if (interrupt_setting_mask & (IRQ_ENABLED << irq)) + if (interrupt_setting_mask & (1ul << irq)) { // The interrupt was enabled, and hence disable it. NVIC_DisableIRQ((IRQn_Type)irq); 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_transport_ble.c b/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c index d731d31..cbb3479 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). */ 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/main.c b/src/main.c index 5c974c1..884a130 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 @@ -134,7 +138,9 @@ enum { BLE_CONN_CFG_HIGH_BANDWIDTH = 1 }; STATIC_ASSERT( APPDATA_ADDR_START == 0x6D000); #endif - +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ void adafruit_factory_reset(void); static uint32_t softdev_init(bool init_softdevice); @@ -155,6 +161,9 @@ void softdev_mbr_init(void) sd_mbr_command(&com); } +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ int main(void) { // SD is already Initialized in case of BOOTLOADER_DFU_OTA_MAGIC diff --git a/src/usb/msc_uf2.c b/src/usb/msc_uf2.c index 8b3d7dc..71ea824 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 @@ -145,7 +145,7 @@ int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* uint32_t count = 0; int wr_ret; - while ( (count < bufsize) && ((wr_ret = write_block(lba, buffer, false, &_wr_state)) > 0) ) + while ( (count < bufsize) && ((wr_ret = write_block(lba, buffer, &_wr_state)) > 0) ) { lba++; buffer += 512; diff --git a/src/usb/uf2/ghostfat.c b/src/usb/uf2/ghostfat.c index e6a2c67..945e02d 100644 --- a/src/usb/uf2/ghostfat.c +++ b/src/usb/uf2/ghostfat.c @@ -93,7 +93,6 @@ 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 UF2_SIZE (current_flash_size() * 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 @@ -295,7 +294,7 @@ void read_block(uint32_t block_no, uint8_t *data) { * 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) { +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); @@ -316,7 +315,6 @@ int write_block(uint32_t block_no, uint8_t *data, bool quiet, WriteState *state) // 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; diff --git a/src/usb/uf2/uf2.h b/src/usb/uf2/uf2.h index 6edbb4f..eae5054 100644 --- a/src/usb/uf2/uf2.h +++ b/src/usb/uf2/uf2.h @@ -44,13 +44,12 @@ SOFTWARE. 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) From 8e85c9aa8a5056e59d9d30d9e3891940704e04ab Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 26 Mar 2020 15:12:13 +0700 Subject: [PATCH 03/61] add uf2 as submodule --- .gitmodules | 3 +++ lib/uf2 | 1 + 2 files changed, 4 insertions(+) create mode 160000 lib/uf2 diff --git a/.gitmodules b/.gitmodules index 8acbe85..1ff4b5a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [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/lib/uf2 b/lib/uf2 new file mode 160000 index 0000000..adbb8c7 --- /dev/null +++ b/lib/uf2 @@ -0,0 +1 @@ +Subproject commit adbb8c7260f938e810eb37f2287f8e1a055ff402 From e92937e9d59f92df991c547ea49a3a53af5fb5de Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 26 Mar 2020 16:32:41 +0700 Subject: [PATCH 04/61] still clean up --- .../bootloader_dfu/dfu_single_bank.c | 3 +- src/usb/uf2/configkeys.h | 334 ++++++++++++++++++ src/usb/uf2/ghostfat.c | 24 +- src/usb/uf2/uf2cfg.h | 2 - 4 files changed, 351 insertions(+), 12 deletions(-) create mode 100644 src/usb/uf2/configkeys.h 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..82e2728 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 diff --git a/src/usb/uf2/configkeys.h b/src/usb/uf2/configkeys.h new file mode 100644 index 0000000..09e90b5 --- /dev/null +++ b/src/usb/uf2/configkeys.h @@ -0,0 +1,334 @@ +#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_MAGIC0 0x1e9e10f1 +#define CFG_MAGIC1 0x20227a79 +#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 945e02d..de0f02c 100644 --- a/src/usb/uf2/ghostfat.c +++ b/src/usb/uf2/ghostfat.c @@ -10,6 +10,10 @@ #include "bootloader_settings.h" #include "bootloader.h" +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + typedef struct { uint8_t JumpInstruction[3]; uint8_t OEMInfo[8]; @@ -55,6 +59,11 @@ struct TextFile { char const *content; }; + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + #define NUM_FAT_BLOCKS UF2_NUM_BLOCKS #define STR0(x) #x @@ -134,8 +143,9 @@ static FAT_BootBlock const BootBlock = { .FilesystemIdentifier = "FAT16 ", }; -#define NRF_LOG_DEBUG(...) -#define NRF_LOG_WARNING(...) +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ // get current.uf2 flash size in bytes, round up to 256 bytes static uint32_t current_flash_size(void) @@ -297,8 +307,6 @@ void read_block(uint32_t block_no, uint8_t *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; } @@ -309,13 +317,13 @@ int write_block(uint32_t block_no, uint8_t *data, WriteState *state) { } if ((bl->flags & UF2_FLAG_NOFLASH) || bl->payloadSize > 256 || (bl->targetAddr & 0xff) || - bl->targetAddr < USER_FLASH_START || bl->targetAddr + bl->payloadSize > USER_FLASH_END) { + (bl->targetAddr < USER_FLASH_START) || (bl->targetAddr + bl->payloadSize > USER_FLASH_END) ) { - NRF_LOG_WARNING("Skip block at %x", bl->targetAddr); + //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 { - NRF_LOG_DEBUG("Write block at %x", bl->targetAddr); + //NRF_LOG_DEBUG("Write block at %x", bl->targetAddr); static bool first_write = true; if ( first_write ) { @@ -346,7 +354,7 @@ int write_block(uint32_t block_no, uint8_t *data, WriteState *state) { flash_nrf5x_flush(true); } } - NRF_LOG_DEBUG("wr %d=%d (of %d)", state->numWritten, bl->blockNo, bl->numBlocks); + //NRF_LOG_DEBUG("wr %d=%d (of %d)", state->numWritten, bl->blockNo, bl->numBlocks); } return 512; diff --git a/src/usb/uf2/uf2cfg.h b/src/usb/uf2/uf2cfg.h index a100f44..ec6dbcc 100644 --- a/src/usb/uf2/uf2cfg.h +++ b/src/usb/uf2/uf2cfg.h @@ -12,6 +12,4 @@ #define USER_FLASH_START 0x26000 #define USER_FLASH_END 0xAD000 // Fat Fs start here -#define FLASH_PAGE_SIZE 4096 - #define UF2_FAMILY_ID 0xADA52840 From 9a7eeeb4990fd2f3f899e1d7c2fab98e45c5a9a8 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 26 Mar 2020 23:57:22 +0700 Subject: [PATCH 05/61] use SD_FLASH_SIZE + MBR_SIZE for USER_FLASH_START --- src/boards.h | 4 +++ src/usb/uf2/ghostfat.c | 60 ++++++++++++++++----------------- src/usb/uf2/uf2.h | 75 ++++-------------------------------------- src/usb/uf2/uf2cfg.h | 7 +--- src/usb/usb.c | 3 ++ 5 files changed, 44 insertions(+), 105 deletions(-) diff --git a/src/boards.h b/src/boards.h index 595f232..4a658ec 100644 --- a/src/boards.h +++ b/src/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 diff --git a/src/usb/uf2/ghostfat.c b/src/usb/uf2/ghostfat.c index de0f02c..1180214 100644 --- a/src/usb/uf2/ghostfat.c +++ b/src/usb/uf2/ghostfat.c @@ -102,7 +102,7 @@ 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 UF2_SIZE (current_flash_size() * 2) +#define UF2_SIZE (uf2current_flash_sz * 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) @@ -146,48 +146,48 @@ static FAT_BootBlock const BootBlock = { //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ +static uint32_t uf2current_flash_sz = 0; + // get current.uf2 flash size in bytes, round up to 256 bytes static uint32_t current_flash_size(void) { - static uint32_t flash_sz = 0; - uint32_t result = flash_sz; // presumes atomic 32-bit read/write and static result + uint32_t flash_sz = 0; - // only need to compute once - if ( result == 0 ) + // return 1 block of 256 bytes + if ( !bootloader_app_is_valid(DFU_BANK_0_REGION_START) ) { - // return 1 block of 256 bytes - if ( !bootloader_app_is_valid(DFU_BANK_0_REGION_START) ) + flash_sz = 256; + }else + { + bootloader_settings_t const * boot_setting; + bootloader_util_settings_get(&boot_setting); + + flash_sz = boot_setting->bank_0_size; + + // Copy size must be multiple of 256 bytes + // else we will got an issue copying current.uf2 + if (flash_sz & 0xff) { - 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 = (flash_sz & ~0xff) + 256; } - flash_sz = result; // presumes atomic 32-bit read/write and static result + // if bank0 size is not valid, happens when flashed with jlink + // use maximum application size + if ( (flash_sz == 0) || (flash_sz == 0xFFFFFFFFUL) ) + { + flash_sz = FLASH_SIZE; + } } return flash_sz; } +void uf2_init(void) +{ + uf2current_flash_sz = current_flash_size(); +} + void padded_memcpy (char *dst, char const *src, int len) { for ( int i = 0; i < len; ++i ) @@ -282,7 +282,7 @@ void read_block(uint32_t block_no, uint8_t *data) { bl->magicStart1 = UF2_MAGIC_START1; bl->magicEnd = UF2_MAGIC_END; bl->blockNo = sectionIdx; - bl->numBlocks = current_flash_size() / 256; + bl->numBlocks = uf2current_flash_sz / 256; bl->targetAddr = addr; bl->payloadSize = 256; bl->flags = UF2_FLAG_FAMILYID; diff --git a/src/usb/uf2/uf2.h b/src/usb/uf2/uf2.h index eae5054..3b55ba0 100644 --- a/src/usb/uf2/uf2.h +++ b/src/usb/uf2/uf2.h @@ -36,12 +36,11 @@ SOFTWARE. #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" @@ -77,77 +76,15 @@ 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; +static inline bool is_uf2_block(UF2_Block const *bl) { 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; + 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 ec6dbcc..11de527 100644 --- a/src/usb/uf2/uf2cfg.h +++ b/src/usb/uf2/uf2cfg.h @@ -1,15 +1,10 @@ #include "boards.h" #define UF2_NUM_BLOCKS 8000 // at least 4,1 MB for FAT16 - -#ifndef UF2_VOLUME_LABEL -#define UF2_VOLUME_LABEL "NRF52BOOT " -#endif - #define FLASH_SIZE (USER_FLASH_END-USER_FLASH_START) // Max flash size // Only allow to write application TODO dynamic depending on SD size -#define USER_FLASH_START 0x26000 +#define USER_FLASH_START (SD_FLASH_SIZE + MBR_SIZE) #define USER_FLASH_END 0xAD000 // Fat Fs start here #define UF2_FAMILY_ID 0xADA52840 diff --git a/src/usb/usb.c b/src/usb/usb.c index 0115072..c0903ca 100644 --- a/src/usb/usb.c +++ b/src/usb/usb.c @@ -34,6 +34,7 @@ #include "tusb.h" #include "usb_desc.h" +#include "uf2/uf2.h" #include "boards.h" //--------------------------------------------------------------------+ @@ -89,6 +90,8 @@ void usb_init(bool cdc_only) usb_desc_init(cdc_only); + uf2_init(); + // Init TinyUSB stack tusb_init(); } From 1c48833336203eef4c3c09423802e1e83013209b Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 27 Mar 2020 00:12:49 +0700 Subject: [PATCH 06/61] more cleanup --- src/usb/uf2/ghostfat.c | 4 ++-- src/usb/uf2/uf2.h | 4 ++-- src/usb/uf2/uf2cfg.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/usb/uf2/ghostfat.c b/src/usb/uf2/ghostfat.c index 1180214..72cadaf 100644 --- a/src/usb/uf2/ghostfat.c +++ b/src/usb/uf2/ghostfat.c @@ -286,7 +286,7 @@ void read_block(uint32_t block_no, uint8_t *data) { bl->targetAddr = addr; bl->payloadSize = 256; bl->flags = UF2_FLAG_FAMILYID; - bl->familyID = UF2_FAMILY_ID; + bl->familyID = CFG_UF2_FAMILY_ID; memcpy(bl->data, (void *)addr, bl->payloadSize); } } @@ -312,7 +312,7 @@ int write_block(uint32_t block_no, uint8_t *data, WriteState *state) { } // only accept block with same family id - if ( UF2_FAMILY_ID && !((bl->flags & UF2_FLAG_FAMILYID) && (bl->familyID == UF2_FAMILY_ID)) ) { + if ( !((bl->flags & UF2_FLAG_FAMILYID) && (bl->familyID == CFG_UF2_FAMILY_ID)) ) { return -1; } diff --git a/src/usb/uf2/uf2.h b/src/usb/uf2/uf2.h index 3b55ba0..339b109 100644 --- a/src/usb/uf2/uf2.h +++ b/src/usb/uf2/uf2.h @@ -77,8 +77,8 @@ typedef struct { } UF2_Block; static inline bool is_uf2_block(UF2_Block const *bl) { - return bl->magicStart0 == UF2_MAGIC_START0 && bl->magicStart1 == UF2_MAGIC_START1 && - bl->magicEnd == UF2_MAGIC_END; + 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) { diff --git a/src/usb/uf2/uf2cfg.h b/src/usb/uf2/uf2cfg.h index 11de527..59ad984 100644 --- a/src/usb/uf2/uf2cfg.h +++ b/src/usb/uf2/uf2cfg.h @@ -7,4 +7,4 @@ #define USER_FLASH_START (SD_FLASH_SIZE + MBR_SIZE) #define USER_FLASH_END 0xAD000 // Fat Fs start here -#define UF2_FAMILY_ID 0xADA52840 +#define CFG_UF2_FAMILY_ID 0xADA52840 From 2b5dd6c6149b9e3c9b21cde54bd607fb2a8a8a21 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 27 Mar 2020 11:57:55 +0700 Subject: [PATCH 07/61] update makefile for uf2 target and ses --- Makefile | 25 +++--- segger/Adafruit_nRF52_Bootloader.emProject | 97 ++++++++-------------- 2 files changed, 49 insertions(+), 73 deletions(-) diff --git a/Makefile b/Makefile index 1ff8a65..09ffebc 100644 --- a/Makefile +++ b/Makefile @@ -204,9 +204,7 @@ INC_PATHS = $(addprefix -I,$(IPATH)) # Debugging/Optimization ifeq ($(DEBUG), 1) - CFLAGS += -Og -ggdb -else - CFLAGS += -Os + CFLAGS += -ggdb endif #flags common to all targets @@ -216,6 +214,7 @@ CFLAGS += \ -mcpu=cortex-m4 \ -mfloat-abi=hard \ -mfpu=fpv4-sp-d16 \ + -Os \ -ffunction-sections \ -fdata-sections \ -fno-builtin \ @@ -306,7 +305,7 @@ endif .PHONY: all clean flash dfu-flash sd gdbflash gdb # default target to build -all: $(BUILD)/$(OUT_FILE)-nosd.out $(BUILD)/$(MERGED_FILE).hex +all: $(BUILD)/$(OUT_FILE)-nosd.out $(BUILD)/$(MERGED_FILE).hex $(BUILD)/$(MERGED_FILE).uf2 #------------------- Flash target ------------------- @@ -319,7 +318,7 @@ __check_defined = \ # Flash the compiled flash: $(BUILD)/$(OUT_FILE)-nosd.hex - @echo Flashing: $< + @echo Flashing: $(notdir $<) $(NRFJPROG) --program $< --sectoranduicrerase -f nrf52 --reset dfu-flash: $(BUILD)/$(MERGED_FILE).zip @@ -339,7 +338,7 @@ gdb: $(BUILD)/$(OUT_FILE)-nosd.out #------------------- Compile rules ------------------- -## Create build directories +# Create build directories $(BUILD): @$(MK) $@ @@ -358,23 +357,27 @@ $(BUILD)/%.o: %.S # Link $(BUILD)/$(OUT_FILE)-nosd.out: $(BUILD) $(OBJECTS) - @echo LD $(OUT_FILE)-nosd.out + @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 +# Create hex file $(BUILD)/$(OUT_FILE)-nosd.hex: $(BUILD)/$(OUT_FILE)-nosd.out - @echo CR $(OUT_FILE)-nosd.hex + @echo CR $(notdir $@) @$(OBJCOPY) -O ihex $< $@ # merge bootloader and sd hex together $(BUILD)/$(MERGED_FILE).hex: $(BUILD)/$(OUT_FILE)-nosd.hex - @echo CR $(MERGED_FILE).hex + @echo CR $(notdir $@) @mergehex -q -m $< $(SD_HEX) -o $@ -## Create pkg zip file for bootloader+SD combo to use with DFU Serial +$(BUILD)/$(MERGED_FILE).uf2: $(BUILD)/$(MERGED_FILE).hex + @echo CR $(notdir $@) + python lib/uf2/utils/uf2conv.py -f 0x239A0029 -c -o $@ $^ + +# Create pkg zip file for bootloader+SD combo to use with DFU Serial .PHONY: genpkg genpkg: $(BUILD)/$(MERGED_FILE).zip diff --git a/segger/Adafruit_nRF52_Bootloader.emProject b/segger/Adafruit_nRF52_Bootloader.emProject index d5e8133..4f3766d 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" /> - + + + + + + + + + + + + + + + + + + + + + - From 56c6378c390d23ffd1a399d7855e1e003cfcbf40 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 27 Mar 2020 11:58:24 +0700 Subject: [PATCH 08/61] comment out unused code in ble_dis --- .../ble/ble_services/ble_dis/ble_dis.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) 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]; From b062026606d389f618fb522b4a830b321cde5761 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 27 Mar 2020 11:59:37 +0700 Subject: [PATCH 09/61] fix potential issue with interrupts_disable also clean up --- .../libraries/bootloader_dfu/bootloader.c | 19 ++++--------------- src/boards.h | 2 ++ src/dfu_ble_svc.c | 15 +++++++++------ src/usb/tusb_config.h | 4 ---- src/usb/uf2/uf2cfg.h | 2 +- 5 files changed, 16 insertions(+), 26 deletions(-) diff --git a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c index 75641e9..32d3e31 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c @@ -352,21 +352,10 @@ uint32_t bootloader_dfu_start(bool ota, uint32_t timeout_ms) */ static void interrupts_disable(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]; - - // TODO 48 exceed 32 bit, should be ISER[1] - for (; irq < MAX_NUMBER_INTERRUPTS; irq++) - { - if (interrupt_setting_mask & (1ul << irq)) - { - // The interrupt was enabled, and hence disable it. - NVIC_DisableIRQ((IRQn_Type)irq); - } - } + for (uint32_t irq = 0; irq < MAX_NUMBER_INTERRUPTS; irq++) + { + NVIC_DisableIRQ((IRQn_Type)irq); + } } diff --git a/src/boards.h b/src/boards.h index 4a658ec..30ad48d 100644 --- a/src/boards.h +++ b/src/boards.h @@ -115,6 +115,7 @@ bool is_ota(void); #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()) @@ -139,6 +140,7 @@ bool is_ota(void); #else +#define PRINTF(...) #define PRINT_LOCATION() #define PRINT_MESS(x) #define PRTNT_HEAP() 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/usb/tusb_config.h b/src/usb/tusb_config.h index 22611b2..688d76f 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 -------------// diff --git a/src/usb/uf2/uf2cfg.h b/src/usb/uf2/uf2cfg.h index 59ad984..9c8406a 100644 --- a/src/usb/uf2/uf2cfg.h +++ b/src/usb/uf2/uf2cfg.h @@ -7,4 +7,4 @@ #define USER_FLASH_START (SD_FLASH_SIZE + MBR_SIZE) #define USER_FLASH_END 0xAD000 // Fat Fs start here -#define CFG_UF2_FAMILY_ID 0xADA52840 +#define CFG_UF2_FAMILY_ID 0xADA52840 From 795fd2ee17cde54cf5dc8499b23d692f7f837b8c Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 27 Mar 2020 12:05:23 +0700 Subject: [PATCH 10/61] correct msc uf2 write, only skip 512 block, not the whole sector --- src/usb/msc_uf2.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/usb/msc_uf2.c b/src/usb/msc_uf2.c index 71ea824..4ef85b0 100644 --- a/src/usb/msc_uf2.c +++ b/src/usb/msc_uf2.c @@ -143,17 +143,18 @@ 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, &_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). From fe1a7ea4f2144153c31b1c43e0942fbfe66da2f1 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 27 Mar 2020 15:12:53 +0700 Subject: [PATCH 11/61] more with uf2 --- src/boards.h | 2 -- src/usb/uf2/ghostfat.c | 21 +++++++++------------ src/usb/uf2/uf2.h | 4 +++- src/usb/uf2/uf2cfg.h | 11 ++++++----- 4 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/boards.h b/src/boards.h index 30ad48d..1290308 100644 --- a/src/boards.h +++ b/src/boards.h @@ -118,7 +118,6 @@ bool is_ota(void); #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) ) @@ -143,7 +142,6 @@ bool is_ota(void); #define PRINTF(...) #define PRINT_LOCATION() #define PRINT_MESS(x) -#define PRTNT_HEAP() #define PRINT_STR(x) #define PRINT_INT(x) #define PRINT_HEX(x) diff --git a/src/usb/uf2/ghostfat.c b/src/usb/uf2/ghostfat.c index 72cadaf..b6aed2e 100644 --- a/src/usb/uf2/ghostfat.c +++ b/src/usb/uf2/ghostfat.c @@ -5,7 +5,6 @@ #include #include "boards.h" -#include "tusb.h" #include "bootloader_settings.h" #include "bootloader.h" @@ -99,8 +98,8 @@ static struct TextFile const info[] = { 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 (uf2current_flash_sz * 2) #define UF2_SECTORS (UF2_SIZE / 512) @@ -202,7 +201,7 @@ void padded_memcpy (char *dst, char const *src, int len) /*------------------------------------------------------------------*/ -/* Read +/* Read CURRENT.UF2 *------------------------------------------------------------------*/ void read_block(uint32_t block_no, uint8_t *data) { memset(data, 0, 512); @@ -311,19 +310,17 @@ int write_block(uint32_t block_no, uint8_t *data, WriteState *state) { return -1; } + // PRINTF("Addr = 0x%08X, Family = 0x%08X\n", bl->targetAddr, bl->familyID); + // only accept block with same family id - if ( !((bl->flags & UF2_FLAG_FAMILYID) && (bl->familyID == CFG_UF2_FAMILY_ID)) ) { + if ( !((bl->familyID == CFG_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) ) { + if ( (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 { - //NRF_LOG_DEBUG("Write block at %x", bl->targetAddr); + //PRINTF("Write block at %x", bl->targetAddr); static bool first_write = true; if ( first_write ) { @@ -354,7 +351,7 @@ int write_block(uint32_t block_no, uint8_t *data, WriteState *state) { flash_nrf5x_flush(true); } } - //NRF_LOG_DEBUG("wr %d=%d (of %d)", state->numWritten, bl->blockNo, bl->numBlocks); + //PRINTF("wr %d=%d (of %d)", state->numWritten, bl->blockNo, bl->numBlocks); } return 512; diff --git a/src/usb/uf2/uf2.h b/src/usb/uf2/uf2.h index 339b109..17f430a 100644 --- a/src/usb/uf2/uf2.h +++ b/src/usb/uf2/uf2.h @@ -78,7 +78,9 @@ typedef struct { static inline bool is_uf2_block(UF2_Block const *bl) { return (bl->magicStart0 == UF2_MAGIC_START0) && (bl->magicStart1 == UF2_MAGIC_START1) && - (bl->magicEnd == UF2_MAGIC_END); + (bl->magicEnd == UF2_MAGIC_END) && + (bl->flags & UF2_FLAG_FAMILYID) && !(bl->flags & UF2_FLAG_NOFLASH) && + (bl->payloadSize == 256) && !(bl->targetAddr & 0xff); } static inline bool in_uf2_bootloader_space(const void *addr) { diff --git a/src/usb/uf2/uf2cfg.h b/src/usb/uf2/uf2cfg.h index 9c8406a..27ebbaf 100644 --- a/src/usb/uf2/uf2cfg.h +++ b/src/usb/uf2/uf2cfg.h @@ -1,10 +1,11 @@ #include "boards.h" -#define UF2_NUM_BLOCKS 8000 // at least 4,1 MB for FAT16 -#define FLASH_SIZE (USER_FLASH_END-USER_FLASH_START) // Max flash size +#define UF2_NUM_BLOCKS 8000 // at least 4,1 MB for FAT16 +#define FLASH_SIZE (USER_FLASH_END-USER_FLASH_START) // Max flash size // Only allow to write application TODO dynamic depending on SD size -#define USER_FLASH_START (SD_FLASH_SIZE + MBR_SIZE) -#define USER_FLASH_END 0xAD000 // Fat Fs start here +#define USER_FLASH_START (SD_FLASH_SIZE + MBR_SIZE) +#define USER_FLASH_END 0xAD000 // Fat Fs start here -#define CFG_UF2_FAMILY_ID 0xADA52840 +#define CFG_UF2_FAMILY_ID 0xADA52840 +#define CFG_UF2_BOOTLOADER_ID ((USB_DESC_VID << 16) | USB_DESC_UF2_PID) From 3ee1955e1b84eed70fc7bce81f255b034842d377 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 27 Mar 2020 17:08:46 +0700 Subject: [PATCH 12/61] move first write to msc_uf2 for consistency --- src/usb/msc_uf2.c | 30 +++++++--- src/usb/uf2/ghostfat.c | 132 +++++++++++++++++++++++++---------------- src/usb/uf2/uf2.h | 11 ---- 3 files changed, 102 insertions(+), 71 deletions(-) diff --git a/src/usb/msc_uf2.c b/src/usb/msc_uf2.c index 4ef85b0..07bedef 100644 --- a/src/usb/msc_uf2.c +++ b/src/usb/msc_uf2.c @@ -160,19 +160,31 @@ int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* // 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; + + if ( _wr_state.numBlocks ) { - led_state(STATE_WRITING_FINISHED); + // Start LED writing pattern with first write + if (first_write) + { + first_write = false; + led_state(STATE_WRITING_STARTED); + } - dfu_update_status_t update_status; + // All block of uf2 file is complete --> complete DFU process + if (_wr_state.numWritten >= _wr_state.numBlocks) + { + led_state(STATE_WRITING_FINISHED); - 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; + dfu_update_status_t update_status; - bootloader_dfu_update_process(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; + + bootloader_dfu_update_process(update_status); + } } } diff --git a/src/usb/uf2/ghostfat.c b/src/usb/uf2/ghostfat.c index b6aed2e..8582bfc 100644 --- a/src/usb/uf2/ghostfat.c +++ b/src/usb/uf2/ghostfat.c @@ -4,8 +4,6 @@ #include "flash_nrf5x.h" #include -#include "boards.h" - #include "bootloader_settings.h" #include "bootloader.h" @@ -142,6 +140,33 @@ static FAT_BootBlock const BootBlock = { .FilesystemIdentifier = "FAT16 ", }; +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ +static inline bool is_uf2_block (UF2_Block const *bl) +{ + 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); +} + +static inline bool in_app_space (uint32_t addr) +{ + return USER_FLASH_START <= addr && addr < USER_FLASH_END; +} + +static inline bool in_softdevice_space (uint32_t addr) +{ + return addr < USER_FLASH_START; +} + +static inline bool in_uf2_bootloader_space (uint32_t addr) +{ + return USER_FLASH_END <= addr /*&& addr < FLASH_SIZE*/; +} + + //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ @@ -187,6 +212,9 @@ void uf2_init(void) uf2current_flash_sz = current_flash_size(); } +/*------------------------------------------------------------------*/ +/* Read CURRENT.UF2 + *------------------------------------------------------------------*/ void padded_memcpy (char *dst, char const *src, int len) { for ( int i = 0; i < len; ++i ) @@ -199,10 +227,6 @@ void padded_memcpy (char *dst, char const *src, int len) } } - -/*------------------------------------------------------------------*/ -/* Read CURRENT.UF2 - *------------------------------------------------------------------*/ void read_block(uint32_t block_no, uint8_t *data) { memset(data, 0, 512); uint32_t sectionIdx = block_no; @@ -303,56 +327,62 @@ void read_block(uint32_t block_no, uint8_t *data) { * 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, WriteState *state) { - UF2_Block *bl = (void *)data; +int write_block (uint32_t block_no, uint8_t *data, WriteState *state) +{ + UF2_Block *bl = (void*) data; - if (!is_uf2_block(bl)) { - return -1; + if ( !is_uf2_block(bl) ) return -1; + + PRINTF("Addr = 0x%08X, Family = 0x%08X\n", bl->targetAddr, bl->familyID); + + // only accept block with same family id + if ( !((bl->familyID == CFG_UF2_FAMILY_ID)) ) + { + return -1; + } + + if ( (bl->targetAddr < USER_FLASH_START) || (bl->targetAddr + bl->payloadSize > USER_FLASH_END) ) + { + + } + else + { + //PRINTF("Write block at %x", bl->targetAddr); + flash_nrf5x_write(bl->targetAddr, bl->data, bl->payloadSize, true); + } + + if ( state && bl->numBlocks ) + { + // Update state num blocks + if ( state->numBlocks != bl->numBlocks ) + { + if ( bl->numBlocks >= MAX_BLOCKS || state->numBlocks ) + state->numBlocks = 0xffffffff; + else + state->numBlocks = bl->numBlocks; } - // PRINTF("Addr = 0x%08X, Family = 0x%08X\n", bl->targetAddr, bl->familyID); + if ( bl->blockNo < MAX_BLOCKS ) + { + uint8_t const mask = 1 << (bl->blockNo % 8); + uint32_t const pos = bl->blockNo / 8; - // only accept block with same family id - if ( !((bl->familyID == CFG_UF2_FAMILY_ID)) ) { - return -1; + // 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 + if ( state->numWritten >= state->numBlocks ) + { + flash_nrf5x_flush(true); + } } - if ( (bl->targetAddr < USER_FLASH_START) || (bl->targetAddr + bl->payloadSize > USER_FLASH_END) ) { + //PRINTF("wr %d=%d (of %d)", state->numWritten, bl->blockNo, bl->numBlocks); + } - } else { - //PRINTF("Write block at %x", bl->targetAddr); - - static bool first_write = true; - if ( first_write ) { - first_write = false; - led_state(STATE_WRITING_STARTED); - } - - flash_nrf5x_write(bl->targetAddr, bl->data, bl->payloadSize, true); - } - - 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); - } - } - //PRINTF("wr %d=%d (of %d)", state->numWritten, bl->blockNo, bl->numBlocks); - } - - return 512; + return 512; } diff --git a/src/usb/uf2/uf2.h b/src/usb/uf2/uf2.h index 17f430a..5be1c95 100644 --- a/src/usb/uf2/uf2.h +++ b/src/usb/uf2/uf2.h @@ -76,17 +76,6 @@ typedef struct { uint32_t magicEnd; } UF2_Block; -static inline bool is_uf2_block(UF2_Block const *bl) { - 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); -} - -static inline bool in_uf2_bootloader_space(const void *addr) { - return USER_FLASH_END <= (uint32_t)addr /*&& (uint32_t)addr < FLASH_SIZE*/; -} - void uf2_init(void); #endif From 632e4611bf4d2f0fd1edfb5e971c43eb7cbe5fcb Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 27 Mar 2020 17:36:51 +0700 Subject: [PATCH 13/61] rename FLASH_SIZE to CFG_UF2_FLASH_SIZE, make it whole flash = 1MB also rename UF2_NUM_BLOCKS to CFG_UF2_NUM_BLOCKS --- src/usb/msc_uf2.c | 2 +- src/usb/uf2/ghostfat.c | 18 ++++++++++++++---- src/usb/uf2/uf2.h | 2 +- src/usb/uf2/uf2cfg.h | 4 ++-- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/usb/msc_uf2.c b/src/usb/msc_uf2.c index 07bedef..6bd0626 100644 --- a/src/usb/msc_uf2.c +++ b/src/usb/msc_uf2.c @@ -194,7 +194,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/uf2/ghostfat.c b/src/usb/uf2/ghostfat.c index 8582bfc..97b4211 100644 --- a/src/usb/uf2/ghostfat.c +++ b/src/usb/uf2/ghostfat.c @@ -61,7 +61,7 @@ struct TextFile { // //--------------------------------------------------------------------+ -#define NUM_FAT_BLOCKS UF2_NUM_BLOCKS +#define NUM_FAT_BLOCKS CFG_UF2_NUM_BLOCKS #define STR0(x) #x #define STR(x) STR0(x) @@ -200,7 +200,7 @@ static uint32_t current_flash_size(void) // use maximum application size if ( (flash_sz == 0) || (flash_sz == 0xFFFFFFFFUL) ) { - flash_sz = FLASH_SIZE; + flash_sz = (USER_FLASH_END-USER_FLASH_START); } } @@ -299,7 +299,7 @@ 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; @@ -320,7 +320,14 @@ void read_block(uint32_t block_no, uint8_t *data) { /* Write UF2 *------------------------------------------------------------------*/ -/** Write an block +/** + * Write an uf2 block wrapped by 512 sector. Writing behavior is different when upgrading: + * - Application + * - current App is erased and flash with new firmware with same starting address + * + * - SoftDevice + Bootloader + * - Current App is erased, contents of SD + bootloader is written to App starting address + * - Trigger the SD + Bootloader migration * * @return number of bytes processed, only 3 following values * -1 : if not an uf2 block @@ -341,6 +348,9 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state) return -1; } + +// if ( (bl->familyID == CFG_UF2_FAMILY_ID) && in_app_space(bl->targetAddr) ) + if ( (bl->targetAddr < USER_FLASH_START) || (bl->targetAddr + bl->payloadSize > USER_FLASH_END) ) { diff --git a/src/usb/uf2/uf2.h b/src/usb/uf2/uf2.h index 5be1c95..92e5ea3 100644 --- a/src/usb/uf2/uf2.h +++ b/src/usb/uf2/uf2.h @@ -51,7 +51,7 @@ SOFTWARE. #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; diff --git a/src/usb/uf2/uf2cfg.h b/src/usb/uf2/uf2cfg.h index 27ebbaf..689706a 100644 --- a/src/usb/uf2/uf2cfg.h +++ b/src/usb/uf2/uf2cfg.h @@ -1,7 +1,7 @@ #include "boards.h" -#define UF2_NUM_BLOCKS 8000 // at least 4,1 MB for FAT16 -#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 (SD_FLASH_SIZE + MBR_SIZE) From d142418b0fa7c368e1662aa114dcec1ffbed0dec Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 30 Mar 2020 16:23:56 +0700 Subject: [PATCH 14/61] update tinyusb submodule to 0.6.0 --- .gitmodules | 2 +- lib/tinyusb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 1ff4b5a..47b2bcb 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ -[submodule "tinyusb"] +[submodule "lib/tinyusb"] path = lib/tinyusb url = https://github.com/hathach/tinyusb.git [submodule "lib/nrfx"] diff --git a/lib/tinyusb b/lib/tinyusb index f2b761f..370dd18 160000 --- a/lib/tinyusb +++ b/lib/tinyusb @@ -1 +1 @@ -Subproject commit f2b761fee98cf9d09500e2475861e51c6ee58e61 +Subproject commit 370dd1839465e71caa3024f6f2347b701a94953d From 630a271372c004760bc6c2e7d947cada8101c64f Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 19 Apr 2020 14:36:13 +0700 Subject: [PATCH 15/61] update tinyusb --- lib/tinyusb | 2 +- src/usb/usb.c | 8 ++++++++ src/usb/usb_desc.c | 4 ++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/tinyusb b/lib/tinyusb index 370dd18..7f92e25 160000 --- a/lib/tinyusb +++ b/lib/tinyusb @@ -1 +1 @@ -Subproject commit 370dd1839465e71caa3024f6f2347b701a94953d +Subproject commit 7f92e255cf27541f3d673fbd80aededd0f462d00 diff --git a/src/usb/usb.c b/src/usb/usb.c index c0903ca..a05b5d6 100644 --- a/src/usb/usb.c +++ b/src/usb/usb.c @@ -45,6 +45,14 @@ * 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) { 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), From 3bf0635676b98be8358741db2f5870054c0758c7 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 23 Apr 2020 13:42:30 +0700 Subject: [PATCH 16/61] updating wip --- .../bootloader_dfu/bootloader_settings.c | 28 +++++++++---------- .../libraries/bootloader_dfu/dfu_types.h | 18 +++++------- src/usb/uf2/uf2.h | 3 -- src/usb/uf2/uf2cfg.h | 25 ++++++++++++----- 4 files changed, 39 insertions(+), 35 deletions(-) diff --git a/lib/sdk11/components/libraries/bootloader_dfu/bootloader_settings.c b/lib/sdk11/components/libraries/bootloader_dfu/bootloader_settings.c index 439d7a0..8367204 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader_settings.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader_settings.c @@ -16,38 +16,38 @@ #if defined ( __CC_ARM ) -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. */ + 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. */ #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. */ + 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. */ + __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 */ + 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 */ + 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. */ + __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 diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h b/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h index 2ed7ba4..568e12e 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h @@ -38,22 +38,18 @@ // 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. */ diff --git a/src/usb/uf2/uf2.h b/src/usb/uf2/uf2.h index 92e5ea3..a71bb32 100644 --- a/src/usb/uf2/uf2.h +++ b/src/usb/uf2/uf2.h @@ -35,9 +35,6 @@ SOFTWARE. #include #include -#include "app_util.h" -#include "dfu_types.h" - //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ diff --git a/src/usb/uf2/uf2cfg.h b/src/usb/uf2/uf2cfg.h index 689706a..276d484 100644 --- a/src/usb/uf2/uf2cfg.h +++ b/src/usb/uf2/uf2cfg.h @@ -1,11 +1,22 @@ #include "boards.h" +#include "dfu_types.h" -#define CFG_UF2_NUM_BLOCKS 8000 // at least 4,1 MB for FAT16 -#define CFG_UF2_FLASH_SIZE (1024*1024) // 1 MB +#define CFG_UF2_FAMILY_ID 0xADA52840 +#define CFG_UF2_BOOTLOADER_ID ((USB_DESC_VID << 16) | USB_DESC_UF2_PID) -// Only allow to write application TODO dynamic depending on SD size -#define USER_FLASH_START (SD_FLASH_SIZE + MBR_SIZE) -#define USER_FLASH_END 0xAD000 // Fat Fs start here +#define CFG_UF2_NUM_BLOCKS 8000 // at least 4,1 MB for FAT16 +#define CFG_UF2_FLASH_SIZE (1024*1024) // 1 MB -#define CFG_UF2_FAMILY_ID 0xADA52840 -#define CFG_UF2_BOOTLOADER_ID ((USB_DESC_VID << 16) | USB_DESC_UF2_PID) +// Softdevice Address Space +#define CFG_UF2_SOFTDEVICE_ADDR_START 0 +#define CFG_UF2_SOFTDEVICE_ADDR_END USER_FLASH_START + +// Application Address Space +#define USER_FLASH_START (SD_FLASH_SIZE + MBR_SIZE) +#define USER_FLASH_END 0xAD000 + +// Bootloader Address Space +#define CFG_UF2_BOOTLOADER_ADDR_START BOOTLOADER_REGION_START +#define CFG_UF2_BOOTLOADER_ADDR_END BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS + +//#define From 1c1104e9890576ba1b81edd26b5e6a4fe5e4ded8 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 4 May 2020 16:48:21 +0700 Subject: [PATCH 17/61] added RTT printf for debugging --- Makefile | 13 +- lib/SEGGER_RTT/License.txt | 34 + lib/SEGGER_RTT/README.txt | 20 + lib/SEGGER_RTT/RTT/SEGGER_RTT.c | 2005 +++++++++++++++++ lib/SEGGER_RTT/RTT/SEGGER_RTT.h | 321 +++ lib/SEGGER_RTT/RTT/SEGGER_RTT_ASM_ARMv7M.S | 235 ++ lib/SEGGER_RTT/RTT/SEGGER_RTT_Conf.h | 384 ++++ lib/SEGGER_RTT/RTT/SEGGER_RTT_printf.c | 500 ++++ .../Syscalls/SEGGER_RTT_Syscalls_GCC.c | 120 + .../Syscalls/SEGGER_RTT_Syscalls_IAR.c | 115 + .../Syscalls/SEGGER_RTT_Syscalls_KEIL.c | 386 ++++ .../Syscalls/SEGGER_RTT_Syscalls_SES.c | 247 ++ .../bootloader_dfu/dfu_transport_ble.c | 4 +- src/boards.h | 10 - src/main.c | 26 + src/usb/tusb_config.h | 10 +- 16 files changed, 4405 insertions(+), 25 deletions(-) create mode 100644 lib/SEGGER_RTT/License.txt create mode 100644 lib/SEGGER_RTT/README.txt create mode 100644 lib/SEGGER_RTT/RTT/SEGGER_RTT.c create mode 100644 lib/SEGGER_RTT/RTT/SEGGER_RTT.h create mode 100644 lib/SEGGER_RTT/RTT/SEGGER_RTT_ASM_ARMv7M.S create mode 100644 lib/SEGGER_RTT/RTT/SEGGER_RTT_Conf.h create mode 100644 lib/SEGGER_RTT/RTT/SEGGER_RTT_printf.c create mode 100644 lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_GCC.c create mode 100644 lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_IAR.c create mode 100644 lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_KEIL.c create mode 100644 lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_SES.c diff --git a/Makefile b/Makefile index 09ffebc..5991179 100644 --- a/Makefile +++ b/Makefile @@ -196,15 +196,18 @@ 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 += -ggdb + 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_printf.c + C_SRC += $(RTT_SRC)/RTT/SEGGER_RTT.c endif #flags common to all targets @@ -288,6 +291,8 @@ vpath %.S $(ASM_PATHS) OBJECTS = $(C_OBJECTS) $(ASM_OBJECTS) +INC_PATHS = $(addprefix -I,$(IPATH)) + #------------------------------------------------------------------------------ # BUILD TARGETS #------------------------------------------------------------------------------ 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/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c b/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c index cbb3479..3f253c4 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_transport_ble.c @@ -736,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) @@ -899,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/src/boards.h b/src/boards.h index 1290308..1b04223 100644 --- a/src/boards.h +++ b/src/boards.h @@ -109,7 +109,6 @@ bool is_ota(void); //--------------------------------------------------------------------+ // DEBUG //--------------------------------------------------------------------+ -//#define CFG_DEBUG #ifdef CFG_DEBUG @@ -130,13 +129,6 @@ 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(...) @@ -147,8 +139,6 @@ bool is_ota(void); #define PRINT_HEX(x) #define PRINT_BUFFER(buf, n) -#define ADALOG(...) - #endif diff --git a/src/main.c b/src/main.c index 884a130..97936d9 100644 --- a/src/main.c +++ b/src/main.c @@ -482,3 +482,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 sys_write (int fhdl, const void *buf, size_t count) +{ + (void) fhdl; + SEGGER_RTT_Write(0, (char*) buf, (int) count); + return count; +} + +__attribute__ ((used)) +int sys_read (int fhdl, char *buf, size_t count) +{ + (void) fhdl; + return SEGGER_RTT_Read(0, buf, count); +} + + +#endif diff --git a/src/usb/tusb_config.h b/src/usb/tusb_config.h index 688d76f..b76c87b 100644 --- a/src/usb/tusb_config.h +++ b/src/usb/tusb_config.h @@ -70,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 From 3ca3b92e2a3cca97c502ea97e62c993aa06b027f Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 4 May 2020 16:51:58 +0700 Subject: [PATCH 18/61] update tinyusb to commit 101f234 --- lib/tinyusb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tinyusb b/lib/tinyusb index 7f92e25..101f234 160000 --- a/lib/tinyusb +++ b/lib/tinyusb @@ -1 +1 @@ -Subproject commit 7f92e255cf27541f3d673fbd80aededd0f462d00 +Subproject commit 101f234a1637b995e771b4999afdf4793ffdc86e From 1dbe7c3b8058e9860d13032c9f6b2e02ed8c786d Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 4 May 2020 17:26:54 +0700 Subject: [PATCH 19/61] correct retarget --- src/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.c b/src/main.c index 97936d9..fae0d69 100644 --- a/src/main.c +++ b/src/main.c @@ -492,7 +492,7 @@ void SD_EVT_IRQHandler(void) #include "SEGGER_RTT.h" __attribute__ ((used)) -int sys_write (int fhdl, const void *buf, size_t count) +int _write (int fhdl, const void *buf, size_t count) { (void) fhdl; SEGGER_RTT_Write(0, (char*) buf, (int) count); @@ -500,7 +500,7 @@ int sys_write (int fhdl, const void *buf, size_t count) } __attribute__ ((used)) -int sys_read (int fhdl, char *buf, size_t count) +int _read (int fhdl, char *buf, size_t count) { (void) fhdl; return SEGGER_RTT_Read(0, buf, count); From 6ac95d3798579a0f0d17826bb8205bcb036b3711 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 5 May 2020 12:33:18 +0700 Subject: [PATCH 20/61] clean up for merging PR --- src/usb/uf2/ghostfat.c | 97 +++++++++++++++++++++++++++++++++++++----- src/usb/uf2/uf2cfg.h | 2 - 2 files changed, 86 insertions(+), 13 deletions(-) diff --git a/src/usb/uf2/ghostfat.c b/src/usb/uf2/ghostfat.c index 97b4211..9293f1d 100644 --- a/src/usb/uf2/ghostfat.c +++ b/src/usb/uf2/ghostfat.c @@ -156,17 +156,21 @@ static inline bool in_app_space (uint32_t addr) return USER_FLASH_START <= addr && addr < USER_FLASH_END; } +static inline bool in_uicr_space(uint32_t addr) +{ + return addr == 0x10001000; +} + +static inline bool in_bootloader_space (uint32_t addr) +{ + return USER_FLASH_END <= addr && addr < CFG_UF2_FLASH_SIZE; +} + static inline bool in_softdevice_space (uint32_t addr) { return addr < USER_FLASH_START; } -static inline bool in_uf2_bootloader_space (uint32_t addr) -{ - return USER_FLASH_END <= addr /*&& addr < FLASH_SIZE*/; -} - - //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ @@ -340,16 +344,87 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state) if ( !is_uf2_block(bl) ) return -1; - PRINTF("Addr = 0x%08X, Family = 0x%08X\n", bl->targetAddr, bl->familyID); + PRINTF("Addr = 0x%08lX, payloadSize = %ld, Family = 0x%08lX\n", bl->targetAddr, bl->payloadSize, bl->familyID); +#if 0 + uint32_t wr_addr; - // only accept block with same family id - if ( !((bl->familyID == CFG_UF2_FAMILY_ID)) ) + switch ( bl->familyID ) { - return -1; + case CFG_UF2_FAMILY_ID: + // Upgrade application + // Directly write over application -- > Target address is the written address + if ( !in_app_space(bl->targetAddr) ) return -1; + + wr_addr = bl->targetAddr; + break; + + case CFG_UF2_BOOTLOADER_ID: + /* Upgrading SoftDevice + Bootloader combo + * + * To prevent corruption/disconnection while transferring we don't directly write over + * SoftDevice and Bootloader. Instead SD + Bootloader is written to Application region. + * Once everything is received and verified.They are written to their respective address + * + * Note: to simplify the upgrade process, we ASSUME + * - Bootloader size is fixed and is the same as the old bootloader + * - New SoftDevice can has different size than the old one + * + * ------------- ------------- ------------- + * | | | | + | New | + * | Bootloader | | Bootloader | + | Bootloader | + * BOOTLOADER_ADDR_START--|-------------| |-------------| + |-------------| + * | | | New | + | | + * | | | Bootloader | + | | + * | | | ++++++++ | | | + * | Application | ---> | | | Invalid | + * | | | | | Application | + * | | | ++++++++ | | | + * | | | New | | | + * | | | SoftDevice | + |-------------| + * USER_FLASH_START--|-------------| |-------------| + | | + * | | | | + | | + * | | | | + | New | + * | SoftDevice | | SoftDevice | + | SoftDevice | + * ------------- ------------- ------------- + */ + + if ( in_uicr_space(bl->targetAddr) ) + { + /* UCIR contains bootloader & MBR address as follow: + * - 0x10001014: for bootloader address + * - 0x10001018: for MBR + * Both values are fixed if bootloader size is not change + */ + + // Nothing to do since bootloader size is fixed + return 512; + } + else if ( in_softdevice_space(bl->targetAddr) ) + { + // Right above the old SoftDevice + wr_addr = USER_FLASH_START + bl->targetAddr; + } + else if ( in_bootloader_space(bl->targetAddr) ) + { + // Right below the old Bootloader + //wr_addr = USER_FLASH_START + bl->targetAddr; + } + else + { + + return -1; + } + break; + + // unknown family ID + default: return -1; } + (void) wr_addr; +#endif -// if ( (bl->familyID == CFG_UF2_FAMILY_ID) && in_app_space(bl->targetAddr) ) + // only accept block with same family id + if ( (bl->familyID != CFG_UF2_FAMILY_ID) ) return -1; if ( (bl->targetAddr < USER_FLASH_START) || (bl->targetAddr + bl->payloadSize > USER_FLASH_END) ) { diff --git a/src/usb/uf2/uf2cfg.h b/src/usb/uf2/uf2cfg.h index 276d484..282a9b0 100644 --- a/src/usb/uf2/uf2cfg.h +++ b/src/usb/uf2/uf2cfg.h @@ -18,5 +18,3 @@ // Bootloader Address Space #define CFG_UF2_BOOTLOADER_ADDR_START BOOTLOADER_REGION_START #define CFG_UF2_BOOTLOADER_ADDR_END BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS - -//#define From 725c82c7e813e895cfb61388c36c3b7c234af5be Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 5 May 2020 14:30:35 +0700 Subject: [PATCH 21/61] clean up cfg --- src/usb/uf2/uf2cfg.h | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/usb/uf2/uf2cfg.h b/src/usb/uf2/uf2cfg.h index 2379ae0..329005d 100644 --- a/src/usb/uf2/uf2cfg.h +++ b/src/usb/uf2/uf2cfg.h @@ -11,19 +11,13 @@ #define CFG_UF2_SOFTDEVICE_ADDR_START 0 #define CFG_UF2_SOFTDEVICE_ADDR_END USER_FLASH_START -#if 0 -// Only allow to write application TODO dynamic depending on SD size +// Application Address Space #ifdef SOFTDEVICE_PRESENT -#define USER_FLASH_START 0x26000 + #define USER_FLASH_START (SD_FLASH_SIZE + MBR_SIZE) #else -#define USER_FLASH_START 0x1000 + #define USER_FLASH_START 0x1000 // MBR is still required #endif -#define USER_FLASH_END 0xAD000 // Fat Fs start here -#endif - -// Application Address Space -#define USER_FLASH_START (SD_FLASH_SIZE + MBR_SIZE) #define USER_FLASH_END 0xAD000 // Bootloader Address Space From 0b84f428d2ed9f22f663e847ad200bd88b98e829 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 5 May 2020 21:47:20 +0700 Subject: [PATCH 22/61] added mbr 2.4.1 --- lib/softdevice/mbr/headers/nrf_mbr.h | 268 ++++++++++++++++++ lib/softdevice/mbr/headers/nrf_svc.h | 100 +++++++ .../hex/mbr_nrf52_2.4.1_licence-agreement.txt | 35 +++ .../mbr/hex/mbr_nrf52_2.4.1_mbr.hex | 179 ++++++++++++ 4 files changed, 582 insertions(+) create mode 100644 lib/softdevice/mbr/headers/nrf_mbr.h create mode 100644 lib/softdevice/mbr/headers/nrf_svc.h create mode 100644 lib/softdevice/mbr/hex/mbr_nrf52_2.4.1_licence-agreement.txt create mode 100644 lib/softdevice/mbr/hex/mbr_nrf52_2.4.1_mbr.hex 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 From ed7c5ac2f30d2fa4af652624ddaf238ddc4ed7a6 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 5 May 2020 22:04:39 +0700 Subject: [PATCH 23/61] add mbr flash target --- Makefile | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Makefile b/Makefile index 5991179..1bc8c3a 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,8 @@ SD_VERSION = 6.1.1 SD_FILENAME = $(SD_NAME)_nrf52_$(SD_VERSION) SD_HEX = $(SD_PATH)/$(SD_FILENAME)_softdevice.hex +MBR_HEX = lib/softdevice/mbr/hex/mbr_nrf52_2.4.1_mbr.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 @@ -326,14 +328,25 @@ 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 --chiperase --reset +# flash MBR only +mbr: + @echo Flashing: $(MBR_HEX) + $(NRFJPROG) --program $(MBR_HEX) -f nrf52 --sectorerase + gdbflash: $(BUILD)/$(MERGED_FILE).hex @echo Flashing: $< @$(GDB_BMP) -nx --batch -ex 'load $<' -ex 'compare-sections' -ex 'kill' From af105128f3a9b7879a0d2b39f396d746121470dc Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 5 May 2020 22:05:03 +0700 Subject: [PATCH 24/61] populate bootloader address and mbr param if not available in MBR check SD MAGIC before using sd API when init usb --- Makefile | 2 +- .../libraries/bootloader_dfu/bootloader.h | 3 + .../bootloader_dfu/bootloader_settings.c | 61 ++++++++----------- .../libraries/bootloader_dfu/dfu_types.h | 8 ++- src/boards.c | 5 -- src/main.c | 3 + src/usb/usb.c | 35 +++-------- 7 files changed, 49 insertions(+), 68 deletions(-) diff --git a/Makefile b/Makefile index 1bc8c3a..d2e90b3 100644 --- a/Makefile +++ b/Makefile @@ -345,7 +345,7 @@ sd: # flash MBR only mbr: @echo Flashing: $(MBR_HEX) - $(NRFJPROG) --program $(MBR_HEX) -f nrf52 --sectorerase + $(NRFJPROG) --program $(MBR_HEX) -f nrf52 --sectorerase --reset gdbflash: $(BUILD)/$(MERGED_FILE).hex @echo Flashing: $< diff --git a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.h b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.h index 3a5fa42..2f81da6 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.h +++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.h @@ -92,6 +92,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 8367204..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_types.h b/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h index d68af7c..8a2467d 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h @@ -29,12 +29,16 @@ #include "nrf.h" #include "app_util.h" -#define SD_MAGIC_NUMBER 0x51b1e5db -#define SD_MAGIC_OK() (*((uint32_t*)(SOFTDEVICE_INFO_STRUCT_ADDRESS+4)) == 0x51b1e5db) +#ifndef SD_MAGIC_NUMBER +#define SD_MAGIC_NUMBER 0x51B1E5DB +#endif + +#define SD_MAGIC_OK() (*((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).*/ +// TODO more testing/checking #define CODE_REGION_1_START (SD_MAGIC_OK() ? 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. */ diff --git a/src/boards.c b/src/boards.c index b4d7ede..e1ab96d 100644 --- a/src/boards.c +++ b/src/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/main.c b/src/main.c index 3389f42..845df00 100644 --- a/src/main.c +++ b/src/main.c @@ -166,6 +166,9 @@ void softdev_mbr_init(void) //--------------------------------------------------------------------+ int main(void) { + // Populate Boot Address and MBR Param if not already + 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); diff --git a/src/usb/usb.c b/src/usb/usb.c index 70247ae..d9bdcf3 100644 --- a/src/usb/usb.c +++ b/src/usb/usb.c @@ -56,6 +56,7 @@ void USBD_IRQHandler(void) //------------- 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 @@ -64,9 +65,14 @@ void usb_init(bool cdc_only) #ifdef SOFTDEVICE_PRESENT uint8_t sd_en = false; - (void) sd_softdevice_is_enabled(&sd_en); - if ( sd_en ) { + if ( SD_MAGIC_OK() ) + { + sd_softdevice_is_enabled(&sd_en); + } + + if ( sd_en ) + { sd_power_usbdetected_enable(true); sd_power_usbpwrrdy_enable(true); sd_power_usbremoved_enable(true); @@ -106,29 +112,8 @@ void usb_init(bool cdc_only) 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); - -#if defined(SOFTDEVICE_PRESENT) - sd_clock_hfclk_release(); - - sd_power_usbdetected_enable(false); - sd_power_usbpwrrdy_enable(false); - sd_power_usbremoved_enable(false); -#endif - } + // Simulate an disconnect which cause pullup disable, USB perpheral disable and hclk disable + tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_REMOVED); } //--------------------------------------------------------------------+ From 74c650851ebdd7961066eb4a76ea948224fd9e63 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 6 May 2020 15:53:31 +0700 Subject: [PATCH 25/61] more update --- Makefile | 2 +- .../components/libraries/bootloader_dfu/dfu_types.h | 7 +++++-- src/boards.h | 2 +- src/usb/uf2/uf2cfg.h | 11 +++-------- src/usb/usb.c | 2 +- 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index d2e90b3..5d6c843 100644 --- a/Makefile +++ b/Makefile @@ -340,7 +340,7 @@ erase: # flash SD only sd: @echo Flashing: $(SD_HEX) - $(NRFJPROG) --program $(SD_HEX) -f nrf52 --chiperase --reset + $(NRFJPROG) --program $(SD_HEX) -f nrf52 --sectorerase --reset # flash MBR only mbr: diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h b/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h index 8a2467d..346242a 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h @@ -33,13 +33,16 @@ #define SD_MAGIC_NUMBER 0x51B1E5DB #endif -#define SD_MAGIC_OK() (*((uint32_t*)(SOFTDEVICE_INFO_STRUCT_ADDRESS+4)) == SD_MAGIC_NUMBER) +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).*/ // TODO more testing/checking -#define CODE_REGION_1_START (SD_MAGIC_OK() ? 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 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. */ diff --git a/src/boards.h b/src/boards.h index 1b04223..edc7666 100644 --- a/src/boards.h +++ b/src/boards.h @@ -119,7 +119,7 @@ bool is_ota(void); #define PRINT_MESS(x) printf("%s: %d: %s \n" , __FUNCTION__, __LINE__, (char*)(x)) #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 {\ diff --git a/src/usb/uf2/uf2cfg.h b/src/usb/uf2/uf2cfg.h index 329005d..4b9254c 100644 --- a/src/usb/uf2/uf2cfg.h +++ b/src/usb/uf2/uf2cfg.h @@ -8,16 +8,11 @@ #define CFG_UF2_FLASH_SIZE (1024*1024) // 1 MB // Softdevice Address Space -#define CFG_UF2_SOFTDEVICE_ADDR_START 0 -#define CFG_UF2_SOFTDEVICE_ADDR_END USER_FLASH_START +#define CFG_UF2_SOFTDEVICE_ADDR_START MBR_SIZE // skip MBR included in SD hex +#define CFG_UF2_SOFTDEVICE_ADDR_END SD_SIZE_GET(MBR_SIZE) // Application Address Space -#ifdef SOFTDEVICE_PRESENT - #define USER_FLASH_START (SD_FLASH_SIZE + MBR_SIZE) -#else - #define USER_FLASH_START 0x1000 // MBR is still required -#endif - +#define USER_FLASH_START MBR_SIZE // skip MBR included in SD hex #define USER_FLASH_END 0xAD000 // Bootloader Address Space diff --git a/src/usb/usb.c b/src/usb/usb.c index d9bdcf3..bdbf00d 100644 --- a/src/usb/usb.c +++ b/src/usb/usb.c @@ -66,7 +66,7 @@ void usb_init(bool cdc_only) #ifdef SOFTDEVICE_PRESENT uint8_t sd_en = false; - if ( SD_MAGIC_OK() ) + if ( is_sd_existed() ) { sd_softdevice_is_enabled(&sd_en); } From d95684ce8bcdad4ff0e7bf54f167d35c9679aa11 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 6 May 2020 16:13:56 +0700 Subject: [PATCH 26/61] comment out factory reset --- src/main.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main.c b/src/main.c index 845df00..7b1d26f 100644 --- a/src/main.c +++ b/src/main.c @@ -119,6 +119,7 @@ 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. +// TODO correct USER_FLASH_START = APP after SoftDevice #define APP_ASKS_FOR_SINGLE_TAP_RESET() (*((uint32_t*)(USER_FLASH_START + 0x200)) == 0x87eeb07c) // These value must be the same with one in dfu_transport_ble.c @@ -167,6 +168,8 @@ void softdev_mbr_init(void) int main(void) { // Populate Boot Address and MBR Param if not already + // Happens if flashing SD hex that overwrite current MBR + // MBR_BOOTLOADER_ADDR/MBR_PARAM_PAGE_ADDR are used if available, else UICR registers are used bootloader_mbr_addrs_populate(); // SD is already Initialized in case of BOOTLOADER_DFU_OTA_MAGIC @@ -188,9 +191,6 @@ int main(void) // Save bootloader version to pre-defined register, retrieved by application 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(); @@ -271,11 +271,13 @@ int main(void) } } +#if 0 // Adafruit Factory reset if ( !button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) ) { adafruit_factory_reset(); } +#endif // Reset Board board_teardown(); @@ -300,6 +302,7 @@ int main(void) } +#if 0 // Perform factory reset to erase Application + Data void adafruit_factory_reset(void) { @@ -317,6 +320,7 @@ void adafruit_factory_reset(void) // back to normal led_state(STATE_FACTORY_RESET_FINISHED); } +#endif /** * Initializes the SoftDevice and the BLE event interrupt. From bce102e34a33fd5638094bf31ceb005321039dad Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 6 May 2020 16:25:50 +0700 Subject: [PATCH 27/61] remove address from checking app valid function either use address after SD or MBR --- .../libraries/bootloader_dfu/bootloader.c | 45 +++++++++---------- .../libraries/bootloader_dfu/bootloader.h | 5 +-- .../libraries/bootloader_dfu/dfu_types.h | 3 +- 3 files changed, 23 insertions(+), 30 deletions(-) diff --git a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c index 249d3a6..96a1b28 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c @@ -143,37 +143,32 @@ 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; + uint32_t const app_addr = DFU_BANK_0_REGION_START; + bootloader_settings_t const *p_bootloader_settings; - // There exists an application in CODE region 1. - if (*((uint32_t *)app_addr) == EMPTY_FLASH_MASK) + bool success = false; + + 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 ) { - 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 *)app_addr, - p_bootloader_settings->bank_0_size, - NULL); - } - - success = (image_crc == p_bootloader_settings->bank_0_crc); - } - - return success; + return success; } diff --git a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.h b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.h index 2f81da6..6c73f7a 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. * diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h b/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h index 346242a..2bf2cb3 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h @@ -41,8 +41,9 @@ static inline bool is_sd_existed(void) #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).*/ -// TODO more testing/checking +// 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. */ From f12c8374792a930b66d17d2d05b03a31b5cf4cb4 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 6 May 2020 17:15:39 +0700 Subject: [PATCH 28/61] the pca10056 and pca10059 usb vid/pid to match those in nordic sdk --- src/boards/pca10056/board.h | 4 ++++ src/boards/pca10059/board.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/boards/pca10056/board.h b/src/boards/pca10056/board.h index a17d597..0682f88 100644 --- a/src/boards/pca10056/board.h +++ b/src/boards/pca10056/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 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/pca10059/board.h b/src/boards/pca10059/board.h index 6654b87..4ca7b1a 100644 --- a/src/boards/pca10059/board.h +++ b/src/boards/pca10059/board.h @@ -53,6 +53,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 nRF52840 Dongle" #define UF2_BOARD_ID "nRF52840-pca10059-v1" #define UF2_INDEX_URL "https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-Dongle" From dad8e10f6c747b3543d40bf16ee23fdbc0415e99 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 6 May 2020 23:12:07 +0700 Subject: [PATCH 29/61] bootloader_app_start() correct set - use sd vector table set if existed - otherwise use mbr to set to application (0x1000) --- .../libraries/bootloader_dfu/bootloader.c | 58 ++++++++----------- .../libraries/bootloader_dfu/bootloader.h | 2 +- src/main.c | 27 +++++---- 3 files changed, 42 insertions(+), 45 deletions(-) diff --git a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c index 96a1b28..db0c111 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c @@ -36,13 +36,6 @@ #include "tusb.h" #endif -/**< 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 @@ -342,45 +335,42 @@ 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) { - for (uint32_t irq = 0; irq < MAX_NUMBER_INTERRUPTS; irq++) - { - NVIC_DisableIRQ((IRQn_Type)irq); - } -} + // If the applications CRC has been checked and passed, the magic number will be written and we + // can start the application safely. + if ( is_sd_existed() ) sd_softdevice_disable(); - -void bootloader_app_start(uint32_t app_addr) -{ -#ifdef SOFTDEVICE_PRESENT - // 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() ); + // 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 - interrupts_disable(); + // default to boot right after MBR + uint32_t app_addr = MBR_SIZE; -#if 0 // may need set forward irq + if ( is_sd_existed() ) + { + app_addr = SD_SIZE_GET(MBR_SIZE); + sd_softdevice_vector_table_base_set(app_addr); + }else + { sd_mbr_command_t command = { - .command = SD_MBR_COMMAND_IRQ_FORWARD_ADDRESS_SET, - .params.irq_forward_address_set.address = MBR_SIZE, + .command = SD_MBR_COMMAND_IRQ_FORWARD_ADDRESS_SET, + .params.irq_forward_address_set.address = app_addr, }; sd_mbr_command(&command); -#endif -#ifdef SOFTDEVICE_PRESENT - APP_ERROR_CHECK( sd_softdevice_vector_table_base_set(app_addr) ); -#else - SCB->VTOR = app_addr; -#endif + // VTOR as last resource ? + // SCB->VTOR = app_addr; + } - bootloader_util_app_start(app_addr); + 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 6c73f7a..9354ffe 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.h +++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.h @@ -52,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. * diff --git a/src/main.c b/src/main.c index 7b1d26f..b4d04e2 100644 --- a/src/main.c +++ b/src/main.c @@ -189,6 +189,7 @@ 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); board_init(); @@ -214,7 +215,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()) @@ -282,20 +283,24 @@ int main(void) // 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()) { -#ifdef SOFTDEVICE_PRESENT // MBR must be init before start application - if ( !sd_inited ) softdev_mbr_init(); -#endif + if ( is_sd_existed() && !sd_inited ) softdev_mbr_init(); // 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(); @@ -323,7 +328,9 @@ void adafruit_factory_reset(void) #endif /** - * 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. From 99d31d2c827154632e38c9f3abf636433036f815 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 6 May 2020 23:16:02 +0700 Subject: [PATCH 30/61] remove the use of factory reset --- src/main.c | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/src/main.c b/src/main.c index b4d04e2..6fdb32e 100644 --- a/src/main.c +++ b/src/main.c @@ -142,7 +142,6 @@ enum { BLE_CONN_CFG_HIGH_BANDWIDTH = 1 }; //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ -void adafruit_factory_reset(void); static uint32_t softdev_init(bool init_softdevice); uint32_t* dbl_reset_mem = ((uint32_t*) DFU_DBL_RESET_MEM ); @@ -272,14 +271,6 @@ int main(void) } } -#if 0 - // Adafruit Factory reset - if ( !button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) ) - { - adafruit_factory_reset(); - } -#endif - // Reset Board board_teardown(); @@ -306,27 +297,6 @@ int main(void) NVIC_SystemReset(); } - -#if 0 -// 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); -} -#endif - /** * Initializes the SotdDevice by following SD specs section * "Master Boot Record and SoftDevice initializaton procedure" From 570bd5b6648ab4a0f02373345fe16afea36277f7 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 6 May 2020 23:42:24 +0700 Subject: [PATCH 31/61] more clean up, everything look good usb example work without SD, which means ISR forwarding is working. --- .../libraries/bootloader_dfu/bootloader.c | 14 +++++--------- src/main.c | 12 +++++++++--- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c index db0c111..85abb40 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c @@ -337,10 +337,6 @@ uint32_t bootloader_dfu_start(bool ota, uint32_t timeout_ms) void bootloader_app_start(void) { - // If the applications CRC has been checked and passed, the magic number will be written and we - // can start the application safely. - if ( is_sd_existed() ) sd_softdevice_disable(); - // Disable all interrupts NVIC->ICER[0]=0xFFFFFFFF; NVIC->ICPR[0]=0xFFFFFFFF; @@ -349,15 +345,17 @@ void bootloader_app_start(void) NVIC->ICPR[1]=0xFFFFFFFF; #endif - // default to boot right after MBR - uint32_t app_addr = MBR_SIZE; + uint32_t app_addr; if ( is_sd_existed() ) { + // App starts after SoftDevice app_addr = SD_SIZE_GET(MBR_SIZE); sd_softdevice_vector_table_base_set(app_addr); }else { + // App starts right after MBR + app_addr = MBR_SIZE; sd_mbr_command_t command = { .command = SD_MBR_COMMAND_IRQ_FORWARD_ADDRESS_SET, @@ -365,11 +363,9 @@ void bootloader_app_start(void) }; sd_mbr_command(&command); - - // VTOR as last resource ? - // SCB->VTOR = app_addr; } + // jump to app bootloader_util_app_start(app_addr); } diff --git a/src/main.c b/src/main.c index 6fdb32e..c309e5c 100644 --- a/src/main.c +++ b/src/main.c @@ -284,8 +284,14 @@ int main(void) if (bootloader_app_is_valid() && !bootloader_dfu_sd_in_progress()) { - // MBR must be init before start application - if ( is_sd_existed() && !sd_inited ) softdev_mbr_init(); + 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; @@ -309,7 +315,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 From 447207b875b5ca67b01e592f7b4c90f8c6d44b78 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 7 May 2020 12:18:58 +0700 Subject: [PATCH 32/61] add failed safe mbr forward address --- .../components/libraries/bootloader_dfu/bootloader.c | 12 ++++++++++-- src/flash_nrf5x.c | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c index 85abb40..3bfd510 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c @@ -345,13 +345,14 @@ void bootloader_app_start(void) NVIC->ICPR[1]=0xFFFFFFFF; #endif + uint32_t fwd_ret; uint32_t app_addr; if ( is_sd_existed() ) { // App starts after SoftDevice app_addr = SD_SIZE_GET(MBR_SIZE); - sd_softdevice_vector_table_base_set(app_addr); + fwd_ret = sd_softdevice_vector_table_base_set(app_addr); }else { // App starts right after MBR @@ -362,7 +363,14 @@ void bootloader_app_start(void) .params.irq_forward_address_set.address = app_addr, }; - sd_mbr_command(&command); + fwd_ret = sd_mbr_command(&command); + } + + // unlikely failed to forward vector table, manually set forward address + if ( fwd_ret != NRF_SUCCESS ) + { + // MBR use first 4-bytes of SRAM to store foward address + *(uint32_t *)(0x20000000) = app_addr; } // jump to app diff --git a/src/flash_nrf5x.c b/src/flash_nrf5x.c index fe563ac..2b71c42 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. From 54a0ad7070597a45517c94095ce2f071de074f12 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 7 May 2020 16:55:57 +0700 Subject: [PATCH 33/61] correct uf2 app/sd size when writing and reading --- src/usb/msc_uf2.c | 28 +++++++-- src/usb/uf2/ghostfat.c | 138 +++++++++++++++++++++++------------------ src/usb/uf2/uf2.h | 2 + src/usb/uf2/uf2cfg.h | 4 -- 4 files changed, 100 insertions(+), 72 deletions(-) diff --git a/src/usb/msc_uf2.c b/src/usb/msc_uf2.c index 6bd0626..178ce22 100644 --- a/src/usb/msc_uf2.c +++ b/src/usb/msc_uf2.c @@ -174,16 +174,32 @@ void tud_msc_write10_complete_cb(uint8_t lun) // All block of uf2 file is complete --> complete DFU process if (_wr_state.numWritten >= _wr_state.numBlocks) { - led_state(STATE_WRITING_FINISHED); - 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; + + if ( _wr_state.update_bootloader ) + { + // update bootloader + }else + { + // update App + update_status.status_code = DFU_UF2_APP_COMPLETE; + update_status.app_crc = 0; // skip CRC checking with uf2 upgrade + update_status.app_size = _wr_state.numBlocks*256; + + if ( _wr_state.has_sd && is_sd_existed() ) + { + /* Since the Bootloader Setting still needs to know the SD and App size separately + * to stay compatible with DFU CDC interface. We re-calculate it based on written + * address and its contents ( SD_MAGIC matches ) + */ + update_status.app_size -= SD_SIZE_GET(MBR_SIZE); + } + } bootloader_dfu_update_process(update_status); + + led_state(STATE_WRITING_FINISHED); } } } diff --git a/src/usb/uf2/ghostfat.c b/src/usb/uf2/ghostfat.c index 9293f1d..262ae39 100644 --- a/src/usb/uf2/ghostfat.c +++ b/src/usb/uf2/ghostfat.c @@ -156,21 +156,16 @@ static inline bool in_app_space (uint32_t addr) return USER_FLASH_START <= addr && addr < USER_FLASH_END; } +static inline bool in_bootloader_space (uint32_t addr) +{ + return CFG_UF2_BOOTLOADER_ADDR_START <= addr && addr < CFG_UF2_BOOTLOADER_ADDR_END; +} + static inline bool in_uicr_space(uint32_t addr) { return addr == 0x10001000; } -static inline bool in_bootloader_space (uint32_t addr) -{ - return USER_FLASH_END <= addr && addr < CFG_UF2_FLASH_SIZE; -} - -static inline bool in_softdevice_space (uint32_t addr) -{ - return addr < USER_FLASH_START; -} - //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ @@ -183,7 +178,7 @@ static uint32_t current_flash_size(void) uint32_t flash_sz = 0; // return 1 block of 256 bytes - if ( !bootloader_app_is_valid(DFU_BANK_0_REGION_START) ) + if ( !bootloader_app_is_valid() ) { flash_sz = 256; }else @@ -193,6 +188,9 @@ static uint32_t current_flash_size(void) flash_sz = boot_setting->bank_0_size; + // Include SoftDevice (excluding MBR) for current.uf2 + if ( is_sd_existed() ) flash_sz += (SD_SIZE_GET(MBR_SIZE) - MBR_SIZE); + // Copy size must be multiple of 256 bytes // else we will got an issue copying current.uf2 if (flash_sz & 0xff) @@ -344,30 +342,63 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state) if ( !is_uf2_block(bl) ) return -1; - PRINTF("Addr = 0x%08lX, payloadSize = %ld, Family = 0x%08lX\n", bl->targetAddr, bl->payloadSize, bl->familyID); -#if 0 - uint32_t wr_addr; - switch ( bl->familyID ) { case CFG_UF2_FAMILY_ID: - // Upgrade application - // Directly write over application -- > Target address is the written address - if ( !in_app_space(bl->targetAddr) ) return -1; + /* Upgrading Application + * + * Although SoftDevice is considered as part of application and the flashing is the same with/without it. + * There are still 3 cases with slight differences in finishing procedure: + * 1. Application with SoftDevice: + * - starting address 0x0000 + * - since MBR is included in SD Hex file (then uf2 file), we must skip it + * 2. Application only + * a. For running with existing SoftDevice on the flash: + * - starting address is right after SD e.g 0x26000 + * b. For running without SoftDevice e.g using other stack such as nimble or zephyr. + * - starting address is right after MBR 0x1000 + * + * ------------- ------------- + * | | | | + * | Bootloader | | Bootloader | + * BOOTLOADER_ADDR_START--|-------------| |-------------| + * | | | | + * | | | | + * | Application | ---> | New | + * | | | 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); - wr_addr = bl->targetAddr; + // writing to SD Info struct is used as SD detector + if (bl->targetAddr == (SOFTDEVICE_INFO_STRUCT_ADDRESS & 0xff) ) state->has_sd = true; + + flash_nrf5x_write(bl->targetAddr, bl->data, bl->payloadSize, true); + }else if ( bl->targetAddr < USER_FLASH_START ) + { + // do nothing if writing to MBR + // keep going as successful write + }else + { + return -1; + } break; case CFG_UF2_BOOTLOADER_ID: - /* Upgrading SoftDevice + Bootloader combo + /* Upgrading Bootloader (with/without SoftDevice) * * To prevent corruption/disconnection while transferring we don't directly write over - * SoftDevice and Bootloader. Instead SD + Bootloader is written to Application region. - * Once everything is received and verified.They are written to their respective address + * Bootloader. Instead Bootloader is written to Application region. + * Once everything is received and verified. It is written to its respective address * - * Note: to simplify the upgrade process, we ASSUME - * - Bootloader size is fixed and is the same as the old bootloader - * - New SoftDevice can has different size than the old one + * Note: to simplify the upgrade process, we ASSUME, Bootloader size is fixed and + * is the same as the old bootloader * * ------------- ------------- ------------- * | | | | + | New | @@ -376,42 +407,41 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state) * | | | New | + | | * | | | Bootloader | + | | * | | | ++++++++ | | | - * | Application | ---> | | | Invalid | - * | | | | | Application | - * | | | ++++++++ | | | - * | | | New | | | - * | | | SoftDevice | + |-------------| - * USER_FLASH_START--|-------------| |-------------| + | | - * | | | | + | | - * | | | | + | New | - * | SoftDevice | | SoftDevice | + | SoftDevice | + * | Application | ---> | | | | + * | | | | | | + * | | | ++++++++ | | ++++++++ | + * | | | New | | New | + * | | | SoftDevice | | SoftDevice | + * USER_FLASH_START--|-------------| |-------------| |-------------| + * | MBR | | MBR | | MBR | * ------------- ------------- ------------- */ - if ( in_uicr_space(bl->targetAddr) ) { /* UCIR contains bootloader & MBR address as follow: - * - 0x10001014: for bootloader address - * - 0x10001018: for MBR - * Both values are fixed if bootloader size is not change + * - 0x10001014 bootloader address: only change of bootloader size changes + * - 0x10001018 MBR Params: mostly fixed + * + * WARNING: incorrect value of these UCIR will break device */ // Nothing to do since bootloader size is fixed return 512; } - else if ( in_softdevice_space(bl->targetAddr) ) + else if ( in_bootloader_space(bl->targetAddr) ) { // Right above the old SoftDevice - wr_addr = USER_FLASH_START + bl->targetAddr; } - else if ( in_bootloader_space(bl->targetAddr) ) + else if ( in_app_space(bl->targetAddr) ) { // Right below the old Bootloader //wr_addr = USER_FLASH_START + bl->targetAddr; + // writing to SD Info struct is used as SD detector + // if (bl->targetAddr == SOFTDEVICE_INFO_STRUCT_ADDRESS) state->has_sd = true; + } else { - return -1; } break; @@ -420,25 +450,10 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state) default: return -1; } - (void) wr_addr; -#endif - - // only accept block with same family id - if ( (bl->familyID != CFG_UF2_FAMILY_ID) ) return -1; - - if ( (bl->targetAddr < USER_FLASH_START) || (bl->targetAddr + bl->payloadSize > USER_FLASH_END) ) + //------------- Update written blocks -------------// + if ( bl->numBlocks ) { - - } - else - { - //PRINTF("Write block at %x", bl->targetAddr); - flash_nrf5x_write(bl->targetAddr, bl->data, bl->payloadSize, true); - } - - if ( state && bl->numBlocks ) - { - // Update state num blocks + // Update state num blocks if needed if ( state->numBlocks != bl->numBlocks ) { if ( bl->numBlocks >= MAX_BLOCKS || state->numBlocks ) @@ -460,13 +475,12 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state) } // flush last blocks + // TODO numWritten can be smaller than numBlocks if return early if ( state->numWritten >= state->numBlocks ) { flash_nrf5x_flush(true); } } - - //PRINTF("wr %d=%d (of %d)", state->numWritten, bl->blockNo, bl->numBlocks); } return 512; diff --git a/src/usb/uf2/uf2.h b/src/usb/uf2/uf2.h index a71bb32..905232c 100644 --- a/src/usb/uf2/uf2.h +++ b/src/usb/uf2/uf2.h @@ -52,6 +52,8 @@ SOFTWARE. typedef struct { uint32_t numBlocks; uint32_t numWritten; + bool has_sd; // if SD is included as part of uf2 file + bool update_bootloader; // if updating bootloader uint8_t writtenMask[MAX_BLOCKS / 8 + 1]; } WriteState; diff --git a/src/usb/uf2/uf2cfg.h b/src/usb/uf2/uf2cfg.h index 4b9254c..e2466c1 100644 --- a/src/usb/uf2/uf2cfg.h +++ b/src/usb/uf2/uf2cfg.h @@ -7,10 +7,6 @@ #define CFG_UF2_NUM_BLOCKS 8000 // at least 4,1 MB for FAT16 #define CFG_UF2_FLASH_SIZE (1024*1024) // 1 MB -// Softdevice Address Space -#define CFG_UF2_SOFTDEVICE_ADDR_START MBR_SIZE // skip MBR included in SD hex -#define CFG_UF2_SOFTDEVICE_ADDR_END SD_SIZE_GET(MBR_SIZE) - // Application Address Space #define USER_FLASH_START MBR_SIZE // skip MBR included in SD hex #define USER_FLASH_END 0xAD000 From 609473760ac9759706c9ae97d7dc0174a89f93bb Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 8 May 2020 00:45:01 +0700 Subject: [PATCH 34/61] mark app as invalid when updating Softdevice only as application in uf2 mode able to flash combine SD + cpy as single uf2. still has issue writing back CURRENT.UF2 --- .../components/libraries/bootloader_dfu/bootloader.c | 2 +- .../components/libraries/bootloader_dfu/dfu_types.h | 3 ++- src/usb/msc_uf2.c | 12 ++++++++++-- src/usb/uf2/ghostfat.c | 11 +++++++++-- src/usb/uf2/uf2.h | 3 ++- 5 files changed, 24 insertions(+), 7 deletions(-) diff --git a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c index 3bfd510..c286936 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c @@ -196,7 +196,7 @@ void bootloader_dfu_update_process(dfu_update_status_t update_status) { settings.bank_0_crc = update_status.app_crc; settings.bank_0_size = update_status.app_size; - settings.bank_0 = BANK_VALID_APP; + settings.bank_0 = (update_status.app_size ? BANK_VALID_APP : BANK_INVALID_APP); settings.bank_1 = BANK_INVALID_APP; m_update_status = BOOTLOADER_SETTINGS_SAVING; diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h b/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h index 2bf2cb3..9492b0e 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h @@ -138,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/src/usb/msc_uf2.c b/src/usb/msc_uf2.c index 178ce22..f164456 100644 --- a/src/usb/msc_uf2.c +++ b/src/usb/msc_uf2.c @@ -183,7 +183,7 @@ void tud_msc_write10_complete_cb(uint8_t lun) }else { // update App - update_status.status_code = DFU_UF2_APP_COMPLETE; + 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; @@ -193,8 +193,16 @@ void tud_msc_write10_complete_cb(uint8_t lun) * to stay compatible with DFU CDC interface. We re-calculate it based on written * address and its contents ( SD_MAGIC matches ) */ - update_status.app_size -= SD_SIZE_GET(MBR_SIZE); + update_status.app_size -= (SD_SIZE_GET(MBR_SIZE) - MBR_SIZE); } + + if ( _wr_state.has_mbr ) + { + // MBR write isn't counted app size as well + update_status.app_size -= MBR_SIZE; + } + + PRINT_INT(update_status.app_size); } bootloader_dfu_update_process(update_status); diff --git a/src/usb/uf2/ghostfat.c b/src/usb/uf2/ghostfat.c index 262ae39..9bddfcd 100644 --- a/src/usb/uf2/ghostfat.c +++ b/src/usb/uf2/ghostfat.c @@ -212,6 +212,7 @@ static uint32_t current_flash_size(void) void uf2_init(void) { uf2current_flash_sz = current_flash_size(); + PRINT_INT(uf2current_flash_sz); } /*------------------------------------------------------------------*/ @@ -348,7 +349,7 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state) /* Upgrading Application * * Although SoftDevice is considered as part of application and the flashing is the same with/without it. - * There are still 3 cases with slight differences in finishing procedure: + * There are still 4 cases with slight differences in finishing procedure: * 1. Application with SoftDevice: * - starting address 0x0000 * - since MBR is included in SD Hex file (then uf2 file), we must skip it @@ -357,6 +358,8 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state) * - starting address is right after SD e.g 0x26000 * b. For running without SoftDevice e.g using other stack such as nimble or zephyr. * - starting address is right after MBR 0x1000 + * 3. SoftDevice only, should user somehow only flash with SD only. Bootloader mark app as invalid and wiil + * back on bootloader mode after reset. * * ------------- ------------- * | | | | @@ -377,13 +380,17 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state) PRINTF("Write addr = 0x%08lX, block = %ld (%ld of %ld)\r\n", bl->targetAddr, bl->blockNo, state->numWritten, bl->numBlocks); // writing to SD Info struct is used as SD detector - if (bl->targetAddr == (SOFTDEVICE_INFO_STRUCT_ADDRESS & 0xff) ) state->has_sd = true; + if (bl->targetAddr == (SOFTDEVICE_INFO_STRUCT_ADDRESS & 0xFFFFFF00) ) + { + state->has_sd = true; + } flash_nrf5x_write(bl->targetAddr, bl->data, bl->payloadSize, true); }else if ( bl->targetAddr < USER_FLASH_START ) { // do nothing if writing to MBR // keep going as successful write + state->has_mbr = true; }else { return -1; diff --git a/src/usb/uf2/uf2.h b/src/usb/uf2/uf2.h index 905232c..a0a72a1 100644 --- a/src/usb/uf2/uf2.h +++ b/src/usb/uf2/uf2.h @@ -52,7 +52,8 @@ SOFTWARE. typedef struct { uint32_t numBlocks; uint32_t numWritten; - bool has_sd; // if SD is included as part of uf2 file + bool has_sd; // if uf2 includes SD + bool has_mbr; // if uf2 includes MBR bool update_bootloader; // if updating bootloader uint8_t writtenMask[MAX_BLOCKS / 8 + 1]; } WriteState; From 6adf9810a61f0dd8138a3127324f54e6173e8830 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 8 May 2020 11:23:11 +0700 Subject: [PATCH 35/61] read back full app size for simplicity --- .../libraries/bootloader_dfu/bootloader.c | 2 +- src/usb/msc_uf2.c | 19 --------------- src/usb/uf2/ghostfat.c | 23 ++----------------- 3 files changed, 3 insertions(+), 41 deletions(-) diff --git a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c index c286936..3bfd510 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c @@ -196,7 +196,7 @@ void bootloader_dfu_update_process(dfu_update_status_t update_status) { settings.bank_0_crc = update_status.app_crc; settings.bank_0_size = update_status.app_size; - settings.bank_0 = (update_status.app_size ? BANK_VALID_APP : BANK_INVALID_APP); + settings.bank_0 = BANK_VALID_APP; settings.bank_1 = BANK_INVALID_APP; m_update_status = BOOTLOADER_SETTINGS_SAVING; diff --git a/src/usb/msc_uf2.c b/src/usb/msc_uf2.c index f164456..bee6f22 100644 --- a/src/usb/msc_uf2.c +++ b/src/usb/msc_uf2.c @@ -184,25 +184,6 @@ void tud_msc_write10_complete_cb(uint8_t lun) { // update App 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; - - if ( _wr_state.has_sd && is_sd_existed() ) - { - /* Since the Bootloader Setting still needs to know the SD and App size separately - * to stay compatible with DFU CDC interface. We re-calculate it based on written - * address and its contents ( SD_MAGIC matches ) - */ - update_status.app_size -= (SD_SIZE_GET(MBR_SIZE) - MBR_SIZE); - } - - if ( _wr_state.has_mbr ) - { - // MBR write isn't counted app size as well - update_status.app_size -= MBR_SIZE; - } - - PRINT_INT(update_status.app_size); } bootloader_dfu_update_process(update_status); diff --git a/src/usb/uf2/ghostfat.c b/src/usb/uf2/ghostfat.c index 9bddfcd..72b5d4d 100644 --- a/src/usb/uf2/ghostfat.c +++ b/src/usb/uf2/ghostfat.c @@ -183,27 +183,8 @@ static uint32_t current_flash_size(void) flash_sz = 256; }else { - bootloader_settings_t const * boot_setting; - bootloader_util_settings_get(&boot_setting); - - flash_sz = boot_setting->bank_0_size; - - // Include SoftDevice (excluding MBR) for current.uf2 - if ( is_sd_existed() ) flash_sz += (SD_SIZE_GET(MBR_SIZE) - MBR_SIZE); - - // Copy size must be multiple of 256 bytes - // else we will got an issue copying current.uf2 - if (flash_sz & 0xff) - { - flash_sz = (flash_sz & ~0xff) + 256; - } - - // if bank0 size is not valid, happens when flashed with jlink - // use maximum application size - if ( (flash_sz == 0) || (flash_sz == 0xFFFFFFFFUL) ) - { - flash_sz = (USER_FLASH_END-USER_FLASH_START); - } + // Use full application size for simplicity + flash_sz = (USER_FLASH_END-USER_FLASH_START); } return flash_sz; From 72902e6931f4efdb3cdbf52bcc353f51e30889c7 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 8 May 2020 11:35:04 +0700 Subject: [PATCH 36/61] finalize fixed readback current.uf2 size --- src/usb/uf2/ghostfat.c | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/src/usb/uf2/ghostfat.c b/src/usb/uf2/ghostfat.c index 72b5d4d..8ad74bf 100644 --- a/src/usb/uf2/ghostfat.c +++ b/src/usb/uf2/ghostfat.c @@ -99,7 +99,7 @@ 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 UF2_SIZE (uf2current_flash_sz * 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) @@ -169,31 +169,10 @@ static inline bool in_uicr_space(uint32_t addr) //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ -static uint32_t uf2current_flash_sz = 0; - - -// get current.uf2 flash size in bytes, round up to 256 bytes -static uint32_t current_flash_size(void) -{ - uint32_t flash_sz = 0; - - // return 1 block of 256 bytes - if ( !bootloader_app_is_valid() ) - { - flash_sz = 256; - }else - { - // Use full application size for simplicity - flash_sz = (USER_FLASH_END-USER_FLASH_START); - } - - return flash_sz; -} void uf2_init(void) { - uf2current_flash_sz = current_flash_size(); - PRINT_INT(uf2current_flash_sz); + // nothing to do } /*------------------------------------------------------------------*/ @@ -289,7 +268,7 @@ void read_block(uint32_t block_no, uint8_t *data) { bl->magicStart1 = UF2_MAGIC_START1; bl->magicEnd = UF2_MAGIC_END; bl->blockNo = sectionIdx; - bl->numBlocks = uf2current_flash_sz / 256; + bl->numBlocks = (UF2_SIZE/2) / 256; bl->targetAddr = addr; bl->payloadSize = 256; bl->flags = UF2_FLAG_FAMILYID; From 348f26811323d3e4ac8831569d529f007f41bd44 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 8 May 2020 12:17:47 +0700 Subject: [PATCH 37/61] app is invalid if both of its 2 first words are empty mask --- .../libraries/bootloader_dfu/bootloader.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c index 3bfd510..e9ad1ed 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c @@ -138,13 +138,21 @@ static void wait_for_events(void) bool bootloader_app_is_valid(void) { - uint32_t const app_addr = DFU_BANK_0_REGION_START; - bootloader_settings_t const *p_bootloader_settings; - bool success = false; + uint32_t const app_addr = DFU_BANK_0_REGION_START; + bootloader_settings_t const *p_bootloader_settings; bootloader_util_settings_get(&p_bootloader_settings); + 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 ) { From 4bbdeab8d10ed2a0e8f00549085940b286cccf22 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 8 May 2020 12:18:37 +0700 Subject: [PATCH 38/61] fix ci build by re-using VID/PID of feather 52840 for other boards build for these board will be disabled in the future. --- src/boards/mdk_nrf52840_dongle/board.h | 6 ++++++ src/boards/particle_argon/board.h | 6 ++++++ src/boards/particle_boron/board.h | 6 ++++++ src/boards/particle_xenon/board.h | 6 ++++++ src/boards/pca10100/board.h | 4 ++++ src/boards/raytac_mdbt50q_rx/board.h | 8 +++++--- 6 files changed, 33 insertions(+), 3 deletions(-) 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/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_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_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/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/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" From cf4efa2c94098908f127699746b5cb9d1538df1d Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 8 May 2020 12:27:20 +0700 Subject: [PATCH 39/61] move boards.c/h into boards folder --- Makefile | 6 ++++-- src/{ => boards}/boards.c | 0 src/{ => boards}/boards.h | 0 3 files changed, 4 insertions(+), 2 deletions(-) rename src/{ => boards}/boards.c (100%) rename src/{ => boards}/boards.h (100%) diff --git a/Makefile b/Makefile index 5d6c843..7815f25 100644 --- a/Makefile +++ b/Makefile @@ -95,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) @@ -164,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 diff --git a/src/boards.c b/src/boards/boards.c similarity index 100% rename from src/boards.c rename to src/boards/boards.c diff --git a/src/boards.h b/src/boards/boards.h similarity index 100% rename from src/boards.h rename to src/boards/boards.h From 5ed4d509f52d38d26abb98def7e214e2c66824cf Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 8 May 2020 12:42:41 +0700 Subject: [PATCH 40/61] clean up --- src/main.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/main.c b/src/main.c index c309e5c..9655d03 100644 --- a/src/main.c +++ b/src/main.c @@ -127,18 +127,6 @@ void usb_teardown(void); #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 - //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ From 08c0f27f45b09e5571d40fc1981d4076af0c7c92 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 8 May 2020 12:44:41 +0700 Subject: [PATCH 41/61] correct app address in APP_ASKS_FOR_SINGLE_TAP_RESET() --- src/main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main.c b/src/main.c index 9655d03..a993966 100644 --- a/src/main.c +++ b/src/main.c @@ -119,8 +119,7 @@ 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. -// TODO correct USER_FLASH_START = APP after SoftDevice -#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 From 46adc425a4a401e7b64d371a808d5393fbf0b89a Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 11 May 2020 19:03:39 +0700 Subject: [PATCH 42/61] try to allow new bootloader with different size than current one however, due to the design of MBR, the SD_MBR_COMMAND_COPY_BL prioritize its internal flash location MBR_BOOTLOADER_ADDR, we won't be able to change bootloader starting address to increase its size --- .gitignore | 5 +- src/main.c | 6 +- src/usb/msc_uf2.c | 58 ++++++++++++++++- src/usb/uf2/ghostfat.c | 144 +++++++++++++++++++++++++---------------- src/usb/uf2/uf2.h | 9 ++- src/usb/uf2/uf2cfg.h | 25 ++++--- 6 files changed, 174 insertions(+), 73 deletions(-) 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/src/main.c b/src/main.c index a993966..3e1c04d 100644 --- a/src/main.c +++ b/src/main.c @@ -153,10 +153,10 @@ void softdev_mbr_init(void) //--------------------------------------------------------------------+ int main(void) { - // Populate Boot Address and MBR Param if not already - // Happens if flashing SD hex that overwrite current MBR + // 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 - bootloader_mbr_addrs_populate(); + // Note: skip it for now since this will prevent us to change the size of bootloader + 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); diff --git a/src/usb/msc_uf2.c b/src/usb/msc_uf2.c index bee6f22..9829b92 100644 --- a/src/usb/msc_uf2.c +++ b/src/usb/msc_uf2.c @@ -162,7 +162,21 @@ void tud_msc_write10_complete_cb(uint8_t lun) { static bool first_write = true; - if ( _wr_state.numBlocks ) + // abort the DFU, uf2 block failed integrity check + if ( _wr_state.aborted ) + { + // 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_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) @@ -177,13 +191,53 @@ void tud_msc_write10_complete_cb(uint8_t lun) dfu_update_status_t update_status; memset(&update_status, 0, sizeof(dfu_update_status_t )); - if ( _wr_state.update_bootloader ) + if ( _wr_state.boot_addr_ucir ) { // update bootloader + update_status.status_code = DFU_RESET; + + if ( 0 == memcmp((uint8_t*) _wr_state.boot_stored_addr, (uint8_t*) BOOTLOADER_ADDR_START, _wr_state.boot_size) ) + { + // skip if there is no bootloader change + }else + { + PRINTF("Coyping bootloader to 0x%08lX from 0x%08lX with size = 0x%lX\r\n", + _wr_state.boot_addr_ucir, _wr_state.boot_stored_addr, _wr_state.boot_size); + + // erase an change UCIR bootloader +// if ( ) + + sd_mbr_command_t command = + { + .command = SD_MBR_COMMAND_COPY_BL, + .params.copy_bl.bl_src = (uint32_t*) _wr_state.boot_stored_addr, + .params.copy_bl.bl_len = _wr_state.boot_size/4 // size in words + }; + + if ( NRF_SUCCESS != sd_mbr_command(&command) ) + { + PRINTF("Failed to execute SD_MBR_COMMAND_COPY_BL, we are about to bricked\r\n"); + }else + { + PRINTF("SD_MBR_COMMAND_COPY_BL successfully\r\n"); + } + + NRFX_DELAY_MS(10); +// update_status.status_code = DFU_UPDATE_BOOT_COMPLETE; +// update_status.bl_size = _wr_state.boot_size; +// +// // Reuse the DFU combined SD + Bootloader with SD Size = 0 +// update_status.sd_image_start = _wr_state.boot_stored_addr; +// update_status.sd_size = 0; + } + + 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); diff --git a/src/usb/uf2/ghostfat.c b/src/usb/uf2/ghostfat.c index 8ad74bf..4fcb522 100644 --- a/src/usb/uf2/ghostfat.c +++ b/src/usb/uf2/ghostfat.c @@ -151,21 +151,40 @@ static inline bool is_uf2_block (UF2_Block const *bl) (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 CFG_UF2_BOOTLOADER_ADDR_START <= addr && addr < CFG_UF2_BOOTLOADER_ADDR_END; + return BOOTLOADER_LOWEST_ADDR <= addr && addr < BOOTLOADER_ADDR_END; } +static inline uint32_t get_new_bootloader_size(uint32_t numblocks) +{ + // -1 for UCIR block + uint32_t new_size = (numblocks-1)*256; + + // round up to 4K + uint32_t mod4k = new_size & 0xFFFUL; + if ( mod4k ) new_size += 4096 - mod4k; + + return new_size; +} + +// used when upgrading bootloader static inline bool in_uicr_space(uint32_t addr) { return addr == 0x10001000; } +//static inline get_new_bootloader_base(uint32_t ) + +static inline uint32_t max32 (uint32_t x, uint32_t y) { return (x > y) ? x : y; } + //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ @@ -284,14 +303,7 @@ void read_block(uint32_t block_no, uint8_t *data) { *------------------------------------------------------------------*/ /** - * Write an uf2 block wrapped by 512 sector. Writing behavior is different when upgrading: - * - Application - * - current App is erased and flash with new firmware with same starting address - * - * - SoftDevice + Bootloader - * - Current App is erased, contents of SD + bootloader is written to App starting address - * - Trigger the SD + Bootloader migration - * + * 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 @@ -308,18 +320,7 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state) case CFG_UF2_FAMILY_ID: /* Upgrading Application * - * Although SoftDevice is considered as part of application and the flashing is the same with/without it. - * There are still 4 cases with slight differences in finishing procedure: - * 1. Application with SoftDevice: - * - starting address 0x0000 - * - since MBR is included in SD Hex file (then uf2 file), we must skip it - * 2. Application only - * a. For running with existing SoftDevice on the flash: - * - starting address is right after SD e.g 0x26000 - * b. For running without SoftDevice e.g using other stack such as nimble or zephyr. - * - starting address is right after MBR 0x1000 - * 3. SoftDevice only, should user somehow only flash with SD only. Bootloader mark app as invalid and wiil - * back on bootloader mode after reset. + * SoftDevice is considered as part of application and can be (or not) included in uf2. * * ------------- ------------- * | | | | @@ -338,19 +339,12 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state) 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); - - // writing to SD Info struct is used as SD detector - if (bl->targetAddr == (SOFTDEVICE_INFO_STRUCT_ADDRESS & 0xFFFFFF00) ) - { - state->has_sd = true; - } - flash_nrf5x_write(bl->targetAddr, bl->data, bl->payloadSize, true); }else if ( bl->targetAddr < USER_FLASH_START ) { - // do nothing if writing to MBR + // do nothing if writing to MBR, occurs when SD hex is included // keep going as successful write - state->has_mbr = true; + PRINTF("skip writing to MBR\r\n"); }else { return -1; @@ -358,14 +352,23 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state) break; case CFG_UF2_BOOTLOADER_ID: - /* Upgrading Bootloader (with/without SoftDevice) + /* Upgrading Bootloader + * + * Along with bootloader code, UCIR (at 0x1000100) is also included containing + * 0x10001014 (bootloader address), and 0x10001018 (MBR Params address). + * + * Since SoftDevice is not part of Bootloader, it must not be included as part of uf2 file. + * To prevent generating uf2 from incorrect bin/hex. Bootloader imposes a hard code limit size + * of 64 KB (end address is fixed at MBR Params). If uf2 contains any address lower than this + * (except UCIR) the update is aborted. * * To prevent corruption/disconnection while transferring we don't directly write over - * Bootloader. Instead Bootloader is written to Application region. - * Once everything is received and verified. It is written to its respective address + * 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. * - * Note: to simplify the upgrade process, we ASSUME, Bootloader size is fixed and - * is the same as the old bootloader + * 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 | @@ -374,41 +377,68 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state) * | | | New | + | | * | | | Bootloader | + | | * | | | ++++++++ | | | - * | Application | ---> | | | | + * | | ---> | | | | + * | | | | | | + * | Application | | Application | | Application | + * | | | | | | * | | | | | | - * | | | ++++++++ | | ++++++++ | - * | | | New | | New | - * | | | SoftDevice | | SoftDevice | * 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); + + uint32_t const new_boot_size = get_new_bootloader_size(bl->numBlocks); + + // Offset write the new bootloader address. + // The offset is the current bootloader size or the new size whichever is larger + uint32_t const offset_addr = max32(new_boot_size, BOOTLOADER_ADDR_END-BOOTLOADER_ADDR_START); + if ( in_uicr_space(bl->targetAddr) ) { /* UCIR contains bootloader & MBR address as follow: - * - 0x10001014 bootloader address: only change of bootloader size changes + * - 0x10001014 bootloader address: only change if bootloader size changes * - 0x10001018 MBR Params: mostly fixed * - * WARNING: incorrect value of these UCIR will break device + * WARNING: incorrect value of these UCIR will brick device */ + uint32_t ucir_boot_addr; + uint32_t ucir_mbr_param; - // Nothing to do since bootloader size is fixed - return 512; - } - else if ( in_bootloader_space(bl->targetAddr) ) - { - // Right above the old SoftDevice - } - else if ( in_app_space(bl->targetAddr) ) - { - // Right below the old Bootloader - //wr_addr = USER_FLASH_START + bl->targetAddr; - // writing to SD Info struct is used as SD detector - // if (bl->targetAddr == SOFTDEVICE_INFO_STRUCT_ADDRESS) state->has_sd = true; + memcpy(&ucir_boot_addr, bl->data + 0x14, 4); + memcpy(&ucir_mbr_param, bl->data + 0x18, 4); + PRINT_HEX(ucir_boot_addr); + PRINT_HEX(ucir_mbr_param); + + PRINT_HEX(new_boot_size); + + // Check MBR params is fixed and prohibited to change and + // Bootloader address against its new size + if ( (ucir_mbr_param != BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS) || + (ucir_boot_addr != BOOTLOADER_ADDR_END - new_boot_size) ) + { + PRINTF("Incorrect UCIR value"); + state->aborted = true; + return -1; + }else + { + // Good to go, save the boot address + state->boot_addr_ucir = ucir_boot_addr; + state->boot_size = new_boot_size; + state->boot_stored_addr = BOOTLOADER_ADDR_END - (new_boot_size + offset_addr); + + PRINT_HEX(state->boot_stored_addr); + } + } + else if ( in_bootloader_space(bl->targetAddr) && (bl->targetAddr >= BOOTLOADER_LOWEST_ADDR) ) + { +// PRINT_HEX(offset_addr); + flash_nrf5x_write(bl->targetAddr-offset_addr, bl->data, bl->payloadSize, true); } else { + state->aborted = true; return -1; } break; @@ -446,6 +476,12 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state) if ( state->numWritten >= state->numBlocks ) { flash_nrf5x_flush(true); + + // Failed if update bootloader without UCIR value + if ( (bl->familyID == CFG_UF2_BOOTLOADER_ID) && !state->boot_addr_ucir ) + { + state->aborted = true; + } } } } diff --git a/src/usb/uf2/uf2.h b/src/usb/uf2/uf2.h index a0a72a1..c2feb82 100644 --- a/src/usb/uf2/uf2.h +++ b/src/usb/uf2/uf2.h @@ -52,9 +52,12 @@ SOFTWARE. typedef struct { uint32_t numBlocks; uint32_t numWritten; - bool has_sd; // if uf2 includes SD - bool has_mbr; // if uf2 includes MBR - bool update_bootloader; // if updating bootloader + + bool aborted; // aborting update and reset + uint32_t boot_addr_ucir; // if ucir bootloader address value + uint32_t boot_size; // new bootloader size + uint32_t boot_stored_addr; // temporary base address storing new bootloader + uint8_t writtenMask[MAX_BLOCKS / 8 + 1]; } WriteState; diff --git a/src/usb/uf2/uf2cfg.h b/src/usb/uf2/uf2cfg.h index e2466c1..bfee69a 100644 --- a/src/usb/uf2/uf2cfg.h +++ b/src/usb/uf2/uf2cfg.h @@ -1,16 +1,23 @@ #include "boards.h" #include "dfu_types.h" -#define CFG_UF2_FAMILY_ID 0xADA52840 -#define CFG_UF2_BOOTLOADER_ID ((USB_DESC_VID << 16) | USB_DESC_UF2_PID) +#define CFG_UF2_FAMILY_ID 0xADA52840 +#define CFG_UF2_BOOTLOADER_ID ((USB_DESC_VID << 16) | USB_DESC_UF2_PID) -#define CFG_UF2_NUM_BLOCKS 8000 // at least 4,1 MB for FAT16 -#define CFG_UF2_FLASH_SIZE (1024*1024) // 1 MB +#define CFG_UF2_NUM_BLOCKS 8000 // at least 4,1 MB for FAT16 +#define CFG_UF2_FLASH_SIZE (1024*1024) // 1 MB // Application Address Space -#define USER_FLASH_START MBR_SIZE // skip MBR included in SD hex -#define USER_FLASH_END 0xAD000 +#define USER_FLASH_START MBR_SIZE // skip MBR included in SD hex +#define USER_FLASH_END 0xAD000 -// Bootloader Address Space -#define CFG_UF2_BOOTLOADER_ADDR_START BOOTLOADER_REGION_START -#define CFG_UF2_BOOTLOADER_ADDR_END BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS +// Current Bootloader start address +#define BOOTLOADER_ADDR_START BOOTLOADER_REGION_START + +// Bootloader end address which is always fixed +#define BOOTLOADER_ADDR_END BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS + +// 64 KB is hard coded limit size for bootloader when updating. +// This is used as sanity check to make sure user doesn't make mistake +// converting wrong bin/hex into uf2 file for bootloader. +#define BOOTLOADER_LOWEST_ADDR (BOOTLOADER_ADDR_END - 64*1024) From afeb645a87a75ef02afef24a2ae5889f1aa99713 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 12 May 2020 00:48:06 +0700 Subject: [PATCH 43/61] correct the DFU_BL_IMAGE_MAX_SIZE skip populate MBR_BOOTLOADER_ADDR/MBR_PARAM_PAGE_ADDR --- lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h | 2 +- src/main.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h b/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h index 9492b0e..ecb8f98 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h @@ -74,7 +74,7 @@ static inline bool is_sd_existed(void) #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. */ diff --git a/src/main.c b/src/main.c index 3e1c04d..bf415e5 100644 --- a/src/main.c +++ b/src/main.c @@ -155,8 +155,8 @@ int main(void) { // Populate Boot Address and MBR Param into MBR if not already // MBR_BOOTLOADER_ADDR/MBR_PARAM_PAGE_ADDR are used if available, else UICR registers are used - // Note: skip it for now since this will prevent us to change the size of bootloader - bootloader_mbr_addrs_populate(); + // 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); From 27882cdce635b6cc5d12f6afe194cccef1610ddf Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 12 May 2020 01:28:21 +0700 Subject: [PATCH 44/61] fixed the bootloader start address for simplicity and prevent bricking device --- src/usb/msc_uf2.c | 42 +++++---------- src/usb/uf2/ghostfat.c | 115 ++++++++++++++++++----------------------- src/usb/uf2/uf2.h | 5 +- src/usb/uf2/uf2cfg.h | 17 +++--- 4 files changed, 75 insertions(+), 104 deletions(-) diff --git a/src/usb/msc_uf2.c b/src/usb/msc_uf2.c index 9829b92..4b6817f 100644 --- a/src/usb/msc_uf2.c +++ b/src/usb/msc_uf2.c @@ -191,44 +191,30 @@ void tud_msc_write10_complete_cb(uint8_t lun) dfu_update_status_t update_status; memset(&update_status, 0, sizeof(dfu_update_status_t )); - if ( _wr_state.boot_addr_ucir ) + if ( _wr_state.update_bootloader ) { - // update bootloader + // update bootloader always end with reset update_status.status_code = DFU_RESET; - if ( 0 == memcmp((uint8_t*) _wr_state.boot_stored_addr, (uint8_t*) BOOTLOADER_ADDR_START, _wr_state.boot_size) ) - { - // skip if there is no bootloader change - }else - { - PRINTF("Coyping bootloader to 0x%08lX from 0x%08lX with size = 0x%lX\r\n", - _wr_state.boot_addr_ucir, _wr_state.boot_stored_addr, _wr_state.boot_size); + // Location of current stored new bootloader + uint32_t * new_bootloader = (uint32_t *) BOOTLOADER_ADDR_NEW_RECIEVED; - // erase an change UCIR bootloader -// if ( ) + 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 = (uint32_t*) _wr_state.boot_stored_addr, - .params.copy_bl.bl_len = _wr_state.boot_size/4 // size in words + .params.copy_bl.bl_src = new_bootloader, + .params.copy_bl.bl_len = DFU_BL_IMAGE_MAX_SIZE/4 // size in words }; - if ( NRF_SUCCESS != sd_mbr_command(&command) ) - { - PRINTF("Failed to execute SD_MBR_COMMAND_COPY_BL, we are about to bricked\r\n"); - }else - { - PRINTF("SD_MBR_COMMAND_COPY_BL successfully\r\n"); - } - - NRFX_DELAY_MS(10); -// update_status.status_code = DFU_UPDATE_BOOT_COMPLETE; -// update_status.bl_size = _wr_state.boot_size; -// -// // Reuse the DFU combined SD + Bootloader with SD Size = 0 -// update_status.sd_image_start = _wr_state.boot_stored_addr; -// update_status.sd_size = 0; + // on success, COPY_BL won't return but run the new bootloader right away. + sd_mbr_command(&command); } PRINTF("bootloader update complete\r\n"); diff --git a/src/usb/uf2/ghostfat.c b/src/usb/uf2/ghostfat.c index 4fcb522..c1da17c 100644 --- a/src/usb/uf2/ghostfat.c +++ b/src/usb/uf2/ghostfat.c @@ -160,19 +160,7 @@ static inline bool in_app_space (uint32_t addr) // used when upgrading bootloader static inline bool in_bootloader_space (uint32_t addr) { - return BOOTLOADER_LOWEST_ADDR <= addr && addr < BOOTLOADER_ADDR_END; -} - -static inline uint32_t get_new_bootloader_size(uint32_t numblocks) -{ - // -1 for UCIR block - uint32_t new_size = (numblocks-1)*256; - - // round up to 4K - uint32_t mod4k = new_size & 0xFFFUL; - if ( mod4k ) new_size += 4096 - mod4k; - - return new_size; + return BOOTLOADER_ADDR_START <= addr && addr < BOOTLOADER_ADDR_END; } // used when upgrading bootloader @@ -324,13 +312,13 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state) * * ------------- ------------- * | | | | - * | Bootloader | | Bootloader | + * | Bootloader | | Bootloader | * BOOTLOADER_ADDR_START--|-------------| |-------------| + * | App Data | | App Data | + * USER_FLASH_END ---|-------------| |-------------| * | | | | - * | | | | - * | Application | ---> | New | - * | | | Application | - * | | | | + * | | | New | + * | Application | ----> | Application | * | | | | * USER_FLASH_START--|-------------| |-------------| * | MBR | | MBR | @@ -354,19 +342,17 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state) case CFG_UF2_BOOTLOADER_ID: /* Upgrading Bootloader * - * Along with bootloader code, UCIR (at 0x1000100) is also included containing + * - 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). * - * Since SoftDevice is not part of Bootloader, it must not be included as part of uf2 file. - * To prevent generating uf2 from incorrect bin/hex. Bootloader imposes a hard code limit size - * of 64 KB (end address is fixed at MBR Params). If uf2 contains any address lower than this - * (except UCIR) the update is aborted. - * - * 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. - * * Note: part of the existing application can be affected when updating bootloader. * TODO May be worth to have some kind crc/application integrity checking * @@ -374,11 +360,11 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state) * | | | | + | New | * | Bootloader | | Bootloader | + | Bootloader | * BOOTLOADER_ADDR_START--|-------------| |-------------| + |-------------| - * | | | New | + | | - * | | | Bootloader | + | | - * | | | ++++++++ | | | - * | | ---> | | | | - * | | | | | | + * | App Data | | App Data | + | App Data | + * USER_FLASH_END --|-------------| | ---------- | + |------------ | + * | | | New |+ | | + * | | ---> | Bootloader | | | + * | | | ++++++ | | | * | Application | | Application | | Application | * | | | | | | * | | | | | | @@ -388,54 +374,53 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state) */ PRINTF("addr = 0x%08lX, block = %ld (%ld of %ld)\r\n", bl->targetAddr, bl->blockNo, state->numWritten, bl->numBlocks); - uint32_t const new_boot_size = get_new_bootloader_size(bl->numBlocks); - - // Offset write the new bootloader address. - // The offset is the current bootloader size or the new size whichever is larger - uint32_t const offset_addr = max32(new_boot_size, BOOTLOADER_ADDR_END-BOOTLOADER_ADDR_START); - + state->update_bootloader = true; if ( in_uicr_space(bl->targetAddr) ) { /* UCIR contains bootloader & MBR address as follow: - * - 0x10001014 bootloader address: only change if bootloader size changes + * - 0x10001014 bootloader address * - 0x10001018 MBR Params: mostly fixed * - * WARNING: incorrect value of these UCIR will brick device + * Since the bootloader start address is fixed, we only use this for verification */ - uint32_t ucir_boot_addr; - uint32_t ucir_mbr_param; + uint32_t uicr_boot_addr; + uint32_t uicr_mbr_param; - memcpy(&ucir_boot_addr, bl->data + 0x14, 4); - memcpy(&ucir_mbr_param, bl->data + 0x18, 4); - - PRINT_HEX(ucir_boot_addr); - PRINT_HEX(ucir_mbr_param); - - PRINT_HEX(new_boot_size); + 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 ( (ucir_mbr_param != BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS) || - (ucir_boot_addr != BOOTLOADER_ADDR_END - new_boot_size) ) + if ( (uicr_boot_addr != BOOTLOADER_ADDR_START) || + (uicr_mbr_param != BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS) ) { - PRINTF("Incorrect UCIR value"); + PRINTF("Incorrect UICR value"); + PRINT_HEX(uicr_boot_addr); + PRINT_HEX(uicr_mbr_param); + state->aborted = true; return -1; - }else - { - // Good to go, save the boot address - state->boot_addr_ucir = ucir_boot_addr; - state->boot_size = new_boot_size; - state->boot_stored_addr = BOOTLOADER_ADDR_END - (new_boot_size + offset_addr); - - PRINT_HEX(state->boot_stored_addr); } + + state->has_uicr = true; } - else if ( in_bootloader_space(bl->targetAddr) && (bl->targetAddr >= BOOTLOADER_LOWEST_ADDR) ) + else if ( in_bootloader_space(bl->targetAddr) ) { -// PRINT_HEX(offset_addr); + // 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); + } + else if ( bl->targetAddr < USER_FLASH_START ) + { + PRINTF("skip writing to MBR\r\n"); + } +#endif else { state->aborted = true; @@ -478,7 +463,7 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state) flash_nrf5x_flush(true); // Failed if update bootloader without UCIR value - if ( (bl->familyID == CFG_UF2_BOOTLOADER_ID) && !state->boot_addr_ucir ) + if ( state->update_bootloader && !state->has_uicr ) { state->aborted = true; } diff --git a/src/usb/uf2/uf2.h b/src/usb/uf2/uf2.h index c2feb82..d4f92e7 100644 --- a/src/usb/uf2/uf2.h +++ b/src/usb/uf2/uf2.h @@ -54,9 +54,8 @@ typedef struct { uint32_t numWritten; bool aborted; // aborting update and reset - uint32_t boot_addr_ucir; // if ucir bootloader address value - uint32_t boot_size; // new bootloader size - uint32_t boot_stored_addr; // temporary base address storing new bootloader + bool update_bootloader; // if updating bootloader (else app) + bool has_uicr; // if containing uicr data uint8_t writtenMask[MAX_BLOCKS / 8 + 1]; } WriteState; diff --git a/src/usb/uf2/uf2cfg.h b/src/usb/uf2/uf2cfg.h index bfee69a..d79a1b3 100644 --- a/src/usb/uf2/uf2cfg.h +++ b/src/usb/uf2/uf2cfg.h @@ -11,13 +11,14 @@ #define USER_FLASH_START MBR_SIZE // skip MBR included in SD hex #define USER_FLASH_END 0xAD000 -// Current Bootloader start address -#define BOOTLOADER_ADDR_START BOOTLOADER_REGION_START +// Due to SD_MBR_COMMAND_COPY_BL, bootloader start address cannot +// be changed with DFU, and only done with a debugger -// Bootloader end address which is always fixed -#define BOOTLOADER_ADDR_END BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS +// Bootloader start address +#define BOOTLOADER_ADDR_START BOOTLOADER_REGION_START -// 64 KB is hard coded limit size for bootloader when updating. -// This is used as sanity check to make sure user doesn't make mistake -// converting wrong bin/hex into uf2 file for bootloader. -#define BOOTLOADER_LOWEST_ADDR (BOOTLOADER_ADDR_END - 64*1024) +// 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) From d594cbc1a4dccdff2c2b1f2c0663070ce6669f9f Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 12 May 2020 13:25:52 +0700 Subject: [PATCH 45/61] add intelhex submodule clean up --- .gitmodules | 3 +++ lib/intelhex | 1 + src/usb/uf2/ghostfat.c | 2 +- src/usb/usb.c | 5 ----- 4 files changed, 5 insertions(+), 6 deletions(-) create mode 160000 lib/intelhex diff --git a/.gitmodules b/.gitmodules index 47b2bcb..71fbabc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "lib/uf2"] path = lib/uf2 url = https://github.com/microsoft/uf2.git +[submodule "lib/intelhex"] + path = lib/intelhex + url = https://github.com/python-intelhex/intelhex.git diff --git a/lib/intelhex b/lib/intelhex new file mode 160000 index 0000000..5c15003 --- /dev/null +++ b/lib/intelhex @@ -0,0 +1 @@ +Subproject commit 5c15003d08bf53512d5eaa54c7d2825a8b5c37cc diff --git a/src/usb/uf2/ghostfat.c b/src/usb/uf2/ghostfat.c index c1da17c..13c3fb5 100644 --- a/src/usb/uf2/ghostfat.c +++ b/src/usb/uf2/ghostfat.c @@ -416,11 +416,11 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state) // 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"); } -#endif else { state->aborted = true; diff --git a/src/usb/usb.c b/src/usb/usb.c index bdbf00d..6a48483 100644 --- a/src/usb/usb.c +++ b/src/usb/usb.c @@ -24,11 +24,8 @@ #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" @@ -63,7 +60,6 @@ void usb_init(bool cdc_only) // We need to invoke the handler based on the status initially uint32_t usb_reg; -#ifdef SOFTDEVICE_PRESENT uint8_t sd_en = false; if ( is_sd_existed() ) @@ -79,7 +75,6 @@ void usb_init(bool cdc_only) sd_power_usbregstatus_get(&usb_reg); }else -#endif { // Power module init const nrfx_power_config_t pwr_cfg = { 0 }; From 013458ad9788f0506f5ff8a10014255bd7f87190 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 12 May 2020 14:33:56 +0700 Subject: [PATCH 46/61] makefile to generate bootloader-nosd.uf2 everything seems working --- Makefile | 106 +++++++++--------- README.md | 20 +--- .../libraries/bootloader_dfu/bootloader.c | 5 + .../bootloader_dfu/dfu_single_bank.c | 4 +- segger/Adafruit_nRF52_Bootloader.emProject | 4 +- src/flash_nrf5x.c | 7 +- src/main.c | 4 + 7 files changed, 78 insertions(+), 72 deletions(-) diff --git a/Makefile b/Makefile index 7815f25..6a2823a 100644 --- a/Makefile +++ b/Makefile @@ -210,7 +210,6 @@ ifeq ($(DEBUG), 1) 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_printf.c C_SRC += $(RTT_SRC)/RTT/SEGGER_RTT.c endif @@ -314,7 +313,58 @@ endif .PHONY: all clean flash dfu-flash sd gdbflash gdb # default target to build -all: $(BUILD)/$(OUT_FILE)-nosd.out $(BUILD)/$(MERGED_FILE).hex $(BUILD)/$(MERGED_FILE).uf2 +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 +$(BUILD): + @$(MK) $@ + +clean: + @$(RM) $(BUILD) + +# Create objects from C SRC files +$(BUILD)/%.o: %.c + @echo CC $(notdir $<) + @$(CC) $(CFLAGS) $(INC_PATHS) -c -o $@ $< + +# Assemble files +$(BUILD)/%.o: %.S + @echo AS $(notdir $<) + @$(CC) -x assembler-with-cpp $(ASFLAGS) $(INC_PATHS) -c -o $@ $< + +# Link +$(BUILD)/$(OUT_FILE).out: $(BUILD) $(OBJECTS) + @echo LD $(notdir $@) + @$(CC) -o $@ $(LDFLAGS) $(OBJECTS) -Wl,--start-group $(LIBS) -Wl,--end-group + @$(SIZE) $@ + +#------------------- Binary generator ------------------- + +# Create hex file (no sd, no mbr) +$(BUILD)/$(OUT_FILE).hex: $(BUILD)/$(OUT_FILE).out + @echo CR $(notdir $@) + @$(OBJCOPY) -O ihex $< $@ + +# Hex file with mbr (still no SD) +$(BUILD)/$(OUT_FILE)-nosd.hex: $(BUILD)/$(OUT_FILE).hex + @echo CR $(notdir $@) + @python lib/intelhex/scripts/hexmerge.py --overlap=replace -o $@ $< $(MBR_HEX) + +# Bootolader only uf2 +$(BUILD)/$(OUT_FILE)-nosd.uf2: $(BUILD)/$(OUT_FILE)-nosd.hex + @echo CR $(notdir $@) + python lib/uf2/utils/uf2conv.py -f 0x239A0029 -c -o $@ $^ + +# merge bootloader and sd hex together +$(BUILD)/$(MERGED_FILE).hex: $(BUILD)/$(OUT_FILE).hex + @echo CR $(notdir $@) + @python lib/intelhex/scripts/hexmerge.py -o $@ $< $(SD_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 ------------------- @@ -342,7 +392,7 @@ erase: # flash SD only sd: @echo Flashing: $(SD_HEX) - $(NRFJPROG) --program $(SD_HEX) -f nrf52 --sectorerase --reset + $(NRFJPROG) --program $(SD_HEX) -f nrf52 --sectorerase --reset # flash MBR only mbr: @@ -353,53 +403,5 @@ 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: $(BUILD)/$(OUT_FILE).out $(GDB_BMP) $< - -#------------------- Compile rules ------------------- - -# Create build directories -$(BUILD): - @$(MK) $@ - -clean: - @$(RM) $(BUILD) - -# Create objects from C SRC files -$(BUILD)/%.o: %.c - @echo CC $(notdir $<) - @$(CC) $(CFLAGS) $(INC_PATHS) -c -o $@ $< - -# Assemble files -$(BUILD)/%.o: %.S - @echo AS $(notdir $<) - @$(CC) -x assembler-with-cpp $(ASFLAGS) $(INC_PATHS) -c -o $@ $< - -# Link -$(BUILD)/$(OUT_FILE)-nosd.out: $(BUILD) $(OBJECTS) - @echo LD $(notdir $@) - @$(CC) -o $@ $(LDFLAGS) $(OBJECTS) -Wl,--start-group $(LIBS) -Wl,--end-group - @$(SIZE) $@ - -#------------------- Binary generator ------------------- - -# Create hex file -$(BUILD)/$(OUT_FILE)-nosd.hex: $(BUILD)/$(OUT_FILE)-nosd.out - @echo CR $(notdir $@) - @$(OBJCOPY) -O ihex $< $@ - -# merge bootloader and sd hex together -$(BUILD)/$(MERGED_FILE).hex: $(BUILD)/$(OUT_FILE)-nosd.hex - @echo CR $(notdir $@) - @mergehex -q -m $< $(SD_HEX) -o $@ - -$(BUILD)/$(MERGED_FILE).uf2: $(BUILD)/$(MERGED_FILE).hex - @echo CR $(notdir $@) - python lib/uf2/utils/uf2conv.py -f 0x239A0029 -c -o $@ $^ - -# 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 - @$(NRFUTIL) dfu genpkg --dev-type 0x0052 --dev-revision $(DFU_DEV_REV) --bootloader $< --softdevice $(SD_HEX) $@ diff --git a/README.md b/README.md index 6c65816..7b84946 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 @@ -111,6 +98,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: diff --git a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c index e9ad1ed..748ccbc 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c @@ -358,11 +358,14 @@ void bootloader_app_start(void) 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 = @@ -377,6 +380,8 @@ void bootloader_app_start(void) // 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; } 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 82e2728..1dbaf3b 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c @@ -150,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/segger/Adafruit_nRF52_Bootloader.emProject b/segger/Adafruit_nRF52_Bootloader.emProject index 4f3766d..8084a4d 100644 --- a/segger/Adafruit_nRF52_Bootloader.emProject +++ b/segger/Adafruit_nRF52_Bootloader.emProject @@ -332,9 +332,9 @@ + + - - Date: Tue, 12 May 2020 14:36:42 +0700 Subject: [PATCH 47/61] update tinyusb for dcd nrf detect SD dynamically. --- lib/tinyusb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tinyusb b/lib/tinyusb index 101f234..4e6aa0d 160000 --- a/lib/tinyusb +++ b/lib/tinyusb @@ -1 +1 @@ -Subproject commit 101f234a1637b995e771b4999afdf4793ffdc86e +Subproject commit 4e6aa0d81d2dbd23006d5a961938f6478049467a From c41dd59b5f1f0dc9c3605519032dab5038994fe6 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 12 May 2020 14:45:51 +0700 Subject: [PATCH 48/61] fixing ci build --- tools/build_all.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/build_all.py b/tools/build_all.py index 24640f5..fe8a41a 100644 --- a/tools/build_all.py +++ b/tools/build_all.py @@ -34,7 +34,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 = "-" From d50796ff4cccd493c9cbdd1114fb7dcad94b27fc Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 12 May 2020 14:53:13 +0700 Subject: [PATCH 49/61] replace mergehex with python-intelhex --- .github/workflows/githubci.yml | 8 ++++---- README.md | 13 ++++++++++--- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/.github/workflows/githubci.yml b/.github/workflows/githubci.yml index a683845..134fa88 100644 --- a/.github/workflows/githubci.yml +++ b/.github/workflows/githubci.yml @@ -23,10 +23,10 @@ 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 + #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" 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/README.md b/README.md index 7b84946..9ab1e58 100644 --- a/README.md +++ b/README.md @@ -152,10 +152,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` From 29a62bc0ed3249d572785629fa9efbbbb5a24a00 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 12 May 2020 15:39:39 +0700 Subject: [PATCH 50/61] continue to fix ci --- tools/build_all.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/build_all.py b/tools/build_all.py index fe8a41a..2220bae 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() From 0e4995c680f0344ecd8a7383f64ab1d282293f9b Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 12 May 2020 16:06:02 +0700 Subject: [PATCH 51/61] drop SD in linker name --- .github/workflows/githubci.yml | 3 --- Makefile | 4 ++-- linker/{nrf52_s132_v6.ld => nrf52.ld} | 0 linker/{nrf52833_s140_v6.ld => nrf52833.ld} | 0 linker/{nrf52840_s140_v6.ld => nrf52840.ld} | 0 tools/build_all.py | 7 ++++--- 6 files changed, 6 insertions(+), 8 deletions(-) rename linker/{nrf52_s132_v6.ld => nrf52.ld} (100%) rename linker/{nrf52833_s140_v6.ld => nrf52833.ld} (100%) rename linker/{nrf52840_s140_v6.ld => nrf52840.ld} (100%) diff --git a/.github/workflows/githubci.yml b/.github/workflows/githubci.yml index 134fa88..22fc553 100644 --- a/.github/workflows/githubci.yml +++ b/.github/workflows/githubci.yml @@ -24,9 +24,6 @@ jobs: - name: Install Toolchains run: | pip3 install adafruit-nrfutil uritemplate requests intelhex - #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" 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/Makefile b/Makefile index 6a2823a..f723aac 100644 --- a/Makefile +++ b/Makefile @@ -19,8 +19,8 @@ SD_HEX = $(SD_PATH)/$(SD_FILENAME)_softdevice.hex MBR_HEX = lib/softdevice/mbr/hex/mbr_nrf52_2.4.1_mbr.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 +# 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" " -) diff --git a/linker/nrf52_s132_v6.ld b/linker/nrf52.ld similarity index 100% rename from linker/nrf52_s132_v6.ld rename to linker/nrf52.ld diff --git a/linker/nrf52833_s140_v6.ld b/linker/nrf52833.ld similarity index 100% rename from linker/nrf52833_s140_v6.ld rename to linker/nrf52833.ld diff --git a/linker/nrf52840_s140_v6.ld b/linker/nrf52840.ld similarity index 100% rename from linker/nrf52840_s140_v6.ld rename to linker/nrf52840.ld diff --git a/tools/build_all.py b/tools/build_all.py index 2220bae..486afa8 100644 --- a/tools/build_all.py +++ b/tools/build_all.py @@ -56,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)) From 7c8e1e59e5a54c88857a1a6071a1adfad6c04378 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 12 May 2020 16:40:24 +0700 Subject: [PATCH 52/61] change bootloader family id to random generated value of 0xd663823c --- Makefile | 2 +- src/usb/uf2/configkeys.h | 2 -- src/usb/uf2/ghostfat.c | 6 +++--- src/usb/uf2/uf2cfg.h | 10 +++++----- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index f723aac..195aea9 100644 --- a/Makefile +++ b/Makefile @@ -355,7 +355,7 @@ $(BUILD)/$(OUT_FILE)-nosd.hex: $(BUILD)/$(OUT_FILE).hex # Bootolader only uf2 $(BUILD)/$(OUT_FILE)-nosd.uf2: $(BUILD)/$(OUT_FILE)-nosd.hex @echo CR $(notdir $@) - python lib/uf2/utils/uf2conv.py -f 0x239A0029 -c -o $@ $^ + python lib/uf2/utils/uf2conv.py -f 0xd663823c -c -o $@ $^ # merge bootloader and sd hex together $(BUILD)/$(MERGED_FILE).hex: $(BUILD)/$(OUT_FILE).hex diff --git a/src/usb/uf2/configkeys.h b/src/usb/uf2/configkeys.h index 09e90b5..9c45b21 100644 --- a/src/usb/uf2/configkeys.h +++ b/src/usb/uf2/configkeys.h @@ -7,8 +7,6 @@ #define CFG_PIN_NAME_MSK 0xffff #define CFG_PIN_CONFIG_MSK 0xffff0000 #define CFG_PIN_CONFIG_ACTIVE_LO 0x10000 -#define CFG_MAGIC0 0x1e9e10f1 -#define CFG_MAGIC1 0x20227a79 #define CFG_PIN_ACCELEROMETER_INT 1 #define CFG_PIN_ACCELEROMETER_SCL 2 #define CFG_PIN_ACCELEROMETER_SDA 3 diff --git a/src/usb/uf2/ghostfat.c b/src/usb/uf2/ghostfat.c index 13c3fb5..defb76f 100644 --- a/src/usb/uf2/ghostfat.c +++ b/src/usb/uf2/ghostfat.c @@ -279,7 +279,7 @@ void read_block(uint32_t block_no, uint8_t *data) { bl->targetAddr = addr; bl->payloadSize = 256; bl->flags = UF2_FLAG_FAMILYID; - bl->familyID = CFG_UF2_FAMILY_ID; + bl->familyID = CFG_UF2_FAMILY_APP_ID; memcpy(bl->data, (void *)addr, bl->payloadSize); } } @@ -305,7 +305,7 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state) switch ( bl->familyID ) { - case CFG_UF2_FAMILY_ID: + case CFG_UF2_FAMILY_APP_ID: /* Upgrading Application * * SoftDevice is considered as part of application and can be (or not) included in uf2. @@ -339,7 +339,7 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state) } break; - case CFG_UF2_BOOTLOADER_ID: + case CFG_UF2_FAMILY_BOOT_ID: /* Upgrading Bootloader * * - For simplicity, the Bootloader Start Address is fixed for now. diff --git a/src/usb/uf2/uf2cfg.h b/src/usb/uf2/uf2cfg.h index d79a1b3..df06f24 100644 --- a/src/usb/uf2/uf2cfg.h +++ b/src/usb/uf2/uf2cfg.h @@ -1,8 +1,11 @@ #include "boards.h" #include "dfu_types.h" -#define CFG_UF2_FAMILY_ID 0xADA52840 -#define CFG_UF2_BOOTLOADER_ID ((USB_DESC_VID << 16) | USB_DESC_UF2_PID) +// Family ID for updating Application +#define CFG_UF2_FAMILY_APP_ID 0xADA52840 + +// Family ID for updating Bootloader +#define CFG_UF2_FAMILY_BOOT_ID 0xd663823c #define CFG_UF2_NUM_BLOCKS 8000 // at least 4,1 MB for FAT16 #define CFG_UF2_FLASH_SIZE (1024*1024) // 1 MB @@ -11,9 +14,6 @@ #define USER_FLASH_START MBR_SIZE // skip MBR included in SD hex #define USER_FLASH_END 0xAD000 -// Due to SD_MBR_COMMAND_COPY_BL, bootloader start address cannot -// be changed with DFU, and only done with a debugger - // Bootloader start address #define BOOTLOADER_ADDR_START BOOTLOADER_REGION_START From 7929dc3dae7331ab27a141c604d948b98dd9c6ee Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 12 May 2020 20:27:07 +0700 Subject: [PATCH 53/61] add check for boatloader id in cf2 config --- .../feather_nrf52840_express/pinconfig.c | 25 +++++++++++++ src/flash_nrf5x.c | 2 +- src/usb/uf2/ghostfat.c | 36 +++++++++++++++++++ src/usb/uf2/uf2.h | 1 + 4 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 src/boards/feather_nrf52840_express/pinconfig.c diff --git a/src/boards/feather_nrf52840_express/pinconfig.c b/src/boards/feather_nrf52840_express/pinconfig.c new file mode 100644 index 0000000..4337212 --- /dev/null +++ b/src/boards/feather_nrf52840_express/pinconfig.c @@ -0,0 +1,25 @@ +#include "boards.h" +#include "uf2/configkeys.h" + +__attribute__((used, section(".bootloaderConfig"))) +const uint32_t bootloaderConfig[] = +{ + /* CF2 START */ + CFG_MAGIC0, CFG_MAGIC1, // magic + 32, 100, // used entries, total entries + +#ifdef LED_NEOPIXEL + 20, LED_NEOPIXEL, // PIN_NEOPIXEL + 200, NEOPIXELS_NUMBER, // NUM_NEOPIXELS +#endif + + 204, 0x100000, // FLASH_BYTES = 0x100000 + 205, 0x40000, // RAM_BYTES = 0x40000 + CFG_BOOTLOADER_BOARD_ID, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, + 209, 0xada52840, // UF2_FAMILY = 0xada52840 + 210, 0x20, // PINS_PORT_SIZE = PA_32 + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* CF2 END */ +}; diff --git a/src/flash_nrf5x.c b/src/flash_nrf5x.c index f338ed6..12c6797 100644 --- a/src/flash_nrf5x.c +++ b/src/flash_nrf5x.c @@ -47,7 +47,7 @@ void flash_nrf5x_flush (bool need_erase) // Note: MSC uf2 does not erase page in advance like dfu serial if ( need_erase ) { - PRINTF("Erase 0x%08lX\r\n", _fl_addr); + PRINTF("Erase and "); nrfx_nvmc_page_erase(_fl_addr); } diff --git a/src/usb/uf2/ghostfat.c b/src/usb/uf2/ghostfat.c index defb76f..0127c34 100644 --- a/src/usb/uf2/ghostfat.c +++ b/src/usb/uf2/ghostfat.c @@ -1,6 +1,7 @@ #include "compile_date.h" #include "uf2.h" +#include "configkeys.h" #include "flash_nrf5x.h" #include @@ -140,6 +141,10 @@ static FAT_BootBlock const BootBlock = { .FilesystemIdentifier = "FAT16 ", }; +// Use bootloaderConfig to detect BOOTLOADER ID when updating bootloader +// This helps to prevent incorrect uf2 from other boards. +extern const uint32_t bootloaderConfig[]; + //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ @@ -406,6 +411,37 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state) } 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); diff --git a/src/usb/uf2/uf2.h b/src/usb/uf2/uf2.h index d4f92e7..081280c 100644 --- a/src/usb/uf2/uf2.h +++ b/src/usb/uf2/uf2.h @@ -56,6 +56,7 @@ typedef struct { 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; From e6de13f67940df0cba6b796ff47fa37597a5ce62 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 12 May 2020 20:43:12 +0700 Subject: [PATCH 54/61] clean up --- src/boards/feather_nrf52840_express/pinconfig.c | 12 +++--------- src/usb/uf2/ghostfat.c | 4 ---- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/src/boards/feather_nrf52840_express/pinconfig.c b/src/boards/feather_nrf52840_express/pinconfig.c index 4337212..a983e4a 100644 --- a/src/boards/feather_nrf52840_express/pinconfig.c +++ b/src/boards/feather_nrf52840_express/pinconfig.c @@ -6,20 +6,14 @@ const uint32_t bootloaderConfig[] = { /* CF2 START */ CFG_MAGIC0, CFG_MAGIC1, // magic - 32, 100, // used entries, total entries - -#ifdef LED_NEOPIXEL - 20, LED_NEOPIXEL, // PIN_NEOPIXEL - 200, NEOPIXELS_NUMBER, // NUM_NEOPIXELS -#endif + 5, 100, // used entries, total entries 204, 0x100000, // FLASH_BYTES = 0x100000 205, 0x40000, // RAM_BYTES = 0x40000 - CFG_BOOTLOADER_BOARD_ID, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, + 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, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 /* CF2 END */ }; diff --git a/src/usb/uf2/ghostfat.c b/src/usb/uf2/ghostfat.c index 0127c34..273bc53 100644 --- a/src/usb/uf2/ghostfat.c +++ b/src/usb/uf2/ghostfat.c @@ -174,10 +174,6 @@ static inline bool in_uicr_space(uint32_t addr) return addr == 0x10001000; } -//static inline get_new_bootloader_base(uint32_t ) - -static inline uint32_t max32 (uint32_t x, uint32_t y) { return (x > y) ? x : y; } - //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ From cf1ccfecad4c1973e07d326a8852cae3763ba400 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 12 May 2020 20:52:21 +0700 Subject: [PATCH 55/61] all boards are now required pinconfig for storing bootloader ID in cf2 format --- src/boards/aramcon_badge_2019/pinconfig.c | 19 +++++++++++++++++++ src/boards/arduino_nano_33_ble/pinconfig.c | 19 +++++++++++++++++++ .../circuitplayground_nrf52840/pinconfig.c | 19 +++++++++++++++++++ src/boards/clue_nrf52840/pinconfig.c | 19 +++++++++++++++++++ src/boards/electronut_labs_papyr/pinconfig.c | 19 +++++++++++++++++++ src/boards/feather_nrf52840_sense/pinconfig.c | 19 +++++++++++++++++++ .../itsybitsy_nrf52840_express/pinconfig.c | 19 +++++++++++++++++++ src/boards/mdk_nrf52840_dongle/pinconfig.c | 19 +++++++++++++++++++ src/boards/metro_nrf52840_express/pinconfig.c | 19 +++++++++++++++++++ src/boards/ohs2020_badge/pinconfig.c | 19 +++++++++++++++++++ src/boards/particle_argon/pinconfig.c | 19 +++++++++++++++++++ src/boards/particle_boron/pinconfig.c | 19 +++++++++++++++++++ src/boards/particle_xenon/pinconfig.c | 19 +++++++++++++++++++ src/boards/pca10056/pinconfig.c | 19 +++++++++++++++++++ src/boards/pca10059/pinconfig.c | 19 +++++++++++++++++++ src/boards/pca10100/pinconfig.c | 19 +++++++++++++++++++ src/boards/raytac_mdbt50q_rx/pinconfig.c | 19 +++++++++++++++++++ .../waveshare_nrf52840_eval/pinconfig.c | 19 +++++++++++++++++++ 18 files changed, 342 insertions(+) create mode 100644 src/boards/aramcon_badge_2019/pinconfig.c create mode 100644 src/boards/arduino_nano_33_ble/pinconfig.c create mode 100644 src/boards/circuitplayground_nrf52840/pinconfig.c create mode 100644 src/boards/clue_nrf52840/pinconfig.c create mode 100644 src/boards/electronut_labs_papyr/pinconfig.c create mode 100644 src/boards/feather_nrf52840_sense/pinconfig.c create mode 100644 src/boards/itsybitsy_nrf52840_express/pinconfig.c create mode 100644 src/boards/mdk_nrf52840_dongle/pinconfig.c create mode 100644 src/boards/metro_nrf52840_express/pinconfig.c create mode 100644 src/boards/ohs2020_badge/pinconfig.c create mode 100644 src/boards/particle_argon/pinconfig.c create mode 100644 src/boards/particle_boron/pinconfig.c create mode 100644 src/boards/particle_xenon/pinconfig.c create mode 100644 src/boards/pca10056/pinconfig.c create mode 100644 src/boards/pca10059/pinconfig.c create mode 100644 src/boards/pca10100/pinconfig.c create mode 100644 src/boards/raytac_mdbt50q_rx/pinconfig.c create mode 100644 src/boards/waveshare_nrf52840_eval/pinconfig.c 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/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_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/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/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/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/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/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/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/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/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 */ +}; From 316891dbd5ceebd9ac4a2dffb65e83b1dd98fb17 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 12 May 2020 23:21:58 +0700 Subject: [PATCH 56/61] everything seems good --- Makefile | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 195aea9..050573d 100644 --- a/Makefile +++ b/Makefile @@ -254,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)))) diff --git a/README.md b/README.md index 9ab1e58..546466a 100644 --- a/README.md +++ b/README.md @@ -50,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. From 62336dc7662792b346236ce8ce160fe274d99eb0 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 13 May 2020 00:00:28 +0700 Subject: [PATCH 57/61] add uf2 conv for bootloader --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 546466a..0a86a9d 100644 --- a/README.md +++ b/README.md @@ -79,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 From 148723984c1075cdae3d7e173f5c475682cd3769 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 13 May 2020 00:59:27 +0700 Subject: [PATCH 58/61] revert VID/PID for pca10056/pca10059 use feather nrf52840 as it previously does. --- src/boards/pca10056/board.h | 8 +++++--- src/boards/pca10059/board.h | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/boards/pca10056/board.h b/src/boards/pca10056/board.h index 0682f88..92ce346 100644 --- a/src/boards/pca10056/board.h +++ b/src/boards/pca10056/board.h @@ -50,9 +50,11 @@ //--------------------------------------------------------------------+ // USB //--------------------------------------------------------------------+ -#define USB_DESC_VID 0x1915 -#define USB_DESC_UF2_PID 0x521F -#define USB_DESC_CDC_ONLY_PID 0x521F + +// 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" diff --git a/src/boards/pca10059/board.h b/src/boards/pca10059/board.h index 4ca7b1a..8b2d89d 100644 --- a/src/boards/pca10059/board.h +++ b/src/boards/pca10059/board.h @@ -53,9 +53,11 @@ //--------------------------------------------------------------------+ // USB //--------------------------------------------------------------------+ -#define USB_DESC_VID 0x1915 -#define USB_DESC_UF2_PID 0x521F -#define USB_DESC_CDC_ONLY_PID 0x521F + +// 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" From 26e02484f354c5066676b4c5c15eea1877952465 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 13 May 2020 13:22:34 +0700 Subject: [PATCH 59/61] remove submodule intelhex, use copied hexmerge.py instead --- .gitmodules | 4 +- Makefile | 4 +- lib/intelhex | 1 - tools/hexmerge.py | 178 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 181 insertions(+), 6 deletions(-) delete mode 160000 lib/intelhex create mode 100755 tools/hexmerge.py diff --git a/.gitmodules b/.gitmodules index 71fbabc..bd80adc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,6 +7,4 @@ [submodule "lib/uf2"] path = lib/uf2 url = https://github.com/microsoft/uf2.git -[submodule "lib/intelhex"] - path = lib/intelhex - url = https://github.com/python-intelhex/intelhex.git + diff --git a/Makefile b/Makefile index 050573d..a0faf4a 100644 --- a/Makefile +++ b/Makefile @@ -350,7 +350,7 @@ $(BUILD)/$(OUT_FILE).hex: $(BUILD)/$(OUT_FILE).out # Hex file with mbr (still no SD) $(BUILD)/$(OUT_FILE)-nosd.hex: $(BUILD)/$(OUT_FILE).hex @echo CR $(notdir $@) - @python lib/intelhex/scripts/hexmerge.py --overlap=replace -o $@ $< $(MBR_HEX) + @python tools/hexmerge.py --overlap=replace -o $@ $< $(MBR_HEX) # Bootolader only uf2 $(BUILD)/$(OUT_FILE)-nosd.uf2: $(BUILD)/$(OUT_FILE)-nosd.hex @@ -360,7 +360,7 @@ $(BUILD)/$(OUT_FILE)-nosd.uf2: $(BUILD)/$(OUT_FILE)-nosd.hex # merge bootloader and sd hex together $(BUILD)/$(MERGED_FILE).hex: $(BUILD)/$(OUT_FILE).hex @echo CR $(notdir $@) - @python lib/intelhex/scripts/hexmerge.py -o $@ $< $(SD_HEX) + @python tools/hexmerge.py -o $@ $< $(SD_HEX) # Create pkg zip file for bootloader+SD combo to use with DFU CDC $(BUILD)/$(MERGED_FILE).zip: $(BUILD)/$(OUT_FILE).hex diff --git a/lib/intelhex b/lib/intelhex deleted file mode 160000 index 5c15003..0000000 --- a/lib/intelhex +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5c15003d08bf53512d5eaa54c7d2825a8b5c37cc 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()) From a4084e0f462290df45a05eda1beac5dba48ab929 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 13 May 2020 14:11:47 +0700 Subject: [PATCH 60/61] add SD detection to INFO.txt --- linker/nrf52.ld | 2 +- linker/nrf52833.ld | 2 +- linker/nrf52840.ld | 2 +- src/usb/uf2/ghostfat.c | 43 ++++++++++++++++++++++++++++-------------- 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/linker/nrf52.ld b/linker/nrf52.ld index db8d06b..756e490 100644 --- a/linker/nrf52.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.ld b/linker/nrf52833.ld index d665d8a..46a23dc 100644 --- a/linker/nrf52833.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.ld b/linker/nrf52840.ld index 3358c98..fcfa425 100644 --- a/linker/nrf52840.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/src/usb/uf2/ghostfat.c b/src/usb/uf2/ghostfat.c index 273bc53..b2c4db6 100644 --- a/src/usb/uf2/ghostfat.c +++ b/src/usb/uf2/ghostfat.c @@ -4,6 +4,7 @@ #include "configkeys.h" #include "flash_nrf5x.h" #include +#include #include "bootloader_settings.h" #include "bootloader.h" @@ -67,13 +68,12 @@ struct TextFile { #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" "" "" @@ -83,17 +83,17 @@ 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); @@ -180,7 +180,24 @@ static inline bool in_uicr_space(uint32_t addr) void uf2_init(void) { - // nothing to do + 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"); } /*------------------------------------------------------------------*/ @@ -258,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 { From 2df81e65431fe7289b77f46d6b455f80ef33b8f0 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 13 May 2020 22:34:05 +0700 Subject: [PATCH 61/61] use python3 for hex merge --- Makefile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index a0faf4a..627e3ae 100644 --- a/Makefile +++ b/Makefile @@ -344,23 +344,23 @@ $(BUILD)/$(OUT_FILE).out: $(BUILD) $(OBJECTS) # Create hex file (no sd, no mbr) $(BUILD)/$(OUT_FILE).hex: $(BUILD)/$(OUT_FILE).out - @echo CR $(notdir $@) + @echo Create $(notdir $@) @$(OBJCOPY) -O ihex $< $@ # Hex file with mbr (still no SD) $(BUILD)/$(OUT_FILE)-nosd.hex: $(BUILD)/$(OUT_FILE).hex - @echo CR $(notdir $@) - @python tools/hexmerge.py --overlap=replace -o $@ $< $(MBR_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 CR $(notdir $@) - python lib/uf2/utils/uf2conv.py -f 0xd663823c -c -o $@ $^ + @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).hex - @echo CR $(notdir $@) - @python tools/hexmerge.py -o $@ $< $(SD_HEX) + @echo Create $(notdir $@) + @python3 tools/hexmerge.py -o $@ $< $(SD_HEX) # Create pkg zip file for bootloader+SD combo to use with DFU CDC $(BUILD)/$(MERGED_FILE).zip: $(BUILD)/$(OUT_FILE).hex