设备驱动程序的开发流程
进行嵌入式Linux系统的开发,很大的工作量是为各种设备编写驱动程序。在ARM平台上开发嵌入式Linux的设备驱动程序与在其他平台上开发是一样的。总的来说,实现一个嵌入式Linux设备驱动的大致流程如下:
(1)查看原理图,理解设备的工作原理
(2)定义主设备号
(3)在驱动程序中实现驱动的初始化。如果驱动程序采用模块的方式,则要实现模块初始化。
(4)设计所要实现的文件操作,定义file_operations结构。
(5)实现中断服务(中断并不是每个设备驱动所必须的)
(6)编译该驱动程序到内核中,或者用insmod命令加载
(7)测试该设备
3.2 linux下字符设备的驱动开发实例----LED驱动
(可参考FS2410P实验指导手册v2.1.2.pdf,302-313)
(1)实验内容:4个LED灯轮流闪烁
本节要求实现在一个字符设备驱动里面实现对GPIO端口的操作。
●在模块加载的时候跑马灯运行起来
●模块卸载的时候,跑马灯停止。
FS2410P上的4个LED指示灯由4个I/O口控制,它们分别是:GPF4~GPF7,输出低电平时候,相应的LED指示灯亮。
(2)LED的原理图
FS2410P带有4个用户可编程I/O方式LED,下表为LED对应的I/O口。
表1用户指示灯占用CPU资源列表
序号名字CPU端口资源
1LED1 GPF4
2 LED2 GPF5
3LED3 GPF6
4LED4GPF7
图1 LED原理图
(3)LED驱动源代码及说明
◆在/s3c2410下新建一个目录:gpiodrv
●#mkdir/s3c2410/gpiodrv
●#cd/s3c2410/gpiodrv
◆在/s3c2410/gpiodrv目录下用vi编辑器编写符合上面功能的驱动源程序
gpiodrv.c
●#cd/s3c2410/gpiodrv
●#vi gpiodrv.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define IOPORT_MAJOR 220
int magic_leds_open(struct inode*inode,struct file*filp);
int magic_leds_ioctl(struct inode*inode,struct file*filp,unsigned int cmd,unsigned long arg);
int magic_leds_release(struct inode*inode,struct file*filp);
static struct file_operations magic_leds_fops=
{
ioctl:magic_leds_ioctl,
open:magic_leds_open,
release:magic_leds_release,
};
#define LED1_ON()(GPFDAT&=~0x10)
#define LED2_ON()(GPFDAT&=~0x20)
#define LED3_ON()(GPFDAT&=~0x40)
#define LED4_ON()(GPFDAT&=~0x80)
#define LED1_OFF()(GPFDAT|=0x10)
#define LED2_OFF()(GPFDAT|=0x20)
#define LED3_OFF()(GPFDAT|=0x40)
#define LED4_OFF()(GPFDAT|=0x80)
static int ledStatus;
void LedSet(int led)
{
ledStatus=led;
if(ledStatus&1)
LED1_ON();
else
LED1_OFF();
if(ledStatus&2)
LED2_ON();
else
LED2_OFF();
if(ledStatus&4)
LED3_ON();
else
LED3_OFF();
if(ledStatus&8)
LED4_ON();
else
LED4_OFF();}
void LedDisy(void)
{
LedSet(0x08);
udelay(0x500000);
LedSet(0x04);
udelay(0x500000);
LedSet(0x02);
udelay(0x500000);
LedSet(0x01);
udelay(0x500000);
LedSet(0x02);
udelay(0x500000);
LedSet(0x04);
udelay(0x500000);
LedSet(0x08);
udelay(0x500000);
}
static int__init magic_leds_init(void)
{
int result=0;
printk("magic_leds_init\n");
result=register_chrdev(IOPORT_MAJOR,"gpio",&magic_leds_fops); if(result<0)
{
printk("Failed to register major.\n");
return result;
}
printk("success to register\n");
return 0;
}
int magic_leds_open(struct inode*inode,struct file*filp)
{
GPFCON=0x5500;
GPFUP=0xff;
printk("open gpio devices\n");
return 0;}
void__exit magic_leds_exit(void)
{
unregister_chrdev(IOPORT_MAJOR,"gpio");
}
int__exit magic_leds_release(struct inode*inode,struct file*filp)
{
printk("release this device\n");
return 0;
}
int magic_leds_ioctl(struct inode*inode,struct file*filp,unsigned int cmd,unsigned
long arg)
{
int err=0;
if(cmd==1)
{
while(arg--)
{
LedDisy();
printk(".....");
}
printk("\n");
return 0;
}
return err;
}
module_init(magic_leds_init);
module_exit(magic_leds_exit);
(3)编译安装LED驱动
◆同样,在/s3c2410/gpiodrv目录下用vi编辑器编写该驱动程序的Makefile文件:(Makefile 的编写可参考Makefile中文教程.pdf)
●#vi Makefile输入以下内容:
CROSS=arm-linux-gcc
CFLAGS=-D__KERNEL__
CFLAGS+=-DMODULE
CFLAGS+=-I/s3c2410/2.4.18-rmk7/include
CFLAGS+=-I/s3c2410/2.4.18-rmk7/include/linux
CFLAGS+=-I/usr/local/arm/2.95.3/include
CFLAGS+=-Wall-Wstrict-prototypes-Wno-trigraphs-Os-mapcs
CFLAGS+=-fno-strict-aliasing-fno-common-fno-common-pipe-mapcs-32
CFLAGS+=-march=armv4-mtune=arm9tdmi-mshort-load-bytes-msoft-float
CFLAGS+=-DKBUILD_BASENAME=gpiodrv
all:gpiodrv.o
gpiodrv.o:gpiodrv.c
$(CROSS)$(CFLAGS)-o gpiodrv.o-c gpiodrv.c
clean:
-rm-f$(EXEC)*.o*~core
将gpiodrv.c和Makefile这个放置在同一个新建目录下gpiodrv下,进入这个目录,输入make 后,编绎成功后将在这个目录下生成一个gpiodrv.o文件。
●#cd/s3c2410/gpiodrv
●#make
3.3 linux下字符设备的驱动开发实例—测试LED
(1)在/s3c2410/gpiodrv目录下用vi编辑器编写led驱动程序相应的测试
程序gpio_test.c
●#vi gpio_test.c
#include
#include
#include
#include
#include
#include
#include
int main(int argc,char**argv)
{
int i;
int fd;fd=open("/dev/gpio",0);
if(fd<0)
{
perror("Failed to open device");
exit(1);
}
while(1)
printf("please select number to run program\n");
printf("1:led on\n2:quit");
scanf("%d",&val);
if(val==1)
ioct1(fd,1,10);
else if(val==2)
{
close(fd);
}
return 0;
}
编译gpio_test.c,得到可执行文件gpio_test。即用下面的命令:
#arm-linux-gcc–o gpio_test gpio_test.c
3.4 linux下字符设备的驱动开发实例—实验步骤
(也可参考FS2410P实验指导手册v2.1.2.pdf,311-313上的方法)
(1)PC机进入LINUX系统,配置好minicom,连接好串口线,让FS2410P教学实验平台进入LINUX 环境,利用minicom来显示。
(2)将编绎生成的gpiodrv.o和gpio_test用NFS mount到/tmp目录下。(方法参考实验三---通过NFS进入映射)
#mount 192.168.3.111:/s3c2410/tmp
#cd/tmp
#cd/gpiodrv
(3)加载设备驱动gpiodrv.o模块:
insmod gpiodrv.o
如果加载成功,可以通过cat/proc/devices命令查看该设备的相关信息。卸载该设备驱动模块的命令是:rmmod gpiodrv
(4)建立gpio设备节点:mknod/dev/gpio c 220 0/dev/gpio为该设备驱动程序的设备名,C表明该设备为字符设备,220为该设备的主设备好,0为从设备号。(5)执行gpio_test程序:./gpio_test
(6)在minicon终端选择1,回车,可以看到4个LED灯轮流闪烁。
选择2,则退出程序的运行。
(7)将应用程序添加根文件系统,并烧写到开发板。
◆将FS2410XP_camare_demo.cramfs拷贝到/s3c2410目录下。
◆在该目录下建立两个文件:
#cd/s3c2410/
#mkdir chang
#mkdir guo
◆将FS2410XP_camare_demo.cramfs挂接到chang目录。
#mount-o loop FS2410XP_camare_demo.cramfs chang
◆将chang目录下的内容压缩。
#cd chang
#tar-cvf/s3c2410/1.tar./
这时,将在chang的目录产生一个1.tar的包。
#cd..
#
mv 1.tar guo
#cd guo
#tar-xvf 1.tar#rm 1.tar
rm:是否删除一般文件“1.tar”?y
◆将自已的gpiodrv.o和gpio_test拷贝到相应的目录下。
将gpiodrv.o拷贝到guo/usr/目录下
将gpio_test拷贝到guo/bin下
◆现在开始制作cramfs根文件系统
./mkcramfs/s3c2410/guo FS2410XP_camare_demo.cramfs
◆下载FS2410XP_camare_demo.cramfs根文件系统到开发板:
★使用tftpcmd网络传输,设置宿主机IP地址,将其地址与开发平台的IP地址设置在同一网段内。这里,将PC的IP设为192.168.0.121。并把
tftpcmd复制到/bin文件夹下。
★#cd/s3c2410/guo
★新建一个down文件
#vi down
tftpcmd 202.193.9.21 69 put FS2410XP_camare_demo.cramfs
★改变down的属性
#chmod 777 down
★改变tftpcmd的属性
#chmod 777/bin/tftpcmd
★将开发板与PC机用交叉网线连接好,复位开发板,按住A键,进入BIOS
命令行状态提示符:(minicom)
\>netload
★#./down
或是双击down批处理文件,选择在终端运行,可以看到内核映像下载到了开发板。★传输完后,再输入命令“nfprog”,然后回车,然后输入“2”选择第
二个区块,输入“Y”确认将文件烧写到nandflash中。
◆重复操作(3),(4),(5),(6),可看到实验结果。
驱动模块makefile文件编写求助
自己编的一个linux驱动,我原来的工程目录是这样的:工程总目录下有一个include文件夹,所有的.c源文件,makefile文件,还有一个总的x.h头文件,x.h中include了include 文件夹中所有的头文件和一些内核的头文件。include文件夹里有几个子文件夹,按类放头文件。每个.c源文件都#include "x.h"。下面是原来的makefile文件。在工程总目录下make
可以生成.ko文件。
KERNELDIR :=/arm/linux-2.6.22.19
PWD :=$(shell pwd)
CFLAGS =-fno-common
CROSS_COMPILE =/arm/3.4.1/bin/arm-linux-
CC =$(CROSS_COMPILE)gcc
OBJECTS :=a.o b.o c.o d.o e.o
obj-m := mydriver.o
mydriver-objs := $(OBJECTS)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *.ko *.mod.o *.mod.c
现在工程的文件越来越多,很乱。我想建立这样的工程目录:
工程总目录下有:include文件夹,src文件夹,makefile文件。include文件夹和src文件夹下都有几个子文件夹,都按类放好头文件或源文件。x.h头文件也放在include文件夹
下。
应该怎么来写makefile。怎么样在驱动模块的makefile中指定头文件、源文件的目录?是
否还需要指定内核头文件的目录?
大家帮我看看!谢谢!
编译驱动模块
2009-07-29 10:45
有两种方法可以编译自己写的驱动程序。
第一种方法:直接加入内核
1. 将驱动程序放入内核相应的驱动文件夹,例如名字为my_led.c
2. 修改此驱动目录下的Kconfig文件,加入对该驱动文件的配置选项:
config MY_LED
bool "S3C2410 LED Driver"
depens on ARCH_S3C2410
help
LED driver for the samsung s3c2410
说明:my_LED是配置选项标题
bool表示该选项要么是y要么是n,不可编译成模块。如需要编译成模块则改为tristate(三态)
3. 修改此驱动目录下的Makefile文件,加入对驱动源码的编译:
obj-$(CONFIG_MY_LED) += my_led.o
第二种方法:单独编译驱动模块(1)
1. 下载内核源代码,选择和你的驱动相同的平台的配置文件进行编译,
假设路径为/root/linux-2.6.29。或者利用/usr/src下面的源码,这样就只能编译主机平台上的驱动。
2. 将驱动文件放在一目录下,例如/root/dirver/my_led.c
3. 在/root/driver下编写Makefile文件,内容为:
obj-m := my_led.o
如果这个模块包含多个.c文件,则如下编写Makefile :
obj-m := module_name.o
module-objs := file1.o file2.o ...
4. 在本目录下执行:
make -C /root/linux-2.6.29 M=$(pwd) modules
第三种方法:单独编译驱动模块(2)
直接编写Makefile文件:
obj-m :=led.o
CURRENT_PATH := $(shell pwd)
ARM_LINUX_KERNEL :=/root/linux-2.6.29
all:
$(MAKE) -C $(ARM_LINUX_KERNEL) M=$(CURRENT_PATH) modules
clean:
rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions Module.symvers .Makefile.swp modules.order
运行make即可
Linux下LED驱动的开发笔记
Linux 2010-07-06 15:52:15 阅读17 评论0 字号:大中小订阅
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
#include
//#include
#include
#include
//#define LED_DRIVER "utu2440 LED Driver v1.00"
#define GPIO_LED_MAJOR 0 //主设备号,如果为0的话,由系统自动分配//#define EINVAL 22
/*static unsigned long led_table [] = {
S3C2410_GPF4,
S3C2410_GPF5,
S3C2410_GPF6,
S3C2410_GPF7,
};*/
//static int led_ioctl(struct inode *inode, struct file *file,
// unsigned int cmd, unsigned long arg);
static int led_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg) {
switch (cmd)
{
case 0:{s3c2410_gpio_setpin(S3C2410_GPF4, 1);
s3c2410_gpio_setpin(S3C2410_GPF5, 1);
s3c2410_gpio_setpin(S3C2410_GPF6, 1);
s3c2410_gpio_setpin(S3C2410_GPF7, 1);
break;}
case 1:{s3c2410_gpio_setpin(S3C2410_GPF4, 0);
s3c2410_gpio_setpin(S3C2410_GPF5, 0);
s3c2410_gpio_setpin(S3C2410_GPF6, 0);
s3c2410_gpio_setpin(S3C2410_GPF7, 0);
break;}
default:
{ printk("no cmd led!");
return -1;
}
}
return 0;
}
static struct file_operations ledz_fops = {
.ioctl = led_ioctl,
};
static int led_init(void)
{
//pr_info("%s\n", LED_DRIVER);
int ret = -1;
//s3c2410_gpio_setpin(S3C2410_GPFCON, 0x55aa);
//s3c2410_gpio_setpin(S3C2410_GPFUP, 0xff);
//s3c2410_gpio_setpin(S3C2410_GPFDA T, 0xff);
//S3C2410_GPFCON=0x55aa;
//S3C2410_GPFUP=0xff;
//S3C2410_GPFDA T=0xff;
s3c2410_gpio_setpin(S3C2410_GPF4, 1);
s3c2410_gpio_setpin(S3C2410_GPF5, 1);
s3c2410_gpio_setpin(S3C2410_GPF6, 1);
s3c2410_gpio_setpin(S3C2410_GPF7, 1);
ret = register_chrdev(GPIO_LED_MAJOR, "gpio_led_ctl",&ledz_fops);//完成注册
if(ret < 0)
{
printk("S3C2410 :init_module failed with %d\n",ret);
return ret;
}
else
printk("S3C2410 :init_module register success!!\n");
return ret;
}
static int __init gpio_led_init(void)
{
int ret = -1;
ret =led_init();
if (ret)
return ret;
return 0;
}
static void __exit led_exit(void)
{
int ret;
ret = unregister_chrdev(GPIO_LED_MAJOR, "gpio_led_ctl");//注销注册
if(ret < 0)
{
printk("S3C2410 :exit_module failed with %d\n",ret);
return ret;
}
else
printk("S3C2410 :exit_module unregister success!!\n");
}
module_init(gpio_led_init);
module_exit(led_exit);
Makefile
# Makefile
# Please modify here or set environments.
# KSOURCE should be pointed to the build directory of your kernel.
#
DEBUG ?= n
#KSOURCE ?= /home/azure/Utu-linux/s3c2440/Kernel/utu-linux_for_s3c2440_V1.5/
KSOURCE ?= /utu-linux/utu-linux
//内核目录,这里的目录是与目标机的linux内核相同版本,并不是自己的linux版本,是重新将源码文件拷到linux下解压后的目录
%.x:%.c
arm-linux-gcc -o $@ $<
KBUILD_VERBOSE:=1
obj-m := leds.o
default:
make -C $(KSOURCE) LANG=C KBUILD_VERBOSE=${KBUILD_VERBOSE} SUBDIRS=`pwd` modules
.PHONY: cscope
cscope:
cscope -b -k -R
.PHONY: clean
clean:
make -C $(KSOURCE) LANG=C KBUILD_VERBOSE=${KBUILD_VERBOSE} SUBDIRS=`pwd` clean rm -f *.x *~
测试程序
#include
#include
#include
#include
int main()
{
int fd;
int num;
int ope;
fd = open("/dev/gpio_led_ctl", 0);
if (fd < 0)
{
perror("open miniled fail");
exit(1);
}
while(1)
{
ioctl(fd, 1);
sleep(1);
ioctl(fd, 0);
sleep(1);
}
close(fd);
return 0;
}
在有leds.c的文件目录下
make
生成4个文件:leds.ko leds.mod.c leds.mod.o leds.o
这里只需要leds.ko,将这个文件传到目标机上,
insmod leds.ko,
Using leds.ko
S3C2410 :init_module register success!!
如果挂载成功,可在/proc/devices 目录下发现挂载的设备名lsmod
Module Size Used by Not tainted
leds 1632 0 - Live 0xbf000000
cat /proc/devices
Character devices:
1 mem
2 pty
3 ttyp
4 /dev/vc/0
4 tty
5 /dev/tty
5 /dev/console
5 /dev/ptmx
7 vcs
10 misc
13 input
14 sound
29 fb
81 video4linux
89 i2c
90 mtd
128 ptm
136 pts
180 usb
204 s3c2410_serial
253 gpio_led_ctl
254 utu2440-buttons
Block devices:
1 ramdisk
7 loop
8 sd
31 mtdblock
43 nbd
65 sd
66 sd
67 sd
68 sd
69 sd
70 sd
71 sd
128 sd
129 sd
130 sd
131 sd
132 sd
133 sd
134 sd
135 sd
254 mmc
然后到/dev 目录下
mknod gpio_led_ctl c 253 0
ls -l /dev |grep gpio_led_ctl
crw-r--r-- 1 root root 253, 0 Jan 1 00:09 gpio_led_ctl 然后运行测试程序
./testled
4个灯不断的闪烁!
Makefile
两个连接成一个模块?
还是两个独立的模块?
两个连接成一个模块
obj-m := module.o //名字随便写
module-y := rs-raidmain.o xor.o
两个独立的模块
obj-m := rs-raidmain.o xor.o
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define DEVICE_NAME "leds" /* 加载模式后,执行”cat /proc/devices”命令看到的设备名称*/#define LED_MAJOR 231 /* 主设备号*//* 应用程序执行ioctl(fd, cmd, arg)时的第2个参数*/
#define IOCTL_LED_ON 1
#define IOCTL_LED_OFF 0/* 用来指定LED所用的GPIO引脚*/static unsigned long led_table [] ={ S3C2410_GPB5, S3C2410_GPB6, S3C2410_GPB7, S3C2410_GPB8,};
/* 应用程序对设备文件/dev/EmbedSky-leds执行open(...)时,
* 就会调用EmbedSky_leds_open函数
*/
static int EmbedSky_leds_open(struct inode *inode, struct file *file)
{
int i;
for (i = 0; i < 4; i++)
{ // 设置GPIO引脚的功能:本驱动中LED所涉及的GPIO引脚设为输出功能s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);
}
return 0;}
/* 应用程序对设备文件/dev/EmbedSky-leds执行ioclt(...)时,
* 就会调用EmbedSky_leds_ioctl函数
*/
static int EmbedSky_leds_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
if (arg > 4)
{
return -EINVAL;
}
switch(cmd)
{ case IOCTL_LED_ON: // 设置指定引脚的输出电平为0 s3c2410_gpio_setpin(led_table[arg], 0);
return 0;
case IOCTL_LED_OFF: // 设置指定引脚的输出电平为 1 s3c2410_gpio_setpin(led_table[arg], 1);
return 0;
default: return -EINVAL; }
}
/* 这个结构是字符设备驱动程序的核心
* 当应用程序操作设备文件时所调用的open、read、write等函数,
* 最终会调用这个结构中指定的对应函数
*/
static struct file_operations EmbedSky_leds_fops ={
.owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量*/
.open = EmbedSky_leds_open,
.ioctl = EmbedSky_leds_ioctl,};
static char __initdata banner[] = "TQ2440/SKY2440 LEDS, (c) 2008,2009 https://www.wendangku.net/doc/e21513734.html,\n"; static struct class *led_class;
/*
* 执行“insmod EmbedSky_leds.ko”命令时就会调用这个函数
*/
static int __init EmbedSky_leds_init(void)
{
int ret;
dev_t devno=MKDEV(LED_MAJOR,0);
printk("init led\n");
printk(banner);
/* 注册字符设备驱动程序
* 参数为主设备号、设备名字、file_operations结构;
* 这样,主设备号就和具体的file_operations结构联系起来了,
* 操作主设备为LED_MAJOR的设备文件时,就会调用EmbedSky_leds_fops中的相关成员函数
ret = register_chrdev_region(devno, 1,DEVICE_NAME);//获得设备编号my_leds_dev=kmalloc(sizeof(struct leds_type),GFP_KERNEL);
/*这个必须有不然会在加载模块时出现Unable to handle kernel NULL pointer dereference at virtual addres 00000000 错误,这是由于在这里my_leds_dev仅仅是个指针,没有相应大小的分配内存,所以使用时会出错,,,寻找这个错误是比较麻烦的*/
if(!my_leds_dev)
{
ret=-ENOMEM;
goto fail_malloc;
}
memset(my_leds_dev,0,sizeof(struct leds_type)); cdev_init(&(my_leds_dev->cdev),&EmbedSky_leds_fops);
ret=cdev_add(&(my_leds_dev->cdev),devno,1);
/*注意:与早期的设备注册方法不同,早期的直接register_chrdev()就可以,*/ if(ret)printk(KERN_NOTICE"ERROR %d",ret); //注册一个类,使mdev可以在"/dev/"目录下面建立设备节点
led_class = class_create(THIS_MODULE, DEVICE_NAME); if(IS_ERR(led_class)) { printk("Err: failed in EmbedSky-leds class. \n"); return -1; } //创建一个设备节点,节点名为DEVICE_NAME device_create(led_class, NULL, MKDEV(LED_MAJOR, 0), NULL, DEVICE_NAME); printk(DEVICE_NAME " initialized\n"); return 0; fail_malloc: unregister_chrdev_region(devno,1); return ret;}/* * 执行”rmmod EmbedSky_leds.ko”命令时就会调用这个函数*/static void __exit EmbedSky_leds_exit(void){ /* 卸载驱动程序*/ unregister_chrdev(LED_MAJOR, DEVICE_NAME); device_destroy(led_class, MKDEV(LED_MAJOR, 0)); //删掉设备节点class_destroy(led_class); //注销类}/* 这两行指定驱动程序的初始化函数和卸载函数*/module_init(EmbedSky_leds_init);module_exit(EmbedSky_leds_exit);/* 描述驱动程序的一些信息,不是必须的*/MODULE_AUTHOR("https://www.wendangku.net/doc/e21513734.html,"); // 驱动程序的作者MODULE_DESCRIPTION("TQ2440/SKY2440 LED Driver"); // 一些描述信息MODULE_LICENSE("GPL"); // 遵循的协议
写内核模块Makefile的技巧
hansel@https://www.wendangku.net/doc/e21513734.html,
2007.11.07
Linux 2.6的内核使用Kbuild来编译内核模块。Kbuild能够编译内核树目录内的内核模块,也能够编译内核树目录外的内核模块(外部内核模块)。
.编译外部内核模块的命令:
#cd
#make -C
其中
对于发行版本的Linux,可以用:
#make -C /lib/modules/`uname -r`/build M=`pwd`
注意:使用Kbuild之前,必须先成功编译过内核源码。
说明:
.#make -C
作用与上面的命令一样
.以前的内核版本可以使用
#make -C
.安装外部内核模块
#make -C
默认安装目录为:/lib/modules/`uname -r`/extra,可以通过INSTALL_MOD_PATH宏在默认安装路径前加前缀。
例如:
#make -C
则编译后的模块会放在/opt/lib/modules/`uname -r`/extra
通过宏INSTALL_MOD_DIR可以修改是否放在'extra'下,例如:
#make -C
则编译后的模块会放在/lib/modules/`uname -r`/golf
.编译单个文件
#make -C
.其他命令
#make -C
#make -C
第一章概述 1.1 功能特点 《LED Player V3.3》是本公司新推出的一套专为LED显示屏设计的功能强大,使用方便,简单易学的节目制作、播放软件,支持多种文件格式:文本文件,WORD文件,图片文件(BMP/JPG/GIF/JPEG...),动画文件(SWF /Gif)。 2.2 运行环境 操作系统 中英文Windows/7/NT/XP 硬件配置 CPU: 奔腾600MHz以上 内存:128M 相关软件 OFFICE2000--如需WORD文件必须安装
第二章安装与卸载 2.1 安装 《LED Player》软件安装很简单,操作如下:将LED Player播放软件的安装光盘插入电脑光驱,即可显示LED Player播放软件的安装文件,双击LED Player,即可实现轻松安装。 《LED Player》软件安装成功后,在【开始】/【程序】里将出现“LED软件”程序组,然后进入该程序组下的“LED Player”,单击即可运行,如图所示, opyright ? 2005-2007 Listen tech. All Rights Reserved 灵感设计诚信 同时,桌面上也出现“LED Player”快捷方式:如右图所示,双击它同样可以启动程序。
2.2 卸载 《LED Player》软件提供了自动卸载功能,使您可以方便地删除《LED Player》的所有文件、程序组和快捷方式,用户可以在“LED软件”组中选择“卸载LED Player”,也可在【控制面板】中选择【添加/删除程序】快速卸载. 第三章使用详解 3.1 节目组成 每块显示屏由一个或多个节目页组成。节目页是用来显示用户所要播放的文本、图片、动画等内容。区域窗口有十一种:图文窗、文本窗、单行文本窗、静止文本窗、时间窗、正计时窗、倒计时窗、模拟时钟窗、表格窗、动画窗、温度窗。 文件窗:可以播放各种文字、图片、动画、表格等几十种文件。 文本窗:用于快速输入简短文字,例如通知等文字。 单行文本窗:用于播放单行文本,例如通知、广告等文字。 静止文本窗:用于播放静止文本,例如公司名称、标题等文字。 时间窗:用于显示数字时间。 计时窗:用于计时,支持正/倒计时显示。
STM32 LCD12864驱动程序(头文件)(2012-05-29 21:25:08)转载▼ 标签:杂谈 #ifndef LCD12864_H #define LCD12864_H #define LCD_CONTROL GPIOD //默认LCD12864的控制口在PD口 #define LCD_DATAPORT GPIOD //默认LCD12864的数据口在PD口 #define LCD_RESET_Pin GPIO_Pin_12 //默认LCD12864的复位引脚连接到PD.12 也可不用 #define LCD_RS_Pin GPIO_Pin_13 //默认LCD12864 RS -- PD.13 #define LCD_RW_Pin GPIO_Pin_14 //默认LCD12864 RW -- PD.14 #define LCD_EN_Pin GPIO_Pin_15 //默认LCD12864 E -- PD.15 #define LCD_CONTROL_CLOCK RCC_APB2Periph_GPIOD //默认LCD12864的控制口时钟 #define LCD_DATAPORT_CLOCK RCC_APB2Periph_GPIOD //默认LCD12864的数据口时钟 #define LCD_RS_1 LCD_CONTROL->BSRR &=~LCD_RS_Pin;LCD_CONTROL->BSRR |=LCD_RS_Pin //RS置高电平 #define LCD_RS_0 LCD_CONTROL->BRR &=~LCD_RS_Pin;LCD_CONTROL->BRR |=LCD_RS_Pin //RS置低电平 #define LCD_RW_1 LCD_CONTROL->BSRR &=~LCD_RW_Pin;LCD_CONTROL->BSRR |=LCD_RW_Pin //RW置高电平 #define LCD_RW_0 LCD_CONTROL->BRR &=~LCD_RW_Pin;LCD_CONTROL->BRR |=LCD_RW_Pin //RW置低电平 #define LCD_EN_1 LCD_CONTROL->BSRR &=~LCD_EN_Pin;LCD_CONTROL->BSRR |=LCD_EN_Pin //EN置高电平 #define LCD_EN_0 LCD_CONTROL->BRR &=~LCD_EN_Pin;LCD_CONTROL->BRR |=LCD_EN_Pin //EN置低电平 #define LCD_RESET_0 LCD_CONTROL->BRR = LCD_RESET_Pin // 复位 #define LCD_RESET_1 LCD_CONTROL->BSRR = LCD_RESET_Pin // 复位脚拉高 #define DATAOUT LCD_DATAPORT->ODR &=0xff00;LCD_DATAPORT->ODR // 数据输出寄存器 #define DATAIN LCD_DATAPORT->IDR // 数据输入寄存器 #define LCD_BF ((DATAIN)& 0x0080) // 忙状态 void LCD_delayus(unsigned long n); //延时n(us) void LCD_delayms(unsigned long n); //延时n(ms) void LCD_WriteInitcmd(uint8_t initcmd); //写初始化命令 void LCD_WaitLaisure(void); //一直等待到LCD内部操作完成,变为空闲状态 void LCD_Writecmd(uint8_t cmd); //写命令到LCD12864 void LCD_WriteByte(uint8_t byte); //写一字节数据到LCD12864 void LCD_pos(uint16_t pos); //LCD显示位置设置 void LCD_Setpos(uint16_t row,uint16_t col);//设定LCD12864的显示地址,根据习惯 void LCD_DispChar(char ch); //显示一个字符 void LCD_Setpos_DispChar(uint16_t row,uint16_t col,char ch);//在指定位置显示一个字符 void LCD_DispString(char str[]); //显示一个字符串,显示位置需提前设定
飞凌OK6410开发板(裸板)第一个点亮LED灯程序,主要的C程序,完整程序请下载附件。 #define rGPMCON (*(volatile unsigned *)(0x7F008820)) #define rGPMDAT (*(volatile unsigned *)(0x7F008824)) #define rGPMPUD (*(volatile unsigned *)(0x7F008828)) void msDelay(int time) { volatile unsigned int i,j; for(i = 0; i < 2000000; i++) for(j=0; j