tkl_uart | UART Driver
Overviewโ
UART (Universal Asynchronous Receiver/Transmitter) is a serial bus for asynchronous communication. It is bidirectional and supports full-duplex transmit and receive.
This driver covers the full UART lifecycle: initialize a port, write and read data, register receive and transmit interrupt callbacks, control the transmit interrupt and receive flow control, wait for incoming data, and issue control commands.
Every function takes a port_id of type TUYA_UART_NUM_E:
typedef enum {
TUYA_UART_NUM_0, // UART 0
TUYA_UART_NUM_1, // UART 1
TUYA_UART_NUM_2, // UART 2
TUYA_UART_NUM_3, // UART 3
TUYA_UART_NUM_4, // UART 4
TUYA_UART_NUM_5, // UART 5
TUYA_UART_NUM_MAX,
} TUYA_UART_NUM_E;
On Linux, the high 16 bits of port_id also encode a TUYA_UART_TYPE_E (one of TUYA_UART_SYS, TUYA_UART_USB, TUYA_UART_SDIO, TUYA_UART_WCH) and the low 16 bits encode the port number. Build such a value with the TUYA_UART_PORT_ID(port_type, port_num) macro, for example TUYA_UART_PORT_ID(TUYA_UART_SYS, 2).
tkl_uart_initโ
OPERATE_RET tkl_uart_init(TUYA_UART_NUM_E port_id, TUYA_UART_BASE_CFG_T *cfg);
Initializes a UART port from the base configuration and returns the result.
Parameters:
-
port_id: Port number. -
cfg: Base configuration โ baud rate, parity, data bits, stop bits, and flow control.typedef struct {uint32_t baudrate;TUYA_UART_PARITY_TYPE_E parity;TUYA_UART_DATA_LEN_E databits;TUYA_UART_STOP_LEN_E stopbits;TUYA_UART_FLOWCTRL_TYPE_E flowctrl;} TUYA_UART_BASE_CFG_T;TUYA_UART_PARITY_TYPE_E:Name Value Description TUYA_UART_PARITY_TYPE_NONE0No parity TUYA_UART_PARITY_TYPE_ODD1Odd parity TUYA_UART_PARITY_TYPE_EVEN2Even parity TUYA_UART_DATA_LEN_E:Name Value Description TUYA_UART_DATA_LEN_5BIT0x055-bit data length TUYA_UART_DATA_LEN_6BIT0x066-bit data length TUYA_UART_DATA_LEN_7BIT0x077-bit data length TUYA_UART_DATA_LEN_8BIT0x088-bit data length TUYA_UART_STOP_LEN_E:Name Value Description TUYA_UART_STOP_LEN_1BIT0x011 stop bit TUYA_UART_STOP_LEN_1_5BIT10x021.5 stop bits TUYA_UART_STOP_LEN_2BIT0x032 stop bits TUYA_UART_FLOWCTRL_TYPE_E:Name Value Description TUYA_UART_FLOWCTRL_NONE0No flow control TUYA_UART_FLOWCTRL_RTSCTS1RTS/CTS hardware flow control TUYA_UART_FLOWCTRL_XONXOFF2XON/XOFF software flow control TUYA_UART_FLOWCTRL_DTRDSR3DTR/DSR hardware flow control
Returns:
OPRT_OKon success. For other values, seetuya_error_code.h.
tkl_uart_deinitโ
OPERATE_RET tkl_uart_deinit(TUYA_UART_NUM_E port_id);
Deinitializes a UART port. This stops the UART, ends any transfer in progress, and releases the related software and hardware resources.
Parameters:
port_id: Port number.
Returns:
OPRT_OKon success. For other values, seetuya_error_code.h.
tkl_uart_writeโ
int tkl_uart_write(TUYA_UART_NUM_E port_id, void *buff, uint16_t len);
Writes data to a UART port.
Parameters:
port_id: Port number.buff: Data buffer to send.len: Length of the data to send.
Returns:
- The number of bytes written (
> 0), or a value less than or equal to0on error.
tkl_uart_rx_irq_cb_regโ
void tkl_uart_rx_irq_cb_reg(TUYA_UART_NUM_E port_id, TUYA_UART_IRQ_CB rx_cb);
Enables the UART receive interrupt and registers its callback.
Parameters:
-
port_id: Port number. -
rx_cb: Receive interrupt callback.TUYA_UART_IRQ_CBis defined as:typedef void (*TUYA_UART_IRQ_CB)(TUYA_UART_NUM_E port_id);where
port_idis the port that raised the interrupt.
Returns:
- None.
tkl_uart_tx_irq_cb_regโ
void tkl_uart_tx_irq_cb_reg(TUYA_UART_NUM_E port_id, TUYA_UART_IRQ_CB tx_cb);
Registers the UART transmit interrupt callback. Registering it means data is sent asynchronously through the interrupt: call tkl_uart_write to start an asynchronous transfer.
Parameters:
-
port_id: Port number. -
tx_cb: Transmit interrupt callback.TUYA_UART_IRQ_CBis defined as:typedef void (*TUYA_UART_IRQ_CB)(TUYA_UART_NUM_E port_id);where
port_idis the port that raised the interrupt.
Returns:
- None.
tkl_uart_readโ
int tkl_uart_read(TUYA_UART_NUM_E port_id, void *buff, uint16_t len);
Reads data from a UART port.
Parameters:
port_id: Port number.buff: Receive buffer.len: Length of the data to read.
Returns:
- The number of bytes read (
>= 0), or a value less than0on error.
tkl_uart_set_tx_intโ
OPERATE_RET tkl_uart_set_tx_int(TUYA_UART_NUM_E port_id, BOOL_T enable);
Enables or disables the UART transmit interrupt.
Parameters:
port_id: Port number.enable:TRUEto enable the transmit interrupt,FALSEto disable it.
Returns:
OPRT_OKon success. For other values, seetuya_error_code.h.
tkl_uart_set_rx_flowctrlโ
OPERATE_RET tkl_uart_set_rx_flowctrl(TUYA_UART_NUM_E port_id, BOOL_T enable);
Enables or disables UART receive flow control.
Parameters:
port_id: Port number.enable:TRUEto enable receive flow control,FALSEto disable it.
Returns:
OPRT_OKon success. For other values, seetuya_error_code.h.
tkl_uart_wait_for_dataโ
OPERATE_RET tkl_uart_wait_for_data(TUYA_UART_NUM_E port_id, int timeout_ms);
Waits for received data to become available.
Parameters:
port_id: Port number.timeout_ms: Maximum wait time in milliseconds.-1blocks indefinitely,0does not block, and a value greater than0is the timeout.
Returns:
OPRT_OKon success. For other values, seetuya_error_code.h.
tkl_uart_ioctlโ
OPERATE_RET tkl_uart_ioctl(TUYA_UART_NUM_E port_id, uint32_t cmd, void *arg);
Issues a control command to a UART port.
Parameters:
-
port_id: Port number. -
cmd: Control command.TUYA_UART_IOCTL_CMD_E:Name Value Description TUYA_UART_SUSPEND_CMD0Suspend the UART TUYA_UART_RESUME_CMD1Resume the UART TUYA_UART_FLUSH_CMD2Flush the UART buffer TUYA_UART_RECONFIG_CMD3Reconfigure the UART TUYA_UART_USER_CMD4User-defined command TUYA_UART_MAX_CMD1000Command boundary -
arg: Argument for the control command.
Returns:
OPRT_OKon success. For other values, seetuya_error_code.h.
Examplesโ
Polled loopbackโ
int uart_loopback_test(void)
{
uint32_t port_id;
TUYA_UART_BASE_CFG_T cfg;
OPERATE_RET ret = OPRT_OK;
const int bufsize = 8;
unsigned char tx[bufsize], rx[bufsize];
int bytes;
int i;
// start
port_id = TUYA_UART_NUM_0;
cfg.baudrate = 115200;
cfg.databits = TUYA_UART_DATA_LEN_8BIT;
cfg.parity = TUYA_UART_PARITY_TYPE_NONE;
cfg.stopbits = TUYA_UART_STOP_LEN_1BIT;
cfg.flowctrl = TUYA_UART_FLOWCTRL_NONE;
ret = tkl_uart_init(port_id, &cfg);
for (i = 0; i < bufsize; i++) {
tx[i] = 'A' + i;
}
// loop 3 times
for (i = 0; i < 3; i++) {
bzero(rx, sizeof(rx));
bytes = tkl_uart_write(port_id, tx, sizeof(tx));
if (bytes <= 0) {
// fail
ret = OPRT_COM_ERROR;
} else {
// wait at most 5 seconds until the data is ready
ret = tkl_uart_wait_for_data(port_id, 5000);
if (ret == OPRT_TIMEOUT) {
// timeout
tkl_uart_deinit(port_id);
return OPRT_COM_ERROR;
}
bytes = tkl_uart_read(port_id, rx, sizeof(rx));
if (bytes < 0) {
// fail
ret = OPRT_COM_ERROR;
} else {
if (memcmp(tx, rx, bufsize) != 0) {
// data is not identical
ret = OPRT_COM_ERROR;
} else {
ret = OPRT_OK;
}
}
}
if (ret != OPRT_OK) {
// fail
} else {
// ok
}
}
// deinit
tkl_uart_deinit(port_id);
return ret;
}
Interrupt-driven loopbackโ
static int sg_rx_flag = 0;
static int sg_tx_flag = 0;
static void tuya_rx_cb(TUYA_UART_NUM_E port_id)
{
// mutex lock
sg_rx_flag = 1;
// mutex unlock
}
static void tuya_tx_cb(TUYA_UART_NUM_E port_id)
{
// mutex lock
sg_tx_flag = 1;
// mutex unlock
}
int uart_loopback_test(void)
{
uint32_t port_id;
TUYA_UART_BASE_CFG_T cfg;
OPERATE_RET ret = OPRT_OK;
const int bufsize = 8;
unsigned char tx[bufsize], rx[bufsize];
int bytes;
static int sl_first_time = 1;
int i;
// start
sg_rx_flag = 0;
sg_tx_flag = 0;
port_id = TUYA_UART_NUM_0;
cfg.baudrate = 115200;
cfg.databits = TUYA_UART_DATA_LEN_8BIT;
cfg.parity = TUYA_UART_PARITY_TYPE_NONE;
cfg.stopbits = TUYA_UART_STOP_LEN_1BIT;
cfg.flowctrl = TUYA_UART_FLOWCTRL_NONE;
ret = tkl_uart_init(port_id, &cfg);
if (tkl_uart_set_tx_int(port_id, 1) < 0) {
// fail
tkl_uart_deinit(port_id);
return OPRT_COM_ERROR;
}
for (i = 0; i < bufsize; i++) {
tx[i] = 'A' + i;
}
// loop 3 times
for (i = 0; i < 3; i++) {
bzero(rx, sizeof(rx));
if (sl_first_time || sg_tx_flag) {
bytes = tkl_uart_write(port_id, tx, sizeof(tx));
} else {
continue;
}
if (bytes <= 0) {
// fail
ret = OPRT_COM_ERROR;
} else {
// wait at most 5 seconds until the data is ready
ret = tkl_uart_wait_for_data(port_id, 5000);
if (sg_rx_flag) {
bytes = tkl_uart_read(port_id, rx, sizeof(rx));
if (bytes < 0) {
// fail
ret = OPRT_COM_ERROR;
} else {
if (memcmp(tx, rx, bufsize) != 0) {
// data is not identical
ret = OPRT_COM_ERROR;
} else {
ret = OPRT_OK;
}
}
sg_rx_flag = 0;
}
}
if (ret != OPRT_OK) {
// fail
} else {
// ok
}
}
// disable int
tkl_uart_set_tx_int(port_id, 0);
// deinit
tkl_uart_deinit(port_id);
return ret;
}