os_evt_wait_or(CHECK_EVENT_FLAGS, INFINITE_TIME); //Wait for an Event to occur rx_event = os_evt_get(); switch(rx_event) { case EVENT_INTERRUPT: if(chkflg) { dif = difftime(_gettime(), setalrm); if(!dif) *(tmp->flg) = 1; // on execution of this line (*tymval)--; if(*tymval == 0) chkflg = 0; } break;
the above code is a part of a task that sets a flag, whose address is passed in a structure using a mail box. dif is double. the alarm is generally set to 2 mins (120 secs) untill the dif > 1, things work well. when the dif = 1, the controller goes into hard fault.
i have read few articles and tried to follow the steps but could not come to any solution. www.ti.com/.../spma043.pdf
i use LPC17xx
This appnote may help here: http://www.keil.com/appnotes/docs/apnt_209.asp
"when the dif = 1, the controller goes into hard fault."
Don't you mean "when the dif == 0, the controller [...]"?
So tmp is a pointer? And it points to a struct having a field flg - that is also a pointer?
You do not show us your data types. Or how you send that mail. Or how you extract your pointer from that mail. You don't even show us if you verify that there actually exists any mails to retrieve.
when the dif = 1,... i m sry. it is, when the dif = 0.
// definitions uint8_t i, chkflg=0, *flg=0; uint16_t rx_event=0; time_t setalrm; double dif=1; typedef struct { time_t *alrm; uint8_t *flg; time_t *pval; }tym; tym *tmp; //fetching the mail os_mbx_wait(&MailAlrm, (void*)&tmp, 0xFFFF); setalrm = *(tmp->alrm) + _gettime(); tymval = tmp->pval;
this is what i send from a function
// definitions typedef struct { time_t *pty; uint8_t *pt; time_t *pval; }strct; strct tym; ... tym.pt = &drpflg; tym.pty = &gLoadedProtoVal.drpsync; tym.pval = &gDropSyncTym; if(os_mbx_check(&MailAlrm) != 0) os_mbx_send(&MailAlrm, (void*)&tym, 0xFFFF);
No - I can still not see any code that shows us how you initialize your data and send any mail. All we can see is that you like pointers and very short variable names.
Hmm - why do you have two different struct definitions? One for the transmitter and one for the receiver? The intention with header files is to make sure that all source files makes uses identical data types.
Your two structures doesn't even use the same field names to make sure that your code should be harder to read. Don't play with fire like that - do it the correct way directly from start.
Have you made sure that the "tym" object you send an address to is still living when the other task is receiving the pointer and starting to make use of it?
Have you verified that your received pointer actually points to drpflg - and is that a writable variable?
Get yourself a Joseph Yiu type Hard Fault handler, dump out the core and processor registers at the fault, and look at the assembler view code that is faulting.
Determine what memory is being accessed, why that might be out-of-range, and if stack related if that is a result of exceeding it's size, or from corruption elsewhere.
If it's fetch related, check any flash wait states or caching settings.
Your two structures doesn't even use the same field names... changed the struct name and field names so that both structs are now identical.
also while doing so, i realised that the flg variable was redundant. hence removed it.
the variable definition was
volatile static uint8_t drpflg=0; // it is local of the sender function
whose address i was trying to assign to
uint8_t *pt; tmp.flg = &drpflg;
the problem has been solved now. thank you for all the guidance.
also request you, if you can explain what went wrong.
"changed the struct name and field names so that both structs are now identical." So you did it the wrong way, even after having been told so.
There should not be two places where you need to make the struct name and field names identical. If you need to use the same data type at two locations in a single source code file, then you describe that data type at the top of that source code file. If you need it in multiple source code files, then you instead make use of a header file that you then #include in the different C files. That's the only correct solution. That's the only solution that allows you to add a new field to that struct without danger of forgetting to also add the field in the "twin".
Another thing - if a variable is volatile, then you need to keep that volatile keyword known to all source code lines that makes use of that variable directly or indirectly. So any pointer to that variable should specify that they are pointers to a volatile variable.
And you still haven't told us if any of the variables that you take the address of when initializing your struct before sending it will remain valid all the time until the receiver has picked up the pointer to the struct and done all work. If you send a pointer to a local variable and that function then ends while the pointer value still exists, then that pointer no longer points to any valid variable. Local variables and parameters "dies" when the function exits.