cancel
Showing results for 
Search instead for 
Did you mean: 

USART1 with missing bytes

teslashock
Associate II
Posted on May 27, 2013 at 06:21

I am trying for now to send 600 001 bytes to PC from stm32f4 discovery board.

below is how USART configured:

uint32_t config_usart3(
void
)
{
//=============================================================================
// USART3 Related configuration
//=============================================================================
// enable clock
RCC->APB1ENR |= RCC_APB1ENR_USART3EN;
// 1) Setting UE, amd M bits
USART3-> CR1 |= 0x2000; 
// UE = 1
// 2) Programming number of stop bits if needed
// 3) Enable DMA if needed
// 4) set the Baud Rate
// BAUD = *** / ( 8 * (2 - OVER8) * USARTDIV )
// *** = 42MHz,
// OVER8 = 0
// Choose BAUD = 115200
// then: USARTDIV = *** / ( 8 * (2 -OVER8) * BAUD = 75
// BRR = (22 << 4) | ( 0.75 * 16) = 364,
// or: BRR = *** / BAUD = 42MHz / 115200 = 364
USART3->BRR = 364;
// enable transmitter
USART3->CR1 |= USART_CR1_TE;
// enable receiver
USART3->CR1 |= USART_CR1_RE;
// enable CTS/RTS
USART3->CR3 |=
(
USART_CR3_CTSE |
USART_CR3_RTSE
);
return
0;
}

Below is how GPIO port relevant to USART1 configured:

//=============================================================================
// GPIOD configuration
//=============================================================================
// enable GPIOD clock
((RCC_TypeDef *)(RCC_BASE))->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
// Alternate Function
((GPIO_TypeDef *)(GPIOD_BASE))->MODER |=
(GPIO_MODER_MODER9_1 | 
// Alternate Function, USART3_RX
GPIO_MODER_MODER8_1 | 
// Alternate Function, USART3_TX
GPIO_MODER_MODER11_1 | 
// Alternate Function, USART3_CTS
GPIO_MODER_MODER12_1 
// Alternate Function, USART3_RTS
);
// Output type
GPIOD->OTYPER = 0;
// Speed type
((GPIO_TypeDef *)(GPIOD))->OSPEEDR |=
(GPIO_OSPEEDER_OSPEEDR8_1 | 
// USART3 TX 50 MHz
GPIO_OSPEEDER_OSPEEDR9_1 | 
// USART3 RX 50 MHz
GPIO_OSPEEDER_OSPEEDR11_1 | 
// USART3 CTS 50 MHz
GPIO_OSPEEDER_OSPEEDR12_1 
// USART3 RTS 50 MHz
);
// Push/Pull for USART3
GPIOD->PUPDR = 0;
((GPIO_TypeDef *)(GPIOD_BASE))->PUPDR |=
(
GPIO_PUPDR_PUPDR8_0 | 
// Pull-Up, USART3 TX
GPIO_PUPDR_PUPDR9_0 | 
// Pull-Up, USART3 RX
GPIO_PUPDR_PUPDR11_0 | 
// Pull-Up, USART3 CTS
GPIO_PUPDR_PUPDR12_0 
// Pull-Up, USART3 RTS
);
((GPIO_TypeDef *)(GPIOD_BASE))->AFR[1] |= (
(7 << ((8 - 8) << 2)) | 
// USART3 TX, AF7
(7 << ((9 - 8) << 2)) | 
// USART3 RX, AF7
(7 << ((11 - 8) << 2)) | 
// USART3 CTS, AF7
(7 << ((12 - 8) << 2)) 
// USART3 RTS, AF7
);

and below is how I send my bytes:

uint8_t mem_read(USART_TypeDef *USART_ID )
{
uint32_t i=0; 
// loop var
//send read buffer to USART
for
(i=0;iSR & USART_SR_TXE)) );
USART_ID->DR = 0x5d; 
// sending a byte
// check if TC bit is set
while
((!(USART_ID->SR & USART_SR_TC)) );
}
return
0;
}

Using WinXP, with FTDI cable and its drivers, cable was loopbacked and seems to work. What happens is, on the PC end I get my 600001 bytes 5-6 times out of 10, in other words, a lot of times I end up missing couple thousand bytes or s (I get something like 597 953 bytes etc). Not sure what else did I do on the STM32 part? as you see I check for TXE, and TC(although checking TC might not be needed that much) I also set up the stm32 in CTS/RTS mode, as well as the PC terminal emulator program. again,.. I do get 600001 bytes but not all the time! And I am curious what else could be wrong?
6 REPLIES 6
Posted on May 27, 2013 at 15:30

Yeah, I'd probably lose the TC, and add stop bits if I had a synchronization issue.

You might want to look at your Windows side app, and it's ability to efficiently sink data. ie not a terminal app dumping received data to the screen.

600001 sounds like a lot of data to transmit over a serial link without some sort of protocol with intrinsic validity checking or flow control. Again, I don't think a terminal app is appropriate for testing such a link.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
teslashock
Associate II
Posted on May 27, 2013 at 16:32

and how about adding something like MAX232, and do STM32--->RS-232---->(USB-RS-232 Adapter) ?

and keeping the same way of doing this?

reason I say that is, I kind of suspect that my USB FTDI cable does not handle CTS/RTS properly thats why I loose data between it and PC, what other methods would be for raw data read using Serial USART? (reliable, without loosing bytes)
teslashock
Associate II
Posted on May 27, 2013 at 16:33

or for example doing something like STM32 USART---> RS-485---> usb adapter?

Posted on May 27, 2013 at 16:57

Which FTDI cable? You should be able to connect the 3V TTL/CMOS type up directly.

http://www.ftdichip.com/Products/Cables/USBTTLSerial.htm

I'm not sure why you think RS232 or RS485 would be intrinsically more reliable in this situation? You want to be looking a layering a protocol on top of the physical transport.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
teslashock
Associate II
Posted on May 27, 2013 at 18:21

well sure I did connect the correct 3V one directly to stm32. thats not the problem.

problem was that: this FTDI cable did not handle big input amounts of data, those CTS/RTS functionality looks to me like was not handled properly, that is why some bytes which were correctly sent from stm32 did not get to PC since they were kinda choked by FTDI.

and the reason I was wondering about RS-485 adapters is: maybe those ones would handle those flow-control signals well and make sure that all data being sent to them from stm32 will be received and redirected to PC (via USB adapter of course). thats why I was curious about it.

another thing I was wondering about is: what about maybe using something like CP2102? any comments on those ones? (maybe they do a better job at hardware flow control than FTDI?)

I know that there are many protocols, but well... afterall CTS/RTS *has* to do its job? Or otherwise whats the purpose of having them if the literally can *not* control your flow?

and from situation I described it looks like my FTDI cable simply cant do that!

Here is another test I did: I shorted the tx-rx, and even tried to short cts-rts on that FTDI cable, and loopback same 600001 bytes, and guess what, still got like 2K bytes less or sometimes even less than that, like only 597000bytes or so.

so now, what I am curious is: Is there some sort of transceiver/adapter which would allow me still to use simple USART with CTS/RTS on STM32, but which would handle those flow control signals well and pass all bytes to PC?

teslashock
Associate II
Posted on May 27, 2013 at 18:36

and in fact, I was kind of right, take a look here:

http://www.ftdichip.com/Support/FAQs.htm#HwGen3

Here FTDI literally tells that their CTS/RTS functionality works *not quite right*, because it operaets on a packet basis, although what they described there has to do with FTDI transmitting to ''device'' (stm32 in my case), I have a feeling same thing happens with FTDI receiving data from ''device''.

so, it turns out that all I need is some sort of FTDI-like chip, but which would handle that CTS/RTS normally with STM32, then it looks like I should not have any problem, right?

Also, another question: take a look for example on my first post, how I turn on the CTS/RTS feature on STM32, as well as configure its ports and send bytes. 

Question is: when CTS/RTS is turned on on stm32, do I have to send bytes in some special way by manually checking for example the CTS bit? or stm32 will automatically make sure that when I write to DR and check TXE/TC it will send only when its CTS is 0, and it will toggle RTS appropriately?