diff --git a/README.md b/README.md index 3c0e1b6d..5664cdb5 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,12 @@ There are two methods that you can use to install this BSP. We highly recommend 1. [Download and install the Arduino IDE](https://www.arduino.cc/en/Main/Software) (At least v1.6.12) 2. Start the Arduino IDE 3. Go into Preferences - 4. Add "https://raw.githubusercontent.com/pdcook/nRFMicro-Arduino-Core/main/package_nRFMicro_index.json" as an 'Additional Board Manager URL' + 4. Add the following line as 'Additional Board Manager URL' + + ``` + https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json,https://raw.githubusercontent.com/pdcook/nRFMicro-Arduino-Core/main/package_nRFMicro_index.json + ``` + 5. Restart the Arduino IDE 6. Open the Boards Manager from the Tools -> Board menu and install 'nRFMicro Boards' 7. Once the BSP is installed, select 'nRFMicro' or 'SuperMini nRF52840' from the Tools -> Board menu, which will update your system config to use the right compiler and settings for the nRF52. diff --git a/libraries/Bluefruit52Lib/src/BLEAdvertising.cpp b/libraries/Bluefruit52Lib/src/BLEAdvertising.cpp index e4437233..6689290e 100644 --- a/libraries/Bluefruit52Lib/src/BLEAdvertising.cpp +++ b/libraries/Bluefruit52Lib/src/BLEAdvertising.cpp @@ -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; @@ -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) @@ -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 }, @@ -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); @@ -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; @@ -425,7 +431,7 @@ void BLEAdvertising::_eventHandler(ble_evt_t* evt) { bitSet(_conn_mask, conn_hdl); - _runnning = false; + _running = false; } } break; @@ -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); diff --git a/libraries/Bluefruit52Lib/src/BLEAdvertising.h b/libraries/Bluefruit52Lib/src/BLEAdvertising.h index 3a0c556e..43a6a9fe 100644 --- a/libraries/Bluefruit52Lib/src/BLEAdvertising.h +++ b/libraries/Bluefruit52Lib/src/BLEAdvertising.h @@ -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; diff --git a/libraries/InternalFileSytem/src/flash/flash_nrf5x.c b/libraries/InternalFileSytem/src/flash/flash_nrf5x.c index f9fac1fd..5ee73025 100644 --- a/libraries/InternalFileSytem/src/flash/flash_nrf5x.c +++ b/libraries/InternalFileSytem/src/flash/flash_nrf5x.c @@ -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[]; @@ -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); @@ -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 //--------------------------------------------------------------------+ @@ -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; diff --git a/nRFMicro-Arduino-Core-1.0.1.tar.bz2 b/nRFMicro-Arduino-Core-1.0.1.tar.bz2 deleted file mode 100644 index 1e08596e..00000000 Binary files a/nRFMicro-Arduino-Core-1.0.1.tar.bz2 and /dev/null differ diff --git a/nRFMicro-Arduino-Core-1.0.2.tar.bz2 b/nRFMicro-Arduino-Core-1.1.0.tar.bz2 similarity index 66% rename from nRFMicro-Arduino-Core-1.0.2.tar.bz2 rename to nRFMicro-Arduino-Core-1.1.0.tar.bz2 index f865db41..dda8f379 100644 Binary files a/nRFMicro-Arduino-Core-1.0.2.tar.bz2 and b/nRFMicro-Arduino-Core-1.1.0.tar.bz2 differ diff --git a/nRFMicro-Arduino-Core.tar.bz2 b/nRFMicro-Arduino-Core.tar.bz2 deleted file mode 100644 index 7c08bdb6..00000000 Binary files a/nRFMicro-Arduino-Core.tar.bz2 and /dev/null differ diff --git a/package.json b/package.json index a7dbea4a..da279c79 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nrfmicro-arduino", - "version": "1.0.2", + "version": "1.1.0", "description": "Arduino core for nRFMicro-compatible boards", "keywords": [ "arduino", @@ -13,6 +13,6 @@ ], "repository": { "type": "git", - "url": "https://github.com/pdcook/nRFMicro-Arduino-Core" + "url": "https://github.com/waltje/Arduino.Core-nRFMicro" } } diff --git a/package_nRFMicro_index.json b/package_nRFMicro_index.json index da56474b..8b60d45f 100644 --- a/package_nRFMicro_index.json +++ b/package_nRFMicro_index.json @@ -1,118 +1,26 @@ { "packages": [ { - "name": "nRFMicro-like Boards", - "maintainer": "pdcook", - "websiteURL": "https://github.com/pdcook/nRFMicro-Arduino-Core", + "name": "nRFMicro-like-boards", + "maintainer": "waltje", + "websiteURL": "https://github.com/waltje/Arduino.Core-nRFMicro", "email": "", "help": { "online": "" }, "platforms": [ { - "name": "nRFMicro-like Boards", + "name": "nRFMicro-like-boards", "architecture": "nrf52", - "version": "1.0.0", + "version": "1.1.0", "category": "Contributed", "help": { "online": "" }, - "url": "https://raw.githubusercontent.com/pdcook/nRFMicro-Arduino-Core/main/nRFMicro-Arduino-Core.tar.bz2", - "archiveFileName": "nRFMicro-Arduino-Core.tar.bz2", - "checksum": "SHA-256:c190cd877a1889bdc99095ebca4cce243e57e80d30b2947b166f7aeab2327921", - "size": "17227165", - "boards": [{ "name": "nRFMicro" }, { "name": "SuperMini nRF52840" }, {"name": "nice!nano v2"}], - "toolsDependencies": [ - { - - "packager": "Seeeduino", - - "name": "arm-none-eabi-gcc", - - "version": "9-2019q4" - - }, - - { - - "packager": "Seeeduino", - - "name": "nrfjprog", - - "version": "9.4.0" - - }, - - { - - "packager": "Seeeduino", - - "name": "CMSIS", - - "version": "5.7.0" - - } - - ] - }, - { - "name": "nRFMicro-like Boards", - "architecture": "nrf52", - "version": "1.0.1", - "category": "Contributed", - "help": { - "online": "" - }, - "url": "https://raw.githubusercontent.com/pdcook/nRFMicro-Arduino-Core/main/nRFMicro-Arduino-Core-1.0.1.tar.bz2", - "archiveFileName": "nRFMicro-Arduino-Core-1.0.1.tar.bz2", - "checksum": "SHA-256:6864b2a506899affe5593dc2c5c65c39273bbef6cf60971a8a33577039e6f3b6", - "size": "20051818", - "boards": [{ "name": "nRFMicro" }, { "name": "SuperMini nRF52840" }, {"name": "nice!nano v2"}], - "toolsDependencies": [ - { - - "packager": "Seeeduino", - - "name": "arm-none-eabi-gcc", - - "version": "9-2019q4" - - }, - - { - - "packager": "Seeeduino", - - "name": "nrfjprog", - - "version": "9.4.0" - - }, - - { - - "packager": "Seeeduino", - - "name": "CMSIS", - - "version": "5.7.0" - - } - - ] - }, - { - "name": "nRFMicro-like Boards", - "architecture": "nrf52", - "version": "1.0.2", - "category": "Contributed", - "help": { - "online": "" - }, - "url": "https://raw.githubusercontent.com/pdcook/nRFMicro-Arduino-Core/main/nRFMicro-Arduino-Core-1.0.2.tar.bz2", - "archiveFileName": "nRFMicro-Arduino-Core-1.0.2.tar.bz2", - "checksum": "SHA-256:44d35927a60cb8a571a210ddeb9d2c5da4957ead5b143623685a8787fa1d04c9", - "size": "20050973", + "url": "https://raw.githubusercontent.com/waltje/Arduino.Core-nRFMicro/main/nRFMicro-Arduino-Core-1.1.0.tar.bz2", + "archiveFileName": "nRFMicro-Arduino-Core-1.1.0.tar.bz2", + "checksum": "SHA-256:da80e1abd50626daf36f9f640ae5afa1b1025a0d5ef516d03fe1920bcfae6c31", + "size": "19483474", "boards": [{ "name": "nRFMicro" }, { "name": "SuperMini nRF52840" }, {"name": "nice!nano v2"}], "toolsDependencies": [ {