|
RT-Thread的V2.1.0版本中,对龙芯1C的中断支持不全。先来看一下中断分发函数rt_interrupt_dispatch()
- void rt_interrupt_dispatch(void *ptreg)
- {
- int irq;
- void *param;
- rt_isr_handler_t irq_func;
- static rt_uint32_t status = 0;
- rt_uint32_t c0_status;
- rt_uint32_t c0_cause;
- volatile rt_uint32_t cause_im;
- volatile rt_uint32_t status_im;
- rt_uint32_t pending_im;
- /* check os timer */
- c0_status = read_c0_status();
- c0_cause = read_c0_cause();
- cause_im = c0_cause & ST0_IM;
- status_im = c0_status & ST0_IM;
- pending_im = cause_im & status_im;
- if (pending_im & CAUSEF_IP7)
- {
- rt_hw_timer_handler();
- }
- if (pending_im & CAUSEF_IP2)
- {
- /* the hardware interrupt */
- status = ls1c_hw0_icregs->int_isr;
- if (!status)
- return;
- for (irq = MAX_INTR; irq > 0; --irq)
- {
- if ((status & (1 << irq)))
- {
- status &= ~(1 << irq);
- irq_func = irq_handle_table[irq].handler;
- param = irq_handle_table[irq].param;
- /* do interrupt */
- irq_func(irq, param);
- #ifdef RT_USING_INTERRUPT_INFO
- irq_handle_table[irq].counter++;
- #endif /* RT_USING_INTERRUPT_INFO */
- /* ack interrupt */
- ls1c_hw0_icregs->int_clr |= (1 << irq);
- }
- }
- }
- else if (pending_im & CAUSEF_IP3)
- {
- rt_kprintf("%s %d\r\n", __FUNCTION__, __LINE__);
- }
- else if (pending_im & CAUSEF_IP4)
- {
- rt_kprintf("%s %d\r\n", __FUNCTION__, __LINE__);
- }
- else if (pending_im & CAUSEF_IP5)
- {
- rt_kprintf("%s %d\r\n", __FUNCTION__, __LINE__);
- }
- else if (pending_im & CAUSEF_IP6)
- {
- rt_kprintf("%s %d\r\n", __FUNCTION__, __LINE__);
- }
- }
复制代码 在fi分支的CAUSEF_IP3,CAUSEF_IP4,CAUSEF_IP5,CAUSEF_IP6中用到了函数rt_kprintf()打印提示消息。可是这是在中断中,用打印函数欠妥吧。这还不是关键,关键是在if的CAUSEF_IP2分支中,变量irq_handle_table的大小为32,如下
也就是说,最多只支持32个中断,可是龙芯1C上GPIO都不止32个,每个GPIO都支持输入中断,即每个GPIO都有一个中断,那还有其它的串口中断,网口等等。
可是问题出在哪里呢?在参考了《龙芯1C处理器用户手册》V1.3、《see mips run 中文版》第二版、《mips linux异常中断代码分析》和linux源码之后,得到如下结论,龙芯1C有五组中断,每组32个,分别对应CAUSEF_IP2,CAUSEF_IP3,CAUSEF_IP4,CAUSEF_IP5,CAUSEF_IP6。
linux中对应源码
- static void ls1x_irq_dispatch(int n)
- {
- u32 intstatus, irq;
- /* Receive interrupt signal, compute the irq */
- intstatus = (ls1x_icregs+n)->int_isr & (ls1x_icregs+n)->int_en;
- if (intstatus) {
- irq = ffs(intstatus);
- do_IRQ((n<<5) + irq - 1);
- }
- }
- asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
- {
- unsigned int pending;
- pending = read_c0_cause() & read_c0_status() & ST0_IM;
- if (pending & CAUSEF_IP7) {
- do_IRQ(TIMER_IRQ);
- }
- else if (pending & CAUSEF_IP2) {
- ls1x_irq_dispatch(0);
- }
- else if (pending & CAUSEF_IP3) {
- ls1x_irq_dispatch(1);
- }
- else if (pending & CAUSEF_IP4) {
- ls1x_irq_dispatch(2);
- }
- else if (pending & CAUSEF_IP5) {
- ls1x_irq_dispatch(3);
- }
- else if (pending & CAUSEF_IP6) {
- ls1x_irq_dispatch(4);
- } else {
- spurious_interrupt();
- }
- }
复制代码
顺便还提一下,RT-Thread中函数rtthread_startup()里面拷贝的异常向量大小应该是0x80,不是0x20.即每个异常向量占0x80个字节。
linux中的代码如下
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|