私はすでにFreeRTOS
いくつかの組み込みプロジェクトに数年間使用しており、今までは本当に完璧に機能していました。FreeRTOS
現在、への移植で高速割り込みを使用することに関連する難しい問題に直面してPIC24H
います。この問題を解決するために皆さんが私を助けてくれることを願っています。前もって感謝します
簡単にテストできるように、小さなデモ プロジェクトを作成しました。
2 つのタスク:
// 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');
}
}
}
上記の 2 つのタスクを実行するには、one Timer
& oneUART
を使用してそれらにセマフォを与えます。
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 のボーレート速度で動作します。
数秒または数分実行した後、プログラムはクラッシュし、プログラムは Traps にジャンプします。
_AddressError
また
_StackError
この問題がどのように発生するかわかりません。長い調査とテストの後、プログラムが割り込みサービス ルーチン (ISR) で実行中および実行中であるときに問題が発生すると考えました。SAVE_CONTEXT()
&RESTORE_CONTEXT()
関数がいくつか必要なようです。しかしPIC24ポートにはそのような人はいません。
この問題についてアドバイスをお願いします
皆さん、ありがとうございました !
私はすでに自分の問題を見つけていると思います。この問題は、PIC24H が割り込みサービス ルーチンに出入りするときに発生します。ここでは、これらは UART RX、TX、タイマー割り込みです。
現在、私は次のように ISR を使用していません。
無効属性((割り込み, auto_psv))
代わりに、アセンブリ コードを使用して自分でメカニズムを作成しました。
__U1RXInterrupt: ; 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時間実行した後でもクラッシュします。つまり、私のアプローチは正しいのですが、それでも何か問題があります。上記のコードで何かが足りないかもしれません。
この状況の理想があれば教えてください。
ありがとう