UART only works for 8N1; API exposes functions that mishandle UARTLCR #548

Closed
opened 2021-08-25 19:41:19 -05:00 by MustBeArt · 15 comments
MustBeArt commented 2021-08-25 19:41:19 -05:00 (Migrated from github.com)

The documented Hardware UART API exposes useful-sounding functions such as uart_set_baudrate() and uart_set_format() (and others) that write to the UARTLCR registers. This can only be done safely if the UART is not enabled, and then only if the UART is not currently busy transmitting or receiving a character, as documented in ARM's PrimeCell UART (PL011) Technical Reference Manual, in the section on the UARTLCR_H register. These functions make no attempt to ensure this is the case, and there is no warning in the API documentation.

In fact there is no safe way to call these functions through the API, because the API does not expose the UART enable separately, but only through uart_init() and uart_deinit(). The programmer can test the enable with uart_is_enabled(), but cannot control it. If the programmer tries to comply with the restriction on writing UARTLCR by first calling uart_deinit(), then calling (say) uart_set_format(), and finally calling uart_init(), their work is immediately undone by uart_init(). The uart_init() functions HARD CODES the format value to 8 bits, 1 stop bit, and no parity! The result is that any attempt to use word size, stop bits, or parity values other than 8, 1, and none is doomed to failure.

Changing baud rate on the fly (by just calling uart_set_baudrate()) does seem to work empirically, but it still violates the requirements set out in the PL011 manual, so there may be cases I didn't try where it fails.

