-
Notifications
You must be signed in to change notification settings - Fork 914
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Problems with pico-sdk UART transmission: blocking exits early, and (possibly PL011) 2nd stop bit missing #1274
Comments
I'm not a hardware engineer, so please take my comments with a grain of salt, but just in case it's helpful...
You've set the system-clock to 133MHz, which (currently) sets the peripheral clock to 48MHz, see #841
Perhaps the data has been written into the UART's TX FIFO buffer, and so from the CPU's point-of-view the "all the data has been transmitted to the UART block", even though the UART hasn't physically transmitted all the data from its TX FIFO over the physical wire yet? Looks like you could use the |
@sdbbs Thank you for your observations and data. There are several things here, I will deal with them in sequence.
This is actually correct, the API provided will block until all the data has been written into the UART. I can offer a mitigation for this. You can add the code I have bolded to busy wait on the UART "busy" bit.
I observe this delays until about halfway through the last character being transmitter on the wire. So now very close, I'm not sure we can do better from the UART. 2: (and other posts). You are entirely correct, your code does configure 2 stop bits but the UART is (still) sending one. I have tracked that down to the fact that the The first time it is called from A temporary mitigation: If you change the call in We will need to decide how we fix this is Pico-SDK, it looks like #556 and #548 you linked are all connected. For your last observation:
That is absolutely fine, the "non-exact" frequency is a result of the maths. Personally I like to see Baud rates within 1% but this link explains what about 2% is accurate enough (and will be even with 11 bit transmission, that is 1 + 8 + 2): https://community.silabs.com/s/article/uart-rs232-required-clock-accuracy?language=en_US Your Baudrate is 99.9791% of expected so is actually very, very close. HTH. |
…s UART still busy sending (raspberrypi#1274)
… UART still busy sending (raspberrypi#1274)
Waiting for this #1709 |
Hi all,
I have prepared a small pico-sdk project,
rp2040_uart_err_test
, an RP2040 UART TX test, in this gist: rp2040_uart_err_testI believe that it demonstrates the following two problems:
uart_write_blocking
does block, but returns early: when it returns, two bytes (in this test) still remain to be sentThe documentation for
uart_write_blocking
explicitly says:... so I would expect either this function to indeed block until all data has been transmitted - or the help text needs to be more precise about what should be expected, otherwise it is misleading as it is.
The documentation for
uart_set_format
explicitly says:... so I would expect that two stop bits are sent, if I have configured the UART for two stop bits.
Few words about the UART TX test project,
rp2040_uart_err_test
:pico_stdlib
and builds only againstpico_runtime
; alsostdio_usb
andstdio_uart
are disabledon_uart_rx_isr
, but it is there simply to go through the setup motions - it is otherwise not expected to fire or do anything in this testSo, the main functionality is in the
main
function:tx_buffer
with some random binary contentmain
goes into the infinitewhile
loop, where:uart_write_blocking
with the intent to send/TX all 24 bytes oftx_buffer
(via reference variables), and sets debug pin LOWThis would allow for the debug pin indicating the duration of
uart_write_blocking
. Here is thewhile
loop:I have tried to use
volatile
variables to hint to the compiler not to reorder statements; looking at the output ofarm-none-eabi-objdump -S rp2040_uart_err_test.elf
that is not obvious at first, because there are branching jumps - but I've tried to follow the jumps, and it does seem the statements are in order.Finally, as output of the test program, I am capturing the debug pin and the UART TX pin with Saleae Logic.
Let's look at the stop bit problem first. First, let's recall, that for a 115200 baud traffic, the bit period is 1/115200 ≈ 8.68 μs
The
rp2040_uart_err_test
code as submitted, sets up the UART (via#define
s) for 115200 baud, 8N2 traffic. However, at first I tested with a 8N1 build, which worked great:Note that I've activated the Async Serial decoder from Saleae Logic on the channel with the digital capture of the UART TX signal, and it decodes the right bytes; also, the duration of a byte in this case is measured at 87.68 μs - quite close to 10 bits (start + 8 data + stop) times the bit period 8.68 μs.
So, then I just change the
STOP_BITS
define to 2, rebuild, capture again, try to capture with Saleae Logic again - and set up the Async Serial decoder accordingly, with stop bits to 2:... and I can see the Async Serial decoder report framing errors; but if I change back the settings of the Async Serial decoder to 8N1, it again decodes no errors:
Here we can see that even if I had specified 8N2, a byte with a duration 87.2 μs has been sent, quite close to the previous duration 87.68 μs - whereas 8N2 would require 1+8+1+1 = 11 bits, times expected duration 8.68 μs, that is around 95.48 μs for the full duration.
Conclusion: second stop bit had not been sent, even if I specified 8N2.
To be frank, I don't think this is pico-sdk problem; the PrimeCell® UART (PL011) Technical Reference Manual mentions:
... and uart_set_format in uart.h does indeed set those bits; and I even have a function
get_uart_lcr_h
in my code, so I can confirm ingdb
(also note thatactual_baud_rate
is 115176, slightly less than requested 115200):... and it's clear that at runtime, the
STP2
(3rd) bit ofUART_LCR_H
register is indeed enabled - and yet, I've obtained the scope traces seen above, where there is no second stop bit.And for the first problem: let's look at debug pin (which indicates the duration of
uart_write_blocking
) versus entire UART TX packet -- where for ease of perception, Async Serial decoder is set up for 8N1:It is visible that right after the debug pin goes low (where supposedly
uart_write_blocking
stopped blocking and returned), another two bytes are being sent on wire.Are there any solutions or workarounds for these issues?
EDIT: also related: UART only works for 8N1; API exposes functions that mishandle UARTLCR · Issue #548 · raspberrypi/pico-sdk
The text was updated successfully, but these errors were encountered: