simmel: remove dfu and ota bootloaders
We don't want this device to be updatable over the air, and we don't need the serial DFU bootloader. This leaves only UF2. Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
parent
30c2c0e7c8
commit
91cd582dea
25
Makefile
25
Makefile
@ -105,11 +105,11 @@ C_SRC += $(NRFX_PATH)/mdk/system_$(MCU_SUB_VARIANT).c
|
|||||||
C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/bootloader.c
|
C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/bootloader.c
|
||||||
C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/bootloader_settings.c
|
C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/bootloader_settings.c
|
||||||
C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/bootloader_util.c
|
C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/bootloader_util.c
|
||||||
C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/dfu_transport_serial.c
|
# C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/dfu_transport_serial.c
|
||||||
C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/dfu_transport_ble.c
|
# C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/dfu_transport_ble.c
|
||||||
C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/dfu_single_bank.c
|
# C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/dfu_single_bank.c
|
||||||
C_SRC += $(SDK11_PATH)/ble/ble_services/ble_dfu/ble_dfu.c
|
# C_SRC += $(SDK11_PATH)/ble/ble_services/ble_dfu/ble_dfu.c
|
||||||
C_SRC += $(SDK11_PATH)/ble/ble_services/ble_dis/ble_dis.c
|
# C_SRC += $(SDK11_PATH)/ble/ble_services/ble_dis/ble_dis.c
|
||||||
C_SRC += $(SDK11_PATH)/drivers_nrf/pstorage/pstorage_raw.c
|
C_SRC += $(SDK11_PATH)/drivers_nrf/pstorage/pstorage_raw.c
|
||||||
|
|
||||||
# Latest SDK files: peripheral drivers
|
# Latest SDK files: peripheral drivers
|
||||||
@ -118,17 +118,17 @@ C_SRC += $(SDK_PATH)/libraries/scheduler/app_scheduler.c
|
|||||||
C_SRC += $(SDK_PATH)/libraries/util/app_error.c
|
C_SRC += $(SDK_PATH)/libraries/util/app_error.c
|
||||||
C_SRC += $(SDK_PATH)/libraries/util/app_util_platform.c
|
C_SRC += $(SDK_PATH)/libraries/util/app_util_platform.c
|
||||||
C_SRC += $(SDK_PATH)/libraries/crc16/crc16.c
|
C_SRC += $(SDK_PATH)/libraries/crc16/crc16.c
|
||||||
C_SRC += $(SDK_PATH)/libraries/hci/hci_mem_pool.c
|
# C_SRC += $(SDK_PATH)/libraries/hci/hci_mem_pool.c
|
||||||
C_SRC += $(SDK_PATH)/libraries/hci/hci_slip.c
|
# C_SRC += $(SDK_PATH)/libraries/hci/hci_slip.c
|
||||||
C_SRC += $(SDK_PATH)/libraries/hci/hci_transport.c
|
# C_SRC += $(SDK_PATH)/libraries/hci/hci_transport.c
|
||||||
C_SRC += $(SDK_PATH)/libraries/util/nrf_assert.c
|
C_SRC += $(SDK_PATH)/libraries/util/nrf_assert.c
|
||||||
|
|
||||||
# UART or USB Serial
|
# UART or USB Serial
|
||||||
ifeq ($(MCU_SUB_VARIANT),nrf52)
|
ifeq ($(MCU_SUB_VARIANT),nrf52)
|
||||||
|
|
||||||
C_SRC += $(SDK_PATH)/libraries/uart/app_uart.c
|
# C_SRC += $(SDK_PATH)/libraries/uart/app_uart.c
|
||||||
C_SRC += $(SDK_PATH)/drivers_nrf/uart/nrf_drv_uart.c
|
# C_SRC += $(SDK_PATH)/drivers_nrf/uart/nrf_drv_uart.c
|
||||||
C_SRC += $(SDK_PATH)/drivers_nrf/common/nrf_drv_common.c
|
# C_SRC += $(SDK_PATH)/drivers_nrf/common/nrf_drv_common.c
|
||||||
|
|
||||||
IPATH += $(SDK11_PATH)/libraries/util
|
IPATH += $(SDK11_PATH)/libraries/util
|
||||||
IPATH += $(SDK_PATH)/drivers_nrf/common
|
IPATH += $(SDK_PATH)/drivers_nrf/common
|
||||||
@ -212,6 +212,7 @@ endif
|
|||||||
#flags common to all targets
|
#flags common to all targets
|
||||||
CFLAGS += \
|
CFLAGS += \
|
||||||
-mthumb \
|
-mthumb \
|
||||||
|
-flto \
|
||||||
-mabi=aapcs \
|
-mabi=aapcs \
|
||||||
-mcpu=cortex-m4 \
|
-mcpu=cortex-m4 \
|
||||||
-mfloat-abi=hard \
|
-mfloat-abi=hard \
|
||||||
@ -372,7 +373,7 @@ $(BUILD)/$(OUT_FILE)-nosd.hex: $(BUILD)/$(OUT_FILE)-nosd.out
|
|||||||
# merge bootloader and sd hex together
|
# merge bootloader and sd hex together
|
||||||
$(BUILD)/$(MERGED_FILE).hex: $(BUILD)/$(OUT_FILE)-nosd.hex
|
$(BUILD)/$(MERGED_FILE).hex: $(BUILD)/$(OUT_FILE)-nosd.hex
|
||||||
@echo CR $(MERGED_FILE).hex
|
@echo CR $(MERGED_FILE).hex
|
||||||
@mergehex -q -m $< $(SD_HEX) -o $@
|
@mergehex.exe -q -m $< $(SD_HEX) -o $@
|
||||||
|
|
||||||
## Create pkg zip file for bootloader+SD combo to use with DFU Serial
|
## Create pkg zip file for bootloader+SD combo to use with DFU Serial
|
||||||
.PHONY: genpkg
|
.PHONY: genpkg
|
||||||
|
@ -183,21 +183,10 @@ bool bootloader_app_is_valid(uint32_t app_addr)
|
|||||||
|
|
||||||
static void bootloader_settings_save(bootloader_settings_t * p_settings)
|
static void bootloader_settings_save(bootloader_settings_t * p_settings)
|
||||||
{
|
{
|
||||||
if ( is_ota() )
|
nrfx_nvmc_page_erase(BOOTLOADER_SETTINGS_ADDRESS);
|
||||||
{
|
nrfx_nvmc_words_write(BOOTLOADER_SETTINGS_ADDRESS, (uint32_t *) p_settings, sizeof(bootloader_settings_t) / 4);
|
||||||
uint32_t err_code = pstorage_clear(&m_bootsettings_handle, sizeof(bootloader_settings_t));
|
|
||||||
APP_ERROR_CHECK(err_code);
|
|
||||||
|
|
||||||
err_code = pstorage_store(&m_bootsettings_handle, (uint8_t *) p_settings, sizeof(bootloader_settings_t), 0);
|
pstorage_callback_handler(&m_bootsettings_handle, PSTORAGE_STORE_OP_CODE, NRF_SUCCESS, (uint8_t *) p_settings, sizeof(bootloader_settings_t));
|
||||||
APP_ERROR_CHECK(err_code);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nrfx_nvmc_page_erase(BOOTLOADER_SETTINGS_ADDRESS);
|
|
||||||
nrfx_nvmc_words_write(BOOTLOADER_SETTINGS_ADDRESS, (uint32_t *) p_settings, sizeof(bootloader_settings_t) / 4);
|
|
||||||
|
|
||||||
pstorage_callback_handler(&m_bootsettings_handle, PSTORAGE_STORE_OP_CODE, NRF_SUCCESS, (uint8_t *) p_settings, sizeof(bootloader_settings_t));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -218,22 +207,22 @@ void bootloader_dfu_update_process(dfu_update_status_t update_status)
|
|||||||
m_update_status = BOOTLOADER_SETTINGS_SAVING;
|
m_update_status = BOOTLOADER_SETTINGS_SAVING;
|
||||||
bootloader_settings_save(&settings);
|
bootloader_settings_save(&settings);
|
||||||
}
|
}
|
||||||
else if (update_status.status_code == DFU_UPDATE_SD_COMPLETE)
|
// else if (update_status.status_code == DFU_UPDATE_SD_COMPLETE)
|
||||||
{
|
// {
|
||||||
settings.bank_0_crc = update_status.app_crc;
|
// settings.bank_0_crc = update_status.app_crc;
|
||||||
settings.bank_0_size = update_status.sd_size +
|
// settings.bank_0_size = update_status.sd_size +
|
||||||
update_status.bl_size +
|
// update_status.bl_size +
|
||||||
update_status.app_size;
|
// update_status.app_size;
|
||||||
settings.bank_0 = BANK_VALID_SD;
|
// settings.bank_0 = BANK_VALID_SD;
|
||||||
settings.bank_1 = BANK_INVALID_APP;
|
// settings.bank_1 = BANK_INVALID_APP;
|
||||||
settings.sd_image_size = update_status.sd_size;
|
// settings.sd_image_size = update_status.sd_size;
|
||||||
settings.bl_image_size = update_status.bl_size;
|
// settings.bl_image_size = update_status.bl_size;
|
||||||
settings.app_image_size = update_status.app_size;
|
// settings.app_image_size = update_status.app_size;
|
||||||
settings.sd_image_start = update_status.sd_image_start;
|
// settings.sd_image_start = update_status.sd_image_start;
|
||||||
|
|
||||||
m_update_status = BOOTLOADER_SETTINGS_SAVING;
|
// m_update_status = BOOTLOADER_SETTINGS_SAVING;
|
||||||
bootloader_settings_save(&settings);
|
// bootloader_settings_save(&settings);
|
||||||
}
|
// }
|
||||||
else if (update_status.status_code == DFU_UPDATE_BOOT_COMPLETE)
|
else if (update_status.status_code == DFU_UPDATE_BOOT_COMPLETE)
|
||||||
{
|
{
|
||||||
settings.bank_0 = p_bootloader_settings->bank_0;
|
settings.bank_0 = p_bootloader_settings->bank_0;
|
||||||
@ -247,54 +236,54 @@ void bootloader_dfu_update_process(dfu_update_status_t update_status)
|
|||||||
m_update_status = BOOTLOADER_SETTINGS_SAVING;
|
m_update_status = BOOTLOADER_SETTINGS_SAVING;
|
||||||
bootloader_settings_save(&settings);
|
bootloader_settings_save(&settings);
|
||||||
}
|
}
|
||||||
else if (update_status.status_code == DFU_UPDATE_SD_SWAPPED)
|
// else if (update_status.status_code == DFU_UPDATE_SD_SWAPPED)
|
||||||
{
|
// {
|
||||||
if (p_bootloader_settings->bank_0 == BANK_VALID_SD)
|
// if (p_bootloader_settings->bank_0 == BANK_VALID_SD)
|
||||||
{
|
// {
|
||||||
settings.bank_0_crc = 0;
|
// settings.bank_0_crc = 0;
|
||||||
settings.bank_0_size = 0;
|
// settings.bank_0_size = 0;
|
||||||
settings.bank_0 = BANK_INVALID_APP;
|
// settings.bank_0 = BANK_INVALID_APP;
|
||||||
}
|
// }
|
||||||
// This handles cases where SoftDevice was not updated, hence bank0 keeps its settings.
|
// // This handles cases where SoftDevice was not updated, hence bank0 keeps its settings.
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
settings.bank_0 = p_bootloader_settings->bank_0;
|
// settings.bank_0 = p_bootloader_settings->bank_0;
|
||||||
settings.bank_0_crc = p_bootloader_settings->bank_0_crc;
|
// settings.bank_0_crc = p_bootloader_settings->bank_0_crc;
|
||||||
settings.bank_0_size = p_bootloader_settings->bank_0_size;
|
// settings.bank_0_size = p_bootloader_settings->bank_0_size;
|
||||||
}
|
// }
|
||||||
|
|
||||||
settings.bank_1 = BANK_INVALID_APP;
|
// settings.bank_1 = BANK_INVALID_APP;
|
||||||
settings.sd_image_size = 0;
|
// settings.sd_image_size = 0;
|
||||||
settings.bl_image_size = 0;
|
// settings.bl_image_size = 0;
|
||||||
settings.app_image_size = 0;
|
// settings.app_image_size = 0;
|
||||||
|
|
||||||
m_update_status = BOOTLOADER_SETTINGS_SAVING;
|
// m_update_status = BOOTLOADER_SETTINGS_SAVING;
|
||||||
bootloader_settings_save(&settings);
|
// bootloader_settings_save(&settings);
|
||||||
}
|
// }
|
||||||
else if (update_status.status_code == DFU_TIMEOUT)
|
else if (update_status.status_code == DFU_TIMEOUT)
|
||||||
{
|
{
|
||||||
// Timeout has occurred. Close the connection with the DFU Controller.
|
// // Timeout has occurred. Close the connection with the DFU Controller.
|
||||||
uint32_t err_code;
|
// uint32_t err_code;
|
||||||
if ( is_ota() )
|
// // if ( is_ota() )
|
||||||
{
|
// // {
|
||||||
err_code = dfu_transport_ble_close();
|
// // err_code = dfu_transport_ble_close();
|
||||||
}else
|
// // }else
|
||||||
{
|
// // {
|
||||||
err_code = dfu_transport_serial_close();
|
// err_code = dfu_transport_serial_close();
|
||||||
}
|
// // }
|
||||||
APP_ERROR_CHECK(err_code);
|
// APP_ERROR_CHECK(err_code);
|
||||||
|
|
||||||
m_update_status = BOOTLOADER_TIMEOUT;
|
m_update_status = BOOTLOADER_TIMEOUT;
|
||||||
}
|
}
|
||||||
else if (update_status.status_code == DFU_BANK_0_ERASED)
|
// else if (update_status.status_code == DFU_BANK_0_ERASED)
|
||||||
{
|
// {
|
||||||
settings.bank_0_crc = 0;
|
// settings.bank_0_crc = 0;
|
||||||
settings.bank_0_size = 0;
|
// settings.bank_0_size = 0;
|
||||||
settings.bank_0 = BANK_INVALID_APP;
|
// settings.bank_0 = BANK_INVALID_APP;
|
||||||
settings.bank_1 = p_bootloader_settings->bank_1;
|
// settings.bank_1 = p_bootloader_settings->bank_1;
|
||||||
|
|
||||||
bootloader_settings_save(&settings);
|
// bootloader_settings_save(&settings);
|
||||||
}
|
// }
|
||||||
else if (update_status.status_code == DFU_RESET)
|
else if (update_status.status_code == DFU_RESET)
|
||||||
{
|
{
|
||||||
m_update_status = BOOTLOADER_RESET;
|
m_update_status = BOOTLOADER_RESET;
|
||||||
@ -321,13 +310,13 @@ uint32_t bootloader_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t bootloader_dfu_start(uint32_t timeout_ms)
|
void bootloader_run(uint32_t timeout_ms)
|
||||||
{
|
{
|
||||||
uint32_t err_code;
|
// uint32_t err_code;
|
||||||
|
|
||||||
// Clear swap if banked update is used.
|
// // Clear swap if banked update is used.
|
||||||
err_code = dfu_init();
|
// err_code = dfu_init();
|
||||||
VERIFY_SUCCESS(err_code);
|
// VERIFY_SUCCESS(err_code);
|
||||||
|
|
||||||
// timeout_ms > 0 is forced startup DFU
|
// timeout_ms > 0 is forced startup DFU
|
||||||
if ( timeout_ms )
|
if ( timeout_ms )
|
||||||
@ -338,11 +327,11 @@ uint32_t bootloader_dfu_start(uint32_t timeout_ms)
|
|||||||
app_timer_start(_dfu_startup_timer, APP_TIMER_TICKS(timeout_ms), NULL);
|
app_timer_start(_dfu_startup_timer, APP_TIMER_TICKS(timeout_ms), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
err_code = dfu_transport_serial_update_start();
|
// err_code = dfu_transport_serial_update_start();
|
||||||
|
|
||||||
wait_for_events();
|
wait_for_events();
|
||||||
|
|
||||||
return err_code;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -434,17 +423,17 @@ uint32_t bootloader_dfu_sd_update_continue(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t bootloader_dfu_sd_update_finalize(void)
|
// uint32_t bootloader_dfu_sd_update_finalize(void)
|
||||||
{
|
// {
|
||||||
dfu_update_status_t update_status = { 0 };
|
// dfu_update_status_t update_status = { 0 };
|
||||||
update_status.status_code = DFU_UPDATE_SD_SWAPPED;
|
// update_status.status_code = DFU_UPDATE_SD_SWAPPED;
|
||||||
|
|
||||||
bootloader_dfu_update_process(update_status);
|
// bootloader_dfu_update_process(update_status);
|
||||||
|
|
||||||
wait_for_events();
|
// wait_for_events();
|
||||||
|
|
||||||
return NRF_SUCCESS;
|
// return NRF_SUCCESS;
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
void bootloader_settings_get(bootloader_settings_t * const p_settings)
|
void bootloader_settings_get(bootloader_settings_t * const p_settings)
|
||||||
|
@ -47,6 +47,8 @@ bool bootloader_app_is_valid(uint32_t app_addr);
|
|||||||
*/
|
*/
|
||||||
uint32_t bootloader_dfu_start(uint32_t timeout_ms);
|
uint32_t bootloader_dfu_start(uint32_t timeout_ms);
|
||||||
|
|
||||||
|
void bootloader_run(uint32_t timeout_ms);
|
||||||
|
|
||||||
/**@brief Function for exiting bootloader and booting into application.
|
/**@brief Function for exiting bootloader and booting into application.
|
||||||
*
|
*
|
||||||
* @details This function will disable SoftDevice and all interrupts before jumping to application.
|
* @details This function will disable SoftDevice and all interrupts before jumping to application.
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
// Flash = 512 KB
|
// Flash = 512 KB
|
||||||
#if defined(NRF52832_XXAA) || defined(NRF52833_XXAA)
|
#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_REGION_START 0x0007A000 /**< 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_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_MBR_PARAMS_PAGE_ADDRESS 0x0007E000 /**< The field specifies the page location of the mbr params page address. */
|
||||||
|
|
||||||
|
@ -5,13 +5,14 @@ GROUP(-lgcc -lc -lnosys)
|
|||||||
|
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
/** Flash start address for the bootloader. This setting will also be stored in UICR to allow the
|
/** Flash start address for the bootloader. This setting will also be stored
|
||||||
* MBR to init the bootloader when starting the system. This value must correspond to
|
in UICR to allow the MBR to init the bootloader when starting the system. This
|
||||||
* BOOTLOADER_REGION_START found in dfu_types.h. The system is prevented from starting up if
|
value must correspond to BOOTLOADER_REGION_START found in dfu_types.h. The
|
||||||
* those values do not match. The check is performed in main.c, see
|
system is prevented from starting up if those values do not match. The check
|
||||||
* APP_ERROR_CHECK_BOOL(*((uint32_t *)NRF_UICR_BOOT_START_ADDRESS) == BOOTLOADER_REGION_START);
|
is performed in main.c, see APP_ERROR_CHECK_BOOL(*((uint32_t
|
||||||
*/
|
*)NRF_UICR_BOOT_START_ADDRESS) == BOOTLOADER_REGION_START); */
|
||||||
FLASH (rx) : ORIGIN = 0x74000, LENGTH = 0x7E000-0x74000 /* 40 KB */
|
|
||||||
|
FLASH (rx) : ORIGIN = 0x7a000, LENGTH = 0x7E000-0x7a000 /* 40 KB */
|
||||||
|
|
||||||
/** Location of mbr params page in flash. */
|
/** Location of mbr params page in flash. */
|
||||||
MBR_PARAMS_PAGE (rw) : ORIGIN = 0x0007E000, LENGTH = 0x1000
|
MBR_PARAMS_PAGE (rw) : ORIGIN = 0x0007E000, LENGTH = 0x1000
|
||||||
@ -19,8 +20,6 @@ MEMORY
|
|||||||
/** Location of bootloader setting in flash. */
|
/** Location of bootloader setting in flash. */
|
||||||
BOOTLOADER_SETTINGS (rw) : ORIGIN = 0x0007F000, LENGTH = 0x1000
|
BOOTLOADER_SETTINGS (rw) : ORIGIN = 0x0007F000, LENGTH = 0x1000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** RAM Region for bootloader. */
|
/** RAM Region for bootloader. */
|
||||||
/* Avoid conflict with NOINIT for OTA bond sharing */
|
/* Avoid conflict with NOINIT for OTA bond sharing */
|
||||||
RAM (rwx) : ORIGIN = 0x20008000, LENGTH = 0x20020000-0x20008000
|
RAM (rwx) : ORIGIN = 0x20008000, LENGTH = 0x20020000-0x20008000
|
||||||
@ -28,11 +27,9 @@ MEMORY
|
|||||||
/* Location for double reset detection, no init */
|
/* Location for double reset detection, no init */
|
||||||
DBL_RESET (rwx) : ORIGIN = 0x20007F7C, LENGTH = 0x04
|
DBL_RESET (rwx) : ORIGIN = 0x20007F7C, LENGTH = 0x04
|
||||||
|
|
||||||
/** Location of non initialized RAM. Non initialized RAM is used for exchanging bond information
|
/** Location of non initialized RAM. Non initialized RAM is used for
|
||||||
* from application to bootloader when using buttonluss DFU OTA. */
|
exchanging bond information * from application to bootloader when using
|
||||||
NOINIT (rwx) : ORIGIN = 0x20007F80, LENGTH = 0x80
|
buttonless DFU OTA. */ NOINIT (rwx) : ORIGIN = 0x20007F80, LENGTH = 0x80
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Location in UICR where bootloader start address is stored. */
|
/** Location in UICR where bootloader start address is stored. */
|
||||||
UICR_BOOTLOADER (r) : ORIGIN = 0x10001014, LENGTH = 0x04
|
UICR_BOOTLOADER (r) : ORIGIN = 0x10001014, LENGTH = 0x04
|
||||||
|
235
src/boards.c
235
src/boards.c
@ -33,34 +33,7 @@
|
|||||||
#define SCHED_MAX_EVENT_DATA_SIZE sizeof(app_timer_event_t) /**< Maximum size of scheduler events. */
|
#define SCHED_MAX_EVENT_DATA_SIZE sizeof(app_timer_event_t) /**< Maximum size of scheduler events. */
|
||||||
#define SCHED_QUEUE_SIZE 30 /**< Maximum number of events in the scheduler queue. */
|
#define SCHED_QUEUE_SIZE 30 /**< Maximum number of events in the scheduler queue. */
|
||||||
|
|
||||||
#if defined(LED_NEOPIXEL) || defined(LED_RGB_RED_PIN)
|
|
||||||
void neopixel_init(void);
|
|
||||||
void neopixel_write(uint8_t *pixels);
|
|
||||||
void neopixel_teardown(void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//------------- IMPLEMENTATION -------------//
|
//------------- IMPLEMENTATION -------------//
|
||||||
#if BUTTONS_NUMBER >= 2
|
|
||||||
void button_init(uint32_t pin)
|
|
||||||
{
|
|
||||||
if ( BUTTON_PULL == NRF_GPIO_PIN_PULLDOWN )
|
|
||||||
{
|
|
||||||
nrf_gpio_cfg_sense_input(pin, BUTTON_PULL, NRF_GPIO_PIN_SENSE_HIGH);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nrf_gpio_cfg_sense_input(pin, BUTTON_PULL, NRF_GPIO_PIN_SENSE_LOW);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if BUTTONS_NUMBER >= 2
|
|
||||||
bool button_pressed(uint32_t pin)
|
|
||||||
{
|
|
||||||
uint32_t const active_state = (BUTTON_PULL == NRF_GPIO_PIN_PULLDOWN ? 1 : 0);
|
|
||||||
return nrf_gpio_pin_read(pin) == active_state;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void board_init(void)
|
void board_init(void)
|
||||||
{
|
{
|
||||||
@ -71,23 +44,12 @@ void board_init(void)
|
|||||||
NRF_CLOCK->LFCLKSRC = CLOCK_LFCLKSRC_SRC_RC;
|
NRF_CLOCK->LFCLKSRC = CLOCK_LFCLKSRC_SRC_RC;
|
||||||
NRF_CLOCK->TASKS_LFCLKSTART = 1UL;
|
NRF_CLOCK->TASKS_LFCLKSTART = 1UL;
|
||||||
|
|
||||||
#if BUTTONS_NUMBER >= 2
|
|
||||||
button_init(BUTTON_DFU);
|
|
||||||
button_init(BUTTON_FRESET);
|
|
||||||
NRFX_DELAY_US(100); // wait for the pin state is stable
|
|
||||||
#endif // BUTTONS >= 2
|
|
||||||
|
|
||||||
// use PMW0 for LED RED
|
// use PMW0 for LED RED
|
||||||
led_pwm_init(LED_PRIMARY, LED_PRIMARY_PIN);
|
led_pwm_init(LED_PRIMARY, LED_PRIMARY_PIN);
|
||||||
#if LEDS_NUMBER > 1
|
#if LEDS_NUMBER > 1
|
||||||
led_pwm_init(LED_SECONDARY, LED_SECONDARY_PIN);
|
led_pwm_init(LED_SECONDARY, LED_SECONDARY_PIN);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// use neopixel for use enumeration
|
|
||||||
#if defined(LED_NEOPIXEL) || defined(LED_RGB_RED_PIN)
|
|
||||||
neopixel_init();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Init scheduler
|
// Init scheduler
|
||||||
APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
|
APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
|
||||||
|
|
||||||
@ -107,10 +69,6 @@ void board_teardown(void)
|
|||||||
// Disable and reset PWM for LEDs
|
// Disable and reset PWM for LEDs
|
||||||
led_pwm_teardown();
|
led_pwm_teardown();
|
||||||
|
|
||||||
#if defined(LED_NEOPIXEL) || defined(LED_RGB_RED_PIN)
|
|
||||||
neopixel_teardown();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Stop RTC1 used by app_timer
|
// Stop RTC1 used by app_timer
|
||||||
NVIC_DisableIRQ(RTC1_IRQn);
|
NVIC_DisableIRQ(RTC1_IRQn);
|
||||||
NRF_RTC1->EVTENCLR = RTC_EVTEN_COMPARE0_Msk;
|
NRF_RTC1->EVTENCLR = RTC_EVTEN_COMPARE0_Msk;
|
||||||
@ -209,9 +167,6 @@ void led_pwm_duty_cycle(uint32_t led_index, uint16_t duty_cycle)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t primary_cycle_length;
|
static uint32_t primary_cycle_length;
|
||||||
#ifdef LED_SECONDARY_PIN
|
|
||||||
static uint32_t secondary_cycle_length;
|
|
||||||
#endif
|
|
||||||
void led_tick() {
|
void led_tick() {
|
||||||
uint32_t millis = _systick_count;
|
uint32_t millis = _systick_count;
|
||||||
|
|
||||||
@ -225,41 +180,21 @@ void led_tick() {
|
|||||||
duty_cycle = 0xff - duty_cycle;
|
duty_cycle = 0xff - duty_cycle;
|
||||||
#endif
|
#endif
|
||||||
led_pwm_duty_cycle(LED_PRIMARY, duty_cycle);
|
led_pwm_duty_cycle(LED_PRIMARY, duty_cycle);
|
||||||
|
|
||||||
#ifdef LED_SECONDARY_PIN
|
|
||||||
cycle = millis % secondary_cycle_length;
|
|
||||||
half_cycle = secondary_cycle_length / 2;
|
|
||||||
if (cycle > half_cycle) {
|
|
||||||
cycle = secondary_cycle_length - cycle;
|
|
||||||
}
|
|
||||||
duty_cycle = 0x8f * cycle / half_cycle;
|
|
||||||
#if LED_STATE_ON == 1
|
|
||||||
duty_cycle = 0xff - duty_cycle;
|
|
||||||
#endif
|
|
||||||
led_pwm_duty_cycle(LED_SECONDARY, duty_cycle);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t rgb_color;
|
|
||||||
static bool temp_color_active = false;
|
|
||||||
void led_state(uint32_t state)
|
void led_state(uint32_t state)
|
||||||
{
|
{
|
||||||
uint32_t new_rgb_color = rgb_color;
|
|
||||||
uint32_t temp_color = 0;
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case STATE_USB_MOUNTED:
|
case STATE_USB_MOUNTED:
|
||||||
new_rgb_color = 0x00ff00;
|
|
||||||
primary_cycle_length = 3000;
|
primary_cycle_length = 3000;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STATE_BOOTLOADER_STARTED:
|
case STATE_BOOTLOADER_STARTED:
|
||||||
case STATE_USB_UNMOUNTED:
|
case STATE_USB_UNMOUNTED:
|
||||||
new_rgb_color = 0xff0000;
|
|
||||||
primary_cycle_length = 300;
|
primary_cycle_length = 300;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STATE_WRITING_STARTED:
|
case STATE_WRITING_STARTED:
|
||||||
temp_color = 0xff0000;
|
|
||||||
primary_cycle_length = 100;
|
primary_cycle_length = 100;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -269,184 +204,14 @@ void led_state(uint32_t state)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case STATE_BLE_CONNECTED:
|
case STATE_BLE_CONNECTED:
|
||||||
new_rgb_color = 0x0000ff;
|
|
||||||
#ifdef LED_SECONDARY_PIN
|
|
||||||
secondary_cycle_length = 3000;
|
|
||||||
#else
|
|
||||||
primary_cycle_length = 3000;
|
primary_cycle_length = 3000;
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STATE_BLE_DISCONNECTED:
|
case STATE_BLE_DISCONNECTED:
|
||||||
new_rgb_color = 0xff00ff;
|
|
||||||
#ifdef LED_SECONDARY_PIN
|
|
||||||
secondary_cycle_length = 300;
|
|
||||||
#else
|
|
||||||
primary_cycle_length = 300;
|
primary_cycle_length = 300;
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
uint8_t* final_color = NULL;
|
|
||||||
new_rgb_color &= BOARD_RGB_BRIGHTNESS;
|
|
||||||
if (temp_color != 0){
|
|
||||||
temp_color &= BOARD_RGB_BRIGHTNESS;
|
|
||||||
final_color = (uint8_t*)&temp_color;
|
|
||||||
temp_color_active = true;
|
|
||||||
} else if (new_rgb_color != rgb_color) {
|
|
||||||
final_color = (uint8_t*)&new_rgb_color;
|
|
||||||
rgb_color = new_rgb_color;
|
|
||||||
} else if (temp_color_active) {
|
|
||||||
final_color = (uint8_t*)&rgb_color;
|
|
||||||
}
|
|
||||||
#if defined(LED_NEOPIXEL) || defined(LED_RGB_RED_PIN)
|
|
||||||
if (final_color != NULL) {
|
|
||||||
neopixel_write(final_color);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
(void) final_color;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LED_NEOPIXEL
|
|
||||||
|
|
||||||
// WS2812B (rev B) timing is 0.4 and 0.8 us
|
|
||||||
#define MAGIC_T0H 6UL | (0x8000) // 0.375us
|
|
||||||
#define MAGIC_T1H 13UL | (0x8000) // 0.8125us
|
|
||||||
#define CTOPVAL 20UL // 1.25us
|
|
||||||
|
|
||||||
#define BYTE_PER_PIXEL 3
|
|
||||||
|
|
||||||
static uint16_t pixels_pattern[NEOPIXELS_NUMBER*BYTE_PER_PIXEL * 8 + 2];
|
|
||||||
|
|
||||||
// use PWM1 for neopixel
|
|
||||||
void neopixel_init(void)
|
|
||||||
{
|
|
||||||
// To support both the SoftDevice + Neopixels we use the EasyDMA
|
|
||||||
// feature from the NRF25. However this technique implies to
|
|
||||||
// generate a pattern and store it on the memory. The actual
|
|
||||||
// memory used in bytes corresponds to the following formula:
|
|
||||||
// totalMem = numBytes*8*2+(2*2)
|
|
||||||
// The two additional bytes at the end are needed to reset the
|
|
||||||
// sequence.
|
|
||||||
NRF_PWM_Type* pwm = NRF_PWM1;
|
|
||||||
|
|
||||||
// Set the wave mode to count UP
|
|
||||||
// Set the PWM to use the 16MHz clock
|
|
||||||
// Setting of the maximum count
|
|
||||||
// but keeping it on 16Mhz allows for more granularity just
|
|
||||||
// in case someone wants to do more fine-tuning of the timing.
|
|
||||||
nrf_pwm_configure(pwm, NRF_PWM_CLK_16MHz, NRF_PWM_MODE_UP, CTOPVAL);
|
|
||||||
|
|
||||||
// Disable loops, we want the sequence to repeat only once
|
|
||||||
nrf_pwm_loop_set(pwm, 0);
|
|
||||||
|
|
||||||
// On the "Common" setting the PWM uses the same pattern for the
|
|
||||||
// for supported sequences. The pattern is stored on half-word of 16bits
|
|
||||||
nrf_pwm_decoder_set(pwm, PWM_DECODER_LOAD_Common, PWM_DECODER_MODE_RefreshCount);
|
|
||||||
|
|
||||||
// The following settings are ignored with the current config.
|
|
||||||
nrf_pwm_seq_refresh_set(pwm, 0, 0);
|
|
||||||
nrf_pwm_seq_end_delay_set(pwm, 0, 0);
|
|
||||||
|
|
||||||
// The Neopixel implementation is a blocking algorithm. DMA
|
|
||||||
// allows for non-blocking operation. To "simulate" a blocking
|
|
||||||
// operation we enable the interruption for the end of sequence
|
|
||||||
// and block the execution thread until the event flag is set by
|
|
||||||
// the peripheral.
|
|
||||||
// pwm->INTEN |= (PWM_INTEN_SEQEND0_Enabled<<PWM_INTEN_SEQEND0_Pos);
|
|
||||||
|
|
||||||
// PSEL must be configured before enabling PWM
|
|
||||||
nrf_pwm_pins_set(pwm, (uint32_t[] ) { LED_NEOPIXEL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL });
|
|
||||||
|
|
||||||
// Enable the PWM
|
|
||||||
nrf_pwm_enable(pwm);
|
|
||||||
}
|
|
||||||
|
|
||||||
void neopixel_teardown(void)
|
|
||||||
{
|
|
||||||
uint8_t rgb[3] = { 0, 0, 0 };
|
|
||||||
|
|
||||||
NRFX_DELAY_US(50); // wait for previous write is complete
|
|
||||||
|
|
||||||
neopixel_write(rgb);
|
|
||||||
NRFX_DELAY_US(50); // wait for this write
|
|
||||||
|
|
||||||
pwm_teardown(NRF_PWM1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// write 3 bytes color RGB to built-in neopixel
|
|
||||||
void neopixel_write (uint8_t *pixels)
|
|
||||||
{
|
|
||||||
// convert RGB to GRB
|
|
||||||
uint8_t grb[BYTE_PER_PIXEL] = {pixels[1], pixels[2], pixels[0]};
|
|
||||||
uint16_t pos = 0; // bit position
|
|
||||||
|
|
||||||
// Set all neopixel to same value
|
|
||||||
for (uint16_t n = 0; n < NEOPIXELS_NUMBER; n++ )
|
|
||||||
{
|
|
||||||
for(uint8_t c = 0; c < BYTE_PER_PIXEL; c++)
|
|
||||||
{
|
|
||||||
uint8_t const pix = grb[c];
|
|
||||||
|
|
||||||
for ( uint8_t mask = 0x80; mask > 0; mask >>= 1 )
|
|
||||||
{
|
|
||||||
pixels_pattern[pos] = (pix & mask) ? MAGIC_T1H : MAGIC_T0H;
|
|
||||||
pos++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Zero padding to indicate the end of sequence
|
|
||||||
pixels_pattern[pos++] = 0 | (0x8000); // Seq end
|
|
||||||
pixels_pattern[pos++] = 0 | (0x8000); // Seq end
|
|
||||||
|
|
||||||
NRF_PWM_Type* pwm = NRF_PWM1;
|
|
||||||
|
|
||||||
nrf_pwm_seq_ptr_set(pwm, 0, pixels_pattern);
|
|
||||||
nrf_pwm_seq_cnt_set(pwm, 0, sizeof(pixels_pattern)/2);
|
|
||||||
nrf_pwm_event_clear(pwm, NRF_PWM_EVENT_SEQEND0);
|
|
||||||
nrf_pwm_task_trigger(pwm, NRF_PWM_TASK_SEQSTART0);
|
|
||||||
|
|
||||||
// blocking wait for sequence complete
|
|
||||||
while( !nrf_pwm_event_check(pwm, NRF_PWM_EVENT_SEQEND0) ) {}
|
|
||||||
nrf_pwm_event_clear(pwm, NRF_PWM_EVENT_SEQEND0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(LED_RGB_RED_PIN) && defined(LED_RGB_GREEN_PIN) && defined(LED_RGB_BLUE_PIN)
|
|
||||||
|
|
||||||
#ifdef LED_SECONDARY_PIN
|
|
||||||
#error "Cannot use secondary LED at the same time as an RGB status LED."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define LED_RGB_RED 1
|
|
||||||
#define LED_RGB_BLUE 2
|
|
||||||
#define LED_RGB_GREEN 3
|
|
||||||
|
|
||||||
void neopixel_init(void)
|
|
||||||
{
|
|
||||||
led_pwm_init(LED_RGB_RED, LED_RGB_RED_PIN);
|
|
||||||
led_pwm_init(LED_RGB_GREEN, LED_RGB_GREEN_PIN);
|
|
||||||
led_pwm_init(LED_RGB_BLUE, LED_RGB_BLUE_PIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
void neopixel_teardown(void)
|
|
||||||
{
|
|
||||||
uint8_t rgb[3] = { 0, 0, 0 };
|
|
||||||
neopixel_write(rgb);
|
|
||||||
nrf_gpio_cfg_default(LED_RGB_RED_PIN);
|
|
||||||
nrf_gpio_cfg_default(LED_RGB_GREEN_PIN);
|
|
||||||
nrf_gpio_cfg_default(LED_RGB_BLUE_PIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
// write 3 bytes color to a built-in neopixel
|
|
||||||
void neopixel_write (uint8_t *pixels)
|
|
||||||
{
|
|
||||||
led_pwm_duty_cycle(LED_RGB_RED, pixels[2]);
|
|
||||||
led_pwm_duty_cycle(LED_RGB_GREEN, pixels[1]);
|
|
||||||
led_pwm_duty_cycle(LED_RGB_BLUE, pixels[0]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
17
src/boards.h
17
src/boards.h
@ -89,23 +89,6 @@ void led_pwm_enable(uint32_t led_index);
|
|||||||
void led_state(uint32_t state);
|
void led_state(uint32_t state);
|
||||||
void led_tick(void);
|
void led_tick(void);
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
|
||||||
// BUTTONS
|
|
||||||
//--------------------------------------------------------------------+
|
|
||||||
// Make sure we have at least two buttons (DFU + FRESET since DFU+FRST=OTA)
|
|
||||||
#if BUTTONS_NUMBER < 2
|
|
||||||
#define button_init(pin)
|
|
||||||
#define button_pressed(pin) false
|
|
||||||
#else
|
|
||||||
// #error "At least two buttons required in the BSP (see 'BUTTONS_NUMBER')"
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
void button_init(uint32_t pin);
|
|
||||||
bool button_pressed(uint32_t pin);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool is_ota(void);
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
// DEBUG
|
// DEBUG
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
|
@ -29,23 +29,19 @@
|
|||||||
/* LED
|
/* LED
|
||||||
*------------------------------------------------------------------*/
|
*------------------------------------------------------------------*/
|
||||||
#define LEDS_NUMBER 1
|
#define LEDS_NUMBER 1
|
||||||
#define LED_PRIMARY_PIN 4
|
// #define LED_PRIMARY_PIN 4
|
||||||
|
#define LED_PRIMARY_PIN 14
|
||||||
#define LED_STATE_ON 0
|
#define LED_STATE_ON 0
|
||||||
|
|
||||||
/*------------------------------------------------------------------*/
|
#define LOOPBACK_TX_PIN 12
|
||||||
/* BUTTON
|
#define LOOPBACK_RX_PIN 11
|
||||||
*------------------------------------------------------------------*/
|
|
||||||
#define BUTTONS_NUMBER 0
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
|
||||||
// BLE OTA
|
|
||||||
//--------------------------------------------------------------------+
|
|
||||||
#define BLEDIS_MANUFACTURER "Betrusted"
|
|
||||||
#define BLEDIS_MODEL "Simmel"
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
// USB
|
// USB
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
|
#define USB_MANUFACTURER "Betrusted"
|
||||||
|
#define USB_MODEL "Simmel"
|
||||||
|
#define UF2_VOLUME_LABEL "SIMMEL_BOOT"
|
||||||
#define UF2_PRODUCT_NAME "Simmel"
|
#define UF2_PRODUCT_NAME "Simmel"
|
||||||
#define UF2_BOARD_ID "nRF52833-simmel-v1"
|
#define UF2_BOARD_ID "nRF52833-simmel-v1"
|
||||||
#define UF2_INDEX_URL "https://github.com/simmel-project/"
|
#define UF2_INDEX_URL "https://github.com/simmel-project/"
|
||||||
|
@ -43,66 +43,66 @@
|
|||||||
#include "nrf_error.h"
|
#include "nrf_error.h"
|
||||||
#include "crc16.h"
|
#include "crc16.h"
|
||||||
|
|
||||||
#if defined ( __CC_ARM )
|
// #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 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 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__ )
|
// #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 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 uint16_t m_peer_data_crc; /**< CRC variable to ensure the integrity of the peer data provided. */
|
||||||
#elif defined ( __ICCARM__ )
|
// #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 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 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
|
// #endif
|
||||||
|
|
||||||
|
|
||||||
/**@brief Function for setting the peer data from application in bootloader before reset.
|
// /**@brief Function for setting the peer data from application in bootloader before reset.
|
||||||
*
|
// *
|
||||||
* @param[in] p_peer_data Pointer to the peer data containing keys for the connection.
|
// * @param[in] p_peer_data Pointer to the peer data containing keys for the connection.
|
||||||
*
|
// *
|
||||||
* @retval NRF_SUCCES The data was set succesfully.
|
// * @retval NRF_SUCCES The data was set succesfully.
|
||||||
* @retval NRF_ERROR_NULL If a null pointer was passed as argument.
|
// * @retval NRF_ERROR_NULL If a null pointer was passed as argument.
|
||||||
*/
|
// */
|
||||||
static uint32_t dfu_ble_peer_data_set(dfu_ble_peer_data_t * p_peer_data)
|
// static uint32_t dfu_ble_peer_data_set(dfu_ble_peer_data_t * p_peer_data)
|
||||||
{
|
// {
|
||||||
if (p_peer_data == NULL)
|
// if (p_peer_data == NULL)
|
||||||
{
|
// {
|
||||||
return NRF_ERROR_NULL;
|
// return NRF_ERROR_NULL;
|
||||||
}
|
// }
|
||||||
|
|
||||||
uint32_t src = (uint32_t)p_peer_data;
|
// uint32_t src = (uint32_t)p_peer_data;
|
||||||
uint32_t dst = (uint32_t)&m_peer_data;
|
// uint32_t dst = (uint32_t)&m_peer_data;
|
||||||
// Calculating length in order to check if destination is residing inside source.
|
// // Calculating length in order to check if destination is residing inside source.
|
||||||
// Source inside the the destination (calculation underflow) is safe a source is read before
|
// // Source inside the the destination (calculation underflow) is safe a source is read before
|
||||||
// written to destination so that when destination grows into source, the source data is no
|
// // written to destination so that when destination grows into source, the source data is no
|
||||||
// longer needed.
|
// // longer needed.
|
||||||
uint32_t len = dst - src;
|
// uint32_t len = dst - src;
|
||||||
|
|
||||||
if (src == dst)
|
// if (src == dst)
|
||||||
{
|
// {
|
||||||
// Do nothing as source and destination are identical, just calculate crc below.
|
// // Do nothing as source and destination are identical, just calculate crc below.
|
||||||
}
|
// }
|
||||||
else if (len < sizeof(dfu_ble_peer_data_t))
|
// else if (len < sizeof(dfu_ble_peer_data_t))
|
||||||
{
|
// {
|
||||||
uint32_t i = 0;
|
// uint32_t i = 0;
|
||||||
|
|
||||||
dst += sizeof(dfu_ble_peer_data_t);
|
// dst += sizeof(dfu_ble_peer_data_t);
|
||||||
src += sizeof(dfu_ble_peer_data_t);
|
// src += sizeof(dfu_ble_peer_data_t);
|
||||||
|
|
||||||
// Copy byte wise backwards when facing overlapping structures.
|
// // Copy byte wise backwards when facing overlapping structures.
|
||||||
while (i++ <= sizeof(dfu_ble_peer_data_t))
|
// while (i++ <= sizeof(dfu_ble_peer_data_t))
|
||||||
{
|
// {
|
||||||
*((uint8_t *)dst--) = *((uint8_t *)src--);
|
// *((uint8_t *)dst--) = *((uint8_t *)src--);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
memcpy((void *)dst, (void *)src, sizeof(dfu_ble_peer_data_t));
|
// memcpy((void *)dst, (void *)src, sizeof(dfu_ble_peer_data_t));
|
||||||
}
|
// }
|
||||||
|
|
||||||
m_peer_data_crc = crc16_compute((uint8_t *)&m_peer_data, sizeof(m_peer_data), NULL);
|
// m_peer_data_crc = crc16_compute((uint8_t *)&m_peer_data, sizeof(m_peer_data), NULL);
|
||||||
|
|
||||||
return NRF_SUCCESS;
|
// return NRF_SUCCESS;
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
/**@brief Function for handling second stage of SuperVisor Calls (SVC).
|
/**@brief Function for handling second stage of SuperVisor Calls (SVC).
|
||||||
@ -119,16 +119,16 @@ static uint32_t dfu_ble_peer_data_set(dfu_ble_peer_data_t * p_peer_data)
|
|||||||
*/
|
*/
|
||||||
void C_SVC_Handler(uint8_t svc_num, uint32_t * p_svc_args)
|
void C_SVC_Handler(uint8_t svc_num, uint32_t * p_svc_args)
|
||||||
{
|
{
|
||||||
switch (svc_num)
|
// switch (svc_num)
|
||||||
{
|
// {
|
||||||
case DFU_BLE_SVC_PEER_DATA_SET:
|
// case DFU_BLE_SVC_PEER_DATA_SET:
|
||||||
p_svc_args[0] = dfu_ble_peer_data_set((dfu_ble_peer_data_t *)p_svc_args[0]);
|
// p_svc_args[0] = dfu_ble_peer_data_set((dfu_ble_peer_data_t *)p_svc_args[0]);
|
||||||
break;
|
// break;
|
||||||
|
|
||||||
default:
|
// default:
|
||||||
p_svc_args[0] = NRF_ERROR_SVC_HANDLER_MISSING;
|
p_svc_args[0] = NRF_ERROR_SVC_HANDLER_MISSING;
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -209,25 +209,25 @@ void SVC_Handler(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
uint32_t dfu_ble_peer_data_get(dfu_ble_peer_data_t * p_peer_data)
|
// uint32_t dfu_ble_peer_data_get(dfu_ble_peer_data_t * p_peer_data)
|
||||||
{
|
// {
|
||||||
uint16_t crc;
|
// uint16_t crc;
|
||||||
|
|
||||||
if (p_peer_data == NULL)
|
// if (p_peer_data == NULL)
|
||||||
{
|
// {
|
||||||
return NRF_ERROR_NULL;
|
// return NRF_ERROR_NULL;
|
||||||
}
|
// }
|
||||||
|
|
||||||
crc = crc16_compute((uint8_t *)&m_peer_data, sizeof(m_peer_data), NULL);
|
// crc = crc16_compute((uint8_t *)&m_peer_data, sizeof(m_peer_data), NULL);
|
||||||
if (crc != m_peer_data_crc)
|
// if (crc != m_peer_data_crc)
|
||||||
{
|
// {
|
||||||
return NRF_ERROR_INVALID_DATA;
|
// return NRF_ERROR_INVALID_DATA;
|
||||||
}
|
// }
|
||||||
|
|
||||||
*p_peer_data = m_peer_data;
|
// *p_peer_data = m_peer_data;
|
||||||
|
|
||||||
// corrupt CRC to invalidate shared information.
|
// // corrupt CRC to invalidate shared information.
|
||||||
m_peer_data_crc++;
|
// m_peer_data_crc++;
|
||||||
|
|
||||||
return NRF_SUCCESS;
|
// return NRF_SUCCESS;
|
||||||
}
|
// }
|
||||||
|
134
src/main.c
134
src/main.c
@ -73,12 +73,12 @@
|
|||||||
#include "nrf_usbd.h"
|
#include "nrf_usbd.h"
|
||||||
#include "tusb.h"
|
#include "tusb.h"
|
||||||
|
|
||||||
void usb_init(bool cdc_only);
|
void usb_init(void);
|
||||||
void usb_teardown(void);
|
void usb_teardown(void);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define usb_init(x) led_state(STATE_USB_MOUNTED) // mark nrf52832 as mounted
|
#define usb_init() led_state(STATE_USB_MOUNTED) // mark nrf52832 as mounted
|
||||||
#define usb_teardown()
|
#define usb_teardown()
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -128,14 +128,13 @@ enum { BLE_CONN_CFG_HIGH_BANDWIDTH = 1 };
|
|||||||
#ifdef NRF52840_XXAA
|
#ifdef NRF52840_XXAA
|
||||||
// Flash 1024 KB
|
// Flash 1024 KB
|
||||||
STATIC_ASSERT( APPDATA_ADDR_START == 0xED000);
|
STATIC_ASSERT( APPDATA_ADDR_START == 0xED000);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
// Flash 512 KB
|
// Flash 512 KB
|
||||||
STATIC_ASSERT( APPDATA_ADDR_START == 0x6D000);
|
STATIC_ASSERT( APPDATA_ADDR_START == 0x73000);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void adafruit_factory_reset(void);
|
// void adafruit_factory_reset(void);
|
||||||
|
|
||||||
uint32_t* dbl_reset_mem = ((uint32_t*) DFU_DBL_RESET_MEM );
|
uint32_t* dbl_reset_mem = ((uint32_t*) DFU_DBL_RESET_MEM );
|
||||||
|
|
||||||
@ -153,18 +152,48 @@ void softdev_mbr_init(void)
|
|||||||
sd_mbr_command(&com);
|
sd_mbr_command(&com);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send data out one pin and look for it coming back
|
||||||
|
// on the other. Toggle it up and down.
|
||||||
|
static bool check_loopback(void) {
|
||||||
|
unsigned int i = 0;
|
||||||
|
nrf_gpio_cfg_output(LOOPBACK_TX_PIN);
|
||||||
|
nrf_gpio_cfg_input(LOOPBACK_RX_PIN, NRF_GPIO_PIN_NOPULL);
|
||||||
|
|
||||||
|
for (i = 0; i < 16; i++) {
|
||||||
|
if ((i & 1) == 0) {
|
||||||
|
nrf_gpio_pin_clear(LOOPBACK_TX_PIN);
|
||||||
|
// Dummy read to force sync
|
||||||
|
(void)nrf_gpio_pin_read(LOOPBACK_TX_PIN);
|
||||||
|
if (nrf_gpio_pin_read(LOOPBACK_RX_PIN))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nrf_gpio_pin_set(LOOPBACK_TX_PIN);
|
||||||
|
// Dummy read to force sync
|
||||||
|
(void)nrf_gpio_pin_read(LOOPBACK_TX_PIN);
|
||||||
|
if (!nrf_gpio_pin_read(LOOPBACK_RX_PIN))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
// SD is already Initialized in case of BOOTLOADER_DFU_OTA_MAGIC
|
// SD is already Initialized in case of BOOTLOADER_DFU_OTA_MAGIC
|
||||||
bool sd_inited = (NRF_POWER->GPREGRET == DFU_MAGIC_OTA_APPJUM);
|
bool sd_inited = (NRF_POWER->GPREGRET == DFU_MAGIC_OTA_APPJUM);
|
||||||
|
|
||||||
// Serial only mode
|
// Serial only mode
|
||||||
bool serial_only_dfu = (NRF_POWER->GPREGRET == DFU_MAGIC_SERIAL_ONLY_RESET);
|
// bool serial_only_dfu = (NRF_POWER->GPREGRET == DFU_MAGIC_SERIAL_ONLY_RESET);
|
||||||
|
|
||||||
|
// Pins are shorted together
|
||||||
|
bool loopback_shorted = check_loopback();
|
||||||
|
|
||||||
// start either serial, uf2 or ble
|
// start either serial, uf2 or ble
|
||||||
bool dfu_start = serial_only_dfu || (NRF_POWER->GPREGRET == DFU_MAGIC_UF2_RESET) ||
|
bool dfu_start = loopback_shorted || (NRF_POWER->GPREGRET == DFU_MAGIC_UF2_RESET) ||
|
||||||
(((*dbl_reset_mem) == DFU_DBL_RESET_MAGIC) && (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk));
|
(((*dbl_reset_mem) == DFU_DBL_RESET_MAGIC) && (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk));
|
||||||
|
|
||||||
|
|
||||||
// Clear GPREGRET if it is our values
|
// Clear GPREGRET if it is our values
|
||||||
if (dfu_start) NRF_POWER->GPREGRET = 0;
|
if (dfu_start) NRF_POWER->GPREGRET = 0;
|
||||||
|
|
||||||
@ -179,20 +208,20 @@ int main(void)
|
|||||||
|
|
||||||
led_state(STATE_BOOTLOADER_STARTED);
|
led_state(STATE_BOOTLOADER_STARTED);
|
||||||
|
|
||||||
// When updating SoftDevice, bootloader will reset before swapping SD
|
// // When updating SoftDevice, bootloader will reset before swapping SD
|
||||||
if (bootloader_dfu_sd_in_progress())
|
// if (bootloader_dfu_sd_in_progress())
|
||||||
{
|
// {
|
||||||
led_state(STATE_WRITING_STARTED);
|
// led_state(STATE_WRITING_STARTED);
|
||||||
|
|
||||||
APP_ERROR_CHECK( bootloader_dfu_sd_update_continue() );
|
// APP_ERROR_CHECK( bootloader_dfu_sd_update_continue() );
|
||||||
APP_ERROR_CHECK( bootloader_dfu_sd_update_finalize() );
|
// APP_ERROR_CHECK( bootloader_dfu_sd_update_finalize() );
|
||||||
|
|
||||||
led_state(STATE_WRITING_FINISHED);
|
// led_state(STATE_WRITING_FINISHED);
|
||||||
}
|
// }
|
||||||
|
|
||||||
/*------------- Determine DFU mode (Serial, OTA, FRESET or normal) -------------*/
|
/*------------- Determine DFU mode (Serial, OTA, FRESET or normal) -------------*/
|
||||||
// DFU button pressed
|
// DFU button pressed
|
||||||
dfu_start = dfu_start || button_pressed(BUTTON_DFU);
|
// dfu_start = dfu_start || button_pressed(BUTTON_DFU);
|
||||||
|
|
||||||
bool const valid_app = bootloader_app_is_valid(DFU_BANK_0_REGION_START);
|
bool const valid_app = bootloader_app_is_valid(DFU_BANK_0_REGION_START);
|
||||||
bool const just_start_app = valid_app && !dfu_start && (*dbl_reset_mem) == DFU_DBL_RESET_APP;
|
bool const just_start_app = valid_app && !dfu_start && (*dbl_reset_mem) == DFU_DBL_RESET_APP;
|
||||||
@ -206,18 +235,18 @@ int main(void)
|
|||||||
// Register our first reset for double reset detection
|
// Register our first reset for double reset detection
|
||||||
(*dbl_reset_mem) = DFU_DBL_RESET_MAGIC;
|
(*dbl_reset_mem) = DFU_DBL_RESET_MAGIC;
|
||||||
|
|
||||||
#ifdef NRF52832_XXAA
|
// #ifdef NRF52832_XXAA
|
||||||
/* Even DFU is not active, we still force an 1000 ms dfu serial mode when startup
|
// /* Even DFU is not active, we still force an 1000 ms dfu serial mode when startup
|
||||||
* to support auto programming from Arduino IDE
|
// * to support auto programming from Arduino IDE
|
||||||
*
|
// *
|
||||||
* Note: Supposedly during this time if RST is press, it will count as double reset.
|
// * Note: Supposedly during this time if RST is press, it will count as double reset.
|
||||||
* However Double Reset WONT work with nrf52832 since its SRAM got cleared anyway.
|
// * However Double Reset WONT work with nrf52832 since its SRAM got cleared anyway.
|
||||||
*/
|
// */
|
||||||
bootloader_dfu_start(DFU_SERIAL_STARTUP_INTERVAL);
|
// bootloader_dfu_start(DFU_SERIAL_STARTUP_INTERVAL);
|
||||||
#else
|
// #else
|
||||||
// if RST is pressed during this delay --> if will enter dfu
|
// // if RST is pressed during this delay --> if will enter dfu
|
||||||
NRFX_DELAY_MS(DFU_DBL_RESET_DELAY);
|
// NRFX_DELAY_MS(DFU_DBL_RESET_DELAY);
|
||||||
#endif
|
// #endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (APP_ASKS_FOR_SINGLE_TAP_RESET())
|
if (APP_ASKS_FOR_SINGLE_TAP_RESET())
|
||||||
@ -225,22 +254,27 @@ int main(void)
|
|||||||
else
|
else
|
||||||
(*dbl_reset_mem) = 0;
|
(*dbl_reset_mem) = 0;
|
||||||
|
|
||||||
if ( dfu_start || !valid_app )
|
if ( dfu_start || !valid_app)
|
||||||
{
|
{
|
||||||
led_state(STATE_USB_UNMOUNTED);
|
led_state(STATE_USB_UNMOUNTED);
|
||||||
usb_init(serial_only_dfu);
|
usb_init();
|
||||||
|
|
||||||
// Initiate an update of the firmware.
|
// Initiate an update of the firmware.
|
||||||
APP_ERROR_CHECK( bootloader_dfu_start(0) );
|
// APP_ERROR_CHECK( bootloader_dfu_start(0) );
|
||||||
|
// while (1) {
|
||||||
|
// tud_task();
|
||||||
|
// tud_cdc_write_flush();
|
||||||
|
// }
|
||||||
|
bootloader_run(0);
|
||||||
|
|
||||||
usb_teardown();
|
usb_teardown();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adafruit Factory reset
|
// // Adafruit Factory reset
|
||||||
if ( !button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) )
|
// if ( !button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) )
|
||||||
{
|
// {
|
||||||
adafruit_factory_reset();
|
// adafruit_factory_reset();
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Reset Board
|
// Reset Board
|
||||||
board_teardown();
|
board_teardown();
|
||||||
@ -263,23 +297,23 @@ int main(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Perform factory reset to erase Application + Data
|
// // Perform factory reset to erase Application + Data
|
||||||
void adafruit_factory_reset(void)
|
// void adafruit_factory_reset(void)
|
||||||
{
|
// {
|
||||||
led_state(STATE_FACTORY_RESET_STARTED);
|
// led_state(STATE_FACTORY_RESET_STARTED);
|
||||||
|
|
||||||
// clear all App Data if any
|
// // clear all App Data if any
|
||||||
if ( DFU_APP_DATA_RESERVED )
|
// if ( DFU_APP_DATA_RESERVED )
|
||||||
{
|
// {
|
||||||
nrfx_nvmc_page_erase(APPDATA_ADDR_START);
|
// nrfx_nvmc_page_erase(APPDATA_ADDR_START);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Only need to erase the 1st page of Application code to make it invalid
|
// // Only need to erase the 1st page of Application code to make it invalid
|
||||||
nrfx_nvmc_page_erase(DFU_BANK_0_REGION_START);
|
// nrfx_nvmc_page_erase(DFU_BANK_0_REGION_START);
|
||||||
|
|
||||||
// back to normal
|
// // back to normal
|
||||||
led_state(STATE_FACTORY_RESET_FINISHED);
|
// led_state(STATE_FACTORY_RESET_FINISHED);
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
extern void tusb_hal_nrf_power_event(uint32_t event);
|
extern void tusb_hal_nrf_power_event(uint32_t event);
|
||||||
|
|
||||||
//------------- IMPLEMENTATION -------------//
|
//------------- IMPLEMENTATION -------------//
|
||||||
void usb_init(bool cdc_only)
|
void usb_init(void)
|
||||||
{
|
{
|
||||||
NVIC_SetPriority(USBD_IRQn, 2);
|
NVIC_SetPriority(USBD_IRQn, 2);
|
||||||
|
|
||||||
@ -87,7 +87,7 @@ void usb_init(bool cdc_only)
|
|||||||
tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_READY);
|
tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_READY);
|
||||||
}
|
}
|
||||||
|
|
||||||
usb_desc_init(cdc_only);
|
usb_desc_init();
|
||||||
|
|
||||||
// Init TinyUSB stack
|
// Init TinyUSB stack
|
||||||
tusb_init();
|
tusb_init();
|
||||||
|
@ -33,9 +33,6 @@ enum {
|
|||||||
ITF_STR_MSC
|
ITF_STR_MSC
|
||||||
};
|
};
|
||||||
|
|
||||||
// CDC + MSC or CDC only mode
|
|
||||||
static bool _cdc_only = false;
|
|
||||||
|
|
||||||
// Serial is 64-bit DeviceID -> 16 chars len
|
// Serial is 64-bit DeviceID -> 16 chars len
|
||||||
static char desc_str_serial[1+16];
|
static char desc_str_serial[1+16];
|
||||||
|
|
||||||
@ -96,15 +93,6 @@ uint8_t const desc_configuration_cdc_msc[] =
|
|||||||
TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, ITF_STR_MSC, 0x03, 0x83, 64),
|
TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, ITF_STR_MSC, 0x03, 0x83, 64),
|
||||||
};
|
};
|
||||||
|
|
||||||
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),
|
|
||||||
|
|
||||||
// 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),
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
||||||
// Application return pointer to descriptor
|
// Application return pointer to descriptor
|
||||||
@ -112,22 +100,26 @@ uint8_t const desc_configuration_cdc_only[] =
|
|||||||
uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
|
uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
|
||||||
{
|
{
|
||||||
(void) index; // for multiple configurations
|
(void) index; // for multiple configurations
|
||||||
return _cdc_only ? desc_configuration_cdc_only : desc_configuration_cdc_msc;
|
return desc_configuration_cdc_msc;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enumerate as CDC + MSC or CDC only
|
// Enumerate as CDC + MSC or CDC only
|
||||||
void usb_desc_init(bool cdc_only)
|
void usb_desc_init(void)
|
||||||
{
|
{
|
||||||
_cdc_only = cdc_only;
|
static const char HEX_DIGITS[16] = "0123456789ABCDEF";
|
||||||
|
unsigned int i;
|
||||||
|
uint32_t serial;
|
||||||
|
|
||||||
if ( cdc_only )
|
serial = NRF_FICR->DEVICEID[1];
|
||||||
{
|
for (i = 0; i < 8; i++) {
|
||||||
// Change PID to CDC only
|
desc_str_serial[i] = HEX_DIGITS[15 & (serial>>(i<<2))];
|
||||||
desc_device.idProduct = USB_DESC_CDC_ONLY_PID;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create Serial string descriptor
|
serial = NRF_FICR->DEVICEID[0];
|
||||||
sprintf(desc_str_serial, "%08lX%08lX", NRF_FICR->DEVICEID[1], NRF_FICR->DEVICEID[0]);
|
for (i = 0; i < 8; i++) {
|
||||||
|
desc_str_serial[8+i] = HEX_DIGITS[15 & (serial>>(i<<2))];
|
||||||
|
}
|
||||||
|
desc_str_serial[16] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
@ -138,8 +130,8 @@ void usb_desc_init(bool cdc_only)
|
|||||||
char const* string_desc_arr [] =
|
char const* string_desc_arr [] =
|
||||||
{
|
{
|
||||||
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
|
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
|
||||||
BLEDIS_MANUFACTURER, // 1: Manufacturer
|
USB_MANUFACTURER, // 1: Manufacturer
|
||||||
BLEDIS_MODEL, // 2: Product
|
USB_MODEL, // 2: Product
|
||||||
desc_str_serial, // 3: Serials, should use chip ID
|
desc_str_serial, // 3: Serials, should use chip ID
|
||||||
"nRF Serial", // 4: CDC Interface
|
"nRF Serial", // 4: CDC Interface
|
||||||
"nRF UF2", // 5: MSC Interface
|
"nRF UF2", // 5: MSC Interface
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
#include "tusb.h"
|
#include "tusb.h"
|
||||||
#include "boards.h"
|
#include "boards.h"
|
||||||
|
|
||||||
void usb_desc_init(bool cdc_only);
|
void usb_desc_init(void);
|
||||||
|
|
||||||
#ifndef USB_DESC_VID
|
#ifndef USB_DESC_VID
|
||||||
#define USB_DESC_VID 0x239A
|
#define USB_DESC_VID 0x239A
|
||||||
|
Loading…
Reference in New Issue
Block a user