如何编写?
- 首先找到板子的原理图,找到对应的引脚。
- 接着打开数据手册,找到对应的寄存器。
- 开始编写LED驱动程序
- 编写makefile
- 编写应用程序
- 连接实验箱,调试
核心板LED部分的原理图:
可直接根据核心板找到LED是由哪个GPIO控制的:
解释:
- LED1->EINT4->GPF4;
- LED2->EINT5->GPF5;
- LED3->EINT6->GPF6;
- LED4->EINT7->GPF7;
打开芯片手册,找到对应的寄存器
将GPF4、GPF5、GPF6、GPF7置01=输出;
其他位保留,
即GPFCON=55FF.
驱动程序流程设计
这里先贴上大连飞翔的例程,理解一下驱动框架在具体实例中的应用,
后续将会分析里面具体一些比较吃力的函数(对我这个小白来说)。
/*****************************************************************
文件名:led.c
硬件描述:
S3C2410_GPF(4)连接LED0,
S3C2410_GPF(5)连接LED1,
S3C2410_GPF(6)连接LED2,
S3C2410_GPF(7)连接LED3。
主要函数描述:led_ioctl()函数控制驱动设备,led_init()函数初始化驱动设备
*****************************************************************/
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <mach/regs-clock.h>
#include <plat/regs-timer.h>
#include <mach/regs-gpio.h>
#include <linux/cdev.h>
#define LED_DRIVER "FES2440 LED Driver"//自定义驱动称为"utu2440 LED Driver v1.00"
/* 用来指定LED所用的引脚设置 */
static unsigned long led_table [] = {
S3C2410_GPF(4),
S3C2410_GPF(5),
S3C2410_GPF(6),
S3C2410_GPF(7),
};
/******************************************************************************
功能描述:控制驱动程序
输入参数:inode为设备节点结构体, file为被操作的设备文件,cmd为传送的命令,arg为传送的数据
输出参数:无
返回结果:0表示成功,-1表示失败
******************************************************************************/
static int led_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg)
{
switch (cmd)
{
case 0:
case 1:
if (arg > 4) {return -EINVAL;}
s3c2410_gpio_setpin(led_table[arg], !cmd); //点亮相应的管脚
default:
return -EINVAL;
}
return 0;
}
/*定义文件操作结构体*/
static struct file_operations led_fops = {
.ioctl = led_ioctl,
};
/*定义杂类设备结构体*/
static struct miscdevice led_dev = {
MISC_DYNAMIC_MINOR, //主设备号
"LED", //设备名
&led_fops // 设备文件操作结构体地址
};
/******************************************************************************
功能描述:设备初始化函数
输入参数:无
输出参数:无
返回结果:0表示成功,-1表示失败
******************************************************************************/
static int led_init(void)
{
pr_info("%s\n", LED_DRIVER);
__raw_writel(0xFFFF55FF,S3C2410_GPFCON);//设置控制寄存器
printk("GPF4=%d",s3c2410_gpio_getpin(S3C2410_GPF(4)));
misc_register(&led_dev);//注册设备驱动
return 0;
}
/******************************************************************************
功能描述:设备退出函数
输入参数:无
输出参数:无
******************************************************************************/
static void __exit led_exit(void)
{
misc_deregister(&led_dev);
}
/*模块参数设置*/
module_init(led_init);
module_exit(led_exit);
MODULE_AUTHOR("FES");
MODULE_LICENSE("GPL");
Makefile
PWD=$(shell pwd)
KERNEL_SRC= /Linux-2.6.32
obj-m += led.o
all:
$(MAKE) -C $(KERNEL_SRC) M=$(PWD)
clean:
rm -rf *.ko *.o *.mod.c *.symvers
测试程序
/*****************************************************************
文件名:ledtest.c
主要函数描述:main()函数实现对led驱动设备的测试
*****************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
/**************************************************************************
功能描述:完成对LED的显示
输入参数:无
输出参数:无
*************************************************************************/
int main(int argc, char **argv)
{
int on,i;//开关标志
int led_number;//要控制的LED number
int fd;//文件操作
char c,d;
int left_num;
/*打开LED设备文件*/
fd = open("/dev/LED", 0);
if (fd < 0)
{
perror("open device /dev/LED failed!");
exit(1);
}
/*开始测试*/
while(1)
{
l1:printf("Please input led_number(0-3)\n");
scanf("%d", &led_number);
if(led_number>3||led_number<0)
{
printf("you input wrong led_number,try again!\n");
goto l1;
}
l2:printf("Please input Command(0 or 1)\n");
scanf("%d", &on) ;
if(on!=0&&on!=1)
{
printf("you input wrong command,try again!\n");
goto l2;
}
scanf("%c",&d); //把回车去掉
ioctl(fd, on, led_number);
l3:printf("go on or not Y/N:\n");
scanf("%c",&c);
if(c=='n'||c=='N') {for(i=0;i<4;i++) ioctl(fd,0,i);break;}
else if(c=='Y'||c=='y') ;
else {printf("you input wrong chose,try again!\n");goto l3;}
}
close(fd);//关闭设备文件
return 0;
}
驱动make完成得到的内核模块文件(.ko文件)就可以加载到实验箱上调试了,
用交叉编译环境arm-linux-gcc编译调试程序,在试验箱中运行进行调试。
连接实验箱
我这里采用的时串口-USB连接
连接试验箱时串口出现黄色感叹号
问题:驱动没装
解决办法:驱动下载连接 密码: Zane
1.打开设备管理器,在黄色感叹号的设备上右键点击更新
2.点击让我从计算机中可用的驱动列表里选
3.找到这个驱动,下一步!!
出现设备列表选择串口(COM口)就会进入这个界面
win7超级终端实现PC机上调试驱动
超级终端for win7可以实现pc机与试验箱间的数据交互,high不high??哈哈。
超级终端 提取密码: Zane
1.点击新建连接,输入名称
2.选择com口
3.波特率设置成115200,数据流控制选择无
4.进去了点一下回车就会弹出命令行
5.插入模块insmod led.ko
6.执行应用程序./ledtest
注意:若是显示permission denied 错误则是权限不够,没有可执行权限
只需chmod u+x ledtest
即可
调试过程:
7.实验现象展示
欢迎指错交流