下面以UCLINUX为例,介绍在一个以模块方式出现的驱动程序test.c基础之上,将其编译进内核的一系列步骤:
(1)
改动test.c源带代码
第一步,将原来的:
#include
#include
char
kernel_version[]=UTS_RELEASE
改动为:
#ifdef
MODULE
#include
#include
char
kernel_version[]=UTS_RELEASE
#else
#define
MOD_INC_USE_COUNT
#define
MOD_DEC_USE_COUNT
#endif
第二步,新建函数int
init_test(void)
将设备注册写在此处:
result=register_chrdev(254,"test",&test_fops)
(2)将test.c复制到/uclinux/linux/drivers/char目录下,并且在/uclinux/linux/drivers/char目录下mem.c中,int
chr_dev_init(
)函数中增加如下代码:
#ifdef
CONFIG_TESTDRIVE
init_test()
#endif
(仔散3)在/uclinux/linux/drivers/char目录下Makefile中增加如下代码:
ifeq($(CONFIG_TESTDRIVE),y)
L_OBJS+=test.o
Endif
(4)在/uclinux/linux/arch/m68knommu目录下config.in中字符设备段里增加如下代码:
bool
'support
for
testdrive'
CONFIG_TESTDRIVE
y
(5)
运行make
menuconfig(在menuconfig的字符设备选项里你可以看见我们刚刚添加的'support
for
testdrive'选项,并且已经被选中念扰氏);make
dep;make
linux;make
linux.text;make
linux.data;cat
linux.text
linux.data
>
linux.bin。
(6)
在
/uclinux/romdisk/romdisk/dev/目录下创建设备:
mknod
test
c
254
0
并且在/uclinux/appsrc/下运行make,生成新的Romdisk.s19文件。
到这里,在UCLINUX中增加设备驱动程序的工作可以说是完成了,只要将新的linux.bin与Romdisk
uclinux表示micro-control linux.即“微控制器领域中的Linux系统”,是Lineo公司的主打产品,亩核宏氏磨同时也是开放源码的嵌入式迅册Linux的典范之作。由于uClinux只能在A核运行,因此它以驱动的形式提供了对B核的支持。默认配置下此好蔽扮支持是打开的,可以通过Kernel Settings->Blackfin Processor Options ->BF561 Specific Configurations
->Core B support进行关闭。估计没人会做这种事吧?呵呵!。
以下的所有代码来自于:linux-2.6.x\arch\blackfin\mach-bf561\coreb.c,也就是/dev/coreb驱动的
实现文件。
1、驱动状态查看
如果此驱动正确加载,在系统启动时有如下提示:友灶
BF561 Core B driver v0.1 initialized.
通过以下命令可以看到此驱动的运行状态:
root:~>cat /sys/class/misc/coreb/coreb_status
Base Address: 0xff600000
Core B is stalled
SICA_SYSCR: 0022
SICB_SYSCR: 0020
IRQ Status: Core A Core B
ISR0: 0000000000000000
ISR1: 0000000000000000
IMASK0: 3000000000000000
IMASK1: 008a800000000000
2、驱动实现的功能
下面看看这个驱动实现的功能。
static struct file_operations coreb_fops = {
.owner = THIS_MODULE,
.llseek = coreb_lseek,
.read = coreb_read,
.write = coreb_write,
.ioctl = coreb_ioctl,
.open = coreb_open,
.release = coreb_release
}
static struct miscdevice coreb_dev = {
COREB_MINOR,
"coreb",
&coreb_fops
}
在此模块加载时执行bf561_coreb_init函数,此函数中有一段代码:
misc_register(&coreb_dev)
if (class_device_create_file(coreb_dev.class,
&class_device_attr_coreb_status))
goto release_dma_src
这两行代码向kernel注册了这个驱动的信息,从这个信息并渗可以看出我们将可以对此设备进行打开和关闭。可以使用fread和fwrite进行数据读写,
可用fseek进行指针的定位,还可用ioctl进行输入输出的控制。
从上面可知对ioctl调用的处理是由coreb_ioctl函数完成的,如下所示:
// 定义ioctl调用中可用的命令
#define CMD_COREB_INDEX1
#define CMD_COREB_START2
#define CMD_COREB_STOP 3
#define CMD_COREB_RESET4
static int coreb_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
int retval = 0
int coreb_index = 0
switch (cmd) {
// 设置基址指针和可 *** 作的空间大小,后面打开文件进行读写时将以此为基址。
case CMD_COREB_INDEX:
if (copy_from_user(&coreb_index, (int *)arg,
sizeof(int))) {
retval = -EFAULT
break
}
spin_lock_irq(&coreb_lock)
switch (coreb_index) {
// 表示要对0xff60 0000 ~ 0xff60 4000这段16K的空间进行读写,也就是Core
B中的L1指令缓存。当CoreB开始允许执行时,第一条指令也是从0xFF60
0000开始执行的。因此在允许B核运行之前,应当将可执行的代码写入到这里。
case 0:
coreb_base = 0xff600000
coreb_size = 0x4000
break
// 表示要对0xff61 0000 ~ 0xff61 4000这段16K的地址空间进行 *** 作,即B核中的L1指令缓存。
case 1:
coreb_base = 0xff610000
coreb_size = 0x4000
break
// 表示要对0xff50 0000 ~ 0xff50 8000这段32K地址空间进行 *** 作,这是B核中的数据缓存。
case 2:
coreb_base = 0xff500000
coreb_size = 0x8000
break
// 表示要对0xff40 0000 ~ 0xff40 8000这段32K地址空间进行 *** 作,这是B核中的另一段数据缓存。
case 3:
coreb_base = 0xff400000
coreb_size = 0x8000
break
default:
retval = -EINVAL
break
}
spin_unlock_irq(&coreb_lock)
mutex_lock(&file->f_dentry->d_inode->i_mutex)
file->f_pos = 0
mutex_unlock(&file->f_dentry->d_inode->i_mutex)
break
// 要求B核从0xff60 0000这个位置开始执行代码
case CMD_COREB_START:
spin_lock_irq(&coreb_lock)
if (coreb_status &COREB_IS_RUNNING) {
retval = -EBUSY
break
}
printk(KERN_INFO "Starting Core B\n")
coreb_status |= COREB_IS_RUNNING
// 将SICA_SYSCR中的CoreB_SRAM_INIT这位设置为0,也即允许B核开始执行
bfin_write_SICA_SYSCR(bfin_read_SICA_SYSCR() &
~0x0020)
SSYNC()
spin_lock_irq(&coreb_lock)
break
#if defined(CONFIG_BF561_COREB_RESET)
// 要求B核停止运行
case CMD_COREB_STOP:
spin_lock_irq(&coreb_lock)
printk(KERN_INFO "Stopping Core B\n")
// 将SICA_SYSCR中的CoreB_SRAM_INIT位设置为1
bfin_write_SICA_SYSCR(bfin_read_SICA_SYSCR() | 0x0020)
//
将SICB_SYSCR中的CB_supplement_int0位写1,要求B核产生中断1进行复位,复位后由于SICA_SYSCR中的
CoreB_SRAM_INIT为1,B核将不再运行。
bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | 0x0080)
coreb_status &= ~COREB_IS_RUNNING
spin_lock_irq(&coreb_lock)
break
// 要求B核复位
case CMD_COREB_RESET:
printk(KERN_INFO "Resetting Core B\n")
bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | 0x0080)
break
#endif
}
return retval
}
至于对read和write的处理则比较简单,主要要注意的就是:在读写时驱动程序将自动将FILE结构中的文件位置加上基地址后再进行读写,且读写不能
超过每个块允许的大小,否则将读写失败,。如对0xff60 0000的读写就不能超过4K。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)