【RA-Eco-RA2L1开发板评测】基于 FSP 实现串口打印功能

以下内容为本人的烂笔头,如需要转载,请全文无改动地复制粘贴,原文链接 「ENG八戒」https://mp.weixin.qq.com/s/flGxC-5658gWQM-bclRT1g

一、前言

在上一篇文章中,我们完成了 RA-Eco-RA2L1 开发板的软件开发环境搭建、工程创建以及程序烧录验证,成功打通了从工程创建到程序运行的完整开发链路。

对于嵌入式开发而言,串口几乎是最重要的调试手段之一。无论是系统初始化、状态输出还是问题定位,都离不开串口日志。

本篇将基于上一篇创建的工程,体验瑞萨 FSP(Flexible Software Package)的外设开发流程,实现 UART 串口打印功能,并构建类似 printf() 的日志输出接口,为后续外设开发和调试打下基础。


二、FSP 串口驱动简介

RA 系列 MCU 的串口驱动由 FSP 提供统一封装。

在 FSP 中,串口驱动主要包含:

  • 控制块(Control Block)
  • 配置结构体(Configuration)
  • 回调函数(Callback)
  • API 接口

工程生成后,并不会直接生成对应外设或者硬件的对象,需要在配置界面按需添加外设,才可以看到类似如下的对象:

bash 复制代码
g_uart0_ctrl
g_uart0_cfg

其中:

bash 复制代码
R_SCI_UART_Open()

用于初始化串口。

bash 复制代码
R_SCI_UART_Write()

用于发送数据。

bash 复制代码
R_SCI_UART_Read()

用于接收数据。

相比直接操作寄存器,FSP 已经完成了底层驱动封装,开发者只需要关注应用逻辑即可。


三、FSP 配置 UART

在 e² studio 中打开:

bash 复制代码
configuration.xml

进入 FSP Configuration 界面。

如上图,添加一个 UART 驱动实例:

bash 复制代码
Stacks
 └── New Stack
  └── Connectiviy
   └── UART(r_sci_uart)

添加完成后,点击 "Stacks" 标签页的外设,进入底部属性栏:

属性配置如下:

参数 配置值
Name g_uart0
Channel 0
Baudrate 115200
Data Bits 8
Stop Bits 1
Parity None
Callback user_uart_callback
其它 默认

对应 IO 口还需要跳转到 FSP Configuration 界面窗口 Pins 标签页配置,可直接点击上图中属性栏 "Pins" -> "RXD0"/"TXD0" 右则的跳转箭头进行跳转(在双击 "RXD0"/"TXD0" 后出现跳转箭头):

找到 "Pin Configuration" -> "Pin Function" -> "Operation Mode",选择 "Asynchronous UART"。

至此,UART 配置完成。

FSP 会自动生成对应代码:

bash 复制代码
g_uart0_ctrl
g_uart0_cfg

开发者无需手动编写初始化代码。


四、实现 UART 回调函数

如上配置,FSP 的 UART 发送采用异步机制。

因此需要通过回调函数 user_uart_callback 获取发送完成事件。

添加代码如下:

bash 复制代码
static volatile bool uart_send_complete_flag = false;

void user_uart_callback(uart_callback_args_t * p_args)
{
    if (UART_EVENT_TX_COMPLETE == p_args->event)
    {
        uart_send_complete_flag = true;
    }
}

当底层发送完成后,FSP 会自动调用该函数。

随后通知应用层当前发送已经结束。

这种分层的设计方式避免了应用层直接访问底层硬件状态,提高了代码的可移植性。


五、封装串口发送接口

为了简化后续开发,首先封装一个统一发送函数。

bash 复制代码
static void uart_send(const uint8_t * data,
                      uint32_t len)
{
    if ((NULL == data) || (0 == len))
    {
        return;
    }

    err = R_SCI_UART_Write(&g_uart0_ctrl,
                           (uint8_t *)data,
                           len);

    if (FSP_SUCCESS != err)
    {
        __BKPT(0);
    }

    while (!uart_send_complete_flag)
    {
    }

    uart_send_complete_flag = false;
}

这里采用了最简单的同步等待方式:

  1. 发起发送
  2. 等待发送完成回调
  3. 返回调用者

对于调试日志这种场景来说,这种方式简单且稳定。


六、实现 UART_PRINT

有了发送接口之后,就可以进一步封装类似 printf() 的日志输出功能。

实现代码如下:

bash 复制代码
static void UART_PRINT(const char * fmt, ...)
{
    char buffer[256];

    va_list args;

    va_start(args, fmt);

    vsnprintf(buffer,
              sizeof(buffer),
              fmt,
              args);

    va_end(args);

    uart_send((uint8_t *)buffer,
              strlen(buffer));
}

这里利用:

bash 复制代码
vsnprintf()

将格式化字符串写入缓存。

随后调用:

bash 复制代码
uart_send()

