jeromecoutant 2020-07-15 14:21:20 +02:00
parent ec1e659d3a
commit 0b5a91c9a2
2 changed files with 115 additions and 48 deletions

View File

@ -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;

View File

@ -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;
} }
/* Clear OPTVERR bit set on virgin samples */ if (BLE_inited) {
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR); /*
* 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);
}
/* Get the page number associated to the address */ do {
PageNumber = GetPage(address); /* PESD bit mechanism used by M0+ to protect its timing */
while (LL_FLASH_IsActiveFlag_OperationSuspended());
/* MBED HAL erases 1 page at a time */ core_util_critical_section_enter();
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
EraseInitStruct.Page = PageNumber;
EraseInitStruct.NbPages = 1;
/* Note: If an erase operation in Flash memory also concerns data in the data or instruction cache, /* Trying to access the flash can stall BLE */
you have to make sure that these data are rewritten before they are accessed during code /* Use this semaphore to check M0+ activity */
execution. If this cannot be done safely, it is recommended to flush the caches by setting the cpu1_sem_status = LL_HSEM_GetStatus(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID);
DCRST and ICRST bits in the FLASH_CR register. */ if (cpu1_sem_status == 0) {
if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK) {
status = -1; /* 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 */
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
/* Get the page number associated to the address */
PageNumber = GetPage(address);
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
EraseInitStruct.Page = PageNumber;
EraseInitStruct.NbPages = 1;
if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK) {
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,51 +181,73 @@ 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;
} }
/* Program the user Flash area word by word */ do {
StartAddress = address; /* PESD bit mechanism used by M0+ to protect its timing */
while (LL_FLASH_IsActiveFlag_OperationSuspended());
/* HW needs an aligned address to program flash, which data parameters doesn't ensure */ core_util_critical_section_enter();
if ((uint32_t) data % 8 != 0) { // Data is not aligned, copy data in a temp buffer before programming it
volatile uint64_t data64; /* Trying to access the flash can stall BLE */
while ((address < (StartAddress + size)) && (status == 0)) { /* Use this semaphore to check M0+ activity */
for (uint8_t i = 0; i < 8; i++) { cpu1_sem_status = LL_HSEM_GetStatus(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID);
*(((uint8_t *) &data64) + i) = *(data + i); if (cpu1_sem_status == 0) {
}
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, data64) == HAL_OK) { /* When flash processing is ongoing, the second CPU cannot access the flash anymore */
address = address + 8; cpu2_sem_status = LL_HSEM_1StepLock(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID);
data = data + 8;
} else { if (cpu2_sem_status == 0) {
status = -1;
/* Program the user Flash area word by word */
StartAddress = address;
/* HW needs an aligned address to program flash, which data parameters doesn't ensure */
if ((uint32_t) data % 8 != 0) { // Data is not aligned, copy data in a temp buffer before programming it
volatile uint64_t data64;
while ((address < (StartAddress + size)) && (status == 0)) {
for (uint8_t i = 0; i < 8; i++) {
*(((uint8_t *) &data64) + i) = *(data + i);
}
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, data64) == HAL_OK) {
address = address + 8;
data = data + 8;
} else {
status = -1;
}
}
} else { // Data is aligned, so let's avoid any copy
while ((address < (StartAddress + size)) && (status == 0)) {
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, *((uint64_t *) data)) == HAL_OK) {
address = address + 8;
data = data + 8;
} else {
status = -1;
}
}
}
LL_HSEM_ReleaseLock(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID, 0);
} }
} }
} else { // Data is aligned, so let's avoid any copy
while ((address < (StartAddress + size)) && (status == 0)) { core_util_critical_section_exit();
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, *((uint64_t *) data)) == HAL_OK) { } while ((cpu2_sem_status) || (cpu1_sem_status));
address = address + 8;
data = data + 8; while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY));
} else {
status = -1;
}
}
}
/* 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;
} }