uart_periodic_tx Module API Manual#
Overview#
uart_periodic_tx is an optional native module that uses a hardware timer to periodically send already-prepared complete UART frames. The timer callback only executes native UART write operations, does not execute Python code, and does not allocate GC memory in the callback.
It is suitable for scenarios that require stable periodic transmission of fixed-length or limited-length data frames, such as sending a status frame every 50 ms. The application calls update() in the normal Python context to prepare the next frame; the module copies the data and sends it when the subsequent timer fires.
Note
This module is a UART periodic transmitter, not a general-purpose hardware timer task framework. It cannot schedule arbitrary Python functions in the timer, nor can it be used directly for network, SPI, or I2C transmissions.
Enabling the Module#
This feature is disabled by default. Before compiling the firmware, execute the configuration command corresponding to the build environment in the source root directory:
# When using k230-builder
k230 make menuconfig
# When compiling directly on the host
make menuconfig
Enable the following option and recompile the firmware:
CanMV Micropython Components Configurations
Enable UART periodic TX module
Importing the module in firmware where this option is not enabled will raise ImportError.
Importing the Module#
from machine import FPIOA, UART
from uart_periodic_tx import UARTPeriodicTx
Quick Start#
The following example maps UART3’s TX to IO50 and sends a frame every 50 ms. Select a UART and pins that are not occupied by REPL or other system functions according to the development board and board-level configuration.
from machine import FPIOA, UART
from uart_periodic_tx import UARTPeriodicTx
import time
fpioa = FPIOA()
fpioa.set_function(50, FPIOA.UART3_TXD)
tx = UARTPeriodicTx(
UART.UART3,
0,
50,
max_len=64,
baudrate=115200,
bits=UART.EIGHTBITS,
parity=UART.PARITY_NONE,
stop=UART.STOPBITS_ONE,
repeat_last=True,
)
try:
tx.update(b"\xA5\x5A\x00\xFF\x3C\xC3\xFF\x0D")
tx.start()
time.sleep_ms(1000)
tx.update(b"\xA5\x5A\x01\xFE\x3C\xC3\xFF\x0D")
time.sleep_ms(1000)
finally:
tx.deinit()
The FPIOA UART TX pin mapping must be completed before calling start(). update() copies the passed-in buffer, so modifying the original bytearray after the call returns will not modify the already-published frame.
UARTPeriodicTx Class#
Constructor#
UARTPeriodicTx(
uart_id,
timer_id,
period=50,
*,
max_len=64,
baudrate=115200,
bits=UART.EIGHTBITS,
parity=UART.PARITY_NONE,
stop=UART.STOPBITS_ONE,
repeat_last=True,
)
Creates a periodic transmitter. The constructor allocates three sets of transmit buffers, but does not occupy UART or hardware timer resources before start() is called.
Parameter |
Description |
|---|---|
|
UART hardware number, e.g., |
|
Hardware timer number. Software timer number |
|
Transmission period in ms, default |
|
Maximum length of a single frame, default |
|
UART baudrate, default |
|
Data bits, using the same constants as |
|
Parity mode, e.g., |
|
Stop bits, e.g., |
|
Whether to repeat sending the last frame when there is no new |
period can be passed as the third positional argument; the remaining UART configuration parameters must be passed as keyword arguments.
update Method#
tx.update(data)
Copies and publishes a complete frame of data for the hardware timer to send when it fires subsequently.
Parameters
data: Data supporting the buffer protocol, e.g.,bytes,bytearray, ormemoryview. Length cannot exceedmax_len.
Exceptions
ValueError: The object has been deinitialized, or the data length exceedsmax_len.OSError(EBUSY): All three buffer sets are temporarily unwritable. Retry later in the normal Python context; do not call this method in amachine.Timercallback.
update() does not wait for the current frame to finish sending, nor does it guarantee that the new frame will appear exactly at the next hardware trigger. If the timer callback has already taken the current buffer, the new frame will take effect on subsequent triggers. When repeat_last=True, the timer continuously sends the most recently successfully published complete frame; when repeat_last=False, after the frame is completely written once, it waits for the next update().
start Method#
tx.start()
Acquires the hardware timer and UART, and starts periodic transmission. At least one successful update() call should be made before calling this; otherwise, timer triggers will be counted as skipped transmissions.
The same timer_id cannot be used by machine.Timer or another UARTPeriodicTx simultaneously. Resource conflicts will raise OSError(EBUSY).
stop Method#
tx.stop()
Stops periodic transmission and releases the runtime resources of the hardware timer and UART, but retains the object and the already-allocated transmit buffers. start() can be called again afterwards.
deinit Method#
tx.deinit()
Stops transmission and releases all native resources and buffers. The object cannot be used after calling this. It is recommended to call this in try / finally to ensure hardware timer release on exception paths.
active Method#
tx.active()
Returns a boolean indicating whether the hardware timer is running.
stats Method#
sent, short_write, errors, skipped = tx.stats()
Returns the cumulative statistics tuple:
Return Value |
Description |
|---|---|
|
Number of times the UART write returned the complete frame length. |
|
Number of times the UART wrote a partial frame. |
|
Number of times the UART write returned an error. |
|
Number of timer triggers that did not send, e.g., the UART is being written by another periodic transmitter, no transmittable frame has been published yet, or there is no new data when |
Statistics accumulate over the object’s lifetime; stop() and subsequent start() do not clear them.
Resources and Timing Constraints#
UARTPeriodicTxholds the native UART driver used for transmission. During operation, do not send on the same UART viamachine.UART.write(), nor reconfigure or release the same UART.Multiple
UARTPeriodicTxinstances can use the same UART, but the UART configuration must be exactly identical. When two transmission moments overlap, one of the triggers will be skipped and counted asskipped. When predictable timing is required, only one periodic transmitter should be created for a UART.Timer triggers are driven by a hardware timer, avoiding the transmission trigger latency caused by the Python VM, GC, and Python callbacks; the actual time to complete a frame on the wire is still affected by baud rate, frame length, and the UART driver state.
The serial transmission time of a frame should be significantly smaller than
period. If the frame is too long, the baud rate is too low, or the UART is busy,short_write,errors, orskippedmay occur.When
repeat_last=True, the logic analyzer will see the most recently successfullyupdate()’d frame being transmitted continuously. Whenrepeat_last=False, each successfulupdate()produces at most one complete frame transmission; triggers without new data will be counted asskipped.
For a complete loopback verification example, see UARTPeriodicTx Hardware Periodic Transmission.
