[drivers][serial_v2]允许阻塞接收超过rx缓冲区大小的数据、增加超时时间、flush、获取缓冲区数据长度命令、数据溢出逻…
…辑修复、稳定性细节优化、添加更多serial_v2测试用例
当前只在STM32平台测试过,别的平台只是将rt_ringbuffer_putchar替换为rt_ringbuffer_putchar_force理论上不会出问题,可以再检查一下
拉取/合并请求描述:(PR description)
[
为什么提交这份PR (why to submit this PR)
优化serial_v2驱动
你的解决方案是什么 (what is your solution)
请提供验证的bsp和config (provide the config and bsp)
- BSP: STM32F407-lckfb-skystar进行utest、echo等测试 STM32F401RCT6进行at_socket测试
- .config:
- action:
]
当前拉取/合并请求的状态 Intent for your PR
必须选择一项 Choose one (Mandatory):
- [ ] 本拉取/合并请求是一个草稿版本 This PR is for a code-review and is intended to get feedback
- [x] 本拉取/合并请求是一个成熟版本 This PR is mature, and ready to be integrated into the repo
代码质量 Code Quality:
我在这个拉取/合并请求中已经考虑了 As part of this pull request, I've considered the following:
- [x] 已经仔细查看过代码改动的对比 Already check the difference between PR and old code
- [x] 代码风格正确,包括缩进空格,命名及其他风格 Style guide is adhered to, including spacing, naming and other styles
- [x] 没有垃圾代码,代码尽量精简,不包含
#if 0代码,不包含已经被注释了的代码 All redundant code is removed and cleaned up - [x] 所有变更均有原因及合理的,并且不会影响到其他软件组件代码或BSP All modifications are justified and not affect other components or BSP
- [x] 对难懂代码均提供对应的注释 I've commented appropriately where code is tricky
- [x] 代码是高质量的 Code in this PR is of high quality
- [x] 已经使用formatting 等源码格式化工具确保格式符合RT-Thread代码规范 This PR complies with RT-Thread code specification
@Ryan-CW-Code 感谢PR,但CI的代码格式化检查没有通过,麻烦使用工具:https://github.com/mysterywolf/formatting 格式化下再提交下~
utest和at_socket都使用dma和int方式分别进行测试。 echo测试代码如下,之前跑了两天数据没有丢包
大家可以再测试测试,看看有什么问题是没发现的
#include <board.h>
#include <rtthread.h>
#include <rtdevice.h>
#define echo_test_buffer_size (1024)
// 测试环境
// 串口2、3开启dma, 5、6不开启
// 缓冲区大小都为 128 字节
// echo test
// 3tx - 6rx
// 3rx - 6tx
// self test
// 2tx - 2rx
// 5tx - 5rx
static rt_device_t u2serial;
static rt_device_t u3serial;
static rt_device_t u5serial;
static rt_device_t u6serial;
static rt_uint32_t u2rx_length = 0;
static rt_uint32_t u2tx_length = 0;
static rt_uint32_t u3rx_length = 0;
static rt_uint32_t u3tx_length = 0;
static rt_uint32_t u5rx_length = 0;
static rt_uint32_t u5tx_length = 0;
static rt_uint32_t u6rx_length = 0;
static rt_uint32_t u6tx_length = 0;
static void echo_test_u3_thread_entry(void *parameter)
{
char *uart_name = "uart3";
rt_err_t result;
static char rx_buffer[echo_test_buffer_size + 1];
char str[] = "hello RT-Thread!";
/* 查找串口设备 */
u3serial = rt_device_find(uart_name);
if (!u3serial)
{
rt_kprintf("find %s failed!\n", uart_name);
return;
}
rt_device_open(u3serial, RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING);
rt_ssize_t buf_datalen = 0;
while (1)
{
rt_device_control(u3serial, RT_SERIAL_CTRL_GET_UNREAD_BYTES_COUNT, (void *)&buf_datalen);
int32_t recbLen = rt_device_read(u3serial, 0, rx_buffer, buf_datalen > 0 ? buf_datalen : 1);
if (recbLen > 0)
{
u3rx_length += recbLen;
u3tx_length += rt_device_write(u3serial, 0, rx_buffer, recbLen);
}
}
}
static void echo_test_u6_thread_entry(void *parameter)
{
static char rx_buffer[echo_test_buffer_size + 1];
rt_ssize_t buf_datalen = 0;
while (1)
{
rt_device_control(u6serial, RT_SERIAL_CTRL_GET_UNREAD_BYTES_COUNT, (void *)&buf_datalen);
int32_t recbLen = rt_device_read(u6serial, 0, rx_buffer, buf_datalen > 0 ? buf_datalen : 1);
if (recbLen > 0)
{
u6rx_length += recbLen;
}
}
}
static void echo_test(void *parameter)
{
static char tx_buffer[echo_test_buffer_size];
for (uint32_t i = 0; i < sizeof(tx_buffer); i++)
tx_buffer[i] = i;
char *uart_name = "uart6";
u6serial = rt_device_find(uart_name);
if (!u6serial)
{
rt_kprintf("find %s failed!\n", uart_name);
return;
}
rt_device_open(u6serial, RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING);
rt_thread_startup(rt_thread_create("serial3", echo_test_u3_thread_entry, RT_NULL, 2048, 7, 5));
rt_thread_startup(rt_thread_create("serial6", echo_test_u6_thread_entry, RT_NULL, 2048, 7, 5));
uint32_t count = 0;
while (1)
{
// 不定长发送数据
for (uint32_t i = sizeof(tx_buffer) / 10; i < sizeof(tx_buffer); i++)
{
count++;
u6tx_length += rt_device_write(u6serial, 0, tx_buffer, i);
rt_thread_mdelay(15);
if (count % 100 == 0)
{
rt_kprintf("echo, uart3: tx: %ld, rx: %ld\r\n", u3tx_length, u3rx_length);
rt_kprintf("echo, uart6: tx: %ld, rx: %ld\r\n", u6tx_length, u6rx_length);
if (u3tx_length != u3rx_length || u6tx_length != u6rx_length || u3tx_length != u6tx_length)
{
rt_kprintf("echo test error!!!\r\n");
return;
}
}
}
}
}
static void self_tx_rx_u2_thread_entry(void *parameter)
{
static char rx_buffer[1024 + 1];
while (1)
{
/* 从串口读取数据 */
u2rx_length += rt_device_read(u2serial, 0, rx_buffer, 1000);
}
}
static void self_tx_rx_u5_thread_entry(void *parameter)
{
static char rx_buffer[1024 + 1];
while (1)
{
/* 从串口读取数据 */
u5rx_length += rt_device_read(u5serial, 0, rx_buffer, 500);
}
}
static void self_tx_rx_test(void *parameter)
{
static char tx_buffer[1024 + 1];
for (uint32_t i = 0; i < sizeof(tx_buffer); i++)
tx_buffer[i] = i;
char *uart_name = "uart2";
u2serial = rt_device_find(uart_name);
if (!u2serial)
{
rt_kprintf("find %s failed!\n", uart_name);
return;
}
rt_device_open(u2serial, RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING);
char *uart5_name = "uart5";
u5serial = rt_device_find(uart5_name);
if (!u5serial)
{
rt_kprintf("find %s failed!\n", uart5_name);
return;
}
rt_device_open(u5serial, RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING);
rt_thread_startup(rt_thread_create("serial2", self_tx_rx_u2_thread_entry, RT_NULL, 2048, 6, 5));
rt_thread_startup(rt_thread_create("serial5", self_tx_rx_u5_thread_entry, RT_NULL, 2048, 6, 5));
for (uint32_t i = 0;; i++)
{
u2tx_length += rt_device_write(u2serial, 0, tx_buffer, 1000);
u5tx_length += rt_device_write(u5serial, 0, tx_buffer, 500);
rt_thread_mdelay(10);
if (i % 100 == 0)
{
rt_kprintf("self_test, uart2: tx: %ld, rx: %ld\r\n", u2tx_length, u2rx_length);
rt_kprintf("self_test, uart5: tx: %ld, rx: %ld\r\n", u5tx_length, u5rx_length);
if (u2tx_length != u2rx_length || u5tx_length != u5rx_length)
{
rt_kprintf("self test error!!!\r\n");
return;
}
}
}
}
static int uart_test(void)
{
rt_thread_startup(rt_thread_create("echo_test", echo_test, RT_NULL, 2048, 10, 5));
rt_thread_startup(rt_thread_create("self_test", self_tx_rx_test, RT_NULL, 2048, 10, 5));
return 0;
}
MSH_CMD_EXPORT_ALIAS(uart_test, uart_test, );
at_client我们配合at_socket用了快一个月。 at_server我们没有产品在使用,用命令行简单的测试了一下
utest和at_socket都使用dma和int方式分别进行测试。 echo测试代码如下,之前跑了两天数据没有丢包
大家可以再测试测试,看看有什么问题是没发现的
#include <board.h> #include <rtthread.h> #include <rtdevice.h> #define echo_test_buffer_size (1024) // 测试环境 // 串口2、3开启dma, 5、6不开启 // 缓冲区大小都为 128 字节 // echo test // 3tx - 6rx // 3rx - 6tx // self test // 2tx - 2rx // 5tx - 5rx static rt_device_t u2serial; static rt_device_t u3serial; static rt_device_t u5serial; static rt_device_t u6serial; static rt_uint32_t u2rx_length = 0; static rt_uint32_t u2tx_length = 0; static rt_uint32_t u3rx_length = 0; static rt_uint32_t u3tx_length = 0; static rt_uint32_t u5rx_length = 0; static rt_uint32_t u5tx_length = 0; static rt_uint32_t u6rx_length = 0; static rt_uint32_t u6tx_length = 0; static void echo_test_u3_thread_entry(void *parameter) { char *uart_name = "uart3"; rt_err_t result; static char rx_buffer[echo_test_buffer_size + 1]; char str[] = "hello RT-Thread!"; /* 查找串口设备 */ u3serial = rt_device_find(uart_name); if (!u3serial) { rt_kprintf("find %s failed!\n", uart_name); return; } rt_device_open(u3serial, RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING); rt_ssize_t buf_datalen = 0; while (1) { rt_device_control(u3serial, RT_SERIAL_CTRL_GET_RX_DATA_LEN, (void *)&buf_datalen); int32_t recbLen = rt_device_read(u3serial, 0, rx_buffer, buf_datalen > 0 ? buf_datalen : 1); if (recbLen > 0) { u3rx_length += recbLen; u3tx_length += rt_device_write(u3serial, 0, rx_buffer, recbLen); } } } static void echo_test_u6_thread_entry(void *parameter) { static char rx_buffer[echo_test_buffer_size + 1]; rt_ssize_t buf_datalen = 0; while (1) { rt_device_control(u6serial, RT_SERIAL_CTRL_GET_RX_DATA_LEN, (void *)&buf_datalen); int32_t recbLen = rt_device_read(u6serial, 0, rx_buffer, buf_datalen > 0 ? buf_datalen : 1); if (recbLen > 0) { u6rx_length += recbLen; } } } static void echo_test(void *parameter) { static char tx_buffer[echo_test_buffer_size]; for (uint32_t i = 0; i < sizeof(tx_buffer); i++) tx_buffer[i] = i; char *uart_name = "uart6"; u6serial = rt_device_find(uart_name); if (!u6serial) { rt_kprintf("find %s failed!\n", uart_name); return; } rt_device_open(u6serial, RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING); rt_thread_startup(rt_thread_create("serial3", echo_test_u3_thread_entry, RT_NULL, 2048, 7, 5)); rt_thread_startup(rt_thread_create("serial6", echo_test_u6_thread_entry, RT_NULL, 2048, 7, 5)); uint32_t count = 0; while (1) { // 不定长发送数据 for (uint32_t i = sizeof(tx_buffer) / 10; i < sizeof(tx_buffer); i++) { count++; u6tx_length += rt_device_write(u6serial, 0, tx_buffer, i); rt_thread_mdelay(15); if (count % 100 == 0) { rt_kprintf("echo, uart3: tx: %ld, rx: %ld\r\n", u3tx_length, u3rx_length); rt_kprintf("echo, uart6: tx: %ld, rx: %ld\r\n", u6tx_length, u6rx_length); if (u3tx_length != u3rx_length || u6tx_length != u6rx_length || u3tx_length != u6tx_length) { rt_kprintf("echo test error!!!\r\n"); return; } } } } } static void self_tx_rx_u2_thread_entry(void *parameter) { static char rx_buffer[1024 + 1]; while (1) { /* 从串口读取数据 */ u2rx_length += rt_device_read(u2serial, 0, rx_buffer, 1000); } } static void self_tx_rx_u5_thread_entry(void *parameter) { static char rx_buffer[1024 + 1]; while (1) { /* 从串口读取数据 */ u5rx_length += rt_device_read(u5serial, 0, rx_buffer, 500); } } static void self_tx_rx_test(void *parameter) { static char tx_buffer[1024 + 1]; for (uint32_t i = 0; i < sizeof(tx_buffer); i++) tx_buffer[i] = i; char *uart_name = "uart2"; u2serial = rt_device_find(uart_name); if (!u2serial) { rt_kprintf("find %s failed!\n", uart_name); return; } rt_device_open(u2serial, RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING); char *uart5_name = "uart5"; u5serial = rt_device_find(uart5_name); if (!u5serial) { rt_kprintf("find %s failed!\n", uart5_name); return; } rt_device_open(u5serial, RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING); rt_thread_startup(rt_thread_create("serial2", self_tx_rx_u2_thread_entry, RT_NULL, 2048, 6, 5)); rt_thread_startup(rt_thread_create("serial5", self_tx_rx_u5_thread_entry, RT_NULL, 2048, 6, 5)); for (uint32_t i = 0;; i++) { u2tx_length += rt_device_write(u2serial, 0, tx_buffer, 1000); u5tx_length += rt_device_write(u5serial, 0, tx_buffer, 500); rt_thread_mdelay(10); if (i % 100 == 0) { rt_kprintf("self_test, uart2: tx: %ld, rx: %ld\r\n", u2tx_length, u2rx_length); rt_kprintf("self_test, uart5: tx: %ld, rx: %ld\r\n", u5tx_length, u5rx_length); if (u2tx_length != u2rx_length || u5tx_length != u5rx_length) { rt_kprintf("self test error!!!\r\n"); return; } } } } static int uart_test(void) { rt_thread_startup(rt_thread_create("echo_test", echo_test, RT_NULL, 2048, 10, 5)); rt_thread_startup(rt_thread_create("self_test", self_tx_rx_test, RT_NULL, 2048, 10, 5)); return 0; } MSH_CMD_EXPORT_ALIAS(uart_test, uart_test, );
已在瑞萨RA8开发板测试,没问题
基于最新提交gd32使能中断后测试结果:
dfs1.0里面这个函数是不是应该把红框部分放到上面,文件有ioctl函数的情况下依然会进不去文件本身的ioctl。
导致现在串口posix的非阻塞和阻塞实现只能在发送函数里面实现,理想情况下是用户调用fcntl时就切换阻塞和非阻塞模式。
#8854 #8352 #8143 #3086
现在驱动中关于ringbuff使用了大量的关中断,看了下ringbuff源码。
如果采用写满拒绝新数据策略,应该能实现单生产者和单消费者,这样能让ringbuff在无锁模式下正常运行,高速通讯丢包会小很多。
RTT官方目前也没看到关于这方面规范的说明,可以在这里讨论下怎么选择。
或许也可以把写满拒绝新数据策略和覆盖旧数据策略选择权交给用户,这样的话要改的东西要多一点
现在驱动中关于ringbuff使用了大量的关中断,看了下ringbuff源码。 如果采用
写满拒绝新数据策略,应该能实现单生产者和单消费者,这样能让ringbuff在无锁模式下正常运行,高速通讯丢包会小很多。 RTT官方目前也没看到关于这方面规范的说明,可以在这里讨论下怎么选择。或许也可以把
写满拒绝新数据策略和覆盖旧数据策略选择权交给用户,这样的话要改的东西要多一点
这块内容要不下次在社区例会讨论下?
现在驱动中关于ringbuff使用了大量的关中断,看了下ringbuff源码。 如果采用
写满拒绝新数据策略,应该能实现单生产者和单消费者,这样能让ringbuff在无锁模式下正常运行,高速通讯丢包会小很多。 RTT官方目前也没看到关于这方面规范的说明,可以在这里讨论下怎么选择。 或许也可以把写满拒绝新数据策略和覆盖旧数据策略选择权交给用户,这样的话要改的东西要多一点这块内容要不下次在社区例会讨论下?
现在驱动中关于ringbuff使用了大量的关中断,看了下ringbuff源码。 如果采用
写满拒绝新数据策略,应该能实现单生产者和单消费者,这样能让ringbuff在无锁模式下正常运行,高速通讯丢包会小很多。 RTT官方目前也没看到关于这方面规范的说明,可以在这里讨论下怎么选择。 或许也可以把写满拒绝新数据策略和覆盖旧数据策略选择权交给用户,这样的话要改的东西要多一点这块内容要不下次在社区例会讨论下?
可以呀,你们来主导就行,驱动规范这方面你们来主导最好。 目前是两种策略都实现了,DMA也狠狠心把乒乓缓冲加上了(原本不想加,修改的的东西太多太麻烦了)。
现在驱动中关于ringbuff使用了大量的关中断,看了下ringbuff源码。 如果采用
写满拒绝新数据策略,应该能实现单生产者和单消费者,这样能让ringbuff在无锁模式下正常运行,高速通讯丢包会小很多。 RTT官方目前也没看到关于这方面规范的说明,可以在这里讨论下怎么选择。 或许也可以把写满拒绝新数据策略和覆盖旧数据策略选择权交给用户,这样的话要改的东西要多一点这块内容要不下次在社区例会讨论下?
现在驱动中关于ringbuff使用了大量的关中断,看了下ringbuff源码。 如果采用
写满拒绝新数据策略,应该能实现单生产者和单消费者,这样能让ringbuff在无锁模式下正常运行,高速通讯丢包会小很多。 RTT官方目前也没看到关于这方面规范的说明,可以在这里讨论下怎么选择。 或许也可以把写满拒绝新数据策略和覆盖旧数据策略选择权交给用户,这样的话要改的东西要多一点这块内容要不下次在社区例会讨论下?
可以呀,你们来主导就行,驱动规范这方面你们来主导最好。 目前是两种策略都实现了,DMA也狠狠心把乒乓缓冲加上了(原本不想加,修改的的东西太多太麻烦了)。
留个联系方式?下次开会拉上你~
留个联系方式?下次开会拉上你~ 发您b站私信了,微信号不方便放到公开区域
这份修改思路合理.
非常详实、也实用的PR,希望能尽快合并,赶上下一次发版
非常详实、也实用的PR,希望能尽快合并,赶上下一次发版
这份PR您有在平台测试过吗?
非常详实、也实用的PR,希望能尽快合并,赶上下一次发版
这份PR您有在平台测试过吗?
暂时没有,我有STM32G4平台,需要帮助测试吗?有哪些部分可以帮上忙的?
非常详实、也实用的PR,希望能尽快合并,赶上下一次发版
这份PR您有在平台测试过吗?
暂时没有,我有STM32G4平台,需要帮助测试吗?有哪些部分可以帮上忙的?
好呀,您可以列一下可以测试的硬件平台,我认为可以把作者的测试用例跑过就算通过了
惭愧,这段时间太忙了,很多事情缠身实在没有精力。 RTT更新了很多,这个PR也有很多冲突需要进行解决。 有愿意继续完善的欢迎贡献和提意见
立个flag,五一前或五一假期完善此PR
惭愧,这段时间太忙了,很多事情缠身实在没有精力。 RTT更新了很多,这个PR也有很多冲突需要进行解决。 有愿意继续完善的欢迎贡献和提意见
立个flag,五一前或五一假期完善此PR
理解,有RTT需要协助帮忙的可以提出来,我们可以一起推进
这个例程能跑过的v2驱动大致就能使用了。 utest能跑过很多隐藏问题应该都可以发现
#include <board.h>
#include <rtthread.h>
#include <rtdevice.h>
#define echo_test_buffer_size (1024)
// 测试环境
// 串口2、3开启dma, 5、6不开启
// 缓冲区大小都为 128 字节
// echo test
// 3tx - 6rx
// 3rx - 6tx
// self test
// 2tx - 2rx
// 5tx - 5rx
static rt_device_t u2serial;
static rt_device_t u3serial;
static rt_device_t u5serial;
static rt_device_t u6serial;
static rt_uint32_t u2rx_length = 0;
static rt_uint32_t u2tx_length = 0;
static rt_uint32_t u3rx_length = 0;
static rt_uint32_t u3tx_length = 0;
static rt_uint32_t u5rx_length = 0;
static rt_uint32_t u5tx_length = 0;
static rt_uint32_t u6rx_length = 0;
static rt_uint32_t u6tx_length = 0;
static void echo_test_u3_thread_entry(void *parameter)
{
char *uart_name = "uart3";
static char rx_buffer[echo_test_buffer_size + 1];
/* 查找串口设备 */
u3serial = rt_device_find(uart_name);
if (!u3serial)
{
rt_kprintf("find %s failed!\n", uart_name);
return;
}
rt_device_open(u3serial, RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING);
rt_ssize_t buf_datalen = 0;
while (1)
{
rt_device_control(u3serial, RT_SERIAL_CTRL_GET_UNREAD_BYTES_COUNT, (void *)&buf_datalen);
int32_t recbLen = rt_device_read(u3serial, 0, rx_buffer, buf_datalen > 0 ? buf_datalen : 1);
if (recbLen > 0)
{
u3rx_length += recbLen;
u3tx_length += rt_device_write(u3serial, 0, rx_buffer, recbLen);
}
}
}
static void echo_test_u6_thread_entry(void *parameter)
{
static char rx_buffer[echo_test_buffer_size + 1];
rt_ssize_t buf_datalen = 0;
while (1)
{
rt_device_control(u6serial, RT_SERIAL_CTRL_GET_UNREAD_BYTES_COUNT, (void *)&buf_datalen);
int32_t recbLen = rt_device_read(u6serial, 0, rx_buffer, buf_datalen > 0 ? buf_datalen : 1);
if (recbLen > 0)
{
u6rx_length += recbLen;
}
}
}
static void echo_test(void *parameter)
{
static char tx_buffer[echo_test_buffer_size];
for (uint32_t i = 0; i < sizeof(tx_buffer); i++)
tx_buffer[i] = i;
char *uart_name = "uart6";
u6serial = rt_device_find(uart_name);
if (!u6serial)
{
rt_kprintf("find %s failed!\n", uart_name);
return;
}
rt_device_open(u6serial, RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING);
rt_thread_startup(rt_thread_create("serial3", echo_test_u3_thread_entry, RT_NULL, 2048, 7, 5));
rt_thread_startup(rt_thread_create("serial6", echo_test_u6_thread_entry, RT_NULL, 2048, 7, 5));
uint32_t count = 0;
uint32_t sendTotalCount = 0;
while (1)
{
count++;
// 不定长发送数据
uint32_t sendCount = rand() % echo_test_buffer_size;
u6tx_length += rt_device_write(u6serial, 0, tx_buffer, sendCount);
sendTotalCount += sendCount;
// 等待交叉发送完毕
rt_thread_mdelay(15);
if (count % 100 == 0)
{
srand(rt_tick_get());
rt_kprintf("echo, uart3: tx: %ld, rx: %ld\r\n", u3tx_length, u3rx_length);
rt_kprintf("echo, uart6: tx: %ld, rx: %ld\r\n", u6tx_length, u6rx_length);
if (u3tx_length != u3rx_length || u6tx_length != u6rx_length || u3tx_length != u6tx_length)
{
rt_kprintf("echo test error!!!\r\n");
return;
}
// 前面已经判断过4个值是否相等了
if (u3tx_length != sendTotalCount)
{
rt_kprintf("发送数据不对等,echo test error!!!\r\n");
return;
}
}
}
}
static void self_tx_rx_u2_thread_entry(void *parameter)
{
static char rx_buffer[1024 + 1];
while (1)
{
u2rx_length += rt_device_read(u2serial, 0, rx_buffer, 1000);
}
}
static void self_tx_rx_u5_thread_entry(void *parameter)
{
static char rx_buffer[1024 + 1];
while (1)
{
u5rx_length += rt_device_read(u5serial, 0, rx_buffer, 500);
}
}
/**
* @brief 测试思路,创建u2和u5线程接收自己的数据并记录接收长度,在当前线程u2和u5发送数据,等待数据发送完毕,判断发送数据长度和接收数据长度是否一致
*
* @param parameter
*/
static void self_tx_rx_test(void *parameter)
{
static char tx_buffer[1024 + 1];
for (uint32_t i = 0; i < sizeof(tx_buffer); i++)
tx_buffer[i] = i;
char *uart_name = "uart2";
u2serial = rt_device_find(uart_name);
if (!u2serial)
{
rt_kprintf("find %s failed!\n", uart_name);
return;
}
rt_device_open(u2serial, RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING);
char *uart5_name = "uart5";
u5serial = rt_device_find(uart5_name);
if (!u5serial)
{
rt_kprintf("find %s failed!\n", uart5_name);
return;
}
rt_device_open(u5serial, RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING);
rt_thread_startup(rt_thread_create("serial2", self_tx_rx_u2_thread_entry, RT_NULL, 2048, 6, 5));
rt_thread_startup(rt_thread_create("serial5", self_tx_rx_u5_thread_entry, RT_NULL, 2048, 6, 5));
for (uint32_t i = 0;; i++)
{
u2tx_length += rt_device_write(u2serial, 0, tx_buffer, 1000);
u5tx_length += rt_device_write(u5serial, 0, tx_buffer, 500);
rt_device_control(u2serial, RT_SERIAL_CTRL_TX_FLUSH, RT_NULL);
rt_device_control(u5serial, RT_SERIAL_CTRL_TX_FLUSH, RT_NULL);
// rt_thread_mdelay(10);
if (i % 100 == 0)
{
rt_kprintf("self_test, uart2: tx: %ld, rx: %ld\r\n", u2tx_length, u2rx_length);
rt_kprintf("self_test, uart5: tx: %ld, rx: %ld\r\n", u5tx_length, u5rx_length);
if (u2tx_length != u2rx_length || u5tx_length != u5rx_length)
{
rt_kprintf("self test error!!!\r\n");
return;
}
if (u5rx_length * 2 != u2rx_length)
{
rt_kprintf("数据不等长 self test error!!!\r\n");
return;
}
}
}
}
//
// uart_blocking_rx
// uart_blocking_tx
// testcases.drivers.uart_flush_rx
// testcases.drivers.uart_flush_txb
// testcases.drivers.uart_flush_txnb
// testcases.drivers.uart_get_unread_bytes_count
// uart_nonblocking_rx
// uart_nonblocking_tx
// testcases.drivers.uart_overflow_rxb_txb
// testcases.drivers.uart_rxb_txb
// testcases.drivers.uart_rxb_txnb
// testcases.drivers.uart_rxnb_txb
// testcases.drivers.uart_rxnb_txnb
// testcases.drivers.uart_timeout_rxb_txb
static int uart_test(void)
{
rt_thread_startup(rt_thread_create("echo_test", echo_test, RT_NULL, 2048, 10, 5));
rt_thread_startup(rt_thread_create("self_test", self_tx_rx_test, RT_NULL, 2048, 10, 5));
return 0;
}
MSH_CMD_EXPORT_ALIAS(uart_test, uart_test, );