USART + DMA = HardFault_Handler
Добавлено: Сб янв 03, 2015 12:19:41
Использую в своем проекте DMA для циклической передачи данных через UART3. Контроллер STM32F100. При включении передачи через некоторое время работы контроллер зависает и вываливается в HardFault_Handler. Если передачу через DMA отключить, то все хорошо работает. В чем может быть причина? Куда копать?
Вот код:
/**
* @brief Инициализация DMA
* @retval None
*/
void InitDMA()
{
DMA_StructInit(&dma);
dma.DMA_PeripheralBaseAddr = (uint32_t)&(USART3->DR);
dma.DMA_MemoryBaseAddr = (uint32_t)&dataBuffer[0];
dma.DMA_DIR = DMA_DIR_PeripheralDST;
dma.DMA_BufferSize = DMA_BUFFER_SIZE;
dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
dma.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
dma.DMA_Mode = DMA_Mode_Normal;
DMA_Init(DMA1_Channel2, &dma);
USART_DMACmd(USART3, USART_DMAReq_Tx, ENABLE);
USART_Cmd(USART3, ENABLE);
//Разрешаем обработку прерываний по окончанию передачи
NVIC_EnableIRQ(DMA1_Channel2_IRQn);
DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);
}
/**
* @brief Переключение DMA для циклической отправки данных
* @retval None
*/
void SendDMA()
{
DMA_Cmd(DMA1_Channel2, DISABLE);
DMA_Init(DMA1_Channel2, &dma);
DMA_Cmd(DMA1_Channel2, ENABLE);
}
Использовал таймер для циклического запуска DMA:
void TIM6_DAC_IRQHandler()
{
SendDMA();
if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
debug_count++;
}
}
Пытался вынести опрос в отдельную задачу для RL-ARM, все равно не работает:
__task void UART_Poolling(void)
{
for(;;)
{
SendDMA();
os_dly_wait(100);
}
}
Вот код:
/**
* @brief Инициализация DMA
* @retval None
*/
void InitDMA()
{
DMA_StructInit(&dma);
dma.DMA_PeripheralBaseAddr = (uint32_t)&(USART3->DR);
dma.DMA_MemoryBaseAddr = (uint32_t)&dataBuffer[0];
dma.DMA_DIR = DMA_DIR_PeripheralDST;
dma.DMA_BufferSize = DMA_BUFFER_SIZE;
dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
dma.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
dma.DMA_Mode = DMA_Mode_Normal;
DMA_Init(DMA1_Channel2, &dma);
USART_DMACmd(USART3, USART_DMAReq_Tx, ENABLE);
USART_Cmd(USART3, ENABLE);
//Разрешаем обработку прерываний по окончанию передачи
NVIC_EnableIRQ(DMA1_Channel2_IRQn);
DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);
}
/**
* @brief Переключение DMA для циклической отправки данных
* @retval None
*/
void SendDMA()
{
DMA_Cmd(DMA1_Channel2, DISABLE);
DMA_Init(DMA1_Channel2, &dma);
DMA_Cmd(DMA1_Channel2, ENABLE);
}
Использовал таймер для циклического запуска DMA:
void TIM6_DAC_IRQHandler()
{
SendDMA();
if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
debug_count++;
}
}
Пытался вынести опрос в отдельную задачу для RL-ARM, все равно не работает:
__task void UART_Poolling(void)
{
for(;;)
{
SendDMA();
os_dly_wait(100);
}
}