Compare commits

..
22 Commits
Author SHA1 Message Date
Ha Thach fc487794b3 Update changelog.md 2021-04-04 15:11:04 +07:00
Ha Thach 4f74d41871 Merge pull request #160 from KK1423/fix-paired-ota
Resolve OTA failure with bond shared from application
2021-04-04 15:09:01 +07:00
Ha Thach 77c7b7f6dc Merge pull request #200 from adafruit/release-0.5.0
update changelog for release
2021-04-04 15:06:31 +07:00
hathach 488c6c4463 update changelog for release
rename board to all lower case
2021-04-04 14:42:12 +07:00
Ha Thach f1b4740579 Merge pull request #196 from lyusupov/BUTTON_DFU_WAKEUP
Improvement/fix of system wake up by BUTTON_DFU GPIO
2021-04-04 14:31:45 +07:00
hathach 0098324683 skip DFU entirely with DFU_MAGIC_SKIP 2021-04-04 12:58:47 +07:00
hathach 26bafdcf24 Merge branch 'BUTTON_DFU_WAKEUP' of https://github.com/lyusupov/Adafruit_nRF52_Bootloader into lyusupov-BUTTON_DFU_WAKEUP 2021-04-02 23:14:02 +07:00
Ha Thach 5e6690e296 Merge pull request #194 from cmdwtf/board-add-sf-nrf52840-micromod
Add board 'sparkfun_nrf52840_micromod'.
2021-03-23 20:41:11 +07:00
Chris Dailey 78d0c3ae27 Update board.h
Adjust `UF2_BOARD_ID` to fit UF2 format.
2021-03-23 09:11:10 -04:00
Ha Thach 3895ffbda6 Merge pull request #197 from adafruit/update-tinyusb-0.9.0
update tinyusb to nclude nrf usb driver race condition fix
2021-03-19 16:27:53 +07:00
hathach a4b5aa4ad1 update tinyusb to include nrf usb driver race fix 2021-03-19 16:22:13 +07:00
hathach 84e843ac86 update tinyusb to 0.9.0 2021-03-16 23:17:32 +07:00
Linar Yusupov 0299cfedb5 Avoid entering into DFU mode upon wake up by BUTTON_DFU GPIO 2021-03-11 13:20:25 +03:00
Chris Dailey b404dabe15 Add sparkfun_nrf52840_micromod to CI 2021-03-09 13:03:07 -05:00
Chris Dailey d88ab7427a Updated sf micromod USB PIDs
As per the PIDs provide by TheHoff, [here](https://forum.sparkfun.com/viewtopic.php?p=223812#p223812)
2021-03-09 12:53:02 -05:00
nitz d481de3e00 Add SparkFun MicroMod nRF52840 to readme. 2021-03-07 01:04:04 -05:00
nitz 1a5df60739 Add board 'sparkfun_nrf52840_micromod'. 2021-03-07 00:56:50 -05:00
Ha Thach cb916d3087 Merge pull request #192 from jamesadevine/apa102
add support for APA102 LEDs
2021-03-04 23:45:34 +07:00
James Devine 0670265be0 Add ifdef guard for apa102 teardown 2021-03-03 12:47:27 +00:00
James Devine 6f7dc38d3c ifdef guard inclusion of nrf_spim 2021-03-02 23:41:45 +00:00
James Devine 91f16ade72 add support for APA102 LEDs 2021-03-02 23:32:01 +00:00
Karthik Karyamapudi 8ba551c07e Fix ota failure when paired 2020-08-17 17:26:16 -04:00
13 changed files with 267 additions and 69 deletions

No files matched your search

+2 -1
View File
@@ -24,7 +24,7 @@ jobs:
- 'itsybitsy_nrf52840_express'
- 'metro_nrf52840_express'
# Alphabetical order
- 'ADM_B_NRF52840_1'
- 'adm_b_nrf52840_1'
- 'ae_bl652_bo'
- 'aramcon_badge_2019'
- 'arcade_feather_nrf52840_express'
@@ -45,6 +45,7 @@ jobs:
- 'pca10100'
- 'pitaya_go'
- 'raytac_mdbt50q_rx'
- 'sparkfun_nrf52840_micromod'
- 'waveshare_nrf52840_eval'
steps:
+1
View File
@@ -20,6 +20,7 @@ This is a CDC/DFU/UF2 bootloader for nRF52 boards.
- Particle Argon
- Particle Boron
- Particle Xenon
- [SparkFun MicroMod nRF52840](https://www.sparkfun.com/products/16984)
UF2 is an easy-to-use bootloader that appears as a flash drive. You can just copy `.uf2`-format
application images to the flash drive to load new firmware. See https://github.com/Microsoft/uf2 and https://github.com/adafruit/uf2-samdx1 for more information.
+8
View File
@@ -1,5 +1,13 @@
# Adafruit nRF52 Bootloader Changelog
## 0.5.0 - 2021.04.04
- Update tinyusb to latest to fix the race condition causing cdc out dropping packet. Which cause DFU failed occasionally
- Add support for Dotstar LED (APA102)
- Add sparkfun_nrf52840_micromod board
- Allow skipping DFU entirely when reset or wakeup from deep sleep
- Fix an issue with OTA when using shared bond with application
## 0.4.1 - 2021.02.17
- Add USB connect timeout for app reset to UF2 or Serial via GPREGRET
@@ -148,6 +148,7 @@ static uint32_t service_change_indicate()
err_code = sd_ble_gatts_service_changed(m_conn_handle, DFU_SERVICE_HANDLE, BLE_HANDLE_MAX);
if ((err_code == BLE_ERROR_INVALID_CONN_HANDLE) ||
(err_code == BLE_ERROR_INVALID_ATTR_HANDLE) ||
(err_code == NRF_ERROR_INVALID_STATE) ||
(err_code == NRF_ERROR_BUSY))
{
File renamed without changes.
File renamed without changes.
+96 -5
View File
@@ -27,13 +27,17 @@
#include "app_scheduler.h"
#include "app_timer.h"
#ifdef LED_APA102
#include "nrf_spim.h"
#endif
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
//--------------------------------------------------------------------+
#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)
#if defined(LED_NEOPIXEL) || defined(LED_RGB_RED_PIN) || defined(LED_APA102)
void neopixel_init(void);
void neopixel_write(uint8_t *pixels);
void neopixel_teardown(void);
@@ -71,14 +75,15 @@ void board_init(void)
button_init(BUTTON_FRESET);
NRFX_DELAY_US(100); // wait for the pin state is stable
#if LEDS_NUMBER > 0
// 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
#endif
// use neopixel for use enumeration
#if defined(LED_NEOPIXEL) || defined(LED_RGB_RED_PIN)
#if defined(LED_NEOPIXEL) || defined(LED_RGB_RED_PIN) || defined(LED_APA102)
neopixel_init();
#endif
@@ -126,9 +131,11 @@ void board_teardown(void)
SysTick->CTRL = 0;
// Disable and reset PWM for LEDs
#if LEDS_NUMBER > 0
led_pwm_teardown();
#endif
#if defined(LED_NEOPIXEL) || defined(LED_RGB_RED_PIN)
#if defined(LED_NEOPIXEL) || defined(LED_RGB_RED_PIN) || defined(LED_APA102)
neopixel_teardown();
#endif
@@ -317,7 +324,7 @@ void led_state(uint32_t state)
} else if (temp_color_active) {
final_color = (uint8_t*)&rgb_color;
}
#if defined(LED_NEOPIXEL) || defined(LED_RGB_RED_PIN)
#if defined(LED_NEOPIXEL) || defined(LED_RGB_RED_PIN) || defined(LED_APA102)
if (final_color != NULL) {
neopixel_write(final_color);
}
@@ -432,6 +439,90 @@ void neopixel_write (uint8_t *pixels)
}
#endif
#ifdef LED_APA102
#define BYTE_PER_PIXEL 4
// 4 zero bytes are required to initiate update
#define PATTERN_SIZE() ((APA102_NUMBER*BYTE_PER_PIXEL) + 4)
// N/2 * 1 bits are required at the end
static uint8_t pixels_pattern[PATTERN_SIZE() + 4];
// use SPIM1 for dotstar
void neopixel_init(void)
{
NRF_SPIM_Type* spi = NRF_SPIM1;
nrf_spim_disable(spi);
nrf_gpio_pin_set(LED_APA102_CLK);
nrf_gpio_cfg(LED_APA102_CLK,
NRF_GPIO_PIN_DIR_OUTPUT,
NRF_GPIO_PIN_INPUT_CONNECT,
NRF_GPIO_PIN_NOPULL,
NRF_GPIO_PIN_S0S1,
NRF_GPIO_PIN_NOSENSE);
nrf_gpio_pin_clear(LED_APA102_DATA);
nrf_gpio_cfg_output(LED_APA102_DATA);
nrf_spim_pins_set(spi, LED_APA102_CLK, LED_APA102_DATA, 0xFFFFFFFF);
nrf_spim_frequency_set(spi, NRF_SPIM_FREQ_4M);
nrf_spim_configure(spi, NRF_SPIM_MODE_3, NRF_SPIM_BIT_ORDER_MSB_FIRST);
nrf_spim_orc_set(spi, 0);
nrf_spim_tx_list_disable(spi);
// Enable the spi
nrf_spim_enable(spi);
uint8_t rgb[3] = {0, 0, 0 };
neopixel_write(rgb);
}
void neopixel_teardown(void)
{
uint8_t rgb[3] = {0, 0, 0 };
neopixel_write(rgb);
NRF_SPIM_Type* spi = NRF_SPIM1;
nrf_spim_disable(spi);
}
// write 3 bytes color RGB to built-in neopixel
void neopixel_write (uint8_t *pixels)
{
NRF_SPIM_Type* spi = NRF_SPIM1;
//brightness, blue, green, red
uint8_t bbgr[BYTE_PER_PIXEL] = {0xE0 | LED_APA102_BRIGHTNESS, pixels[0], pixels[1], pixels[2]};
pixels_pattern[0] = 0;
pixels_pattern[1] = 0;
pixels_pattern[2] = 0;
pixels_pattern[3] = 0;
for (uint8_t i = 4; i < PATTERN_SIZE(); i+=4) {
pixels_pattern[i] = bbgr[0];
pixels_pattern[i+1] = bbgr[1];
pixels_pattern[i+2] = bbgr[2];
pixels_pattern[i+3] = bbgr[3];
}
pixels_pattern[PATTERN_SIZE()] = 0xff;
pixels_pattern[PATTERN_SIZE()+1] = 0xff;
pixels_pattern[PATTERN_SIZE()+2] = 0xff;
pixels_pattern[PATTERN_SIZE()+3] = 0xff;
nrf_spim_tx_buffer_set(spi, pixels_pattern, PATTERN_SIZE() + 4);
nrf_spim_event_clear(spi, NRF_SPIM_EVENT_ENDTX);
nrf_spim_task_trigger(spi, NRF_SPIM_TASK_START);
while(!nrf_spim_event_check(spi, NRF_SPIM_EVENT_ENDTX));
}
#endif
#if defined(LED_RGB_RED_PIN) && defined(LED_RGB_GREEN_PIN) && defined(LED_RGB_BLUE_PIN)
#ifdef LED_SECONDARY_PIN
@@ -0,0 +1,66 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2018 Ha Thach for Adafruit Industries
* Copyright (c) 2021 Chris Marc Dailey
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef _SPARKFUN_NRF52840_MICROMOD_H_
#define _SPARKFUN_NRF52840_MICROMOD_H_
#define _PINNUM(port, pin) ((port)*32 + (pin))
/*------------------------------------------------------------------*/
/* LED
*------------------------------------------------------------------*/
#define LEDS_NUMBER 1
#define LED_PRIMARY_PIN _PINNUM(0, 13)
#define LED_STATE_ON 1
/*------------------------------------------------------------------*/
/* BUTTON
*------------------------------------------------------------------*/
#define BUTTONS_NUMBER 2
#define BUTTON_1 _PINNUM(0, 7)
#define BUTTON_2 _PINNUM(0, 10)
#define BUTTON_PULL NRF_GPIO_PIN_PULLUP
//--------------------------------------------------------------------+
// BLE OTA
//--------------------------------------------------------------------+
#define BLEDIS_MANUFACTURER "SparkFun"
#define BLEDIS_MODEL "MicroMod nRF52840"
//--------------------------------------------------------------------+
// USB
//--------------------------------------------------------------------+
#define USB_DESC_VID 0x1B4F
#define USB_DESC_UF2_PID 0x0022
#define USB_DESC_CDC_ONLY_PID 0x0023
//------------- UF2 -------------//
#define UF2_PRODUCT_NAME "SparkFun MicroMod nRF52840"
#define UF2_VOLUME_LABEL "SFMM852BOOT"
#define UF2_BOARD_ID "nRF52840-micromod-v10"
#define UF2_INDEX_URL "https://www.sparkfun.com/products/16984"
#endif /* _SPARKFUN_NRF52840_MICROMOD_H_ */
@@ -0,0 +1 @@
MCU_SUB_VARIANT = nrf52840
@@ -0,0 +1,19 @@
#include "boards.h"
#include "uf2/configkeys.h"
__attribute__((used, section(".bootloaderConfig")))
const uint32_t bootloaderConfig[] =
{
/* CF2 START */
CFG_MAGIC0, CFG_MAGIC1, // magic
5, 100, // used entries, total entries
204, 0x100000, // FLASH_BYTES = 0x100000
205, 0x40000, // RAM_BYTES = 0x40000
208, (USB_DESC_VID << 16) | USB_DESC_UF2_PID, // BOOTLOADER_BOARD_ID = USB VID+PID, used for verification when updating bootloader via uf2
209, 0xada52840, // UF2_FAMILY = 0xada52840
210, 0x20, // PINS_PORT_SIZE = PA_32
0, 0, 0, 0, 0, 0, 0, 0
/* CF2 END */
};
+72 -62
View File
@@ -97,18 +97,20 @@ void usb_teardown(void);
*/
/* Magic that written to NRF_POWER->GPREGRET by application when it wish to go into DFU
* - DFU_MAGIC_OTA_APPJUM used by BLEDfu service : SD is already init
* - DFU_MAGIC_OTA_RESET entered by soft reset : SD is not init
* - DFU_MAGIC_SERIAL_ONLY_RESET with CDC interface only
* - DFU_MAGIC_UF2_RESET with CDC and MSC interfaces
* - DFU_MAGIC_OTA_APPJUM : used by BLEDfu service, SD is already inited
* - DFU_MAGIC_OTA_RESET : entered by soft reset, SD is not inited yet
* - DFU_MAGIC_SERIAL_ONLY_RESET : with CDC interface only
* - DFU_MAGIC_UF2_RESET : with CDC and MSC interfaces
* - DFU_MAGIC_SKIP : skip DFU entirely including double reset delay
*
* Note: for DFU_MAGIC_OTA_APPJUM Softdevice must not initialized.
* since it is already in application. In all other case of OTA SD must be initialized
*/
#define DFU_MAGIC_OTA_APPJUM BOOTLOADER_DFU_START // 0xB1
#define DFU_MAGIC_OTA_APPJUM BOOTLOADER_DFU_START // 0xB1
#define DFU_MAGIC_OTA_RESET 0xA8
#define DFU_MAGIC_SERIAL_ONLY_RESET 0x4e
#define DFU_MAGIC_UF2_RESET 0x57
#define DFU_MAGIC_SKIP 0x6d
#define DFU_DBL_RESET_MAGIC 0x5A1AD5 // SALADS
#define DFU_DBL_RESET_APP 0x4ee5677e
@@ -176,8 +178,10 @@ int main(void)
bool dfu_start = _ota_dfu || serial_only_dfu || uf2_dfu ||
(((*dbl_reset_mem) == DFU_DBL_RESET_MAGIC) && (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk));
bool const dfu_skip = (NRF_POWER->GPREGRET == DFU_MAGIC_SKIP);
// Clear GPREGRET if it is our values
if (dfu_start) NRF_POWER->GPREGRET = 0;
if (dfu_start || dfu_skip) NRF_POWER->GPREGRET = 0;
// Save bootloader version to pre-defined register, retrieved by application
// TODO move to CF2
@@ -200,79 +204,85 @@ int main(void)
}
/*------------- Determine DFU mode (Serial, OTA, FRESET or normal) -------------*/
// DFU button pressed
dfu_start = dfu_start || button_pressed(BUTTON_DFU);
// DFU + FRESET are pressed --> OTA
_ota_dfu = _ota_dfu || ( button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) ) ;
bool const valid_app = bootloader_app_is_valid();
bool const just_start_app = valid_app && !dfu_start && (*dbl_reset_mem) == DFU_DBL_RESET_APP;
if (!just_start_app && APP_ASKS_FOR_SINGLE_TAP_RESET())
dfu_start = 1;
// App mode: register 1st reset and DFU startup (nrf52832)
if ( ! (just_start_app || dfu_start || !valid_app) )
if ( !dfu_skip )
{
// Register our first reset for double reset detection
(*dbl_reset_mem) = DFU_DBL_RESET_MAGIC;
// DFU button pressed
dfu_start = dfu_start || (button_pressed(BUTTON_DFU) && !dfu_skip);
// DFU + FRESET are pressed --> OTA
_ota_dfu = _ota_dfu || ( button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) ) ;
bool const valid_app = bootloader_app_is_valid();
bool const just_start_app = valid_app && !dfu_start && (*dbl_reset_mem) == DFU_DBL_RESET_APP;
if (!just_start_app && APP_ASKS_FOR_SINGLE_TAP_RESET()) dfu_start = 1;
// App mode: register 1st reset and DFU startup (nrf52832)
if ( ! (just_start_app || dfu_start || !valid_app) )
{
// 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(false, DFU_SERIAL_STARTUP_INTERVAL, false);
/* 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(false, DFU_SERIAL_STARTUP_INTERVAL, false);
#else
// if RST is pressed during this delay --> if will enter dfu
NRFX_DELAY_MS(DFU_DBL_RESET_DELAY);
// 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())
(*dbl_reset_mem) = DFU_DBL_RESET_APP;
else
(*dbl_reset_mem) = 0;
if ( dfu_start || !valid_app )
{
if ( _ota_dfu )
if (APP_ASKS_FOR_SINGLE_TAP_RESET())
{
led_state(STATE_BLE_DISCONNECTED);
softdev_init(!sd_inited);
sd_inited = true;
(*dbl_reset_mem) = DFU_DBL_RESET_APP;
}
else
{
led_state(STATE_USB_UNMOUNTED);
usb_init(serial_only_dfu);
(*dbl_reset_mem) = 0;
}
// Initiate an update of the firmware.
if (APP_ASKS_FOR_SINGLE_TAP_RESET() || uf2_dfu || serial_only_dfu)
if ( dfu_start || !valid_app )
{
// If USB is not enumerated in 3s (eg. because we're running on battery), we restart into app.
APP_ERROR_CHECK( bootloader_dfu_start(_ota_dfu, 3000, true) );
}
else
{
// No timeout if bootloader requires user action (double-reset).
APP_ERROR_CHECK( bootloader_dfu_start(_ota_dfu, 0, false) );
}
if ( _ota_dfu )
{
led_state(STATE_BLE_DISCONNECTED);
softdev_init(!sd_inited);
sd_inited = true;
}
else
{
led_state(STATE_USB_UNMOUNTED);
usb_init(serial_only_dfu);
}
if ( _ota_dfu )
{
sd_softdevice_disable();
}else
{
usb_teardown();
// Initiate an update of the firmware.
if (APP_ASKS_FOR_SINGLE_TAP_RESET() || uf2_dfu || serial_only_dfu)
{
// If USB is not enumerated in 3s (eg. because we're running on battery), we restart into app.
APP_ERROR_CHECK( bootloader_dfu_start(_ota_dfu, 3000, true) );
}
else
{
// No timeout if bootloader requires user action (double-reset).
APP_ERROR_CHECK( bootloader_dfu_start(_ota_dfu, 0, false) );
}
if ( _ota_dfu )
{
sd_softdevice_disable();
}else
{
usb_teardown();
}
}
}
// Reset Board
// Reset peripherals
board_teardown();
/* Jump to application if valid