AliOS Things标准输入输出端口对接以及修改方法

本文涉及的产品
云原生多模数据库 Lindorm,多引擎 多规格 0-4节点
Lindorm AIGC体验服务,AIGC 体验服务
简介: 1 标准输入输出端口对接 标准输入输出用于输出系统日志、打印异常信息、软件调试、CLI交互等场景。在具体项目中,只需要对接PUTCHAR_PROTOTYPE和GETCHAR_PROTOTYPE两个函数即可。

1 标准输入输出端口对接

标准输入输出用于输出系统日志、打印异常信息、软件调试、CLI交互等场景。在具体项目中,只需要对接PUTCHAR_PROTOTYPE和GETCHAR_PROTOTYPE两个函数即可。其具体定义如下:

#if defined (__CC_ARM) && defined(__MICROLIB)
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#define GETCHAR_PROTOTYPE int fgetc(FILE *f)

#elif defined(__ICCARM__)
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#define GETCHAR_PROTOTYPE int fgetc(FILE *f)
#else
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
   set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#define GETCHAR_PROTOTYPE int __io_getchar(void)
#endif /* defined (__CC_ARM) && defined(__MICROLIB) */

在gcc下,对接代码示例如下:

/**
  * @brief  Retargets the C library printf function to the USART.
  * @param  None
  * @retval None
  */
PUTCHAR_PROTOTYPE
{
    if (ch == '\n') {
        hal_uart_send(&uart_0, (void *)"\r", 1, 30000);
    }
  
    hal_uart_send(&uart_0, &ch, 1, 30000);
  
    return ch;
}

/**
  * @brief  Retargets the C library scanf function to the USART.
  * @param  None
  * @retval None
  */
GETCHAR_PROTOTYPE
{
    uint8_t ch = EOF;
    int32_t ret = -1;
    uint32_t recv_size = 0;
  
    ret = hal_uart_recv_II(&uart_0, &ch, 1, &recv_size, HAL_WAIT_FOREVER);

    if ((ret == 0) && (recv_size == 1)) {
        return ch;
    } else {
        return -1;
    }
}

可以看出输入输出最终调用的是hal_uart_send 和hal_uart_recv_II这两个函数,实现这两个函数即可。在具体芯片上,需要将芯片的串口驱动对接到uart的hal接口,具体方法见https://github.com/alibaba/AliOS-Things/wiki/AliOS-Things-HAL-Porting-Guide.zh

标准输入输出串口的逻辑端口号必须为0,也就是其对应的uart_dev_t结构体的port元素必须设置为0

2 如何从其他物理端口输入输出

标准输入输出串口的逻辑端口号必须为0,并不意味着标准输入输出只能通过固定的端。因为这个0指的是逻辑端口,逻辑端口与物理端口存在一个映射关系。在一个由多个串口的芯片上,可以将port0映射到任意的串口。逻辑端口到物理端口的映射是在hal的对接代码中实现的。
以stm32平台为例,其hal_uart_send函数实现如下:

int32_t hal_uart_send(uart_dev_t *uart, const void *data, uint32_t size, uint32_t timeout)
{
    UART_HandleTypeDef *handle = NULL;
    int32_t ret = -1;

    if ((uart == NULL) || (data == NULL)) {
        return -1;
    }

    switch (uart->port) {
        case PORT_UART0:
            handle = &uart0_handle;
            break;
        case PORT_UART1:
            handle = &uart1_handle;
            break;
        case PORT_UART2:
            handle = &uart2_handle;
            break;
        /* if other uart exist add code here */
        default:
        break;
    }
   
    if (handle != NULL) {
        ret = HAL_UART_Transmit_IT(handle, (uint8_t *)data, size);
    }

    return ret;
}

其中PORT_UART0、PORT_UART1、PORT_UART2的值分别为0,1,2,代表的逻辑端口号,uart0_handle、uart1_handle、uart2_handle分别为物理端口串口0、1、2的设备句柄,上述代码中逻辑端口和物理端口是一一对应的,标准输入输出对应到了物理端口串口0.
如果要将标准输入输出端口对应到物理端口串口1,则只需要按照如下修改代码:

