Thread: [libopenstm32-devel] usart_set_baudrate(...)
Status: Inactive
Brought to you by:
uh1763
From: Nico v. G. <Nic...@FU...> - 2011-03-09 13:34:20
Attachments:
0x1F785AE4.asc
|
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hey, I had some problems with the usart_set_baudrate() function and so I took a deeper look how it works. The baud rade generation for stm32 is described in the section "Fractional baud rate generation" in RM0008 Reference manual, Page 747. To set the baud rate for the stm32 boards, you have to set the correct unsigned fixed point number (fraction and mantissa) USARTDIV in USART_BRR. USART_BRR is a 32 Bit Register and divided into the following regions: Bit 3:0 DIV_FRACTION of USARTDIV Bit 15:4 DIV_MANTISSA of USARTDIV BIT 16:31 reserverd formula for baud rate Baud = f_ck / (16 * USARTDIV) , f_ck = PCLK1 (for USART 2,3,4,5, max 36MHz) or PCLK2 (for USART 1, max 72Mhz) => USARTDIV = f_ck / (16 * BAUD) We have to set the mantissa and fraction of USARTDIV in USART_BRR DIV_Mantissa = (u16) f_ck / (16* BAUD) -- USART_DIV value before the comma DIV_Fraction = f_ck / (16* BAUD) - DIV_Mantissa -- USART_DIV value after the comma To set the baud rate we have to form the correct unsigned fixed point number. For that we have to combine DIV_Mantissa and DIV_Fraction. The first four bits are for the fraction value and the next 11 bits are for the mantissa (for that shift DIV_Mantissa 4 times). USART_BRR = (DIV_MANTISSA << 4) | DIV_FRACTION the current implementation in lib/stm32/lib/usart.c: void usart_set_baudrate(u32 usart, u32 baud) { u32 clock = 72000000; /* FIXME: Don't hardcode this clock! */ /* TODO: Document and explain calculation. */ USART_BRR(usart) = (u16)((clock << 4) / (baud * 16)); } The assignment in the function does the calculation and the shift in one step but ignores the fraction value. With that I think you can not set all possible baud rate values... USART_BRR(usart) = (clock << 4) / (baud * 16) For the stm-h107 development the current implementation works fine for usart 2,3 but not for usart1. Usart1 has a different clock source (PCLK2, 72Mhz) and so you have to divide the baud parameter (for usart_set_baudrate(...)) by two to get the correct values. As it is hard to get the current pclk1 or pclk2 values, wouldn't it be better if there is a function like the following: void usart_set_baudrate(u32 clock, u32 usart, u32 baud); //set the clock manually or void rcc_get_pclkX(); //to get the clock for the calculation Then you don't have to hardcode the clock. Greetings Nico -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.14 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iQEcBAEBAgAGBQJNd4HUAAoJEBnE9vofeFrkc2kH+QHE8x+u7pCcvCrsysU64b9v 2Bf923Bjuzfjs6uNN2vw2RUuYl+7wXhNdgYhcGvKcyIDvlCT3oYLsPSmt6DCo0Gb o/W/isET4bd9dthu0lvAGmiBAOHsgTfv8IaiqvhrlDLTQdCp/QiJqLNPHrkczKBb IJ9HFFSMkTu+vK8l4KH+UcMpcw0ZVH7V3pS40illHLQmqiae5X7N1LyjutDI9H9d Ikzf9wE4zPXBNWCZ1kUB7qLAWpjUcgm2qCXnnwQed7vy/g7VUg13eV2eQQUdnTbz 5uvEgecyvJ2vrlAeFCxGXdUDOVke8xyw/IPOc1qFF/CsdTEB1LWVvWmBnL2Raik= =0oHY -----END PGP SIGNATURE----- |
From: Gareth M. <ga...@bl...> - 2011-03-13 00:53:06
|
On Thu, Mar 10, 2011 at 2:34 AM, Nico von Geyso <Nic...@fu...> wrote: > I had some problems with the usart_set_baudrate() function and so I took > a deeper look how it works. > The baud rade generation for stm32 is described in the section > "Fractional baud rate generation" in RM0008 Reference manual, Page 747. If I read it correctly, all the talk in the manual makes it sound fancy and complicated, but the simple division calculates the correct value. > For the stm-h107 development the current implementation works fine for > usart 2,3 but not for usart1. > Usart1 has a different clock source (PCLK2, 72Mhz) and so you have to > divide the baud parameter (for usart_set_baudrate(...)) by two to get > the correct values. > As it is hard to get the current pclk1 or pclk2 values, wouldn't it be > better if there is a function like the following: > > void usart_set_baudrate(u32 clock, u32 usart, u32 baud); //set the > clock manually I think this is the most obvious way to do it. I would swap the clock and usart parameters though. Regards, Gareth -- Black Sphere Technologies Ltd. Web: www.blacksphere.co.nz Mobile: +64 27 777 2182 Tel: +64 9 478 8885 Skype: gareth.mcmullin LinkedIn: http://nz.linkedin.com/in/gsmcmullin |
From: Piotr Esden-T. <pi...@es...> - 2011-03-13 19:57:39
|
Hi! On Mar 12, 2011, at 4:52 PM, Gareth McMullin wrote: > On Thu, Mar 10, 2011 at 2:34 AM, Nico von Geyso <Nic...@fu...> wrote: >> I had some problems with the usart_set_baudrate() function and so I took >> a deeper look how it works. >> The baud rade generation for stm32 is described in the section >> "Fractional baud rate generation" in RM0008 Reference manual, Page 747. > > If I read it correctly, all the talk in the manual makes it sound fancy and > complicated, but the simple division calculates the correct value. Yes that is what I figured myself. This sounds like marketting talk to make the divider sound more awesome than it is. :) I updated the rcc code to store the clock speeds of the apb1 and apb2 into variables and use them to calculate the baud divider, using just a simple division. Tested it a little and it seems to work like a charm. just pull from my fork repository and give it a try. :) > >> For the stm-h107 development the current implementation works fine for >> usart 2,3 but not for usart1. >> Usart1 has a different clock source (PCLK2, 72Mhz) and so you have to >> divide the baud parameter (for usart_set_baudrate(...)) by two to get >> the correct values. >> As it is hard to get the current pclk1 or pclk2 values, wouldn't it be >> better if there is a function like the following: >> >> void usart_set_baudrate(u32 clock, u32 usart, u32 baud); //set the >> clock manually > > I think this is the most obvious way to do it. I would swap the clock and usart > parameters though. I think it is better to track the clock speed of the system and have the baud rate still be calculated automatically... Cheers Esden -- Blog: http://www.esden.net Projects: http://open-bldc.org http://paparazziuav.org http://github.org/esden/floss-jtag http://github.org/esden/summon-arm-toolchain |