1、# Makefile for LED drivers #mod-subdirs := dio hil mtd sbus video macintosh usb input telephony ide message/i2o message/fusion scsi md ieee1394 pnp isdn atm fc4 net/hamradio i2c acpi bluetooth usb/gadget subdir-y := parport char block net sound misc media cdrom hotplug subdir-y += led subdir-m := $(
2、subdir-y) (3)修改/uClinux-dist/linux-2.4.x/Makefile文件,在“DRIVERS-y :=”之后,添加如下加粗代码,这样在连接 uClinux 内核映像文件时,能把 led.o连接进去。DRIVERS-n := DRIVERS-y :DRIVERS-$(CONFIG_ACPI_BOOT) += drivers/acpi/acpi.o DRIVERS-$(CONFIG_PARPORT) += drivers/parport/driver.o DRIVERS-y += drivers/char/char.o drivers/block/block.o dr
3、ivers/misc/misc.o drivers/net/net.o DRIVERS-y += drivers/led/led.o(4)修改/uClinux-dist/vendors/Embest/EduKit/Makefile文件, 在”DRIVERS =”后,添加如下加粗代码“led0,c,60,0”。其中 led0 为设备名称,c 代表字符设备,60 为主设备号,最后一个 0 是从设备号。主设备号与驱动程序注册时的主设备号要求一致,否则用户程序用设备文件名称请求打开设备时,内核无法根据主设备号找到对应的设备驱动程序。DEVICES = tty,c,5,0 console,c,5,1 c
4、ua0,c,5,64 cua1,c,5,65 led0,c,60,0 (5)完成以上修改后,重新构造 romfs和内核映像文件,并烧录到开发板的 FLASH上。(6)最后,启动 uClinux。使用 cp 命令,简单测试一下 LED驱动程序。把任意一个文件复制到 led 设备上,检查是否能点亮其中某个 LED。例如在 uClinux 输入终端执行如下命令:$ cp /bin/init /dev/led0 观察并记录实验现象。 2. 测试驱动程序(1)准备实验环境,使用 Embest EduKit44B0目标开发板附带的串口线分别连接到目标板上的 UART0 和 PC机的串口,将 Embest
5、仿真器的 JTAG接口与 Embest EduKit的 JTAG 接口相连,仿真器的 PARALLEL 接口与 PC机的并口相连。(2)在 PC 机上运行 Windows 附件中自带的超级中断串口通信程序(波特率 115200、1位停止位、无检验位、无硬件流控制);或者使用其它串口通信程序。(3)交叉编译 led 测试程序 test-led。(4)编译好测试程序后,启动目标板的 uClinux 操作系统,在 PC 机上观察超级终端程序主窗口,可以看到如下界面:Sash command shell (version 1.1.1) /在 PC 机上运行 tftp 服务端程序,设置好传送文件路径,通
6、过以太网使用 tftp 把test-led 下载到/var目录下。在 uClinux的输入终端里输入如下命令: cd var /var tftp g 192.168.0.101 r ./test-led (此处 IP地址可能不同) (5)修改 test-led 程序的属性,使其拥有可执行属性,然后运行 test-led。观察 test-led点亮目标开发板上的 LED的情况,并描述。var chmod 777 test-led ./test-led 2. 编写驱动程序 编写测试程序,让各个 LED以人眼能够识别的频率依次闪烁,每个 LED持续闪烁大约3 秒钟,找到编号为 14 的 LED在实验
7、板上的布局,绘制布局图,添加到实验报告中。四、 实验数据记录和处理驱动程序代码:/* linux/deriver/led/ekii-led.c* led driver for Embest EduKit II* Copyright (C) 2005 Embest */#include linux/init.hlinux/sched.hlinux/kernel.hlinux/fs.hlinux/errno.h / error codeslinux/types.h / size_tlinux/delay.h / mdelayasm/uaccess.hasm/arch-S3C44B0X/s3c44b
8、0x.h#undef DEBUG#ifdef DEBUG#define TRACE(str, args.) printk(led: str, # args)#else#define TRACE(str, args.)#endif/TRACE没用#define LED_MAJOR 60 /设备号#define LED_DEVNAME led /设备名称#define GPC_MASK (38) /掩码.pc8/pc9#define GPF_MASK (35) | (c&0x100)7) | (f&0x10)3) | (f&0x08)3) )/把b、f的值组合为一个8位数据/ 3 2 1 0 /
9、pc8 pc9 pf4 pf3#define SET_DATA(t, c, f) ( c = (t&0x08)5) | (t&0x04)7), f = (t&0x02)3) | (t&0x01)lock); /信号量#define LED_UNLOCK(u) up(&struct unit /定义一个结构类型,成员是整型指针,代表各个口寄存器,以及两个变量 struct semaphore lock; /定义信号量 u32 *PCONC; /* PCONB register */ u32 *PDATC; /* PDATB register */ u32 *PCONF; /* PCONF reg
10、ister */ u32 *PDATF; /* PDATF register */ u32 *PUPF; /* PUPF register */ u32 c; /* store LED 1 and LED 2 value */ u32 f; /* store LED 3 and LED 4 value */;static char *version = Embest Edukit-II led driver version 1.0 (2005-04-18) c, unit-f); /第一次:用0x0f 给c、f 赋值为:0、0。点亮4个led /第二次:用0给c、f赋值,使pc8、pc9、pf
11、4、pf3均为1,关闭4个led /写函数还要多次调用本函数 temp = *unit-PDATC; /取pb口状态 temp &= GPC_MASK; /清pb4、pb5 temp |= unit-c; /用新值更新temp *unit-PDATC = temp; /写回pc口PDATF;= GPF_MASK;f;PDATF = temp;static u8 led_get_value(struct unit *unit) u8 temp = GET_DATA(unit- return temp;static int led_open(struct inode *inode, struct
12、file *file) TRACE(openn); file-private_data = &led_unit; /这个操作为read服务 MOD_INC_USE_COUNT; return 0;static int led_release(struct inode *inode, struct file *file)releasen MOD_DEC_USE_COUNT; /模块引用计数自减static ssize_t led_read(struct file *file, char *buf, size_t count, loff_t *offset) u8 temp; int ret; s
13、truct unit *unit = (struct unit *)file-private_data; /使在read函数中可以访问硬件寄存器readn if(count 1) count = 1; LED_LOCK(unit); /信号量操作 temp = led_get_value(unit); /读数据 ret = copy_to_user(buf, &temp, count) ? -EFAULT : count; /把数据从内核空间拷贝到用户空间, /copy_from_user、copy_to_user函数返回不能被复制的字节数, /因此,如果完全复制成功,返回值为0。 LED_U
14、NLOCK(unit); /信号量操作 return ret;static ssize_t led_write(struct file *file, const char *buf, size_t count, loff_t *offset) /使在write函数中可以访问硬件寄存器writen ret = copy_from_user(&temp, buf, count) ? /把数据从用户空间拷贝到内核空间 if(ret) led_set_value(unit, temp);static struct file_operations led_ops = owner: THIS_MODULE
15、, read: led_read, write: led_write, open: led_open, release: led_release,* led device initstatic void _init led_init(struct unit *unit) /* init device lock */ init_MUTEX(&unit- /* init io port */PCONC;= (316) | (318); /16、17、18、19均0,表示pf3、pf4输入 temp |= (116) | (1 /16、18为1,所以pc8、pc9都是输出口 / pconc8、pco
16、nc9:01表示输出PCONC = temp;PUPC; temp |= (38); /8、9置高,pc8、pc9无上拉PUPC = temp;PCONF;8) | (36); /6、7、8、9均0,表示pf3、pf4输入8) | (1 /6、8为1,所以pf3、pf4都是输出口PCONF = temp;PUPF;3); /4、3置高,pf3、pf4无上拉PUPF = temp; /* init data and turn on led*/ led_set_value(unit, 0x0f); /* delay some time */ mdelay(100); /* turn off led
17、 */ led_set_value(unit, 0x00);* module initint _init led_init_module(void) int res;init_modulen /* print version information */ printk(KERN_INFO %s, version); /* register led device */ res = register_chrdev(LED_MAJOR, LED_DEVNAME, &led_ops); if(res 0) printk(ekii-led.o: unable to get major %d for le
18、d device.n, LED_MAJOR); return res; /* then call led_init() */ led_init(&led_unit);* module cleanupvoid _exit led_cleanup(void)cleanupn /* unregister led device */ res = unregister_chrdev(LED_MAJOR, LED_DEVNAME); 0) unable to release major %d for led device.nmodule_init(led_init_module);module_exit(
19、led_cleanup);MODULE_DESCRIPTION(EduKit-II led driverMODULE_AUTHOR(Embest tech&info Co.,Ltd. stdio.hstdlib.hlinux/fcntl.h#define LED_NUM 4int main(int argc, char* argv) int i, j, wval, rval, fd; printf(Test LED.n /* open led device */ fd = open(/dev/led0, O_RDWR); /* test single led */ while(1) for(i
20、=0; i3; i+) for(j=0; jLED_NUM; j+) wval = 1j; write(fd, &wval, 1); read(fd, &rval, 1); printf(Turn on LED%d, readback val = 0x%02Xn, j+1, rval); /* delay 500ms */ usleep(3000*1000); /* close led device */ close(fd);六、实验结果与分析将驱动程序添加到文件系统,重新编译文件系统和内核映像,将编译好的内核映像烧写到目标板上,重启目标板,使用tftp将驱动测试程序传入到目标板中,运行测试程序,试验箱上的4个LED灯按顺序依次点亮。七、讨论、建议、质疑1. 考虑到自动匹配不同寄存器的长度,在给寄存器置位时,对数据进行使用取非操作可以自动补齐到寄存器的长度。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1