Page 1 of 1

Corruption Of Interrupt Control Register

PostPosted: Tue Apr 28, 2009 9:20 am
by mmck

I am having an issue with regards to a corruption of my interrupt control register (INTCON) on my PIC18F4550 device using a very simple application based on your Salvo Tutorial 6. I find that I set up my INTCON register to my desired configuration 0x21 and then set up the tasks and message using your tutorial code. This seems to work fine and my INTCON register remains as 0x21. I then execute the OSEi() call which changes the interrupt register to 0xE1 as expected. However, when I the execute the OSSched() call I end up stuck in my interrupt handler responding to an interrupt that should never have been enabled. The INTCON register is now 0x79!

I have stepped through the assembler and it would seem that the call to OSSched() makes a store of my current global interrupt bits as stored in the INTCON register (bits 7 and 6). This value is stored in some sort of stack based at 0x200. Stack pointer is then incremented to 0x201. Then a fair bit of code is executed which I assume is preparing my highest priority task to run by setting up its context. A call is then made to my highest priority task (TaskBlink()). This call dumps two values on the stack at the start of TaskBlink().TaskBlink() makes a call to OS_Delay() which causes to task to yield the processor and hand back to the scheduler. When the code steps back to the OSSched() routine I see that the stack pointer is still at 0x203 (rather than 0x201 as I would have thought it should be). Then the scheduler tried to reinstate the stored interrupt value which was stored earlier at 0x200 but instead it loads a value from 0x202 (which happens to be 0x79) and hence my interrupt register is corrupted.

I am worried that there is some sort of issue with the scheduler as implemented in the free libraries for the PIC18F using the mcc18 compiler. I have version 3.2.3 of Salvo.(sfc18sfa.lib , modified date 30 Oct 2005 , size 723703 bytes) It is either this or I have set up my system incorrectly. Note, this curruption may only occur on the first call to OSSched() - I've not been able to check subsequent calls yet due to the interrupt corruption.

I have put all my code in one file to ease the transport to you for investigation. Here it is (main.c)

Thanks for any help you can provide.

#include "salvo.h"
//From Main.h
/* setup which port to use, and initialize it */
#define InitPORT() do { PORTD = 0x0A;
TRISD = 0x00;
} while (0)

//Initialise the interrupt registers
#define Init() do { T0CONbits.T08BIT = 1;
T0CONbits.T0CS = 0;
T0CONbits.PSA = 0;
T0CONbits.T0PS2 = 1;
T0CONbits.T0PS1 = 1;
T0CONbits.T0PS0 = 1;
INTCONbits.TMR0IE = 1;
INTCONbits.INT0IE = 0;
INTCONbits.RBIE = 0;
} while (0)

#define TMR0_RELOAD 195 /* for 100Hz ints @ 20MHz */
#define TMR0 TMR0L

//From isr.c
#pragma interrupt ISRHigh save=PROD,section(".tmpdata")
#pragma interrupt ISRHigh
void ISRHigh( void )
if ( INTCONbits.TMR0IE && INTCONbits.TMR0IF ) {
INTCONbits.TMR0IF = 0;


#pragma code IntVectorHigh = 0x08
void IntVectorHigh( void )
goto ISRHigh

#define TASK_COUNT_P OSTCBP(1) /* task #1 */
#define TASK_SHOW_P OSTCBP(2) /* "" #2 */
#define TASK_BLINK_P OSTCBP(3) /* "" #3 */
#define PRIO_COUNT 12 /* task priorities*/
#define PRIO_SHOW 10 /* "" */
#define PRIO_BLINK 2 /* "" */
#define MSG_UPDATE_PORT_P OSECBP(1) /* semaphore #1 */

unsigned int counter;

char CODE_B = 'B';
char CODE_C = 'C';


void TaskCount( void )
counter = 0;

for (; {

if ( !(counter & 0x01FF) )


void TaskShow( void )
OStypeMsgP msgP;


for (; {

if ( *(char *)msgP == CODE_C ) {
PORTD = (PORTD & ~0xFE) | ((counter >> 8) & 0xFE);
PORTD ^= 0x01;

void TaskBlink( void )
OStypeErr err;

for (; {
OS_Delay(50, TaskBlink1);

err = OSSignalMsg(MSG_UPDATE_PORT_P, (OStypeMsgP) &CODE_B);

if ( err == OSERR_EVENT_FULL ) {
OS_SetPrio(PRIO_SHOW+1, TaskBlink2);

void main( void )
//INTCON 0x21 here!

OSCreateTask(TaskCount, TASK_COUNT_P, PRIO_COUNT);
OSCreateTask(TaskShow, TASK_SHOW_P, PRIO_SHOW);
OSCreateTask(TaskBlink, TASK_BLINK_P, PRIO_BLINK);

OSCreateMsg(MSG_UPDATE_PORT_P, (OStypeMsgP) 0);
//INTCON still 0x21 here!
//INTCON now 0xE1 here - OK!
for (;
OSSched(); //INTCON now 0x79! Stuck in ISR


/* */
/* Salvo Lite build */
/* */
#define OSEVENTS 1
#define OSTASKS 3

Re: Corruption Of Interrupt Control Register

PostPosted: Tue Apr 28, 2009 9:34 am
by mmck
Sorry...Please replace all annoying smilies with ;)

Also, it would seem that only the first call to the scheduler causes a corruption of the interrupt register??

Re: Corruption Of Interrupt Control Register

PostPosted: Tue Apr 28, 2009 9:36 am
by aek
Remove all instances of auto variables in your tasks -- this is a problem with Salvo + MPLAB C18 in the current (v3.2.3) Salvo for PIC release.


Re: Corruption Of Interrupt Control Register

PostPosted: Tue Apr 28, 2009 9:53 am
by mmck
Thanks for the amazingly quick response!

If I make all the auto (local) variables global then this seems to fix the problem.

This is a bit of a drag with a view to my future development with Salvo. Is this something that is expected to be fixed soon? Not having the ability to use auto variables in tasks makes the code much more "clunky" and less maintainable.

What about using auto variables in functions called from the task main loop?

Did older versions of Salvo have this problem?

Thanks again...

Re: Corruption Of Interrupt Control Register

PostPosted: Tue Apr 28, 2009 11:20 am
by aek
It's a problem that is unique to that particular Salvo version and port -- it's not present in, say, Salvo 4 for MSP430.

We will fix that once Salvo for PIC moves up to Salvo 4. No date announced yet, however.

Of course it's always OK to declare variables inside a task as static.

Also, it's OK for (called) functions to have auto variables -- it's just Salvo task that need to avoid auto variables in this case.


Re: Corruption Of Interrupt Control Register

PostPosted: Wed Apr 29, 2009 1:38 am
by mmck
Thanks aek.

The issue in not too much of a hindrence then. Given that my tasks are likely to be while(1) loops then having their "auto" variables as "static" doesn't cause any additional memory usage anyway.