UNO R4 and Serial1 , different nr databits

On the UNO R4 Wifi/Minima : Serial1.begin(9600, SERIAL_8E1) works fine . (As well as None, Odd Parity). But I can not use other databits than 8. Normally You could set between 5-8 databits here.
Will this be supported later ???

Also.. does anyone know what other commands could be used with Serial1 ?

Hi,

I have the same problem with my UNO R4 Minima.
Trying to get Serial1 to transmit with SERIAL_7E1, but no such luck. The Arduino locks up every time.

To better understand what is happening and try different settings, Serial1 is connected to a PC (Win or Mac) with a USB-TTL adapter based on CH340 chip.
When receiving data in 7E1 from the PC, the Arduino will read single characters correctly. When trying to transmit data from the Arduino it will lock up every time, with or without the USB-TTL adapter connected to it.

I'm happy to start a separate thread with more details about what I'm trying to achive. But at this time I'd just like to second Christer_A1's question:

Do different No. databits work for Serial1 on the UNO R4? (More specifically SERIAL_7E1.)
If not, will this ever change?

Did you find a solution?

I have not tried since beginning of this year.
So I am not up to date here.
I have used other boards than Uno R4

1 Like

Have they worked okay? i may do the same... mine constantly crashes with 7 data bits. fine with 8...

The old UNO R3 works fine as well many other boards.
Checked 5,6,7,8 bits
No, Even, Odd parity
Baud 4800, 9600, 38400, 115200.

It does not surprise me...

Looking at the current code:

/* -------------------------------------------------------------------------- */
void UART::begin(unsigned long baudrate, uint16_t config) {
/* -------------------------------------------------------------------------- */  
  int max_index = PINS_COUNT;

  init_ok = cfg_pins(max_index);
  
  if(init_ok) {
    UART::g_uarts[channel]        = this;

    uart_baud.semr_baudrate_bits_b.abcse          = 0;
    uart_baud.semr_baudrate_bits_b.abcs           = 0;
    uart_baud.semr_baudrate_bits_b.bgdm           = 1;
    uart_baud.cks                                 = 0;
    uart_baud.brr                                 = 25;
    uart_baud.mddr                                = (uint8_t) 256;
    uart_baud.semr_baudrate_bits_b.brme           = false;

    uart_cfg_extend.clock                         = SCI_UART_CLOCK_INT;
    uart_cfg_extend.rx_edge_start                 = SCI_UART_START_BIT_FALLING_EDGE;
    uart_cfg_extend.noise_cancel                  = SCI_UART_NOISE_CANCELLATION_DISABLE;
    uart_cfg_extend.rx_fifo_trigger               = SCI_UART_RX_FIFO_TRIGGER_MAX;
    uart_cfg_extend.p_baud_setting                = &uart_baud;
    uart_cfg_extend.flow_control                  = SCI_UART_FLOW_CONTROL_RTS;
    uart_cfg_extend.flow_control_pin              = (bsp_io_port_pin_t) UINT16_MAX;
    if (rts_pin != -1 && cts_pin != -1) {
      uart_cfg_extend.flow_control                  = SCI_UART_FLOW_CONTROL_HARDWARE_CTSRTS;
    }
    uart_cfg_extend.rs485_setting.enable          = SCI_UART_RS485_DISABLE;
    uart_cfg_extend.rs485_setting.polarity        = SCI_UART_RS485_DE_POLARITY_HIGH;
    uart_cfg_extend.rs485_setting.de_control_pin  = (bsp_io_port_pin_t) UINT16_MAX;
    
    uart_cfg.channel                              = channel; 
    uart_cfg.p_context                            = NULL;
    uart_cfg.p_extend                             = &uart_cfg_extend;
    uart_cfg.p_transfer_tx                        = NULL;
    uart_cfg.p_transfer_rx                        = NULL;
  
    switch(config){
      case SERIAL_8N1:
          uart_cfg.data_bits = UART_DATA_BITS_8;
          uart_cfg.parity = UART_PARITY_OFF;
          uart_cfg.stop_bits = UART_STOP_BITS_1;
          break;
      case SERIAL_8N2:
          uart_cfg.data_bits = UART_DATA_BITS_8;
          uart_cfg.parity = UART_PARITY_OFF;
          uart_cfg.stop_bits = UART_STOP_BITS_2;
          break;
      case SERIAL_8E1:
          uart_cfg.data_bits = UART_DATA_BITS_8;
          uart_cfg.parity = UART_PARITY_EVEN;
          uart_cfg.stop_bits = UART_STOP_BITS_1;
          break;
      case SERIAL_8E2:
          uart_cfg.data_bits = UART_DATA_BITS_8;
          uart_cfg.parity = UART_PARITY_EVEN;
          uart_cfg.stop_bits = UART_STOP_BITS_2;
          break;
      case SERIAL_8O1:
          uart_cfg.data_bits = UART_DATA_BITS_8;
          uart_cfg.parity = UART_PARITY_ODD;
          uart_cfg.stop_bits = UART_STOP_BITS_1;
          break;
      case SERIAL_8O2:
          uart_cfg.data_bits = UART_DATA_BITS_8;
          uart_cfg.parity = UART_PARITY_ODD;
          uart_cfg.stop_bits = UART_STOP_BITS_2;
          break;
    }
    
    uart_cfg.p_callback = UART::WrapperCallback;
  }
  else {
    return;
  }

  init_ok &= setUpUartIrqs(uart_cfg);
  
  fsp_err_t err;
  const bool bit_mod = true;
  const uint32_t err_rate = 3000; //means 3%

  err = R_SCI_UART_BaudCalculate(baudrate, bit_mod, err_rate, &uart_baud);
  if (uart_baud.mddr == 0) {
    err = R_SCI_UART_BaudCalculate(baudrate, false, err_rate, &uart_baud);
  }
  err = R_SCI_UART_Open (&uart_ctrl, &uart_cfg);
  if(err != FSP_SUCCESS) while(1);
  err = R_SCI_UART_BaudSet(&uart_ctrl, (void *) &uart_baud);
  if(err != FSP_SUCCESS) while(1);

  rxBuffer.clear();
  txBuffer.clear();
}

