F1C200S闪烁LED(基于Pinctrl子系统)

本文详细介绍了如何在F1C200S板子上通过修改设备树和编写驱动程序使LEDPD13亮起,包括硬件配置、设备树节点添加、GPIO设置以及驱动代码实现。
摘要由CSDN通过智能技术生成

 最近无聊将以前没做完的板子拿出来玩了一下,发现开发方面f1c200s和i.mx6ull还是有些细微的差别。话不多说,下面开始讲解如何让板子上的LED亮起来(从32点灯大师转行)。

我的led引脚是PD13且低电平有效。

 

okay,硬件确定好,接下来是修改设备树,我使用的是荔枝Pi的内核

打开内核目录,如下路径找到dts文件,ach/arm/boot/dts/suniv-f1c100s-licheepi-nano.dts,添加设备节点。这里我的绝对路径为 /home/wmp/linux/lc_core/Linux/arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dts

/ {
	model = "Lichee Pi Nano";
	compatible = "licheepi,licheepi-nano", "allwinner,suniv-f1c100s",
		     "allwinner,suniv";
		
led{
	compatible = "wmp,led-PD13";
	pinctrl-names = "default";
	pinctrl-0 = <&led_pins>;
    led-pin = <&pio 3 13 GPIO_ACTIVE_LOW>;
	status = "okay";
	
};
.......

pinctrl-0后面再说,先说led-pin,其中描述了PD13的信息,3代表PD13中的D具体对应如下

A-0
B-1
C-2
D-3
E-4

其中13为IO号,也就是PD13中的13,如果是PD12则为12

GPIO_ACTIVE_LOW为低电平有效

其余的均根据实际定义

然后打开ach/arm/boot/dts/suniv.dtsi,在pio节点下添加自己的节点


		pio: pinctrl@1c20800 {
			compatible = "allwinner,suniv-pinctrl";
			reg = <0x01c20800 0x400>;
			interrupts = <38>, <39>, <40>;
			clocks = <&ccu CLK_BUS_PIO>, <&osc24M>, <&osc32k>;
			clock-names = "apb", "hosc", "losc";
			gpio-controller;
			interrupt-controller;
			#interrupt-cells = <3>;
			#gpio-cells = <3>;

			spi0_pins_a: spi0-pins-pc {
				//pins = "PC0", "PC1", "PC2", "PC3";
				pins = "PD18", "PD19", "PD20", "PD21";
				function = "spi0";
			};
			led_pins: led-pins{
				pins = "PD13";
				function = "gpio_out";
			};
            ...

在dts文件的pinctrl-0便是引用该文件的led节点,这里function不能随意修改,如果要修改的话,需要到对应c文件添加自定义功能,具体这里不再赘述,修改完成后保存并重新编译设备树

我已经在内核的Makefile中添加了编译器信息,因此直接用如下指令编译

make dtbs

编译完成后将dtb文件保存到SD卡对应分区中

如此一来,设备树修改完成,接下来便是编写驱动代码

下面是具体驱动代码

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/timer.h>

#define MINOR               10              //次设备号
#define LED_BLINK_TIME      1000            //定时器中断出发时间 单位:ms
#define DEVICE_NAME         "led"           //设备名称
#define DTB_COMPATIABLE     "wmp,led-PD13"  //设备树led节点下的compatible属性



static int led_probe(struct platform_device * dev);
static int led_remove(struct platform_device * dev);
static void led_blink(struct timer_list *unused);

/*定义用户设备结构体*/
typedef struct{
    struct device_node *nd;
    int gpio_num;
    struct timer_list timer;
}gpio_dev_t;
gpio_dev_t led = {0};
/*定义杂项设备结构体*/
struct miscdevice led_misc={
    .minor = MINOR,
    .name = DEVICE_NAME,
};
/*定义平台驱动匹配表*/
struct of_device_id led_table[]={
    {.compatible = DTB_COMPATIABLE},
};
/*定义平台设备驱动结构体*/
struct platform_driver platform_led={
    .driver={
        .name = DEVICE_NAME,
        .of_match_table = led_table,
    },
    .probe = led_probe,
    .remove = led_remove,
};
/*probe函数*/
static int led_probe(struct platform_device * dev)
{
    printk("led probe\r\n");
    led.nd = dev->dev.of_node;//获取设备节点
    led.gpio_num = of_get_named_gpio(led.nd,"led-pin",0);//获取gpio号
    gpio_request(led.gpio_num,"led-pin");//请求gpio资源
    gpio_direction_output(led.gpio_num,1);//设置gpio为输出
    timer_setup(&led.timer, led_blink, 0);//初始化定时器
    led.timer.expires = jiffies_64+msecs_to_jiffies(LED_BLINK_TIME);//设置超时时间
    add_timer(&led.timer);//向内核添加定时器并开始计时
    misc_register(&led_misc);//注册杂项设备
    return 0;
}
/*remove函数*/
static int led_remove(struct platform_device * dev)
{
    printk("led remove\r\n");
    del_timer(&led.timer);//向内核注销定时器
    gpio_set_value(led.gpio_num,1);//关灯
    gpio_free(led.gpio_num);//释放gpio
    misc_deregister(&led_misc);//注销杂项设备
     return 0;
}
/*模块初始化函数*/
static int __init led_init(void)
{
     printk("module init\r\n");
    return platform_driver_register(&platform_led); 
}
/*模块退出出函数*/
static void __exit led_exit(void)
{
     printk("module exit\r\n");
     platform_driver_unregister(&platform_led); 
}

/*定时器超时函数*/
static void led_blink(struct timer_list *unused)
{
    static unsigned char i;
    if((++i)%2==1)
    {
        printk("led on!\r\n");
        gpio_set_value(led.gpio_num,0);
    }else{
        printk("led off!\r\n");
        gpio_set_value(led.gpio_num,1);
        i=0;
    }
    led.timer.expires = jiffies_64+msecs_to_jiffies(LED_BLINK_TIME);//更新定时器超时时间
    add_timer(&led.timer);//启动定时器
}


module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("wmp");

 根据自己的需求修改

接下来编译模块

make

将生成的文件保存到SD卡对应分区如下目录 /lib/modules/4.15.0-rc8-licheepi-nano+/

这一步还没完,还需要在内核当中复制两个依赖文件到上述目录下用于加载模块

接下来便可以使用模块

depmod生成加载模块的依赖文件

modprobe led 加载模块

出现了led闪烁的打印信息说明模块加载成功!!!

如果实在不放心可以使用lsmod查看模块加载情况

使用ls /dev/ 查看设备是否挂载

这下确信模块加载成功,使用rmmod led即可删除该设备。

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值