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 <p32xxxx.h>
#include <sys/asm.h>
#include "libs/FreeRTOS/ISR_Support.h"
.set nomips16
.set noreorder
.extern vCNInterruptHandler
.extern xISRStackTop
.global vCNInterruptWrapper
.set noreorder
.set noat
.ent vCNInterruptWrapper
vCNInterruptWrapper:
portSAVE_CONTEXT
jal vCNInterruptHandler
nop
portRESTORE_CONTEXT
.end vCNInterruptWrapper
Some stuff from FreeRtosConfig.h:#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 0
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_uxTaskGetStackHighWaterMark 0
#define INCLUDE_xTaskResumeFromISR 1
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 0x03
#define configKERNEL_INTERRUPT_PRIORITY 0x01 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.