NuttX 中断管理

来源:互联网 发布:苹果手机导出照片到mac 编辑:程序博客网 时间:2024/06/05 23:39
(嵌入式 实时操作系统 rtos nuttx 7.18 stm32 源代码分析)

NuttX 中断管理

转载请注明出处: http://blog.csdn.net/zhumaill/article/details/70141440

nuttx中断处理流程:
           硬件查表  向量号    地址     handlers              |-->     0    8000000  IDLE_STACK---------->|              |-->     1    8000004  __start              |              |-->     2    8000008  stm32_nmi----------->|              |-->     3    800000c  stm32_hardfault----->|  硬件产生中断-|-->     4    8000010  stm32_mpu----------->|              |-->     5    8000014  stm32_busfault------>|              |-->     6    8000018  stm32_usagefault---->|              |-->     7    800001c  stm32_reserved       |              |-->     8    8000020  stm32_reserved       |              |-->     9    8000024  stm32_reserved       |              |-->    10    8000028  stm32_reserved       |              |-->    11    800002c  stm32_svcall-------->|              |-->    12    8000030  stm32_dbgmonitor---->|              |-->    13    8000034  stm32_reserved------>|               |-->    14    8000038  stm32_pendsv-------->|                |-->    15    800003c  stm32_systick------->|               |-->    16    8000040  stm32_wwdg---------->|  中断号0              |-->   ...     ...     ......-------------->|  ......              |-->    83    800014c  stm32_otgfs--------->|  中断号67                                                          |                                                          |  |<------------------------------------------------------|  |  |                                                             |-->irq_unexpected_isr()  |-->exception_common()-->up_doirq()-->irq_dispatch()(code4)-->|                                                                |-->g_irqvector[irq]()
虽然一个向量号对应一个handlers,但功能是一样的,将向量号写入R0,然后跳转到exception_common()。nuttx没有使用cortex-m3的硬件跳转功能,而是由irq_dispatch()实现软件跳转。

g_irqvector[NR_IRQS]
中断处理程序列表,一个中断号对应一项,当中断发生后,irq_dispatch()根据中断号从列表中读取对应处理程序的地址。

(code1):
nuttx/sched/irq/irq_initialize.c
  /* 系统初始化时调用 */void irq_initialize(void){  int i;  /* 将所有中断向量都指向非正常中断处理程序 */  for (i = 0; i < NR_IRQS; i++)     {      g_irqvector[i] = irq_unexpected_isr;    }}