Changing the stop bits, word width, or parity on the fly (by just calling uart_set_format()) seems to work sometimes and fail sometimes. My current project requires changing all those values quite frequently (to exercise another device's serial port implementation). Sometimes it transmits with the wrong parameters, and other times it fails to transmit at all after a parameter change.

I did not investigate whether other settings in UARTLCR work or not. FIFO enable, for instance, is in UARTLCR_H, and uart_init() has a hard-coded value for that one, too. However, uart_init() erroneously sets the FIFO enable bit AFTER enabling the UART, so it is always in violation of the rule from the PL011 manual. The API function for this, uart_set_fifo_enabled(), writes UARTLCR_H without any checks, just as uart_set_format() does.

It's great that the API presents a simplified model of the UART, hiding all these weird rules from the programmer. I'm not suggesting that more of the details be exposed. In fact, I'd remove the uart_is_enabled() function. I'm suggesting that the implementation of the API should do the necessary magic to make the simplified API work as expected, reliably. It should document any weird side effects caused by the magic (such as: the UART goes dead briefly to change parameters). The typical user should be able to get reliable performance out of the UART without worrying about these details.

The Linux kernel has a surprisingly complicated-looking driver for PL011 UARTs, written originally by ARM and updated by other ARM-licensed manufacturers. It might be valuable to go through that driver and see if there are other hard-learned tricks that need to be included in the Pico SDK's UART APIs.

The documented Hardware UART API exposes useful-sounding functions such as `uart_set_baudrate()` and `uart_set_format()` (and others) that write to the UARTLCR registers. This can only be done safely if the UART is not enabled, and then only if the UART is not currently busy transmitting or receiving a character, as documented in ARM's _PrimeCell UART (PL011) Technical Reference Manual_, in the section on the UARTLCR_H register. These functions make no attempt to ensure this is the case, and there is no warning in the API documentation. In fact there is no safe way to call these functions through the API, because the API does not expose the UART enable separately, but only through uart_init() and uart_deinit(). The programmer can test the enable with uart_is_enabled(), but cannot control it. If the programmer tries to comply with the restriction on writing UARTLCR by first calling uart_deinit(), then calling (say) uart_set_format(), and finally calling uart_init(), their work is immediately undone by uart_init(). **The uart_init() functions HARD CODES the format value to 8 bits, 1 stop bit, and no parity! The result is that any attempt to use word size, stop bits, or parity values other than 8, 1, and none is doomed to failure.** Changing baud rate on the fly (by just calling uart_set_baudrate()) does seem to work empirically, but it still violates the requirements set out in the PL011 manual, so there may be cases I didn't try where it fails. Changing the stop bits, word width, or parity on the fly (by just calling uart_set_format()) seems to work sometimes and fail sometimes. My current project requires changing all those values quite frequently (to exercise another device's serial port implementation). Sometimes it transmits with the wrong parameters, and other times it fails to transmit at all after a parameter change. I did not investigate whether other settings in UARTLCR work or not. FIFO enable, for instance, is in UARTLCR_H, and uart_init() has a hard-coded value for that one, too. However, uart_init() erroneously sets the FIFO enable bit AFTER enabling the UART, so it is always in violation of the rule from the PL011 manual. The API function for this, uart_set_fifo_enabled(), writes UARTLCR_H without any checks, just as uart_set_format() does. It's great that the API presents a simplified model of the UART, hiding all these weird rules from the programmer. I'm not suggesting that more of the details be exposed. In fact, I'd remove the `uart_is_enabled()` function. I'm suggesting that the implementation of the API should do the necessary magic to make the simplified API work as expected, reliably. It should document any weird side effects caused by the magic (such as: the UART goes dead briefly to change parameters). The typical user should be able to get reliable performance out of the UART without worrying about these details. The Linux kernel has a surprisingly complicated-looking driver for PL011 UARTs, written originally by ARM and updated by other ARM-licensed manufacturers. It might be valuable to go through that driver and see if there are other hard-learned tricks that need to be included in the Pico SDK's UART APIs.
daveythacher commented 2021-09-01 09:08:12 -05:00 (Migrated from github.com)

There is an issue in uart_init possibly which is related to this. It enables the module then attempts to enable the FIFO which is forbidden in PrimeCell UART manual. Loopback logic may not be supported by SDK. See this conversation for more information: https://www.raspberrypi.org/forums/viewtopic.php?f=144&t=318787

Recommend to changing this to Update SDK to implement PrimeCell UART. Also RP2040 datasheet lacks most of this, which is very strange.

There is an issue in uart_init possibly which is related to this. It enables the module then attempts to enable the FIFO which is forbidden in PrimeCell UART manual. Loopback logic may not be supported by SDK. See this conversation for more information: https://www.raspberrypi.org/forums/viewtopic.php?f=144&t=318787 Recommend to changing this to Update SDK to implement PrimeCell UART. Also RP2040 datasheet lacks most of this, which is very strange.
daveythacher commented 2021-09-01 11:01:38 -05:00 (Migrated from github.com)

Hardware_uart may need to be refactored. It looks like it currently only supports what is needed by CMake printf.

Hardware_uart may need to be refactored. It looks like it currently only supports what is needed by CMake printf.
kilograham commented 2021-09-01 11:20:51 -05:00 (Migrated from github.com)

what is "CMake printf"?!

what is "CMake printf"?!
daveythacher commented 2021-09-01 11:27:26 -05:00 (Migrated from github.com)

PICO_STDIO_UART, PICO_UART_DEFAULT_CRLF, PICO_DEFAULT_UART, PICO_DEFAULT_UART_BAUD_RATE, etc.
This
https://raspberrypi.github.io/pico-sdk-doxygen/group__pico__stdio.html
Looks like this:
https://raspberrypi.github.io/pico-sdk-doxygen/group__hardware__uart.html
Not like PL011

PICO_STDIO_UART, PICO_UART_DEFAULT_CRLF, PICO_DEFAULT_UART, PICO_DEFAULT_UART_BAUD_RATE, etc. This https://raspberrypi.github.io/pico-sdk-doxygen/group__pico__stdio.html Looks like this: https://raspberrypi.github.io/pico-sdk-doxygen/group__hardware__uart.html Not like PL011
Wren6991 commented 2021-09-06 04:06:22 -05:00 (Migrated from github.com)

that write to the UARTLCR registers. This can only be done safely if the UART is not enabled, and then only if the UART is not currently busy transmitting or receiving a character, as documented in ARM's PrimeCell UART (PL011) Technical Reference Manual, in the section on the UARTLCR_H register.

Thanks, this is definitely a bug. Hopefully we can keep the fixes cleanly contained on the implementation side.

> that write to the UARTLCR registers. This can only be done safely if the UART is not enabled, and then only if the UART is not currently busy transmitting or receiving a character, as documented in ARM's PrimeCell UART (PL011) Technical Reference Manual, in the section on the UARTLCR_H register. Thanks, this is definitely a bug. Hopefully we can keep the fixes cleanly contained on the implementation side.
Wren6991 commented 2021-09-08 04:57:59 -05:00 (Migrated from github.com)

There is a WIP pull request, currently only worth discussing, not running.

I'd like to preserve the current API. There is code added to enable/disable the UART around LCR updates, which may lead to loss of data, but this isn't such a big deal as different UART data formats are mutually unintelligible anyway.

Unfortunately the approach is a bit of a hack -- see comments at github.com/raspberrypi/pico-sdk@25b98942ce/src/rp2_common/hardware_uart/uart.c (L73-L92). The PL011 doesn't seem to have the necessary status bits for you to poll in order to wait for the current TX/RX characters to complete like it asks you to do. This code just adds a 15 baud period busy wait after disabling the UART, to make sure in-progress characters have finished.

I did have a look at the kernel driver but it's odd, doesn't seem to line up with the information in the reference manual. I have no idea where the 10-PCLK delay in pl011_set_termios comes from for example.

There is a WIP pull request, currently only worth discussing, not running. I'd like to preserve the current API. There is code added to enable/disable the UART around LCR updates, which may lead to loss of data, but this isn't such a big deal as different UART data formats are mutually unintelligible anyway. Unfortunately the approach is a bit of a hack -- see comments at https://github.com/raspberrypi/pico-sdk/blob/25b98942ce90e77862d101ee607d227d1c93ff9b/src/rp2_common/hardware_uart/uart.c#L73-L92. The PL011 doesn't seem to have the necessary status bits for you to poll in order to wait for the current TX/RX characters to complete like it asks you to do. This code just adds a 15 baud period busy wait after disabling the UART, to make sure in-progress characters have finished. I did have a look at the kernel driver but it's odd, doesn't seem to line up with the information in the reference manual. I have no idea where the 10-PCLK delay in `pl011_set_termios` comes from for example.
daveythacher commented 2021-09-08 07:50:37 -05:00 (Migrated from github.com)

I'd like to preserve the current API. There is code added to enable/disable the UART around LCR updates, which may lead to loss of data, but this isn't such a big deal as different UART data formats are mutually unintelligible anyway.

The PL011 doesn't seem to have the necessary status bits for you to poll in order to wait for the current TX/RX characters to complete like it asks you to do. This code just adds a 15 baud period busy wait after disabling the UART, to make sure in-progress characters have finished.

This is not true. This UART module is complete with busy and FIFO flags. You can block. Note you will need to block on DMA? There needs to be warnings in the documentation for hardware_uart.

Taking enable out of uart_init and creating uart_enable is possible. However you could also create structure for uart_init. This is kind of bad. However baud change will now block and call deinit update current struct then proceed with init. Structure will need to be preserved.

MIcrochip's PLIB HAL is known for creating an enable and init routine which allowed reconfiguration then locking it in with enable. That is another approach here. Init would do most of the initialization but a few other things were also possible. This will need to be documented. Avoiding this for this issue here is possible with existing API.

Edit: Continued here - https://github.com/raspberrypi/pico-sdk/pull/556#issuecomment-915238869

> I'd like to preserve the current API. There is code added to enable/disable the UART around LCR updates, which may lead to loss of data, but this isn't such a big deal as different UART data formats are mutually unintelligible anyway. >The PL011 doesn't seem to have the necessary status bits for you to poll in order to wait for the current TX/RX characters to complete like it asks you to do. This code just adds a 15 baud period busy wait after disabling the UART, to make sure in-progress characters have finished. This is not true. This UART module is complete with busy and FIFO flags. You can block. Note you will need to block on DMA? There needs to be warnings in the documentation for hardware_uart. Taking enable out of uart_init and creating uart_enable is possible. However you could also create structure for uart_init. This is kind of bad. However baud change will now block and call deinit update current struct then proceed with init. Structure will need to be preserved. MIcrochip's PLIB HAL is known for creating an enable and init routine which allowed reconfiguration then locking it in with enable. That is another approach here. Init would do most of the initialization but a few other things were also possible. This will need to be documented. Avoiding this for this issue here is possible with existing API. Edit: Continued here - https://github.com/raspberrypi/pico-sdk/pull/556#issuecomment-915238869
Wren6991 commented 2021-09-08 10:40:42 -05:00 (Migrated from github.com)

This is not true. This UART module is complete with busy and FIFO flags. You can block. Note you will need to block on DMA? There needs to be warnings in the documentation for hardware_uart.

There is a TX BUSY flag but no RX BUSY. Even if you poll for TX to completely drain, an RX can begin arbitrarily close to the point where you disable the UART, and you have no flag to precisely wait this out. You can't modify the LCR whilst that RX is still in progress. What am I missing?

> This is not true. This UART module is complete with busy and FIFO flags. You can block. Note you will need to block on DMA? There needs to be warnings in the documentation for hardware_uart. There is a TX BUSY flag but no RX BUSY. Even if you poll for TX to completely drain, an RX can begin arbitrarily close to the point where you disable the UART, and you have no flag to precisely wait this out. You can't modify the LCR whilst that RX is still in progress. What am I missing?
daveythacher commented 2021-09-08 12:14:07 -05:00 (Migrated from github.com)

This is not true. This UART module is complete with busy and FIFO flags. You can block. Note you will need to block on DMA? There needs to be warnings in the documentation for hardware_uart.

There is a TX BUSY flag but no RX BUSY. Even if you poll for TX to completely drain, an RX can begin arbitrarily close to the point where you disable the UART, and you have no flag to precisely wait this out. You can't modify the LCR whilst that RX is still in progress. What am I missing?

Application logic problem. UART is not like SPI and I2C in that it lacks state and is async like. The SDK does not have enough information but does provide a means to solve this. I would recommend ignoring this. It is a both a valid and invalid problem.

The solution of blocking for it to arrive is potentially valid. If the application need instant frequency change after last byte this could be justified. However I think you could also assume that it is forced to be idle at the time of the call. The issue with delay is potentially overhead. The issue with and without it is confusion.

> > This is not true. This UART module is complete with busy and FIFO flags. You can block. Note you will need to block on DMA? There needs to be warnings in the documentation for hardware_uart. > > There is a TX BUSY flag but no RX BUSY. Even if you poll for TX to completely drain, an RX can begin arbitrarily close to the point where you disable the UART, and you have no flag to precisely wait this out. You can't modify the LCR whilst that RX is still in progress. What am I missing? Application logic problem. UART is not like SPI and I2C in that it lacks state and is async like. The SDK does not have enough information but does provide a means to solve this. I would recommend ignoring this. It is a both a valid and invalid problem. The solution of blocking for it to arrive is potentially valid. If the application need instant frequency change after last byte this could be justified. However I think you could also assume that it is forced to be idle at the time of the call. The issue with delay is potentially overhead. The issue with and without it is confusion.
Wren6991 commented 2021-11-02 07:27:48 -05:00 (Migrated from github.com)

I spent some time reading the PL011 source to understand the actual reason for the requirement in the PL011 manual.

  • The CDC between PCLK and UCLK domain should be safe no matter when LCR/IBRD/FBRD are written
  • The baud divider counter always reloads when LCR is written, so this should always be safe, and the only symptom is a stretched baud period due to a potential partial count followed by reload.
  • The rest of the LCR (the 8 actual bits in UARTLCR_H) ignores updates if failing a (UCLK-synchronous) check that neither a TX nor RX character is in progress. Most LCR_H writes are dropped whilst the UART is active. The LCR is either written or not -- no funny in-between behaviour. This seems consistent with the problems people have seen in the wild.
  • The status flag for RX busy exists inside of the UART, but is not exposed through any status or debug signals.

I can't guess why Arm added that check -- maybe they were being defensive against the TX/RX state machines reaching bad states when the format changes part way.

So based on this, I think:

  • The baud rate can be safely changed at any time -- the wording in the TRM is too conservative here, and it is only the bits in LCR_H itself that are problematic, even though the LCR_H write is what triggers the BRD update in the UCLK domain
  • The above has one caveat which is that the first new free-running baud period may be stretched by (as long as) 1/16th of the old baud period, which may cause issues if the old baud period is long and the new is short
  • There are only two ways to safely change frame format etc once the UART has already entered the enabled state:
    • Reset the UART
    • Delay for one character period after disabling the UART (like in the draft PR)

The delay is ugly, so I am tempted to leave the baud rate change unpatched (as it should work fine based on reading the implementation, and empirically does work), add a new method to initialise the UART without enabling, and add a new requirement to the format change functions that they can only be called before the UART is enabled.

I can see why it's attractive to just reset the hardware with each configuration change. PL011 doesn't make this easy.

I spent some time reading the PL011 source to understand the actual reason for the requirement in the PL011 manual. - The CDC between PCLK and UCLK domain should be safe no matter when LCR/IBRD/FBRD are written - The baud divider counter always reloads when LCR is written, so this should always be safe, and the only symptom is a stretched baud period due to a potential partial count followed by reload. - The rest of the LCR (the 8 actual bits in UARTLCR_H) ignores updates if failing a (UCLK-synchronous) check that neither a TX nor RX character is in progress. Most LCR_H writes are dropped whilst the UART is active. The LCR is either written or not -- no funny in-between behaviour. This seems consistent with the problems people have seen in the wild. - The status flag for RX busy exists inside of the UART, but is not exposed through any status or debug signals. I can't guess why Arm added that check -- maybe they were being defensive against the TX/RX state machines reaching bad states when the format changes part way. So based on this, I think: - The baud rate can be safely changed at any time -- the wording in the TRM is too conservative here, and it is only the bits in LCR_H itself that are problematic, even though the LCR_H write is what triggers the BRD update in the UCLK domain - The above has one caveat which is that the first new free-running baud period may be stretched by (as long as) 1/16th of the old baud period, which may cause issues if the old baud period is long and the new is short - There are only two ways to safely change frame format etc once the UART has already entered the enabled state: - Reset the UART - Delay for one character period after disabling the UART (like in the draft PR) The delay is ugly, so I am tempted to leave the baud rate change unpatched (as it should work fine based on reading the implementation, and empirically does work), add a new method to initialise the UART without enabling, and add a new requirement to the format change functions that they can only be called before the UART is enabled. I can see why it's attractive to just reset the hardware with each configuration change. PL011 doesn't make this easy.
Wren6991 commented 2021-11-02 08:20:38 -05:00 (Migrated from github.com)

There is an issue in uart_init possibly which is related to this. It enables the module then attempts to enable the FIFO which is forbidden in PrimeCell UART manual. Loopback logic may not be supported by SDK. See this conversation for more information: https://www.raspberrypi.org/forums/viewtopic.php?f=144&t=318787

I had a closer look at this and it seems unrelated. They are getting a 0-pulse on the RX input because the GPIO is unconfigured, and at certain baud rates this appears as a 0-character prepended to their data.

> There is an issue in uart_init possibly which is related to this. It enables the module then attempts to enable the FIFO which is forbidden in PrimeCell UART manual. Loopback logic may not be supported by SDK. See this conversation for more information: https://www.raspberrypi.org/forums/viewtopic.php?f=144&t=318787 I had a closer look at this and it seems unrelated. They are getting a 0-pulse on the RX input because the GPIO is unconfigured, and at certain baud rates this appears as a 0-character prepended to their data.
rhulme commented 2021-11-08 06:29:17 -06:00 (Migrated from github.com)

I have a couple of additional observations from a simple test program and a logic analyser that may or may not be helpful. This is in the context of making changes whilst data is being sent:

  1. It appears that the baudate can be changed at any time and the current byte will continue to be sent with the old baudrate but the stop bit will have the width of the new baudrate.
  2. Calling uart_set_format immediately after uart_set_baudrate causes the new baudrate to be ignored (but the IBRD and FBRD registers will still indicate the new baudrate)
  3. The delay in the draft PR will not always work in the case of (2) because it assumes (not unreasonably) that the baudrate indicated by the IBRD and FBRD registers is accurate.

For completeness, here is the test program I used as a basis:

#include "pico/stdlib.h"

int main()
{
    gpio_set_function(0, GPIO_FUNC_UART);
    gpio_set_function(1, GPIO_FUNC_UART);

    uart_init(uart0, 9600);

    uart_putc_raw(uart0, '1');

    uart_set_baudrate(uart0, 115200);
    uart_set_format(uart0, 8, 1, UART_PARITY_NONE);

    while(true)
        uart_puts(uart0, "Test string\n");
}
I have a couple of additional observations from a simple test program and a logic analyser that may or may not be helpful. This is in the context of making changes whilst data is being sent: 1. It appears that the baudate _can_ be changed at any time and the current byte will continue to be sent with the old baudrate but the stop bit will have the width of the new baudrate. 2. Calling `uart_set_format` immediately after `uart_set_baudrate` causes the new baudrate to be ignored (but the IBRD and FBRD registers will still indicate the new baudrate) 3. The delay in the draft PR will not always work in the case of (2) because it assumes (not unreasonably) that the baudrate indicated by the IBRD and FBRD registers is accurate. For completeness, here is the test program I used as a basis: ``` #include "pico/stdlib.h" int main() { gpio_set_function(0, GPIO_FUNC_UART); gpio_set_function(1, GPIO_FUNC_UART); uart_init(uart0, 9600); uart_putc_raw(uart0, '1'); uart_set_baudrate(uart0, 115200); uart_set_format(uart0, 8, 1, UART_PARITY_NONE); while(true) uart_puts(uart0, "Test string\n"); } ```
RayNieport commented 2022-10-17 09:38:46 -05:00 (Migrated from github.com)

Is there any update on this? My project requires that I change UART parameters frequently as I am using a MUX to communicate with multiple different devices. Many of these devices are not 115200 + 8N1. I need to be able to change both baud rate (which appears to work with the caveats mentioned by @rhulme) as well as word size, parity, and stop bits.

For example, one protocol I will be using is SDI-12, where I will need 1200 baud, 7 bit words, Even parity, and 1 stop bit. Another is Modbus, which typically uses 8E1 frames.

None of these use cases seem to be currently supported by the hardware_uart API. I can try using the draft PR mentioned, but I would much prefer if this were "officially" fixed and released as part of the SDK. Seems the PR above has been sitting untouched for around a year. I can dig into using the hardware registers and attempting to write the functionality myself, but that seems a little silly given that this API already exists.

Edit: As a temporary workaround, I run the following after calling uart_init(uart1, Baud);:

uart_get_hw(uart1)->cr = 0;
uart_set_format(uart1, WordSize, StopBits, Parity);
uart_get_hw(uart1)->cr = UART_UARTCR_UARTEN_BITS | UART_UARTCR_TXE_BITS | UART_UARTCR_RXE_BITS;

This does not check if the UART is busy though, so still not a great solution.

Is there any update on this? My project requires that I change UART parameters frequently as I am using a MUX to communicate with multiple different devices. Many of these devices are not 115200 + 8N1. I need to be able to change both baud rate (which appears to work with the caveats mentioned by @rhulme) as well as word size, parity, and stop bits. For example, one protocol I will be using is [SDI-12](https://en.wikipedia.org/wiki/SDI-12), where I will need 1200 baud, 7 bit words, Even parity, and 1 stop bit. Another is [Modbus](https://en.wikipedia.org/wiki/Modbus), which typically uses 8E1 frames. None of these use cases seem to be currently supported by the hardware_uart API. I can try using the draft PR mentioned, but I would much prefer if this were "officially" fixed and released as part of the SDK. Seems the PR above has been sitting untouched for around a year. I can dig into using the hardware registers and attempting to write the functionality myself, but that seems a little silly given that this API already exists. Edit: As a temporary workaround, I run the following after calling `uart_init(uart1, Baud);`: ``` uart_get_hw(uart1)->cr = 0; uart_set_format(uart1, WordSize, StopBits, Parity); uart_get_hw(uart1)->cr = UART_UARTCR_UARTEN_BITS | UART_UARTCR_TXE_BITS | UART_UARTCR_RXE_BITS; ``` This does not check if the UART is busy though, so still not a great solution.
jorgen-vc commented 2023-03-08 07:39:20 -06:00 (Migrated from github.com)

MicroPython v1.19.1-879-g294098d28 on 2023-02-20; Raspberry Pi Pico with RP2040

Had perhaps the same problem in Python on Pico, also for modbus 8E1 Even Pairty
main.py

from machine import UART, Pin
uart0 = UART(0,baudrate=57600, bits=8, parity = 0, stop=1, rx=Pin(1),tx=Pin(0))
uart0.write("AAA")

When executing the code from "Thonny" it works
Receiving in my terminal, and this is correct.
01000001 01000001 01000001

When unplugging the USB port and reconnect so that it runs without thonny
Receiving this
01000001 01000001 11010000
Last byte is garbage..

This isue has been fixed 9 Mar 2023

https://github.com/micropython/micropython/issues/10976

Best regrads
Jørgen Johannessen

MicroPython v1.19.1-879-g294098d28 on 2023-02-20; Raspberry Pi Pico with RP2040 Had perhaps the same problem in Python on Pico, also for modbus 8E1 Even Pairty main.py from machine import UART, Pin uart0 = UART(0,baudrate=57600, bits=8, parity = 0, stop=1, rx=Pin(1),tx=Pin(0)) uart0.write("AAA") When executing the code from "Thonny" it works Receiving in my terminal, and this is correct. 01000001 01000001 01000001 When unplugging the USB port and reconnect so that it runs without thonny Receiving this 01000001 01000001 11010000 Last byte is garbage.. This isue has been fixed 9 Mar 2023 https://github.com/micropython/micropython/issues/10976 Best regrads Jørgen Johannessen
kilograham commented 2023-06-06 12:09:31 -05:00 (Migrated from github.com)

fix merged into develop

fix merged into develop
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-raspberrypi/pico-sdk#548
No description provided.