拿到RA工作室寄过来的RA-Eco-RA6E2-64PIN-V1.0 开发板已经两周多了,之前陆陆续续的写过几篇测评,今天我们写写有关zephyr实时操作系统的测评。
Zephyr 是 Linux 基金会托管、开源、模块化、安全导向的实时操作系统(RTOS),专为资源受限的嵌入式设备设计,也可扩展到多核 SoC。一句话:“像 Linux 一样开发,像 RTOS 一样运行。”
zephyr的详细介绍可以查看官网https://docs.zephyrproject.org/4.2.0/introduction/index.html
官网上也有详细的开发环境的介绍,我是用的vscode插件的形式。安装方法见https://bbs.21ic.com/icview-3492711-1-1.html。
下面我们来进入正题,安装好环境的vscode如下:

一、板卡适配
由于zephyr社区团体的强大存在,已经适配了很多板子,所以我们也不需要从头到尾的去做这部分工作,只需要找到一款和RA-Eco-RA6E2-64PIN-V1.0 开发板相近的板子作为模板,在此基础上进行修改。支持的板卡类型可以通过官网查找https://docs.zephyrproject.org/latest/boards/index.html#boards=
或者通过源码boards文件夹里进行查看,如下图

在renesas文件夹里可以看到有很多的板子,我们找了和当前开发板 相似的板子如下:

我们随便复制一份,改名为eco-ra6e2然后将里面的文件需要全部重命名,如下:

配置文件里需要修改的内容不多,其中doc里的文件无关紧要,不需要考虑。board.cmake文件于下载及debug工具相关,默认的是jlink,这里也保持默认。由于我复制的是ek_ra6e2,所以就是将其他的配置文件有关ek的内容修改成eco就行了。如下:




到这里板卡基本也就适配完成,但是由于ek_ra6e2板子的串口、led、按键等外设引脚和RA-Eco-RA6E2-64PIN-V1.0 开发板存在差异,所以我们要对其设备树文件进行修改,根据原理图修改如下:






到这里才完成了适配并且可以满足将今天要测试的功能。
二、工程创建及下载观看效果
创建工程的步骤参考如下的文章
https://bbs.21ic.com/icview-3493132-1-1.html
需要注意的是选择板卡类型是要选择刚刚自己添加的板卡名称eco-ra6e2。
根据如下步骤操作下来基本上就可以看见板卡的q其中一个led在闪烁了。串口打印信息如下:

三、应用程序分析
上面的初步效果已经看到了,接下来我们分析一下应用程序是如何实现的。程序在如下位置:

从图上可见程序代码并不多,我们进行讲解
#include <stdio.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
头文件包含,主要就是zephyr相关的基础头文件。
#define SLEEP_TIME_MS 1000
宏定义,led闪烁的周期,改大数值就闪的慢一点,改小就闪的快一点。
#define LED0_NODE DT_ALIAS(led0)
这是一个宏函数,用于从设备树获取led0节点信息,接下来对led0的属性的获取。
static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
根据节点获取到led0的属性。接下来就可以根据这个属性来操作led0的初始化、高低电平控制了。

