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:
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_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
|
||||
|
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_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
|
||||
//--------------------------------------------------------------------+
|
||||
|
@ -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/"
|
||||
|
@ -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;
|
||||
// }
|
||||
|
134
src/main.c
134
src/main.c
@ -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);
|
||||
// }
|
||||
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user