mirror of https://github.com/ARMmbed/mbed-os.git
STM32WB FLASH activity shared with M0+ core
source: - https://github.com/STMicroelectronics/STM32CubeWB/blob/master/Projects/P-NUCLEO-WB55.Nucleo/Applications/BLE/BLE_RfWithFlash/Core/Src/flash_driver.c - Figure 10 from AN5289pull/13304/head
parent
ec1e659d3a
commit
0b5a91c9a2
|
@ -86,6 +86,7 @@ static bool get_bd_address(uint8_t *bd_addr);
|
||||||
static bool sysevt_wait(void);
|
static bool sysevt_wait(void);
|
||||||
static bool sysevt_check(void);
|
static bool sysevt_check(void);
|
||||||
|
|
||||||
|
extern int BLE_inited;
|
||||||
|
|
||||||
namespace ble {
|
namespace ble {
|
||||||
namespace vendor {
|
namespace vendor {
|
||||||
|
@ -675,6 +676,9 @@ private:
|
||||||
* Starts the BLE Stack on CPU2
|
* Starts the BLE Stack on CPU2
|
||||||
*/
|
*/
|
||||||
SHCI_C2_BLE_Init(&ble_init_cmd_packet);
|
SHCI_C2_BLE_Init(&ble_init_cmd_packet);
|
||||||
|
|
||||||
|
/* Used in flash_api.c */
|
||||||
|
BLE_inited = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
TL_CmdPacket_t *bleCmdBuf;
|
TL_CmdPacket_t *bleCmdBuf;
|
||||||
|
|
|
@ -27,6 +27,10 @@
|
||||||
/* Family specific include for WB with HW semaphores */
|
/* Family specific include for WB with HW semaphores */
|
||||||
#include "hw.h"
|
#include "hw.h"
|
||||||
#include "hw_conf.h"
|
#include "hw_conf.h"
|
||||||
|
#include "shci.h"
|
||||||
|
|
||||||
|
/* Used in HCIDriver.cpp/stm32wb_start_ble() */
|
||||||
|
int BLE_inited = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the page of a given address
|
* @brief Gets the page of a given address
|
||||||
|
@ -71,47 +75,82 @@ int32_t flash_erase_sector(flash_t *obj, uint32_t address)
|
||||||
uint32_t PAGEError = 0;
|
uint32_t PAGEError = 0;
|
||||||
FLASH_EraseInitTypeDef EraseInitStruct;
|
FLASH_EraseInitTypeDef EraseInitStruct;
|
||||||
int32_t status = 0;
|
int32_t status = 0;
|
||||||
|
uint32_t cpu1_sem_status = 1;
|
||||||
|
uint32_t cpu2_sem_status = 1;
|
||||||
|
|
||||||
if ((address >= (FLASH_BASE + FLASH_SIZE)) || (address < FLASH_BASE)) {
|
if ((address >= (FLASH_BASE + FLASH_SIZE)) || (address < FLASH_BASE)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CFG_HW_FLASH_SEMID)
|
/* Flash IP semaphore */
|
||||||
/* In case RNG is a shared ressource, get the HW semaphore first */
|
|
||||||
while (LL_HSEM_1StepLock(HSEM, CFG_HW_FLASH_SEMID));
|
while (LL_HSEM_1StepLock(HSEM, CFG_HW_FLASH_SEMID));
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Unlock the Flash to enable the flash control register access */
|
/* Unlock the Flash to enable the flash control register access */
|
||||||
if (HAL_FLASH_Unlock() != HAL_OK) {
|
if (HAL_FLASH_Unlock() != HAL_OK) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (BLE_inited) {
|
||||||
|
/*
|
||||||
|
* Notify the CPU2 that some flash erase activity may be executed
|
||||||
|
* On reception of this command, the CPU2 enables the BLE timing protection versus flash erase processing
|
||||||
|
* The Erase flash activity will be executed only when the BLE RF is idle for at least 25ms
|
||||||
|
* The CPU2 will prevent all flash activity (write or erase) in all cases when the BL RF Idle is shorter than 25ms.
|
||||||
|
*/
|
||||||
|
SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_ON);
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
/* PESD bit mechanism used by M0+ to protect its timing */
|
||||||
|
while (LL_FLASH_IsActiveFlag_OperationSuspended());
|
||||||
|
|
||||||
|
core_util_critical_section_enter();
|
||||||
|
|
||||||
|
/* Trying to access the flash can stall BLE */
|
||||||
|
/* Use this semaphore to check M0+ activity */
|
||||||
|
cpu1_sem_status = LL_HSEM_GetStatus(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID);
|
||||||
|
if (cpu1_sem_status == 0) {
|
||||||
|
|
||||||
|
/* When flash processing is ongoing, the second CPU cannot access the flash anymore */
|
||||||
|
cpu2_sem_status = LL_HSEM_1StepLock(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID);
|
||||||
|
|
||||||
|
if (cpu2_sem_status == 0) {
|
||||||
/* Clear OPTVERR bit set on virgin samples */
|
/* Clear OPTVERR bit set on virgin samples */
|
||||||
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
|
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
|
||||||
|
|
||||||
/* Get the page number associated to the address */
|
/* Get the page number associated to the address */
|
||||||
PageNumber = GetPage(address);
|
PageNumber = GetPage(address);
|
||||||
|
|
||||||
/* MBED HAL erases 1 page at a time */
|
|
||||||
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
|
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
|
||||||
EraseInitStruct.Page = PageNumber;
|
EraseInitStruct.Page = PageNumber;
|
||||||
EraseInitStruct.NbPages = 1;
|
EraseInitStruct.NbPages = 1;
|
||||||
|
|
||||||
/* Note: If an erase operation in Flash memory also concerns data in the data or instruction cache,
|
|
||||||
you have to make sure that these data are rewritten before they are accessed during code
|
|
||||||
execution. If this cannot be done safely, it is recommended to flush the caches by setting the
|
|
||||||
DCRST and ICRST bits in the FLASH_CR register. */
|
|
||||||
if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK) {
|
if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK) {
|
||||||
status = -1;
|
status = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LL_HSEM_ReleaseLock(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
core_util_critical_section_exit();
|
||||||
|
} while ((cpu2_sem_status) || (cpu1_sem_status));
|
||||||
|
|
||||||
|
while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY));
|
||||||
|
|
||||||
|
if (BLE_inited) {
|
||||||
|
/**
|
||||||
|
* Notify the CPU2 there will be no request anymore to erase the flash
|
||||||
|
* On reception of this command, the CPU2 disables the BLE timing protection versus flash erase processing
|
||||||
|
*/
|
||||||
|
SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_OFF);
|
||||||
|
}
|
||||||
|
|
||||||
/* Lock the Flash to disable the flash control register access (recommended
|
/* Lock the Flash to disable the flash control register access (recommended
|
||||||
to protect the FLASH memory against possible unwanted operation) */
|
to protect the FLASH memory against possible unwanted operation) */
|
||||||
HAL_FLASH_Lock();
|
HAL_FLASH_Lock();
|
||||||
|
|
||||||
#if defined(CFG_HW_FLASH_SEMID)
|
/* Flash IP semaphore */
|
||||||
LL_HSEM_ReleaseLock(HSEM, CFG_HW_FLASH_SEMID, 0);
|
LL_HSEM_ReleaseLock(HSEM, CFG_HW_FLASH_SEMID, 0);
|
||||||
#endif
|
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -131,6 +170,8 @@ int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data,
|
||||||
{
|
{
|
||||||
uint32_t StartAddress = 0;
|
uint32_t StartAddress = 0;
|
||||||
int32_t status = 0;
|
int32_t status = 0;
|
||||||
|
uint32_t cpu1_sem_status = 1;
|
||||||
|
uint32_t cpu2_sem_status = 1;
|
||||||
|
|
||||||
if ((address >= (FLASH_BASE + FLASH_SIZE)) || (address < FLASH_BASE)) {
|
if ((address >= (FLASH_BASE + FLASH_SIZE)) || (address < FLASH_BASE)) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -140,16 +181,30 @@ int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CFG_HW_FLASH_SEMID)
|
/* Flash IP semaphore */
|
||||||
/* In case RNG is a shared ressource, get the HW semaphore first */
|
|
||||||
while (LL_HSEM_1StepLock(HSEM, CFG_HW_FLASH_SEMID));
|
while (LL_HSEM_1StepLock(HSEM, CFG_HW_FLASH_SEMID));
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Unlock the Flash to enable the flash control register access */
|
/* Unlock the Flash to enable the flash control register access */
|
||||||
if (HAL_FLASH_Unlock() != HAL_OK) {
|
if (HAL_FLASH_Unlock() != HAL_OK) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
/* PESD bit mechanism used by M0+ to protect its timing */
|
||||||
|
while (LL_FLASH_IsActiveFlag_OperationSuspended());
|
||||||
|
|
||||||
|
core_util_critical_section_enter();
|
||||||
|
|
||||||
|
/* Trying to access the flash can stall BLE */
|
||||||
|
/* Use this semaphore to check M0+ activity */
|
||||||
|
cpu1_sem_status = LL_HSEM_GetStatus(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID);
|
||||||
|
if (cpu1_sem_status == 0) {
|
||||||
|
|
||||||
|
/* When flash processing is ongoing, the second CPU cannot access the flash anymore */
|
||||||
|
cpu2_sem_status = LL_HSEM_1StepLock(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID);
|
||||||
|
|
||||||
|
if (cpu2_sem_status == 0) {
|
||||||
|
|
||||||
/* Program the user Flash area word by word */
|
/* Program the user Flash area word by word */
|
||||||
StartAddress = address;
|
StartAddress = address;
|
||||||
|
|
||||||
|
@ -178,13 +233,21 @@ int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LL_HSEM_ReleaseLock(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
core_util_critical_section_exit();
|
||||||
|
} while ((cpu2_sem_status) || (cpu1_sem_status));
|
||||||
|
|
||||||
|
while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY));
|
||||||
|
|
||||||
/* Lock the Flash to disable the flash control register access (recommended
|
/* Lock the Flash to disable the flash control register access (recommended
|
||||||
to protect the FLASH memory against possible unwanted operation) */
|
to protect the FLASH memory against possible unwanted operation) */
|
||||||
HAL_FLASH_Lock();
|
HAL_FLASH_Lock();
|
||||||
|
|
||||||
#if defined(CFG_HW_FLASH_SEMID)
|
/* Flash IP semaphore */
|
||||||
LL_HSEM_ReleaseLock(HSEM, CFG_HW_FLASH_SEMID, 0);
|
LL_HSEM_ReleaseLock(HSEM, CFG_HW_FLASH_SEMID, 0);
|
||||||
#endif
|
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue