btstack_flash_bank: write empty tag instead of overwriting existing tag with ENABLE_TLV_FLASH_WRITE_ONCE

This commit is contained in:
Matthias Ringwald 2023-01-18 14:24:58 +01:00
parent 5bc527fedb
commit 052e5e4278
3 changed files with 122 additions and 75 deletions

View File

@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## Changed
- GAP: add gap_set_peer_privacy_mode with default LE_PRIVACY_MODE_DEVICE
- bluetooth: indicated identity address in resolved address types
- btstack_flash_bank: write empty tag instead of overwriting existing tag with ENABLE_TLV_FLASH_WRITE_ONCE
## Release v1.5.5

View File

@ -76,7 +76,7 @@ POSIX platform properties:
BTstack properties:
| \#define | Description |
|-----------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------|
|-----------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------|
| ENABLE_CLASSIC | Enable Classic related code in HCI and L2CAP |
| ENABLE_BLE | Enable BLE related code in HCI and L2CAP |
| ENABLE_EHCILL | Enable eHCILL low power mode on TI CC256x/WL18xx chipsets |
@ -112,7 +112,8 @@ BTstack properties:
| ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND | Enable workaround for bug in CC256x Flow Control during baud rate change, see chipset docs. |
| ENABLE_CYPRESS_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND | Enable workaround for bug in CYW2070x Flow Control during baud rate change, similar to CC256x. |
| ENABLE_LE_LIMIT_ACL_FRAGMENT_BY_MAX_OCTETS | Force HCI to fragment ACL-LE packets to fit into over-the-air packet |
| ENABLE_TLV_FLASH_EXPLICIT_DELETE_FIELD | Enable use of explicit delete field in TLV Flash implemenation - required when flash value cannot be overwritten with zero |
| ENABLE_TLV_FLASH_EXPLICIT_DELETE_FIELD | Enable use of explicit delete field in TLV Flash implementation - required when flash value cannot be overwritten with zero |
| ENABLE_TLV_FLASH_WRITE_ONCE | Enable storing of emtpy tag instead of overwriting existing tag - required when flash value cannot be overwritten at all |
| ENABLE_CONTROLLER_WARM_BOOT | Enable stack startup without power cycle (if supported/possible) |
| ENABLE_SEGGER_RTT | Use SEGGER RTT for console output and packet log, see [additional options](#sec:rttConfiguration) |
| ENABLE_EXPLICIT_CONNECTABLE_MODE_CONTROL | Disable calls to control Connectable Mode by L2CAP |

View File

@ -57,12 +57,19 @@
// Most Flash implementations allow to:
// - erase sector -> all values are 0xff
// - write value (1s -> 0s)
// - overwrite value with zero (remaininig 1s -> 0s)
// - overwrite value with zero (remaining 1s -> 0s)
//
// We use the ability to overwrite a value with zeros to mark deleted enttries (by writing zero into the tag field).
// Some targetes, E.g. Kinetix K64F, do enot allow for that.
// Some targets, E.g. Kinetix K64F, do enot allow for that.
//
// With ENABLE_TLV_FLASH_EXPLICIT_DELETE_FIELD an extra field is reserved to indicate a deleted tag, while keeping main logic
//
// With ENABLE_TLV_FLASH_WRITE_ONCE, tags are never marked as deleted. Instead, an emtpy tag will be written instead.
// Also, lookup and migrate requires to always search until the end of the valid bank
#if defined (ENABLE_TLV_FLASH_EXPLICIT_DELETE_FIELD) && defined (ENABLE_TLV_FLASH_WRITE_ONCE)
#error "Please define either ENABLE_TLV_FLASH_EXPLICIT_DELETE_FIELD or ENABLE_TLV_FLASH_WRITE_ONCE"
#endif
#define BTSTACK_TLV_HEADER_LEN 8
@ -255,6 +262,27 @@ static void btstack_tlv_flash_bank_migrate(btstack_tlv_flash_bank_t * self){
uint32_t tag_len = it.len;
uint32_t tag_index = it.offset;
bool tag_valid = true;
#ifdef ENABLE_TLV_FLASH_WRITE_ONCE
// search until end for newer entry of same tag
tlv_iterator_t it2;
memcpy(&it2, &it, sizeof(tlv_iterator_t));
while (btstack_tlv_flash_bank_iterator_has_next(self, &it2)){
if ((it2.offset != it.offset) && (it2.tag == it.tag)){
tag_valid = false;
break;
}
tlv_iterator_fetch_next(self, &it2);
}
if (tag_valid == false){
log_info("skip pos %u, tag '%x' as newer entry found at %u", (unsigned int) tag_index, (unsigned int) it.tag,
(unsigned int) it2.offset);
}
#endif
if (tag_valid) {
log_info("migrate pos %u, tag '%x' len %u -> new pos %u",
(unsigned int) tag_index, (unsigned int) it.tag, (unsigned int) tag_len, next_write_pos);
@ -281,6 +309,7 @@ static void btstack_tlv_flash_bank_migrate(btstack_tlv_flash_bank_t * self){
next_write_pos += bytes_this_iteration;
bytes_to_copy -= bytes_this_iteration;
}
}
}
tlv_iterator_fetch_next(self, &it);
}
@ -293,6 +322,7 @@ static void btstack_tlv_flash_bank_migrate(btstack_tlv_flash_bank_t * self){
self->write_offset = next_write_pos;
}
#ifndef ENABLE_TLV_FLASH_WRITE_ONCE
static void btstack_tlv_flash_bank_delete_tag_until_offset(btstack_tlv_flash_bank_t * self, uint32_t tag, uint32_t offset){
tlv_iterator_t it;
btstack_tlv_flash_bank_iterator_init(self, &it, self->current_bank);
@ -314,6 +344,7 @@ static void btstack_tlv_flash_bank_delete_tag_until_offset(btstack_tlv_flash_ban
tlv_iterator_fetch_next(self, &it);
}
}
#endif
/**
* Get Value for Tag
@ -335,7 +366,9 @@ static int btstack_tlv_flash_bank_get_tag(void * context, uint32_t tag, uint8_t
log_info("Found tag '%x' at position %u", (unsigned int) tag, (unsigned int) it.offset);
tag_index = it.offset;
tag_len = it.len;
#ifndef ENABLE_TLV_FLASH_WRITE_ONCE
break;
#endif
}
tlv_iterator_fetch_next(self, &it);
}
@ -391,8 +424,10 @@ static int btstack_tlv_flash_bank_store_tag(void * context, uint32_t tag, const
// then entry
btstack_tlv_flash_bank_write(self, self->current_bank, self->write_offset, entry, sizeof(entry));
#ifndef ENABLE_TLV_FLASH_WRITE_ONCE
// overwrite old entries (if exists)
btstack_tlv_flash_bank_delete_tag_until_offset(self, tag, self->write_offset);
#endif
// done
self->write_offset += sizeof(entry) + btstack_tlv_flash_bank_align_size(self, data_size);
@ -410,8 +445,12 @@ static int btstack_tlv_flash_bank_store_tag(void * context, uint32_t tag, const
* @param tag
*/
static void btstack_tlv_flash_bank_delete_tag(void * context, uint32_t tag){
#ifdef ENABLE_TLV_FLASH_WRITE_ONCE
btstack_tlv_flash_bank_store_tag(context, tag, NULL, 0);
#else
btstack_tlv_flash_bank_t * self = (btstack_tlv_flash_bank_t *) context;
btstack_tlv_flash_bank_delete_tag_until_offset(self, tag, self->write_offset);
#endif
}
static const btstack_tlv_t btstack_tlv_flash_bank = {
@ -447,23 +486,29 @@ const btstack_tlv_t * btstack_tlv_flash_bank_init_instance(btstack_tlv_flash_ban
// find last entry and write offset
tlv_iterator_t it;
#ifndef ENABLE_TLV_FLASH_WRITE_ONCE
uint32_t last_tag = 0;
uint32_t last_offset = 0;
#endif
btstack_tlv_flash_bank_iterator_init(self, &it, self->current_bank);
while (btstack_tlv_flash_bank_iterator_has_next(self, &it)){
#ifndef ENABLE_TLV_FLASH_WRITE_ONCE
last_tag = it.tag;
last_offset = it.offset;
#endif
tlv_iterator_fetch_next(self, &it);
}
self->write_offset = it.offset;
if (self->write_offset < self->hal_flash_bank_impl->get_size(self->hal_flash_bank_context)){
#ifndef ENABLE_TLV_FLASH_WRITE_ONCE
// delete older instances of last_tag
// this handles the unlikely case where MCU did reset after new value + header was written but before delete did complete
if (last_tag){
btstack_tlv_flash_bank_delete_tag_until_offset(self, last_tag, last_offset);
}
#endif
// verify that rest of bank is empty
// this handles the unlikely case where MCU did reset after new value was written, but not the tag