2018-02-07 16:32:49 +00:00
|
|
|
/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* The information contained herein is property of Nordic Semiconductor ASA.
|
|
|
|
* Terms and conditions of usage are described in detail in NORDIC
|
|
|
|
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
|
|
|
|
*
|
|
|
|
* Licensees are granted free, non-transferable use of the information. NO
|
|
|
|
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
|
|
|
|
* the file.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**@file
|
|
|
|
*
|
|
|
|
* @defgroup ble_sdk_app_bootloader_main main.c
|
|
|
|
* @{
|
|
|
|
* @ingroup dfu_bootloader_api
|
|
|
|
* @brief Bootloader project main file.
|
|
|
|
*
|
|
|
|
* -# Receive start data packet.
|
|
|
|
* -# Based on start packet, prepare NVM area to store received data.
|
|
|
|
* -# Receive data packet.
|
|
|
|
* -# Validate data packet.
|
|
|
|
* -# Write Data packet to NVM.
|
|
|
|
* -# If not finished - Wait for next packet.
|
|
|
|
* -# Receive stop data packet.
|
|
|
|
* -# Activate Image, boot application.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stddef.h>
|
2018-08-07 15:00:35 +00:00
|
|
|
|
2018-08-07 06:33:44 +00:00
|
|
|
#include "nrfx.h"
|
|
|
|
#include "nrfx_power.h"
|
2018-08-13 17:56:51 +00:00
|
|
|
#include "nrfx_pwm.h"
|
2018-02-07 16:32:49 +00:00
|
|
|
|
2018-02-15 09:27:51 +00:00
|
|
|
#include "nordic_common.h"
|
|
|
|
#include "sdk_common.h"
|
2018-02-07 16:32:49 +00:00
|
|
|
#include "dfu_transport.h"
|
|
|
|
#include "bootloader.h"
|
|
|
|
#include "bootloader_util.h"
|
|
|
|
|
|
|
|
#include "nrf.h"
|
|
|
|
#include "nrf_soc.h"
|
2018-04-03 16:53:38 +00:00
|
|
|
#include "nrf_nvic.h"
|
2018-02-07 16:32:49 +00:00
|
|
|
#include "app_error.h"
|
|
|
|
#include "nrf_gpio.h"
|
|
|
|
#include "ble.h"
|
|
|
|
#include "nrf.h"
|
|
|
|
#include "ble_hci.h"
|
|
|
|
#include "app_scheduler.h"
|
2018-02-15 09:27:51 +00:00
|
|
|
#include "app_timer.h"
|
2018-02-07 16:32:49 +00:00
|
|
|
#include "nrf_error.h"
|
2018-08-07 15:00:35 +00:00
|
|
|
|
2018-08-08 08:19:02 +00:00
|
|
|
#include "boards.h"
|
2018-02-07 16:32:49 +00:00
|
|
|
|
|
|
|
#include "pstorage_platform.h"
|
|
|
|
#include "nrf_mbr.h"
|
|
|
|
#include "nrf_wdt.h"
|
|
|
|
#include "pstorage.h"
|
|
|
|
|
2018-08-08 09:55:57 +00:00
|
|
|
#include "nrf_nvmc.h"
|
|
|
|
|
2018-08-06 13:28:20 +00:00
|
|
|
#ifdef NRF52840_XXAA
|
2018-04-16 10:29:24 +00:00
|
|
|
#include "nrf_usbd.h"
|
2018-06-18 09:54:41 +00:00
|
|
|
#include "tusb.h"
|
2018-06-20 08:28:30 +00:00
|
|
|
#include "usb/msc_uf2.h"
|
2018-04-25 08:57:31 +00:00
|
|
|
|
2018-08-06 13:46:53 +00:00
|
|
|
void usb_init(void);
|
2018-08-06 15:02:29 +00:00
|
|
|
void usb_teardown(void);
|
2018-08-06 13:46:53 +00:00
|
|
|
|
2018-08-06 15:02:29 +00:00
|
|
|
#else
|
|
|
|
|
|
|
|
#define usb_init()
|
|
|
|
#define usb_teardown()
|
|
|
|
|
2018-08-06 13:28:20 +00:00
|
|
|
#endif
|
|
|
|
|
2018-02-07 16:32:49 +00:00
|
|
|
|
|
|
|
#define BOOTLOADER_VERSION_REGISTER NRF_TIMER2->CC[0]
|
|
|
|
|
|
|
|
#define LED_BLINK_INTERVAL 100
|
|
|
|
#define BOOTLOADER_STARTUP_DFU_INTERVAL 1000
|
|
|
|
|
|
|
|
/* Magic that written to NRF_POWER->GPREGRET by application when it wish to go into DFU
|
|
|
|
* - BOOTLOADER_DFU_OTA_MAGIC used by BLEDfu service : SD is already init
|
|
|
|
* - BOOTLOADER_DFU_OTA_FULLRESET_MAGIC entered by soft reset : SD is not init
|
|
|
|
* - BOOTLOADER_DFU_SERIAL_MAGIC entered by soft reset : SD is not init
|
|
|
|
*
|
|
|
|
* Note: for BOOTLOADER_DFU_OTA_MAGIC Softdevice should not initialized. In other case SD must be initialized
|
|
|
|
*/
|
|
|
|
#define BOOTLOADER_DFU_OTA_MAGIC BOOTLOADER_DFU_START // 0xB1
|
|
|
|
#define BOOTLOADER_DFU_OTA_FULLRESET_MAGIC 0xA8
|
|
|
|
#define BOOTLOADER_DFU_SERIAL_MAGIC 0x4e
|
|
|
|
|
2018-08-07 18:03:33 +00:00
|
|
|
#define BUTTON_DFU BUTTON_1 // Button used to enter SW update mode.
|
|
|
|
#define BUTTON_FRESET BUTTON_2 // Button used in addition to DFU button, to force OTA DFU
|
2018-02-07 16:32:49 +00:00
|
|
|
|
2018-02-15 09:27:51 +00:00
|
|
|
#define SCHED_MAX_EVENT_DATA_SIZE sizeof(app_timer_event_t) /**< Maximum size of scheduler events. */
|
2018-04-14 05:15:50 +00:00
|
|
|
#define SCHED_QUEUE_SIZE 30 /**< Maximum number of events in the scheduler queue. */
|
2018-02-07 16:32:49 +00:00
|
|
|
|
|
|
|
// Helper function
|
|
|
|
#define memclr(buffer, size) memset(buffer, 0, size)
|
|
|
|
#define varclr(_var) memclr(_var, sizeof(*(_var)))
|
|
|
|
#define arrclr(_arr) memclr(_arr, sizeof(_arr))
|
|
|
|
#define arrcount(_arr) ( sizeof(_arr) / sizeof(_arr[0]) )
|
|
|
|
|
|
|
|
|
|
|
|
// These value must be the same with one in dfu_transport_ble.c
|
|
|
|
#define BLEGAP_EVENT_LENGTH 6
|
|
|
|
#define BLEGATT_ATT_MTU_MAX 247
|
|
|
|
enum { BLE_CONN_CFG_HIGH_BANDWIDTH = 1 };
|
|
|
|
|
|
|
|
// Adafruit for factory reset
|
|
|
|
#define APPDATA_ADDR_START (BOOTLOADER_REGION_START-DFU_APP_DATA_RESERVED)
|
2018-08-06 15:02:29 +00:00
|
|
|
|
|
|
|
#ifdef NRF52840_XXAA
|
2018-02-09 16:06:27 +00:00
|
|
|
STATIC_ASSERT( APPDATA_ADDR_START == 0xED000);
|
2018-08-06 15:02:29 +00:00
|
|
|
#else
|
|
|
|
STATIC_ASSERT( APPDATA_ADDR_START == 0x6D000);
|
|
|
|
#endif
|
2018-04-19 12:15:19 +00:00
|
|
|
|
2018-02-07 16:32:49 +00:00
|
|
|
|
|
|
|
void adafruit_factory_reset(void);
|
2018-08-08 09:55:57 +00:00
|
|
|
|
2018-02-07 16:32:49 +00:00
|
|
|
/*
|
2018-08-13 17:56:51 +00:00
|
|
|
* Blinking patterns:
|
2018-02-07 16:32:49 +00:00
|
|
|
* - DFU Serial : LED Status blink
|
|
|
|
* - DFU OTA : LED Status & Conn blink at the same time
|
|
|
|
* - DFU Flashing : LED Status blink 2x fast
|
|
|
|
* - Factory Reset : LED Status blink 2x fast
|
|
|
|
* - Fatal Error : LED Status & Conn blink one after another
|
|
|
|
*/
|
2018-08-13 17:56:51 +00:00
|
|
|
bool _ota_connected = false;
|
2018-02-07 16:32:49 +00:00
|
|
|
|
2018-08-13 17:56:51 +00:00
|
|
|
// true if ble, false if serial
|
|
|
|
bool _ota_update = false;
|
2018-02-07 16:32:49 +00:00
|
|
|
|
2018-08-13 17:56:51 +00:00
|
|
|
bool is_ota(void) { return _ota_update; }
|
2018-02-07 16:32:49 +00:00
|
|
|
|
2018-08-13 17:56:51 +00:00
|
|
|
#define PWM_MAXCOUNT 25000
|
|
|
|
uint16_t _pwm_red_seq0 [NRF_PWM_CHANNEL_COUNT] = { PWM_MAXCOUNT/2, 0, 0 , 0 };
|
|
|
|
uint16_t _pwm_blue_seq0[NRF_PWM_CHANNEL_COUNT] = { PWM_MAXCOUNT/2, 0, 0 , 0 };
|
2018-02-07 16:32:49 +00:00
|
|
|
|
2018-08-13 17:56:51 +00:00
|
|
|
void led_blink_fast(bool enable)
|
|
|
|
{
|
|
|
|
if ( enable )
|
2018-02-07 16:32:49 +00:00
|
|
|
{
|
2018-08-13 17:56:51 +00:00
|
|
|
NRF_PWM0->MODE = PWM_MODE_UPDOWN_Up;
|
|
|
|
}else
|
2018-02-07 16:32:49 +00:00
|
|
|
{
|
2018-08-13 17:56:51 +00:00
|
|
|
NRF_PWM0->MODE = PWM_MODE_UPDOWN_UpAndDown;
|
2018-02-07 16:32:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-13 17:56:51 +00:00
|
|
|
/* use PWM for blinky to prevent inconsistency due to MCU blocking in flash operation
|
|
|
|
* clock = 125khz --> resolution = 8us
|
|
|
|
* top value = 25000 -> period = 200 ms (fast blink) --> up and down mode = 400 ms ( slow blink )
|
|
|
|
*/
|
|
|
|
void led_pwm_init(NRF_PWM_Type* pwm, uint32_t led_pin)
|
2018-08-07 17:33:22 +00:00
|
|
|
{
|
2018-08-13 17:56:51 +00:00
|
|
|
pwm->MODE = PWM_MODE_UPDOWN_UpAndDown;
|
|
|
|
pwm->COUNTERTOP = PWM_MAXCOUNT;
|
|
|
|
pwm->PRESCALER = PWM_PRESCALER_PRESCALER_DIV_128;
|
|
|
|
pwm->DECODER = PWM_DECODER_LOAD_Individual;
|
|
|
|
pwm->LOOP = 0;
|
|
|
|
|
|
|
|
pwm->SEQ[0].PTR = (uint32_t) (led_pin == LED_RED ? _pwm_red_seq0 : _pwm_blue_seq0);
|
|
|
|
pwm->SEQ[0].CNT = NRF_PWM_CHANNEL_COUNT; // default mode is Individual --> count must be 4
|
|
|
|
pwm->SEQ[0].REFRESH = 0;
|
|
|
|
pwm->SEQ[0].ENDDELAY = 0;
|
|
|
|
|
|
|
|
pwm->PSEL.OUT[0] = led_pin;
|
|
|
|
|
|
|
|
pwm->ENABLE = 1;
|
|
|
|
pwm->TASKS_SEQSTART[0] = 1;
|
2018-08-07 17:33:22 +00:00
|
|
|
}
|
|
|
|
|
2018-08-13 17:56:51 +00:00
|
|
|
void led_pwm_teardown(NRF_PWM_Type* pwm)
|
2018-02-07 16:32:49 +00:00
|
|
|
{
|
2018-08-13 17:56:51 +00:00
|
|
|
pwm->TASKS_SEQSTART[0] = 0;
|
|
|
|
pwm->ENABLE = 0;
|
|
|
|
|
|
|
|
pwm->PSEL.OUT[0] = 0xFFFFFFFF;
|
|
|
|
|
|
|
|
pwm->MODE = 0;
|
|
|
|
pwm->COUNTERTOP = 0x3FF;
|
|
|
|
pwm->PRESCALER = 0;
|
|
|
|
pwm->DECODER = 0;
|
|
|
|
pwm->LOOP = 0;
|
|
|
|
pwm->SEQ[0].PTR = 0;
|
|
|
|
pwm->SEQ[0].CNT = 0;
|
2018-02-07 16:32:49 +00:00
|
|
|
}
|
|
|
|
|
2018-08-06 13:28:20 +00:00
|
|
|
void board_init(void)
|
|
|
|
{
|
2018-08-13 17:56:51 +00:00
|
|
|
// stop WDT if started by application, when jumping from application using BLE DFU
|
|
|
|
if ( NRF_WDT->RUNSTATUS )
|
|
|
|
{
|
|
|
|
NRF_WDT->TASKS_START = 0;
|
|
|
|
}
|
|
|
|
|
2018-08-07 18:03:33 +00:00
|
|
|
button_init(BUTTON_DFU);
|
|
|
|
button_init(BUTTON_FRESET);
|
2018-08-07 05:55:42 +00:00
|
|
|
NRFX_DELAY_US(100); // wait for the pin state is stable
|
2018-08-06 13:28:20 +00:00
|
|
|
|
2018-08-07 15:00:35 +00:00
|
|
|
// LED init
|
|
|
|
nrf_gpio_cfg_output(LED_RED);
|
|
|
|
nrf_gpio_cfg_output(LED_BLUE);
|
|
|
|
led_off(LED_RED);
|
|
|
|
led_off(LED_BLUE);
|
2018-08-06 13:28:20 +00:00
|
|
|
|
2018-08-13 17:56:51 +00:00
|
|
|
// use PMW0 for LED RED
|
|
|
|
led_pwm_init(NRF_PWM0, LED_RED);
|
|
|
|
|
2018-08-07 17:33:22 +00:00
|
|
|
// Init scheduler
|
2018-08-06 13:28:20 +00:00
|
|
|
APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
|
|
|
|
}
|
|
|
|
|
2018-08-07 17:33:22 +00:00
|
|
|
void board_teardown(void)
|
|
|
|
{
|
2018-08-13 17:56:51 +00:00
|
|
|
// Disable and reset PWM for LED
|
|
|
|
led_pwm_teardown(NRF_PWM0);
|
|
|
|
|
|
|
|
if ( is_ota() ) led_pwm_teardown(NRF_PWM1);
|
2018-08-06 13:28:20 +00:00
|
|
|
|
2018-08-07 17:33:22 +00:00
|
|
|
led_off(LED_BLUE);
|
|
|
|
led_off(LED_RED);
|
2018-08-06 13:28:20 +00:00
|
|
|
|
2018-08-07 17:33:22 +00:00
|
|
|
// Stop RTC1 used by app_timer
|
|
|
|
NVIC_DisableIRQ(RTC1_IRQn);
|
|
|
|
NRF_RTC1->EVTENCLR = RTC_EVTEN_COMPARE0_Msk;
|
|
|
|
NRF_RTC1->INTENCLR = RTC_INTENSET_COMPARE0_Msk;
|
|
|
|
NRF_RTC1->TASKS_STOP = 1;
|
|
|
|
NRF_RTC1->TASKS_CLEAR = 1;
|
|
|
|
|
|
|
|
// disable usb
|
|
|
|
usb_teardown();
|
|
|
|
}
|
|
|
|
|
2018-08-11 04:43:57 +00:00
|
|
|
void softdev_mbr_init(void)
|
|
|
|
{
|
|
|
|
sd_mbr_command_t com = { .command = SD_MBR_COMMAND_INIT_SD };
|
|
|
|
sd_mbr_command(&com);
|
|
|
|
}
|
2018-08-07 17:33:22 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Initializes the SoftDevice and the BLE event interrupt.
|
2018-02-07 16:32:49 +00:00
|
|
|
* @param[in] init_softdevice true if SoftDevice should be initialized. The SoftDevice must only
|
2018-08-08 09:55:57 +00:00
|
|
|
* be initialized if a chip reset has occured. Soft reset (jump ) from
|
2018-02-07 16:32:49 +00:00
|
|
|
* application must not reinitialize the SoftDevice.
|
|
|
|
*/
|
2018-08-13 17:56:51 +00:00
|
|
|
static uint32_t softdev_init(bool init_softdevice)
|
2018-02-07 16:32:49 +00:00
|
|
|
{
|
2018-08-11 04:43:57 +00:00
|
|
|
if (init_softdevice) softdev_mbr_init();
|
2018-04-03 16:53:38 +00:00
|
|
|
|
2018-08-08 09:55:57 +00:00
|
|
|
// map vector table to bootloader address
|
2018-05-25 14:33:47 +00:00
|
|
|
APP_ERROR_CHECK( sd_softdevice_vector_table_base_set(BOOTLOADER_REGION_START) );
|
2018-04-03 16:53:38 +00:00
|
|
|
|
|
|
|
// Enable Softdevice
|
|
|
|
nrf_clock_lf_cfg_t clock_cfg =
|
2018-02-07 16:32:49 +00:00
|
|
|
{
|
2018-08-07 09:51:08 +00:00
|
|
|
#ifdef NRF52840_XXAA // TODO use xtal source for feather52832
|
2018-02-15 09:27:51 +00:00
|
|
|
.source = NRF_CLOCK_LF_SRC_XTAL,
|
|
|
|
.rc_ctiv = 0,
|
|
|
|
.rc_temp_ctiv = 0,
|
|
|
|
.accuracy = NRF_CLOCK_LF_ACCURACY_20_PPM
|
2018-08-07 09:51:08 +00:00
|
|
|
#else
|
|
|
|
.source = NRF_CLOCK_LF_SRC_RC,
|
|
|
|
.rc_ctiv = 16,
|
|
|
|
.rc_temp_ctiv = 2,
|
|
|
|
.accuracy = NRF_CLOCK_LF_ACCURACY_20_PPM
|
2018-02-15 09:27:51 +00:00
|
|
|
#endif
|
2018-02-07 16:32:49 +00:00
|
|
|
};
|
|
|
|
|
2018-04-04 10:39:26 +00:00
|
|
|
APP_ERROR_CHECK( sd_softdevice_enable(&clock_cfg, app_error_fault_handler) );
|
2018-04-03 16:53:38 +00:00
|
|
|
sd_nvic_EnableIRQ(SD_EVT_IRQn);
|
2018-02-07 16:32:49 +00:00
|
|
|
|
|
|
|
/*------------- Configure BLE params -------------*/
|
|
|
|
extern uint32_t __data_start__[]; // defined in linker
|
|
|
|
uint32_t ram_start = (uint32_t) __data_start__;
|
|
|
|
|
|
|
|
ble_cfg_t blecfg;
|
|
|
|
|
|
|
|
// Configure the maximum number of connections.
|
|
|
|
varclr(&blecfg);
|
|
|
|
blecfg.gap_cfg.role_count_cfg.periph_role_count = 1;
|
|
|
|
blecfg.gap_cfg.role_count_cfg.central_role_count = 0;
|
|
|
|
blecfg.gap_cfg.role_count_cfg.central_sec_count = 0;
|
2018-05-25 14:33:47 +00:00
|
|
|
APP_ERROR_CHECK( sd_ble_cfg_set(BLE_GAP_CFG_ROLE_COUNT, &blecfg, ram_start) );
|
2018-02-07 16:32:49 +00:00
|
|
|
|
|
|
|
// NRF_DFU_BLE_REQUIRES_BONDS
|
|
|
|
varclr(&blecfg);
|
|
|
|
blecfg.gatts_cfg.service_changed.service_changed = 1;
|
2018-05-25 14:33:47 +00:00
|
|
|
APP_ERROR_CHECK( sd_ble_cfg_set(BLE_GATTS_CFG_SERVICE_CHANGED, &blecfg, ram_start) );
|
2018-02-07 16:32:49 +00:00
|
|
|
|
|
|
|
// ATT MTU
|
|
|
|
varclr(&blecfg);
|
|
|
|
blecfg.conn_cfg.conn_cfg_tag = BLE_CONN_CFG_HIGH_BANDWIDTH;
|
|
|
|
blecfg.conn_cfg.params.gatt_conn_cfg.att_mtu = BLEGATT_ATT_MTU_MAX;
|
2018-05-25 14:33:47 +00:00
|
|
|
APP_ERROR_CHECK( sd_ble_cfg_set(BLE_CONN_CFG_GATT, &blecfg, ram_start) );
|
2018-02-07 16:32:49 +00:00
|
|
|
|
|
|
|
// Event Length + HVN queue + WRITE CMD queue setting affecting bandwidth
|
|
|
|
varclr(&blecfg);
|
|
|
|
blecfg.conn_cfg.conn_cfg_tag = BLE_CONN_CFG_HIGH_BANDWIDTH;
|
|
|
|
blecfg.conn_cfg.params.gap_conn_cfg.conn_count = 1;
|
|
|
|
blecfg.conn_cfg.params.gap_conn_cfg.event_length = BLEGAP_EVENT_LENGTH;
|
2018-05-25 14:33:47 +00:00
|
|
|
APP_ERROR_CHECK( sd_ble_cfg_set(BLE_CONN_CFG_GAP, &blecfg, ram_start) );
|
2018-02-07 16:32:49 +00:00
|
|
|
|
|
|
|
// Enable BLE stack.
|
2018-08-08 11:01:09 +00:00
|
|
|
// Note: Interrupt state (enabled, forwarding) is not work properly if not enable ble
|
2018-05-25 14:33:47 +00:00
|
|
|
APP_ERROR_CHECK( sd_ble_enable(&ram_start) );
|
2018-02-07 16:32:49 +00:00
|
|
|
|
2018-05-25 14:33:47 +00:00
|
|
|
return NRF_SUCCESS;
|
2018-02-07 16:32:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int main(void)
|
|
|
|
{
|
|
|
|
// SD is already Initialized in case of BOOTLOADER_DFU_OTA_MAGIC
|
2018-08-11 04:43:57 +00:00
|
|
|
bool sd_inited = (NRF_POWER->GPREGRET == BOOTLOADER_DFU_OTA_MAGIC);
|
2018-02-07 16:32:49 +00:00
|
|
|
|
|
|
|
// Start Bootloader in BLE OTA mode
|
|
|
|
_ota_update = (NRF_POWER->GPREGRET == BOOTLOADER_DFU_OTA_MAGIC) ||
|
|
|
|
(NRF_POWER->GPREGRET == BOOTLOADER_DFU_OTA_FULLRESET_MAGIC);
|
|
|
|
|
|
|
|
// start bootloader either serial or ble
|
|
|
|
bool dfu_start = _ota_update || (NRF_POWER->GPREGRET == BOOTLOADER_DFU_SERIAL_MAGIC);
|
|
|
|
|
2018-04-04 10:39:26 +00:00
|
|
|
// Clear GPREGRET if it is our values
|
|
|
|
if (dfu_start) NRF_POWER->GPREGRET = 0;
|
2018-02-07 16:32:49 +00:00
|
|
|
|
|
|
|
// Save bootloader version to pre-defined register, retrieved by application
|
2018-08-07 10:00:33 +00:00
|
|
|
BOOTLOADER_VERSION_REGISTER = (MK_BOOTLOADER_VERSION);
|
2018-02-07 16:32:49 +00:00
|
|
|
|
2018-08-08 10:14:58 +00:00
|
|
|
// This check ensures that the defined fields in the bootloader corresponds with actual setting in the chip.
|
2018-02-07 16:32:49 +00:00
|
|
|
APP_ERROR_CHECK_BOOL(*((uint32_t *)NRF_UICR_BOOT_START_ADDRESS) == BOOTLOADER_REGION_START);
|
|
|
|
|
2018-08-06 13:28:20 +00:00
|
|
|
board_init();
|
2018-08-07 17:33:22 +00:00
|
|
|
bootloader_init();
|
2018-05-11 13:34:17 +00:00
|
|
|
|
2018-08-13 14:50:55 +00:00
|
|
|
// When updating SoftDevice, bootloader will reset before swapping SD
|
2018-02-07 16:32:49 +00:00
|
|
|
if (bootloader_dfu_sd_in_progress())
|
|
|
|
{
|
2018-05-25 14:33:47 +00:00
|
|
|
APP_ERROR_CHECK( bootloader_dfu_sd_update_continue() );
|
|
|
|
APP_ERROR_CHECK( bootloader_dfu_sd_update_finalize() );
|
2018-02-07 16:32:49 +00:00
|
|
|
}
|
2018-04-04 13:03:56 +00:00
|
|
|
|
2018-04-04 10:39:26 +00:00
|
|
|
/*------------- Determine DFU mode (Serial, OTA, FRESET or normal) -------------*/
|
2018-02-07 16:32:49 +00:00
|
|
|
// DFU button pressed
|
2018-08-07 18:03:33 +00:00
|
|
|
dfu_start = dfu_start || button_pressed(BUTTON_DFU);
|
2018-02-07 16:32:49 +00:00
|
|
|
|
|
|
|
// DFU + FRESET are pressed --> OTA
|
2018-08-07 18:03:33 +00:00
|
|
|
_ota_update = _ota_update || ( button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) ) ;
|
2018-02-07 16:32:49 +00:00
|
|
|
|
2018-08-07 18:03:33 +00:00
|
|
|
if ( dfu_start || !bootloader_app_is_valid(DFU_BANK_0_REGION_START) )
|
2018-02-07 16:32:49 +00:00
|
|
|
{
|
2018-08-11 04:43:57 +00:00
|
|
|
if ( _ota_update )
|
|
|
|
{
|
2018-08-13 17:56:51 +00:00
|
|
|
// Enable BLE if in OTA
|
|
|
|
led_pwm_init(NRF_PWM1, LED_BLUE);
|
|
|
|
|
2018-08-11 04:43:57 +00:00
|
|
|
softdev_init(!sd_inited);
|
|
|
|
sd_inited = true;
|
2018-08-13 17:56:51 +00:00
|
|
|
|
|
|
|
// Init app timer (use RTC1)
|
|
|
|
app_timer_init();
|
2018-08-11 04:43:57 +00:00
|
|
|
}
|
2018-08-13 17:56:51 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// Init app timer (use RTC1)
|
|
|
|
app_timer_init();
|
2018-08-11 04:43:57 +00:00
|
|
|
|
2018-08-13 17:56:51 +00:00
|
|
|
// otherwise USB for Serial & UF2
|
|
|
|
usb_init();
|
|
|
|
}
|
2018-08-08 11:01:09 +00:00
|
|
|
|
2018-02-07 16:32:49 +00:00
|
|
|
// Initiate an update of the firmware.
|
2018-05-25 14:33:47 +00:00
|
|
|
APP_ERROR_CHECK( bootloader_dfu_start(_ota_update, 0) );
|
2018-08-13 14:50:55 +00:00
|
|
|
|
|
|
|
if ( _ota_update ) sd_softdevice_disable();
|
2018-02-07 16:32:49 +00:00
|
|
|
}
|
2018-08-07 09:51:08 +00:00
|
|
|
#ifdef NRF52832_XXAA
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Adafruit Modification
|
|
|
|
* Even DFU is not active, we still force an 1000 ms dfu serial mode when startup
|
|
|
|
* to support auto programming from Arduino IDE */
|
2018-08-07 17:33:22 +00:00
|
|
|
bootloader_dfu_start(false, BOOTLOADER_STARTUP_DFU_INTERVAL);
|
2018-08-07 09:51:08 +00:00
|
|
|
}
|
|
|
|
#endif
|
2018-02-07 16:32:49 +00:00
|
|
|
|
2018-04-04 10:39:26 +00:00
|
|
|
/*------------- Adafruit Factory reset -------------*/
|
2018-08-07 18:03:33 +00:00
|
|
|
if ( !button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) )
|
|
|
|
{
|
|
|
|
adafruit_factory_reset();
|
|
|
|
}
|
2018-02-07 16:32:49 +00:00
|
|
|
|
2018-08-07 18:03:33 +00:00
|
|
|
/*------------- Reset used prph and jump to application -------------*/
|
2018-08-07 17:33:22 +00:00
|
|
|
board_teardown();
|
2018-04-20 05:58:17 +00:00
|
|
|
|
2018-02-07 16:32:49 +00:00
|
|
|
if (bootloader_app_is_valid(DFU_BANK_0_REGION_START) && !bootloader_dfu_sd_in_progress())
|
|
|
|
{
|
2018-08-11 04:43:57 +00:00
|
|
|
// MBR must be init before start application
|
|
|
|
if ( !sd_inited ) softdev_mbr_init();
|
|
|
|
|
2018-02-07 16:32:49 +00:00
|
|
|
// Select a bank region to use as application region.
|
|
|
|
// @note: Only applications running from DFU_BANK_0_REGION_START is supported.
|
|
|
|
bootloader_app_start(DFU_BANK_0_REGION_START);
|
|
|
|
}
|
|
|
|
|
|
|
|
NVIC_SystemReset();
|
|
|
|
}
|
|
|
|
|
2018-04-05 11:35:30 +00:00
|
|
|
|
2018-08-07 17:33:22 +00:00
|
|
|
//--------------------------------------------------------------------+
|
|
|
|
// FACTORY RESET
|
|
|
|
//--------------------------------------------------------------------+
|
|
|
|
|
|
|
|
// Perform factory reset to erase Application + Data
|
2018-02-07 16:32:49 +00:00
|
|
|
void adafruit_factory_reset(void)
|
|
|
|
{
|
|
|
|
// Blink fast RED and turn on BLUE when erasing
|
2018-08-07 17:41:41 +00:00
|
|
|
led_blink_fast(true);
|
2018-02-07 16:32:49 +00:00
|
|
|
led_on(LED_BLUE);
|
|
|
|
|
2018-08-08 09:55:57 +00:00
|
|
|
// clear all App Data if any
|
|
|
|
if ( DFU_APP_DATA_RESERVED )
|
|
|
|
{
|
|
|
|
nrf_nvmc_page_erase(APPDATA_ADDR_START);
|
|
|
|
}
|
2018-02-07 16:32:49 +00:00
|
|
|
|
|
|
|
// Only need to erase the 1st page of Application code to make it invalid
|
2018-08-08 09:55:57 +00:00
|
|
|
nrf_nvmc_page_erase(DFU_BANK_0_REGION_START);
|
2018-02-07 16:32:49 +00:00
|
|
|
|
|
|
|
// back to normal
|
2018-08-07 17:41:41 +00:00
|
|
|
led_blink_fast(false);
|
2018-02-07 16:32:49 +00:00
|
|
|
led_off(LED_BLUE);
|
|
|
|
}
|
2018-04-02 06:11:21 +00:00
|
|
|
|
2018-04-05 11:35:30 +00:00
|
|
|
//--------------------------------------------------------------------+
|
|
|
|
// Error Handler
|
|
|
|
//--------------------------------------------------------------------+
|
2018-04-02 06:11:21 +00:00
|
|
|
void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info)
|
|
|
|
{
|
2018-08-06 15:02:29 +00:00
|
|
|
volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */
|
|
|
|
if ( (*ARM_CM_DHCSR) & 1UL ) __asm("BKPT #0\n"); /* Only halt mcu if debugger is attached */
|
2018-04-02 06:11:21 +00:00
|
|
|
NVIC_SystemReset();
|
|
|
|
}
|
|
|
|
|
2018-04-04 10:39:26 +00:00
|
|
|
void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
|
|
|
|
{
|
2018-05-25 14:33:47 +00:00
|
|
|
app_error_handler(0xDEADBEEF, line_num, p_file_name);
|
2018-04-04 10:39:26 +00:00
|
|
|
}
|
|
|
|
|
2018-04-02 06:11:21 +00:00
|
|
|
uint32_t tusb_hal_millis(void)
|
|
|
|
{
|
|
|
|
return ( ( ((uint64_t)app_timer_cnt_get())*1000*(APP_TIMER_CONFIG_RTC_FREQUENCY+1)) / APP_TIMER_CLOCK_FREQ );
|
|
|
|
}
|
2018-04-03 16:53:38 +00:00
|
|
|
|
2018-04-14 05:15:50 +00:00
|
|
|
/*------------------------------------------------------------------*/
|
|
|
|
/* SoftDevice Event handler
|
|
|
|
*------------------------------------------------------------------*/
|
2018-08-07 15:09:51 +00:00
|
|
|
|
2018-08-07 17:33:22 +00:00
|
|
|
// Process BLE event from SD
|
2018-04-14 05:15:50 +00:00
|
|
|
uint32_t proc_ble(void)
|
2018-04-03 16:53:38 +00:00
|
|
|
{
|
|
|
|
__ALIGN(4) uint8_t ev_buf[ BLE_EVT_LEN_MAX(BLEGATT_ATT_MTU_MAX) ];
|
2018-04-14 05:15:50 +00:00
|
|
|
uint16_t ev_len = BLE_EVT_LEN_MAX(BLEGATT_ATT_MTU_MAX);
|
2018-04-03 16:53:38 +00:00
|
|
|
|
2018-04-14 05:15:50 +00:00
|
|
|
// Get BLE Event
|
|
|
|
uint32_t err = sd_ble_evt_get(ev_buf, &ev_len);
|
2018-04-03 16:53:38 +00:00
|
|
|
|
2018-04-14 05:15:50 +00:00
|
|
|
// Handle valid event, ignore error
|
|
|
|
if( NRF_SUCCESS == err)
|
2018-04-03 16:53:38 +00:00
|
|
|
{
|
2018-08-07 15:09:51 +00:00
|
|
|
ble_evt_t* evt = (ble_evt_t*) ev_buf;
|
|
|
|
|
|
|
|
switch (evt->header.evt_id)
|
|
|
|
{
|
|
|
|
case BLE_GAP_EVT_CONNECTED:
|
|
|
|
_ota_connected = true;
|
2018-08-13 17:56:51 +00:00
|
|
|
_pwm_blue_seq0[0] = PWM_MAXCOUNT;
|
2018-08-07 15:09:51 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case BLE_GAP_EVT_DISCONNECTED:
|
|
|
|
_ota_connected = false;
|
2018-08-13 17:56:51 +00:00
|
|
|
_pwm_blue_seq0[0] = PWM_MAXCOUNT/2;
|
2018-08-07 15:09:51 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
|
2018-05-25 14:33:47 +00:00
|
|
|
// from dfu_transport_ble
|
|
|
|
extern void ble_evt_dispatch(ble_evt_t * p_ble_evt);
|
|
|
|
ble_evt_dispatch(evt);
|
2018-04-14 05:15:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
2018-04-03 16:53:38 +00:00
|
|
|
|
2018-08-07 17:33:22 +00:00
|
|
|
// process SOC event from SD
|
2018-04-14 05:15:50 +00:00
|
|
|
uint32_t proc_soc(void)
|
|
|
|
{
|
|
|
|
uint32_t soc_evt;
|
|
|
|
uint32_t err = sd_evt_get(&soc_evt);
|
2018-04-03 16:53:38 +00:00
|
|
|
|
2018-04-14 05:15:50 +00:00
|
|
|
if (NRF_SUCCESS == err)
|
|
|
|
{
|
|
|
|
pstorage_sys_event_handler(soc_evt);
|
2018-05-14 07:20:37 +00:00
|
|
|
|
2018-08-06 15:02:29 +00:00
|
|
|
#ifdef NRF52840_XXAA
|
2018-08-07 09:51:08 +00:00
|
|
|
extern void tusb_hal_nrf_power_event(uint32_t event);
|
2018-05-14 07:20:37 +00:00
|
|
|
/*------------- usb power event handler -------------*/
|
|
|
|
int32_t usbevt = (soc_evt == NRF_EVT_POWER_USB_DETECTED ) ? NRFX_POWER_USB_EVT_DETECTED:
|
|
|
|
(soc_evt == NRF_EVT_POWER_USB_POWER_READY) ? NRFX_POWER_USB_EVT_READY :
|
|
|
|
(soc_evt == NRF_EVT_POWER_USB_REMOVED ) ? NRFX_POWER_USB_EVT_REMOVED : -1;
|
|
|
|
|
|
|
|
if ( usbevt >= 0) tusb_hal_nrf_power_event(usbevt);
|
2018-08-06 15:02:29 +00:00
|
|
|
#endif
|
2018-04-03 16:53:38 +00:00
|
|
|
}
|
2018-04-14 05:15:50 +00:00
|
|
|
|
|
|
|
return err;
|
2018-04-03 16:53:38 +00:00
|
|
|
}
|
|
|
|
|
2018-04-14 05:15:50 +00:00
|
|
|
void ada_sd_task(void* evt_data, uint16_t evt_size)
|
2018-04-03 16:53:38 +00:00
|
|
|
{
|
|
|
|
(void) evt_data;
|
|
|
|
(void) evt_size;
|
|
|
|
|
2018-04-14 05:15:50 +00:00
|
|
|
// process BLE and SOC until there is no more events
|
|
|
|
while( (NRF_ERROR_NOT_FOUND != proc_ble()) || (NRF_ERROR_NOT_FOUND != proc_soc()) )
|
2018-04-03 16:53:38 +00:00
|
|
|
{
|
2018-04-04 13:03:56 +00:00
|
|
|
|
2018-04-03 16:53:38 +00:00
|
|
|
}
|
|
|
|
}
|
2018-04-14 05:15:50 +00:00
|
|
|
|
|
|
|
void SD_EVT_IRQHandler(void)
|
|
|
|
{
|
|
|
|
// Use App Scheduler to defer handling code in non-isr context
|
|
|
|
app_sched_event_put(NULL, 0, ada_sd_task);
|
|
|
|
}
|
|
|
|
|
|
|
|
|