They are only setup for 8 bit versions...
Looks like the hardware should support it:

It has been awhile since I looked at this stuff, so I don't have any idea
if the underlying code, like:

fsp_err_t R_SCI_UART_Open(uart_ctrl_t * const p_api_ctrl, uart_cfg_t const * const p_cfg);

Handles other options or not.

Thanks. I also think that the hardware will support more than 8 bit. 7-9 bits !
There are many cases where 9bit support is needed.
In my case, several marine instrument systems use the 9bit as a separate signalling bit.
There are tweaks here for UNO R3 , ESP32.
Also Teensy support 9bit with a documented small change in a .h file.
It would be great if also UNO R4 could be used here.

It should be easy for any of you to be able to try adding 7 bit support and see if it works...

That is try, changing the above mentioned method, to something like:

/* -------------------------------------------------------------------------- */
void UART::begin(unsigned long baudrate, uint16_t config) {
/* -------------------------------------------------------------------------- */  
  int max_index = PINS_COUNT;

  init_ok = cfg_pins(max_index);
  
  if(init_ok) {
    UART::g_uarts[channel]        = this;

    uart_baud.semr_baudrate_bits_b.abcse          = 0;
    uart_baud.semr_baudrate_bits_b.abcs           = 0;
    uart_baud.semr_baudrate_bits_b.bgdm           = 1;
    uart_baud.cks                                 = 0;
    uart_baud.brr                                 = 25;
    uart_baud.mddr                                = (uint8_t) 256;
    uart_baud.semr_baudrate_bits_b.brme           = false;

    uart_cfg_extend.clock                         = SCI_UART_CLOCK_INT;
    uart_cfg_extend.rx_edge_start                 = SCI_UART_START_BIT_FALLING_EDGE;
    uart_cfg_extend.noise_cancel                  = SCI_UART_NOISE_CANCELLATION_DISABLE;
    uart_cfg_extend.rx_fifo_trigger               = SCI_UART_RX_FIFO_TRIGGER_MAX;
    uart_cfg_extend.p_baud_setting                = &uart_baud;
    uart_cfg_extend.flow_control                  = SCI_UART_FLOW_CONTROL_RTS;
    uart_cfg_extend.flow_control_pin              = (bsp_io_port_pin_t) UINT16_MAX;
    if (rts_pin != -1 && cts_pin != -1) {
      uart_cfg_extend.flow_control                  = SCI_UART_FLOW_CONTROL_HARDWARE_CTSRTS;
    }
    uart_cfg_extend.rs485_setting.enable          = SCI_UART_RS485_DISABLE;
    uart_cfg_extend.rs485_setting.polarity        = SCI_UART_RS485_DE_POLARITY_HIGH;
    uart_cfg_extend.rs485_setting.de_control_pin  = (bsp_io_port_pin_t) UINT16_MAX;
    
    uart_cfg.channel                              = channel; 
    uart_cfg.p_context                            = NULL;
    uart_cfg.p_extend                             = &uart_cfg_extend;
    uart_cfg.p_transfer_tx                        = NULL;
    uart_cfg.p_transfer_rx                        = NULL;
  
    switch(config){
      case SERIAL_8N1:
          uart_cfg.data_bits = UART_DATA_BITS_8;
          uart_cfg.parity = UART_PARITY_OFF;
          uart_cfg.stop_bits = UART_STOP_BITS_1;
          break;
      case SERIAL_8N2:
          uart_cfg.data_bits = UART_DATA_BITS_8;
          uart_cfg.parity = UART_PARITY_OFF;
          uart_cfg.stop_bits = UART_STOP_BITS_2;
          break;
      case SERIAL_8E1:
          uart_cfg.data_bits = UART_DATA_BITS_8;
          uart_cfg.parity = UART_PARITY_EVEN;
          uart_cfg.stop_bits = UART_STOP_BITS_1;
          break;
      case SERIAL_8E2:
          uart_cfg.data_bits = UART_DATA_BITS_8;
          uart_cfg.parity = UART_PARITY_EVEN;
          uart_cfg.stop_bits = UART_STOP_BITS_2;
          break;
      case SERIAL_8O1:
          uart_cfg.data_bits = UART_DATA_BITS_8;
          uart_cfg.parity = UART_PARITY_ODD;
          uart_cfg.stop_bits = UART_STOP_BITS_1;
          break;
      case SERIAL_8O2:
          uart_cfg.data_bits = UART_DATA_BITS_8;
          uart_cfg.parity = UART_PARITY_ODD;
          uart_cfg.stop_bits = UART_STOP_BITS_2;
          break;
      // add 7 bit support
      case SERIAL_7N1:
          uart_cfg.data_bits = UART_DATA_BITS_7;
          uart_cfg.parity = UART_PARITY_OFF;
          uart_cfg.stop_bits = UART_STOP_BITS_1;
          break;
      case SERIAL_7N2:
          uart_cfg.data_bits = UART_DATA_BITS_7;
          uart_cfg.parity = UART_PARITY_OFF;
          uart_cfg.stop_bits = UART_STOP_BITS_2;
          break;
      case SERIAL_7E1:
          uart_cfg.data_bits = UART_DATA_BITS_7;
          uart_cfg.parity = UART_PARITY_EVEN;
          uart_cfg.stop_bits = UART_STOP_BITS_1;
          break;
      case SERIAL_7E2:
          uart_cfg.data_bits = UART_DATA_BITS_7;
          uart_cfg.parity = UART_PARITY_EVEN;
          uart_cfg.stop_bits = UART_STOP_BITS_2;
          break;
      case SERIAL_7O1:
          uart_cfg.data_bits = UART_DATA_BITS_7;
          uart_cfg.parity = UART_PARITY_ODD;
          uart_cfg.stop_bits = UART_STOP_BITS_1;
          break;
      case SERIAL_7O2:
          uart_cfg.data_bits = UART_DATA_BITS_7;
          uart_cfg.parity = UART_PARITY_ODD;
          uart_cfg.stop_bits = UART_STOP_BITS_2;
          break;

    }
    
    uart_cfg.p_callback = UART::WrapperCallback;
  }
  else {
    return;
  }

  init_ok &= setUpUartIrqs(uart_cfg);
  
  fsp_err_t err;
  const bool bit_mod = true;
  const uint32_t err_rate = 3000; //means 3%

  err = R_SCI_UART_BaudCalculate(baudrate, bit_mod, err_rate, &uart_baud);
  if (uart_baud.mddr == 0) {
    err = R_SCI_UART_BaudCalculate(baudrate, false, err_rate, &uart_baud);
  }
  err = R_SCI_UART_Open (&uart_ctrl, &uart_cfg);
  if(err != FSP_SUCCESS) while(1);
  err = R_SCI_UART_BaudSet(&uart_ctrl, (void *) &uart_baud);
  if(err != FSP_SUCCESS) while(1);

  rxBuffer.clear();
  txBuffer.clear();
}

