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:
Sean Cross 2020-04-18 22:37:06 +08:00
parent 30c2c0e7c8
commit 91cd582dea
13 changed files with 295 additions and 536 deletions

View File

@ -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_settings.c
C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/bootloader_util.c
C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/dfu_transport_serial.c
C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/dfu_transport_ble.c
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_dis/ble_dis.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_single_bank.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)/drivers_nrf/pstorage/pstorage_raw.c
# 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_util_platform.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_slip.c
C_SRC += $(SDK_PATH)/libraries/hci/hci_transport.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_transport.c
C_SRC += $(SDK_PATH)/libraries/util/nrf_assert.c
# UART or USB Serial
ifeq ($(MCU_SUB_VARIANT),nrf52)
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/common/nrf_drv_common.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/common/nrf_drv_common.c
IPATH += $(SDK11_PATH)/libraries/util
IPATH += $(SDK_PATH)/drivers_nrf/common
@ -212,6 +212,7 @@ endif
#flags common to all targets
CFLAGS += \
-mthumb \
-flto \
-mabi=aapcs \
-mcpu=cortex-m4 \
-mfloat-abi=hard \
@ -234,7 +235,7 @@ CFLAGS += \
-Wsign-compare \
-Wmissing-format-attribute \
-Wno-endif-labels \
-Wunreachable-code
-Wunreachable-code
# Suppress warning caused by SDK
CFLAGS += -Wno-unused-parameter -Wno-expansion-to-defined
@ -372,7 +373,7 @@ $(BUILD)/$(OUT_FILE)-nosd.hex: $(BUILD)/$(OUT_FILE)-nosd.out
# merge bootloader and sd hex together
$(BUILD)/$(MERGED_FILE).hex: $(BUILD)/$(OUT_FILE)-nosd.hex
@echo CR $(MERGED_FILE).hex
@mergehex -q -m $< $(SD_HEX) -o $@
@mergehex.exe -q -m $< $(SD_HEX) -o $@
## Create pkg zip file for bootloader+SD combo to use with DFU Serial
.PHONY: genpkg

View File

