Rockchip系列之LED状态灯 CAN收发数据流程以及控制状态显示(4)

简介: Rockchip系列之LED状态灯 CAN收发数据流程以及控制状态显示(4)

在前几篇文章中,介绍了如何在Rockchip RK3568平台上使用LED状态灯,以及如何通过设备树和内核驱动来控制它们。在本文中,将进一步介绍如何在内核驱动中添加一些功能,使得LED状态灯能够根据CAN的收发数据的情况来变化,从而显示CAN的活动状态。

逻辑分析

要实现这个功能,需要修改内核驱动中的两个函数:rockchip_can_start_xmit和rockchip_can_rx。这两个函数分别负责处理CAN的发送和接收数据的操作。需要在这两个函数中添加一些代码,来记录每次发送或接收数据的设备名,并根据设备名来控制LED状态灯的亮灭。还需要引入一个外部函数led_control_set_leds_by_str,来方便地设置LED状态灯的状态。

以kernel/drivers/net/can/rockchip/rockchip_can.c为例,看看如何修改这两个函数:

+++ b/kernel/drivers/net/can/rockchip/rockchip_can.c
@@ -19,6 +19,7 @@
 #include <linux/pm_runtime.h>
 
 #define DRV_NAME               "rockchip_can"
+extern int led_control_set_leds_by_str(const char *buf);
 
 #define CAN_MODE               0x00
 #define RESET_MODE             0
@@ -281,6 +282,32 @@ static int rockchip_can_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        u32 fi;
        u32 data1 = 0, data2 = 0;
 
+       char led_ctrl_str[16];
+        // 添加一个变量来保存当前的设备名
+        const char *dev_name = ndev->name; 
+       // 在发送数据帧之前打印设备名和 CAN ID
+       printk("%s: sending frame with ID \n", ndev->name);
+
+       // 根据设备名来执行不同的操作
+        switch (dev_name[3]) {
+        case '0':
+                snprintf(led_ctrl_str, sizeof(led_ctrl_str), "%d %d %d", 3, 0, 0);
+                led_control_set_leds_by_str(led_ctrl_str);
+                mdelay(10);//msleep(100); // 延时 1 秒
+                snprintf(led_ctrl_str, sizeof(led_ctrl_str), "%d %d %d", 3, 0, 1);
+                led_control_set_leds_by_str(led_ctrl_str);
+                break;
+        case '1':
+                snprintf(led_ctrl_str, sizeof(led_ctrl_str), "%d %d %d", 4, 0, 0);
+                led_control_set_leds_by_str(led_ctrl_str);
+                mdelay(10);//msleep(100); // 延时 1 秒
+                snprintf(led_ctrl_str, sizeof(led_ctrl_str), "%d %d %d", 4, 0, 1);
+                led_control_set_leds_by_str(led_ctrl_str);
+                break;
+        default:
+                // 其他设备名不做任何操作
+                break;
+        }
        if (can_dropped_invalid_skb(ndev, skb))
                return NETDEV_TX_OK;
 
@@ -327,6 +354,33 @@ static void rockchip_can_rx(struct net_device *ndev)
        canid_t id;
        u8 fi;
        u32 data1 = 0, data2 = 0;
+       char led_ctrl_str[16];
+        // 添加一个变量来保存当前的设备名
+        const char *dev_name = ndev->name;
+       // 在接收数据帧之后打印设备名和 CAN ID
+        printk("%s: received frame with ID \n", ndev->name);
+
+       // 根据设备名来执行不同的操作
+        switch (dev_name[3]) {
+        case '0':
+                snprintf(led_ctrl_str, sizeof(led_ctrl_str), "%d %d %d", 3, 1, 0);
+                led_control_set_leds_by_str(led_ctrl_str);
+                mdelay(10);//msleep(100); // 延时 1 秒
+                snprintf(led_ctrl_str, sizeof(led_ctrl_str), "%d %d %d", 3, 1, 1);
+                led_control_set_leds_by_str(led_ctrl_str);
+                break;
+        case '1':
+                snprintf(led_ctrl_str, sizeof(led_ctrl_str), "%d %d %d", 4, 1, 0);
+                led_control_set_leds_by_str(led_ctrl_str);
+                mdelay(10);//msleep(100); // 延时 1 秒
+                snprintf(led_ctrl_str, sizeof(led_ctrl_str), "%d %d %d", 4, 1, 1);
+                led_control_set_leds_by_str(led_ctrl_str);
+                break;
+        default:
+                // 其他设备名不做任何操作
+                break;
+        }
+
 
        /* create zero'ed CAN frame buffer */
        skb = alloc_can_skb(ndev, &cf);

