我的信号量有问题,似乎有时在ISR内部调用的SemPost是无效的。
我的应用程序基于Micrimum UCOS III,目标平台基于Microsemi Smartfusion2 SoC(Cortex-M3)。我的应用程序由两个任务(A和B)组成,但当问题发生时,只有一个是活动的(另一个被信号量卡住了)。
当活动任务(我们称之为任务A)执行以下操作时,就会出现问题:
- 写入某个寄存器以在触发中断后启动操作
- 等待操作完成,在semafore上生成OSSemPend(我们称之为Sem a),将时间设置为100毫秒
- 检查OSSemPend调用是否正常结束或是否发生i超时
当中断被触发时,相关ISR在Sem a上进行SemPost,以便在超时前解锁信号量。
当问题发生时,OSSemPend返回OS_ERR_TIMEOUT。我很少看到这个问题。
我确信:
- 给出启动操作(参见第一点),并启动操作
- 中断被触发并且在Sem A上执行OSSemPost
- 中断在从开始小于500 usec(即<1msec)之后被触发
代码写得正确吗?ISR内部信号量的使用有任何限制吗?有人能帮我吗?谢谢
我附上代码的简化版本
/*
* the interrupt handler, triggered at the end of the operation
*/
void FabricIrq2_IRQHandler(void)
{
OS_ERR os_err;
CPU_SR_ALLOC();
CPU_CRITICAL_ENTER();
/*
* write in a register of the ip core generating the interrupt in order
* to reset the interrupt
*/
OSSemPost(&Sem_A, OS_OPT_POST_ALL, &os_err);
OSSemSet(&Sem_Tx, 0, &os_err); /* not relevant for this problem */
CPU_CRITICAL_EXIT();
}
void startOp()
{
CPU_SR_ALLOC();
CPU_CRITICAL_ENTER();
/*
* write in an ip core register in order to start operation
*/
CPU_CRITICAL_EXIT();
}
/*
* task a **partial**
*/
uint8_t task_a(void)
{
uint8_t ret;
OS_ERR os_err;
startOp();
OSSemPend(&Sem_A, (OS_TICK)10, OS_OPT_PEND_BLOCKING, NULL, &os_err);
switch (os_err){
/* manage errors*/
}
return ret;
}
-
调用OSSemPost()时不需要禁用中断。OSSemPost()被认为是应用程序的原子操作w/r。
-
Cortex-M3核心的ISR应该是这样的,这就是Microsemi部分的内容:
void MyISR (void) { CPU_SR_ALLOC(); CPU_CRITICAL_ENTER(); OSIntEnter(); CPU_CRITICAL_EXIT(); OSSemPost(...); OSIntExit(); }
这允许您告诉uC/OS-III您正在启动ISR。如果发布的任务是准备运行的最高优先级,那么这对于允许内核调度发布的任务来说是必要的。