前言
前边调试通了cp Transport,但是有很多带网卡的场合,串口设备却很不配备。
串口传输接口
首先,我们浏览一下“erpc_serial.h”头文件,这里声明了6个函数:
int serial_setup(int fd, speed_t speed);
int serial_set_read_timeout(int fd, uint8_t vtime, uint8_t vmin);
int serial_write(int fd, char *buf, int size);
int serial_read(int fd, char *buf, int size);
int serial_open(const char *port);
int serial_close(int fd);
的,不同的是cp传输修改TCPTransport类,串口不修改SerialTransport这个函数,到时候再细说每个函数的作用以及点儿。
SerialTransport
虽然说不修改吧,倒是需要做点线儿,添加rt-thread平台预编译上线代码,比如非rt-thread操作支持掉线,
#ifdef _WIN32
#include <direct.h>
#include <io.h>
#include <windows.h>
#elif defined(RTTHREAD)
#else
#include <termios.h>
#endif
头文件未添加新头文件包含,还有两个地方原本是在WIN32平台下啥都没干,这里比猫画虎,也让rt-thread环境下啥也不干(共两处)
#ifdef _WIN32
// TODO
#elif defined(RTTHREAD)
// TODO
修改“serial.h”
添加speed_t类型定义:
#elif defined(RTTHREAD)
typedef unsigned int speed_t;
“串行.cpp”
添加 rt-thread 设备框架头文件:
#elif defined(RTTHREAD)
#include "rtdevice.h"
struct rt_completion rx_ind;
serial_setup
串口配置,主要是配置端口修改率值。rt-thread中配置串口设备率只需要调用一个函数rt_device_control。
是我们serial_setup函数的第一个int任务类型,但这rt_deivce_xxx是我们函数中的第一个任务类型rt_device_t。
很简单,强制一下,闭着眼就认为就好了:rt_device_t dev = (rt_device_t)((unsigned int)fd);
完整代码如下:
#elif defined(RTTHREAD)
rt_device_t dev;
struct serial_configure uart_conf = {
BAUD_RATE_115200, /* 115200 bits/s */
DATA_BITS_8, /* 8 databits /
STOP_BITS_1, / 1 stopbit /
PARITY_NONE, / No parity /
BIT_ORDER_LSB, / LSB first sent /
NRZ_NORMAL, / Normal mode /
RT_SERIAL_RB_BUFSZ, / Buffer size */
0
};
uart_conf.baud_rate = speed;
dev = (rt_device_t)((unsigned int)fd);
rt_device_control(dev, RT_DEVICE_CTRL_CONFIG, &uart_conf);
serial_set_read_timeout
也是串口设备的,使用这个重定向读取里设置这个概念。rt没有,可以设置空。
#ifdef _WIN32
// TODO
#elif defined(RTTHREAD)
// TODO
#else
...
serial_write
写一个数据,第二个参数是预发送数据的首字节,参数是预发送数据的字节数。
rt_device_t dev;
rt_size_t len = 0, ret = 0;
dev = (rt_device_t)((unsigned int)fd);
do {
ret = rt_device_write(dev, 0, buf, size);
if (ret == 0) {
break;
}
len += ret;
} while(len < size);
return ret;
serial_read
size读个串口,第二个参数是接收数据缓存首地址后第三个参数是预读取数据数据。样本错误。错误返回-1。
rt_device_t dev;
rt_err_t err = 0;
rt_size_t len = 0, ret = 0;
rt_tick_t timeout = 0;
dev = (rt_device_t)((unsigned int)fd);
timeout = rt_tick_get() + 10000;
do {
err = rt_completion_wait(&rx_ind, 10);
if (err == RT_ETIMEOUT) {
if ((rt_tick_get() - timeout) < RT_TICK_MAX / 2) {
return -1;
}
continue;
}
ret = rt_device_read(dev, 0, buf + len, size - len);
if (ret == 0) {
return -1;
} else {
len += ret;
}
} while (len < size);
return len;
这里有两点需要注意:
也是一个do while循环结构,没有得到想要的数据量之前不能退出函数。
做个处理,然后十个错误返回。
serial_open
目前正在使用轮询v1,所以只显示接收,询发送模式。
rt_device_t dev = RT_NULL;
dev = rt_device_find(port);
if (dev == RT_NULL)
{
rt_kprintf("Can not find device: %s\n", port);
return -1;
}
rt_completion_init(&rx_ind);
if (rt_device_open(dev, RT_DEVICE_OFLAG_RDWR |
RT_DEVICE_FLAG_INT_RX
) == RT_EOK)
{
rt_device_set_rx_indicate(dev, serial_rx_ind);
}
return (int)dev;
错误接收添加了杰出功能serial_rx_ind
static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size)
{
rt_completion_done(&rx_ind);
}
这里没有使用消息,也就是没有使用信号量,使用完成量,通知serial_read有数据来。
如果换成serialX 经常用方便呢?
首先,打开串口设备使用模式最好,发送都可以使用或者DMA。
服务端有一些特别的影响,但如果终端的读过程有特别的影响,可能会出现拒绝的终止线,因为可能会出现下滑serial_read,因为它被拒绝到达,这rt_device_read本身就没有概念。最优解。
这样,使用 serialX 或者 v1 上面的代码差异不大。
serial_close
关闭串口设备就简单了
#elif defined(RTTHREAD)
rt_device_t dev;
dev = (rt_device_t)((unsigned int)fd);
rt_device_close(dev);
验证
和tcp
不同的是初始化transport 不一样了。
erpc_transport_t transport = erpc_transport_serial_init("uart2", 115200);
只是一个参数,一个是串口率,一个是串口监视器serial_setup。
串口传输没有关闭,没有因此erpc_transport_serial_close函数。
结束语
佳佳,serialX 的非自由读实现使用serial_read效果更佳。
原作者:出出啊
更多回帖