将缓存数据输出到串口,完成发送。

这样后续调试时即可直接使用:

bash 复制代码
UART_PRINT("value=%d\r\n", value);

输出串口日志。

开发体验与 PC 平台下的 printf() 非常接近。


七、应用程序实现

进入 hal_entry() 时,先对 UART 初始化。

bash 复制代码
err = R_SCI_UART_Open(&g_uart0_ctrl,
                      &g_uart0_cfg);

if (FSP_SUCCESS != err)
{
    __BKPT(0);
}

有调试器连接时,如果初始化失败,运行到这里自动断住。没有调试器连接,则可能触发 HardFault 或者 UsageFault。

初始化成功后输出启动信息:

bash 复制代码
UART_PRINT("\r\n");
UART_PRINT("=====================================\r\n");
UART_PRINT("RA2L1 UART Demo\r\n");
UART_PRINT("e2studio + FSP 6.4 + LLVM\r\n");
UART_PRINT("=====================================\r\n");

随后周期性输出测试数据:

bash 复制代码
int int_i = 55;
float float_i = 66.2f;
char str[] = "hello e2studio";

循环打印:

bash 复制代码
while (1)
{
    UART_PRINT("int_i   = %d\r\n", int_i);
    UART_PRINT("float_i = %.2f\r\n", float_i);
    UART_PRINT("str     = %s\r\n", str);

    UART_PRINT("-------------------------------------\r\n");

    int_i++;

    R_BSP_SoftwareDelay(
        1000,
        BSP_DELAY_UNITS_MILLISECONDS);
}

这样既验证了:

  • 整数格式化输出
  • 浮点格式化输出
  • 字符串格式化输出

也验证了 UART 发送功能工作正常。

点击工具栏的 "构建" 图标,或者菜单栏选择 "项目" -> "构建项目" 来执行工程构建。

编译成功。


八、运行效果验证

对照前面的 IO 口配置,通过 "USB 转 TTL 模块" 连接电脑 USB 和开发板。

连接完成,确保电脑端能成功识别串口设备。

打开电脑串口调试助手,配置如下:

参数 配置
波特率 115200
数据位 8
停止位 1
校验位 None

打开串口终端后,可以看到如下输出:

开发板上有红色的复位(RESET)按钮,点击可重启设备。

从输出结果可以看到:

  • UART 初始化正常
  • 格式化输出正常
  • 浮点打印正常
  • 周期发送稳定

整个串口打印功能已经成功运行。


九、开发体验分析

通过本次 UART 实践,可以初步体验到 FSP 的开发模式。

优点

  • 图形化配置方便
  • 驱动初始化简单
  • API 接口统一
  • 代码结构清晰
  • 适合快速开发

可以优化的地方

当前实现采用:

bash 复制代码
发送 -> 等待完成 -> 返回

属于阻塞式发送。

后续可以尝试:

  • 环形缓冲区
  • DMA 发送
  • RTOS 消息队列

进一步提高日志输出效率。

对于当前评测阶段而言,已经完全满足调试需求。


十、总结

本篇基于 RA-Eco-RA2L1 开发板和 FSP 框架,实现了 UART 串口打印功能,并封装了类似 printf() 的日志输出接口。

通过实际开发体验可以发现,FSP 已经对底层驱动进行了较好的封装,开发者无需直接操作寄存器即可快速完成外设开发。相比传统 MCU 开发模式,开发效率有明显提升,同时避免了寄存器的错误操作。

至此,开发环境搭建、工程创建、程序下载以及串口日志功能均已验证完成。

后续评测将继续体验板载更多功能,进一步熟悉 RA2L1 的开发流程和外设能力。

相关推荐
嵌入式ZYXC1 小时前
第2篇:《面试题:LDO和DC-DC的区别?分别用在什么场景?》
stm32·单片机·嵌入式硬件·面试·职场和发展
HAPPY酷2 小时前
单片机OLED进阶:打造赛博朋克风“碎片化消散”文字特效
单片机·嵌入式硬件·microsoft
czhaii2 小时前
GB2312简体中文编码表
单片机·算法
玩转单片机与嵌入式2 小时前
AI 推理会不会堵住实时任务?MCU 上跑模型时,RTOS 和 DMA 该怎么配合?
人工智能·单片机·嵌入式硬件
清风6666662 小时前
基于单片机的超声波人体感应PWM自动调光灯设计与实现
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
fffzd2 小时前
STM32:IIC与温湿度传感器(轮询模式)
stm32·单片机·嵌入式硬件·iic·通信·嵌入式软件·i2c
项目題供诗2 小时前
STM32-编码器接口测速(十七)
stm32·单片机·嵌入式硬件
嵌入式小站2 小时前
STM32 零基础可移植教程 19:I2C 读写寄存器,先读一个设备 ID
stm32·单片机·嵌入式硬件
minglie13 小时前
zynq用普通网口在局域网同步
单片机