【驱动】第25.4课、毕业班第4课_移植2期驱动到 Linux3.4.2内核

【驱动】第25.4课、毕业班第4课_移植2期驱动到 Linux3.4.2内核,第1张

概述主    机:VMWare--Ubuntu-16.04.2-x64-100ask 开发板:JZ2440--256M NandFlash,   2M NorFlash,   64M SDRAM,   LCD-4.3寸;     bootlorder:  u-boot-2012.04.01,       Kernel:  Linux3.4.2; 编译器:arm-linux-gcc-4.3.2   节一

主    机:VMWare--Ubuntu-16.04.2-x64-100ask

开发板:JZ2440--256M NandFlash,  2M norFlash,  64M SDRAM,  LCD-4.3寸;
    bootlorder:  u-boot-2012.04.01,      Kernel:  linux3.4.2;
编译器:arm-linux-gcc-4.3.2

 

节一、网卡驱动移植
1、网卡(包括ifconfig命令、Ping命令的有效性)在当machID为mini2440的7cf时才可用,在machID是smdk2440的16a时是不可用的。
因此也证明了,之前修改的linux-3.4.2内核中网卡部分关于smdk2440.c部分有些问题。
<1>machID是smdk2440的16a时,实 *** 如下:
/ # ifconfig eth0 192.168.1.11
dm9000 dm9000: eth0: link down
dm9000 dm9000: eth0: link up,100Mbps,full-duplex,lpa 0xC1E1
/ # Ping 192.168.1.105
Ping 192.168.1.105 (192.168.1.105): 56 data bytes
64 bytes from 192.168.1.105: seq=0 ttl=64 time=13.754 ms
...
^C
--- 192.168.1.105 Ping statistics ---
5 packets transmitted,5 packets received,0% packet loss
round-trip min/avg/max = 3.170/5.689/13.754 ms
<2>machID是smdk2440的16a时,实 *** 如下:
/ # ifconfig
/ # ifconfig eth0 192.168.1.11
ifconfig: SIOCSIFADDR: No such device
/ # Ping 192.168.1.105
Ping 192.168.1.105 (192.168.1.105): 56 data bytes
Ping: sendto: Network is unreachable

2、常用命令:
192.168.1.105
192.168.1.11
# ifconfig eth0 192.168.1.11
# Ping 192.168.1.105
mount -t nfs -o nolock,vers=2 192.168.1.105:/work/nfs_root/fs_mini_mdev_new_digitpic /mnt
nfs 30000000 192.168.1.105:/work/nfs_root/uImage_net_new; bootm 30000000
set bootargs console=ttySAC0,115200 root=/dev/nfs nfsroot=192.168.1.105:/work/nfs_root/fs_mini_mdev_new_digitpic ip=192.168.1.11:192.168.1.105:192.168.1.1:255.255.255.0::eth0:off
nfs 32000000 192.168.1.105:/work/nfs_root/uImage_mini2440_new

---------------------------------------------
节二、LED和按键驱动移植
一、LED驱动移植
1.Makefile修改:
KERN_DIR ?= /home/book/workbook/mini2440/systems/linux-3.4.2

2、课堂问题
问题:1、test文件open()函数,如:fd = open("/dev/leds",O_RDWR)打开的是设备、文件还是什么?
答:open打开的是设备,是class_create函数创建的设备的类class下,用class_device_create函数创建的该类设备的某一个设备class_device,
也称为设备节点。

3、调试问题
3.1、led_2驱动加载出现错误(基本崩溃,但还可用),系统报错如下,原因是什么?
错误打印:
/driver_test/char/leds # insmod led_2.ko
------------[ cut here ]------------
WARNING: at fs/sysfs/dir.c:508 sysfs_add_one+0x8c/0xb0()
sysfs: cannot create duplicate filename ‘/class/leds‘
Modules linked in: led_2(O+) [last unloaded: first_drv]
...
WARNING: at lib/kobject.c:198 kobject_add_internal+0x1c0/0x1f8()
kobject_add_internal Failed for leds with -EEXIST,don‘t try to register things with the same name in the same directory.
Modules linked in: led_2(O+) [last unloaded: first_drv]
...
/driver_test/char/leds # rmmod led_2
Unable to handle kernel NulL pointer dereference at virtual address 0000002b
pgd = c3ad4000
...
原因1.查看一下驱动源码
原因2.根文件系统时么有mdev; 答:不是此原因,fs已经有了mdev;
答:查看已经在sys/系统下创建的设备类class:
# ls /sys/class/
... input leds mtd net sb_device...
如此可知,sys/文件系统中已经有了leds设备类,系统提示:对于具有-EEXIST的led,kobject_add_internal失败,请不要尝试在相同目录中注册
具有相同名称的内容。

