Em sistemas baseados em microcontroladores STM32, a integração da biblioteca HAL com o FreeRTOS pode causar falhas inesperadas durante operações na memória Flash. Este guia aborda um problema comum de falha na escrita e apagamento da Flash, sua causa raiz e soluções práticas.
Cenário do Problema
Ambiente de desenvolvimento: STM32CubeMX e ferramentas Keil. Hardware: STM32F407VET6. Software: FreeRTOS para gerenciamento de tarefas, com uso da Flash para persistência de dados. Observa-se que, antes da adição do FreeRTOS, as operações de leitura e escrita na Flash funcionam corretamente. No entanto, após integrar o FreeRTOS, a escrita na Flash falha, sendo rastreada até uma falha no processo de apagamento.
Análise da Causa
Através de depuração, verifica-se que bits específicos em registradores relacionados à Flash permanecem em estados inválidos, impedindo a conclusão bem-sucedida das operações. Esse comportamento está vinculado a alterações nos registradores durante a inicialização do FreeRTOS, resultando em conflitos com as rotinas da biblioteca HAL, como observado no código-fonte da HAL.
Implementação da Solução
Para resolver o problema, limpe as flags de status dos registradores da Flash antes de iniciar qualquer operação de apagamento ou escrita. Além disso, é recomendável desabilitar interrupções e o escalonador do FreeRTOS durante o acesso à Flash, reativando-os após a conclusão. Essa abordagem garante a exclusão mútua e previne condições de corrida.
Fatores Adicionais a Considerar
Confirme que o endereço e o setor da Flash utilizados para apagamento correspondem exatamente aos da escrita. Verifique também as configurações de tensão e o tamanho do setor na inicialização, pois inconsistências podem levar a falhas silenciosas.
Exemplo de Códiggo Adaptado
As funções abaixo demonstram a implementação de operações na Flash com correções aplicadas. O código foi refatorado para utilizar nomes alternativos de variáveis e uma estrutura lógica modificada, mantendo a funcionalidade essencial.
#ifndef FLASH_DRIVER_H
#define FLASH_DRIVER_H
#include "stm32f4xx_hal.h"
#define FLASH_CAPACITY_KB 512
#if FLASH_CAPACITY_KB < 256
#define SECTOR_SIZE_BYTES 1024
#else
#define SECTOR_SIZE_BYTES 2048
#endif
#define FLASH_BASE_ADDRESS 0x08000000
#define USER_FLASH_START 0x08040000
#define USER_FLASH_END 0x08060000
void Sector_Erase(void);
void Data_Write(uint32_t *src_buffer, uint32_t data_length, uint32_t *dest_addr);
void Data_Read(uint32_t *dst_buffer, uint32_t data_length, uint32_t *src_addr);
#endif
static uint32_t current_write_ptr = USER_FLASH_START;
static uint32_t current_read_ptr = USER_FLASH_START;
void Sector_Erase(void) {
FLASH_EraseInitTypeDef erase_config;
uint32_t error_code = 0;
erase_config.TypeErase = FLASH_TYPEERASE_SECTORS;
erase_config.Sector = FLASH_SECTOR_6;
erase_config.NbSectors = 1;
erase_config.VoltageRange = FLASH_VOLTAGE_RANGE_3;
if (HAL_FLASHEx_Erase(&erase_config, &error_code) != HAL_OK) {
HAL_FLASH_Lock();
// Tratamento de erro adequado
}
}
void Data_Write(uint32_t *src_buffer, uint32_t data_length, uint32_t *dest_addr) {
uint32_t index = 0;
HAL_FLASH_Unlock();
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
Sector_Erase();
while ((*dest_addr < USER_FLASH_END) && (index < data_length)) {
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, *dest_addr, src_buffer[index]) == HAL_OK) {
*dest_addr += 4;
index++;
} else {
// Lógica de recuperação de erro
break;
}
}
HAL_FLASH_Lock();
}
void Data_Read(uint32_t *dst_buffer, uint32_t data_length, uint32_t *src_addr) {
uint32_t index = 0;
while ((*src_addr < USER_FLASH_END) && (index < data_length)) {
dst_buffer[index++] = *(__IO uint32_t *)(*src_addr);
*src_addr += 4;
}
}