【发布时间】:2013-11-11 03:32:42
【问题描述】:
我已经将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小时后仍然崩溃。这意味着我的方法是正确的,但仍然有问题。可能是我错过了上面的代码。
如果大家对这种情况有什么理想,请告诉我。
谢谢
【问题讨论】:
-
嗯,通过以 230400 波特为每个字符发送一个信号量来发起线程切换是一个相当大的负担。你能缓冲 rx 字符从而减少信号量吗?
-
亲爱的詹姆斯知道这更好,但我认为对于这个演示案例,FreeRTOS 仍然应该正常工作。
-
一个字符,一个调度运行,每 43us :( putchar1() 是做什么的?
-
你能展示你的信号量和中断初始化代码吗?
标签: c multithreading stm32 mplab freertos