[SOLVED] Non-standard baud rate

Hi,
I’m using a boron to communicate with another micro over serial1 only problem is that the required baud rate is 63000. The problem is it looks like I cant setup Serial1 for 63000.
When ever I include the following code in Setup

                      Serial1.begin(63000,SERIAL_8E1);    // for profibus mux

The boron boots up ok, but then throws a panic:hard fault error as soon as it hits the line.
Doing a safe boot, followed by reprogramming with the baud rate changed to 115200 fixes it

EDIT
I have also verified that the ARGON has the exact same behavior.
The troubleshooting guides says that hard faults are caused by the following

  • Using an invalid pointer.
  • Memory corruption caused by freeing memory twice, overwriting the end of a block of memory, etc.
  • Making Wire (I2C) calls without calling Wire.begin().

Since the only change needed is to change the baud rate back to a standard one, I don’t think the issue is with my code.

Also just for grins I changed it to 57600 and there was no hard fault, but changing to 57601 resulted in a hard fault. Seems like it is anything other than “approved” baud rates.
/EDIT

So is there anyway I can use custom baud rates with the Boron?
Can it be done with direct writes to registers?

Any help would be appreciated, since it is sort of a show stopper…

SOLVED
Thanks to all. Ended up just writing to the Nordic’s uart baudrate register.
Verified and it works.
Note that this has only been tested on the BORON, but should also work on the ARGON since they use the same micro

 #define UARTE0_BASE_ADDR            0x40002000  // As per nRF52840 Product spec - UARTE
 #define UARTE1_BASE_ADDR            0x40028000  // As per nRF52840 Product spec - UARTE
 #define UART_BAUDRATE_REG_OFFSET    0x524 // As per nRF52840 Product spec - UARTE
 
 #define UART0_BAUDRATE_REGISTER     (*(( unsigned int *)(UARTE0_BASE_ADDR + UART_BAUDRATE_REG_OFFSET)))
 #define UART1_BAUDRATE_REGISTER     (*(( unsigned int *)(UARTE1_BASE_ADDR + UART_BAUDRATE_REG_OFFSET)))
 
 /* from nRF52840 Product spec
    A baud rate of 31250 uses a register value of 0x00800000
   (31250/0x00800000) = 0.00372529 baud per bit
    63000 / 0.00372529 = 0x0102116F
    rounding it off to 0x0102100 give a theoretical baud rate of 62998  (Pretty good)
*/
  #define BAUD63000                    0x01021000

 
   Serial1.begin(19200,SERIAL_8E1);    // IFS board attached to Serial1, use this to setup Serial port for class use
 
   // original values - used to verify that we are looking at the correct registers
   Serial.print("UART0 Baud rate: 0x"); Serial.println(UART0_BAUDRATE_REGISTER,HEX);
   Serial.print("UART1 Baud rate: 0x"); Serial.println(UART1_BAUDRATE_REGISTER,HEX);
   Serial.println("");
 
   // change the baud rate
   UART0_BAUDRATE_REGISTER = BAUD63000;// NOTE: UART0 is attached to Serial1.  Serial is attached   to USB
 
   // Did the right stuff change?
   Serial.print("UART0 Baud rate: 0x"); Serial.println(UART0_BAUDRATE_REGISTER,HEX);
   Serial.print("UART1 Baud rate: 0x"); Serial.println(UART1_BAUDRATE_REGISTER,HEX);

No answers, but I’m just curious what the other micro is that’s using that odd baud rate?

It's nothing special, simply an MSP430. The complication comes in is that the software on this micro is designed to interface with a COTS (commercial off the shelf) radio module that uses a different micro and different master clock. So 63000 was the max baud rate that we could reliably synthesize on both micros with enough accuracy to work reliably. As I remember the next lowest baud that worked was 19200.

As you probably know, micro's use a divider or series of dividers to generate the baud rate from the system clock. Since both of the micros (the MSP430 that I am interfacing to and an NXP that the 430 originally interfaced to) have rather slow clocks and are older, the resolution of those dividers are limited. So you never really get the baud rate you are looking for there is always a certain amount of error. The question is how much error can your system handle.
The Boron uses the Nordic nRF52840 which uses a 32bit divider so I should be able to get a buad rate close enough to work.
My assumption is the Serial.begin(baud), method simply does the math and writes the correct value to the BAUD register, so I don't get why calling Serial.begin(63000) throws a hardware fault.

from the nordic data sheet.

BAUDRATE Address offset: 0x524

For instance writing 0x01D7E000 to the BAUDRATE register will set the baud rate to 115200 which is actually a rate of 115942, but this is close enough due to oversampling of the signal.

At the end of the day I could change the msp430 to use 57600 vs 63000, but since this is a legacy device its gonna be a pain to fire up the build computer, pull the source, recompile, reprogram, etc. vs just setting the Boron / Argon to 63000 which should in theory be simple.

Digging through the open source of the particle OS I wasn't able to find where the value for the baud rate register is calculated and written.

It’s not possible to use a non-standard baud rate with Serial.begin(), as you discovered, because there’s a lookup table that translates the values:

I’m not sure whether you could get around this by using a modified Device OS or directly manipulating registers; I’ve never tried it.

1 Like

Awesome!
Thanks. I should be able to write to register directly.
Can you tell me what the base address for the registers are?
I’m not seeing it in the Boron documentation…

Awesome to see the fix for the mesh products. I want to make a Photon talk at 100,000 Baud, do you think a similar approach would work there? I haven’t ever written directly to registers on the photon before, but I’m guessing the same approach would make it through the compiler for the STM?

Yes the same approach should(I won’t say it will until I have done it myself :slight_smile: work for the STM32 on the Photon.
I’m sure you know, but just in case…
The details will be different between the two processors (register address, values, how to calculate, etc etc etc) but the general concept is the same.
BTW: Just pulled up the data sheet for the STM32F205 and everything you need is in the USART section. Also one thing to keep in mind, I think the 205 has multiple USARTS, so make sure you are working with the correct one.
Another route is STM has a tool called cubeMX that is used to generate C code to set up the registers on the uC’s. This might be easier since all you need to do is select the baud rate you want and it will tell you the registers and values you need to set. But that is not as fun…

1 Like

Cheers,

I’ve already hit the datasheet, got the addresses right and the weird as hell baud calcs the STM uses (fractional baud divisors?!?). I just wanted to make sure there’s nothing in the libs that’s going to ‘fix’ with the registers after I’ve screwed with them. I do uP stuff for my day job (mostly on atmels), but that’s working true bare-metal with basically no lib or driver support, so I’m bloody terrible at chasing down side-effect issues from other people’s code running on my device… :wink: