首先,求助一下。今天忙了一下午,就为了找到一个可以和国嵌内核匹配的u-boot,但是还是没有找到。网上的大神们谁有国嵌的mini2440的u-boot可以传给我一个,感激不尽。
由于没有u-boot,内核模块编译出来了也不能在板子上运行,所以很多代码没有亲测。
首先说编译内核模块,编译内核模块的Makefile如下:
ifneq ($(KERNELRELEASE),)
obj-m := mini2440_leds.o
else
KDIR := /home/guoqian/4-3-1/linux-2.6.29
all:
make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-
clean:
rm -f *.ko *.o *.mod.o *.mod.c *.symvers modul*
endif
KDIR := /home/guoqian/4-3-1/linux-2.6.29 这个路径是要找到自己板载内核的路径,同时要注意这个路径下的内核是已经被编译过的,最好直接一次编译成zImage。要不然会出现各类的问题,不过还好前人走的路很多,随手百度问题也就解决了。
但是今天又开始面临了第二个困扰。上图。
这就是今天面临的情况。驱动程序中调用的IO函数一会再列出来,但是这两个驱动函数初步可以看出是在内核中实现的。出现的错误是寄存器的定义问题。所以要想把程序走通,必须使用国嵌移植的内核。所以弄到了国嵌的u-boot以后估计就可以开始测试代码了。
下面开始分析点亮和熄灭四个二极管的驱动程序。
1.dev_init
static int __init dev_init(void)
{
int ret;
int i;
for (i = 0; i < 4; i++) {
s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);
//设置IO口的模式,定义为输出。
s3c2410_gpio_setpin(led_table[i], 0);
//定义引脚全部为低电平,在结束后,四个 LED 应该是全部都是发光。
}
/*注册混杂设备*/
ret = misc_register(&misc);
printk (DEVICE_NAME"\tinitialized\n");
return ret;
}
注意:混杂设备注册是在dev_init函数中完成的。
2.在dev_init函数中完成了混杂设备的注册,下面列出混杂设备的属性定义。
static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR, //这个宏(内核中)定义的混杂设备的此设备号,
//由内核动态的进行分配的。
.name = DEVICE_NAME, //定义了设备的名字--可以随意定义。
.fops = &dev_fops, //混杂设备的实质是字符设备,字符设备都有file_operations。
};
3.file_operations
static struct file_operations dev_fops = {
.owner = THIS_MODULE,
.ioctl = sbc2440_leds_ioctl,
//驱动程序不一定要实现open和release,但是内核会自动实现这两个设备方法。
};
注意:最后一句备注。现在接触的程序太少了,没能真正的理解。
4.s3c2440_leds_ioctl函数。
static int s3c2440_leds_ioctl(
struct inode *inode,
struct file *file,
unsigned int cmd,
unsigned long arg)
/*传递进来的是整形的参数arg,所以没有进行对参数的检测,只有传进来是指针的时候才进行检测。*/
{
switch(cmd) {
case 0:
case 1:
if (arg > 4) {
return -EINVAL;
}
s3c2410_gpio_setpin(led_table[arg], !cmd);
//根据命令传进来的参数来直接设置灯的亮和灭----arg。
return 0;
default:
return -EINVAL;
}
}
注意:命令的实质是一个三十二位的无符号长整形数,定义命令是要让命令具有更高的可读性,使命令执行的时候更加安全。
5.最后送上两个数组
static unsigned long led_table [] = {
S3C2410_GPB5,
S3C2410_GPB6,
S3C2410_GPB7,
S3C2410_GPB8,
};
//LED 对应端口将要输出的状态列表
static unsigned int led_cfg_table [] = {
S3C2410_GPB5_OUTP,
S3C2410_GPB6_OUTP,
S3C2410_GPB7_OUTP,
S3C2410_GPB8_OUTP,
};
在网上找到了这两个数组参数具体实现的代码了,就不贴了,因为自己看不懂,所以就这样先。
6.直接粘上测试部分的应用程序
#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;
/*argv[1]本身是一个字符串,把这个字符串通过%d传递给led_no
on < 0 || on > 1 设定on的有效值只能取0或1。
led_no < 0 || led_no > 3 设定led_no的有效值。
*/
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);
}
fd = open("/dev/leds", 0);
if (fd < 0) {
perror("open device leds");
exit(1);
}
ioctl(fd, on, led_no);
close(fd);
return 0;
}