cancel
Showing results for 
Search instead for 
Did you mean: 

STM32Lxx Data Loss in Rx if I receive more than 15 bytes.

raghavb1979
Associate II
Posted on April 17, 2013 at 07:38

Hello,

This is raghav here. I have STM32Lxx board which is connected to Telit GPRS board. 

I am trying to receive the FTP file content through RxNe and could receive only the first byte of the content through RxNe.The command replies are fine in rxne as the command replies does not exceed 15 to 20byte. There is a data Loss if the bytes are more in Rxne(20 bytes or more then there is a data loss). I tried to lower the bit rate but problem didn't solve.

We use interrupt and not polling mechanism. Will this problem solved if I use DMA Rx ? If so please give me the sample code how to use DMA RX in ST32MLxx boards. Will be more helpful if you reply me quickly or post me the polling code which could receive more than 1k byte which will never incur any data loss.

Regards,

Raghav

#usart
9 REPLIES 9
Posted on April 17, 2013 at 13:31

Consider the need for hardware flow control in data mode.

Consider what you are doing in the RXNE interrupt, just buffering, or doing excessive processing.

Consider how fast the processor is running.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
raghavb1979
Associate II
Posted on April 18, 2013 at 07:32

Dear Clive,

In the interrupt nothing is done except buffering. Can I use DMA to solve the problem.

How to consider the Speed of the TelIt CPU?

Can you give me example on DMA RX sample code?

Posted on April 18, 2013 at 07:58

Actually I was looking for the speed the L1 was running at.

I've posted some DMA examples for other STM32 parts, not sure I have one built for the L1.

Honestly I think an L1 running at 48 MHz should have not problem dealing with data at 115200 or 9600 baud. If the processor is overwhelmed, use flow control. If you ignore the modem telling you not to send data, it will likely get lost. Is the USART signalling any framing or overflow errors?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on April 18, 2013 at 08:15

This is an F4 DMA Rx example, you will need to adapt for the L1 USART and DMA specifics.

[DEAD LINK /public/STe2ecommunities/mcu/Lists/STM32Discovery/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/STM32Discovery/UART%20with%20DMA%20mode&FolderCTID=0x01200200770978C69A1141439FE559EB459D75800084C20D8867EAD444A5987D47BE638E0F&currentviews=2051]https://my.st.com/public/STe2ecommunities/mcu/Lists/STM32Discovery/Flat.aspx?RootFolder=%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2FSTM32Discovery%2FUART%20with%20DMA%20mode&FolderCTID=0x01200200770978C69A1141439FE559EB459D75800084C20D8867EAD444A5987D47BE638E0F¤tviews=2051
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
adithya2
Associate II
Posted on April 18, 2013 at 09:25

Where are you buffering your received data? If you are receiving in an interrupt handler, then check the size of the receive buffer( usually an array ) and check if it is larger than 1KB to avoid ring buffering of your data. Also it is possible to receive at 9600 baud or any other baud. I have received up to 4KB data on an STM32L151 at 8MHz clock from a GPRS modem.

raghavb1979
Associate II
Posted on April 18, 2013 at 09:53

Dear Adithya,

The buffer is not a ring buffer. It will be helpful if you post your sample program here. Is it based on Polling or interrupt?

Posted on April 18, 2013 at 14:08

Ring / Circular / FIFO Buffers are a pretty core compsci concept.

http://en.wikipedia.org/wiki/Circular_buffer

If you are current using some kind of line buffer arrangement, you have to copy that off some where else or process it very quickly in place, otherwise you'll lose data.

Having an IRQ routine that simply dispatches a received byte into a sufficiently large FIFO buffer (perhaps 1-2KB depending on how quickly you process things, and how large the bursts/packets are), should be adequate for the scenario you are describing.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
jpeacock2399
Associate II
Posted on April 18, 2013 at 16:42

How do you determine data loss?   Are you getting RX errors (overrun, framing)?  Assuming you have enough CPU time to process the interrupt and your buffer code is working, there is also the possibility of slightly mismatched baud rates.  In a long string of async data with no gaps between bytes, and the baud rate isn't quite matched, the start bit may eventually drift into the time period for the previous stop bit and you'll see framing errors.

I've encountered this before with equipment that has 1% or greater variance in the baud rate generator.  It only occurs with long sbursts of data, not on single or short strings.  If you can program a gap between characters that may solve the problem.  An inter-character gap gives the USART time to sync sampling on the next start bit.

  Jack Peacock
Posted on April 20, 2013 at 15:23

This should work as a USART3 DMA RX example for the L1, should echo a H and C as you send 16 characters to the receiver, and it triggers the half and complete DMA transfers.

// STM32L15x USART3 DMA RX (PC.10 Tx, PC.11 Rx) - sourcer32@gmail.com
#include ''stm32l1xx.h''
/**************************************************************************************/
void RCC_Configuration(void)
{
/* --------------------------- System Clocks Configuration -----------------*/
/* USART3 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
/* GPIOC clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
/* DMA1 clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
}
/**************************************************************************************/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Configure USART Tx & Rx as alternate function */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Mux out USART3 Tx & Rx */
GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_USART3);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_USART3);
}
/**************************************************************************************/
void USART3_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
/* USARTx configuration ------------------------------------------------------*/
/* USARTx configured as follow:
- BaudRate = 9600 baud
- Word Length = 8 Bits
- One Stop Bit
- No parity
- Hardware flow control disabled (RTS and CTS signals)
- Receive and transmit enabled
*/
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART3, &USART_InitStructure);
USART_Cmd(USART3, ENABLE);
}
/**************************************************************************************/
uint8_t Buffer[32];
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(DMA1_Channel3); // USART3_RX
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART3->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Buffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = sizeof(Buffer);
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_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel3, &DMA_InitStructure);
/* Enable the USART Rx DMA request */
USART_DMACmd(USART3, USART_DMAReq_Rx, ENABLE);
/* Enable DMA Stream Half Transfer and Transfer Complete interrupt */
DMA_ITConfig(DMA1_Channel3, DMA_IT_TC, ENABLE);
DMA_ITConfig(DMA1_Channel3, DMA_IT_HT, ENABLE);
/* Enable DMA1 Channel3 */
DMA_Cmd(DMA1_Channel3, ENABLE);
}
/**************************************************************************************/
void DMA1_Channel3_IRQHandler(void)
{
/* Test on DMA Stream Transfer Complete interrupt */
if (DMA_GetITStatus(DMA1_IT_TC3))
{
/* Clear DMA Stream Transfer Complete interrupt pending bit */
DMA_ClearITPendingBit(DMA1_IT_TC3);
USART_SendData(USART3, 'C');
}
/* Test on DMA Stream Half Transfer interrupt */
if (DMA_GetITStatus(DMA1_IT_HT3))
{
/* Clear DMA Stream Half Transfer interrupt pending bit */
DMA_ClearITPendingBit(DMA1_IT_HT3);
USART_SendData(USART3, 'H');
}
}
/**************************************************************************************/
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure the Priority Group to 2 bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* Enable the USART3 RX DMA Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/**************************************************************************************/
int main(void)
{
RCC_Configuration();
NVIC_Configuration();
GPIO_Configuration();
USART3_Configuration();
DMA_Configuration();
while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET); // Wait for Empty
USART_SendData(USART3, '*');
while(1); // Don't want to exit
}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..