2020-04-08 02:43 AM
Hello,
I am trying to develop a FreeRTOS application which need to detect/read/write an NFC tag.
I managed to make the NFC part work (based on ST's example code), but after changing my task stack size, a usage fault occurs (FORCED, INVSTATE).
After a few attempt to reproduce and solve this, I noticed the following :
ReturnCode ndefT4TPollerSelectFile(ndefContext *ctx, const uint8_t *fileId)
{
ReturnCode ret;
rfalIsoDepApduTxRxParam isoDepAPDU;
if( (ctx == NULL) || !ndefT4TisT4TDevice(&ctx->device) ) // HARD FAULT on this line
{
return ERR_PARAM;
}
ndefT4TInitializeIsoDepTxRxParam(ctx, &isoDepAPDU);
if (ctx->subCtx.t4t.mv1Flag)
{
(void)rfalT4TPollerComposeSelectFileV1Mapping(isoDepAPDU.txBuf, fileId, (uint8_t)sizeof(fileId), &isoDepAPDU.txBufLen);
}
else
{
(void)rfalT4TPollerComposeSelectFile(isoDepAPDU.txBuf, fileId, NDEF_T4T_FID_SIZE, &isoDepAPDU.txBufLen);
}
ret = ndefT4TTransceiveTxRx(ctx, &isoDepAPDU);
return ret;
}
Might be worth to add a few days back, I had unexpected behaviour on some variable. In the code below, the address linked by usrRec_ptr was set to the right adress on definition, but changed after the call to ndefMessageDecode function.
I moved the declaration on the line before the while, then it worked as expected.
After modification on other part of the program, I tried to put it back at function start, now it works...
void nfc_parseMessage(uint8_t* rawMsgBuf, uint32_t rawMsgLen, nfc_text_records_t *usrRec, bool *tag_empty){
ReturnCode err;
ndefConstBuffer bufRawMessage;
ndefMessage message;
ndefRecord* record;
char* usrRec_ptr[3] = {usrRec->app_id, usrRec->user_name, usrRec->remaining_coffee};
bufRawMessage.buffer = rawMsgBuf;
bufRawMessage.length = rawMsgLen;
err = ndefMessageDecode(&bufRawMessage, &message);
if (err != ERR_NONE)
{
return;
}
record = ndefMessageGetFirstRecord(&message);
uint8_t i=0;
ndefType type;
while (record != NULL)
{
ndefRecordToType(record, &type);
if(type.id == NDEF_TYPE_RTD_TEXT){
memcpy(usrRec_ptr[i], type.data.text.bufSentence.buffer, type.data.text.bufSentence.length);
usrRec_ptr[i++][type.data.text.bufSentence.length] = '\0';
}
nfc_parseRecord(record);
record = ndefMessageGetNextRecord(record);
}
if(i==0 && type.id==NDEF_TYPE_EMPTY){
*tag_empty = true;
}
else{
*tag_empty = false;
}
}
Not sure if this is an NFC related issue, linker/compiler config issue (didn't change anything there except increasing heap and stack minimal size, but the default values don't work either). RAM usage is 35% with the largest task stack size
I doubt this issue is related to FreeRTOS, the code was generated by CubeIDE 1.3 (which take care of the interrupt/task priority to avoid conflicts). I have configASSERT defined, and I enabled stack overflow hook (mode 2) to check this (also, just to be sure I have checked the task stack in RAM which still has 0xA5 values at the end). I have just 2 tasks running, one for NFC, the other one for LED blink.
I tried to lower the FreeRTOS heap for stack sizes of 1024 and 768 words, the behaviour is the same (work with 1024, INVSTATE with 768, PC on the same line of code).
Any idea where I should look next ?
Solved! Go to Solution.
2020-04-10 05:26 AM
Hi
issue found: huge buffer allocated in the stack.
Rgds
BT
2020-04-08 09:13 AM
Hi,
can you provide to me (in private) the raw message buffer so I check the decoding of this NDEF? how many records do you have in this NDEF message?
if the corrupted address is always the same, can you try to set a write access hardware breakpoint and see which part of code is corrupting the data?
Regarding the stack size for tasks, if the tasks have been created by STM32CubeMX, the sizes are currently in bytes and not in dwords (i.e. 4 times less than expected). The static stack analyzer in STM32CubeIDE should help you to find the appropriate stack size for the various tasks. For example, ndefMessageDecode and its callees costs only 96 bytes of stack. The overall rfalNfcWorker costs 668 bytes.
if you have an hardfault on if( (ctx == NULL) || !ndefT4TisT4TDevice(&ctx->device) ), this means ctx does not point to a valid location i.e the ctx pointer is corrupted.
Rgds
BT
2020-04-08 03:21 PM
Thanks for your reply, I sent you the file in private.
There should be 3 text records in this NDEF (but this is a read attempt, I'm not sure the tag has been read yet when the fault occurs.
Good to know for the stack, I never used the static stack analyzer and will give it a try (but I know 768 is a bit more than what I need, and 512 is too small as vApplicationStackOverflowHook is called).
Each time I read ctx value with breackpoint in there, it seem to point to a valid location, but I noticed the hardfault occurs later in that case ( breakpoint near if( (ctx == NULL) || !ndefT4TisT4TDevice(&ctx->device) ) ). In such cases, the overflow occurs on isoDepDataExchangePCD function, on the line gIsoDep.hdrLen = RFAL_ISODEP_PCB_LEN;
What does confuse me is the difference between a task size of 768, 1024 and 2048, even if I don't have stack overflow on those 3 sizes.
2020-04-08 03:29 PM
I also noticed platformProtectWorker and platformUnprotectWorker macros in plateform.h, provided to "Protect RFAL Worker/Task/Process from concurrent execution on multi thread platforms". Even if I'm using an RTOS I didn't set those macros, but as I have a single NFC task this should not be an issue ?
2020-04-10 05:26 AM
Hi
issue found: huge buffer allocated in the stack.
Rgds
BT
2020-04-10 10:20 AM
Thanks again for your help Brian.
Just wanted to add, if someone has a similar issue, the buffer was the one used by ndef functions, and was declared as a local variable inside a function.
The library add a reference to this buffer to ndefContext. In my case, the local buffer was probably overwritten before being used again, with wrong data.
Regards.
2022-06-19 10:02 AM
this is really helpful informative post. i must share this on my website. thanks for sharing this.