1

我正在为 NXP LPC1788 微控制器开发软件,我正在使用 embOS RTOS。每当通过 USB 接收到消息时,我想使用 OS_PutMailCond() 函数将 USB 消息存储在处理函数正在等待的邮箱中。换句话说,我想让消息处理由中断驱动。

embOS 用户手册可以在这里找到。第 145 页描述了 OS_PutMailCond() 函数。

每当接收到 USB 消息时,它都会触发 LPC 上的 USB 中断服务例程,但是为了让 embOS 知道这是一个 ISR,我必须将 OS_EnterInterrupt() 和 OS_LeaveInterrupt() 分别放在 ISR 的开头和结尾。如果我想在其中调用 embOS 函数,包括 OS_PutMailCond(),这是必要的。

问题是,如果我将 OS_EnterInterrupt()/OS_LeaveInterrupt() 放在 USB ISR 中的任何位置,USB 将停止正常工作,并且 Windows 会通知我设备出现故障。

我不知道为什么会这样。我们已经尝试过类似的方法来处理 CAN 上的消息,如下所示,并且效果很好。

void CAN_IRQHandler(void)
{   
  OS_EnterInterrupt();

  ...

  if (MBfieldCANframeInitialised)
    OS_PutMailCond (&MBfieldCANframe, &recMessage);
  OS_LeaveInterrupt();
}

OS_EnterInterrupt() 和 OS_LeaveInterrupt() 在链接手册的第 252 和 253 页上进行了描述。从前者的附加信息部分:

如果使用 OS_EnterInterrupt(),它应该是在中断处理程序中调用的第一个函数。它必须与 OS_LeaveInterrupt() 一起使用,作为最后调用的函数。使用该功能有以下效果,它:

  • 禁用任务开关
  • 保持内部程序中的中断被禁用

编辑

我进行了进一步调查,发现在 USB ISR 中使用 OS_EnterInterrupt() 和 OS_LeaveInterrupt()(以及在引脚上检测到上升沿或下降沿时用于 GPIO 的其他 ISR)会导致操作系统错误。错误值为 166,表示“从 ISR 调用的具有高优先级的 OS 函数”。

如果我发现任何其他内容,我会更新。

4

1 回答 1

1

问题解决了。事实证明,为 CAN ISR 完成这项工作的人更改了其中一个 embOS 源文件的代码,将 CAN ISR 优先级从 0 设置为 29(更高级别 = 更低优先级)。我对 USB ISR 做了同样的事情:

void OS_InitHW(void) {
  OS_IncDI();
  //
  // We assume, the PLL and core clock was already set by the SystemInit() function
  // which was called from the startup code
  // Therefore, we don't have to initailize any hardware here,
  // we just ensure that the system clock variable is updated and then
  // set the periodic system timer tick for embOS.
  //
  SystemCoreClockUpdate();                             // Update the system clock variable (might not have been set before)
  if (SysTick_Config (OS_PCLK_TIMER / OS_TICK_FREQ)) { // Setup SysTick Timer for 1 msec interrupts
    while (1);                                         // Handle Error
  }
  //
  // Initialize NVIC vector base address. Might be necessary for RAM targets or application not running from 0
  //
  NVIC_VTOR = (OS_U32)&__Vectors;
  //
  // Set the interrupt priority for the system timer to 2nd lowest level to ensure the timer can preempt PendSV handler
  //
  NVIC_SetPriority(SysTick_IRQn, (1u << __NVIC_PRIO_BITS) - 2u);

  NVIC_SetPriority(CANActivity_IRQn, (1u << __NVIC_PRIO_BITS) - 3u);
  NVIC_SetPriority(CAN_IRQn, (1u << __NVIC_PRIO_BITS) - 3u);
  NVIC_SetPriority(USB_IRQn, (1u << __NVIC_PRIO_BITS) - 3u);

  OS_COM_INIT();
  OS_DecRI();
}

我在 embOS 文档中找到了这个:

为什么高优先级 ISR 不能使用 OS API?

当 embOS 数据结构被修改时,embOS 禁用低优先级中断。在此期间,启用高优先级 ISR。如果他们调用 embOS 函数,该函数也会修改 embOS 数据,则 embOS 数据结构将被破坏。

于 2014-07-18T10:00:07.703 回答