32F417 - any way to get baud rates below 1200? - Page 1
Forum section: electronics / general

author: peter-h
author_rank: Super Contributor
timestamp: March 13, 2021, 06:18:41 am
content: We have 42MHz on APB1 (168MHz CPU). Cube IDE generates the code for setting the baud rate in UART_SetConfig (via some extremely convoluted code) and my tests show good accuracy 2400-921.6k which is all I need at the top end, but I am trying to achieve compatibility with other stuff I have done and go down to these30, 37.5, 50, 75, 100, 110, 134, 150, 300, 600, 1200...The table in the ref manual for a 42Mhz clock shows thisand nothing below that but even 1200 baud doesn't work (it generates ~ 4k so probably some integer overflow).This is with x16 oversampling; x8 makes it even worse. This is the relevant bitLooking in the reference manual, there seems no obvious way other than to drastically slow down APB1, which we can't do because we are running some fast SPI stuff off that. There seems to be no other prescaler there, but maybe I am missing something obvious? And googling for hours finds nothing, other than the usual tons of negative comments on the ST "code generator", and one article which found an int32 overflow bug with CPUs running above 172MHz.Could one use one of the timers for the clock?Thank you for any ideas. No; I don't need 30 baudbut 110 is still used in some very old kit, and 1200 is definitely used (and should work IAW the above).

author: harerod
author_rank: Frequent Contributor
timestamp: March 13, 2021, 11:05:12 am
content: Since you have ruled out slowing down APB1-Clock, and you need a sloooow UART - why not go for a firmware emulation? AN4457 describes the concept.Not that it helps you with your current issue, but have a look at the STM32F40xxx block diagram. Not all U?ARTs are connected to APB1. USART1/6 are connected to APB2. Same goes for the SPIs. Not being intimate with you actual setup, I can only say that the firmware approach will work. You might even be able to share a timer.

author: peter-h
author_rank: Super Contributor
timestamp: March 13, 2021, 02:50:55 pm
content: OK; if one could bring a timer out onto a pin, square wave, and feed the UARTs from that pin, that would be another approach.I am using four uarts, 1,2,3 and 6. Uarts 1 and 6 come off apb2 (84MHz) and uarts 2,3 come off apb1 (42MHz). The baud rate issue exists on all the UARTs but at a push I would settle for supporting the low speeds on one of the UARTs only.Also I am using spi2 and spi3. SPI2 and 3 both come off apb1, 42MHz. We can't reduce that; while the fastest SPI3 clock is ~5.5MHz (the submultiple of 42 or 168MHz), I need 21MHz on SPI2. So apb1 is stuck at 42MHz afaict.It looks like APB2 is the one which we could play with because none of the SPI2/3 use it, and uarts 2,3 use it.But really I think I have the answer to my basic Q i.e. it isnotpossible to get low baud rates without some hacks.

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 13, 2021, 02:51:11 pm
content: Yeah UART emulation that would be. At such low rates, even with no particular care, any jitter due to software emulation is likely to be completely negligible for UART communication. Now for something with good accuracy, you can always use some timer with output compare feature, and feed it with periods corresponding to the 1's and 0's. That could even be done using DMA. All you'd need to do is convert the data to a stream of periods, which is straightforward.

author: peter-h
author_rank: Super Contributor
timestamp: March 13, 2021, 03:30:43 pm
content: There is something strange in the way the ST code calculates the divisors, because even setting both pclk1 and pclk2 to div16 (about 10MHz) still cannot produce less than 1200 baud on any uart!They call a function which returns the pclk frequency (which is slick, if slightly weird) so the whole thing is auto-compensating for whatever clock frequencies you select, but something weird is going on.The reference manual gives 1200 as the lowest baud rate. Maybe for a reason?