On my machine this is the file:
C:\Users\kurte\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.2.2\cores\arduino\Serial.cpp

And if it works, then maybe someone can create a Pull request for the change.

Note: If it were me, I would probably also add a default:
line above the 8N1, such that if the format does not match any known ones, at least
the options are set to something...

EDIT: Should mention, I edited this on the fly, so could be typos or the like.

1 Like

I modified the Serial.cpp file and added 7 bit, No Even and Odd parity, 1 or 2 stopbit.

Simple Serial TX code, and it compiles .
Checking the signals on my Keysight oscilloscope and we have 7 bit running with correct parity! !

Only tested at 9600 baud so far but I expect nothing odd here.

Fantastic!
Thanks for finding the Serial.cpp file.

This is at least the second time I've seen this solved. Someone should do a pull request and have it added to the official core.

I Will do some more tests today.
And you are right, then it should be added to the official Core.
I am using Arduino as a small hobby so not the best person to do a Pull request. Never done before.
However if no one else…….I Will give it a try end of this month.

2 Likes

Thanks for testing,
Do your tests include the 9-bits version?

Now I have tested most combinations for 7and 8 bit.
Several baud rates.
1 and 2 stop bits.
No, Even and Odd parity.
All OK !

Just added some lines in the ”Serial.cpp” file.

