|
版主 这个错误是什么意思
如题:我在 我的驱动程序里面
static struct spi_driver spi_test_driver = {
.probe = spi_test_probe,
.remove = spi_test_remove,
.driver = {
.name = "netx-spi",
},
};
先 result=spi_register_driver(&spi_test_driver);
然后调用 SPI的驱动spi.c里面的spi_write();怎么会出这个错??
void Mp3WriteRegister(struct spi_device *spi,unsigned char addressbyte, unsigned char highbyte, unsigned char lowbyte)
{
Mp3DeselectData();
Mp3SelectControl();//XCS = 0
unsigned char writebuf[4]={VS_WRITE_COMMAND,addressbyte,highbyte,lowbyte};
spi_write(spi, writebuf, 4);
Mp3DeselectControl();
}
[ 189.590000] Unable to handle kernel NULL pointer dereference at virtual address 00000130
[ 189.600000] pgd = c365c000
[ 189.600000] [00000130] *pgd=83b78031, *pte=00000000, *ppte=00000000
[ 189.600000] Internal error: Oops: 17 [#1]
[ 189.600000] Modules linked in:
[ 189.600000] CPU: 0 Tainted: GF (2.6.23.1-rt5-ptx3-netx2 #63)
[ 189.600000] PC is at spi_sync+0x3c/0x6c
[ 189.600000] LR is at Mp3WriteRegister+0xcc/0xf4
[ 189.600000] pc : [<c0216438>] lr : [<c01f9980>] psr: 40000013
[ 189.600000] sp : c3c9bd48 ip : c3c9bd78 fp : c3c9bd74
[ 189.600000] r10: 00000000 r9 : 00000008 r8 : 00000020
[ 189.600000] r7 : 00000000 r6 : 00000000 r5 : c3c9bd7c r4 : c3c9bd4c
[ 189.600000] r3 : c0216468 r2 : c3c9bd50 r1 : c3c9bd7c r0 : 00000000
[ 189.600000] Flags: nZcv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
[ 189.600000] Control: 0005317f Table: 8365c000 DAC: 00000015
[ 189.600000] Process spi_ctrl_test (pid: 953, stack limit = 0xc3c9a260)
[ 189.600000] Stack: (0xc3c9bd48 to 0xc3c9c000)
[ 189.600000] bd40: c3c1de60 00000000 c3c9bd50 c3c9bd50 00000000 c3c9bd7c
[ 189.600000] bd60: 00000000 00000004 c3c9bdfc c3c9bd78 c01f9980 c021640c c008560c c3c9bdc4
[ 189.600000] bd80: c3c9bdc4 00000000 00000000 c0216468 c3c9bd4c 00000000 00000000 00000000
[ 189.600000] bda0: 00000000 00000000 c3c9bdcc 00000000 00000004 00000000 00000000 00000000
[ 189.600000] bdc0: 00000000 c3c9bd7c c3c9bd7c 20080002 c3c1de60 00000000 c0588ea0 c3571000
[ 189.600000] bde0: c3c1de60 c06b3880 c3c9a000 00000000 c3c9be74 c3c9be00 c01f9a58 c01f98c4
[ 189.600000] be00: c3c9be24 c3c9be10 c01c4074 c01c4f58 ffffff9c 00000000 c3c9be3c c3c9be28
[ 189.600000] be20: c00978f0 c01c4064 c04fe900 00000000 c3c9be4c c3c9be40 c0097920 c00978b8
[ 189.600000] be40: c3c9be84 c3c9be50 c0204044 c005f264 00000000 c0588ea0 c3571000 c3c1de60
[ 189.600000] be60: c06b3880 00000000 c3c9be84 c3c9be78 c01f9cfc c01f99b8 c3c9beac c3c9be88
[ 189.600000] be80: c00979dc c01f9cec c3c9beac 00000000 c3c1de60 c3571000 c0097930 c3b6aa00
[ 189.600000] bea0: c3c9bed4 c3c9beb0 c0092a58 c0097940 c3c1de60 c3c9bf00 c06ad000 00000003
[ 189.600000] bec0: ffffff9c 00000000 c3c9bef4 c3c9bed8 c0092c3c c00929a4 00000000 ffffff9c
[ 189.600000] bee0: c3c9a000 00000802 c3c9bf64 c3c9bef8 c0092c90 c0092c08 c3c9bf00 c01e568c
[ 189.600000] bf00: c3b6aa00 c06b3880 00000013 00000000 00000000 00000101 00000001 00000000
[ 189.600000] bf20: c3d96b48 c3d96b40 c3c9a000 00000802 c3c9bf64 c3c9bf40 c00928e0 c00abce8
[ 189.600000] bf40: c009e45c 00000803 00000000 c3c1de60 00000802 4001e000 c3c9bf94 c3c9bf68
[ 189.600000] bf60: c0092cec c0092c54 c3c9bfa4 c3c9bf78 c00958c4 40023db8 00000000 00000000
[ 189.600000] bf80: 00000005 c0027fc8 c3c9bfa4 c3c9bf98 c0092db4 c0092ca4 00000000 c3c9bfa8
[ 189.600000] bfa0: c0027e20 c0092da0 40023db8 00000000 000086fc 00000802 4001e000 00000001
[ 189.600000] bfc0: 40023db8 00000000 00000000 00000005 00000000 00000000 4013a000 becaed3c
[ 189.600000] bfe0: 00000000 becaed20 000084ac 400d244c 60000010 000086fc 00000000 00000000
[ 189.600000] Backtrace:
[ 189.600000] [<c02163fc>] (spi_sync+0x0/0x6c) from [<c01f9980>] (Mp3WriteRegister+0xcc/0xf4)
[ 189.600000] r7:00000004 r6:00000000 r5:c3c9bd7c r4:00000000
[ 189.600000] [<c01f98b4>] (Mp3WriteRegister+0x0/0xf4) from [<c01f9a58>] (VsSineTest+0xb0/0x334)
[ 189.600000] [<c01f99a8>] (VsSineTest+0x0/0x334) from [<c01f9cfc>] (spi_codec_open+0x20/0x38)
[ 189.600000] [<c01f9cdc>] (spi_codec_open+0x0/0x38) from [<c00979dc>] (chrdev_open+0xac/0x190)
[ 189.600000] [<c0097930>] (chrdev_open+0x0/0x190) from [<c0092a58>] (__dentry_open+0xc4/0x1ec)
[ 189.600000] r7:c3b6aa00 r6:c0097930 r5:c3571000 r4:c3c1de60
[ 189.600000] [<c0092994>] (__dentry_open+0x0/0x1ec) from [<c0092c3c>] (nameidata_to_filp+0x44/0x4c)
[ 189.600000] [<c0092bf8>] (nameidata_to_filp+0x0/0x4c) from [<c0092c90>] (do_filp_open+0x4c/0x50)
[ 189.600000] r4:00000802
[ 189.600000] [<c0092c44>] (do_filp_open+0x0/0x50) from [<c0092cec>] (do_sys_open+0x58/0xe8)
[ 189.600000] r5:4001e000 r4:00000802
[ 189.600000] [<c0092c94>] (do_sys_open+0x0/0xe8) from [<c0092db4>] (sys_open+0x24/0x28)
[ 189.600000] r8:c0027fc8 r7:00000005 r6:00000000 r5:00000000 r4:40023db8
[ 189.600000] [<c0092d90>] (sys_open+0x0/0x28) from [<c0027e20>] (ret_fast_syscall+0x0/0x2c)
[ 189.600000] Code: e5850008 e50b2020 e50b7028 e50b2024 (e5903130)
|
| 2009-3-25 14:14:28 | |
huangning | | |
等级:超级版主
文章:1468
积分:3269
注册:2007-6-6
|
这几天也在看,,补充一点..
其实理解了框架应该很简单的.首先要基本了解下linux的驱动模型,
其次,分两种驱动.一个是master(也就是板子上控制器的驱动). 另一个是device(通过spi接到的设备的驱动,比如接到个nand flash).
对于master驱动, 一般可以挂在platform总线.
device端:
platform_device_register()把控制器注册成一个platform设备.同时把spi_device加到board_info中.
driver端:
platform_driver_register()注册控制器的驱动,在probe中> spi_register_master > scan_board_info > spi_new_device >spi_add_device(). 会把spi_device注册到spi_bus上.当然把spi_device一些结构跟master挂上钩.
对于具体的devcie驱动,得另外写, 比如nandflash.
得注册一个spi_driver到spi_bus,跟我们前面master注册的spi_device匹配.
在probe中 > 注册mtd设备, 并且初始一些函数接口(比如读写,让它调spi层的具体实现函数).
|
| 2009-3-27 9:42:23 | |
huangning | | |
等级:超级版主
文章:1468
积分:3269
注册:2007-6-6
|
认真查看了Document/spi/spi-summary文件,发现里面有这一段话:
The SPI core will autmatically attempt to bind this driver to any SPI
device whose board_info gave a modalias of "CHIP".
比如你的SLAVE DEVICES 定义为:
static struct ads7846_platform_data ads_info = {
.vref_delay_usecs = 100,
.x_plate_ohms = 580,
.y_plate_ohms = 410,
};
static struct spi_board_info spi_board_info[] __initdata = {
{
.modalias = "ads7846",
.platform_data = &ads_info,
.mode = SPI_MODE_0,
.irq = GPIO_IRQ(31),
.max_speed_hz = 120000 /* max sample rate at 3V */ * 16,
.bus_num = 1,
.chip_select = 0,
},
};
那你的驱动的device可以这样定义:
static struct device_driver CHIP_driver = {
.name = "CHIP",
.bus = &spi_bus_type,
.probe = CHIP_probe,
.remove = __exit_p(CHIP_remove),
.suspend = CHIP_suspend,
.resume = CHIP_resume,
};
关键是这里的“CHIP”要和从设备定义的名字相同,因为内核就是*这个来匹配的,再一次引用文档的话:
The SPI core will autmatically attempt to bind this driver to any SPI
device whose board_info gave a modalias of "CHIP".
所以我把从设备的定义改为:
static struct spi_board_info s3c2410_spi_board[] = {
[0] = {
.modalias = "ads7846", //注意:只要和驱动的名字相同就行,改驱动下的名字也是可以的
.platform_data = NULL,
.irq = IRQ_EINT1,
.chip_select = 1,
.max_speed_hz = 500*1000,
},
};
就行了^_^
看来要提高E文的水平,多看一下内核自带的文档才行~
编辑者: luofuchong (07-04-24 23:33)
|
| 2009-3-27 9:42:42 | |
huangning | | |
等级:超级版主
文章:1468
积分:3269
注册:2007-6-6
|
既然这样,让我们来看看你的第一个问题吧。
如果你需要使用spi驱动的接口,不是去修改驱动的实现代码,因为它只负责完成spi的硬件交互功能。
你使用spi功能的代码只需要用到spi.h中定义的方法就可以了,这就是linux driver layers framework的可人之处。
我们通过一个简单的例子来实际理解一下:
#include <linux/config.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#define TEST_REG 0x02
static int test_read_reg(struct spi_device *spi, int reg)
{
char buf[2];
buf[0] = reg << 2;
buf[1] = 0;
spi_write_then_read(spi, buf, 2, buf, 2);
return buf[1] << 8 | buf[0];
}
static int spi_test_probe(struct spi_device *spi)
{
printk("TEST_REG: 0x%02x\n", test_read_reg(spi, TEST_REG));
return 0;
}
static int spi_test_remove(struct spi_device *spi)
{
return 0;
}
static struct spi_driver spi_test_driver = {
.probe = spi_test_probe,
.remove = spi_test_remove,
.driver = {
.name = "testHW",
},
};
static int __init spi_test_init(void)
{
return spi_register_driver(&spi_test_driver);
}
static void __exit spi_test_exit(void)
{
spi_unregister_driver(&spi_test_driver);
}
module_init(spi_test_init);
module_exit(spi_test_exit);
MODULE_DESCRIPTION("spi device test");
MODULE_LICENSE("GPL");
在这个驱动中,你只需要用spi_register_driver向系统进行注册,就可以让系统用你指定的与 .name 相匹配的硬件交互代码
去执行你的读写请求。
几乎在所有与spi相关的函数中都会用到struct spi_device *spi这个指针,probe函数正好把这个指针传给你,保存好这个指针,你就可以在驱动的任何地方通过他去处理与spi设备相关的操作。
ZT by panjet
|
|
|
|