limingth 发表于 2005-11-23 22:30:03

答关于 Step by Step 综合实验二的几个问题

int0文件夹
a)        int0_driver.c中实现的主要函数:
int int0_open( void )                                 /* set int0 related gpio */
int int0_ioctl( unsigned int cmd, unsigned long arg )      //设置了int0各种控制参数
b)        int0_api.c中实现的主要函数:
void int0_irq_handler( void )                     
// 包装了一层的中断处理函数,在调用用户给的处理函数后,清除中断
void int0_install_irq_hooker( void (*handler)(void) )
//提供给用户用来注册自己写的中断处理函数
int int0_init( void )
   //初始化与中断有关的各种操作:请求中断号,设置中断模式,设置各种中断参数

整个程序的处理过程就是:在进入主函数之前初始化系统态和中断态下的堆栈指针,进入主函数后,先调用install_irq_handler()函数将中断处理指令的首地址放到0x18地址中,然后将用户提供的中断处理函数注册,然后初始化led,接着初始化设备int0(包括注册中断处理函数的中断号,设置中断模式和各种参数),主函数进入无限循环中,当中断发生时,系统自动跳转到IRQ 状态,同时 CPU 会自动到 0x18 地址处执行这里的处理指令。
疑问:虽然install_irq_handler()函数的功能已清楚,但具体的一些代码还是很费解,比如:
instruction = ((unsigned int) isr_entry_addr- (unsigned int)irq_vec_addr - 0x08) | 0xe59ff000;
//这个计算过程到底得到的是个什么地址,为什么这么算?还有那个irq_handler()一直都是//个空函数,是为什么?这样指向的不是个空函数的地址么?而且好像还少了一个判断该中断是中断向量表中的哪一个的过程吧?


Re: 这个计算过程得到的不是地址,而是一条机器指令,确切的说是一条相对跳转指令。0xe59ff000 代表跳转指令,这个值可以查看 arm 指令格式的文档。
在这个实验里面,所有中断的检查和跳转都是在 do_irq 里面完成的,可以看一下 irq_api.c 中的相关源码。irq_handler 是在 startup.s 启动汇编代码中定义的一个符号,具体实现为处理保存好 cpu 现场,然后跳转到 do_irq 中。


irq文件夹
a)        这一个文件夹里的函数主要是方便供前面两个调用才独立出来的。主要实现的函数有:
int request_irq( unsigned int irq, void (*handler)(int irq) )
   //请求中断号,并关联相关的中断处理函数
int free_irq( unsigned int irq, void (*handler)(int irq) )
   //释放中断号
void do_irq( void )
   //处理中断
void install_irq_handler( void (*isr)(void) )
   //设置物理地址,处理跟硬件相关的一些操作
这四个函数基本是中断功能必用的一些函数,在这里又多了一个疑问:
就是do_irq(void)函数好像不见那个函数调用过,只在startup.s见过一个B do_irq的语句,但具体怎么用到还是不太清楚。


Re:这个函数是在 startup.s 中,irq_handler 来调用的,所有 irq 中断来了之后都通过 do_irq 来处理。


其实这个实验主要目的是为了学习 linux 设备驱动的模型,并把它简化运用到 lumit 平台上,同时也是为其他做底层硬件测试和移植的朋友们提供一个可移植和可扩展的接口标准,尽量做到在针对自己特定的板子做移植时只用修改 xxx_driver. ,而把更多可扩展的部分留在 xxx_api. 中实现。
页: [1]
查看完整版本: 答关于 Step by Step 综合实验二的几个问题