Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 19 additions & 13 deletions libraries/Bluefruit52Lib/src/BLEAdvertising.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ BLEAdvertising::BLEAdvertising(void)
_hdl = BLE_GAP_ADV_SET_HANDLE_NOT_SET;
_type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
_start_if_disconnect = true;
_runnning = false;
_running = false;

_conn_mask = 0;

Expand Down Expand Up @@ -321,7 +321,7 @@ void BLEAdvertising::setPeerAddress(const ble_gap_addr_t& peer_addr) {

bool BLEAdvertising::isRunning(void)
{
return _runnning;
return _running;
}

bool BLEAdvertising::setBeacon(BLEBeacon& beacon)
Expand All @@ -339,8 +339,7 @@ void BLEAdvertising::restartOnDisconnect(bool enable)
_start_if_disconnect = enable;
}

bool BLEAdvertising::_start(uint16_t interval, uint16_t timeout)
{
bool BLEAdvertising::_start(uint16_t interval, uint16_t timeout) {
// ADV Params
ble_gap_adv_params_t adv_para = {
.properties = { .type = _type, .anonymous = 0 },
Expand Down Expand Up @@ -369,17 +368,24 @@ bool BLEAdvertising::_start(uint16_t interval, uint16_t timeout)
default: break;
}

// stop first if current running since we may change advertising data/params
if (_running) {
sd_ble_gap_adv_stop(_hdl);
}

// gap_adv long-live is required by SD v6
static ble_gap_adv_data_t gap_adv = {
.adv_data = { .p_data = _data, .len = _count },
.scan_rsp_data = { .p_data = Bluefruit.ScanResponse.getData(), .len = Bluefruit.ScanResponse.count() }
};
static ble_gap_adv_data_t gap_adv;
gap_adv.adv_data.p_data = _data;
gap_adv.adv_data.len = _count;
gap_adv.scan_rsp_data.p_data = Bluefruit.ScanResponse.getData();
gap_adv.scan_rsp_data.len = Bluefruit.ScanResponse.count();

VERIFY_STATUS( sd_ble_gap_adv_set_configure(&_hdl, &gap_adv, &adv_para), false );
VERIFY_STATUS( sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, _hdl, Bluefruit.getTxPower() ), false );
VERIFY_STATUS( sd_ble_gap_adv_start(_hdl, CONN_CFG_PERIPHERAL), false );

Bluefruit._startConnLed(); // start blinking
_runnning = true;
_running = true;
_active_interval = interval;

_left_timeout -= min16(_left_timeout, timeout);
Expand All @@ -403,7 +409,7 @@ bool BLEAdvertising::stop(void)
{
VERIFY_STATUS( sd_ble_gap_adv_stop(_hdl), false);

_runnning = false;
_running = false;
Bluefruit._stopConnLed(); // stop blinking

return true;
Expand All @@ -425,7 +431,7 @@ void BLEAdvertising::_eventHandler(ble_evt_t* evt)
{
bitSet(_conn_mask, conn_hdl);

_runnning = false;
_running = false;
}
}
break;
Expand All @@ -436,14 +442,14 @@ void BLEAdvertising::_eventHandler(ble_evt_t* evt)
bitClear(_conn_mask, conn_hdl);

// Auto start if enabled and not connected to any central
if ( !_runnning && _start_if_disconnect ) start(_stop_timeout);
if ( !_running && _start_if_disconnect ) start(_stop_timeout);
}
break;

case BLE_GAP_EVT_ADV_SET_TERMINATED:
if (evt->evt.gap_evt.params.adv_set_terminated.reason == BLE_GAP_EVT_ADV_SET_TERMINATED_REASON_TIMEOUT)
{
_runnning = false;
_running = false;

// If still advertising, it is only in slow mode --> blink normal
Bluefruit.setConnLedInterval(CFG_ADV_BLINKY_INTERVAL);
Expand Down
2 changes: 1 addition & 1 deletion libraries/Bluefruit52Lib/src/BLEAdvertising.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ class BLEAdvertising : public BLEAdvertisingData
uint8_t _hdl;
uint8_t _type;
bool _start_if_disconnect;
bool _runnning;
bool _running;
ble_gap_addr_t _peer_addr; //! Target address for an ADV_DIRECT_IND advertisement

uint32_t _conn_mask;
Expand Down
110 changes: 59 additions & 51 deletions libraries/InternalFileSytem/src/flash/flash_nrf5x.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@
#include "delay.h"
#include "rtos.h"


#ifdef NRF52840_XXAA
#define BOOTLOADER_ADDR 0xF4000
#else
#define BOOTLOADER_ADDR 0x74000
#endif

// How many retry attempts when performing flash operations
#define MAX_RETRY 20

// defined in linker script
extern uint32_t __flash_arduino_start[];
//extern uint32_t __flash_arduino_end[];
Expand All @@ -44,12 +46,7 @@ extern uint32_t __flash_arduino_start[];
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
//--------------------------------------------------------------------+
static SemaphoreHandle_t _sem = NULL;

void flash_nrf5x_event_cb (uint32_t event)
{
// if (event != NRF_EVT_FLASH_OPERATION_SUCCESS) LOG_LV1("IFLASH", "Flash op Failed");
if ( _sem ) xSemaphoreGive(_sem);
}
static uint32_t _flash_op_result = NRF_EVT_FLASH_OPERATION_SUCCESS;

// Flash Abstraction Layer
static bool fal_erase (uint32_t addr);
Expand All @@ -70,6 +67,31 @@ static flash_cache_t _cache =
.cache_buf = _cache_buffer
};

