Tiny-S3C6410_Linux下LED灯驱动移植过程

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

UT-S3C6410 ARM11 Linux 下的LED驱动
一、实验环境
操作系统:fedora13
交叉编译环境:arm-Linux-gcc 或以上,
6410板子内核源码路径在:忘了,需要厂家给的内核源代码
硬件平台:S3C6410开发板(其他类型的开发板也可以注意配置GPIO)
注:交叉编译环境一定要装好,一般的开发板给的配套资料中都会有,安装过程也都有详细的过程,如果没有,亲,你只有自己解决了。

也可以联系我(****************),泪奔支持你们。

二、实验原理
控制LED是最简单的一件事情,就像学C语言时候写的“hello world”程序一样,是一个入门的程序。

首先来了解一下相关的硬件知识:
UT-S3C6410LED原理图
UT-S3C6410LED外部引脚图
从上面的原理图可以得知,LED与CPU引脚的连接方法如下,高电平点亮。

LED1 -GPM0
LED2 -GPM1
LED3 -GPM2
LED4 -GPM3
从数据手册可以找到相应的控制方法。

这里我们以LED1为例,介绍一下LED1的操作方法,其他的类似,请大家自行分析。

通过上面可以得知,需要先将GPM0设置为输出方式。

将寄存器GPMCON低四位配置成0001。

然后将GPMDAT寄存器的第0位置1灯亮,置LED0灯亮,开发板上有四个LED所以要对GPMDAT的低四位进行操作,就可以实现对灯的亮灭操作了。

三、实验步骤
1、编写驱动程序
mini6410_leds.c
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <asm/irq.h>
//#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>
#include <mach/map.h>
#include <mach/regs-clock.h>
#include <mach/regs-gpio.h>
#include <plat/gpio-cfg.h>
#include <mach/gpio-bank-e.h>
#include <mach/gpio-bank-k.h>
#define DEVICE_NAME "leds"
static long sbc2440_leds_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) {
switch(cmd) {
unsigned tmp;
case 0:
case 1:
if (arg > 4) {
return -EINVAL;
}
tmp = readl(S3C64XX_GPKDAT);
tmp &= ~(1 << (4 + arg));
tmp |= ( (!cmd) << (4 + arg) );
writel(tmp, S3C64XX_GPKDAT);
//printk (DEVICE_NAME": %d %d\n", arg, cmd); return 0;
default:
return -EINVAL;
}
}
static struct file_operations dev_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = sbc2440_leds_ioctl,
};
static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &dev_fops,
};
static int __init dev_init(void)
{
int ret;
{
unsigned tmp;
tmp = readl(S3C64XX_GPKCON);
tmp = (tmp & ~(0xffffU<<16))|(0x1111U<<16); writel(tmp, S3C64XX_GPKCON);
tmp = readl(S3C64XX_GPKDAT);
tmp |= (0xF << 4);
writel(tmp, S3C64XX_GPKDAT);
}
ret = misc_register(&misc);
printk (DEVICE_NAME"\tinitialized\n");
return ret;
}
static void __exit dev_exit(void)
{
misc_deregister(&misc);
}
module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("FriendlyARM Inc.");
(1)把Hello,Module 加入内核代码树,并编译
一般编译2.6 版本的驱动模块需要把驱动代码加入内核代码树,并做相应的配置,如
下步骤(注意:实际上以下步骤均已经做好,你只需要打开检查一下直接编译就可以了):
Step1:编辑配置文件Kconfig,加入驱动选项,使之在make menuconfig 的时候出现
打开linux-2.6.38/drivers/char/Kconfig 文件,添加如图所示:
#====================cgf add===================================== config MINI6410_LEDS
tristate "LED Support for Mini6410 GPIO LEDs"
depends on CPU_S3C6410
default y
help
This option enables support for LEDs connected to GPIO lines
on Mini6410 boards.
#================================================================== 保存退出,这时在linux-2.6.38 目录位置运行一下make menuconfig 就可以在Device
Drivers Character devices 菜单中看到刚才所添加的选项了,按下空格键将会选择为<M>,
此意为要把该选项编译为模块方式;再按下空格会变为<*>,意为要把该选项编译到内核中,
在此我们选择<M>,如图,如果没有出现,请检查你是否已经装载了缺省的内核配置文件,
(2)Makefile文件
Step2:通过上一步,我们虽然可以在配置内核的时候进行选择,但实际上此时执行
编译内核还是不能把mini6410_leds.c编译进去的,还需要在Makefile 中把内核配置
选项和真正的源代码联系起来,打开linux-2.6.38-cgf/drivers/char/Makefile,
obj-$(CONFIG_MINI6410_LEDS) += mini6410_leds.o
添加并保存退出
Step3:这时回到linux-2.6.38 源代码根目录位置,执行make modules,就可以生成我
们所需要的内核模块文件drivers/char/mini6410_leds.ko 了,注意:执行make modules 之前,必
须先执行make zImage,只需一次就可以了。

