Note

This is the documentation for the latest development branch and may refer to features that are not available in released versions. If you are looking for the documentation for a specific release, use the drop-down menu on the left and select the desired version.

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_id

UART hardware number, e.g., UART.UART3. A number is passed in rather than a machine.UART object. The UART must be available and the TX pin must be properly muxed.

timer_id

Hardware timer number. Software timer number -1 cannot be used. The current K230 timer numbers are 0 to 5.

period

Transmission period in ms, default 50, minimum value is 1.

max_len

Maximum length of a single frame, default 64, range is 1 to 4096 bytes. The module allocates three sets of buffers for this capacity.

baudrate

UART baudrate, default 115200.

bits

Data bits, using the same constants as machine.UART, e.g., UART.EIGHTBITS. Supports 5 to 9 bits.

parity

Parity mode, e.g., UART.PARITY_NONE, UART.PARITY_ODD, or UART.PARITY_EVEN.

stop

Stop bits, e.g., UART.STOPBITS_ONE or UART.STOPBITS_TWO.

repeat_last

Whether to repeat sending the last frame when there is no new update(), default True. When set to False, each non-empty frame successfully update()d is only sent once after being completely written to the UART; subsequent timer triggers are skipped until a new update() occurs.

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, or memoryview. Length cannot exceed max_len.

Exceptions

  • ValueError: The object has been deinitialized, or the data length exceeds max_len.

  • OSError(EBUSY): All three buffer sets are temporarily unwritable. Retry later in the normal Python context; do not call this method in a machine.Timer callback.

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

sent

Number of times the UART write returned the complete frame length.

short_write

Number of times the UART wrote a partial frame.

errors

Number of times the UART write returned an error.

skipped

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 repeat_last=False.

Statistics accumulate over the object’s lifetime; stop() and subsequent start() do not clear them.

Resources and Timing Constraints#

  • UARTPeriodicTx holds the native UART driver used for transmission. During operation, do not send on the same UART via machine.UART.write(), nor reconfigure or release the same UART.

  • Multiple UARTPeriodicTx instances 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 as skipped. 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, or skipped may occur.

  • When repeat_last=True, the logic analyzer will see the most recently successfully update()’d frame being transmitted continuously. When repeat_last=False, each successful update() produces at most one complete frame transmission; triggers without new data will be counted as skipped.

For a complete loopback verification example, see UARTPeriodicTx Hardware Periodic Transmission.

Comments list
Comments
Log in