int32_t hal_uart_send(uart_dev_t *uart, const void *data, uint32_t size, uint32_t timeout)
{
    UART_HandleTypeDef *handle = NULL;
    int32_t ret = -1;

    if ((uart == NULL) || (data == NULL)) {
        return -1;
    }

    switch (uart->port) {
        case PORT_UART0:
            handle = &uart1_handle;
            break;
        case PORT_UART1:
            handle = &uart0_handle;
            break;
        case PORT_UART2:
            handle = &uart2_handle;
            break;
        /* if other uart exist add code here */
        default:
        break;
    }
   
    if (handle != NULL) {
        ret = HAL_UART_Transmit_IT(handle, (uint8_t *)data, size);
    }

    return ret;
}

3 注意事项

在多bin的情况下,app和kernel是分开的。标准输入输出是由用户进行初始化,也就是其对应的uart_dev_t结构体是定义在app中的,但是kernel中要进行异常输出和CLI交互等功能,也需要使用到该结构体,kernel无法获取app中的该结构体。由于kernel中只需要进行send和recive操作而不需要初始化,因此kernel中需要进行标准输入输出时,我们重新定义一个uart_dev_t结构体,将port设置为0即可。由于这个结构体不是初始化时app传入的结构体,因此这个结构体中除了port之外其他的成员都是不可用的。具体来说就是针对标准输入输出串口,在数据发送和接收函数中不要使用uart_dev_t结构体中的priv和config元素,因为这两个元素在kernel中是无效的。对于其他串口,还有其他设备,无此限制。

相关文章
|
网络协议 Linux 网络安全
Linux测试端口的连通性的四种方法
Linux测试端口的连通性的四种方法
510 0
高通平台开发系列讲解(USB篇)USB端口的说明及切换方法
高通平台开发系列讲解(USB篇)USB端口的说明及切换方法
525 0
高通平台开发系列讲解(USB篇)USB端口的说明及切换方法
|
前端开发 应用服务中间件 nginx
nginx中配置不输入端口(指定地址)访问项目的方法
nginx中配置不输入端口(指定地址)访问项目的方法
634 0
|
14天前
|
传感器 人工智能 物联网
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发,以及面临的挑战和未来趋势,旨在帮助读者深入了解并掌握这些关键技术。
36 6
|
2月前
|
运维 Linux
Linux查找占用的端口,并杀死进程的简单方法
通过上述步骤和命令,您能够迅速识别并根据实际情况管理Linux系统中占用特定端口的进程。为了获得更全面的服务器管理技巧和解决方案,提供了丰富的资源和专业服务,是您提升运维技能的理想选择。
60 1
|
2月前
|
JSON 网络协议 Linux
Shadowsocks多端口启用教程方法
【10月更文挑战第19天】Shadowsocks多端口启用教程方法
97 1
|
3月前
|
Ubuntu 应用服务中间件 网络安全
Ubuntu 22.04环境下为Odoo开启80端口的方法
通过以上步骤,你应该能够在Ubuntu 22.04环境下为Odoo开启80端口。访问你的域名时,Nginx会将请求代理到Odoo,允许你通过80端口访问Odoo应用。
105 1
|
6月前
|
域名解析 存储 缓存
HTTP请求流程概览:浏览器构建请求行含方法、URL和版本;检查缓存;解析IP与端口
【6月更文挑战第23天】 HTTP请求流程概览:浏览器构建请求行含方法、URL和版本;检查缓存;解析IP与端口;TCP连接(HTTP/1.1可能需排队);三次握手;发送请求头与体;服务器处理并返回响应;TCP连接可能关闭或保持;浏览器接收并显示响应,更新缓存。HTTP版本间有差异。
97 5
|
6月前
|
设计模式 Java 关系型数据库
Spring的配置文件,如何配置端口号,,properties,yml获取配置项等方法,外观模式及其优缺点,日志代表的信息
Spring的配置文件,如何配置端口号,,properties,yml获取配置项等方法,外观模式及其优缺点,日志代表的信息
|
6月前
IDEA同一项目启动在不同端口方法
IDEA同一项目启动在不同端口方法
1089 0