全志A33 linux led驱动编程(附实测参考代码)
发表于:2025-01-23 作者:千家信息网编辑
千家信息网最后更新 2025年01月23日,开发平台开发平台* 芯灵思SinlinxA33开发板淘宝店铺: https://sinlinx.taobao.com/嵌入式linux 开发板交流 QQ:641395230#实验原理在芯灵思开发板上
千家信息网最后更新 2025年01月23日全志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安全错误
数据库的锁怎样保障安全
扫描机服务器保存位置
rna测序数据库
网络技术年度总结
access数据库一日通
杭州电子科技大学网络安全
国家网络安全保卫部队招聘
网络安全攻防实战演习视频
服务器共享文件怎么打开
北京软件开发 智联
忘记云服务器的安全狗密码
博雅数据库估分准不准
计算机网络技术类学考
浏览器提示服务器内部崩溃
三年级的网络安全手抄报价
信息技术高中走进数据库
cmcc share网络安全
软件开发技术人才岗位
mc的服务器怎么弄
职业高中网络安全大赛直播
软件开发咋样才能学好
软件开发公司是什么样的
森州互联网科技
检测到系统更新数据库错误
计算机网络技术有关网站
网络安全问题看法
幼儿园网络安全教育报道
数据库年龄不超过60
数据库改数据个数
网络安全监督工作思路
csgo完美服务器