简单的代码分析:

  • 在文件开头引入了一个外部函数led_control_set_leds_by_str,用来设置LED状态灯的状态,该函数的定义在kernel/drivers/leds/led_control.c中。
  • (重点)在rockchip_can_start_xmit函数中,在发送数据帧之前,定义一个字符数组led_ctrl_str,用来存放LED状态灯的控制字符串。
  • 获取当前的设备名,并打印一条日志信息,显示发送的CAN ID。
  • 根据设备名的第四个字符(即canx中的x)来执行不同的操作。如果是'0',表示是can0设备,那么就设置第3组LED的红色为关闭(即亮起),延时10毫秒,再设置为打开(即灭掉)。如果是'1',表示是can1设备,那么就设置第4组LED的红色为关闭(即亮起),延时10毫秒,再设置为打开(即灭掉)。如果是其他字符,那么就不做任何操作。这样就实现了每次发送数据帧时,对应的LED会闪烁一下的效果。
  • (重点)在rockchip_can_rx函数中,在接收数据帧之后,定义一个字符数组led_ctrl_str,用来存放LED状态灯的控制字符串。
  • 获取当前的设备名,并打印一条日志信息,显示接收的CAN ID。
  • 根据设备名的第四个字符(即canx中的x)来执行不同的操作。如果是'0',表示是can0设备,那么就设置第3组LED的绿色为关闭(即亮起),延时10毫秒,再设置为打开(即灭掉)。如果是'1',表示是can1设备,那么就设置第4组LED的绿色为关闭(即亮起),延时10毫秒,再设置为打开(即灭掉)。如果是其他字符,那么就不做任何操作。这样就实现了每次接收数据帧时,对应的LED会闪烁一下的效果。(上面一样的)

测试效果

要测试这个功能,需要在RK3568平台上编译并加载修改后的内核驱动。然后可以使用cansend或其他CAN工具来发送或接收数据帧,观察LED状态灯的变化。例如,可以在RK3568平台上执行以下命令:

ip link set can0 down && ip link set can0 type can bitrate 50000 && ip link set can0 up   
 
ip link set can1 down && ip link set can1 type can bitrate 50000 && ip link set can1 up   
 
candump can0 & 
 
cansend can0 123#1122334455667788 

(我这里是回环测试can0对接can1,实际应用也是如此)通过上面的命令这样就会向can0设备发送一个CAN ID为0x123,数据为0x1122334455667788的数据帧。可以看到,每次发送数据帧时,对应的LED状态灯会闪烁一下,表示CAN的活动状态。

总结

本文介绍了如何在内核驱动中添加一些功能,使得LED状态灯能够根据CAN的收发数据的情况来变化,从而显示CAN的活动状态。修改了内核驱动中的rockchip_can_start_xmit和rockchip_can_rx函数,添加了一些代码,来记录每次发送或接收数据的设备名,并根据设备名来控制LED状态灯的亮灭。还引入了一个外部函数led_control_set_leds_by_str,来方便地设置LED状态灯的状态。

希望本文对你有所帮助。如果你有任何问题,请在评论区留言。谢谢!

相关文章
|
2月前
Rockchip系列之LED状态灯 串口收发数据流程以及控制状态显示(3)
Rockchip系列之LED状态灯 串口收发数据流程以及控制状态显示(3)
38 0
|
10月前
|
算法 芯片 异构计算
通过FPGA实现基于RS232串口的指令发送并控制显示器中目标位置
通过FPGA实现基于RS232串口的指令发送并控制显示器中目标位置
|
2月前
|
Linux
Rockchip系列之LED状态灯 以太网收发数据包流程以及控制状态显示(2)
Rockchip系列之LED状态灯 以太网收发数据包流程以及控制状态显示(2)
22 1
|
2月前
|
C语言
独立按键控制LED亮灭、独立按键控制LED状态、独立按键控制LED显示二进制、独立按键控制LED移位——“51单片机”
独立按键控制LED亮灭、独立按键控制LED状态、独立按键控制LED显示二进制、独立按键控制LED移位——“51单片机”
|
12月前
51单片机--利用独立按键控制LED
51单片机--利用独立按键控制LED
222 0
|
异构计算
实验二 基于FPGA的分频器的设计(基本任务:设计一个分频器,输入信号50MHz,输出信号频率分别为1KHz、500Hz及1Hz。拓展任务1:用按键或开关控制蜂鸣器的响与不响。拓展任务2:用按键或开)
实验二 基于FPGA的分频器的设计(基本任务:设计一个分频器,输入信号50MHz,输出信号频率分别为1KHz、500Hz及1Hz。拓展任务1:用按键或开关控制蜂鸣器的响与不响。拓展任务2:用按键或开)
1097 0
实验二 基于FPGA的分频器的设计(基本任务:设计一个分频器,输入信号50MHz,输出信号频率分别为1KHz、500Hz及1Hz。拓展任务1:用按键或开关控制蜂鸣器的响与不响。拓展任务2:用按键或开)
|
传感器 存储 物联网
Zigbee 自定义任务处理按键和双串口数据|学习笔记
快速学习Zigbee 自定义任务处理按键和双串口数据
164 0
Zigbee 自定义任务处理按键和双串口数据|学习笔记
独立按键控制LED亮灭及状态
独立按键控制LED亮灭及状态
220 0
|
C语言
【51单片机】独立按键控制LED灯(四种形式)
轻触按键:相当于是一种电子开关,按下时开关接通,松开时开关断开,实现原理是通过轻触按键内部的金属弹片受力弹动来实现接通和断开。 英文:independent press button
1127 0
【51单片机】独立按键控制LED灯(四种形式)
接收PC端的信息控制LED灯(中断法)
接收PC端的信息控制LED灯(中断法) 宏定义 初始化 中断 主函数
133 0