I'm trying to implement communication between stm32f103 and SIM900A using FreeRTOS (mutexes and stream buffers), DMA and USART3.
I've enabled USART_IT_IDLE USART3 interrupt to be able to detect end of SIM900 transmittion and make force firing of DMA transmission complete interrupt to copy data from memory into FreeRtos's streamBuffer.
This article said that this is possible.
/**
* \brief Global interrupt handler for USART2
*/
void USART2_IRQHandler(void) {
/* Check for IDLE flag */
if (USART2->SR & USART_FLAG_IDLE) { /* We want IDLE flag only */
/* This part is important */
/* Clear IDLE flag by reading status register first */
/* And follow by reading data register */
volatile uint32_t tmp; /* Must be volatile to prevent optimizations */
tmp = USART2->SR; /* Read status register */
tmp = USART2->DR; /* Read data register */
(void)tmp; /* Prevent compiler warnings */
DMA1_Stream5->CR &= ~DMA_SxCR_EN; /* Disabling DMA will force transfer complete interrupt if enabled */
}
}
But my debugger says: no
Here is my code:
#define BUFF_SIZE 16
uint8_t RX_BUFFER[BUFF_SIZE] = {"\0"};
uint8_t TX_BUFFER[BUFF_SIZE] = {"\0"};
....
// USART TX channel
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(USART3->DR);
DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&TX_BUFFER[0];
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStruct.DMA_BufferSize = sizeof(TX_BUFFER);
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
DMA_InitStruct.DMA_Priority = DMA_Priority_Low;
DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel2, &DMA_InitStruct);
DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&RX_BUFFER[0];
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStruct.DMA_BufferSize = sizeof(RX_BUFFER);
DMA_Init(DMA1_Channel3, &DMA_InitStruct);
// USART RX channel
DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&RX_BUFFER[0];
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStruct.DMA_BufferSize = sizeof(RX_BUFFER);
DMA_Init(DMA1_Channel3, &DMA_InitStruct);
// Interrupts
USART_ITConfig(USART3, USART_IT_IDLE, ENABLE);
USART_DMACmd(USART3, USART_DMAReq_Tx | USART_DMAReq_Rx, ENABLE);
USART_Cmd(USART3, ENABLE);
DMA_ITConfig(DMA1_Channel3, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA1_Channel3, ENABLE);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY + 10;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 4;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_Init(&NVIC_InitStructure);
....
void USART3_IRQHandler() {
if (USART_GetITStatus(USART3, USART_IT_IDLE) == SET) {
volatile uint32_t tmp = USART3->SR;
tmp = USART3->DR;
(void) tmp;
// HERE interrupt should be fired!
DMA1_Channel3->CCR &= (uint16_t)(~DMA_CCR1_EN);
USART_ClearITPendingBit(USART3, USART_IT_IDLE);
}
}
void DMA1_Channel3_IRQHandler(void) {
if (DMA_GetITStatus(DMA1_IT_TC3) == SET) {
uint8_t len = BUFF_SIZE - DMA1_Channel3->CNDTR;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xStreamBufferSendFromISR(xUSART3ReceiveStreamBuffer, &RX_BUFFER, len, &xHigherPriorityTaskWoken);
for (uint8_t i = 0; i < len; i++) {
RX_BUFFER[i] = '\0';
}
DMA1_Channel3->CNDTR = BUFF_SIZE;
DMA_Cmd(DMA1_Channel3, ENABLE);
DMA_ClearITPendingBit(DMA1_IT_TC3);
}
}
Why I can't force DMA1_IT_TC3 interrupt? Or can it be forced on STM32F103?