Also tried 6 bit with corresponding added lines.
This does not work !

For 9 bit I think much is done in another place. Search on vashallow

2 Likes

I just pushed it up as a Pull request:
SerialX.begin - support 7 bit modes. by KurtE · Pull Request #391 · arduino/ArduinoCore-renesas

I did not add anything for 9 bit support. As there is no Arduino standard for this.
That is, it there are no modes defined in their API HardwareSerial.h file that supports
9 bits.

I also did not add anything, that does anything with all of the modes that the board
does not support, like 5 bit or 6 bit, or Mark Parity.

Hopefully that gives this PR a higher probability of being merged.

3 Likes

Great, thank you !!!

So hopefully there will support for 7 and 8 bit Serial.

Forget about 5 and 6 bit on UNO R4.

For 9 bit I think there is a (more complex) Pull request already …. Not sure.
For me I will continue to use Teensy 3.6 and 4.0 where I need 9bit.

I hear you! My guess is that it is more of a long shot for Arduino to take in a PR
for the 9 bit code. That is I am not sure what they will think of the approach of passing in an array of bytes and assuming that the bytes in your array are in some specific order. (LSB or MSB...).

There are also issues, with API, as for example Serial1.write() only takes an 8 bit value...
Teensy We added another api:
size_t write9bit(uint32_t c);
Also, when the 9 bit support was turned on:
//#define SERIAL_9BIT_SUPPORT
Both the RX and TX queues were updated to hold 16 bit values (double the memory
usage).

Note: the API code is not setup to handle 16 bits. There are hacks around this, like take up two memory slots in the queue to hold the values. But then all sketches that process 9 bits would need to know to read two items... Or maybe the read method would need to know this, as well as the available and the peek methods...

Would mention the write and availableForWrite methods, but they are still not using
the queue that was defined within the object...

Stoffregan at Teensy wrote that 9 bit support is not in the standard core . You have to do a specified tweek and use a special api for TX of 9bit.
Double memory size and Legacy concern.

Once again Thank you for helping with this for UNO R4 !

I fixed my issue i had to go into the core and edit the serial part of the file to include SERIAL_7O2.

Worked perfectly... Seems the software just isn't there yet.

Part 2 of initial question..
Is it possible to set up the UNO R4 for Idle Low?

Something like….. Serial1.setInvertTX(1);