@ -183,21 +183,10 @@ bool bootloader_app_is_valid(uint32_t app_addr)
static void bootloader_settings_save(bootloader_settings_t * p_settings)
{
if ( is_ota() )
{
uint32_t err_code = pstorage_clear(&m_bootsettings_handle, sizeof(bootloader_settings_t));
APP_ERROR_CHECK(err_code);
nrfx_nvmc_page_erase(BOOTLOADER_SETTINGS_ADDRESS);
nrfx_nvmc_words_write(BOOTLOADER_SETTINGS_ADDRESS, (uint32_t *) p_settings, sizeof(bootloader_settings_t) / 4);
err_code = pstorage_store(&m_bootsettings_handle, (uint8_t *) p_settings, sizeof(bootloader_settings_t), 0);
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));
}
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;
bootloader_settings_save(&settings);
}
else if (update_status.status_code == DFU_UPDATE_SD_COMPLETE)
{
settings.bank_0_crc = update_status.app_crc;
settings.bank_0_size = update_status.sd_size +
update_status.bl_size +
update_status.app_size;
settings.bank_0 = BANK_VALID_SD;
settings.bank_1 = BANK_INVALID_APP;
settings.sd_image_size = update_status.sd_size;
settings.bl_image_size = update_status.bl_size;
settings.app_image_size = update_status.app_size;
settings.sd_image_start = update_status.sd_image_start;
// else if (update_status.status_code == DFU_UPDATE_SD_COMPLETE)
// {
// settings.bank_0_crc = update_status.app_crc;
// settings.bank_0_size = update_status.sd_size +
// update_status.bl_size +
// update_status.app_size;
// settings.bank_0 = BANK_VALID_SD;
// settings.bank_1 = BANK_INVALID_APP;
// settings.sd_image_size = update_status.sd_size;
// settings.bl_image_size = update_status.bl_size;
// settings.app_image_size = update_status.app_size;
// settings.sd_image_start = update_status.sd_image_start;
m_update_status = BOOTLOADER_SETTINGS_SAVING;
bootloader_settings_save(&settings);
}
// m_update_status = BOOTLOADER_SETTINGS_SAVING;
// bootloader_settings_save(&settings);
// }
else if (update_status.status_code == DFU_UPDATE_BOOT_COMPLETE)
{
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;
bootloader_settings_save(&settings);
}
else if (update_status.status_code == DFU_UPDATE_SD_SWAPPED)
{
if (p_bootloader_settings->bank_0 == BANK_VALID_SD)
{
settings.bank_0_crc = 0;
settings.bank_0_size = 0;
settings.bank_0 = BANK_INVALID_APP;
}
// This handles cases where SoftDevice was not updated, hence bank0 keeps its settings.
else
{
settings.bank_0 = p_bootloader_settings->bank_0;
settings.bank_0_crc = p_bootloader_settings->bank_0_crc;
settings.bank_0_size = p_bootloader_settings->bank_0_size;
}
// else if (update_status.status_code == DFU_UPDATE_SD_SWAPPED)
// {
// if (p_bootloader_settings->bank_0 == BANK_VALID_SD)
// {
// settings.bank_0_crc = 0;
// settings.bank_0_size = 0;
// settings.bank_0 = BANK_INVALID_APP;
// }
// // This handles cases where SoftDevice was not updated, hence bank0 keeps its settings.
// else
// {
// settings.bank_0 = p_bootloader_settings->bank_0;
// settings.bank_0_crc = p_bootloader_settings->bank_0_crc;
// settings.bank_0_size = p_bootloader_settings->bank_0_size;
// }
settings.bank_1 = BANK_INVALID_APP;
settings.sd_image_size = 0;
settings.bl_image_size = 0;
settings.app_image_size = 0;
// settings.bank_1 = BANK_INVALID_APP;
// settings.sd_image_size = 0;
// settings.bl_image_size = 0;
// settings.app_image_size = 0;
m_update_status = BOOTLOADER_SETTINGS_SAVING;
bootloader_settings_save(&settings);
}
// m_update_status = BOOTLOADER_SETTINGS_SAVING;
// bootloader_settings_save(&settings);
// }
else if (update_status.status_code == DFU_TIMEOUT)
{
// Timeout has occurred. Close the connection with the DFU Controller.
uint32_t err_code;
if ( is_ota() )
{
err_code = dfu_transport_ble_close();
}else
{
err_code = dfu_transport_serial_close();
}
APP_ERROR_CHECK(err_code);
// // Timeout has occurred. Close the connection with the DFU Controller.
// uint32_t err_code;
// // if ( is_ota() )
// // {
// // err_code = dfu_transport_ble_close();
// // }else
// // {
// err_code = dfu_transport_serial_close();
// // }
// APP_ERROR_CHECK(err_code);
m_update_status = BOOTLOADER_TIMEOUT;
}
else if (update_status.status_code == DFU_BANK_0_ERASED)
{
settings.bank_0_crc = 0;
settings.bank_0_size = 0;
settings.bank_0 = BANK_INVALID_APP;
settings.bank_1 = p_bootloader_settings->bank_1;
// else if (update_status.status_code == DFU_BANK_0_ERASED)
// {
// settings.bank_0_crc = 0;
// settings.bank_0_size = 0;
// settings.bank_0 = BANK_INVALID_APP;
// settings.bank_1 = p_bootloader_settings->bank_1;
bootloader_settings_save(&settings);
}
// bootloader_settings_save(&settings);
// }
else if (update_status.status_code == DFU_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.
err_code = dfu_init();
VERIFY_SUCCESS(err_code);
// // Clear swap if banked update is used.
// err_code = dfu_init();
// VERIFY_SUCCESS(err_code);
// timeout_ms > 0 is forced startup DFU
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);
}
err_code = dfu_transport_serial_update_start();
// err_code = dfu_transport_serial_update_start();
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)
{
dfu_update_status_t update_status = { 0 };
update_status.status_code = DFU_UPDATE_SD_SWAPPED;
// uint32_t bootloader_dfu_sd_update_finalize(void)
// {
// dfu_update_status_t update_status = { 0 };
// 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)

View File

@ -47,6 +47,8 @@ bool bootloader_app_is_valid(uint32_t app_addr);
*/
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.
*
* @details This function will disable SoftDevice and all interrupts before jumping to application.

View File

@ -39,7 +39,7 @@
// 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_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_MBR_PARAMS_PAGE_ADDRESS 0x0007E000 /**< The field specifies the page location of the mbr params page address. */

View File

@ -5,38 +5,35 @@ GROUP(-lgcc -lc -lnosys)
MEMORY
{
/** Flash start address for the bootloader. This setting will also be stored in UICR to allow the
* MBR to init the bootloader when starting the system. This value must correspond to
* BOOTLOADER_REGION_START found in dfu_types.h. The system is prevented from starting up if
* those values do not match. The check 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 start address for the bootloader. This setting will also be stored
in UICR to allow the MBR to init the bootloader when starting the system. This
value must correspond to BOOTLOADER_REGION_START found in dfu_types.h. The
system is prevented from starting up if those values do not match. The check
is performed in main.c, see APP_ERROR_CHECK_BOOL(*((uint32_t
*)NRF_UICR_BOOT_START_ADDRESS) == BOOTLOADER_REGION_START); */
FLASH (rx) : ORIGIN = 0x7a000, LENGTH = 0x7E000-0x7a000 /* 40 KB */
/** Location of mbr params page in flash. */
MBR_PARAMS_PAGE (rw) : ORIGIN = 0x0007E000, LENGTH = 0x1000
/** Location of bootloader setting in flash. */
BOOTLOADER_SETTINGS (rw) : ORIGIN = 0x0007F000, LENGTH = 0x1000
/** RAM Region for bootloader. */
/* Avoid conflict with NOINIT for OTA bond sharing */
RAM (rwx) : ORIGIN = 0x20008000, LENGTH = 0x20020000-0x20008000
/* Location for double reset detection, no init */
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. */
NOINIT (rwx) : ORIGIN = 0x20007F80, LENGTH = 0x80
/** Location of non initialized RAM. Non initialized RAM is used for
exchanging bond information * from application to bootloader when using
buttonless DFU OTA. */ NOINIT (rwx) : ORIGIN = 0x20007F80, LENGTH = 0x80
/** Location in UICR where bootloader start address is stored. */
UICR_BOOTLOADER (r) : ORIGIN = 0x10001014, LENGTH = 0x04
/** Location in UICR where mbr params page address is stored. */
UICR_MBR_PARAM_PAGE(r) : ORIGIN = 0x10001018, LENGTH = 0x04
}
@ -53,21 +50,21 @@ SECTIONS
/* Place the bootloader settings page in flash. */
.bootloaderSettings(NOLOAD) :
{
} > BOOTLOADER_SETTINGS
/* Write the bootloader address in UICR. */
.uicrBootStartAddress :
.uicrBootStartAddress :
{
KEEP(*(.uicrBootStartAddress))
} > UICR_BOOTLOADER
/* Place the mbr params page in flash. */
.mbrParamsPage(NOLOAD) :
{
} > MBR_PARAMS_PAGE
/* Write the bootloader address in UICR. */
.uicrMbrParamsPageAddress :
{

View File

@ -33,34 +33,7 @@
#define SCHED_MAX_EVENT_DATA_SIZE sizeof(app_timer_event_t) /**< Maximum size of scheduler events. */
#define SCHED_QUEUE_SIZE 30 /**< Maximum number of events in the scheduler queue. */
#if defined(LED_NEOPIXEL) || defined(LED_RGB_RED_PIN)
void neopixel_init(void);
void neopixel_write(uint8_t *pixels);
void neopixel_teardown(void);
#endif
//------------- 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)
{
@ -71,23 +44,12 @@ void board_init(void)
NRF_CLOCK->LFCLKSRC = CLOCK_LFCLKSRC_SRC_RC;
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
led_pwm_init(LED_PRIMARY, LED_PRIMARY_PIN);
#if LEDS_NUMBER > 1
led_pwm_init(LED_SECONDARY, LED_SECONDARY_PIN);
#endif
// use neopixel for use enumeration
#if defined(LED_NEOPIXEL) || defined(LED_RGB_RED_PIN)
neopixel_init();
#endif
// Init scheduler
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
led_pwm_teardown();
#if defined(LED_NEOPIXEL) || defined(LED_RGB_RED_PIN)
neopixel_teardown();
#endif
// Stop RTC1 used by app_timer
NVIC_DisableIRQ(RTC1_IRQn);
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;
#ifdef LED_SECONDARY_PIN
static uint32_t secondary_cycle_length;
#endif
void led_tick() {
uint32_t millis = _systick_count;
@ -225,41 +180,21 @@ void led_tick() {
duty_cycle = 0xff - duty_cycle;
#endif
led_pwm_duty_cycle(LED_PRIMARY, duty_cycle);
#ifdef LED_SECONDARY_PIN
cycle = millis % secondary_cycle_length;
half_cycle = secondary_cycle_length / 2;
if (cycle > half_cycle) {
cycle = secondary_cycle_length - cycle;
}
duty_cycle = 0x8f * cycle / half_cycle;
#if LED_STATE_ON == 1
duty_cycle = 0xff - duty_cycle;
#endif
led_pwm_duty_cycle(LED_SECONDARY, duty_cycle);
#endif
}
static uint32_t rgb_color;
static bool temp_color_active = false;
void led_state(uint32_t state)
{
uint32_t new_rgb_color = rgb_color;
uint32_t temp_color = 0;
switch (state) {
case STATE_USB_MOUNTED:
new_rgb_color = 0x00ff00;
primary_cycle_length = 3000;
break;
case STATE_BOOTLOADER_STARTED:
case STATE_USB_UNMOUNTED:
new_rgb_color = 0xff0000;
primary_cycle_length = 300;
break;
case STATE_WRITING_STARTED:
temp_color = 0xff0000;
primary_cycle_length = 100;
break;
@ -269,184 +204,14 @@ void led_state(uint32_t state)
break;
case STATE_BLE_CONNECTED:
new_rgb_color = 0x0000ff;
#ifdef LED_SECONDARY_PIN
secondary_cycle_length = 3000;
#else
primary_cycle_length = 3000;
#endif
break;
case STATE_BLE_DISCONNECTED:
new_rgb_color = 0xff00ff;
#ifdef LED_SECONDARY_PIN
secondary_cycle_length = 300;
#else
primary_cycle_length = 300;
#endif
break;
default:
break;
}
uint8_t* final_color = NULL;
new_rgb_color &= BOARD_RGB_BRIGHTNESS;
if (temp_color != 0){
temp_color &= BOARD_RGB_BRIGHTNESS;
final_color = (uint8_t*)&temp_color;
temp_color_active = true;
} else if (new_rgb_color != rgb_color) {
final_color = (uint8_t*)&new_rgb_color;
rgb_color = new_rgb_color;
} else if (temp_color_active) {
final_color = (uint8_t*)&rgb_color;
}
#if defined(LED_NEOPIXEL) || defined(LED_RGB_RED_PIN)
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

View File

@ -89,23 +89,6 @@ void led_pwm_enable(uint32_t led_index);
void led_state(uint32_t state);
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
//--------------------------------------------------------------------+

View File

@ -29,23 +29,19 @@
/* LED
*------------------------------------------------------------------*/
#define LEDS_NUMBER 1
#define LED_PRIMARY_PIN 4
// #define LED_PRIMARY_PIN 4
#define LED_PRIMARY_PIN 14
#define LED_STATE_ON 0
/*------------------------------------------------------------------*/
/* BUTTON
*------------------------------------------------------------------*/
#define BUTTONS_NUMBER 0
//--------------------------------------------------------------------+
// BLE OTA
//--------------------------------------------------------------------+
#define BLEDIS_MANUFACTURER "Betrusted"
#define BLEDIS_MODEL "Simmel"
#define LOOPBACK_TX_PIN 12
#define LOOPBACK_RX_PIN 11
//--------------------------------------------------------------------+
// USB
//--------------------------------------------------------------------+
#define USB_MANUFACTURER "Betrusted"
#define USB_MODEL "Simmel"
#define UF2_VOLUME_LABEL "SIMMEL_BOOT"
#define UF2_PRODUCT_NAME "Simmel"
#define UF2_BOARD_ID "nRF52833-simmel-v1"
#define UF2_INDEX_URL "https://github.com/simmel-project/"

View File

@ -43,66 +43,66 @@
#include "nrf_error.h"
#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. */
#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. */
#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. */
#endif
// #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. */
// #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. */
// #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. */
// #endif
/**@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.
*
* @retval NRF_SUCCES The data was set succesfully.
* @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)
{
if (p_peer_data == NULL)
{
return NRF_ERROR_NULL;
}
// /**@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.
// *
// * @retval NRF_SUCCES The data was set succesfully.
// * @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)
// {
// if (p_peer_data == NULL)
// {
// return NRF_ERROR_NULL;
// }
uint32_t src = (uint32_t)p_peer_data;
uint32_t dst = (uint32_t)&m_peer_data;
// 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
// written to destination so that when destination grows into source, the source data is no
// longer needed.
uint32_t len = dst - src;
// uint32_t src = (uint32_t)p_peer_data;
// uint32_t dst = (uint32_t)&m_peer_data;
// // 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
// // written to destination so that when destination grows into source, the source data is no
// // longer needed.
// uint32_t len = dst - src;
if (src == dst)
{
// Do nothing as source and destination are identical, just calculate crc below.
}
else if (len < sizeof(dfu_ble_peer_data_t))
{
uint32_t i = 0;
// if (src == dst)
// {
// // Do nothing as source and destination are identical, just calculate crc below.
// }
// else if (len < sizeof(dfu_ble_peer_data_t))
// {
// uint32_t i = 0;
dst += sizeof(dfu_ble_peer_data_t);
src += sizeof(dfu_ble_peer_data_t);
// dst += sizeof(dfu_ble_peer_data_t);
// src += sizeof(dfu_ble_peer_data_t);
// Copy byte wise backwards when facing overlapping structures.
while (i++ <= sizeof(dfu_ble_peer_data_t))
{
*((uint8_t *)dst--) = *((uint8_t *)src--);
}
}
else
{
memcpy((void *)dst, (void *)src, sizeof(dfu_ble_peer_data_t));
}
// // Copy byte wise backwards when facing overlapping structures.
// while (i++ <= sizeof(dfu_ble_peer_data_t))
// {
// *((uint8_t *)dst--) = *((uint8_t *)src--);
// }
// }
// else
// {
// 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).
@ -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)
{
switch (svc_num)
{
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]);
break;
// switch (svc_num)
// {
// 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]);
// break;
default:
// default:
p_svc_args[0] = NRF_ERROR_SVC_HANDLER_MISSING;
break;
}
// break;
// }
}
@ -209,25 +209,25 @@ void SVC_Handler(void)
#endif
uint32_t dfu_ble_peer_data_get(dfu_ble_peer_data_t * p_peer_data)
{
uint16_t crc;
// uint32_t dfu_ble_peer_data_get(dfu_ble_peer_data_t * p_peer_data)
// {
// uint16_t crc;
if (p_peer_data == NULL)
{
return NRF_ERROR_NULL;
}
// if (p_peer_data == NULL)
// {
// return NRF_ERROR_NULL;
// }
crc = crc16_compute((uint8_t *)&m_peer_data, sizeof(m_peer_data), NULL);
if (crc != m_peer_data_crc)
{
return NRF_ERROR_INVALID_DATA;
}
// crc = crc16_compute((uint8_t *)&m_peer_data, sizeof(m_peer_data), NULL);
// if (crc != m_peer_data_crc)
// {
// return NRF_ERROR_INVALID_DATA;
// }
*p_peer_data = m_peer_data;
// *p_peer_data = m_peer_data;
// corrupt CRC to invalidate shared information.
m_peer_data_crc++;
// // corrupt CRC to invalidate shared information.
// m_peer_data_crc++;
return NRF_SUCCESS;
}
// return NRF_SUCCESS;
// }

View File

@ -73,12 +73,12 @@
#include "nrf_usbd.h"
#include "tusb.h"
void usb_init(bool cdc_only);
void usb_init(void);
void usb_teardown(void);
#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()
#endif
@ -128,14 +128,13 @@ enum { BLE_CONN_CFG_HIGH_BANDWIDTH = 1 };
#ifdef NRF52840_XXAA
// Flash 1024 KB
STATIC_ASSERT( APPDATA_ADDR_START == 0xED000);
#else
// Flash 512 KB
STATIC_ASSERT( APPDATA_ADDR_START == 0x6D000);
STATIC_ASSERT( APPDATA_ADDR_START == 0x73000);
#endif
void adafruit_factory_reset(void);
// void adafruit_factory_reset(void);
uint32_t* dbl_reset_mem = ((uint32_t*) DFU_DBL_RESET_MEM );
@ -153,18 +152,48 @@ void softdev_mbr_init(void)
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)
{
// SD is already Initialized in case of BOOTLOADER_DFU_OTA_MAGIC
bool sd_inited = (NRF_POWER->GPREGRET == DFU_MAGIC_OTA_APPJUM);
// 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
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));
// Clear GPREGRET if it is our values
if (dfu_start) NRF_POWER->GPREGRET = 0;
@ -179,20 +208,20 @@ int main(void)
led_state(STATE_BOOTLOADER_STARTED);
// When updating SoftDevice, bootloader will reset before swapping SD
if (bootloader_dfu_sd_in_progress())
{
led_state(STATE_WRITING_STARTED);
// // When updating SoftDevice, bootloader will reset before swapping SD
// if (bootloader_dfu_sd_in_progress())
// {
// led_state(STATE_WRITING_STARTED);
APP_ERROR_CHECK( bootloader_dfu_sd_update_continue() );
APP_ERROR_CHECK( bootloader_dfu_sd_update_finalize() );
// APP_ERROR_CHECK( bootloader_dfu_sd_update_continue() );
// 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) -------------*/
// 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 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
(*dbl_reset_mem) = DFU_DBL_RESET_MAGIC;
#ifdef NRF52832_XXAA
/* Even DFU is not active, we still force an 1000 ms dfu serial mode when startup
* to support auto programming from Arduino IDE
*
* Note: 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.
*/
bootloader_dfu_start(DFU_SERIAL_STARTUP_INTERVAL);
#else
// if RST is pressed during this delay --> if will enter dfu
NRFX_DELAY_MS(DFU_DBL_RESET_DELAY);
#endif
// #ifdef NRF52832_XXAA
// /* Even DFU is not active, we still force an 1000 ms dfu serial mode when startup
// * to support auto programming from Arduino IDE
// *
// * Note: 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.
// */
// bootloader_dfu_start(DFU_SERIAL_STARTUP_INTERVAL);
// #else
// // if RST is pressed during this delay --> if will enter dfu
// NRFX_DELAY_MS(DFU_DBL_RESET_DELAY);
// #endif
}
if (APP_ASKS_FOR_SINGLE_TAP_RESET())
@ -225,22 +254,27 @@ int main(void)
else
(*dbl_reset_mem) = 0;
if ( dfu_start || !valid_app )
if ( dfu_start || !valid_app)
{
led_state(STATE_USB_UNMOUNTED);
usb_init(serial_only_dfu);
usb_init();
// 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();
}
// Adafruit Factory reset
if ( !button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) )
{
adafruit_factory_reset();
}
// // Adafruit Factory reset
// if ( !button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) )
// {
// adafruit_factory_reset();
// }
// Reset Board
board_teardown();
@ -263,23 +297,23 @@ int main(void)
}
// Perform factory reset to erase Application + Data
void adafruit_factory_reset(void)
{
led_state(STATE_FACTORY_RESET_STARTED);
// // 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);
}
// // 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);
// // 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);
}
// // back to normal
// led_state(STATE_FACTORY_RESET_FINISHED);
// }
//--------------------------------------------------------------------+

View File

@ -45,7 +45,7 @@
extern void tusb_hal_nrf_power_event(uint32_t event);
//------------- IMPLEMENTATION -------------//
void usb_init(bool cdc_only)
void usb_init(void)
{
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);
}
usb_desc_init(cdc_only);
usb_desc_init();
// Init TinyUSB stack
tusb_init();

