I am working on building an interrupt based program flow using the PIC24FV32KA302 module from Microchip. However, I am having some trouble with intermittent resets (it seems).
I am currently using the MPLAB X Simulator, trying to find out where the issue is happening. I was originally using a PICKit3 on real hardware, but I ran into some trouble where, after a few cycles through the main loop, the debugger would stop and throw an error "PC at 0x0", which is an address without a valid instruction. I don't think these issues are related, but I can't really eliminate the possibility.
In essence, my program flow is as follows:
main()
{
init();
print_an_init_message();
while(1)
{
check_some_flags();
if(flags_are_set)
{
do_something_about_them();
}
}
}
During simulation, the program repeatedly prints the init message. It does catch on a breakpoint in the while(1) loop - so it must be entering. Also, if I continue from that breakpoint, it will loop around to it (not reset). If I step from that breakpoint, the debugger crashes.
So, I tried printing out values from the RSON register (which is supposed to be set during any reset condition) in the init message. None of the values are set. If I add a simple delay (built-in XC16 __delay_ms()) to the while loop, the _AddressError interrupt is called. The instruction from which the address error originates is always a ULNK instruction from one of the functions used in do_something_about_them() (which represents multiple flags and functions, it seems to be possible that it is any of the functions, but most often it is the first or last).
Also worth noting, if I put a breakpoint on the last line of main (return -1), it is never hit, but the simulator continuously prints the init message.
Is this likely a problem with the simulator, or my program? Could this be related to my PC 0x0 problem when running on real hardware, or are those likely different?
If anyone wants real code to help out, I can provide it - I just didn't provide it right away because I feel it would obfuscate my real problem, which I don't think is being caused by my C code.
Thanks in advance!
After a little bit of debugging, I managed to get the PC 0x0 error to go away. I'm still dealing with landing in the address error ISR. This is now programming real hardware with the PICKit3.
I believe the code that is causing the problem is a queue that I am dealing with.
typedef struct uint16_queue_tag {
uint16_t *contents;
int front;
int back;
int maxSize;
int cnt;
} uint16_queue;
bool uint16_InitQueue(uint16_queue *queueP, uint8_t queueSize)
{
uint16_t newContents[queueSize];
queueP->contents = &newContents[0];
queueP->maxSize = queueSize;
queueP->cnt = 0;
queueP->front = -1;
queueP->back = -1;
return true;
}
bool uint16_IsQueueEmpty(uint16_queue *queueP)
{
return (bool) (queueP->cnt == 0);
}
bool uint16_IsQueueFull(uint16_queue *queueP)
{
return (bool) (queueP->cnt == queueP->maxSize);
}
bool uint16_ClearQueue(uint16_queue *queueP)
{
queueP->front = -1;
queueP->back = -1;
queueP->cnt = 0;
return true;
}
bool uint16_PushQueue(uint16_queue *queueP, uint16_t element)
{
if (uint16_IsQueueFull(queueP))
{
return false; // We can't push to the queue, its full
}
else
{
queueP->back++;
queueP->contents[(queueP->back % queueP->maxSize)] = element;
queueP->cnt++;
return true;
}
}
uint16_t uint16_PullQueue(uint16_queue *queueP)
{
if (uint16_IsQueueEmpty(queueP))
{
return NULL;
}
else
{
queueP->front++;
queueP->cnt--;
return queueP->contents[(queueP->front % queueP->maxSize)];
}
}
This is all working fine for some iterations it seems, but at some point a uint16_PushQueue(&queue_obj, value)
breaks the code. After the queue is initialized, all that I do is check if it is full, Push, and Pull. Strangely, it seems like the value of the contents pointer is different - after it breaks, the pointer is pointing to the same value as "front", which is definitely not the same value as it started at. Also, the element at the place that it is pointing is reported, by MPLAB, as 0.0 (which is definitely not a float).
So I guess this is just some kind of pointer assignment stupidity, which kind of explains the whole address problem too - I am somehow moving where the contents pointer is pointing to.