最近在写stm32的串口处理程序,遇到一个问题程序跑着跑着就进入了硬件错误中断不可自拔。
void HardFault_Handler(void)
{
/* Go to infinite loop when Hard Fault exception occurs */
while (1)
{
}
}
通过调试定位到错误出现在下面的字符串处理函数函数中
char** strsplit(char *str, char stok)
{
char *p = str, *h = str, *item = NULL;
char **ret = NULL, **index;
int size = 0;
while(*p)
{
if(*p == stok)
size++;
p++;
}
ret = (char **)malloc((size+2) * sizeof(char *));
if(ret == NULL)
return NULL;
p = str;
index = ret;
while(*p)
{
if(*p == stok)
{
size = p - h-1;
item = (char *)malloc((size+1)*sizeof(char));
memset(item, '\0', size+1);
if(h == str)
memcpy(item, h,size+1);
else
memcpy(item, h+1,size);
h = p;
*index = item;
index++;
}
p++;
}
size = p - h-1;
item = (char *)malloc(size*sizeof(char));
memcpy(item, h+1,size);
*index = item;
*(index + 1) = NULL;
return ret;
}
这个函数单独测试没有任何题,但是我的系统使用的ucos-ii的多线程系统,另外我系统里还有5个串口中断处理函数。在这样的多线程系统中这个函数就出现了问题。
要分析这个函数的问题所在,首先要判断这回函数是否可重入。这是判断一个函数是否是线程安全的必要条件。我重读了这个函数,发现函数中没有使用全局变量和全局资源,唯一调用了malloc这个函数。如果这函数是不可重入的则strsplit这个函数也是不可重入的。
我百度发现https://blog.csdn.net/weiganyi/article/details/11142347这篇博文说malloc是不可重入的。于是我找到了 问题的原因:
我的程序结构如下:
//中断处理1
void uart1_hander()
{}
//中断处理2
void uart2_hander()
{}
//中断处理3
void uart3_hander()
{}
//中断处理4
void uart4_hander()
{}
//中断处理5
void uart5_hander()
{}
//解报文
void thread(){
switch(number){
case 1:
message = strsplit(buff, ',');
break;
case 2:
message = strsplit(buff, ',');
break;
case 3:
message = strsplit(buff, ',');
break;
case 4:
message = strsplit(buff, ',');
break;
case 5:
message = strsplit(buff, ',');
break;
}
}
如果程序在执行strsplit函数中的malloc函数时产生了串口中断,当中断返回时就可能出现栈溢出的问题,因此触发硬件中断。