嵌入式技术论坛
直播中

陈敏

7年用户 1294经验值
私信 关注
[问答]

RT-Thread串口终端finsh和用户自定义串口协议共用一个物理串口如何实现呢?

怎样能够让finsh调试串口和上位机通讯的串口进行共用,而不是通过输入特定指令进入通讯模式,大家做产品时都是怎么去协调的呢?

回帖(2)

王秀珍

2023-3-29 15:36:20
是因为板子串口资源不够吗?一般都会单独留出来一个串口作为控制台调试使用,如果实在不够用可以把Finsh控制台给关了,这样能多出来一个串口供用户使用,

Finsh 控制台线程的名字是 “tshell”,线程的处理函数名称为 finsh_thread_entry(),位置位于文件 rt-thread/components/finsh/shell.c 中。该线程处理函数的逻辑如下,阻塞的从串口设备中读取数据,读取到一行后从命令表中查找并执行相应的命令。

void finsh_thread_entry(void *parameter)
{
    ... ...
    while (1)
    {
        ch = (int)finsh_getchar();  // 从串口中读取数据,阻塞
        if (ch < 0)
        {
            continue;
        }
        ... ...
        /* handle end of line, break */
        if (ch == 'r' || ch == 'n')
        {
#ifdef FINSH_USING_HISTORY
            shell_push_history(shell);
#endif
            if (shell->echo_mode)
                rt_kprintf("n");
            msh_exec(shell->line, shell->line_position);    // 执行相应的命令
            rt_kprintf(FINSH_PROMPT);
            memset(shell->line, 0, sizeof(shell->line));
            shell->line_curpos = shell->line_position = 0;
            continue;
        }
        ... ...
    } /* end of device read */
}
如果非要实现用户串口和控制台串口共有的话可以考虑从这里面入手,比如说用户串口使用时有特殊的结尾字符,或者特殊的报头等情况,程序判断到特殊的报头或者报尾后执行用户的代码而不去执行相应的命令。
举报

陈敏

2023-3-29 15:36:35
感谢回复,经过一段时间的摸索,参考AT组件里面的写法,确实是可以实现的,具体重点部分代码附上:

/**
* @file app_factory_task.c
* @author your name (you@domain.com)
* @Brief
* @version 0.1
* @date 2022-03-20
*
* @copyright Copyright (c) 2022
*
*/
#define LOG_TAG                        "factory"
#define LOG_LVL                        LOG_LVL_INFO
#include
#include "app_factory_task.h"
#include
#include
#define FACTORY_ESC_KEY                0x1B
static rt_device_t console;
static struct rt_semaphore console_rx_notice;
static rt_err_t (*odev_rx_ind)(rt_device_t dev, rt_size_t size) = RT_NULL;
static rt_uint16_t odev_oflag = 0;
static char console_getchar(void)
{
    char ch;
    rt_sem_take(&console_rx_notice, RT_WAITING_FOREVER);
    return ch;
}
static void console_putchar(char ch)
{
    rt_device_write(console, 0, &ch, 1);
}
static rt_err_t console_getchar_rx_ind(rt_device_t dev, rt_size_t size)
{
    rt_uint8_t ch;
    rt_size_t i;
    for (i = 0; i < size; i++)
    {
        /* read a char */
        if (rt_device_read(dev, 0, &ch, 1))
        {
            rt_sem_release(&console_rx_notice);
        }
    }
    return RT_EOK;
}
void factory_port_init(void)
{
    rt_base_t int_lvl;
    rt_sem_init(&console_rx_notice, "factory_rx", 0, RT_IPC_FLAG_FIFO);
    int_lvl = rt_hw_interrupt_disable();
    console = rt_console_get_device();
    if (console)
    {
        /* backup RX indicate */
        odev_rx_ind = console->rx_indicate;
        odev_oflag = console->open_flag;
        console->open_flag &= ~RT_DEVICE_FLAG_STREAM;
        rt_device_set_rx_indicate(console, console_getchar_rx_ind);
    }
    rt_hw_interrupt_enable(int_lvl);
}
void factory_port_deinit(void)
{
    rt_base_t int_lvl;
    rt_device_t console;
    int_lvl = rt_hw_interrupt_disable();
    console = rt_console_get_device();
    if (console && odev_rx_ind)
    {
        /* restore RX indicate */
        console->open_flag |= RT_DEVICE_FLAG_STREAM;
        rt_device_set_rx_indicate(console, odev_rx_ind);
    }
    rt_hw_interrupt_enable(int_lvl);
    rt_sem_detach(&console_rx_notice);
}
static void factory_cfg(int argc, char **argv)
{
    char ch;
    factory_port_init();
    rt_kprintf("======== Start to factory mode to config board ========n");
    rt_kprintf("Config software will control console. Press 'ESC' to exit.n");
    /* process user input */
    while (FACTORY_ESC_KEY != (ch = console_getchar()))
    {
        //TO DO parse the protocol for upper software
        console_putchar(ch);
    }
    factory_port_deinit();
}
MSH_CMD_EXPORT(factory_cfg, Factory mode to config board);
MSH_CMD_EXPORT_ALIAS(factory_cfg, P0, Factory mode to config board);
举报

更多回帖

发帖
×
20
完善资料,
赚取积分