author: Siwastaja
author_rank: Super Contributor
timestamp: March 13, 2021, 04:47:33 pm
content: Bitbang in timer ISR.Make that same ISR do some other periodic workload, if possible. For example, my projects tend to involve either 10kHz or 1kHz timebase interrupt which does whatever is needed. You can divide such interrupt handler down; run a counter, do different things based on the remainder of the counter.If jitter is important, make the ISR high priority and run the UART stuff first.The reason super slow data rates are not supported is the rare need for them and the triviality of bitbanging such slow interfaces.Also as side note, you seem to be struggling with the ST "helper" tools and libraries. The only point is they should make your life easy. Apparently it's not working, so you will save time if you start reading the manual and writing bare metal. Configuring the UART is literally 3 lines of code. Configuring the clock tree first is maybe 6-10.

author: peter-h
author_rank: Super Contributor
timestamp: March 13, 2021, 06:00:31 pm
content: Could anyone have a guess why setting 600 as the baud rate simply does not work regardless of the clock setting?1200 works (with a 42MHz pclk) so going down another 4x should produce 300 baudBut instead at 600 baud one gets ~9400 baud so clearly something is broken.Yes indeed I may dump that ST code and just create a table of values to load in there.UPDATE:There is no mystery anymore really... The ST code generates a function SetSysClock for setting up the clocks but it doesn't call it. Another one is also created and that one is getting called: SystemClock_Config. Now I am using these settingsand I get a minimum baud rate of161 baudon uarts 2,3 which run off APB1 which with DIV16 is 10.5MHz. The minimum baud rate on uarts 1,6 which run off APB2 which with DIV2 is 84MHz, is about1285 baud.So basically the lowest baud rateachievable using any UARTon the 32F417 at 168MHz is161 baud. 150 baud could be achieved with a 150MHz core clock. This involves setting the slowest possible APB1 (or APB2 depending on which UART / SPI / timers you don't want to screw up) clock speed.No real issue with the top end, with 460800 fine on uart 2,3 (won't go higher) and 921600 fine on uart 1,6 (will go higher but limited by drivers in this case).The low baud rates are generated with great accuracy, as you might expect. The top ones achievable are generally no worse than 1% off, which is OK (10% out over 10 bits is still ok, unless the far end is doing auto baud, but few will be doing that at >> 115k).

author: peter-h
author_rank: Super Contributor
timestamp: May 02, 2021, 08:55:42 pm
content: There are some mistakes in my posts above regarding which UARTs use which APB clock source. I posted a long correction but it has disappeared.Also the ST32F4xx has TWO bits of code for setting up the APB1/APB2 clocks and the 2nd overrides the first, obviously. The first gets called from SystemInit which gets called from startup_stm32f407xx.s. This duplication of clock setup wasted a lot of time.

author: abyrvalg
author_rank: Frequent Contributor
timestamp: May 03, 2021, 09:39:34 am
content: That looks ridiculous. According to STM32F4xx reference manual baudrate=PCLKx/(16*USARTDIV) (not mentioning 8x oversample for simplicity), where USARTDIV is a 16 bit number, so at your original 42MHz PCLK the slowest achievable rate will be 42000000/(16*65535)=40.055.All you need to do is to write a correct value into USARTx->BRR manually after buggy Cube’s init. I.e. for 110 baud setting BRR=23864 would result in 109.998 baud - a great accuracy. You can just make precalculated baud:BRR table if your PCLKs doesn’t charge at runtime.

author: peter-h
author_rank: Super Contributor
timestamp: May 03, 2021, 11:02:34 am
content: I don't think BRR works as a straight 16 bit counter. This is from the manual I haveBRR is split into two bitfields.What the silicon implementation is, I have no idea, but somehow it enables them to achieve high baud rates with good accuracy which would never be possible with a straight divider. See the first image at the top of this thread. How would you get a < 1% error at 921.6k? This is why, traditionally, any project whose UART needed to achieve 38400, never mind anything faster like 115200, had to have the crystal chosen for exact division e.g. 14.7456MHz for the H8/300. The 32F4 typically runs with a 25MHz xtal since that is the only way to get both ethernet and USB to work. Internally there is a PLL multiplier which can generate integer multiples of this e.g. 168MHz but not fractional multiples. There is no "fractional-N" frequency synthesiser AFAICT, even though the Marconi patents on that must have lapsed by now.However, on actually reading it carefully, there is a mode which uses the BRR as you describe, but it isn't a UART mode AFAICTAs I say it is hard to imagine the silicon implementation but it looks like they have two separate dividers. One from the top 12 bits of BRR and the other from the bottom 4 bits. That is how they achieve the "fractional" divisions e.g. 2187.5.

author: abyrvalg
author_rank: Frequent Contributor
timestamp: May 03, 2021, 12:35:44 pm
content: Ahh, sorry, my mistake. I remembered that all that fractional stuff reduces to a simple integer division but forgot that reduction consumes the x16 multiplier (a 12:4 bits fixed point USARTDIV multiplied by 16 produces 16 bit integer, so baudrate=PCLK/BRR in 16x oversample mode).

author: peter-h
author_rank: Super Contributor
timestamp: May 03, 2021, 12:46:17 pm
content: I had a dig around on google trying to find out how this stuff actually works but found nothing other than the same people regurgitating the same pages from the reference manualOne possibility is that the 12:4 split in the description is purely artificial and actually it is just a 16 bit number, but that can't be right because you could not achieve the baud rate range together with the low errors at the high rates.Also the ref manual doesn't show anything below 1200 baud, in any of the many example tables of baud rate accuracies. I know "fashionable people" don't use anything that slow today but it doesn't seem likely that the entire ref manual has been written by 25 year oldsCould it be that 4 bits select a prescaler (a divider on the clock feed) and the 12 bits select the divisor? Calling it "mantissa" and "fraction" is just weird though.

author: abyrvalg
author_rank: Frequent Contributor
timestamp: May 03, 2021, 01:22:30 pm
content: I think it is artificial. Depending on the order of operations, if you divide PCLK by 16 first then divide by USARTDIV - it is fractional division. But if you multiply that fractional USARTDIV by 16 then divide PCLK by result - it is integer. I’ve found my older project with BRR=556 producing ~115200 baud at 64MHz PCLK, that matches PCLK/BRR.The calcultion in Cube sources (https://github.com/STMicroelectronics/STM32CubeF4/blob/2f3b26f16559f7af495727a98253067a31182cfc/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h#L833) looks quite complicated, but all that *25/4/100<<4 reduces to round(PCLK/baudrate).

author: peter-h
author_rank: Super Contributor
timestamp: May 03, 2021, 01:37:46 pm
content: I can't get my head around this.Taking the table at the top of the thread, and with a 42MHz clock, 42E6/2187 gives very close to (1200*16) which is a normal x16 clock for a UART at 1200 baud.And 2187*16=34992 which is why 600 baud cannot be done because you would need > 16 bits. The lowest which doesn't exceed 65536 is around 640 baud. But actually it is more complex. I found that this is what is achievableP1,P4 can support baud rates from 161 baud to 460800 baud (PCLK2, 10.5MHz)P2,P3 can support baud rates from 1288 baud to 3686400 baud (PCLK1, 42MHz)and the 1288 baud figure suggests that there is an additional /2 involved, which makes sense in frequency generation where you use the overflow pulse from a counter to flip a flip-flop to produce a square wave.But what about 921.6k? The x16 clock needed is 14.7456MHz. The required divider is 2.848 and there is no way to achieve anything near that.There is nothing one can do with 42MHz which achieves 14.7456MHz to < 1% which is what they are achieving. The only way is toupscalethe 42MHz with a DPLL.One can step through the code and see the values actually being loaded.I know these high baud rates work accurately because I checked them with a scope.

author: abyrvalg
author_rank: Frequent Contributor
timestamp: May 03, 2021, 06:28:35 pm
content: 921600 from 42MHz PCLK: BRR=46, 42000000/46=913043 - that is <1% error. And those numbers are exactly what we can see inRM- table 142, row 10. They specify 2.875 divisor there, 2.875*16=46.

author: peter-h
author_rank: Super Contributor
timestamp: May 03, 2021, 07:59:05 pm
content: You need a x16 clock for this UART though. 921600x16=14.7456MHz.Thatis the frequency which needs to be generated to better than 1%, not 921600.

author: PCB.Wiz
author_rank: Super Contributor
timestamp: May 03, 2021, 08:53:21 pm
content: Quote from: peter-h on May 03, 2021, 01:37:46 pmThose values suggest a 16 bit divider on P1,P4 and a 15 bit divider on P2,P3Quote from: peter-h on May 03, 2021, 01:37:46 pmFractional baud is delivered by wobbling each bit time, so the average is validan example 7/8 = 0.875If we take 8 bit times, and choose to /2 or /3 for each of those bits, the totalaverage freqover 8 cycles is8/((7*3/42M)+(1*2/42M)) = 14608695.65and the Baud error from your ideal clock1-ans/14.7456M = 0.928%Your scope may show you the fractional decisions jitter, if you send "U"

author: peter-h
author_rank: Super Contributor
timestamp: May 03, 2021, 09:32:10 pm
content: What do you think is the actual circuit implementation?Yes; of course, one could wobble the edges with the 42MHz resolution. But that's quite clever. And it certainly isn't a straight 15 or 16 bit divider from 42MHz.

author: PCB.Wiz
author_rank: Super Contributor
timestamp: May 03, 2021, 10:00:05 pm
content: Quote from: peter-h on May 03, 2021, 09:32:10 pmI'd guess they use a rate-multiplier (google CD4089) and an add-one Flip-flop to a reload counter. You need to spread the jitter as evenly as possible.ie you set to /2 and add one clock to make that /3 etcYour scope should show that wobble.One detail around averages is the common UART frame is 10 bits (start-data-stop) but the divider is binary, so that means the wobble pattern would repeat every 5 bytes if they do not reset the swallow counters.

author: cv007
author_rank: Frequent Contributor
timestamp: May 04, 2021, 01:02:58 am
content: >And it certainly isn't a straight 15 or 16 bit divider from 42MHz.I am not a chip designer, but why wouldn't it be straight forward-load counters from brr- an integer counter that uses the divided clock (/8 or /16), and a fractional counter taking a /1 clock(a re-settable main counter/divider with taps at /16,/8,/1 which I'm sure is in some diagram somewhere)when fractional counter reaches 0, enable integer counterwhen integer counter reaches 0, do stuffreload counters from brrrepeat until frame is doneSince your minimal value has to be >=1 in the integer portion, it would appear they use the integer counter value of 0 as the 'do stuff' signal. You will notice that for 8x sampling they require you to make the fractional portion 0-7 ( [3:0]>>1 ). So that fractional part must go to a separate counter.This would also mean that error calculations are just as straight forward as anything else since your error is calculated for 1 bit and error tolerance depends on data bits used just as before.So although I know less about everything than everyone else, I think there is no 'wobble' and your bit times are consistent. I have a G0 doing 9600 baud from 16MHz, so I guess I could check it myself by hooking up the logic analyzer although I cannot get to the uart pins easily (although I can move the uart to other pins I can get to). I also have avr0/1's which also have a fractional baud rate divider and have looked at uart signals often enough, and can't say I have ever noticed any variation in the bit times.

author: amyk
author_rank: Super Contributor
timestamp: May 04, 2021, 03:30:06 am
content: This thread is a good example of how shitty software can get in the way of exploiting the full capabilities of the hardware.You should be able to get down to ~160.2 baud (10.5MHz) and ~1281.8 (84MHz) with the divider maxed out (FFFF = 4095.9375) - that is, assuming you've checked that the upper 16 bits of that register are indeed not used, and that 0 doesn't actually result in a "secret" 4096 divisor.As for the implementation, my guess is just a 16x PLL multiplier with a 16-bit divider (BRR itself), especially given that it does 16x oversampling. In 8x mode it ignores BRR.

author: technix
author_rank: Super Contributor
timestamp: May 04, 2021, 06:05:46 am
content: If nothing else works, you can always resort to external chips. It can be a separate slow clock MCU like STM32L011/STM32F030 aggregating multiple slow comms into one faster link (a 2.5Mbps SPI or 100kbps I2C,) or it can be dedicated external UART chips like SC16IS740 running on its own slow clock. Basically you may need a south bridge for your high speed chip.

author: peter-h
author_rank: Super Contributor
timestamp: May 04, 2021, 07:36:02 am
content: "You should be able to get down to ~160.2 baud (10.5MHz) and ~1281.8 (84MHz) "That is what I found experimentally - except that the 84MHz happens to be on PCLK1 which is 42MHz max, so the max is ~640 baud. Hmmm not actually sure; will need to re-test that.The 10.5MHz has been set up on PCLK2.I am glad that I wasn't missing something obviousThe SC16IS740 is a nice chip - thanks. It does all sorts of good stuff like 485 driver enable, too.

author: technix
author_rank: Super Contributor
timestamp: May 04, 2021, 08:22:45 am
content: Quote from: peter-h on May 04, 2021, 07:36:02 amSC16IS740 is the bottom of the stack here - there are SC16IS750, SC16IS752 etc above it.I have used a lot of SC16IS740's on Raspberry Pi projects since Raspberry Pi 3, as that chip no longer have a properly functioning, stable UART on the GPIO pins, unless you sacrifice onboard Bluetooth. My GPS board used an SC16IS752 dual UART, one going to the GPS module, and the other going to an onboard microcontroller that trims the DS3231 TCXO.

author: cv007
author_rank: Frequent Contributor
timestamp: May 04, 2021, 08:45:47 pm
content: >so I guess I could check it myself by hooking up the logic analyzerCan't really determine what goes on under the hood it seems (on a G0). I have a DSLogic that can do 400MHz, and measure what I guess are precise bit times, but what I see suggests there is a difference in rising vs falling measurements for the dslogic. The high bit times remain consistently higher than the low bit times no matter if the bit pattern changes. Maybe this is really from the mcu, but seems unlikely.In over8 mode, it appears bit3 doesn't seem to make any difference whether its set or not, so not sure why the datasheet shows concern for this bit in over8 mode, although you will clear it when you adjust the fraction anyway.I'll stick to just being a uart user, where I belong.#include "MyStm32.hpp"Uart u1{ Uart1_B6B7, 9600 }; //baud doesn't matter, will be changing brrint main(){for( auto brr = 16;; ) { //16-31, 16MHz/16=1Mbaud, 16MHz/31=~516kbaudif( brr > 31 ){ brr = 16; delayMS(1000); }u1.reg_.BRR = brr++; //reg_ made public so have access to registersu1.print("\x55\x55");delayMS(10);}}

author: PCB.Wiz
author_rank: Super Contributor
timestamp: May 04, 2021, 10:06:15 pm
content: Quote from: cv007 on May 04, 2021, 01:02:58 amThere will be some wobble in fractional UARTS, as any edge has to snap to a 42Mhz slot.What the logic tries to do, is pick the best-fit 1/42M time tick, so theaveragecan have better precision.At low bauds like 9600, such ~24ns wobble will be lost in the dividers, to look for this effect you need to pick a much higher baud rate.

author: peter-h
author_rank: Super Contributor
timestamp: May 08, 2021, 10:38:19 am
content: After all this, is there any consensus on the actual hardware?Is it possible that the two integers are just- a clock prescaler- a conventional UART dividerThe CD4089 is just a sync counter with a selector on the outputs. It doesn't "multiply" the clock in any way." as any edge has to snap to a 42Mhz slot."That's the clever bit I don't get.

author: PCB.Wiz
author_rank: Super Contributor
timestamp: May 09, 2021, 10:07:28 am
content: Quote from: peter-h on May 08, 2021, 10:38:19 amAlmost, you need to get the fractional decision in there somehowQuote from: peter-h on May 08, 2021, 10:38:19 amYes, but it can give a varying density spread swallow pulse enable. Thus it gives a means to enable a /N or /(N+1) counterBy varying when that decision is applied, you can on average, get some average adder between +0 and +1 - ie a fractionQuote from: peter-h on May 08, 2021, 10:38:19 amThe edges have to be aligned to the clock, so the fractional part is anaverage over many bits.None of the bits are actually of exactly the desired baud time, some are slower and some are faster, but any edge should (ideally) always be at the nearest (1/42M) time slot.

author: amyk
author_rank: Super Contributor
timestamp: May 10, 2021, 03:31:42 am
content: I don't think there's anything complex going on here; it's just a 16x or 8x fixed multiplier with a variable divider (the baudrate control register). It's not a coincidence that the oversampling is 16x (or 8x) and the "fractional" part of the register is 4 bits (or 3).

author: cv007
author_rank: Frequent Contributor
timestamp: May 10, 2021, 05:35:37 am
content: >I don't think there's anything complex going on here;Most likely. For transmitting, they can simply count using the brr value and if over8 mode then they make bit3 'disappear' so the fractional part underflows/overflows from bit2 to bit4 doubling the speed. For receiving, they now have to sample probably 3 times somewhere in what they think is the middle of the bit time. The incoming clock drives everything (the internal bus clock).The below takes the minimum value for the integer portion (which is 1) and uses both extremes of the fractional value. I'll assume everything above these numbers works out the same. The over8 mode somehow makes bit3 disappear, but don't know how- magic maybe.====================================default 16x mode====================================|-1 bit time, 16 clocks-------|-|extra 1/16|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7|_|_||-sample 3 starting here (#8)brr = 0b10001 = 1 1/16sample counter = 0b10001>>1 = 0b1000 = 8|-1 bit time, 16 clocks-------|---- extra 15/16-------------||x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1|_|_|---> |_|_||-sample 3 starting here (#15)brr = 0b11111 = 1 15/16sample counter = 0b11111>>1 = 0b1111 = 15====================================over8 mode - make bit3 disappear====================================|-1 bit time |-|--extra 1/8|x|x|x|x|x|x|x|x|X|1 2 3 4 5 6 7 8 9|_|_||-sample 3 starting here (#4)brr = 0b1_001 = 1 1/8sample counter = 0b1_001>>1 = 0b100 = 4|-1 bit time--|-|-extra 7/8-||x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|1 2 3 4 5 6 7 8 9 0 1 2 3 4 5|_|_|>|_|_||-sample 3 starting here (#7)brr = 0b1_111 = 1 7/8sample counter = 0b1_111>>1 = 0b111 = 7My technical drawings were provided by KWrite, the #1 technical drawing app.

author: PCB.Wiz
author_rank: Super Contributor
timestamp: May 10, 2021, 11:01:13 pm
content: Quote from: amyk on May 10, 2021, 03:31:42 amThat's easy to say, but is actually complex in silicon. Multipliers are very hard to do, especially over wide clock ranges.The simplest solutions are entirely digital.The simplest digital solution I can see is a /N or N+1, which you implement with an optional single FF delay on the reload, and that decision comes from a Rate Multiplier fed from the fractional bit field.The outcome is edges that jitter, by 1 sysclk, but the average across a whole data byte is less than 1 sysclk.

author: abyrvalg
author_rank: Frequent Contributor
timestamp: May 11, 2021, 09:18:16 am
content: Also note that fractional wobbling applies to x16 (x8) sampling clock. The bit duration still can be expressed as an integer number of source clock pulses by design. So in the worst case we have wobbling sampling points within a stable bit, who cares? Majority encoder will hide it.

author: peter-h
author_rank: Super Contributor
timestamp: May 17, 2021, 02:33:29 pm
content: Turns out the proposed solution - dropping PCLK2 to the lowest figure of 10.5MHz - is a problem if you want to use ethernet. Some undocumented hardware bug:https://www.eevblog.com/forum/microcontrollers/stm32f417-any-reason-why-a-min-pclk2-speed-is-required-for-ethernet-to-work/msg3571352/#msg3571352EDIT: the latest reference manual, Feb 2021, modifies some of the supported baud rate tables, and confirms the above conclusion i.e. at42MHzPCLKx, the achievable rates are644baud (my own measurement, and implied by their "1200" figure) to1843200baud (their figure, which correlates with me measuring 2x that as max possible with an 84MHz PCLK2).Update: actual tests with a 42MHz PCLK show a range of 642 baud to over 2.7mbps.The error goes somewhat above 1% at the top end. At 1843200 it is 0.7%. At 115200 it is 0.17%. At 38400 it is 0.02%.