Skip to content

Commit

Permalink
fix: sync uart and flash for wba (#453)
Browse files Browse the repository at this point in the history
* fix: receive on sync uart

* fix: sync flash write

* fix erase for dual bank mcus
  • Loading branch information
andjordan authored Nov 18, 2024
1 parent d7204bd commit feb8b53
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 69 deletions.
113 changes: 54 additions & 59 deletions hal_st/synchronous_stm32fxxx/SynchronousFlashInternalStm.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
#include "hal_st/synchronous_stm32fxxx/SynchronousFlashInternalStm.hpp"
#include "services/util/FlashAlign.hpp"
#include "hal_st/stm32fxxx/FlashInternalStmDetail.hpp"

namespace
{
struct uint128_t
{
#ifdef __ARM_BIG_ENDIAN
uint64_t high;
uint64_t low;
#else
uint64_t low;
uint64_t high;
#endif
};

#if defined(FLASH_DBANK_SUPPORT)
uint32_t GetBank(uint32_t sectorIndex)
{
return sectorIndex < FLASH_PAGE_NB ? FLASH_BANK_1 : FLASH_BANK_2;
}
#endif
}

namespace hal
{
Expand All @@ -10,13 +31,12 @@ namespace hal
void SynchronousFlashInternalStmBase::WriteBuffer(infra::ConstByteRange buffer, uint32_t address)
{
HAL_FLASH_Unlock();
const auto flashBegin = reinterpret_cast<uint32_t>(flashMemory.begin());

#if defined(STM32WBA)
AlignedWriteBuffer(buffer, address);
#if defined(STM32WBA) || defined(STM32H5)
detail::AlignedWriteBuffer<uint128_t, FLASH_TYPEPROGRAM_QUADWORD, true>(buffer, address, flashBegin);
#elif defined(STM32WB) || defined(STM32G4) || defined(STM32G0)
AlignedWriteBuffer<uint64_t, FLASH_TYPEPROGRAM_DOUBLEWORD>(buffer, address);
#elif defined(STM32WBA)
AlignedWriteBuffer<uint64_t, FLASH_TYPEPROGRAM_QUADWORD>(buffer, address);
detail::AlignedWriteBuffer<uint64_t, FLASH_TYPEPROGRAM_DOUBLEWORD, false>(buffer, address, flashBegin);
#else
uint32_t word;
while (buffer.size() >= sizeof(word) && ((address & (sizeof(word) - 1)) == 0))
Expand All @@ -30,7 +50,7 @@ namespace hal
#endif

#if defined(STM32F0) || defined(STM32F3)
AlignedWriteBuffer<uint16_t, FLASH_TYPEPROGRAM_HALFWORD>(buffer, address);
detail::AlignedWriteBuffer<uint16_t, FLASH_TYPEPROGRAM_HALFWORD, false>(buffer, address);
#elif !defined(STM32WB) && !defined(STM32G4) && !defined(STM32G0) && !defined(STM32WBA)
for (uint8_t byte : buffer)
{
Expand All @@ -53,15 +73,35 @@ namespace hal
HAL_FLASH_Unlock();

#if defined(STM32WB) || defined(STM32G4) || defined(STM32G0) || defined(STM32WBA)
uint32_t pageError = 0;

FLASH_EraseInitTypeDef eraseInitStruct;
eraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
eraseInitStruct.Page = beginIndex;
eraseInitStruct.NbPages = endIndex - beginIndex;
auto erase = [](uint32_t beginIndex, uint32_t nbPages, uint32_t bank)
{
uint32_t sectorError = 0;

FLASH_EraseInitTypeDef eraseInitStruct{};
#if defined(FLASH_DBANK_SUPPORT)
eraseInitStruct.Banks = bank;
#endif
eraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
eraseInitStruct.Page = beginIndex;
eraseInitStruct.NbPages = nbPages;

auto result = HAL_FLASHEx_Erase(&eraseInitStruct, &sectorError);
really_assert(result == HAL_OK);
};

#if defined(FLASH_DBANK_SUPPORT)
if (GetBank(beginIndex) == GetBank(endIndex - 1))
erase(beginIndex % FLASH_PAGE_NB, endIndex - beginIndex, GetBank(beginIndex));
else
{
erase(beginIndex, FLASH_PAGE_NB - beginIndex, FLASH_BANK_1);
erase(0, endIndex - FLASH_PAGE_NB + 1, FLASH_BANK_2);
}
#else
erase(beginIndex, endIndex - beginIndex, 0);
#endif

auto result = HAL_FLASHEx_Erase(&eraseInitStruct, &pageError);
really_assert(result == HAL_OK);
#else
for (uint32_t index = beginIndex; index != endIndex; ++index)
{
Expand All @@ -79,51 +119,6 @@ namespace hal
HAL_FLASH_Lock();
}

template<typename alignment, uint32_t flashType>
void SynchronousFlashInternalStmBase::AlignedWriteBuffer(infra::ConstByteRange buffer, uint32_t address)
{
services::FlashAlign::WithAlignment<sizeof(alignment)> flashAlign;
flashAlign.Align(address, buffer);

services::FlashAlign::Chunk* chunk = flashAlign.First();
while (chunk != nullptr)
{
really_assert(chunk->data.size() % sizeof(alignment) == 0);
auto fullAddress = reinterpret_cast<uint32_t>(flashMemory.begin() + chunk->alignedAddress);

for (alignment data : infra::ReinterpretCastMemoryRange<const alignment>(chunk->data))
{
auto result = HAL_FLASH_Program(flashType, fullAddress, data);
really_assert(result == HAL_OK);
fullAddress += sizeof(alignment);
}
chunk = flashAlign.Next();
}
}

#ifdef STM32WBA
const uint8_t alignment = sizeof(uint64_t) * 2;
void SynchronousFlashInternalStmBase::AlignedWriteBuffer(infra::ConstByteRange buffer, uint32_t address)
{
services::FlashAlign::WithAlignment<alignment> flashAlign;
flashAlign.Align(address, buffer);

services::FlashAlign::Chunk* chunk = flashAlign.First();
auto dataSize = chunk->data.size();
while (chunk != nullptr)
{
really_assert(chunk->data.size() % sizeof(alignment) == 0);
auto fullAddress = reinterpret_cast<uint32_t>(flashMemory.begin() + chunk->alignedAddress);

uint32_t addr = reinterpret_cast<uint32_t>(chunk->data.begin());
auto result = HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, fullAddress, addr);
really_assert(result == HAL_OK);
fullAddress += alignment;
chunk = flashAlign.Next();
}
}
#endif

SynchronousFlashInternalStm::SynchronousFlashInternalStm(infra::MemoryRange<uint32_t> sectorSizes, infra::ConstByteRange flashMemory)
: SynchronousFlashInternalStmBase(flashMemory)
, sectorSizes(sectorSizes)
Expand Down
14 changes: 4 additions & 10 deletions hal_st/synchronous_stm32fxxx/SynchronousUartStm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,15 @@ namespace hal
uartHandle.Init.Parity = USART_PARITY_NONE;
uartHandle.Init.Mode = USART_MODE_TX_RX;
uartHandle.Init.HwFlowCtl = flowControl;
#if defined(STM32F0) || defined(STM32F3) || defined(STM32F7) || defined(STM32WB)
uartHandle.Init.OverSampling = USART_OVERSAMPLING_8;
#if defined(UART_ONE_BIT_SAMPLE_ENABLE)
uartHandle.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_ENABLE;
#else
uartHandle.Init.OverSampling = UART_OVERSAMPLING_8;
#endif
uartHandle.Init.OverSampling = UART_OVERSAMPLING_8;

HAL_UART_Init(&uartHandle);

peripheralUart[uartIndex]->CR2 &= ~USART_CLOCK_ENABLED;

#if defined(STM32F0) || defined(STM32F1) || defined(STM32F3) || defined(STM32F7) || defined(STM32WB) || defined(STM32G4) || defined(STM32G0)
peripheralUart[uartIndex]->CR1 |= 1 << (USART_IT_RXNE & USART_IT_MASK);
#else
peripheralUart[uartIndex]->CR1 |= USART_IT_RXNE & USART_IT_MASK;
#endif
peripheralUart[uartIndex]->CR1 |= USART_CR1_RXNEIE;
}

SynchronousUartStm::~SynchronousUartStm()
Expand Down

0 comments on commit feb8b53

Please sign in to comment.