本文内容由浅入深主要介绍了JZ2440的LED裸板程序,LED的简单驱动程序
一、LED裸板程序
arm开发板的裸板程序和51单片机类似,需要通过配置寄存器来实现。s3c2440有130个I/O口,共分为A-J共9组。
1.硬件原理图:
JZ2440的硬件连接图,如下图所示:
从图中可以看出LED1、LED2、LED3、LED4这四个LED灯分别于GPB5-GPB8相连,因此需要通过控制GPB5-GPB8的寄存器的输出来控制,LED等的亮灭。
2.寄存器的配置
s3c2440的I/O口可以用于输入、输出或是其他特殊功能,因此需要有寄存器来对引脚的功能进行配置。GPB引脚的位置及配置可以从s3c2440手册上查到,如下图所示:
由上图可以看出对GPB引脚进行设置的有4个寄存器,其中包括一个保留的,即有三个寄存器来对GPB引脚进行设置。
这三个寄存器的功能如下:
GPBCON:主要用于配置,选择引脚的功能。GPBDAT:用于读写引脚,当引脚被设为输入时,读此寄存器可知相应引脚的电平状态是高还是低;当引脚被设为输出时,写此寄存器相应位可令此引脚输出高电平或低电平。GPBUP寄存器:某位为1时,相应引脚无内部上拉电阻;为0时,相应引脚使用内不上拉电阻。
3、代码分析
点亮LED的C语言代码很简单,如下所示:
/*定义GPBCON的地址,其中的volatile主要是为了防止编译器在编译时对代码进行优化,从而产生错误*/
#define GPBCON (*(volatile unsigned long*)0x56000010)
#define GPBDAT (*(volatile unsigned long*)0x56000014)
int main()
{
GPBCON=0x00015400;//设置GPB5-GPB8位输出端口
GPBDAT=0x00000000;//GPB5-GPB8输出0,LED1-4点亮
}
二、LED驱动程序
1.驱动简介
一个软件系统可以分为:应用程序、库、操作系统、驱动程序四部分,其架构图如下所示:
首先应用程序使用库提供的open函数打开代表LED的设备文件;库根据open函数传入的参数执行swi指令,该指令引起系统调用;内核的异常处理函数根据这些参数找到对应的驱动程序,返回文件的句柄;应用程序得到文件句柄后,使用库提供的write或ioctl函数发出控制命令;库根据write或ioctl函数传入的参数执行swi指令,这条指令会引起CPU异常,进入内核;内核的异常处理函数根据这些参数调用驱动程序的相关函数,点亮LED。
Linux的外设可以分为3类:字符设备、块设备和网络设备。字符设备是能够像字节流一样被访问的设备,对设备的读写是以字节为单位的。块设备的数据是以块的形式存放的,如硬盘、U盘等。
2.源码分析
#define LED_MATOR0
Static unsignedlong led_table[]={
S3C2410_GPB(5),
S3C2410_GPB(6),
S3C2410_GPB(7),
S3C2410_GPB(8),
};
staticint s3c2440_leds_open(struct inode *inode,struct file *file)
{
int i;
for(i=0;i<4;i++)
{
S3c2410_gpio_cfgpin(led_table[i], S3C2410_GPIO_OUTPUT);//配置引脚为输出
}
return 0;
}
staticint s3c2440_leds_ioctl(struct inode *inode,struct file *file,unsigned intcmd,unsigned long arg){
if(arg>4)
return –EINVAL;
switch(cmd){
case IOCTL_LED_ON:
s3c2410_gpio_setpin(led_table[arg],0);//设置引脚输出电平为0
return 0;
case IOCTL_LED_OFF:
s3c2410_gpio_setpin(led_table[arg],1); //设置引脚输出电平为1
return 0;
defaule:
return –EINVAL;
}
}
/*驱动的操作函数集*/
static structfile_operations s3c2440_leds_fops={
.owner=THIS_MODULE,
.open=s3c2440_leds_open,
.ioctl=s3c2440_leds_ioctl,
};
staticint s3c2440_leds_init(void)
{
int ret;
ret=register_chrdev(LED_MATOR,”leds”,&s3c2440_leds_fops);//向内核注册驱动函数
if(ret<0)
return ret;
return 0;
}
Staticvoid s3c2440_leds_exit(void)
{
Unregister_chrdev(LED_MATOR, ”leds”);//卸载驱动的函数
}
module_init(s3c2440_leds_init);//指定驱动程序的初始化函数
module_exit(s3c2440_leds_exit);//指定驱动程序的卸载函数