PIC32 _CHANGE_NOTICE_VECTOR freezes running processes

I’m working with the PIC32 USB Starter Kit II with a PIC32MX795F512L. The 18 sample software projects provided by FreeRTOS.org in the purchased manual used version 7.5.3. I made a project that creates a CHANGENOTICEVECTOR interrupt that responds to an SW1 button press. In addition, I created another task that flashes an LED (25ms ON / 50ms OFF). When I press SW1, I get a message from my task that responds to the interrupt, but I notice the LED flashing is interrupted. When I press and hold SW1, the LED does not flash at all, and I don’t get my message until I release SW1. I tried increasing the priority of my LED flashing task. I also switched from using assembly code for the interrupt to straight C. I looked for other configuration settings for the change notice. Nothing seems to help. I also have a UART2 interrupt and related task that seems to operate properly without affecting the LED flash rate. Any help would be appreciated. Code: ~~~~

include <p32xxxx.h>

include <plib.h>

include “FreeRTOS.h”

include “task.h”

include “semphr.h”

include “basic_io.h”

pragma config FPLLODIV = DIV1, FPLLMUL = MUL20, FPLLIDIV = DIV_2

pragma config FWDTEN = OFF, FPBDIV = DIV_2, POSCMOD = XT, FNOSC = PRIPLL, CP = OFF

pragma config FSRSSEL = PRIORITY_7

static void vHandlerTask( void *pvParameters ); static void vHandlerTask2( void *pvParameters ); void vSetupEnvironment( void ); static void vTimerFunction( void *pvParameters ); xSemaphoreHandle xBinarySemaphore, xBinarySemaphore2;

define DESIRED_BAUDRATE (9600)

define SYSCLK (80000000L)

define MAXCOMMANDSIZE 256

char CommandString[MAXCOMMANDSIZE]; int CommandLoc = 0; int main( void ) { vSetupEnvironment();
vSemaphoreCreateBinary( xBinarySemaphore );
vSemaphoreCreateBinary( xBinarySemaphore2 );

if( xBinarySemaphore != NULL && xBinarySemaphore2 != NULL) {
    xTaskCreate( vHandlerTask, ( signed char * ) "Handler", 240, NULL, 2, NULL );
    xTaskCreate( vHandlerTask2, ( signed char * ) "Handler 2", 240, NULL, 2, NULL );
    xTaskCreate( vTimerFunction, ( signed char * ) "LED Task", 240, NULL, 3, NULL );
    vTaskStartScheduler();
}

for( ;; );
return 0;
} static void vHandlerTask( void *pvParameters ) { xSemaphoreTake( xBinarySemaphore, 0 );
for( ;; ) {
    xSemaphoreTake( xBinarySemaphore, portMAX_DELAY );
    putsUART2("Command string: ");
    putsUART2(CommandString);
    putsUART2("n");
    CommandLoc = 0;
}
} static void vHandlerTask2( void *pvParameters ) { xSemaphoreTake( xBinarySemaphore2, 0 );
for( ;; ) {
    xSemaphoreTake( xBinarySemaphore2, portMAX_DELAY );
    putsUART2("button eventn");
}
} void __ISR(CHANGENOTICE_VECTOR, ipl1) vButtonISRHandler(void) { long sHigherPriorityTaskWoken = pdFALSE;
mCNClearIntFlag();
xSemaphoreGiveFromISR( xBinarySemaphore2, &sHigherPriorityTaskWoken );
portEND_SWITCHING_ISR( sHigherPriorityTaskWoken );
} void __ISR(UART2VECTOR, ipl2) IntUart2Handler(void) { unsigned int ch; long sHigherPriorityTaskWoken = pdFALSE;
if(INTGetFlag(INT_SOURCE_UART_RX(UART2))) {
    INTClearFlag(INT_SOURCE_UART_RX(UART2));

    while (DataRdyUART2()) {
        ch = getcUART2();
        putcUART2(ch);
        if (ch == 10 || ch == 13) {
            if (CommandLoc > 0)
                xSemaphoreGiveFromISR( xBinarySemaphore, &sHigherPriorityTaskWoken );
        }
        else if (CommandLoc < MAXCOMMANDSIZE-1) {
            CommandString[CommandLoc++] = ch;
            CommandString[CommandLoc] = 0;
        }
        else {
            xSemaphoreGiveFromISR( xBinarySemaphore, &sHigherPriorityTaskWoken );
        }
    }
}

if ( INTGetFlag(INT_SOURCE_UART_TX(UART2)) ) {
        INTClearFlag(INT_SOURCE_UART_TX(UART2));
}

portEND_SWITCHING_ISR( sHigherPriorityTaskWoken );
} void vSetupEnvironment( void ) { unsigned int dummy; int pbClk;
SYSTEMConfigPerformance( configCPU_CLOCK_HZ );
mOSCSetPBDIV( OSC_PB_DIV_2 );

mPORTDClearBits(BIT_0 | BIT_1 | BIT_2);
mPORTDSetPinsDigitalOut(BIT_0 | BIT_1 | BIT_2 );
PORTSetPinsDigitalIn(IOPORT_D, BIT_6 | BIT_7);

mCNOpen((CN_ON | CN_FRZ_OFF), (CN15_ENABLE), 0);
dummy = mPORTDRead();
ConfigIntCN((CHANGE_INT_ON | CHANGE_INT_PRI_1));

pbClk=SYSTEMConfig( SYSCLK, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);

OpenUART2( UART_EN, UART_RX_ENABLE | UART_TX_ENABLE, pbClk/16/DESIRED_BAUDRATE-1);

INTEnable(INT_SOURCE_UART_RX(UART2), INT_ENABLED);
INTSetVectorPriority(INT_VECTOR_UART(UART2), INT_PRIORITY_LEVEL_2);
INTSetVectorSubPriority(INT_VECTOR_UART(UART2), INT_SUB_PRIORITY_LEVEL_0);

INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR);

