我已经在一些嵌入式项目中使用 FreeRTOS
一年了,直到现在它都非常完美。目前我正面临一个与在 FreeRTOS
中使用高速中断移植到 PIC24H
相关的难题,希望大家能帮助我解决这个问题。提前致谢
我创建了一个小型演示项目以便于测试:
两个任务:
// Task 1
if (xTaskCreate(RTOSTask_1, (signed char) "[T1]", configMINIMAL_STACK_SIZE2, NULL, tskIDLE_PRIORITY + 1, &hTask1) == errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY)
{
LREP("\r\nCannot create Task 1.");
Display_Error(1000);
}
// Task 2
if (xTaskCreate(RTOSTask_2, (signed char) "[T2]", configMINIMAL_STACK_SIZE2, NULL, tskIDLE_PRIORITY + 2, &hTask2) == errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY)
{
LREP("\r\nCannot create Task 2.");
Display_Error(1000);
}
任务的执行:
void RTOSTask_1(void* pvParameter)
{
while(1)
{
if (xSemaphoreTake(hTask1Semaphore, portMAX_DELAY) == pdTRUE)
{
putchar1('1');
}
}
}
void RTOSTask_2(void* pvParameter)
{
while(1)
{
if (xSemaphoreTake(hTask2Semaphore, portMAX_DELAY) == pdTRUE)
{
putchar1('2');
}
}
}
为了让以上两个任务运行,我使用一个 Timer
和一个 UART
给它们信号量:
void attribute((interrupt, auto_psv)) _T2Interrupt (void)
{
_T2IF = 0;
static signed portBASE_TYPE xTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(hTask1Semaphore, &xTaskWoken );
if( xTaskWoken != pdFALSE )
{
taskYIELD();
}
}
void attribute((interrupt, auto_psv)) _U1TXInterrupt()
{
_U1TXIF = 0;
putchar1('E');
}
void attribute((interrupt, auto_psv)) _U1RXInterrupt()
{
_U1RXIF = 0;
if(U1STAbits.URXDA == 1)
{
uint8 u8Recv = U1RXREG;
}
static signed portBASE_TYPE xTaskWoken;
xTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(hTask2Semaphore, &xTaskWoken);
if( xTaskWoken != pdFALSE )
{
taskYIELD();
}
}
我的定时器每 100us 中断一次,UART 以 230400 bps 的波特率速度工作。
运行几秒钟或几分钟后,程序崩溃并跳转到陷阱:
_AddressError
或
_StackError
我不知道怎么会出现这个问题。经过长时间的调查和测试,我认为问题发生在程序运行在中断服务例程 (ISR) 中或运行完时。看来我们需要几个 SAVE_CONTEXT()
和 RESTORE_CONTEXT()
函数。但在 PIC24 端口上没有这样的端口。
请你给我一些关于这个问题的建议
谢谢大家!
我想我已经找到了我的问题。当 PIC24H 进入和退出中断服务程序时会出现问题,这里是 UART RX、TX、定时器中断。
目前我没有像这样使用 ISR:
void 属性((中断, auto_psv))
取而代之的是,我自己用汇编代码创建了一个机制:
__U1RX中断: ;将 CPU 寄存器压入堆栈
PUSH SR
PUSH W0
PUSH W1
PUSH.D W2
PUSH.D W4
PUSH.D W6
PUSH.D W8
PUSH.D W10
PUSH.D W12
PUSH W14
PUSH RCOUNT
PUSH TBLPAG
PUSH CORCON
PUSH PSVPAG
; Call my ISR
call _UART1_RxISRHandler
; Pop out CPU registers
POP PSVPAG
POP CORCON
POP TBLPAG
POP RCOUNT
POP W14
POP.D W12
POP.D W10
POP.D W8
POP.D W6
POP.D W4
POP.D W2
POP.D W0
POP SR
retfie
UART1_RxISRHandler 是我的 ISR 实现。我对 TX、定时器中断做同样的事情。
结果是我的程序运行更流畅,时间更长了 1 小时(程序崩溃之前只有 1-5 分钟)。但最后它在运行 1-2 小时后仍然崩溃。这意味着我的方法是正确的,但仍然有问题。可能是我错过了上面代码的一些东西。
如果你们对这种情况有什么理想,请告诉我。
谢谢
最佳答案
我遇到了类似的问题。
你的 uart 中断的优先级是多少?
它不应高于 FreeRTOSConfig.h 中设置的 RTOS 内核中断优先级,后者的默认优先级为 1,而 PIC 中断的默认优先级为 3。
这似乎偶尔会导致崩溃。
对于 PIC,SAVE_CONTEXT() 和 RESTORE_CONTEXT() 不是必需的,因为编译器会处理它,至少如果您使用编译器函数声明并避免使用 _FASTISR 或隐藏。
关于c - PIC24H 中的高速 UART 中断导致 FreeRTOS 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19701246/