FreeRTOS Support Archive
The FreeRTOS support forum is used to obtain active support directly from Real
Time Engineers Ltd. In return for using our top quality software and services for
free, we request you play fair and do your bit to help others too! Sign up
to receive notifications of new support topics then help where you can.
This is a read only archive of threads posted to the FreeRTOS support forum.
The archive is updated every week, so will not always contain the very latest posts.
Use these archive pages to search previous posts. Use the Live FreeRTOS Forum
link to reply to a post, or start a new support thread.
[FreeRTOS Home] [Live FreeRTOS Forum] [FAQ] [Archive Top] [January 2013 Threads] PIC32 interrupt issue xQueueSendToBackFromISRPosted by Michael on January 10, 2013 Hello. I have a huge problem with my touch screen driver which is interrupt driven under FreeRtos. I hope someone can help me. Here is my code (sorry for a mess) void vCNInterruptHandler( void ); extern void __attribute__( (interrupt(ipl3), vector(_CHANGE_NOTICE_VECTOR))) vCNInterruptWrapper( void ); extern xQueueHandle hTouchMsgQueue;
void TouchStandby( void ) { IEC1bits.CNIE = 0; // Set Yadc and Xadc pins as digital inputs AD1PCFG |= 0xC000;
// Set X axis tied to GND: // X- as HiZ with PD (hardwired) TRIS_XNEG = 1; // HiZ // X+ as Gnd without PU LAT_XPOS(0); TRIS_XPOS(0);// Gnd // Set Y axis tied to VCC ( close to Vcc because of hardwired PD on RB15. It couses current flow! ) // Y+ as HiZ with PU enabled TRIS_YPOS(1); // HiZ // Y- as HiZ with CN interrupt enabled. PD is present (hardwired) TRIS_YNEG = 1; // INT
RtosDelayMs(1); CNEN = 0x1000; // Clear mismatch condition BYTE dummyRead = PORTB; // Clear CN interrutp flag IFS1bits.CNIF = 0; // Enable interrupt IEC1bits.CNIE = 1; }
void TouchWakeup( void ) { // Set Yadc and Xadc pins as analog inputs AD1PCFG &= 0x3FFF; } volatile BYTE smTouchDetection = touchStandby;
void TouchInterruptInit( void ) { WORD dummyRead;
// Enable CN12 interrupt CNEN = 0x1000; // Enable CN module and set halt in idle mode CNCON = 0xA000; // Interrupt priority 2, subpriority 1 IPC6 = 0x000900000; // Clear mismatch condition dummyRead = PORTB; // Clear CN interrutp flag IFS1bits.CNIF = 0; // Enable CN interrupt //IEC1bits.CNIE = 1;
} enum{ touchUnpressed = 0, touchPressed = 1 };
volatile BYTE touchMsgCnt = 0; // CN12 = RB15 void vCNInterruptHandler( void ) { static isrTest = 0; signed portBASE_TYPE xHigherPriorityTaskWoken; xHigherPriorityTaskWoken = pdFALSE;
isrTest++; if( isrTest > 1 ){ Nop(); } WORD dummyRead; // Clear mismatch dummyRead = PORTB; // Clear CN interrutp flag IFS1bits.CNIF = 0;
if( !_RB15 ) { // Disable CN interrupt until int source is handled IEC1bits.CNIE = 0; // CNEN = 0x0000; // Inform touchTask about touch screen being pressed BYTE touchMsg; touchMsg = touchPressed; if( xQueueSendToBackFromISR( hTouchMsgQueue, &touchMsg, &xHigherPriorityTaskWoken ) ) { touchMsgCnt++; } } if( isrTest > 1 ){ Nop(); }
isrTest = 0;
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken ); // If necessary change context to task with higher priority
} volatile BYTE touchDebug = 0;
void TouchTask(void *pVoid) {
volatile int touchPressed = 0; BYTE touchMessage; //TouchStandby(); RtosDelayMs(100); TouchInterruptInit(); while (TRUE) { touchDebug = 0; switch( smTouchDetection ) { case touchStandby: touchDebug = 1; LockSD(); touchDebug = 2; TouchStandby(); touchDebug = 3; UnlockSD(); touchDebug = 4; // Block until touch screen is pressed. Detection done in CN interrupt handler if( !xQueueReceive( hTouchMsgQueue, &touchMessage, 100000 ) ) { //Timeout if( touchMsgCnt > 0 ){ Nop(); } else break; } touchMsgCnt--; touchDebug = 5; TouchWakeup(); touchDebug = 8; smTouchDetection = touchDetect; touchDebug = 9; //RtosDelayMs(25); //break; case touchDetect: touchDebug = 10; LockSD(); touchDebug = 11; touchPressed = TouchDetectPosition(); touchDebug = 12; UnlockSD(); touchDebug = 13; if( touchPressed ) { touchDebug = 14; RtosDelayMs(25); touchDebug = 15; } else{ touchDebug = 16; // Touch is depressed. Return to standby state smTouchDetection = touchStandby; touchDebug = 17; } break; }
#ifdef WIN32 Sleep(1); #endif touchDebug = 18; taskYIELD(); //tuchDebug = 19; } } //void TouchTask(void *pVoid) {
ISR.S: #include #include #include "libs/FreeRTOS/ISR_Support.h"
.setnomips16 .set noreorder .extern vCNInterruptHandler .extern xISRStackTop .globalvCNInterruptWrapper
.setnoreorder .set noat .entvCNInterruptWrapper
vCNInterruptWrapper:
portSAVE_CONTEXT jal vCNInterruptHandler nop portRESTORE_CONTEXT
.endvCNInterruptWrapper
Some stuff from FreeRtosConfig.h: #define INCLUDE_vTaskPrioritySet1 #define INCLUDE_uxTaskPriorityGet1 #define INCLUDE_vTaskDelete1 #define INCLUDE_vTaskCleanUpResources0 #define INCLUDE_vTaskSuspend1 #define INCLUDE_vTaskDelayUntil1 #define INCLUDE_vTaskDelay1 #define INCLUDE_uxTaskGetStackHighWaterMark0 #define INCLUDE_xTaskResumeFromISR 1 #define configMAX_SYSCALL_INTERRUPT_PRIORITY0x03 #define configKERNEL_INTERRUPT_PRIORITY0x01 And last but not least problem description: TouchTask block(should do this indefinitely but I used 10s for debuf purpose) until touch is detected by change notice interrupt. Interrupt sends message "touchPressed" if CN12 is pushed. Message from queue is received by touchTask and detection is procced. Everything works great until I start pushing touch screen rapidly. Then touch task hangs. I was able to determine that: 1.CN interrupt detects push and sends message into hTouchMsgQueue. It returns with xHigherPriorityTaskWoken = pdTrue. 2. The touch task never unblocks even with xTicksToWait definied (as it is in code above) and message being queued. I read about interrupt priority issues but I made everything (or rather I hope) according to FreeRtos manuall scheme. I tried to comment out portEND_SWITCHING_ISR but problem still exists.
RE: PIC32 interrupt issue xQueueSendToBackFromISRPosted by Richard on January 10, 2013 From reading the code, it looks like the interrupt has a priority of 2, and the max syscall priority is 3, so on a PIC32 device that is ok.
Are you able to determine what the TouchTask is doing? What is it executing. This sort of thing can sometimes happen when the peripheral drivers (in this case I presume this is the TouchDetectPosition(), and the lock/unlock SD functions, etc.) contain polling loops in them, and the loop exit condition never occurs leaving the task just spinning on the same code continuously. (I had the same thing recently myself with a USB CDC driver - when I hammered it by automatically sending it lots of characters in quick succession it ended up getting stuck in a loop that was polling for a bit change that never changed).
Which IDE are you using? If MPLAB 8 then Microchip provide a FreeRTOS plug-in that will at least tell you the state of the task (running/blocked/etc.). If using MPLAB X then there is also a plug-in but I'm not sure of its status at the moment (a recent support request was having a problem using it). If you don't have the plug-in then I can tell you how to determine the state using the debugger - but that involves following a pointer chain so is not very user friendly.
The trace tool offers another option to see what is actually running if you have the possibility to add in the trace recorder code and obtain the tool.
Does xQueueSendToBackFromISR() ever return pdFALSE? How big is the queue? Is it correct that the break statement is commented out in the switch statement of your task?
Regards.
RE: PIC32 interrupt issue xQueueSendToBackFromISRPosted by Michael on January 10, 2013 Thanks for quick respond. The last line executed by TouchTask is xQueueReceive( hTouchMsgQueue, &touchMessage, 100000 ) . The touchDebug variable has value of 4 and touchMsgCnt = 1. The LockSD and UnlockSD are just mutexes that secure the SPI4 peripherial. The commented break is just to speed up touch detection a little. For xQueueSendToBackFromISR() I decided to disable CN interrupt each time touch screen is pressed, procced with touch detection and then reenable interrupt. I think it is more safe right now but I have also tried approch without disabling it. I was able to spot that CN ISR was preempting it self! (is it normal?) Preemption occurs during xQueueSendToBackFromISR() ( line 919 of queue.c ). That time is return with pdFalse. This is wired because it happensa also when the CN12 interrupt is masked (CNEN = 0! ) But for now lest return to problem with touch task queue. I am using MPLAB8 and all task in RtosViewer are suspended. I tried to see if other task that are working in time dependant manner (like networkTask, lcdTask etc ). are working correctly. It turned out that only one task is running and there is no task switch. The vPortIncrementTick is executed so tick interrupt is working fine. I really don't have any idea what to check next:/
RE: PIC32 interrupt issue xQueueSendToBackFromISRPosted by Michael on January 10, 2013 I've forgot to add my hTouchQueueMsg initialization: hTouchMsgQueue = xQueueCreate( 1, 1 );
RE: PIC32 interrupt issue xQueueSendToBackFromISRPosted by Dave on January 10, 2013 Because of the way FreeRTOS handles indefinite waits a task that makes a blocking call with a block time of portMAX_DELAY will show as being Suspended when it is actually Blocked. I don't see TouchTask() ever using portMAX_DELAY or actually being suspended, but you say the viewer shows it as Suspended?
RE: PIC32 interrupt issue xQueueSendToBackFromISRPosted by Michael on January 10, 2013 No it is my mistake. I checked RtosViewer once again and IDLE is in ready state TmrSvc Unkcnown 6 more tasks are Suspended (blocked indefinite, waiting for message in queue/ semaphore ) but there are many tasks missing in the list. However before this error shows (before touch screen stops responding and task switch stop working) all of them are present. Is it possible to determine what exactly touchTask is doing? I know that last command is xQueueReceive();
RE: PIC32 interrupt issue xQueueSendToBackFromISRPosted by Richard on January 10, 2013 So it looks likely there is some corruption of the kernel data somewhere.
Before I walk through manually tracking the stat of the task, a couple of quick questions:
1) Do you have stack overflow checking switched on? 2) What is the priority of the touch task? 3) When the error occurs, what is the value of the uxTopReadyPriority variable in tasks.c? 4) If you are using FreeRTOS V7.3.0, what is configUSE_PORT_OPTIMISED_TASK_SELECTION set to (if it is not defined then I will look up the default).
Regards.
RE: PIC32 interrupt issue xQueueSendToBackFromISRPosted by Michael on January 10, 2013 Here it goes: 1) I have #define configCHECK_FOR_STACK_OVERFLOW1 #define INCLUDE_uxTaskGetStackHighWaterMark1
But neither my constructor task that monitors every tasks thru uxTaskGetStackHighWaterMark nor vApplicationStackOverflowHook() indicates any stack problems. 2) touch task has priority 2 (as most tasks in project) 3) uxTopReadyPriority = 2 (when screen freezes ) 4) I have FreeRTOS V7.3.0 with onfigUSE_PORT_OPTIMISED_TASK_SELECTION set to default (not definied at all)
RE: PIC32 interrupt issue xQueueSendToBackFromISRPosted by Michael on January 10, 2013 Small update but maybe helpful. If I change lines: if( !xQueueReceive( hTouchMsgQueue, &touchMessage, 100000 ) ) { //Timeout if( touchMsgCnt > 0 ){ Nop(); } else break; } to only: xQueueReceive( hTouchMsgQueue, &touchMessage, portMAX_DELAY ); Symptoms are the same for touchTask but other tasks are switching normally. What is more every task is present in RtosViewer list (including those in block state as well) expect touchTask. Let me know if I can be of any more help
RE: PIC32 interrupt issue xQueueSendToBackFromISRPosted by Michael on January 10, 2013 One last update for today. I've modified taskTocuh. It is a little less efective (checking Queue every 50ms) but right now it seems to work without a problem. Here it is: void TouchTask(void *pVoid) {
volatile int touchPressed = 0; BYTE touchMessage; RtosDelayMs(100); TouchInterruptInit(); while (TRUE) { switch( smTouchDetection ) { case touchStandby: LockSD(); TouchStandby(); UnlockSD(); smTouchDetection = touchCheck;
break;
case touchCheck: // Block until touch screen is pressed. Detection done in CN interrupt handler RtosDelayMs(50); if( !xQueueReceive( hTouchMsgQueue, &touchMessage, 0 ) ) { break; } touchMsgCnt--; TouchWakeup(); smTouchDetection = touchDetect; case touchDetect: LockSD(); touchPressed = TouchDetectPosition(); UnlockSD(); if( touchPressed ) { RtosDelayMs(25); } else{ // Touch is depressed. Return to standby state smTouchDetection = touchStandby; } break; }
#ifdef WIN32 Sleep(1); #endif taskYIELD(); } } //void TouchTask(void *pVoid) {
I've noticed that when the xTickToWait time in xQueueReceive call is small (I've tried up to 100ticks=10ms ) every think works correctly. This could point to a reson why longer blocking/suspending of touchTask currupts some data (etc.:xEventList? xSuspendedTaskList?)
RE: PIC32 interrupt issue xQueueSendToBackFromISRPosted by Michael on May 7, 2013 Lately I was able to finally solve the problem from my first post. I had Read-Modify-Write hazard when clearing/setting interrupt flag for CN peripherial. I used IEC1bits.CNIE and IFS1bits.CNIE commands which are not atomic operations. After changing these to atomic opeartions (IEC1SET IEC1CLR IFS1SET IFS1CLR ) everything works flawless. I hope someone will find it usefull in the future.
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.
|