У меня есть несколько ошибок OVERRUN на периферии UART, потому что я продолжаю получать данные UART, пока мой код останавливается, потому что я выполняю операцию записи на флэш-памяти .
Я использую прерываниядля UART и поясняется в Прикладной ноте AN3969 :
Прошивка эмуляции EEPROM запускается из внутренней Flash-памяти, поэтому доступ к Flash-памяти будет заблокирован во время операций, требующих удаления Flash илипрограммирование (инициализация EEPROM, обновление переменной или удаление страницы).Как следствие, код приложения не выполняется, и прерывание не может быть обработано.
Такое поведение может быть приемлемым для многих приложений, однако для приложений с ограничениями в реальном времени необходимо запуститькритические процессы из внутренней памяти.
В этом случае:
- Перемещение таблицы векторов во внутреннюю память.
- Выполнение всех критических процессов и процедур обработки прерыванийиз внутренней оперативной памяти.Компилятор предоставляет ключевое слово для объявления функций как функции RAM;функция копируется из флэш-памяти в ОЗУ при запуске системы, как и любая инициализированная переменная.Важно отметить, что для функции ОЗУ все используемые переменные и вызываемые функции должны быть в ОЗУ.
Так что я ищу в Интернете инайдено AN4808 , в котором приведены примеры того, как поддерживать прерывания во время операций флэш-памяти.
Я продолжил и изменил свой код:
Сценарий компоновщика : Добавлена таблица векторов в SRAM и определена секция .ramfunc
/* stm32f417.dld */
ENTRY(Reset_Handler)
MEMORY
{
ccmram(xrw) : ORIGIN = 0x10000000, LENGTH = 64k
sram : ORIGIN = 0x20000000, LENGTH = 112k
eeprom_default : ORIGIN = 0x08004008, LENGTH = 16376
eeprom_s1 : ORIGIN = 0x08008000, LENGTH = 16k
eeprom_s2 : ORIGIN = 0x0800C000, LENGTH = 16k
flash_unused : ORIGIN = 0x08010000, LENGTH = 64k
flash : ORIGIN = 0x08020000, LENGTH = 896k
}
_end_stack = 0x2001BFF0;
SECTIONS
{
. = ORIGIN(eeprom_default);
.eeprom_data :
{
*(.eeprom_data)
} >eeprom_default
. = ORIGIN(flash);
.vectors :
{
_load_vector = LOADADDR(.vectors);
_start_vector = .;
*(.vectors)
_end_vector = .;
} >sram AT >flash
.text :
{
*(.text)
*(.rodata)
*(.rodata*)
_end_text = .;
} >flash
.data :
{
_load_data = LOADADDR(.data);
. = ALIGN(4);
_start_data = .;
*(.data)
} >sram AT >flash
.ramfunc :
{
. = ALIGN(4);
*(.ramfunc)
*(.ramfunc.*)
. = ALIGN(4);
_end_data = .;
} >sram AT >flash
.ccmram :
{
_load_ccmram = LOADADDR(.ccmram);
. = ALIGN(4);
_start_ccmram = .;
*(.ccmram)
*(.ccmram*)
. = ALIGN(4);
_end_ccmram = .;
} > ccmram AT >flash
.bss :
{
_start_bss = .;
*(.bss)
_end_bss = .;
} >sram
. = ALIGN(4);
_start_stack = .;
}
_end = .;
PROVIDE(end = .);
Сброс обработчика : Добавлена копия таблицы векторов SRAM и определена секция .ramfunc
void Reset_Handler(void)
{
unsigned int *src, *dst;
/* Copy vector table from flash to RAM */
src = &_load_vector;
dst = &_start_vector;
while (dst < &_end_vector)
*dst++ = *src++;
/* Copy data section from flash to RAM */
src = &_load_data;
dst = &_start_data;
while (dst < &_end_data)
*dst++ = *src++;
/* Copy data section from flash to CCRAM */
src = &_load_ccmram;
dst = &_start_ccmram;
while (dst < &_end_ccmram)
*dst++ = *src++;
/* Clear the bss section */
dst = &_start_bss;
while (dst < &_end_bss)
*dst++ = 0;
SystemInit();
SystemCoreClockUpdate();
RCC->AHB1ENR = 0xFFFFFFFF;
RCC->AHB2ENR = 0xFFFFFFFF;
RCC->AHB3ENR = 0xFFFFFFFF;
RCC->APB1ENR = 0xFFFFFFFF;
RCC->APB2ENR = 0xFFFFFFFF;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOEEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOFEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOGEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOHEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOIEN;
RCC->AHB1ENR |= RCC_AHB1ENR_CCMDATARAMEN;
main();
while(1);
}
system_stm32f4xxx.c: Некомментированный VECT_TAB_SRAM define
/*!< Uncomment the following line if you need to relocate your vector Table in
Internal SRAM. */
#define VECT_TAB_SRAM
#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field.
This value must be a multiple of 0x200. */
Добавлено определение RAMFUNC для установки атрибутов раздела:
#define RAMFUNC __attribute__ ((section (".ramfunc")))
Добавлен RAMFUNC перед функцией и прототипами, связанными с UART, чтобы запускаться из ОЗУ.
RAMFUNC void USART1_IRQHandler(void)
{
uint32_t sr = USART1->SR;
USART1->SR & USART_SR_ORE ? GPIO_SET(LED_ERROR_PORT, LED_ERROR_PIN_bp):GPIO_CLR(LED_ERROR_PORT, LED_ERROR_PIN_bp);
if(sr & USART_SR_TXE)
{
if(uart_1_send_write_pos != uart_1_send_read_pos)
{
USART1->DR = uart_1_send_buffer[uart_1_send_read_pos];
uart_1_send_read_pos = (uart_1_send_read_pos + 1) % USART_1_SEND_BUF_SIZE;
}
else
{
USART1->CR1 &= ~USART_CR1_TXEIE;
}
}
if(sr & (USART_SR_RXNE | USART_SR_ORE))
{
USART1->SR &= ~(USART_SR_RXNE | USART_SR_ORE);
uint8_t byte = USART1->DR;
uart_1_recv_buffer[uart_1_recv_write_pos] = byte;
uart_1_recv_write_pos = (uart_1_recv_write_pos + 1) % USART_1_RECV_BUF_SIZE;
}
}
Моя цель работает правильно с таблицей векторов и функцией UART в ОЗУ, но я все еще получаюпревышение на USART.Я также не отключаю прерывания при выполнении операции флэш-записи.
Я также пытался запускать код из ОЗУ CCM вместо SRAM, но я видел на этот пост код не может бытьисполняется в оперативной памяти CCM на STMF32F4XX ...
Есть идеи?Спасибо.