Allowed Baud Rates on Serial1 in Arduino Nano 33 BLE

Hi,
I'd like to use the UART on the BLE33 in a project.
The one mapped on the pins RX(P1.10) and TX(P1.03).
I'm connecting Arduino to a Bluetooth module (Microchip RN4678) which supports up to 1Mbit baud rates for the best transfer rates over the air.
I've successfully initialized the UART using the Serial1.begin() function.
Serial.begin() instead is reserved for the UART over the USB port.

Since Arduino 33 BLE is based on the Nina B306 module
(datasheet here: https://www.u-blox.com/sites/default/files/NINA-B3_DataSheet_(UBX-17052099).pdf)
I'm reading on page 15 that the UART in the module supports up to 1Mbit baud rate and it has a programmable baud rate generator so that both standard and non standard baud rates are supported.
Hardware flow control is possible but on Arduino it doesn't seem like the possibility has been given since no pins have been mapped to RTS and CTS functions.

My BT module supports 115200, 307200 and 1000000 baud rates.
I've successfully initizialized the UART in Arduino with the Serial1.begin(115200) function and it perfectly works if the BT module if set to 115200 as well. The datas that Arduino sends to the BT module perfectly arrive to my smartphone.
Things do not work if I try to set both the BT module and Arduino to 307200 and 1000000 baud rates. Bad characters are sent to the BT module.
Is this a software problem related to the Serial1.begin() function that maybe doesn't support for example 307200 as a valid input? Which are the supported inputs in this case?
I also wonder if in the Arduino Nano 33 BLE the UART is effectively hardware based or maybe they're using a software serial over standard GPIO pins and renamed sofwareserial to serial1.

I've tried to set the BT module to 307200 baud rate and send datas to a smartphone from a PC using TeraTerm and it works so it's not a problem with the BT module.

Could you help me?
Thanks!

frank83poliba:
I also wonder if in the Arduino Nano 33 BLE the UART is effectively hardware based or maybe they're using a software serial over standard GPIO pins and renamed sofwareserial to serial1.

Its a hardware serial.

Serial is a asynchronous protocol. There is no clock signal available for the receiver to know where the data bits are valid. Any differences (crystal/resonator tolerance/quality, PLL stability, temperature) between transceiver and receiver clocks will introduce errors. With higher speeds the chance of that happening increases.

This is something best addressed by measurements e.g. looking at the signals with an oscilloscope.

Klaus_K:
Its a hardware serial.

Serial is a asynchronous protocol. There is no clock signal available for the receiver to know where the data bits are valid. Any differences (crystal/resonator tolerance/quality, PLL stability, temperature) between transceiver and receiver clocks will introduce errors. With higher speeds the chance of that happening increases.

This is something best addressed by measurements e.g. looking at the signals with an oscilloscope.

Thank you, I'm going to check it out when I'm in lab.
So looking at the datasheet it should be possible to set the UART at 307200 using the Serial1.begin(307200) function? And similarly at 1Mbit? There are no issues with particular values passed to the fuction as long as the hardware supports them?

I did some further testing and found you cannot generate 307200 baud using the library. The baud rate I measured (250 kbaud) was too far off for a tolerance issue.

So, I looked at mbedOS code. In the Serial.h file I found the following file link.

Github - ARMmbed - TARGET_NRF52 - serial_api.c

The code rounds the baud rates down before applying the settings. The baud rates supported are the ones used as example in the nRF52840 datasheet. Unfortunately the source file does not seem to be part of the installation. It likely is part of a pre-built library object.

So, I wrote a small test sketch to manually set the Baudrate register after you initialize the Serial1. I measured the baud rate using an oscilloscope.

void setup()
{
  Serial.begin( 9600 );
  while ( !Serial );

  Serial1.begin( 9600 );

  /*
    UART0 Base address 0x40002000
    UART Baudrate register address offset 0x524


    Baudrate formular according Nordic devzone

    Baudrate = desired baudrate * 2^32 / 16000000

    Baudrate = 307200 * 2^32 / 16.000.000
    Baudrate = 82.463.372 = 0x4EA4A8C
  */

  uint32_t baudrate;
  uint32_t *pBaudrate;

  pBaudrate = ( uint32_t * )0x40002524;
  baudrate = *pBaudrate;

  Serial.print( "Old Baudrate UART0: 0x" );
  Serial.println( baudrate, HEX );

  baudrate = 0x4EA4A8C;
 *pBaudrate = baudrate;

  pBaudrate = ( uint32_t * )0x40002524;
  baudrate = *pBaudrate;

  Serial.print( "New Baudrate UART0: 0x" );
  Serial.println( baudrate, HEX );
}

void loop()
{
  unsigned char c = 0x55;

  Serial1.print( c );
  delay( 1 );
}

Of course you don't need all the code just the following. Try and see whether the settings work on your board.

Serial1.begin( 9600 );
uint32_t baudrate = 0x4EA4A8C;
uint32_t *pBaudrate = ( uint32_t * )0x40002524;
*pBaudrate = baudrate;

Thank you Klaus!
I did some research on my own and it seems like the Serial1.begin() function cannot map and set non standard baud rates properly on the BLE 33.
These Arduino boards are relatively new and there are still many bugs (if you put serial transmissions and SPI transfers inside interrupt service routines the code will compile correctly but it won’t work at runtime…).
I’ve solved my issue with a few lines of code:

#define UARTE0_BASE_ADDR            0x40002000  // 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 BAUD307200                   0x04d01eac

 Serial1.begin(19200, SERIAL_8E1);
 UART0_BAUDRATE_REGISTER = BAUD307200;

Basically you have to write the correct baud rate value in the register itself using the datasheet:

I used the value on page 464 relative to the 460800 baud rate to get the bit/baud rate (0x075F7000/470588), then I multipled that value for 307200 and converted to HEX.
It works.