cancel
Showing results for 
Search instead for 
Did you mean: 

Higher than 921600 baud does not work stm32f4Discovery

michaelmccartyeng
Associate II
Posted on March 11, 2014 at 00:15

Hello All,

I'm communicating with a wifi module that uses a stm32 internally and it supports up to 2073600. I can use that baud rate with usb to uart adapter and communicate with the wifi module but when I put my stm32f4 discovery any higher than 921600 it does not seem to work. Is it possible to achieve this speed ? Thanks !

void setupCommUart(int baud)
{
USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
// init clocks 
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);
//110, 150, 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
USART_InitStructure.USART_BaudRate = baud;
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(USART2, &USART_InitStructure);
// enable usart
USART_Cmd(USART2, ENABLE);
}

#discovery #stm32f4 #uart
20 REPLIES 20
Posted on March 11, 2014 at 00:23

Is it possible to achieve this speed ?

It should be capable of 2-3 Mbps, though I'd probably not be using interrupts, as the STM32 USART hardware has no depth.

Nominally 1/16 of the APB clock is the max unless you switch to OVER8 mode.

Like many things with the STM32 clocking scheme the error % is going to get quite large the higher you go, so you might want to pick crystals with magic frequencies or play games with the PLL/CPU speed to find optimal combinations.

RS232 level converter circuits filter in the 1 Mbps region.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
frankmeyer9
Associate II
Posted on March 11, 2014 at 08:49

In addition, you will need impedance-matched cables/wiring, as short as possible.

Posted on March 11, 2014 at 09:03

> RS232 level converter circuits filter in the 1 Mbps region.

Actually, the standard mandates slew rate limiting which precludes RS232 communication over 115200 baud, so that's the practical limit. There are converters capable of 1Mbaud out there, but they are strictly speaking non-conforming and rarely seen in wild.

Nevertheless, I guess this all is not pertinent to Michael's problem, as he most probably does not convert to RS232 levels. And, as you've said above, it's most probably either improperly set baudrate following from an ''impossible'' APB clock, or way too long connection and/or improper return/ground.

JW

Posted on March 11, 2014 at 09:39

I don't know it's at all rare, chip solutions permitting ''RS232'' level conversion have long been capable of 921600 baud. At least 15 years ago I was using PC ISA based RS232 cards, with 16550 chips, that were easily capable of sub 1 Mbps operation. The usual problem with PC USART implementations was the use of 1.8432 MHz crystals which limited the max speed. The chips themselves were capable of using 24 MHz oscillators, so replacing the can oscillators, and modifying the drivers (DOS/Windows) to compute the baud rates properly was easy enough to do.

These cards could get beyond 1 Mbps, up to 3 Mbps as I recall, but you had to remove the MC1488/1489 parts, some of which were certainly capable of sub-micro second switching and use TTL. I built a network bridge between two building using ''RS485'' signalling (differential)  at 1 Mbps.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on March 11, 2014 at 10:30

> These cards could get beyond 1 Mbps, up to 3 Mbps as I recall, but you had to remove the MC1488/1489 parts,

That's what I'm talking about. These transceivers - as the vast majority of the transceivers used commonly on PC motherboards, add-on cards, instrument interfaces, etc. - are deliberately designed to provide the limited slew rate required by the RS-232 standard, and that in turn limits the baudrate to 115k2. That requirement is part of the ''forgiveness'' of the RS-232 interface, decreasing electromagnetic emission of the single-ended link with undefined cable shielding, and limiting risks of high-speed bounces as the impedances of the cabling/terminating devices are not that well defined either.

Yes, most of USARTs support higher baudrates, but it's irrelevant from signalling point of view; and that there are transceivers which do that too, it's something you have to look for and check, not the common, usual case. RS-485/RS-422 is again something entirely different from signalling point of view.

JW

Posted on March 11, 2014 at 10:58

Indeed, but the point being that the RS232<->RS485 converters I used where basically screwed directly onto the RS232 cards of the PC. So PC-USART<->RS232<->RS485, the bandwidth limitation being the RS232 to/from converters, and by removing those and creating a PC-USART<->TTL<->RS485 the limitation was avoided.

The bandwidth/filtering was at about 1 MHz (1 Mbps), with parts commonly used a long time ago, other part will of course have their own limits, and one should refer to the documentation of them to understand them, so I'm contending that 921600 is neither impractical or rare. But it is often the limit at which such interfaces are constructed.