至此,我们已经完成了模块驱动的编译。

注意:在编译过程中会出现
drivers/char/mini6410_leds.c:31:30: fatal error: mach/gpio-bank-k.h: No such file or directory
compilation terminated.
则表明自己的内核里缺相关的头文件,只要把光盘里的头文件复制到相关的目录下则可以
一般头文件路径会在arch/arm/mach-s3c64xx/include
cp linux-2.6.38/arch/arm/mach-s3c64xx/include/mach/gpio-bank-k.h
/root/mywork/linux-2.6.38-cgf/arch/arm/mach-s3c64xx/include/mach/gpio-bank-k.h
(3)把Module 下载到开发板并安装使用
在此使用ftp 命令把编译出的mini6410_hello_module.ko 下载到板子中,并把它移动
到/lib/modules/2.6.38-FriendlyARM 目录然后在板子中现在执行
insmod mini6410_leds.ko
出现如下结果:
leds initialized
可以看到该模块已经被装载了(注意:使用modprobe 命令加载模块不需要加“ko”尾
缀)
再执行以下命令,可以看到该模块被卸载
#rmmod mini6410_hello_module
注意:要能够正常卸载模块,必须把模块放入开发板的
/lib/modules/2.6.38-FriendlyARM 目录
2、编写测试程序
光盘中的样例测试程序:
mini6410_leds.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
int main(int argc, char **argv)
{
int on;
int led_no;
int fd;
/* 检查led 控制的两个参数,如果没有参数输入则退出。

*/
if (argc != 3 || sscanf(argv[1], "%d", &led_no) != 1 || sscanf(argv[2],"%d", &on) != 1 || on < 0 || on > 1 || led_no < 0 || led_no > 3) {
fprintf(stderr, "Usage: leds led_no 0|1\n");
exit(1);
}
/*打开/dev/leds 设备文件*/
fd = open("/dev/leds0", 0);
if (fd < 0) {
fd = open("/dev/leds", 0);
}
if (fd < 0) {
perror("open device leds");
exit(1);
}
/*通过系统调用ioctl 和输入的参数控制led*/
ioctl(fd, on, led_no);
/*关闭设备句柄*/
close(fd);
return 0;
}
3、将程序下载到开发板,推荐使用ftp下载
将开发板的IP地址修改,与主机在同一个网段,并修改PC机上Linux下/etc/exports 网络配置文件的IP与开发板的一致。

确保PC机上Linux已经安装了NFS服务器,。

4、测试
5.1加载驱动 # insmod mini6410_leds.ko
5.2测试 ./led 3 1
#chmod 777 led
5.4卸载驱动#rmmod mini6410_leds.ko
从上面的结果我们可以看到,当用户调用相应的文件操作函数时,驱动程序中的相应的函数也会被调用。

大家可以修改相应程序,测试一下其他的情况,如有什么错误也可以一起探讨,今生为嵌入式事业奋斗终身,谢谢!
邮箱:*****************。

相关文档
最新文档