(code2):
nuttx/arch/arm/src/chip/stm32_irq.c
/* 设置中断优先级,关联硬件异常处理函数,系统初始化时调用 */void up_irqinitialize(void){  uint32_t regaddr;  int num_priority_registers;  int i;  /* 禁用所有中断 */  for (i = 0; i < NR_IRQS - STM32_IRQ_FIRST; i += 32)    {      putreg32(0xffffffff, NVIC_IRQ_CLEAR(i));    }  /* 在中断栈填充固定数据(0xdeadbeef)以方便调试 */#if defined(CONFIG_STACK_COLORATION) && CONFIG_ARCH_INTERRUPTSTACK > 3  {    size_t intstack_size = (CONFIG_ARCH_INTERRUPTSTACK & ~3);    up_stack_color((FAR void *)((uintptr_t)&g_intstackbase - intstack_size),                   intstack_size);  }#endif  /* 向量表的标准位置起始于 FLASH地址0x0800:0000   * 如果我们使用 STMicro DFU bootloader,   * 向量表将偏移到FLASH的不同位置,   * 我们需要设置 NVIC向量到改变后位置   */#if defined(__ICCARM__)  putreg32((uint32_t)__vector_table, NVIC_VECTAB);#else  putreg32((uint32_t)_vectors, NVIC_VECTAB);#endif#ifdef CONFIG_ARCH_RAMVECTORS  /* 如果定义了CONFIG_ARCH_RAMVECTORS,   * 我们正在使用基于RAM的向量表,需要特别的初始化   */  up_ramvec_initialize();#endif  /* 设置所有的异常和中断到默认的优先级 */  putreg32(DEFPRIORITY32, NVIC_SYSH4_7_PRIORITY);  putreg32(DEFPRIORITY32, NVIC_SYSH8_11_PRIORITY);  putreg32(DEFPRIORITY32, NVIC_SYSH12_15_PRIORITY);  /* The NVIC ICTR register (bits 0-4) holds the number of of interrupt   * lines that the NVIC supports:   *   *  0 -> 32 interrupt lines,  8 priority registers   *  1 -> 64 "       " "   ", 16 priority registers   *  2 -> 96 "       " "   ", 32 priority registers   *  ...   */  num_priority_registers = (getreg32(NVIC_ICTR) + 1) * 8;  /* Now set all of the interrupt lines to the default priority */  regaddr = NVIC_IRQ0_3_PRIORITY;  while (num_priority_registers--)    {      putreg32(DEFPRIORITY32, regaddr);      regaddr += 4;    }  /* currents_regs is non-NULL only while processing an interrupt */  CURRENT_REGS = NULL;  /* Attach the SVCall and Hard Fault exception handlers.  The SVCall   * exception is used for performing context switches; The Hard Fault   * must also be caught because a SVCall may show up as a Hard Fault   * under certain conditions.   */  irq_attach(STM32_IRQ_SVCALL, up_svcall);  irq_attach(STM32_IRQ_HARDFAULT, up_hardfault);  /* Set the priority of the SVCall interrupt */#ifdef CONFIG_ARCH_IRQPRIO  /* up_prioritize_irq(STM32_IRQ_PENDSV, NVIC_SYSH_PRIORITY_MIN); */#endif#ifdef CONFIG_ARMV7M_USEBASEPRI  stm32_prioritize_syscall(NVIC_SYSH_SVCALL_PRIORITY);#endif  /* If the MPU is enabled, then attach and enable the Memory Management   * Fault handler.   */#ifdef CONFIG_ARM_MPU  irq_attach(STM32_IRQ_MEMFAULT, up_memfault);  up_enable_irq(STM32_IRQ_MEMFAULT);#endif  /* 关联所有其它的处理器异常(除了复位和系统滴答) */#ifdef CONFIG_DEBUG_FEATURES  irq_attach(STM32_IRQ_NMI, stm32_nmi);#ifndef CONFIG_ARM_MPU  irq_attach(STM32_IRQ_MEMFAULT, up_memfault);#endif  irq_attach(STM32_IRQ_BUSFAULT, stm32_busfault);  irq_attach(STM32_IRQ_USAGEFAULT, stm32_usagefault);  irq_attach(STM32_IRQ_PENDSV, stm32_pendsv);  irq_attach(STM32_IRQ_DBGMONITOR, stm32_dbgmonitor);  irq_attach(STM32_IRQ_RESERVED, stm32_reserved);#endif  stm32_dumpnvic("initial", NR_IRQS);#ifndef CONFIG_SUPPRESS_INTERRUPTS  /* 最后,使能中断 */  up_irq_enable();#endif}
(code3):
nuttx/sched/irq/irq_attach.c
/* 配置IRQ子系统,以便使用IRQ 号 'irq' 分派 'isr',外设初始化时调用 */int irq_attach(int irq, xcpt_t isr){#if NR_IRQS > 0  int ret = ERROR;  if ((unsigned)irq < NR_IRQS)    {      irqstate_t flags;      /* 如果 ISR 是 NULL, ISR 将不被关联.       * 这种情况下,禁用 ISR ,中断将指向非正常中断处理程序       */      flags = enter_critical_section();      if (isr == NULL)        {          /* Disable the interrupt if we can before detaching it.  We might           * not be able to do this if:  (1) the device does not have a           * centralized interrupt controller (so up_disable_irq() is not           * supported).  Or (2) if the device has different number for vector           * numbers and IRQ numbers (in that case, we don't know the correct           * IRQ number to use to disable the interrupt).  In those cases, the           * code will just need to be careful that it disables all interrupt           * sources before detaching from the interrupt vector.           */#if !defined(CONFIG_ARCH_NOINTC) && !defined(CONFIG_ARCH_VECNOTIRQ)          up_disable_irq(irq);#endif          /* Detaching the ISR really means re-attaching it to the           * unexpected exception handler.           */           isr = irq_unexpected_isr;        }      /* 保存新的 ISR 到表. */      g_irqvector[irq] = isr;      leave_critical_section(flags);      ret = OK;    }  return ret;#else  return OK;#endif}
(code4):
nuttx/sched/irq/irq_dispatch.c
/* 此函数必须从架构特定的逻辑调用,以分派一个中断到适当的、已注册的处理逻辑, 中断发生时调用 */void irq_dispatch(int irq, FAR void *context){  xcpt_t vector;  /* Perform some sanity checks */#if NR_IRQS > 0  if ((unsigned)irq >= NR_IRQS || g_irqvector[irq] == NULL)    {      vector = irq_unexpected_isr;    }  else    {      vector = g_irqvector[irq];    }#else  vector = irq_unexpected_isr;#endif  /* 分派到中断处理程序 */  vector(irq, context);}
0 0
原创粉丝点击