RT-Thread中龙芯1C的中断支持不全
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.handler;
param = irq_handle_table.param;
/* do interrupt */
irq_func(irq, param);
#ifdef RT_USING_INTERRUPT_INFO
irq_handle_table.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中的代码如下
:)分析精辟 smiletan 发表于 2017-3-17 16:19
强烈要求给一个开源龙芯1C的GPIO外部中断例子
我正在研究裸机下怎么实现中断,后面会写个测试例子来测试的,请关注http://git.oschina.net/caogos/OpenLoongsonLib1c
另外,在linux下应该很容易实现按键中断的,百度上应该有很多资料 git上最新的RT-Thread可以支持所有中断了,包括GPIO中断。
https://github.com/RT-Thread/rt-thread 膜拜!向大神致敬! 龙芯1C有五组中断,每组32个。
感谢版主的钻研与分享!
页:
[1]