3.2、问题:驱动keys_2_drv.c执行ctrl +c强制中断当前程序时当前程序崩溃:
# ./keys_2_drvtest
key_val = 0x1
key_val = 0x81
key_val = 0x4
key_val = 0x84
^C------------[ cut here ]------------
WARNING: at kernel/irq/manage.c:1193 __free_irq+0xa0/0x184()
Trying to free already-free IRQ 16
Modules linked in: keys_2_drv(O)
...
错误源码:
static int keys_drv_open(struct inode * inode,struct file *filp)
{
request_irq(IRQ_EINT0,keys_irq,(IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALliNG),"key_2",&pins_desc[0]);
...
}
static int keys_drv_close(struct inode * inode,struct file *file)
{
free_irq(IRQ_EINT0,NulL);
...
}
改为:
static int keys_drv_close(struct inode * inode,&pins_desc[0]);
...
}
则当执行ctrl +c强制中断当前程序时,不会再发生程序崩溃了。
其中的原因是什么?
两个函数原型:
static inline int __must_check request_irq(unsigned int irq,irq_handler_t handler,unsigned long flags,const char *name,voID *dev)
{...}
voID free_irq(unsigned int irq,voID *dev_ID)
{...}


---------------------------------------------
节三、LCD及输入系统
1.Makefile修改:
KERN_DIR ?= /home/book/workbook/mini2440/systems/linux-3.4.2

 


---------------------------------------------
节四、块设备和虚拟网卡

1、调试错误及解决
1.1关于释放空指针造成系统崩溃的解决
/driver_test # insmod s3c_nor3.ko
use cfi_probe
use jedec_probe
map_probe Failed!
Unable to handle kernel NulL pointer dereference at virtual address 000000d8
...
Backtrace:
[<c01c31d4>] (map_destroy+0x0/0x44) from [<bf004158>] (s3c_nor_init+0x11c/0x19c [s3c_nor3])
r5:bf0044d4 r4:c39e8b20
[<bf00403c>] (s3c_nor_init+0x0/0x19c [s3c_nor3]) from [<c0008580>] (do_one_initcall+0x3c/0x194)
r5:000e2e38 r4:0000a6a3
[<c0008544>] (do_one_initcall+0x0/0x194) from [<c004d324>] (sys_init_module+0x8c/0x1a4)
[<c004d298>] (sys_init_module+0x0/0x1a4) from [<c0009280>] (ret_fast_syscall+0x0/0x2c)
r7:00000080 r6:bea93ea8 r5:00000000 r4:00000001
Code: 00200200 e1a0c00d e92dd830 e24cb004 (e59040d8)
---[ end trace 2caaa0976448c7ae ]---
Segmentation fault


造成崩溃的原代码:
static int s3c_nor_init(voID)
{
int err,ret;
/* 1.分配一个map_info结构体 */
s3c_nor_map = kzalloc(sizeof(struct map_info ),GFP_KERNEL);
if(!s3c_nor_map)
{
printk(KERN_ERR "Failed to allocate s3c_nor_map map_info structure!\n");
err = -ENOMEM;
goto err_fail1;
}
/* 2.设置该结构体 */
s3c_nor_map->name = "s3c_nor"; /* 名字 */
s3c_nor_map->phys = 0; /* 物理基地址 */
s3c_nor_map->size = 0x1000000; /* 16M大小 */
s3c_nor_map->bankwIDth = 2; /* 位宽: 2x8位 */
s3c_nor_map->virt = ioremap(s3c_nor_map->phys,s3c_nor_map->size); /* 虚拟基地址 */
if(!s3c_nor_map->virt)
{
printk(KERN_ERR "Failed to ioremap s3c_nor_map->virt regions!\n");
err = -ENOMEM;
goto err_fail2;
}
simple_map_init(s3c_nor_map);
/* 3.使用: 调用norflash协议层提供的函数来识别 */
printk("use cfi_probe\n");
s3c_nor_mtd = do_map_probe("cfi_probe",s3c_nor_map);
if(!s3c_nor_mtd)
{
printk("use jedec_probe\n");
s3c_nor_mtd = do_map_probe("jedec_probe",s3c_nor_map);
}
if(!s3c_nor_mtd)
{
printk("map_probe Failed!\n");
err = -ENXIO;
goto err_fail3;
}
s3c_nor_mtd->owner = THIS_MODulE;
/* 4.注册mtd分区表 */
//add_mtd_partitions(s3c_nor_mtd,s3c_nor_parts,2);
ret = mtd_device_register(s3c_nor_mtd,2);
if(ret < 0)
{
printk("Failed to register s3c_nor_mtd mtd device!\n");
goto err_fail3;
}

return 0;
err_fail3:
map_destroy(s3c_nor_mtd); //在这里!!!
err_fail2:
IoUnmap(s3c_nor_map->virt); //在这里!!!
err_fail1:
kfree(s3c_nor_map);
return err;
}
static voID s3c_nor_exit(voID)
{
//del_mtd_device(s3c_nor_mtd);
//del_mtd_partitions(s3c_nor_mtd);
mtd_device_unregister(s3c_nor_mtd); //在这里!!!
map_destroy(s3c_nor_mtd); //在这里!!!
IoUnmap(s3c_nor_map->virt);
kfree(s3c_nor_map);
}

