2012-11-20 08:15 AM
Hi,
I have the following Usart interrupt request handler: (simplified version, but has all the necessary information) void USART1_IRQHandler(void) { if(USART_GetITStatus(COM1_PC, USART_IT_RXNE) != RESET) { data = (USART_ReceiveData(COM1_PC) & 0xfF); if (data == DATA_READ) { //Disable the Usart interrupt request because from this point, //I want to use the DMA to store the incoming data at a specified address! USART_ITConfig(COM1_PC, USART_IT_RXNE, DISABLE); //make sure that the DMA is not transferring any data before configuring it with new parameters while (DMA_GetCmdStatus(RS232_DMA_RX_STREAM) != DISABLE) { } //Configure the DMA to store usNumOfBytes bytes to memory, starting at address pStartAddress RS232_DMA_RX_STREAM->NDTR = usNumOfbytes; RS232_DMA_RX_STREAM->M0AR = (uint32_t)pStartAddress; //Clear some flags before enable the DMA DMA_ClearFlag(RS232_DMA_RX_STREAM, RS232_RX_DMA_FLAG_HTIF | RS232_RX_DMA_FLAG_TCIF); /* Enable DMA Stream Transfer Complete interrupt */ DMA_ITConfig(RS232_DMA_RX_STREAM, DMA_IT_TC, ENABLE); //Only for debugging to make sure that it no data has been stored until now! RXcounter=DMA_GetCurrDataCounter(RS232_DMA_RX_STREAM); //make sure that the RXNE bit is cleared before activating the DMA while(USART_GetITStatus(COM1_PC, USART_IT_RXNE) != RESET); //Activate the DMA DMA_Cmd(RS232_DMA_RX_STREAM, ENABLE); //only for debugging, but at this point the DMA, has read the old data stored in the DR register, and RXcounter is equal to usNumOfbytes - 1! RXcounter=DMA_GetCurrDataCounter(RS232_DMA_RX_STREAM); } } } With this interrupt handler I want to implement the following: Whenever it receives a DATA_READ command, it should: -Disable the USART RX interrupt request; -Configure the DMA to read data coming from a host PC via RS232 and store it at the specified address. -Enable the DMA for that propose. Surprisingly (for me), the DMA stores the old received data at the specified address, as soon as, it is enabled. Even with the RXNE bit cleared. But, on page 786 of the reference manual RM0008 (Doc ID 13902 Rev 14), subtitle ''Reception using DMA'', it states that ''The data will be loaded from USART_DR to this memory area after each RXNE event.'' So, I would like to know, what really forces the DMA to read data from the DR register to the specified memory! It doesn't seems that it is the RXNE event, because this bit is cleared by reading data from the DR register, and I have forced to make sure that this bit was cleared before enabling the DMA. Thank you all for any help, Best regards, A. Paiva #usart #dma #rxne2012-11-20 02:39 PM
Does it happen also the first time the DMA is enabled, or only the second time and on?
If the latter, it will be a similar or the same issue as I reported in https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fcortex%5fmx%5fstm32%2fHow%20to%20clear%20pending%20DMA%20request&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&TopicsView=ht... . JW2012-11-21 07:10 AM
Thanks for your post.
As soon as, I enable the DMA, this occurs! Inspite of the last received data from the UART has already been read by the processor, it reads it again, and then wait for the new incoming data. Best regards, A.Paiva2012-11-21 08:56 AM
Ok,
It's working, but I really don't like my solution. I would like to find the source of the fault, instead of shut up the DMA! I force the DMA to read the unwanted byte to a dummy address, and then I prepare the DMA to receive new data. void USART1_IRQHandler(void) { if(USART_GetITStatus(COM1_PC, USART_IT_RXNE) != RESET) { data = (USART_ReceiveData(COM1_PC) & 0xfF); if (data == DATA_READ) { //Disable the Usart interrupt request because from this point, //I want to use the DMA to store the incoming data at a specified address! USART_ITConfig(COM1_PC, USART_IT_RXNE, DISABLE); //make sure that the DMA is not transferring any data before configuring it with new parameters while (DMA_GetCmdStatus(RS232_DMA_RX_STREAM) != DISABLE) { } /************************* NEW CODE START's HERE ************************************/ //Force the DMA to read unwanted byte to a dummy address! RS232_DMA_RX_STREAM->NDTR = 1; RS232_DMA_RX_STREAM->M0AR = (uint32_t)dummyAddress; DMA_Cmd(RS232_DMA_RX_STREAM, ENABLE); DMA_ClearITPendingBit(RS232_DMA_RX_STREAM, RS232_DMA_RX_IT_TCIF); /************************* NEW CODE STOP's HERE ************************************/ //Configure the DMA to store usNumOfBytes bytes to memory, starting at address pStartAddress RS232_DMA_RX_STREAM->NDTR = usNumOfbytes; RS232_DMA_RX_STREAM->M0AR = (uint32_t)pStartAddress; //Clear some flags before enable the DMA DMA_ClearFlag(RS232_DMA_RX_STREAM, RS232_RX_DMA_FLAG_HTIF | RS232_RX_DMA_FLAG_TCIF); /* Enable DMA Stream Transfer Complete interrupt */ DMA_ITConfig(RS232_DMA_RX_STREAM, DMA_IT_TC, ENABLE); //Only for debugging to make sure that it no data has been stored until now! RXcounter=DMA_GetCurrDataCounter(RS232_DMA_RX_STREAM); //make sure that the RXNE bit is cleared before activating the DMA while(USART_GetITStatus(COM1_PC, USART_IT_RXNE) != RESET); //Activate the DMA DMA_Cmd(RS232_DMA_RX_STREAM, ENABLE); //only for debugging, but at this point the DMA, has read the old data stored in the DR register, and RXcounter is equal to usNumOfbytes - 1! RXcounter=DMA_GetCurrDataCounter(RS232_DMA_RX_STREAM); } } } Even so, I would be grateful if someone could explain what forces the DMA read with the RXNE cleared. Thanks, Regards, A. Paiva2012-11-21 10:36 AM
> As soon as, I enable the DMA, this occurs!
Yes, but that does not answer my question. I meant, does this happen when the DMA is enabled for the very first time after reset (i.e. the first time the interrupt routine is entered)? JW2012-11-21 01:34 PM
Hi Jan,
I have not tested. As I had mencioned before, this is a simplified code of my interrupt routine. Actualy, I don't receive only a byte, before configuring the DMA to receive data. Tomorrow, I will try and post here if it also appears the first time the interrupt routine is called. Regards, A.Paiva2012-11-22 12:40 AM
Hi,
It occurs at the first time the interrupt routine is called too. Best regards, A.Paiva2012-11-22 03:07 AM
Thanks.
Hummmm.... JW2012-11-26 08:35 AM
Hi,
''... Inspite of the last received data from the UART has already been read by the processor, it reads it again, and then wait for the new incoming data.''
It seems this is due to the fact that sizeof(USART_DR) = 1 byte Cheers, STOne-322012-11-26 08:53 AM
How do you mean that?
In stm32f4xx.h,typedef struct
{ __IO uint16_t SR; /*!< USART Status register, Address offset: 0x00 */ uint16_t RESERVED0; /*!< Reserved, 0x02 */ __IO uint16_t DR; /*!< USART Data register, Address offset: 0x04 */ uint16_t RESERVED1; /*!< Reserved, 0x06 */ __IO uint16_t BRR; /*!< USART Baud rate register, Address offset: 0x08 */ uint16_t RESERVED2; /*!< Reserved, 0x0A */ __IO uint16_t CR1; /*!< USART Control register 1, Address offset: 0x0C */ uint16_t RESERVED3; /*!< Reserved, 0x0E */ __IO uint16_t CR2; /*!< USART Control register 2, Address offset: 0x10 */ uint16_t RESERVED4; /*!< Reserved, 0x12 */ __IO uint16_t CR3; /*!< USART Control register 3, Address offset: 0x14 */ uint16_t RESERVED5; /*!< Reserved, 0x16 */ __IO uint16_t GTPR; /*!< USART Guard time and prescaler register, Address offset: 0x18 */ uint16_t RESERVED6; /*!< Reserved, 0x1A */ } USART_TypeDef; For me it looks that DR is declared as 16-bit, ie. sizeof(DR) is 2. I of course don't see what did compiler A.Paiva used make out of it, but I somehow doubt it is anything else than a halfword access. Could you please be more specific with your comment? Thanks, JW