wip; redid flash writing to be compatible with SD
This commit is contained in:
parent
390337b9a5
commit
9c167af17a
|
@ -670,5 +670,4 @@ void bleio_adapter_reset(bleio_adapter_obj_t* adapter) {
|
|||
bleio_connection_internal_t *connection = &connections[i];
|
||||
connection->connection_obj = mp_const_none;
|
||||
}
|
||||
bonding_reset();
|
||||
}
|
||||
|
|
|
@ -133,7 +133,8 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self,
|
|||
common_hal_bleio_characteristic_set_value(self, initial_value_bufinfo);
|
||||
}
|
||||
|
||||
ble_drv_add_event_handler(characteristic_on_ble_evt, self);
|
||||
self->handler_entry.next = NULL;
|
||||
//////////////// ble_drv_add_event_handler_entry(&self->handler_entry, characteristic_on_ble_evt, self);
|
||||
}
|
||||
|
||||
bleio_descriptor_obj_t *common_hal_bleio_characteristic_get_descriptor_list(bleio_characteristic_obj_t *self) {
|
||||
|
@ -287,3 +288,8 @@ void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self,
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
void common_hal_bleio_characteristic_del(bleio_characteristic_obj_t *self) {
|
||||
// Remove from event handler list, since the evt handler entry is built-in and not a heap object.
|
||||
ble_drv_remove_event_handler(characteristic_on_ble_evt, self);
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ typedef struct _bleio_characteristic_obj {
|
|||
bleio_attribute_security_mode_t read_perm;
|
||||
bleio_attribute_security_mode_t write_perm;
|
||||
bleio_descriptor_obj_t *descriptor_list;
|
||||
ble_drv_evt_handler_entry_t handler_entry;
|
||||
uint16_t user_desc_handle;
|
||||
uint16_t cccd_handle;
|
||||
uint16_t sccd_handle;
|
||||
|
|
|
@ -94,6 +94,7 @@ void bleio_reset() {
|
|||
common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, false);
|
||||
}
|
||||
supervisor_start_bluetooth();
|
||||
bonding_reset();
|
||||
}
|
||||
|
||||
// The singleton _bleio.Adapter object, bound to _bleio.adapter
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include "shared-bindings/_bleio/Adapter.h"
|
||||
#include "shared-bindings/nvm/ByteArray.h"
|
||||
|
||||
#include "nrf_nvmc.h"
|
||||
#include "nrf_soc.h"
|
||||
#include "sd_mutex.h"
|
||||
|
||||
#include "bonding.h"
|
||||
|
@ -68,15 +68,17 @@ STATIC inline size_t compute_block_size(uint16_t data_length) {
|
|||
|
||||
STATIC void erase_bonding_storage(void) {
|
||||
// Erase all pages in the bonding area.
|
||||
BONDING_DEBUG_PRINTF("erase_bonding_storage()\n");
|
||||
for(uint32_t page_address = BONDING_PAGES_START_ADDR;
|
||||
page_address < BONDING_PAGES_END_ADDR;
|
||||
page_address += FLASH_PAGE_SIZE) {
|
||||
nrf_nvmc_page_erase(page_address);
|
||||
// Argument is page number, not address.
|
||||
sd_flash_page_erase_sync(page_address / FLASH_PAGE_SIZE);
|
||||
}
|
||||
// Write marker words at the beginning and the end of the bonding area.
|
||||
nrf_nvmc_write_word(BONDING_DATA_START_ADDR, BONDING_START_FLAG_ADDR);
|
||||
nrf_nvmc_write_word(BONDING_DATA_END_ADDR, BONDING_END_FLAG_ADDR);
|
||||
uint32_t flag = BONDING_START_FLAG;
|
||||
sd_flash_write_sync((uint32_t *) BONDING_DATA_START_ADDR, &flag, 1);
|
||||
flag = BONDING_END_FLAG;
|
||||
sd_flash_write_sync((uint32_t *) BONDING_DATA_END_ADDR, &flag, 1);
|
||||
// First unused block is at the beginning.
|
||||
bonding_unused_block = (bonding_block_t *) BONDING_DATA_START_ADDR;
|
||||
}
|
||||
|
@ -135,7 +137,8 @@ STATIC bonding_block_t *find_block(bool is_central, bonding_block_type_t type, u
|
|||
// We don't change data_length, so we can still skip over this block.
|
||||
STATIC void invalidate_block(bonding_block_t *block) {
|
||||
BONDING_DEBUG_PRINTF("invalidate_block()\n");
|
||||
nrf_nvmc_write_word((uint32_t) block, 0x00000000);
|
||||
uint32_t zero = 0;
|
||||
sd_flash_write_sync((uint32_t *) block, &zero, 1);
|
||||
}
|
||||
|
||||
STATIC void queue_write_block(bool is_central, bonding_block_type_t type, uint16_t ediv, uint16_t conn_handle, uint8_t *data, uint16_t data_length) {
|
||||
|
@ -178,7 +181,7 @@ STATIC void write_block_header(bonding_block_t *block) {
|
|||
erase_bonding_storage();
|
||||
}
|
||||
|
||||
nrf_nvmc_write_words((uint32_t) bonding_unused_block, (uint32_t *) block, sizeof(bonding_block_t) / 4);
|
||||
sd_flash_write_sync((uint32_t *) bonding_unused_block, (uint32_t *) block, sizeof(bonding_block_t) / 4);
|
||||
}
|
||||
|
||||
// Write variable-length data at end of bonding block.
|
||||
|
@ -190,7 +193,7 @@ STATIC void write_block_data(uint8_t *data, uint16_t data_length) {
|
|||
while (1) {
|
||||
uint32_t word = 0xffffffff;
|
||||
memcpy(&word, data, data_length >= 4 ? 4 : data_length);
|
||||
nrf_nvmc_write_word((uint32_t) flash_word_p, word);
|
||||
sd_flash_write_sync(flash_word_p, &word, 1);
|
||||
if (data_length <= 4) {
|
||||
break;
|
||||
}
|
||||
|
@ -242,8 +245,9 @@ void bonding_clear_keys(bonding_keys_t *bonding_keys) {
|
|||
memset((uint8_t*) bonding_keys, 0, sizeof(bonding_keys_t));
|
||||
}
|
||||
|
||||
// Call only when SD is enabled.
|
||||
void bonding_reset(void) {
|
||||
BONDING_DEBUG_PRINTF("bonding_reset()\n");
|
||||
MP_STATE_VM(queued_bonding_block_list) = NULL;
|
||||
sd_mutex_new(&queued_bonding_block_list_mutex);
|
||||
if (BONDING_START_FLAG != *((uint32_t *) BONDING_START_FLAG_ADDR) ||
|
||||
BONDING_END_FLAG != *((uint32_t *) BONDING_END_FLAG_ADDR)) {
|
||||
|
@ -256,18 +260,20 @@ void bonding_reset(void) {
|
|||
// Write bonding blocks to flash. These have been queued during event handlers.
|
||||
// We do one at a time, on each background call.
|
||||
void bonding_background(void) {
|
||||
|
||||
uint8_t sd_en = 0;
|
||||
(void) sd_softdevice_is_enabled(&sd_en);
|
||||
if (!sd_en) {
|
||||
return;
|
||||
}
|
||||
// Get block at front of list.
|
||||
sd_mutex_acquire_wait(&queued_bonding_block_list_mutex);
|
||||
bonding_block_t *block = &(MP_STATE_VM(queued_bonding_block_list)->bonding_block);
|
||||
bonding_block_t *block = (bonding_block_t *) MP_STATE_VM(queued_bonding_block_list);
|
||||
if (block) {
|
||||
// Remove written block from front of list.
|
||||
// Remove block from list.
|
||||
MP_STATE_VM(queued_bonding_block_list) = MP_STATE_VM(queued_bonding_block_list)->next_queued_block;
|
||||
}
|
||||
sd_mutex_release(&queued_bonding_block_list_mutex);
|
||||
|
||||
if (!block) {
|
||||
// No blocks in queue.
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,29 +38,62 @@
|
|||
#include "ble_drv.h"
|
||||
#include "nrf_sdm.h"
|
||||
|
||||
STATIC bool sd_is_enabled(void) {
|
||||
uint8_t sd_en = 0;
|
||||
(void) sd_softdevice_is_enabled(&sd_en);
|
||||
return sd_en;
|
||||
}
|
||||
|
||||
STATIC void sd_flash_operation_start(void) {
|
||||
sd_flash_operation_status = SD_FLASH_OPERATION_IN_PROGRESS;
|
||||
}
|
||||
|
||||
STATIC sd_flash_operation_status_t sd_flash_operation_wait_until_done(void) {
|
||||
while (sd_flash_operation_status == SD_FLASH_OPERATION_IN_PROGRESS) {
|
||||
sd_app_evt_wait();
|
||||
// If the SD is not enabled, no events are generated, so just return immediately.
|
||||
if (sd_is_enabled()) {
|
||||
while (sd_flash_operation_status == SD_FLASH_OPERATION_IN_PROGRESS) {
|
||||
sd_app_evt_wait();
|
||||
}
|
||||
} else {
|
||||
sd_flash_operation_status = SD_FLASH_OPERATION_DONE;
|
||||
}
|
||||
return sd_flash_operation_status;
|
||||
|
||||
}
|
||||
|
||||
bool sd_flash_page_erase_sync(uint32_t page_number) {
|
||||
sd_flash_operation_start();
|
||||
if (sd_flash_page_erase(page_number) != NRF_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
if (sd_flash_operation_wait_until_done() == SD_FLASH_OPERATION_ERROR) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sd_flash_write_sync(uint32_t *dest_words, uint32_t* src_words, uint32_t num_words) {
|
||||
sd_flash_operation_start();
|
||||
if (sd_flash_write(dest_words, src_words, num_words) != NRF_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
if (sd_flash_operation_wait_until_done() == SD_FLASH_OPERATION_ERROR) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// The nRF52840 datasheet specifies a maximum of two writes to a flash
|
||||
// location before an erase is necessary, even if the write is all
|
||||
// ones (erased state). So we can't avoid erases even if the page
|
||||
// appears to be already erased (all ones), unless we keep track of
|
||||
// writes to a page.
|
||||
// writes to a page.g
|
||||
|
||||
bool nrf_nvm_safe_flash_page_write(uint32_t page_addr, uint8_t *data) {
|
||||
#ifdef BLUETOOTH_SD
|
||||
uint8_t sd_en = 0;
|
||||
(void) sd_softdevice_is_enabled(&sd_en);
|
||||
if (sd_en) {
|
||||
if (sd_is_enabled()) {
|
||||
uint32_t err_code;
|
||||
sd_flash_operation_status_t status;
|
||||
|
||||
|
|
|
@ -27,4 +27,9 @@
|
|||
|
||||
#define FLASH_PAGE_SIZE (4096)
|
||||
|
||||
#if BLUETOOTH_SD
|
||||
bool sd_flash_page_erase_sync(uint32_t page_number);
|
||||
bool sd_flash_write_sync(uint32_t *dest_words, uint32_t* src_words, uint32_t num_words);
|
||||
#endif
|
||||
|
||||
bool nrf_nvm_safe_flash_page_write(uint32_t page_addr, uint8_t *data);
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Dan Halbert for Adafruit Industries
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
#include "py/runtime.h"
|
||||
#include "nrf_soc.h"
|
||||
|
||||
void sd_mutex_acquire_check(nrf_mutex_t* p_mutex) {
|
||||
uint32_t err_code = sd_mutex_acquire(p_mutex);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg_varg(translate("Failed to acquire mutex, err 0x%04x"), err_code);
|
||||
}
|
||||
}
|
||||
|
||||
void sd_mutex_acquire_wait(nrf_mutex_t* p_mutex) {
|
||||
while (sd_mutex_acquire(p_mutex) == NRF_ERROR_SOC_MUTEX_ALREADY_TAKEN) {
|
||||
RUN_BACKGROUND_TASKS;
|
||||
}
|
||||
}
|
||||
|
||||
void sd_mutex_acquire_wait_no_vm(nrf_mutex_t* p_mutex) {
|
||||
while (sd_mutex_acquire(p_mutex) == NRF_ERROR_SOC_MUTEX_ALREADY_TAKEN) {
|
||||
}
|
||||
}
|
||||
|
||||
void sd_mutex_release_check(nrf_mutex_t* p_mutex) {
|
||||
uint32_t err_code = sd_mutex_release(p_mutex);
|
||||
if (err_code != NRF_SUCCESS) {
|
||||
mp_raise_OSError_msg_varg(translate("Failed to release mutex, err 0x%04x"), err_code);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Dan Halbert for Adafruit Industries
|
||||
*
|
||||
* 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 MICROPY_INCLUDED_NRF_SD_MUTEX_H
|
||||
#define MICROPY_INCLUDED_NRF_SD_MUTEX_H
|
||||
|
||||
#include "nrf_soc.h"
|
||||
|
||||
// Helpers for common usage of nrf_mutex.
|
||||
|
||||
// Try to acquire a mutex right now. Raise exception if we can't get it.
|
||||
void sd_mutex_acquire_check(nrf_mutex_t* p_mutex);
|
||||
|
||||
// Wait for a mutex to become available. Run VM background tasks while waiting.
|
||||
void sd_mutex_acquire_wait(nrf_mutex_t* p_mutex);
|
||||
|
||||
// Wait for a mutex to become available.. Block VM while waiting.
|
||||
void sd_mutex_acquire_wait_no_vm(nrf_mutex_t* p_mutex);
|
||||
|
||||
// Release a mutex, and raise exception on error.
|
||||
void sd_mutex_release_check(nrf_mutex_t* p_mutex);
|
||||
|
||||
#endif // MICROPY_INCLUDED_NRF_SD_MUTEX_H
|
|
@ -128,7 +128,8 @@ STATIC mp_obj_t bleio_characteristic_add_to_service(size_t n_args, const mp_obj_
|
|||
}
|
||||
mp_get_buffer_raise(initial_value, &initial_value_bufinfo, MP_BUFFER_READ);
|
||||
|
||||
bleio_characteristic_obj_t *characteristic = m_new_obj(bleio_characteristic_obj_t);
|
||||
// There may be some cleanup needed when a characteristic is gc'd, so enable finaliser.
|
||||
bleio_characteristic_obj_t *characteristic = m_new_obj_with_finaliser(bleio_characteristic_obj_t);
|
||||
characteristic->base.type = &bleio_characteristic_type;
|
||||
|
||||
// Range checking on max_length arg is done by the common_hal layer, because
|
||||
|
@ -292,8 +293,17 @@ STATIC mp_obj_t bleio_characteristic_set_cccd(mp_uint_t n_args, const mp_obj_t *
|
|||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_characteristic_set_cccd_obj, 1, bleio_characteristic_set_cccd);
|
||||
|
||||
// Cleanup on gc.
|
||||
STATIC mp_obj_t bleio_characteristic_del(mp_obj_t self_in) {
|
||||
bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
common_hal_bleio_characteristic_del(self);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_del_obj, bleio_characteristic_del);
|
||||
|
||||
|
||||
STATIC const mp_rom_map_elem_t bleio_characteristic_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&bleio_characteristic_del_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_add_to_service), MP_ROM_PTR(&bleio_characteristic_add_to_service_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_properties), MP_ROM_PTR(&bleio_characteristic_properties_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_characteristic_uuid_obj) },
|
||||
|
|
|
@ -45,5 +45,6 @@ extern bleio_descriptor_obj_t *common_hal_bleio_characteristic_get_descriptor_li
|
|||
extern bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_characteristic_obj_t *self);
|
||||
extern void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *self, bleio_descriptor_obj_t *descriptor);
|
||||
extern void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate);
|
||||
extern void common_hal_bleio_characteristic_del(bleio_characteristic_obj_t *self);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CHARACTERISTIC_H
|
||||
|
|
Loading…
Reference in New Issue