STM32F100RB
включены АЦП, USART1 и DMA chanel4
Настроил DMA на передачу данных в усарт и нужен был режим работы в котором при передаче половины буфера срабатывало бы прерывание, а так же по завершению.
Всё срабатывает нормально до поры до времени. Ровно до тех пор пока обработчик прерывания не вызовется с запозданием и если во время обработки половины буфера выставится флаг TC ( передача завершена) то прерывание TC не срабатывает, в итоге прога не сбрасывает флаг занятости USART и ждёт у моря погоды вечно (или пока принудительно не будешь опрашивать счётчик отсавшихся транзакций в ДМА и по нему ориентироваться).
Исходники
Прерывание
CODE
void DMA1_Channel4_IRQHandler(void) //TX
{
if (DMA_GetFlagStatus(DMA1_FLAG_TE4))
{
DMA_ClearFlag(DMA1_FLAG_TE4 | DMA1_FLAG_GL4);
error_add(ERROR_UART_TX_DMA);
};
if (DMA_GetFlagStatus(DMA1_FLAG_HT4))
{
DMA_ClearFlag(DMA1_FLAG_HT4 | DMA1_FLAG_GL4);
};
if (DMA_GetFlagStatus(DMA1_FLAG_TC4))
{
DMA_ClearFlag(DMA1_FLAG_TC4 | DMA1_FLAG_GL4);
usart_transmit_complite = true;
};
usart_check_shift();
}
{
if (DMA_GetFlagStatus(DMA1_FLAG_TE4))
{
DMA_ClearFlag(DMA1_FLAG_TE4 | DMA1_FLAG_GL4);
error_add(ERROR_UART_TX_DMA);
};
if (DMA_GetFlagStatus(DMA1_FLAG_HT4))
{
DMA_ClearFlag(DMA1_FLAG_HT4 | DMA1_FLAG_GL4);
};
if (DMA_GetFlagStatus(DMA1_FLAG_TC4))
{
DMA_ClearFlag(DMA1_FLAG_TC4 | DMA1_FLAG_GL4);
usart_transmit_complite = true;
};
usart_check_shift();
}
Настройка ДМА:
CODE
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
NVIC_InitTypeDef NVIC_InitStructure;
STRUCT_CLEAR(NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
DMA_DeInit(DMA1_Channel4);
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(DMA1_Channel4);
STRUCT_CLEAR(DMA_InitStructure);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32) &(USART1->DR);
DMA_InitStructure.DMA_MemoryBaseAddr = (u32) data;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = size;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel4, &DMA_InitStructure);
DMA_ITConfig(DMA1_Channel4, DMA_IT_TE | DMA_IT_HT | DMA_IT_TC, ENABLE);
USART1->SR=0;
DMA_Cmd(DMA1_Channel4, ENABLE);
В чём может быть проблема?
Стоит ли флаг глобального прерывания канала очищать?
Или достаточно очистить конкретный флаг не глобального а HT | TC?
В документации от СТМ не нашол ответа