我们在上一篇已经基于Zephyr 的demo 工程添加了shell(【Zephyr】MCXN947 Zephyr 开发入门适配shell),我们基于此基础上田间shell 命令来控制板子(MCXN947-FRDM)的LED功能。查看MCXN947-FRDM原理图,板子上的RGB LED 通过P0_10/P0_27/P1_2来控制。

Zephyr 的驱动使用设备树来描述硬件信息,驱动程序和硬件信息相隔离的方式管理驱动程序,以下是mcxn947(\zephyrproject\zephyr\dts\arm\nxp\nxp_mcxn94x_common.dtsi) 共通设备树文件中对GPIO节点的描述。
gpio0: gpio@96000 {
compatible = "nxp,kinetis-gpio";
status = "disabled";
reg = <0x96000 0x1000>;
interrupts = <17 0>,<18 0>;
gpio-controller;
#gpio-cells = <2>;
nxp,kinetis-port = <&porta>;
};
gpio1: gpio@98000 {
compatible = "nxp,kinetis-gpio";
status = "disabled";
reg = <0x98000 0x1000>;
interrupts = <19 0>,<20 0>;
gpio-controller;
#gpio-cells = <2>;
nxp,kinetis-port = <&portb>;
};
gpio2: gpio@9a000 {
compatible = "nxp,kinetis-gpio";
status = "disabled";
reg = <0x9a000 0x1000>;
interrupts = <21 0>,<22 0>;
gpio-controller;
#gpio-cells = <2>;
nxp,kinetis-port = <&portc>;
};
gpio3: gpio@9c000 {
compatible = "nxp,kinetis-gpio";
status = "disabled";
reg = <0x9c000 0x1000>;
interrupts = <23 0>,<24 0>;
gpio-controller;
#gpio-cells = <2>;
nxp,kinetis-port = <&portd>;
};
gpio4: gpio@9e000 {
compatible = "nxp,kinetis-gpio";
status = "disabled";
reg = <0x9e000 0x1000>;
interrupts = <25 0>,<26 0>;
gpio-controller;
#gpio-cells = <2>;
nxp,kinetis-port = <&porte>;
};
gpio5: gpio@40000 {
compatible = "nxp,kinetis-gpio";
status = "disabled";
reg = <0x40000 0x1000>;
interrupts = <27 0>,<28 0>;
gpio-controller;
#gpio-cells = <2>;
nxp,kinetis-port = <&portf>;
};gpio 节点采用了"ip@地址" 的描述形式,默认为开启的状态,这时针对CPU级别的DTS文件,在我们使用的MCXN947 板级的DTSI文件中已经将这部分配置更新为“okay”,对应\zephyr\boards\nxp\frdm_mcxn947\frdm_mcxn947_mcxn947_cpu0.dtsi 文件中更新status 配置如下。
&gpio4 {
status = "okay";
};
&gpio1 {
status = "okay";
};
&gpio0 {
status = "okay";
};
&gpio2 {
status = "okay";
};相当于 默认frdm_mcxn947 已经开启了GPIO,添加如下代码通过gpio 驱动控制LED状态。
以下链接为官方的gpio 接口说明文档(https://docs.zephyrproject.org/apidoc/latest/group__gpio__interface.html#gabfab69282fb99be119760436f2d18a9b)
unsigned int led(char argc,char ** argv)
{
const struct device * dev;
dev = device_get_binding("gpio@96000");
if(dev)
{
printf("get device ok %p.\r\n",dev);
if(0 == strcmp(argv[1],"init"))
{
gpio_pin_configure(dev,27,GPIO_OUTPUT);
}
if(0 == strcmp(argv[1],"on"))
{
gpio_pin_set(dev,27,0);
}
if(0 == strcmp(argv[1],"off"))
{
gpio_pin_set(dev,27,1);
}
}
else
{
printf("get device failed.\r\n");
}
return 1;
}
LTSH_FUNCTION_EXPORT(led,"test shell");输入 “led init" 配置P0_27为输出引脚。
输入 led on 板子的LED 被点亮,led off LED灯熄灭。

验证完了GPIO的输出功能,我们继续验证GPIO输入功能,原理图上P0_23 连接了外部按键。

参考Zephyr 的GPIO 接口说明我们添加如下的代码配置P0_23为中断输入,触发方式为双边沿并在中断函数中添加状态打印处理。
void gpio_key_cb(const struct device *port,struct gpio_callback *cb,gpio_port_pins_t pins)
{
/* printf key status */
printf("pin status %d\r\n",gpio_pin_get(port,23));
}
/* config p023 as input */
const struct device * dev;
dev = device_get_binding("gpio@96000");
if(dev)
{
static struct gpio_callback callback;
gpio_pin_configure(dev,23,GPIO_INPUT);
/* gpio interrupt init */
callback.pin_mask = 0xffffffff;
callback.handler = gpio_key_cb;
gpio_add_callback(dev,&callback);
gpio_pin_interrupt_configure(dev,23,GPIO_INT_EDGE_BOTH);
}运行效果如下按键按下抬起会有打印输出,至此我们已经完成了Zephyr 系统下的GPIO的输入输出功能验证。

我要赚赏金
