Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem


Loading

PIC32 interrupt issue xQueueSendToBackFromISR

Posted 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 xQueueSendToBackFromISR

Posted 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 xQueueSendToBackFromISR

Posted 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 xQueueSendToBackFromISR

Posted by Michael on January 10, 2013
I've forgot to add my hTouchQueueMsg initialization: hTouchMsgQueue = xQueueCreate( 1, 1 );

RE: PIC32 interrupt issue xQueueSendToBackFromISR

Posted 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 xQueueSendToBackFromISR

Posted 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 xQueueSendToBackFromISR

Posted 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 xQueueSendToBackFromISR

Posted 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 xQueueSendToBackFromISR

Posted 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 xQueueSendToBackFromISR

Posted 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 xQueueSendToBackFromISR

Posted 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.


[ Back to the top ]    [ About FreeRTOS ]    [ Privacy ]    [ Sitemap ]    [ ]


Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

NXP tweet showing LPC5500 (ARMv8-M Cortex-M33) running FreeRTOS.

Meet Richard Barry and learn about running FreeRTOS on RISC-V at FOSDEM 2019

Version 10.1.1 of the FreeRTOS kernel is available for immediate download. MIT licensed.

View a recording of the "OTA Update Security and Reliability" webinar, presented by TI and AWS.


Careers

FreeRTOS and other embedded software careers at AWS.



FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Espressif ESP32

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Renesas

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS

Xilinx Microblaze and Zynq partner