INTEnableSystemMultiVectoredInt();

while( BusyUART2());
putsUART2( "Startuprn");
} static void vTimerFunction( void *pvParameters ) { const int DLY1 = 25; const int DLY2 = 50; portTickType xLastWakeTime;
mPORTDClearBits(BIT_2);
xLastWakeTime = xTaskGetTickCount();

for( ;; ) {
    mPORTDSetBits(BIT_2);
    vTaskDelayUntil( &xLastWakeTime, DLY1 / portTICK_RATE_MS );

    mPORTDClearBits(BIT_2);
    vTaskDelayUntil( &xLastWakeTime, DLY2 / portTICK_RATE_MS );
}
} ~~~~

PIC32 _CHANGE_NOTICE_VECTOR freezes running processes

Is the button interrupt edge or level sensitive? If it is level sensitive then you may be continuously re-entering the interrupt while the button is being held down, preventing other code from running. Regards.

PIC32 _CHANGE_NOTICE_VECTOR freezes running processes

Thanks for your response. I looked through the PIC32 manual, and unless I missed something, there is no way to set the CNx inputs to a rising or falling edge. The INT0 – INT4 external inputs do allow an edge setting. I will try INT0 and see if it solves the problem.

PIC32 _CHANGE_NOTICE_VECTOR freezes running processes

Not true, I do not have the data sheet here, but you can set edge or state on each pin for interrupt. Re read data sheet.

PIC32 _CHANGE_NOTICE_VECTOR freezes running processes

“The CNENx registers contain the CN interrupt enable control bits for each of the input pins. Setting any of these bits enables a CN interrupt for the corresponding pins.” This will give you an interrupt when a pin changes state, you must in the interrupt service routine, clear the interrupt, check if it’s a state you are looking for, set a flag or mutex, exit the routine… It will only interrupt on a pin state change, a 1 to a 0, or a 0 to a 1

PIC32 _CHANGE_NOTICE_VECTOR freezes running processes

It interrupts on BOTH edge, so a small state machine can set a flag on edge you want.

PIC32 _CHANGE_NOTICE_VECTOR freezes running processes

It doesn’t seem to interrupt on both edges. I get an interrupt only when the button is released. I don’t have a problem getting the change notice interrupt. The problem is: when the button is held down the other running processes halt.

PIC32 _CHANGE_NOTICE_VECTOR freezes running processes

INT0 / RD0 was tied to an LED on the board so I used INT1. There were no problems with the LED flashing when multiple interrupts were generated on INT1. ~~~~ void __ISR(EXTERNAL1_VECTOR, ipl1) vExternalInterrupt1(void) { long sHigherPriorityTaskWoken = pdFALSE; mINT1ClearIntFlag();
xSemaphoreGiveFromISR( xBinarySemaphore2, &sHigherPriorityTaskWoken );
portEND_SWITCHING_ISR( sHigherPriorityTaskWoken );
} //inside SetupEnvironment:
ConfigINT1(EXT_INT_PRI_1 | FALLING_EDGE_INT | EXT_INT_ENABLE);
~~~~

PIC32 _CHANGE_NOTICE_VECTOR freezes running processes

Run the code in the debugger, press and hold the button so the symptom shows itself, then while holding down the button pause the debugger….which code is running?

PIC32 _CHANGE_NOTICE_VECTOR freezes running processes

It turns out I was missing a call to mPORTDRead() in the interrupt handler. That is why I did not get an interrupt on both edges as stated by lafleur. With the following code I can press the button without interferring with the LED flashing. ~~~~ void __ISR(CHANGENOTICE_VECTOR, ipl1) vButtonISRHandler(void) { long sHigherPriorityTaskWoken = pdFALSE; mPORTDRead(); mCNClearIntFlag();
xSemaphoreGiveFromISR( xBinarySemaphore2, &sHigherPriorityTaskWoken );
portEND_SWITCHING_ISR( sHigherPriorityTaskWoken );
} ~~~~