100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > LED驱动—基于OpenWRT

LED驱动—基于OpenWRT

时间:2021-10-19 19:58:20

相关推荐

LED驱动—基于OpenWRT

声明:本文只个人在初学驱动时做的笔记,适用于初学习开发者学习使用,了解如何查看和使用寄存器。在正真使用过程只要在设备树文件中配置LED相应部分即可,非常简单。

CPU平台:MT7621

LED控制引脚: GPIO15

一、寄存器控制查询

1、复位引脚转换

查看mt7621指南手册,在 “GPIO pin mapping” 中可以查看到 GPIO15为复位引脚,function 0为JTMS功能,function 1为GPIO功能。

查看 MT7621A_Datasheet文档中的 “GPIO pin share scheme” 可知,引脚GPIO15默认是处于JTAG组中的JTMS功能。

由于 LED的控制是属于GPIO out的控制,因此需要将GPIO15设置为GPIO模式。查看指南手册中的 “SYSCTL Base address” 部分,可以查看到 “GPIO MODE” 的地址为 “1E000060”。

继续查看 GPIO MODE的详情部分,由于GPIO15是属于JTAG组的,因此找到 JTAG_MODE 部分的功能切换,由下表可知JTAG模式转换是位于GPIO_MODE的第7位,该位值为0表示JTAG模式,值1表示GPIO模式。因此若要让GPIO15处于GPIO模式,则需要将寄存器地址 “1E000060”对应的bit7置为1。

2、设置GPIO方向

查看 “GPIO Base address” 表可知,GPIO1~GPIO31 direction control register 对应的地址为“1E000600”。查看对应的控制列表,可知寄存器值对应的gpio口相应bit值为0代表 input,1为 output模式。这里需要将 bit15的值置为1。

3、设置GPIO输出的值

查看 “GPIO Base address” 表可知,GPIO1~GPIO31 data register 对应的地址为“1E000620”。查看对应的控制列表,可知GPIO15对应位为该地址值的bit15。

二、LED驱动代码

【gpio-ctrl-led.c】#include <linux/errno.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/cdev.h>#include <linux/fs.h>#include <linux/uaccess.h>#include <linux/ioport.h>#include <linux/io.h>#include <linux/device.h>#include <linux/vmalloc.h>#define GPIO_MODE_ADDR0xbe000060#define GPIO_DIR_ADDR0xbe000600#define GPIO_DATA_ADDR0xbe000620unsigned int value;static long lfz_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg){switch(cmd){case 0:value = readl(GPIO_DATA_ADDR);value &= ~(0x1 << 15);writel(value, GPIO_DATA_ADDR);printk("---------> goio down\n");break;case 1:value = readl(GPIO_DATA_ADDR);value |= (0x1 << 15);writel(value, GPIO_DATA_ADDR);printk("---------> goio up\n");break;default:break;}return 0;}static const struct file_operations test_fops={.owner= THIS_MODULE,// 代表改驱动适用于本内核.unlocked_ioctl = lfz_unlocked_ioctl,};static void led_init(void){// 这边使用方式1/2/3都可以读写寄存器/* 方式1 */value = readl(GPIO_MODE_ADDR);value |= (0x1 << 7);// 设置复用引脚pin15为gpio模式writel(value, GPIO_MODE_ADDR);value = readl(GPIO_DIR_ADDR);value |= (0x1 << 15);// GPIO15方向为输出writel(value, GPIO_DIR_ADDR);value = readl(GPIO_DATA_ADDR);value &= ~(0x1 << 15);// GPIO15输出低电平writel(value, GPIO_DATA_ADDR);/* 方式2 */// *(volatile u32 *)(GPIO_MODE_ADDR) |= (0x1 << 7);// *(volatile u32 *)(GPIO_DIR_ADDR) |= (0x1 << 15);// *(volatile u32 *)(GPIO_DATA_ADDR) &= ~(0x1 << 15);/* 方式3 */// value = le32_to_cpu(*(volatile unsigned long *)GPIO_MODE_ADDR);// value |= (0x1 << 7);// *(volatile unsigned long *)GPIO_MODE_ADDR = cpu_to_le32(value);// value = le32_to_cpu(*(volatile unsigned long *)GPIO_DIR_ADDR);// value |= (0x1 << 15);// *(volatile unsigned long *)GPIO_DIR_ADDR = cpu_to_le32(value);// value = le32_to_cpu(*(volatile unsigned long *)GPIO_DATA_ADDR);// value &= ~(0x1 << 15);// *(volatile unsigned long *)GPIO_DATA_ADDR = cpu_to_le32(value);}char acCDevName[] = "led-gpio15";// 字符设备文件名称unsigned int unMajorId, unMinorId = 0;// 主次设备号struct class *pClass;int __init test_init(void){// 注意:这边只是简单写流程,没有函数失败返回处理/* 1.注册,返回主设备号 */unMajorId = register_chrdev(0, acCDevName, &test_fops);/* 2.创建类 /sys/class/led123 */pClass = class_create(THIS_MODULE, "led123");// 若该目录存在则会返回失败/* 3. /dev/和/sys/class/led123/ 目录下自动创建设备节点 */device_create(pClass, NULL, MKDEV(unMajorId, unMinorId), NULL, acCDevName);/* LED init */led_init();return 0;}void __exit test_exit(void){unregister_chrdev(unMajorId, acCDevName);device_destroy(pClass, MKDEV(unMajorId, unMinorId));class_destroy(pClass);printk("exit lfz chrdev driver.\n");}module_init(test_init);module_exit(test_exit);MODULE_LICENSE("GPL");

