在LPC1788的USB ISR中使用embOS功能

在LPC1788的USB ISR中使用embOS功能,c,usb,microcontroller,rtos,lpc,C,Usb,Microcontroller,Rtos,Lpc,我正在为NXP LPC1788微控制器开发软件,我正在使用embOS RTOS。每当通过USB接收到消息时,我都希望使用OS_PutMailCond()函数将USB消息存储在处理程序函数正在等待的邮箱中。换句话说,我想让消息处理成为中断驱动的 可以找到embOS用户手册。第145页介绍了OS_PutMailCond()函数 无论何时收到USB消息,它都会触发LPC上的USB中断服务例程,但为了让embOS知道这是一个ISR,我必须将OS_EnterInterrupt()和OS_LeaveInte

我正在为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();
}
链接手册的第252页和第253页介绍了操作系统输入中断()和操作系统离开中断()。从前者的附加信息部分:

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

  • 禁用任务开关
  • 使内部例程中的中断保持禁用状态
编辑

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


如果我发现任何其他问题,我将更新。

问题已解决。原来,为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();
}
void OS_InitHW(void){
OS_IncDI();
//
//我们假设,PLL和核心时钟已经由SystemInit()函数设置
//这是从启动代码中调用的
//因此,我们不必在这里初始化任何硬件,
//我们只需确保系统时钟变量已更新,然后
//为EMBO设置定期系统计时器滴答声。
//
SystemCoreClockUpdate();//更新系统时钟变量(以前可能未设置)
如果(SysTick_配置(OS_PCLK_定时器/OS_TICK_FREQ)){//设置1毫秒中断的SysTick定时器
while(1);//句柄错误
}
//
//初始化NVIC矢量基址。对于RAM目标或不是从0运行的应用程序,可能需要初始化NVIC矢量基址
//
NVIC_VTOR=(OS_U32)和向量;
//
//将系统计时器的中断优先级设置为第二个最低级别,以确保计时器可以抢占PendSV处理程序
//
NVIC_设置优先级(SysTick_IRQn,(1u