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

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