void flash_nrf5x_event_cb (uint32_t event) {
if ( _sem ) {
// Record the result, for consumption by fal_erase or fal_program
// Used to reattempt failed operations
_flash_op_result = event;

// Signal to fal_erase or fal_program that our async flash op is now complete
xSemaphoreGive(_sem);
}
}

// When soft device is enabled, flash ops are async
// Eventual success is reported via callback, which we await
static uint32_t wait_for_async_flash_op_completion(void) {
uint8_t sd_en = 0;
(void) sd_softdevice_is_enabled(&sd_en);

if (sd_en) {
xSemaphoreTake(_sem, portMAX_DELAY);
return (_flash_op_result == NRF_EVT_FLASH_OPERATION_SUCCESS) ? NRF_SUCCESS : NRF_ERROR_TIMEOUT;
} else {
return NRF_SUCCESS;
}
}

//--------------------------------------------------------------------+
// Application API
//--------------------------------------------------------------------+
Expand Down Expand Up @@ -105,62 +127,48 @@ bool flash_nrf5x_erase(uint32_t addr)
static bool fal_erase (uint32_t addr)
{
// Init semaphore for first call
if ( _sem == NULL )
{
_sem = xSemaphoreCreateCounting(10, 0);
if ( _sem == NULL ) {
_sem = xSemaphoreCreateBinary();
VERIFY(_sem);
}

// retry if busy
uint32_t err;
while ( NRF_ERROR_BUSY == (err = sd_flash_page_erase(addr / FLASH_NRF52_PAGE_SIZE)) )
{
// Erase the page: Multiple attempts if needed
for (uint8_t attempt = 0; attempt < MAX_RETRY; ++attempt) {
if (NRF_SUCCESS == sd_flash_page_erase(addr / FLASH_NRF52_PAGE_SIZE)) {
if (NRF_SUCCESS == wait_for_async_flash_op_completion()) {
return true;
}
}
delay(1);
}
VERIFY_STATUS(err, false);

// wait for async event if SD is enabled
uint8_t sd_en = 0;
(void) sd_softdevice_is_enabled(&sd_en);

if ( sd_en ) xSemaphoreTake(_sem, portMAX_DELAY);

return true;
return false;
}

static uint32_t fal_program (uint32_t dst, void const * src, uint32_t len)
{
// wait for async event if SD is enabled
uint8_t sd_en = 0;
(void) sd_softdevice_is_enabled(&sd_en);

uint32_t err;

// Somehow S140 v6.1.1 assert an error when writing a whole page
// https://devzone.nordicsemi.com/f/nordic-q-a/40088/sd_flash_write-cause-nrf_fault_id_sd_assert
// Workaround: write half page at a time.
#if NRF52832_XXAA
while ( NRF_ERROR_BUSY == (err = sd_flash_write((uint32_t*) dst, (uint32_t const *) src, len/4)) )
{
// helper for fal_program()
static bool fal_sub_program(uint32_t dst, void const * src, uint32_t len) {
for (uint8_t attempt = 0; attempt < MAX_RETRY; ++attempt) {
if (NRF_SUCCESS == sd_flash_write((uint32_t*) dst, (uint32_t const *) src, len/4)) {
if (NRF_SUCCESS == wait_for_async_flash_op_completion()) {
return true;
}
}
delay(1);
}
VERIFY_STATUS(err, 0);
return false;
}

if ( sd_en ) xSemaphoreTake(_sem, portMAX_DELAY);
static uint32_t fal_program (uint32_t dst, void const * src, uint32_t len) {
#if NRF52832_XXAA
VERIFY(fal_sub_program(dst, src, len), 0);
#else
while ( NRF_ERROR_BUSY == (err = sd_flash_write((uint32_t*) dst, (uint32_t const *) src, len/8)) )
{
delay(1);
}
VERIFY_STATUS(err, 0);
if ( sd_en ) xSemaphoreTake(_sem, portMAX_DELAY);
// Somehow S140 v6.1.1 assert an error when writing a whole page
// https://devzone.nordicsemi.com/f/nordic-q-a/40088/sd_flash_write-cause-nrf_fault_id_sd_assert
// Workaround: write half page at a time.
VERIFY(fal_sub_program(dst, src, len/2), 0); // 1st half

while ( NRF_ERROR_BUSY == (err = sd_flash_write((uint32_t*) (dst+ len/2), (uint32_t const *) (src + len/2), len/8)) )
{
delay(1);
}
VERIFY_STATUS(err, 0);
if ( sd_en ) xSemaphoreTake(_sem, portMAX_DELAY);
dst += len/2;
src += len/2;
VERIFY(fal_sub_program(dst, src, len/2), 0); // 2nd half
#endif

return len;
Expand Down