全志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安全错误
数据库的锁怎样保障安全
如何建立mysql数据库
服务器分销业务规划
双线服务器怎么解析
网络安全工作如何具体落实
耕地资源调查数据库
全球共享病毒基因数据库
两栖类数据库
宝德40核CPU服务器
湖南有软件开发专业的大专
余姚机械刀片服务器专业服务
软件开发案例论文3000字
网络技术的微信公众号
移动互联网与软件开发
网络服务器有什么操作系统
数据库2000置疑修复
数据库的关键字是啥
如何利用api抓取数据库
软件开发与人工智能
北京双强电脑网络技术公司
国家软件开发证书
网络安全风险评估多少年进行一次
深信服网络安全入门
浪潮服务器登陆管理口
长宁区网络营销网络技术推荐咨询
pg数据库 切换用户登录
网络安全预算和总预算
关于软件开发提议
不履行网络安全义务违法行为
数据库表怎么画
数据库数据安全保护