问题描述
以下功能在LPC1769中运行。我使用FreeRTOS版本10。
我有HardFault
。我已经调试,长时间工作后我想解决这个问题。
如果我运行此函数,它将给出HardFault
。最初,我怀疑malloc
函数中的substr3
导致了它。释放内存分配没有帮助。因此,我开始逐块注释掉代码,直到在parseMessage
函数中找到问题的更准确位置为止。
如果我注释掉/* START OF PROBLEMATIC AREA */
和/* END OF PROBLEMATIC AREA */
之间的界限
其余代码无需打h即可工作。
我在该代码块中所做的所有事情,都是在struct变量中分配值。该结构是全局的并已初始化。我认为,这最终会导致问题。也许是间接的,我还不知道。
例如strcpy(productInfoLeft.ucActualID,pid);
如果我运行parseMessage
中的所有代码,则它适用于一条或几条消息,它们解析为OK,然后MCU停止响应。
在名为common.h
的文件中构造
struct ProductInfoLeft
{
char ucActualID[ 7 ];
char ucProductName[ 13 ];
char ucBestBeforeDate[ 13 ];
char ucPrinted[ 4 ];
char ucToBePrinted[ 4 ];
char ucLane[ 3 ];
char ucLcdNumber [ 2 ];
char ucPrinterLane [ 3 ];
char ucsupplierInfo [ 13 ];
};
extern struct ProductInfoLeft productInfoLeft;
struct ProductInfoRight
{
char ucActualID[ 7 ];
char ucProductName[ 13 ];
char ucBestBeforeDate[ 13 ];
char ucPrinted[ 4 ];
char ucToBePrinted[ 4 ];
char ucLane[ 3 ];
char ucLcdNumber [ 2 ];
char ucPrinterLane [ 3 ];
char ucsupplierInfo [ 13 ];
};
extern struct ProductInfoRight productInfoRight;
结构初始化在名为lcdtasks.c
的文件中进行;
struct ProductInfoLeft productInfoLeft = {
.ucActualID = "",.ucProductName = "",.ucBestBeforeDate = "",.ucPrinted = "",.ucToBePrinted = "",.ucLane = "",.ucLcdNumber = "",.ucPrinterLane = "",.ucsupplierInfo = ""
};
struct ProductInfoRight productInfoRight = {
.ucActualID = "",.ucsupplierInfo = ""
};
void parseMessage(char * message){
//Sample data
//const char* str = "7E00002A347C31323030302D3132353330387C33302E30372E323032307C31317C33307C33317C31352D31367C31357C317C57656E67657274880D0000";
// Parsing the frame
char* start;
char* len;
char* cmd;
char* data;
char* chksum;
char* end;
stripEOL(message);
unsigned int messagelen = strlen(message);
start = substr3(message,2);
len = substr3(message,2,4);
cmd = substr3(message,6,2);
data = substr3(message,8,messagelen-8-4);
chksum = substr3(message,messagelen-4,2);
end = substr3(message,messagelen-2,2);
// Converting hex (only for data) to string
char str[250];
hex_to_string(data,str,sizeof(str));
// Parsing the data in variables
//Sample data content to be parsed in variables;
//char str1[50] ="7|10000-145310|12.10.2018|1|10|0|15-16|15|1|Wegert";
char pid[6],pname[12],bbdate[10],pnr[2],ltoprinted[3],lprinted[3],planes[5],laneNr[2],lcdNr[1],sinfo[12];
strcpy(pid,strtok(str,"|"));
strcpy(pname,strtok(NULL,"|"));
strcpy(bbdate,"|"));
strcpy(pnr,"|"));
strcpy(ltoprinted,"|"));
strcpy(lprinted,"|"));
strcpy(planes,"|"));
strcpy(laneNr,"|"));
strcpy(lcdNr,"|"));
strcpy(sinfo,"|"));
uint8_t resultLCDNr1 = strncmp(lcdNr,"1",1);
uint8_t resultLCDNr2 = strncmp(lcdNr,"2",1);
uint8_t result7E = strcmp(start,pcStart);
uint8_t result0D = strcmp(end,pcEnd);
uint8_t result2A = strcmp(cmd,pcProductChange);
uint8_t result30 = strcmp(cmd,pcsupplierChange);
char planeleft[2],planeright[2],tempplanes[5];
strcpy(tempplanes,planes); // If this is used,the next strcpy causes lprinted variable's first element to be "0\"
strcpy(planeleft,strtok(tempplanes,"-"));
strcpy(planeright,"-"));
/* START OF PROBLEMATIC AREA */
if (result7E == 0 && result0D == 0){
if (result2A == 0){ //Product Change
if (resultLCDNr1 == 0){
strcpy(productInfoLeft.ucActualID,pid);
strcpy(productInfoLeft.ucPrinterLane,planeleft);
strcpy(productInfoLeft.ucProductName,pname);
strcpy(productInfoLeft.ucBestBeforeDate,bbdate);
strcpy(productInfoLeft.ucPrinted,lprinted);
strcpy(productInfoLeft.ucToBePrinted,ltoprinted);
strcpy(productInfoLeft.ucLane,laneNr);
strcpy(productInfoLeft.ucLcdNumber,lcdNr);
strcpy(productInfoLeft.ucsupplierInfo,sinfo);
}else if (resultLCDNr2 == 0){
strcpy(productInfoRight.ucActualID,pid);
strcpy(productInfoRight.ucPrinterLane,planeright);
strcpy(productInfoRight.ucProductName,pname);
strcpy(productInfoRight.ucBestBeforeDate,bbdate);
strcpy(productInfoRight.ucPrinted,lprinted);
strcpy(productInfoRight.ucToBePrinted,ltoprinted);
strcpy(productInfoRight.ucLane,laneNr);
strcpy(productInfoRight.ucLcdNumber,lcdNr);
strcpy(productInfoRight.ucsupplierInfo,sinfo);
}else{
return;
}
SetProductChangeOnLCD(lcdNr);
}
if (result30 == 0){ //Supply Change
if (resultLCDNr1 == 0){
strcpy(productInfoLeft.ucActualID,sinfo);
}else{
return;
}
SetsupplierChangeOnLCD(lcdNr);
}
}
/* END OF PROBLEMATIC AREA */
free(start);
free(len);
free(cmd);
free(data);
free(chksum);
free(end);
}
子字符串函数:
char *substr3(char const *input,size_t start,size_t len) {
char *ret = malloc(len+1);
memcpy(ret,input+start,len);
ret[len] = '\0';
return ret;
}
解决方法
仅供参考,我想分享我的发现和解决问题的方法。
有两个问题。一种是数组大小,其中char用于strcpy。某些贡献者没有正确设置。
一旦数组大小固定,就会以更清晰的方式揭示出另一个问题。关于malloc。出于某种原因,尽管在各种资源中都有其他说明,但如果在FreeRTOS实现中使用malloc,则可能会有HardFault。一旦我改用FreeRTOS建议的malloc和free函数,一切就变平了。 HardFault问题神奇地消失了。
我刚刚放置了这两个包装函数(在公共文件中的某个位置),甚至没有更改我的malloc和free调用。
创建与内置FreeRTOS堆一起使用的malloc / free函数非常简单。我们只包装了pvPortMalloc / pvPortFree调用:
void* malloc(size_t size)
{
void* ptr = NULL;
if(size > 0)
{
// We simply wrap the FreeRTOS call into a standard form
ptr = pvPortMalloc(size);
} // else NULL if there was an error
return ptr;
}
void free(void* ptr)
{
if(ptr)
{
// We simply wrap the FreeRTOS call into a standard form
vPortFree(ptr);
}
}
请注意:您不能将其与堆模式1一起使用,而与其他模式(2、3、4和5)一起使用。我建议开始使用Portable / MemMang / heap_4.c