Beyond >1Mbps I'm of the opinion people should be using synchronous, or self clocked signally, such that the encoding permits easy timing recovery, rather than the rather lame clock center scheme used for async serial. I've built other connections at 2.048 Mbps using Manchester encoding schemes.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
michaelmccartyeng
Associate II
Posted on March 16, 2014 at 02:32

I'm not using rs-232 signaling anywhere, sorry if I gave that impression.

I was just using a usb<->uart adapter with a prolific chip, similar to the ftdi chips but cheaper I'm sure. I'm starting to rethink my whole UART rx design. I set a int on uart rx, then in that int I read the byte into a circular buffer (software). I always have issues simply reading the RX its like I can see if the flag is set rxne then get the data but then how long do I wait before giving up. I think for high speed ''hands off'' operation using uart its better that I use dma and a circular buffer (in the dma). With these wifi modules I have to poll to see if data has come in, so its not really full duplex :( Anyway I'm rambling. @ Clive, nice new pic ! You previously said ''Nominally 1/16 of the APB clock is the max unless you switch to OVER8 mode.'' How can I calculate the APB clock ? I dont know why but for some reason the clocking system of the stm32 is still a big mystery to me.

/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
#define PLL_M 16
/* USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLLQ */
#define PLL_Q 7
#if defined (STM32F40_41xxx)
#define PLL_N 336
/* SYSCLK = PLL_VCO / PLL_P */
#define PLL_P 2
#endif /* STM32F40_41xxx */
#if defined (STM32F427_437xx) || defined (STM32F429_439xx)
#define PLL_N 360
/* SYSCLK = PLL_VCO / PLL_P */
#define PLL_P 2
#endif /* STM32F427_437x || STM32F429_439xx */
#if defined (STM32F401xx)
#define PLL_N 336
/* SYSCLK = PLL_VCO / PLL_P */
#define PLL_P 4
#endif /* STM32F401xx */
/******************************************************************************/
/**
* @}
*/
/** @addtogroup STM32F4xx_System_Private_Macros
* @{
*/
/**
* @}
*/
/** @addtogroup STM32F4xx_System_Private_Variables
* @{
*/
#if defined (STM32F40_41xxx)
uint32_t SystemCoreClock = 168000000;
#endif /* STM32F40_41xxx */
#if defined (STM32F427_437xx) || defined (STM32F429_439xx)
uint32_t SystemCoreClock = 180000000;
#endif /* STM32F427_437x || STM32F429_439xx */
#if defined (STM32F401xx)
uint32_t SystemCoreClock = 84000000;
#endif /* STM32F401xx */

Posted on March 16, 2014 at 02:56

If you look further through system_stm32f4xx.c you'll find APB1 at DIV4 and APB2 at DIV2, so 42 MHz, and 84 MHz, respectively, in a nominal 168 MHz system.

There is also a ''GetClocks'' function that should permit you to pull the current settings, based on HSE_VALUE, HSI_VALUE, and the assorted clock and PLL settings in effect. USART_Init() might be a good place to look.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
michaelmccartyeng
Associate II
Posted on March 16, 2014 at 03:42

USART2 uses APB1, 42,000,000 hz. That divided by 16 is 2,625,000. So I should be able to reach the maximum desired baud rate at 2073600.

I tested 2073600 between my usb/uart to the wifi device using the uart at that rate. It works.

Then I test from my stm32f4 discovery to the uart, I see the RX light but see nothing on the screen (in putty). Tested several times. Also set BP on RX in keil and tried to get it to break by sending data, no go. Then without shutting down anything I re plugged it into the wifi module already talking at that baud and it worked fine.

I must be doing something right or it would not work at the other baud rates ?

Tried that function you suggest

    RCC_GetClocksFreq(&rcc_clocks);

sysclk = 84000000

hclk = 84000000

PCLK1 = 21000000

PCLK2 = 42000000

I think that means I'm running at 84MHz not 168MHz, so that would mean my max baud is

21000000/16 = 1312500 which makes perfect sense !

Am I right in all this is pclk1 and pclk2 apb1 and apb2 ? and sysclk is the actual clock at which everything runs ?

If so do you have any idea how I can change it to 168MHz? I need to get smarter about the stm32 clocking situation. It has left me stumped quite a few times. I had set up clocks in the PIC years ago and understood how the different pieces fit together to form the system clock, similar to the tim setup.

Let me know if I'm on the right track and I'll continue down it.