mpasmwin.exe v5.42
mplink.exe v4.40
mcc18.exe v3.40
mplib.exe v4.40 MPLAB SIM:
PIC18F4553 When running some fairly simple code to implement a low frequency PWM I’m seeing a stack underflow error on the second execution of a DelayTaskUntil function. Using the MPLab simulator I’ve been able to trace it as far as is described below. I’m stuck trying to understanding why the program counter is jumping in the middle of executing the function portRESTORE_CONTEXT? I can’t imagine its possible to change the program counter within a MOVFF instruction? I would appreciate if anyone could help understand what could cause the jump and how I might go about finding the exact problem.
vTaskDelayUntil calls portYIELD_WITHIN_API calls portRESTORE_CONTEXT
On attempting to restore the eight byte of the ".tmpdata and MATH_DATA memory " with the instruction in Program memory as:
6041 2F30 CFE5 MOVFF POSTDEC1, POSTDEC0
6042 2F32 FFED NOP
An error occurs:
>>> CORE-W0015: Out of bounds Memory Access (at address 0x089966 on 0x000002 bytes)
The program counter then jumps to program address: 196C and the instructions is:
3255 196C C010 MOVFF __tmp_0, PRODL
3256 196E FFF3 NOP
the program then conintues on (presumably processing rubish) until it reaches the next return call and fails at address 198A.
3270 198A 0012 RETURN 0
>>> CORE-E0002: Stack under flow error occurred from instruction at 0x00198a
#define portRESTORE_CONTEXT() {
_asm
/* Set FSR0 to point to pxCurrentTCB->pxTopOfStack. */
MOVFF pxCurrentTCB, FSR0L
MOVFF pxCurrentTCB + 1, FSR0H
/* De-reference FSR0 to set the address it holds into FSR1.
(i.e. *( pxCurrentTCB->pxTopOfStack ) ). */
MOVFF POSTINC0, FSR1L
MOVFF POSTINC0, FSR1H
/* How many return addresses are there on the hardware stack? Discard
the first byte as we are pointing to the next free space. */
MOVFF POSTDEC1, FSR0L
MOVFF POSTDEC1, FSR0L
_endasm
/* Fill the hardware stack from our software stack. */
STKPTR = 0;
while( STKPTR < FSR0L )
{
_asm
PUSH
MOVF POSTDEC1, 0, 0
MOVWF TOSU, 0
MOVF POSTDEC1, 0, 0
MOVWF TOSH, 0
MOVF POSTDEC1, 0, 0
MOVWF TOSL, 0
_endasm
}
_asm
/* Restore the .tmpdata and MATH_DATA memory. */
MOVFF POSTDEC1, FSR0H
MOVFF POSTDEC1, FSR0L
MOVFF POSTDEC1, POSTDEC0
MOVFF POSTDEC1, POSTDEC0
MOVFF POSTDEC1, POSTDEC0
MOVFF POSTDEC1, POSTDEC0
MOVFF POSTDEC1, POSTDEC0
MOVFF POSTDEC1, POSTDEC0
MOVFF POSTDEC1, POSTDEC0
MOVFF POSTDEC1, POSTDEC0 <<<< Here the error starts
MOVFF POSTDEC1, POSTDEC0
MOVFF POSTDEC1, POSTDEC0
MOVFF POSTDEC1, POSTDEC0
MOVFF POSTDEC1, POSTDEC0
MOVFF POSTDEC1, POSTDEC0
MOVFF POSTDEC1, POSTDEC0
MOVFF POSTDEC1, POSTDEC0
MOVFF POSTDEC1, POSTDEC0
MOVFF POSTDEC1, POSTDEC0
MOVFF POSTDEC1, POSTDEC0
MOVFF POSTDEC1, POSTDEC0
MOVFF POSTDEC1, POSTDEC0
MOVFF POSTDEC1, POSTDEC0
MOVFF POSTDEC1, POSTDEC0
MOVFF POSTDEC1, INDF0
/* Restore the other registers forming the tasks context. */
MOVFF POSTDEC1, PCLATH
MOVFF POSTDEC1, PCLATU
MOVFF POSTDEC1, PRODL
MOVFF POSTDEC1, PRODH
MOVFF POSTDEC1, TBLPTRL
MOVFF POSTDEC1, TBLPTRH
MOVFF POSTDEC1, TBLPTRU
MOVFF POSTDEC1, TABLAT
MOVFF POSTDEC1, FSR0H
MOVFF POSTDEC1, FSR0L
MOVFF POSTDEC1, FSR2H
MOVFF POSTDEC1, FSR2L
MOVFF POSTDEC1, BSR
/* The next byte is the INTCON register. Read this into WREG as some
manipulation is required. */
MOVFF POSTDEC1, WREG
_endasm
.......