全志A33 linux led驱动编程(附实测参考代码)
发表于:2024-11-19 作者:千家信息网编辑
千家信息网最后更新 2024年11月19日,开发平台开发平台* 芯灵思SinlinxA33开发板淘宝店铺: https://sinlinx.taobao.com/嵌入式linux 开发板交流 QQ:641395230#实验原理在芯灵思开发板上
千家信息网最后更新 2024年11月19日全志A33 linux led驱动编程(附实测参考代码)
开发平台
开发平台
* 芯灵思SinlinxA33开发板
淘宝店铺: https://sinlinx.taobao.com/
嵌入式linux 开发板交流 QQ:641395230
#实验原理
在芯灵思开发板上,没有led灯模块,只能通过引脚电平观察: 这里我选择LS-INT引脚。
全志A33一共有10组IO口,每组IO有9个相关功能控制器,LS-INT属于PB7,相关寄存器如图
本次实验只用到这两个寄存器,在程序中命名为gpio_con,gpio_dat ,设置为输出引脚。
- 1)注册 class_register(class) 将class注册到内核中。调用前,必须手动分配class内存;调用后必须设置class的name等参数注册 class_create(owner,name) 创建class并将class注册到内核中。返回值为class结构体指针。注销 void class_unregister(struct class cls) 注销class,与class_register()配对使用。注销void class_destroy(struct class cls) 注销class,与class_create()配对使用内核中定义了struct class结构体顾名思义,一个struct class结构体类型变量对应一个类,内核同时提供了class_create(…)函数,可以用它来创建一个类,这个类存放于sysfs下面,一旦创建好了这个类,再调用device_create(…)函数来在/dev目录下创建相应的设备节点。这样,加载模块的时候,用户空间中的udev会自动响应device_create(…)函数,去/sysfs下寻找对应的类从而创建设备节点.
- 2)void ioremap(unsigned long phys_addr , unsigned long size , unsigned long flags)用mmap映射一个设备意味着使用户空间的一段地址关联到设备内存上,这使得只要程序在分配的地址范围内进行读取或写入实际上就是对设备的访问。解除映射void iounmap(void addr)//取消ioremap所映射的IO地址
- 3)register_chrdev(unsigned int major, const char name,const struct file_operations fops);
但其实这个函数是linux版本2.4之前的注册方式,它的原理是:- (1)确定一个主设备号,如果major=0,则会自动分配设备号
- (2)构造一个file_operations结构体, 然后放在chrdevs数组中
- (3)注册:register_chrdev,cat /proc/devices查看内核中已经注册过的字符设备驱动(和块设备驱动),注意这里并不是驱动文件设备节点!
- 4) Linux使用file_operations结构访问驱动程序的函数,这个结构的每一个成员的名字都对应着一个调用
- 5) class_device_create() 调用class_create为该设备创建一个class,再为每个设备调用 class_device_create创建对应的设备。大致用法如下:struct class *myclass = class_create(THIS_MODULE, "my_device_driver");class_device_create(myclass, NULL, MKDEV(major_num, 0), NULL, "my_device");这样的module被加载时,udev daemon就会自动在/dev下创建my_device设备件。
总体代码框架
1)先要有file_operations先要有引脚初始化函数myled_init(void),在myled_init里面注册class并将class类注册到内核中创建设备节点,初始化引脚已经将寄存器地址映射到虚拟内存中,最后调用module_init(myled_init)驱动的加载就靠它2)创建这个file_operations结构体 static struct file_operations myled_oprs = { .owner = THIS_MODULE, .open = led_open, .write = led_write, .release = led_release, }; 下面就围绕这个结构体写函数led_write() led_open() led_release()3)最后要注销设备
附实测代码,参考下
LED驱动代码:
#include #include #include #include #include #include #include #include #include #include #include static int major;static struct class *led_class;volatile unsigned long *gpio_con = NULL;volatile unsigned long *gpio_dat = NULL;static int led_open (struct inode *node, struct file *filp){ /* PB7 - 0x01C20824 */ if (gpio_con) { printk("ioremap 0x%x\n", gpio_con); } else { return -EINVAL; } return 0;}static ssize_t led_write (struct file *filp, const char __user *buf, size_t size, loff_t *off){ unsigned char val; copy_from_user(&val, buf, 1); if (val) { *gpio_dat |= (1<<7); } else { *gpio_dat &= ~(1<<7); } return 1; }static int led_release (struct inode *node, struct file *filp){ printk("iounmap(0x%x)\n", gpio_con); iounmap(gpio_con); return 0;}static struct file_operations myled_oprs = { .owner = THIS_MODULE, .open = led_open, .write = led_write, .release = led_release,};static int myled_init(void){ major = register_chrdev(0, "myled", &myled_oprs); led_class = class_create(THIS_MODULE, "myled"); device_create(led_class, NULL, MKDEV(major, 0), NULL, "ledzzzzzzzz"); gpio_con = (volatile unsigned long *)ioremap(0x01C20824, 1); //0x01C20824 gpio_dat = gpio_con + 4; //0x01C20834 *gpio_con &= ~(7<<28); *gpio_con |= (1<<28); *gpio_dat &= ~(1<<7); return 0;}
APP代码:
#include #include #include #include #include #include #include #include #include #include #include static int major;static struct class *led_class;volatile unsigned long *gpio_con = NULL;volatile unsigned long *gpio_dat = NULL;static int led_open (struct inode *node, struct file *filp){ /* PB7 - 0x01C20824 */ if (gpio_con) { printk("ioremap 0x%x\n", gpio_con); } else { return -EINVAL; } return 0;}static ssize_t led_write (struct file *filp, const char __user *buf, size_t size, loff_t *off){ unsigned char val; copy_from_user(&val, buf, 1); if (val) { *gpio_dat |= (1<<7); } else { *gpio_dat &= ~(1<<7); } return 1; }static int led_release (struct inode *node, struct file *filp){ printk("iounmap(0x%x)\n", gpio_con); iounmap(gpio_con); return 0;}static struct file_operations myled_oprs = { .owner = THIS_MODULE, .open = led_open, .write = led_write, .release = led_release,};static int myled_init(void){ major = register_chrdev(0, "myled", &myled_oprs); led_class = class_create(THIS_MODULE, "myled"); device_create(led_class, NULL, MKDEV(major, 0), NULL, "ledzzzzzzzz"); gpio_con = (volatile unsigned long *)ioremap(0x01C20824, 1); //0x01C20824 gpio_dat = gpio_con + 4; //0x01C20834 *gpio_con &= ~(7<<28); *gpio_con |= (1<<28); *gpio_dat &= ~(1<<7); return 0;}
Makefile代码:
#include #include #include /* ledtest on * * ledtest off * */int main(int argc, char **argv){ int fd; unsigned char val = 1; fd = open("/dev/ledzzzzzzzz", O_RDWR); if (fd < 0) { printf("can't open!\n"); } if (argc != 2) { printf("Usage :\n"); printf("%s \n", argv[0]); return 0; } if (strcmp(argv[1], "on") == 0) { val = 1; } else { val = 0; } write(fd, &val, 1); return 0;}
设备
结构
函数
驱动
内核
代码
开发
地址
节点
内存
寄存器
程序
分配
原理
平台
开发平台
模块
用户
空间
设备驱动
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
网络安全渗透实验
天猫魔盒 服务器
华为x服务器管理口ip
软件开发供应商绩效的方法
网络安全法治宣传教育ppt
dreamsmom的服务器
去中兴进行软件开发
图形验证码服务器
轻量级应用服务器平台
5g网络安全架构设计的原则
教育网 网络安全形式
徐州工程软件开发售后保障
服务器禁止单个IP访问方法
洛阳炫优互联网科技
科脉迷你pos数据库修改
网络技术的专科
自学考试计算机网络技术学分
淮安银联软件开发费用是多少
财汇金融数据库使用
厦门网络技术诈骗
湖北交友软件开发哪家专业
保卫者网络安全团队
如何提高网络安全意识文章
舆情网络安全教育手抄报
电脑网络安全模式能远程吗
数据库规范化原则意义
无人售货机软件开发怎么开发
软件开发网络安全
服务器域名是自己的吗
服务器引擎部干嘛的