龙芯俱乐部开源技术社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 6399|回复: 6

RT-Thread中龙芯1C的中断支持不全

[复制链接]

48

主题

257

帖子

4920

积分

新手上路

Rank: 1

积分
4920
发表于 2017-3-17 11:21:54 | 显示全部楼层 |阅读模式
RT-Thread的V2.1.0版本中,对龙芯1C的中断支持不全。先来看一下中断分发函数rt_interrupt_dispatch()

  1. void rt_interrupt_dispatch(void *ptreg)
  2. {
  3.     int irq;
  4.     void *param;
  5.     rt_isr_handler_t irq_func;
  6.     static rt_uint32_t status = 0;
  7.     rt_uint32_t c0_status;
  8.     rt_uint32_t c0_cause;
  9.     volatile rt_uint32_t cause_im;
  10.     volatile rt_uint32_t status_im;
  11.     rt_uint32_t pending_im;

  12.     /* check os timer */
  13.     c0_status = read_c0_status();
  14.     c0_cause = read_c0_cause();

  15.     cause_im = c0_cause & ST0_IM;
  16.     status_im = c0_status & ST0_IM;
  17.     pending_im = cause_im & status_im;

  18.     if (pending_im & CAUSEF_IP7)
  19.     {
  20.         rt_hw_timer_handler();
  21.     }

  22.     if (pending_im & CAUSEF_IP2)
  23.     {
  24.         /* the hardware interrupt */
  25.         status = ls1c_hw0_icregs->int_isr;
  26.         if (!status)
  27.             return;

  28.         for (irq = MAX_INTR; irq > 0; --irq)
  29.         {
  30.             if ((status & (1 << irq)))
  31.             {
  32.                 status &= ~(1 << irq);

  33.                 irq_func = irq_handle_table[irq].handler;
  34.                 param = irq_handle_table[irq].param;

  35.                 /* do interrupt */
  36.                 irq_func(irq, param);

  37. #ifdef RT_USING_INTERRUPT_INFO
  38.                 irq_handle_table[irq].counter++;
  39. #endif /* RT_USING_INTERRUPT_INFO */

  40.                 /* ack interrupt */
  41.                 ls1c_hw0_icregs->int_clr |= (1 << irq);
  42.             }
  43.         }
  44.     }
  45.     else if (pending_im & CAUSEF_IP3)
  46.     {
  47.         rt_kprintf("%s %d\r\n", __FUNCTION__, __LINE__);
  48.     }
  49.     else if (pending_im & CAUSEF_IP4)
  50.     {
  51.         rt_kprintf("%s %d\r\n", __FUNCTION__, __LINE__);
  52.     }
  53.     else if (pending_im & CAUSEF_IP5)
  54.     {
  55.         rt_kprintf("%s %d\r\n", __FUNCTION__, __LINE__);
  56.     }
  57.     else if (pending_im & CAUSEF_IP6)
  58.     {
  59.         rt_kprintf("%s %d\r\n", __FUNCTION__, __LINE__);
  60.     }
  61. }
复制代码
在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中对应源码

  1. static void ls1x_irq_dispatch(int n)
  2. {
  3.         u32 intstatus, irq;

  4.         /* Receive interrupt signal, compute the irq */
  5.         intstatus = (ls1x_icregs+n)->int_isr & (ls1x_icregs+n)->int_en;
  6.         if (intstatus) {
  7.                 irq = ffs(intstatus);
  8.                 do_IRQ((n<<5) + irq - 1);
  9.         }
  10. }

  11. asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
  12. {
  13.         unsigned int pending;

  14.         pending = read_c0_cause() & read_c0_status() & ST0_IM;

  15.         if (pending & CAUSEF_IP7) {
  16.                 do_IRQ(TIMER_IRQ);
  17.         }
  18.         else if (pending & CAUSEF_IP2) {
  19.                 ls1x_irq_dispatch(0);
  20.         }
  21.         else if (pending & CAUSEF_IP3) {
  22.                 ls1x_irq_dispatch(1);
  23.         }
  24.         else if (pending & CAUSEF_IP4) {
  25.                 ls1x_irq_dispatch(2);
  26.         }
  27.         else if (pending & CAUSEF_IP5) {
  28.                 ls1x_irq_dispatch(3);
  29.         }
  30.         else if (pending & CAUSEF_IP6) {
  31.                 ls1x_irq_dispatch(4);
  32.         } else {
  33.                 spurious_interrupt();
  34.         }
  35. }
复制代码

顺便还提一下,RT-Thread中函数rtthread_startup()里面拷贝的异常向量大小应该是0x80,不是0x20.即每个异常向量占0x80个字节。

linux中的代码如下








本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

19

主题

79

帖子

3533

积分

论坛元老

Rank: 8Rank: 8

积分
3533
发表于 2017-3-17 13:23:12 | 显示全部楼层
分析精辟

48

主题

257

帖子

4920

积分

新手上路

Rank: 1

积分
4920
 楼主| 发表于 2017-3-17 16:46:50 | 显示全部楼层
smiletan 发表于 2017-3-17 16:19
强烈要求给一个开源龙芯1C的GPIO外部中断例子

我正在研究裸机下怎么实现中断,后面会写个测试例子来测试的,请关注http://git.oschina.net/caogos/OpenLoongsonLib1c

另外,在linux下应该很容易实现按键中断的,百度上应该有很多资料

48

主题

257

帖子

4920

积分

新手上路

Rank: 1

积分
4920
 楼主| 发表于 2017-7-24 11:34:32 | 显示全部楼层
git上最新的RT-Thread可以支持所有中断了,包括GPIO中断。
https://github.com/RT-Thread/rt-thread

2

主题

9

帖子

1428

积分

金牌会员

Rank: 6Rank: 6

积分
1428
发表于 2017-7-25 20:55:51 | 显示全部楼层
膜拜!向大神致敬!

28

主题

260

帖子

17万

积分

论坛元老

Rank: 8Rank: 8

积分
170816
发表于 2017-7-26 08:53:21 | 显示全部楼层
龙芯1C有五组中断,每组32个。
感谢版主的钻研与分享!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|龙芯俱乐部开源技术社区

GMT+8, 2024-11-28 09:49 , Processed in 0.136049 second(s), 23 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表