参考 openwrt/package/kernel/gpio-button-hotplug/(也可以是kernel目录下的其它文件),创建目录 “openwrt/package/kernel/gpio-ctrl-led/”,进入该目录创建src文件夹,将 “gpio-ctrl-led.c”文件拷贝到该src目录下,并新建 Makefile文件,文件类容如下:

obj-m += gpio-ctrl-led.o

在 gpio-ctrl-led/ 目录下新建Makefile文件(内容可参考 gpio-button-hotplug/Makefile),内容如下:

include $(TOPDIR)/rules.mkinclude $(INCLUDE_DIR)/kernel.mkPKG_NAME:=gpio-ctrl-ledPKG_RELEASE:=2PKG_LICENSE:=GPL-2.0include $(INCLUDE_DIR)/package.mkdefine KernelPackage/gpio-ctrl-ledSUBMENU:=Other modulesTITLE:=Simple GPIO ctrl LED driverFILES:=$(PKG_BUILD_DIR)/gpio-ctrl-led.koAUTOLOAD:=$(call AutoLoad,30,gpio-ctrl-led,1)KCONFIG:=endefdefine KernelPackage/gpio-ctrl-led/descriptionKernel module to control GPIO LED for mt7621endefMAKE_OPTS:= \$(KERNEL_MAKE_FLAGS) \SUBDIRS="$(PKG_BUILD_DIR)"define Build/Compile$(MAKE) -C "$(LINUX_DIR)" \$(MAKE_OPTS) \modulesendef$(eval $(call KernelPackage,gpio-ctrl-led))

返回 openwrt目录,按如下操作:

 make menuconfig

Kernel modules —>

 Other modules —>

<*> kmod-gpio-ctrl-led

如此,执行 “make V=99” 编译完固件,烧写到板子在系统跑起来后,该LED驱动会自动完成加载。

三、应用层代码

#include <stdio.h>#include <fcntl.h>#include <unistd.h>#include <sys/ioctl.h>int main(int argc, char **argv){int nRet = 0;char acBuf[128] = "";int nFd = open("/dev/led-gpio15", O_RDWR);if(nFd < 0){printf("Err!!! open '/dev/led-gpio15' fail.\n");return -1;}ioctl(nFd, 1);// led upsleep(1);ioctl(nFd, 0);// led downclose(nFd);return 0;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。