修改之后的代码:static int s3c_nor_init(voID){ int err,ret; /* 1.分配一个map_info结构体 */ s3c_nor_map = kzalloc(sizeof(struct map_info ),GFP_KERNEL); if(!s3c_nor_map) { printk(KERN_ERR "Failed to allocate s3c_nor_map map_info structure!\n"); err = -ENOMEM; goto err_fail1; } /* 2.设置该结构体 */ s3c_nor_map->name = "s3c_nor"; /* 名字 */ s3c_nor_map->phys = 0; /* 物理基地址 */ s3c_nor_map->size = 0x1000000; /* 16M大小 */ s3c_nor_map->bankwIDth = 2; /* 位宽: 2x8位 */ s3c_nor_map->virt = ioremap(s3c_nor_map->phys,s3c_nor_map->size); /* 虚拟基地址 */ if(!s3c_nor_map->virt) { printk(KERN_ERR "Failed to ioremap s3c_nor_map->virt regions!\n"); err = -ENOMEM; goto err_fail2; } simple_map_init(s3c_nor_map); /* 3.使用: 调用norflash协议层提供的函数来识别 */ printk("use cfi_probe\n"); s3c_nor_mtd = do_map_probe("cfi_probe",s3c_nor_map); if(!s3c_nor_mtd) { printk("use jedec_probe\n"); s3c_nor_mtd = do_map_probe("jedec_probe",s3c_nor_map); } if(!s3c_nor_mtd) { printk("map_probe Failed!\n"); err = -ENXIO; goto err_fail3; } s3c_nor_mtd->owner = THIS_MODulE; /* 4.注册mtd分区表 */ //add_mtd_partitions(s3c_nor_mtd,2); ret = mtd_device_register(s3c_nor_mtd,2); if(ret < 0) { printk("Failed to register s3c_nor_mtd mtd device!\n"); goto err_fail3; } return 0; err_fail3: if(s3c_nor_mtd) //在这里!!! { map_destroy(s3c_nor_mtd); //在这里!!! } err_fail2: IoUnmap(s3c_nor_map->virt); err_fail1: kfree(s3c_nor_map); return err;}static voID s3c_nor_exit(voID){ //del_mtd_device(s3c_nor_mtd); //del_mtd_partitions(s3c_nor_mtd); if(s3c_nor_mtd) //在这里!!! { mtd_device_unregister(s3c_nor_mtd); //在这里!!! //map_destroy(s3c_nor_mtd); //在这里!!! } IoUnmap(s3c_nor_map->virt); kfree(s3c_nor_map);}举例:s3c_nor_mtd = do_map_probe("cfi_probe",s3c_nor_map);与: map_destroy(s3c_nor_mtd); //在这里!!!当map不成功时,map_destroy是不合法的!

@H_403_224@ 总结

以上是内存溢出为你收集整理的【驱动】第25.4课、毕业班第4课_移植2期驱动到 Linux3.4.2内核全部内容,希望文章能够帮你解决【驱动】第25.4课、毕业班第4课_移植2期驱动到 Linux3.4.2内核所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/1032146.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-24
下一篇 2022-05-24

发表评论

登录后才能评论

评论列表(0条)

保存