stm32/flash: Implement WB55 flash locking.
This is needed to moderate concurrent access to the internal flash, as while an erase/write is in progress execution will stall on the wireless core due to the bus being locked. This implements Figure 10 from AN5289 Rev 3. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
This commit is contained in:
parent
a64121b0d4
commit
119c88ef17
@ -29,6 +29,21 @@
|
|||||||
#include "py/mphal.h"
|
#include "py/mphal.h"
|
||||||
#include "flash.h"
|
#include "flash.h"
|
||||||
|
|
||||||
|
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
|
||||||
|
// See WB55 specific documentation in AN5289 Rev 3, and in particular, Figure 10.
|
||||||
|
|
||||||
|
#include "rfcore.h"
|
||||||
|
#include "stm32wbxx_ll_hsem.h"
|
||||||
|
|
||||||
|
// Protects all flash registers.
|
||||||
|
#define SEMID_FLASH_REGISTERS (2)
|
||||||
|
// Used by CPU1 to prevent CPU2 from writing/erasing data in flash memory.
|
||||||
|
#define SEMID_FLASH_CPU1 (6)
|
||||||
|
// Used by CPU2 to prevent CPU1 from writing/erasing data in flash memory.
|
||||||
|
#define SEMID_FLASH_CPU2 (7)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t base_address;
|
uint32_t base_address;
|
||||||
uint32_t sector_size;
|
uint32_t sector_size;
|
||||||
@ -181,9 +196,27 @@ int flash_erase(uint32_t flash_dest, uint32_t num_word32) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
|
||||||
|
// Acquire lock on the flash peripheral.
|
||||||
|
while (LL_HSEM_1StepLock(HSEM, SEMID_FLASH_REGISTERS)) {
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Unlock the flash for erase.
|
// Unlock the flash for erase.
|
||||||
HAL_FLASH_Unlock();
|
HAL_FLASH_Unlock();
|
||||||
|
|
||||||
|
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
|
||||||
|
// Tell the HCI controller stack we're starting an erase, so it
|
||||||
|
// avoids radio activity for a while.
|
||||||
|
rfcore_start_flash_erase();
|
||||||
|
// Wait for PES.
|
||||||
|
while (LL_FLASH_IsActiveFlag_OperationSuspended()) {
|
||||||
|
}
|
||||||
|
// Wait for flash lock.
|
||||||
|
while (LL_HSEM_1StepLock(HSEM, SEMID_FLASH_CPU2)) {
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Clear pending flags (if any) and set up EraseInitStruct.
|
// Clear pending flags (if any) and set up EraseInitStruct.
|
||||||
|
|
||||||
FLASH_EraseInitTypeDef EraseInitStruct;
|
FLASH_EraseInitTypeDef EraseInitStruct;
|
||||||
@ -233,9 +266,23 @@ int flash_erase(uint32_t flash_dest, uint32_t num_word32) {
|
|||||||
uint32_t SectorError = 0;
|
uint32_t SectorError = 0;
|
||||||
HAL_StatusTypeDef status = HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError);
|
HAL_StatusTypeDef status = HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError);
|
||||||
|
|
||||||
|
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
|
||||||
|
// Release flash lock.
|
||||||
|
while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY)) {
|
||||||
|
}
|
||||||
|
LL_HSEM_ReleaseLock(HSEM, SEMID_FLASH_CPU2, 0);
|
||||||
|
// Tell HCI controller that erase is over.
|
||||||
|
rfcore_end_flash_erase();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Lock the flash after erase.
|
// Lock the flash after erase.
|
||||||
HAL_FLASH_Lock();
|
HAL_FLASH_Lock();
|
||||||
|
|
||||||
|
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
|
||||||
|
// Release lock on the flash peripheral.
|
||||||
|
LL_HSEM_ReleaseLock(HSEM, SEMID_FLASH_REGISTERS, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
return mp_hal_status_to_neg_errno(status);
|
return mp_hal_status_to_neg_errno(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,9 +316,21 @@ void flash_erase_it(uint32_t flash_dest, uint32_t num_word32) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) {
|
int flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) {
|
||||||
|
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
|
||||||
|
// Acquire lock on the flash peripheral.
|
||||||
|
while (LL_HSEM_1StepLock(HSEM, SEMID_FLASH_REGISTERS)) {
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Unlock the flash for write.
|
// Unlock the flash for write.
|
||||||
HAL_FLASH_Unlock();
|
HAL_FLASH_Unlock();
|
||||||
|
|
||||||
|
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
|
||||||
|
// Wait for PES.
|
||||||
|
while (LL_FLASH_IsActiveFlag_OperationSuspended()) {
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
HAL_StatusTypeDef status = HAL_OK;
|
HAL_StatusTypeDef status = HAL_OK;
|
||||||
|
|
||||||
#if defined(STM32L4) || defined(STM32WB)
|
#if defined(STM32L4) || defined(STM32WB)
|
||||||
@ -279,7 +338,22 @@ int flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) {
|
|||||||
// program the flash uint64 by uint64
|
// program the flash uint64 by uint64
|
||||||
for (int i = 0; i < num_word32 / 2; i++) {
|
for (int i = 0; i < num_word32 / 2; i++) {
|
||||||
uint64_t val = *(uint64_t *)src;
|
uint64_t val = *(uint64_t *)src;
|
||||||
|
|
||||||
|
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
|
||||||
|
// Wait for flash lock.
|
||||||
|
while (LL_HSEM_1StepLock(HSEM, SEMID_FLASH_CPU2)) {
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, flash_dest, val);
|
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, flash_dest, val);
|
||||||
|
|
||||||
|
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
|
||||||
|
// Release flash lock.
|
||||||
|
LL_HSEM_ReleaseLock(HSEM, SEMID_FLASH_CPU2, 0);
|
||||||
|
while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY)) {
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (status != HAL_OK) {
|
if (status != HAL_OK) {
|
||||||
num_word32 = 0; // don't write any odd word after this loop
|
num_word32 = 0; // don't write any odd word after this loop
|
||||||
break;
|
break;
|
||||||
@ -290,7 +364,21 @@ int flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) {
|
|||||||
if ((num_word32 & 0x01) == 1) {
|
if ((num_word32 & 0x01) == 1) {
|
||||||
uint64_t val = *(uint64_t *)flash_dest;
|
uint64_t val = *(uint64_t *)flash_dest;
|
||||||
val = (val & 0xffffffff00000000uL) | (*src);
|
val = (val & 0xffffffff00000000uL) | (*src);
|
||||||
|
|
||||||
|
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
|
||||||
|
// Wait for flash lock.
|
||||||
|
while (LL_HSEM_1StepLock(HSEM, SEMID_FLASH_CPU2)) {
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, flash_dest, val);
|
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, flash_dest, val);
|
||||||
|
|
||||||
|
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
|
||||||
|
// Release flash lock.
|
||||||
|
LL_HSEM_ReleaseLock(HSEM, SEMID_FLASH_CPU2, 0);
|
||||||
|
while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY)) {
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(STM32H7)
|
#elif defined(STM32H7)
|
||||||
@ -322,6 +410,11 @@ int flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) {
|
|||||||
// Lock the flash after write.
|
// Lock the flash after write.
|
||||||
HAL_FLASH_Lock();
|
HAL_FLASH_Lock();
|
||||||
|
|
||||||
|
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
|
||||||
|
// Release lock on the flash peripheral.
|
||||||
|
LL_HSEM_ReleaseLock(HSEM, SEMID_FLASH_REGISTERS, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
return mp_hal_status_to_neg_errno(status);
|
return mp_hal_status_to_neg_errno(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,6 +73,7 @@ CFLAGS += -DFFCONF_H=\"ports/stm32/mboot/ffconf.h\"
|
|||||||
CFLAGS += -DLFS1_NO_MALLOC -DLFS1_NO_DEBUG -DLFS1_NO_WARN -DLFS1_NO_ERROR -DLFS1_NO_ASSERT
|
CFLAGS += -DLFS1_NO_MALLOC -DLFS1_NO_DEBUG -DLFS1_NO_WARN -DLFS1_NO_ERROR -DLFS1_NO_ASSERT
|
||||||
CFLAGS += -DLFS2_NO_MALLOC -DLFS2_NO_DEBUG -DLFS2_NO_WARN -DLFS2_NO_ERROR -DLFS2_NO_ASSERT
|
CFLAGS += -DLFS2_NO_MALLOC -DLFS2_NO_DEBUG -DLFS2_NO_WARN -DLFS2_NO_ERROR -DLFS2_NO_ASSERT
|
||||||
CFLAGS += -DBUILDING_MBOOT=1
|
CFLAGS += -DBUILDING_MBOOT=1
|
||||||
|
CFLAGS += -DMICROPY_HW_STM32WB_FLASH_SYNCRONISATION=0
|
||||||
CFLAGS += -DBOOTLOADER_DFU_USB_VID=$(BOOTLOADER_DFU_USB_VID) -DBOOTLOADER_DFU_USB_PID=$(BOOTLOADER_DFU_USB_PID)
|
CFLAGS += -DBOOTLOADER_DFU_USB_VID=$(BOOTLOADER_DFU_USB_VID) -DBOOTLOADER_DFU_USB_PID=$(BOOTLOADER_DFU_USB_PID)
|
||||||
|
|
||||||
LDFLAGS = -nostdlib -L . -T stm32_generic.ld -Map=$(@:.elf=.map) --cref
|
LDFLAGS = -nostdlib -L . -T stm32_generic.ld -Map=$(@:.elf=.map) --cref
|
||||||
|
@ -216,6 +216,10 @@
|
|||||||
#define MICROPY_HW_MAX_TIMER (17)
|
#define MICROPY_HW_MAX_TIMER (17)
|
||||||
#define MICROPY_HW_MAX_UART (1)
|
#define MICROPY_HW_MAX_UART (1)
|
||||||
|
|
||||||
|
#ifndef MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
|
||||||
|
#define MICROPY_HW_STM32WB_FLASH_SYNCRONISATION (1)
|
||||||
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#error Unsupported MCU series
|
#error Unsupported MCU series
|
||||||
#endif
|
#endif
|
||||||
|
@ -57,10 +57,12 @@
|
|||||||
#define OCF_CB_RESET (0x03)
|
#define OCF_CB_RESET (0x03)
|
||||||
#define OCF_CB_SET_EVENT_MASK2 (0x63)
|
#define OCF_CB_SET_EVENT_MASK2 (0x63)
|
||||||
|
|
||||||
#define OGF_VENDOR (0x3f)
|
#define OGF_VENDOR (0x3f)
|
||||||
#define OCF_WRITE_CONFIG (0x0c)
|
#define OCF_WRITE_CONFIG (0x0c)
|
||||||
#define OCF_SET_TX_POWER (0x0f)
|
#define OCF_SET_TX_POWER (0x0f)
|
||||||
#define OCF_BLE_INIT (0x66)
|
#define OCF_BLE_INIT (0x66)
|
||||||
|
#define OCF_C2_FLASH_ERASE_ACTIVITY (0x69)
|
||||||
|
#define OCF_C2_SET_FLASH_ACTIVITY_CONTROL (0x73)
|
||||||
|
|
||||||
#define HCI_OPCODE(ogf, ocf) ((ogf) << 10 | (ocf))
|
#define HCI_OPCODE(ogf, ocf) ((ogf) << 10 | (ocf))
|
||||||
|
|
||||||
@ -557,6 +559,10 @@ void rfcore_ble_init(void) {
|
|||||||
// Configure and reset the BLE controller.
|
// Configure and reset the BLE controller.
|
||||||
tl_sys_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_BLE_INIT), (const uint8_t *)&ble_init_params, sizeof(ble_init_params), 0);
|
tl_sys_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_BLE_INIT), (const uint8_t *)&ble_init_params, sizeof(ble_init_params), 0);
|
||||||
tl_ble_hci_cmd_resp(HCI_OPCODE(0x03, 0x0003), NULL, 0);
|
tl_ble_hci_cmd_resp(HCI_OPCODE(0x03, 0x0003), NULL, 0);
|
||||||
|
|
||||||
|
// Enable PES rather than SEM7 to moderate flash access between the cores.
|
||||||
|
uint8_t buf = 0; // FLASH_ACTIVITY_CONTROL_PES
|
||||||
|
tl_sys_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_C2_SET_FLASH_ACTIVITY_CONTROL), &buf, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rfcore_ble_hci_cmd(size_t len, const uint8_t *src) {
|
void rfcore_ble_hci_cmd(size_t len, const uint8_t *src) {
|
||||||
@ -616,6 +622,16 @@ void rfcore_ble_set_txpower(uint8_t level) {
|
|||||||
tl_ble_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_SET_TX_POWER), buf, 2);
|
tl_ble_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_SET_TX_POWER), buf, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rfcore_start_flash_erase(void) {
|
||||||
|
uint8_t buf = 1; // ERASE_ACTIVITY_ON
|
||||||
|
tl_sys_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_C2_FLASH_ERASE_ACTIVITY), &buf, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rfcore_end_flash_erase(void) {
|
||||||
|
uint8_t buf = 0; // ERASE_ACTIVITY_OFF
|
||||||
|
tl_sys_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_C2_FLASH_ERASE_ACTIVITY), &buf, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// IPCC IRQ Handlers
|
// IPCC IRQ Handlers
|
||||||
void IPCC_C1_TX_IRQHandler(void) {
|
void IPCC_C1_TX_IRQHandler(void) {
|
||||||
IRQ_ENTER(IPCC_C1_TX_IRQn);
|
IRQ_ENTER(IPCC_C1_TX_IRQn);
|
||||||
|
@ -35,6 +35,9 @@ void rfcore_ble_hci_cmd(size_t len, const uint8_t *src);
|
|||||||
void rfcore_ble_check_msg(int (*cb)(void *, const uint8_t *, size_t), void *env);
|
void rfcore_ble_check_msg(int (*cb)(void *, const uint8_t *, size_t), void *env);
|
||||||
void rfcore_ble_set_txpower(uint8_t level);
|
void rfcore_ble_set_txpower(uint8_t level);
|
||||||
|
|
||||||
|
void rfcore_start_flash_erase(void);
|
||||||
|
void rfcore_end_flash_erase(void);
|
||||||
|
|
||||||
MP_DECLARE_CONST_FUN_OBJ_0(rfcore_status_obj);
|
MP_DECLARE_CONST_FUN_OBJ_0(rfcore_status_obj);
|
||||||
MP_DECLARE_CONST_FUN_OBJ_1(rfcore_fw_version_obj);
|
MP_DECLARE_CONST_FUN_OBJ_1(rfcore_fw_version_obj);
|
||||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(rfcore_sys_hci_obj);
|
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(rfcore_sys_hci_obj);
|
||||||
|
Loading…
Reference in New Issue
Block a user