Step1:驱动加载函数: ***_init;
该函数内容为驱动硬件时仅执行一次的函数,其作用是硬件初始化。如配置IO端口输出方向,配置IO上拉等;该函数传入在module_init(***_init);函数中以使得在加载驱动时自动执行;
Step2:写open,read,write,release函数;
这三个函数的作用是为了传入file_operations结构体;在应用程序调用驱动时这三个函数作为借口被调用。
其中open的作用是在编写应用程序时加载驱动程序;其原型为pen(strpath, authority )如:fd = open("/dev/led",O_RDWR);//open函数加载驱动,返回值为描述符,返回值为0时则成功加载驱动。
Write函数的原型为: (structfile *filp, const char __user *buf, size_t count,loff_t *f_pos)
Step3:将step2中的函数赋给operations结构体
struct file_operations led_fops =
{
.owner= THIS_MODULE,
.open= led_open,
.read= led_read,
.write= led_write,
.release= led_release,
};
Step4:在***_init函数中注册字符型设备驱动模块;如以下为注册led驱动函数:
register_chrdev(LED_MAJOR,"led",&led_fops);
int register_chrdev(unsignedintmajor,constchar*name,structfile_operations*fops);
其中参数major如果等于0,则表示采用系统动态分配的主设备号;不为0,则表示静态注册。
注销字符设备可以使用unregister_chrdev函数。
Step5:注销字符型设备驱动模块:
在led_exit(可以任意名字,最后把函数名传给module_exit即可)使用unregister_chrdev(LED_MAJOR,"led"); 函数注销驱动。并赋给module_exit(led_exit);
·一个活生生的例子
1.查看用户手册
led1、led2、led3、led4 连接的分别是 GPK4、GPK5、GPK6、GPK7
2、查询6410芯片手册
下面还需要3个步骤:
1、设置GPIO为OUTPUT。
将GPK4、GPK5、GPK6、GPK7设置为输出output=0001
即GPKCON0的19:28都配置为0001
2、设置GPIO的数据。
将GPKDATA的4:7位赋值为0
3、设置GPKUP为上拉。
将GPKUP的4:7位设置为10
3、代码
led_driver.cStep1:驱动加载函数: ***_init;
该函数内容为驱动硬件时仅执行一次的函数,其作用是硬件初始化。如配置IO端口输出方向,配置IO上拉等;该函数传入在module_init(***_init);函数中以使得在加载驱动时自动执行;
Step2:写open,read,write,release函数;
这三个函数的作用是为了传入file_operations结构体;在应用程序调用驱动时这三个函数作为借口被调用。
其中open的作用是在编写应用程序时加载驱动程序;其原型为pen(strpath, authority )如:fd = open("/dev/led",O_RDWR);//open函数加载驱动,返回值为描述符,返回值为0时则成功加载驱动。
Write函数的原型为: (structfile *filp, const char __user *buf, size_t count,loff_t *f_pos)
Step3:将step2中的函数赋给operations结构体
struct file_operations led_fops =
{
.owner= THIS_MODULE,
.open= led_open,
.read= led_read,
.write= led_write,
.release= led_release,
};
Step4:在***_init函数中注册字符型设备驱动模块;如以下为注册led驱动函数:
register_chrdev(LED_MAJOR,"led",&led_fops);
int register_chrdev(unsignedintmajor,constchar*name,structfile_operations*fops);
其中参数major如果等于0,则表示采用系统动态分配的主设备号;不为0,则表示静态注册。
注销字符设备可以使用unregister_chrdev函数。
Step5:注销字符型设备驱动模块:
在led_exit(可以任意名字,最后把函数名传给module_exit即可)使用unregister_chrdev(LED_MAJOR,"led"); 函数注销驱动。并赋给module_exit(led_exit);
·一个活生生的例子
1.查看用户手册
led1、led2、led3、led4 连接的分别是 GPK4、GPK5、GPK6、GPK7
2、查询6410芯片手册
下面还需要3个步骤:
1、设置GPIO为OUTPUT。
将GPK4、GPK5、GPK6、GPK7设置为输出output=0001
即GPKCON0的19:28都配置为0001
2、设置GPIO的数据。
将GPKDATA的4:7位赋值为0
3、设置GPKUP为上拉。
将GPKUP的4:7位设置为10
3、代码
led_driver.c
#include #include #include #include #include #include #include #include #define LED_MAJOR 243 #define LED_ON 1 #define LED_OFF 0 #define LED_1_ON 2 #define LED_1_OFF 3 #define LED_2_ON 4 #define LED_2_OFF 5 #define LED_3_ON 6 #define LED_3_OFF 7 #define LED_4_ON 8 #define LED_4_OFF 9 static int led_open (struct inode *inode,struct file *filp) { unsigned tmp; tmp = readl(S3C64XX_GPKCON); tmp = (tmp&0x0000ffff)| 0x1111ffff; writel(tmp, S3C64XX_GPKCON); printk("#########open######n"); return 0; } static int led_read (struct file *filp, char __user *buf, size_t count,loff_t *f_pos) { return count; } static int led_write (struct file *filp, const char __user *buf, size_t count,loff_t *f_pos) { char wbuf[10]; unsigned tmp; if(copy_from_user(wbuf,buf,count)) return -EFAULT; switch(wbuf[0]) { case LED_ON: tmp = readl(S3C64XX_GPKDAT); tmp &= (0x0f); writel(tmp, S3C64XX_GPKDAT); printk("turn on!n"); break; case LED_OFF: tmp = readl(S3C64XX_GPKDAT); tmp |= (0xf0); writel(tmp, S3C64XX_GPKDAT); printk("turn off!n"); break; case LED_1_ON: tmp = readl(S3C64XX_GPKDAT); tmp &= (0xef); writel(tmp, S3C64XX_GPKDAT); printk("turn off!n"); break; case LED_1_OFF: tmp = readl(S3C64XX_GPKDAT); tmp |= (0xf0); writel(tmp, S3C64XX_GPKDAT); printk("turn on!n"); break; case LED_2_ON: tmp = readl(S3C64XX_GPKDAT); tmp &= (0xdf); writel(tmp, S3C64XX_GPKDAT); printk("turn off!n"); break; case LED_2_OFF: tmp = readl(S3C64XX_GPKDAT); tmp |= (0xf0); writel(tmp, S3C64XX_GPKDAT); printk("turn on!n"); break; case LED_3_ON: tmp = readl(S3C64XX_GPKDAT);
上一篇:ARM与嵌入式入门的建议
下一篇:三星S3C2440 ARM920T内核处理器寄存器整理--非常有用的资料
推荐阅读最新更新时间:2024-11-16 22:52
设计资源 培训 开发板 精华推荐
- LT1767EMS8E-3.3 双路输出 SEPIC 转换器的典型应用电路
- MB3771 5V和12V电源监控器典型应用电路(RESET信号由5V产生,VCC1 = 5V,VCC2 = 12V)
- MC33166离线预转换器的典型应用
- LT1171,用户线接口电路的电源
- LTC2953CDD-2 电压监控器的典型应用电路,用于在 40V 电源瞬态条件下工作
- DC1263A,使用 LTC4558EDU 双 SIM 卡智能卡电源和接口的演示板
- 禁用看门狗的 LTC2938IDE 四电源监视器的典型应用电路
- STEVAL-IPT005V1,基于 ST8034P 的智能卡接口评估板
- MAXREFDES164#:IO-Link本地温度传感器
- 基于esp32h2的开源微型赛车,灵感来源马里奥赛车
- Allegro MicroSystems 在 2024 年德国慕尼黑电子展上推出先进的磁性和电感式位置感测解决方案
- 左手车钥匙,右手活体检测雷达,UWB上车势在必行!
- 狂飙十年,国产CIS挤上牌桌
- 神盾短刀电池+雷神EM-i超级电混,吉利新能源甩出了两张“王炸”
- 浅谈功能安全之故障(fault),错误(error),失效(failure)
- 智能汽车2.0周期,这几大核心产业链迎来重大机会!
- 美日研发新型电池,宁德时代面临挑战?中国新能源电池产业如何应对?
- Rambus推出业界首款HBM 4控制器IP:背后有哪些技术细节?
- 村田推出高精度汽车用6轴惯性传感器
- 福特获得预充电报警专利 有助于节约成本和应对紧急情况