View File

@ -33,9 +33,6 @@ enum {
ITF_STR_MSC
};
// CDC + MSC or CDC only mode
static bool _cdc_only = false;
// Serial is 64-bit DeviceID -> 16 chars len
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),
};
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
// 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)
{
(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
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 )
{
// Change PID to CDC only
desc_device.idProduct = USB_DESC_CDC_ONLY_PID;
serial = NRF_FICR->DEVICEID[1];
for (i = 0; i < 8; i++) {
desc_str_serial[i] = HEX_DIGITS[15 & (serial>>(i<<2))];
}
// Create Serial string descriptor
sprintf(desc_str_serial, "%08lX%08lX", NRF_FICR->DEVICEID[1], NRF_FICR->DEVICEID[0]);
serial = 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 [] =
{
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
BLEDIS_MANUFACTURER, // 1: Manufacturer
BLEDIS_MODEL, // 2: Product
USB_MANUFACTURER, // 1: Manufacturer
USB_MODEL, // 2: Product
desc_str_serial, // 3: Serials, should use chip ID
"nRF Serial", // 4: CDC Interface
"nRF UF2", // 5: MSC Interface

View File

@ -28,7 +28,7 @@
#include "tusb.h"
#include "boards.h"
void usb_desc_init(bool cdc_only);
void usb_desc_init(void);
#ifndef USB_DESC_VID
#define USB_DESC_VID 0x239A