fix mb & tty

This commit is contained in:
wmano
2025-09-13 23:08:11 +08:00
parent ffe1456b3a
commit 349741d9e1
33 changed files with 1745 additions and 4418 deletions
+516 -126
View File
@@ -1,169 +1,559 @@
#include <string.h>
#include <rtthread.h>
#include <rtdevice.h>
#include <rthw.h>
#include "chrg_tty.h"
#include <chrg_tty.h>
#include "chrg_north.h"
#include "chrg_south.h"
#define LOG_TAG "chrg.tty"
#define DBG_LEVEL DBG_LOG
#define DBG_TAG "chrg.tty"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
struct chrg_tty_t chrgtty[TOTAL_TTY] = {
[IDX_TTY_LCD] = {
.dev = RT_NULL,
.name = DEV_NAME_LCD,
.index = IDX_TTY_LCD,
.baudrate = BAUD_RATE_115200,
.rb = RT_NULL,
},
[IDX_TTY_NORTH] = {
.dev = RT_NULL,
.name = DEV_NAME_NORTH,
.index = IDX_TTY_NORTH,
.baudrate = BAUD_RATE_2000000,
.rb = RT_NULL,
},
[IDX_TTY_SOUTH] = {
.dev = RT_NULL,
.name = DEV_NAME_SOUTH,
.index = IDX_TTY_SOUTH,
.baudrate = BAUD_RATE_2000000,
.rb = RT_NULL,
}
};
static rt_err_t chrg_lcd_tty_input (rt_device_t dev, rt_size_t size)
#ifdef TTY_USING_DMA_TX
static rt_err_t chrg_tty_send_comp_hook (rt_device_t dev, void *buffer)
{
rt_err_t ret;
struct chrg_tty_t *pTTY = &chrgtty[IDX_TTY_LCD];
struct mq_msg_t msg;
struct chrg_tty_t *pTTY = (struct chrg_tty_t *)(dev->user_data);
rt_completion_done(&pTTY->tx_comp);
if ((RT_NULL != dev) && (RT_NULL != pTTY->mq) && (size > 0)) {
msg.dev = dev;
msg.size = size;
ret = rt_mq_send(pTTY->mq, &msg, sizeof(struct mq_msg_t));
if (RT_EOK != ret) {
LOG_E("send mq '%s' failed.", pTTY->name);
}
}
return (RT_EOK);
}
#endif
return ret;
static rt_err_t chrg_tty_recv_ind_hook (rt_device_t dev, rt_size_t size)
{
struct chrg_tty_t *pTTY = (struct chrg_tty_t *)(dev->user_data);
if (pTTY->evt) {
rt_event_send(pTTY->evt, TTY_EVT_RX_IND);
}
return (RT_EOK);
}
static rt_err_t chrg_north_tty_input (rt_device_t dev, rt_size_t size)
static int chrg_tty_cal_byte_tmo (int baudrate)
{
rt_err_t ret;
struct chrg_tty_t *pTTY = &chrgtty[IDX_TTY_NORTH];
struct mq_msg_t msg;
int tmo = (40 * 1000) / baudrate;
if ((RT_NULL != dev) && (RT_NULL != pTTY->mq) && (size > 0)) {
msg.dev = dev;
msg.size = size;
ret = rt_mq_send(pTTY->mq, &msg, sizeof(struct mq_msg_t));
if (RT_EOK != ret) {
LOG_E("send mq '%s' failed.", pTTY->name);
}
}
if (tmo < TTY_BYTE_TMO_MIN) {
tmo = TTY_BYTE_TMO_MIN;
} else if (tmo > TTY_BYTE_TMO_MAX) {
tmo = TTY_BYTE_TMO_MAX;
}
return ret;
return (tmo);
}
static rt_err_t chrg_south_tty_input (rt_device_t dev, rt_size_t size)
// mode : 0--receive mode, 1--send mode
static void chrg_tty_mode_set (struct chrg_tty_t *pTTY, int mode)
{
rt_err_t ret;
struct chrg_tty_t *pTTY = &chrgtty[IDX_TTY_SOUTH];
struct mq_msg_t msg;
if (pTTY->pin < 0) {
return;
}
if ((RT_NULL != dev) && (RT_NULL != pTTY->mq) && (size > 0)) {
msg.dev = dev;
msg.size = size;
ret = rt_mq_send(pTTY->mq, &msg, sizeof(struct mq_msg_t));
if (RT_EOK != ret) {
LOG_E("send mq '%s' failed.", pTTY->name);
}
}
if (mode) {
rt_pin_write(pTTY->pin, pTTY->level);
#if (TTY_SW_DLY_US > 0)
rt_hw_us_delay(TTY_SW_DLY_US);
#endif
} else {
return ret;
#ifdef TTY_USING_DMA_TX
rt_completion_wait(&pTTY->tx_comp, TTY_TX_COMP_TMO_MAX);
rt_thread_mdelay(pTTY->tx_dly_ms); // 等待末尾数据传输完成
#elif (TTY_SW_DLY_US > 0)
rt_hw_us_delay(TTY_SW_DLY_US);
#endif
rt_pin_write(pTTY->pin, !pTTY->level);
}
}
rt_err_t chrg_tty_open (struct chrg_tty_t *pTTY)
static int chrg_tty_dev_open (struct chrg_tty_t *pTTY)
{
rt_err_t ret = RT_EOK;
if (RT_NULL == pTTY) {
return RT_EEMPTY;
}
#ifdef TTY_USING_DMA_RX
struct serial_configure cfg = {
.baud_rate = pTTY->baudrate,
.data_bits = DATA_BITS_8,
.stop_bits = STOP_BITS_1,
.parity = PARITY_NONE,
.bit_order = BIT_ORDER_LSB,
.invert = NRZ_NORMAL,
.bufsz = RT_SERIAL_RB_BUFSZ,
.flowcontrol = RT_SERIAL_FLOWCONTROL_NONE,
};
#ifdef TTY_USING_DMA_TX
ret = rt_device_open(pTTY->dev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_DMA_RX | RT_DEVICE_FLAG_DMA_TX);
if (RT_EOK == ret) {
return (RT_EOK);
}
#endif
pTTY->dev = rt_device_find(pTTY->name);
if (RT_NULL == pTTY->dev) {
LOG_E("dev '%s' not found.", pTTY->name);
return RT_ERROR;
}
#ifdef TTY_USING_INT_TX
ret = rt_device_open(pTTY->dev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_DMA_RX | RT_DEVICE_FLAG_INT_TX);
if (RT_EOK == ret) {
return (RT_EOK);
}
#endif
ret = rt_device_open(pTTY->dev, RT_DEVICE_OFLAG_RDWR|RT_DEVICE_FLAG_INT_RX);
if (ret != RT_EOK) {
LOG_E("open '%s' failed.", pTTY->name);
return ret;
}
ret = rt_device_open(pTTY->dev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_DMA_RX);
if (RT_EOK == ret) {
return (RT_EOK);
}
ret = rt_device_control(pTTY->dev, RT_DEVICE_CTRL_CONFIG, &cfg);
if (ret != RT_EOK) {
LOG_E("control '%s' failed.", pTTY->name);
return ret;
}
#endif
switch (pTTY->index) {
case IDX_TTY_LCD:
rt_device_set_rx_indicate(pTTY->dev, chrg_lcd_tty_input);
break;
case IDX_TTY_NORTH:
rt_device_set_rx_indicate(pTTY->dev, chrg_north_tty_input);
break;
case IDX_TTY_SOUTH:
rt_device_set_rx_indicate(pTTY->dev, chrg_south_tty_input);
break;
default:
return RT_ERROR;
}
#ifdef TTY_USING_DMA_TX
ret = rt_device_open(pTTY->dev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_DMA_TX);
if (RT_EOK == ret) {
return (RT_EOK);
}
#endif
pTTY->mq = rt_mq_create(pTTY->name, sizeof(struct mq_msg_t), 16, RT_IPC_FLAG_FIFO);
if (RT_NULL == pTTY->mq) {
LOG_E("create mq '%s' failed.", pTTY->name);
return RT_ERROR;
}
#ifdef TTY_USING_INT_TX
ret = rt_device_open(pTTY->dev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX);
if (RT_EOK == ret) {
return (RT_EOK);
}
#endif
return RT_EOK;
ret = rt_device_open(pTTY->dev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
if (RT_EOK == ret) {
return (RT_EOK);
}
return (-RT_ERROR);
}
static int chrg_tty_init (void)
/*
* @brief create tty instance dynamically
* @param name - serial device name
* @param baudrate - serial baud rate
* @param parity - serial parity mode
* @param pin - mode contrle pin
* @param level - send mode level
* @retval instance handle
*/
struct chrg_tty_t *chrg_tty_create (const char *name, int baudrate, int parity, int pin, int level)
{
struct chrg_tty_t *pTTY = RT_NULL;
int i = 0;
struct chrg_tty_t *pTTY = RT_NULL;
rt_device_t dev;
for (i = 0; i < TOTAL_TTY; i++) {
pTTY = &chrgtty[i];
chrg_tty_open(pTTY);
}
dev = rt_device_find(name);
if (RT_NULL == dev) {
LOG_E("tty device '%s' not found.", name);
return (RT_NULL);
}
return RT_EOK;
if (RT_Device_Class_Char != dev->type) {
LOG_E("tty device '%s' type is not char.", name);
return (RT_NULL);
}
pTTY = (struct chrg_tty_t *)rt_malloc(sizeof(struct chrg_tty_t));
if (RT_NULL == pTTY) {
LOG_E("no memory for tty create instance.");
return (RT_NULL);
}
pTTY->lock = rt_mutex_create(name, RT_IPC_FLAG_FIFO);
if (RT_NULL == pTTY->lock) {
rt_free(pTTY);
LOG_E("create mutex failed.");
return (RT_NULL);
}
pTTY->evt = rt_event_create(name, RT_IPC_FLAG_FIFO);
if (RT_NULL == pTTY->evt) {
rt_mutex_delete(pTTY->lock);
rt_free(pTTY);
LOG_E("create event failed.");
return (RT_NULL);
}
#ifdef TTY_USING_DMA_TX
pTTY->tx_dly_ms = ((2 * 11 *1000) / baudrate) + 1;
rt_completion_init(&pTTY->tx_comp);
#endif
pTTY->dev = dev;
pTTY->status = 0;
pTTY->pin = pin;
pTTY->level = (level != 0);
pTTY->timeout = 0;
pTTY->byte_tmo = chrg_tty_cal_byte_tmo(baudrate);
chrg_tty_config(pTTY, baudrate, 8, parity, 0);
return pTTY;
}
INIT_APP_EXPORT(chrg_tty_init);
/*
* @brief destory tty instance created dynamically
* @param pTTY - instance handle
* @retval 0 - success, other - error
*/
int chrg_tty_destory (struct chrg_tty_t *pTTY)
{
if (RT_NULL == pTTY) {
LOG_E("param null.");
return (-RT_ERROR);
}
chrg_tty_disconn(pTTY);
if (pTTY->lock) {
rt_mutex_delete(pTTY->lock);
pTTY->lock = RT_NULL;
}
if (pTTY->evt) {
rt_event_delete(pTTY->evt);
pTTY->evt = RT_NULL;
}
rt_free(pTTY);
return (RT_EOK);
}
/*
* @brief config tty params
* @param pTTY - instance handle
* @param baudrate - baudrate of communication
* @param databits - data bits, 5~8
* @param parity - parity bit, 0~2, 0 - none, 1 - odd, 2 - even
* @param stopbits - stop bits, 0~1, 0 - 1 stop bit, 1 - 2 stop bits
* @retval 0 - success, other - error
*/
int chrg_tty_config (struct chrg_tty_t *pTTY,
int baudrate, int databits, int parity, int stopbits)
{
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
if (RT_NULL == pTTY) {
LOG_E("param null.");
return (-RT_ERROR);
}
#ifdef TTY_USING_DMA_TX
pTTY->tx_dly_ms = ((2 * 11 *1000) / baudrate) + 1;
#endif
pTTY->byte_tmo = chrg_tty_cal_byte_tmo(baudrate);
config.baud_rate = baudrate;
config.data_bits = databits;
config.parity = parity;
config.stop_bits = stopbits;
rt_device_control(pTTY->dev, RT_DEVICE_CTRL_CONFIG, &config);
return (RT_EOK);
}
/*
* @brief set wait datas timeout for receiving
* @param pTTY - instance handle
* @param tmo_ms - receive wait timeout, 0--no wait, <0--wait forever, >0--wait timeout, default = 0
* @retval 0 - success, other - error
*/
int chrg_tty_set_recv_tmo (struct chrg_tty_t *pTTY, int tmo_ms)
{
if (RT_NULL == pTTY) {
LOG_E("param null.");
return (-RT_ERROR);
}
pTTY->timeout = tmo_ms;
return (RT_EOK);
}
/*
* @brief set byte interval timeout for receiving
* @param pTTY - instance handle
* @param tmo_ms - byte interval timeout, default is calculated from baudrate
* @retval 0 - success, other - error
*/
int chrg_tty_set_byte_tmo (struct chrg_tty_t *pTTY, int tmo_ms)
{
if (RT_NULL == pTTY) {
LOG_E("param null.");
return (-RT_ERROR);
}
if (tmo_ms < TTY_BYTE_TMO_MIN) {
tmo_ms = TTY_BYTE_TMO_MIN;
} else if (tmo_ms > TTY_BYTE_TMO_MAX) {
tmo_ms = TTY_BYTE_TMO_MAX;
}
pTTY->byte_tmo = tmo_ms;
return (RT_EOK);
}
/*
* @brief open tty connect
* @param pTTY - instance handle
* @retval 0 - success, other - error
*/
int chrg_tty_connect (struct chrg_tty_t * pTTY)
{
if (RT_NULL == pTTY) {
LOG_E("param null.");
return -RT_ERROR;
}
if (pTTY->status == 1) {
return RT_EOK;
}
if (chrg_tty_dev_open(pTTY) != RT_EOK) {
LOG_E("tty open failed.");
return -RT_ERROR;
}
if (pTTY->pin >= 0) {
rt_pin_mode(pTTY->pin, PIN_MODE_OUTPUT);
rt_pin_write(pTTY->pin, !pTTY->level);
}
pTTY->dev->user_data = pTTY;
pTTY->dev->rx_indicate = chrg_tty_recv_ind_hook;
#ifdef TTY_USING_DMA_TX
pTTY->dev->tx_complete = chrg_tty_send_comp_hook;
#endif
pTTY->status = 1;
return (RT_EOK);
}
/*
* @brief close tty connect
* @param pTTY - instance handle
* @retval 0 - success, other - error
*/
int chrg_tty_disconn (struct chrg_tty_t *pTTY)
{
if (RT_NULL == pTTY) {
LOG_E("param null.");
return (-RT_ERROR);
}
if (pTTY->status == 0) {
return(RT_EOK);
}
rt_mutex_take(pTTY->lock, RT_WAITING_FOREVER);
if (pTTY->dev) {
pTTY->dev->rx_indicate = RT_NULL;
#ifdef TTY_USING_DMA_TX
pTTY->dev->tx_complete = RT_NULL;
#endif
rt_device_close(pTTY->dev);
}
if (pTTY->pin >= 0) {
rt_pin_mode(pTTY->pin, PIN_MODE_INPUT);
}
pTTY->status = 0;
rt_mutex_release(pTTY->lock);
return (RT_EOK);
}
/*
* @brief receive datas from tty
* @param pTTY - instance handle
* @param buf - buffer addr
* @param size - maximum length of received datas
* @retval >=0 - length of received datas, <0 - error
*/
int chrg_tty_recv (struct chrg_tty_t *pTTY, void *buf, int size)
{
rt_err_t ret = RT_EOK;
int recv_len = 0;
rt_uint32_t recved = 0;
if (pTTY == RT_NULL || buf == RT_NULL || size == 0) {
LOG_E("param null.");
return (-RT_ERROR);
}
if (pTTY->status == 0) {
return (-RT_ERROR);
}
ret = rt_mutex_take(pTTY->lock, RT_WAITING_FOREVER);
if (RT_EOK != ret) {
LOG_E("mutex take failed. [%d]", ret);
return(-RT_ERROR);
}
while (size) {
int len = rt_device_read(pTTY->dev, 0, (char *)buf + recv_len, size);
if (len) {
recv_len += len;
size -= len;
continue;
}
rt_event_control(pTTY->evt, RT_IPC_CMD_RESET, RT_NULL);
if (recv_len) {
ret = rt_event_recv(pTTY->evt, TTY_EVT_RX_IND,
(RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR), pTTY->byte_tmo, &recved);
if (RT_EOK != ret) {
break;
}
} else {
ret = rt_event_recv(pTTY->evt, (TTY_EVT_RX_IND | TTY_EVT_RX_BREAK),
(RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR), pTTY->timeout, &recved);
if (RT_EOK != ret) {
break;
}
if ((recved & TTY_EVT_RX_BREAK) != 0) {
rt_mutex_release(pTTY->lock);
rt_thread_delay(2);
return 0;
}
}
}
rt_mutex_release(pTTY->lock);
return recv_len;
}
/*
* @brief send datas to tty
* @param pTTY - instance handle
* @param buf - buffer addr
* @param size - length of send datas
* @retval >=0 - length of sent datas, <0 - error
*/
int chrg_tty_send (struct chrg_tty_t *pTTY, void *buf, int size)
{
rt_err_t ret = RT_EOK;
int send_len = 0;
if (pTTY == RT_NULL || buf == RT_NULL || size == 0) {
LOG_E("param null.");
return (-RT_ERROR);
}
if (pTTY->status == 0) {
LOG_E("tty not connected.");
return (-RT_ERROR);
}
rt_kprintf("%s %d\r\n", __func__, __LINE__);
ret = rt_mutex_take(pTTY->lock, RT_WAITING_FOREVER);
if (RT_EOK != ret) {
LOG_E("mutex take failed. [%d]", ret);
return (-RT_ERROR);
}
rt_kprintf("%s %d size %d\r\n", __func__, __LINE__, size);
chrg_tty_mode_set(pTTY, 1);//set to send mode
rt_kprintf("%s %d\r\n", __func__, __LINE__);
send_len = rt_device_write(pTTY->dev, 0, buf, size);
rt_kprintf("%s %d %d\r\n", __func__, __LINE__, send_len);
chrg_tty_mode_set(pTTY, 0);//set to receive mode
rt_mutex_release(pTTY->lock);
rt_kprintf("%s %d\r\n", __func__, __LINE__);
return send_len;
}
/*
* @brief break tty receive wait
* @param pTTY - instance handle
* @retval 0 - success, other - error
*/
int chrg_tty_break_recv (struct chrg_tty_t *pTTY)
{
if ((pTTY == RT_NULL) || (pTTY->evt == RT_NULL)) {
return (-RT_ERROR);
}
rt_event_send(pTTY->evt, TTY_EVT_RX_BREAK);
return (RT_EOK);
}
/*
* @brief send data to tty and then receive response data from tty
* @param pTTY - instance handle
* @param send_buf - send buffer addr
* @param send_len - length of send datas
* @param recv_buf - recv buffer addr
* @param recv_size - maximum length of received datas
* @retval >=0 - length of received datas, <0 - error
*/
int chrg_tty_send_then_recv (struct chrg_tty_t *pTTY,
void *send_buf, int send_len, void *recv_buf, int recv_size)
{
rt_err_t ret = RT_EOK;
int recv_len = 0;
rt_uint32_t recved = 0;
if (pTTY == RT_NULL || send_buf == RT_NULL || send_len == 0 || recv_buf == RT_NULL || recv_size == 0) {
LOG_E("null param");
return(-RT_ERROR);
}
if (pTTY->status == 0) {
LOG_E("tty not connected.");
return(-RT_ERROR);
}
ret = rt_mutex_take(pTTY->lock, RT_WAITING_FOREVER);
if (RT_EOK != ret) {
LOG_E("mutex take failed. [%d]", ret);
return(-RT_ERROR);
}
chrg_tty_mode_set(pTTY, 1);//set to send mode
send_len = rt_device_write(pTTY->dev, 0, send_buf, send_len);
chrg_tty_mode_set(pTTY, 0);//set to receive mode
if (send_len < 0) {
rt_mutex_release(pTTY->lock);
LOG_E("send error.");
return(-RT_ERROR);
}
while (recv_size) {
int len = rt_device_read(pTTY->dev, 0, (char *)recv_buf + recv_len, recv_size);
if (len) {
recv_len += len;
recv_size -= len;
continue;
}
rt_event_control(pTTY->evt, RT_IPC_CMD_RESET, RT_NULL);
if (recv_len) {
ret = rt_event_recv(pTTY->evt, TTY_EVT_RX_IND,
(RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR), pTTY->byte_tmo, &recved);
if (RT_EOK != ret) {
break;
}
} else {
ret = rt_event_recv(pTTY->evt, TTY_EVT_RX_IND,
(RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR), pTTY->timeout, &recved);
if (RT_EOK != ret) {
break;
}
}
}
rt_mutex_release(pTTY->lock);
return recv_len;
}