I started with the PIC32MX MPLAB demo. I converted to MPLAB-X and am using the version 2.01 MPLAB C32 compiler with a PIC32MX575F512H device.
I stripped the demo down to the point that ONLY the Idle Task is running. I get a general exception (type 7 - DBE bus error load/save) in the prvCheckTasksWaitingTermination function (seems to move around a little).
I put a counter in the idle task and see that the task loops approximately 5300 times before the exception hits. Unfortunately, I can’t do a trace to backtrack how the code died.
Does this sound familiar to anyone?
Do you have any suggestions as to what I might be doing wrong?
Update,
I have enabled all the API functions. The counter that I stuck in the Idle Task gives me a loop count of 3474 before the exception handler gets hit.
If the only task running is the Idle Task, it is likely looping very fast, so 5300 times isn’t that long. Can you check the tic counter? What might be happening is your tic interrupt isn’t set right some how and the tic interrupt is crashing the system, or perhaps some other interrupt is happening that crashes it.
Richard,
Thanks for the reply.
Just did an autopsy following the break at the exception handler. The variable, xTickCount is zero. Looks like the tic interrupt isn’t running. Matter of fact, a break point in the vPortIncrementTick never gets hit.
Will look at SFRs to see if the interrupt is even enabled.
Further info:
ISR is in fact, enabled and the interrupt flag is set.
Followed the code into the ISR.
<CODE>
/* Make room for the context. First save the current status so we can
manipulate it, and the cause and EPC registers so we capture their
original values in case of interrupt nesting. */
/*entry pt*/ mfc0 k0, _CP0_CAUSE
addiu sp, sp, -portCONTEXT_SIZE
mfc0 k1, _CP0_STATUS
/* Also save s6 and s5 so we can use them during this interrupt. Any
nesting interrupts should maintain the values of these registers
across the ISR. */
/*---->*/ sw s6, 44(sp)
sw s5, 40(sp)
sw k1, portSTATUS_STACK_LOCATION(sp)
</CODE>
Jump to exception handler occurs at arrow.
In MPLAB-X, I set the stack to 8000. I didn’t set anything for the heap assuming that the code would handle this. Even when I set a value for the heap the exception occurs.
Upon hitting the ISR, the SP is ZERO. Everything goes down hill from there. The SP gets adjusted down from a value of zero which has the SP pointing off to Alpha Centauri and there you go. All of the stuff that should be saved off is attempting to be saved somewhere out in hyper space - exception occurs.
Need to see what SP should be when ISR hits, why it appears to be getting klobbered and go from there.
Thanks,
KagnewKid.
Sorry, Richard, I missed your post.
I am running 7.1.0.
With regard to the “before MPLAB-X” question, I’ve been working pretty exclusively in MPLAB-X so I never ran the project in MPLAB-8.xx. I know this is not preferred practice and I may be trudging into thistle-laden territory to say the least.
Interesting. I have not used MPLAB-X myself, although I will be soon while setting up some conference talks.
When you enter the task, on the very first line, before the compiler generated prologue code (which will move the stack pointer) executes, the stack pointer should point to the top (highest address) of the stack allocated to the task inside the call to xTaskCreate() used to create the task (does that make sense?). That is the first thing to check. If the stack pointer is not right there, then there is no point going down the route of looking at the interrupts. If the stack pointer is correct there, then look at it again at the point the first line of C code executes. If it is correct there too, then the interrupt entry is suspicious.
The PIC32 interrupt handler is written in asm, so the compiler should not effect it. The stack pointer should still be pointing to the task stack when the interrupt starts (assuming the interrupt is not nesting with an existing interrupt) - so try putting another break point on the first line of vT1InterruptHandler(), which is in FreeRTOS/Source/Portable/MPLAB/PIC32MX/port_asm.h. It is unfortunately a macro, so to see the code itself will require a switch to assembly view - but the important thing to check first is the stack pointer value.
The FreeRTOS interrupt entry code will move the stack pointer to the dedicated system/ISR stack - so at some point in the interrupt entry code I will expect the stack pointer to change from pointing inside the task stack, so instead point to inside the xISRStack array.
Richard,
I pulled the macro code into the ISR and placed it in the spot occupied by the macro invocation. This is how I was able to observe that when the ISR first begins to run, the SP has a value of zero.
Here’s what I find chasing the stack pointer:
- During the execution of vTaskStartScheduler, the SP is in the area of the processor stack.
- Upon entering VPortSartFirstTask, the SP is still in the area of the processor stack.
- Upon completion of the portRESTORE_CONTEXT macro, the SP changes and is in the area of the declared memory for the heap (xHeap in heap_2.c (made temporarily public so I can see it in the map file).
- When I let fly so the tick ISR hits, my break point at the first assembly line of the ISR (exact copy of the code in the portSAVE_CONTEXT macro moved so that I can set a break point), the SP is set to Zero.
Hmm. It would appear then, that the hardware itself is setting the stack pointer to that value, assuming the CPU is vectoring directly to the ISR without running any other code.
I know the interrupt controller can be configured in a number of different ways - and would guess that either the IDE or the start-up code is different to that in MPLAB 8 - and has configured the CPU in a way that is incompatible with FreeRTOS.
That is just guess work, but it looks like more investigation is required to see how the interrupt controller can be manually programmed to how we need it.
It sounds like you are changing to a shadow register set when entering the ISR. I’m not sure you have fixed the problem, and may have difficulties when interrupts nest.
I did NOT put this in the macro (that seems not to play well with other things…)
I put it immediately before the invocation of the portSAVE_CONTEXT macro in the vT1InterruptHandler as shown below:
Please clarify one other thing - when you said that using MPLAB 8 worked “as described above” - did you mean it worked as expected, or did you mean it exhibited the same behaviour of SP being NULL on interrupt entry?
I need to understand where this change in behaviour has come from. The code is not written to use the shadow registers, which is evidently what is happening, so the question then is - is the additional line you added adequate to enable the shadow registers to be used.
Thanks, Richard. Sorry - under MPLAB-8, the SP was cleared as I observed with MPLAB-X.
And, yes I think you’re correct. Somehow shadow registers are being used but this delves into areas that I am pretty weak on.
Regards,
KagnewKid.
I just looked in the source file, and because the demo was created on a part for which it did not matter, SRSSEL was not manually being set. This sets the interrupt priority that will use shadow registers, which should be set, but then avoided. I would be grateful if you could try adding the following line to near the top of main.c, where you will see other #pragma directive, take out the assembly instruction you added, and let me know if it fixes your original problem.