代码还是比较简洁的,整体代码如下:
#include <stdio.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
#define SLEEP_TIME_MS 1000
#define LED0_NODE DT_ALIAS(led0)
static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
int main(void)
{
int ret;
bool led_state = true;
if (!gpio_is_ready_dt(&led)) {
return 0;
}
ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
if (ret < 0) {
return 0;
}
while (1) {
ret = gpio_pin_toggle_dt(&led);
if (ret < 0) {
return 0;
}
led_state = !led_state;
printf("LED state: %s\\n", led_state ? "ON" : "OFF");
k_msleep(SLEEP_TIME_MS);
}
return 0;
}
到此,也就将这个简单的例程讲解完了,但是我不是很满足,明明有两个led,怎么能指点了一个,我要将另外一个也点亮。实现的代码如下:
#include <stdio.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
#define SLEEP_TIME_MS 500
#define LED0_NODE DT_ALIAS(led0)
#define LED1_NODE DT_ALIAS(led1)
#if !DT_NODE_HAS_STATUS_OKAY(LED0_NODE)
#error "Unsupported board: led0 devicetree alias is not defined"
#endif
#if !DT_NODE_HAS_STATUS_OKAY(LED1_NODE)
#error "Unsupported board: led1 devicetree alias is not defined"
#endif
static const struct gpio_dt_spec led[] = {GPIO_DT_SPEC_GET(LED0_NODE, gpios)
,GPIO_DT_SPEC_GET(LED1_NODE, gpios)};
int main(void)
{
int ret;
bool led_state[] = {true,true};
if (!gpio_is_ready_dt(&led[0])) {
return 0;
}
if (!gpio_is_ready_dt(&led[1])) {
return 0;
}
ret = gpio_pin_configure_dt(&led[0], GPIO_OUTPUT_ACTIVE);
if (ret < 0) {
return 0;
}
ret = gpio_pin_configure_dt(&led[1], GPIO_OUTPUT_ACTIVE);
if (ret < 0) {
return 0;
}
while (1) {
for (size_t i = 0; i < sizeof(led)/sizeof(struct gpio_dt_spec); i++) {
ret = gpio_pin_toggle_dt(&led[i]);
if (ret < 0) {
return 0;
}
led_state[i] = !led_state[i];
printf("LED[%d] state: %s\\n",i, led_state[i] ? "ON" : "OFF");
}
k_msleep(SLEEP_TIME_MS);
}
return 0;
}
细心的朋友可能发现和原来例程的代码有点不同,增加了
#if !DT_NODE_HAS_STATUS_OKAY(LED0_NODE)
#error "Unsupported board: led0 devicetree alias is not defined"
#endif
#if !DT_NODE_HAS_STATUS_OKAY(LED1_NODE)
#error "Unsupported board: led1 devicetree alias is not defined"
#endif
这里就可以在编译时就发现设备树中有没有相对应得节点描述,我们屏蔽掉led1节点,试一下编译发现抱错如下:

编译好的程序下载进MCU中观察效果,详细开头视频。
不过两个led试同时同周期得闪烁,改一下程序让其不同周期得闪烁。代码如下:
#include <stdio.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
#define SLEEP_TIME_MS 500
#define LED0_NODE DT_ALIAS(led0)
#define LED1_NODE DT_ALIAS(led1)
#if !DT_NODE_HAS_STATUS_OKAY(LED0_NODE)
#error "Unsupported board: led0 devicetree alias is not defined"
#endif
#if !DT_NODE_HAS_STATUS_OKAY(LED1_NODE)
#error "Unsupported board: led1 devicetree alias is not defined"
#endif
static const struct gpio_dt_spec led[] = {GPIO_DT_SPEC_GET(LED0_NODE, gpios)
,GPIO_DT_SPEC_GET(LED1_NODE, gpios)};
int main(void)
{
int ret;
bool led_state[] = {true,true};
uint16_t led_period_target[] = {200,300};
uint16_t led_period_cur[] = {0,0};
if (!gpio_is_ready_dt(&led[0])) {
return 0;
}
if (!gpio_is_ready_dt(&led[1])) {
return 0;
}
ret = gpio_pin_configure_dt(&led[0], GPIO_OUTPUT_ACTIVE);
if (ret < 0) {
return 0;
}
ret = gpio_pin_configure_dt(&led[1], GPIO_OUTPUT_ACTIVE);
if (ret < 0) {
return 0;
}
while (1) {
for (size_t i = 0; i < sizeof(led)/sizeof(struct gpio_dt_spec); i++) {
if (led_period_cur[i]++ >= led_period_target[i]) {
led_period_cur[i] = 0;
ret = gpio_pin_toggle_dt(&led[i]);
if (ret < 0) {
return 0;
}
led_state[i] = !led_state[i];
printf("LED[%d] state: %s\\n",i, led_state[i] ? "ON" : "OFF");
}
}
k_msleep(1);
}
return 0;
}
至此,今天得评测也就完成了,后面会更新更多zephyr其他功能得评测功能,尽请期待。