硬件环境:F103ZET6,DM9000
软件环境:ucosii,lwip1.4.1
在开发mqtt应用的时候,遇到如下问题:
(1)程序进入 HardFault_Handler ,并且没有什么规律,有时候运行几小时,有时候运行数天才会进入,日志输出lwip的断言错误:Assertion "tcp_write: pbufs on queue => at least one queue non-empty" failed at line 329 in ..\LWIP\lwip-1.4.1\src\core\tcp_out.c
(2)调用过程如下:
文章图片
【UCOS与LWIP使用过程中遇到的进入HardFault_Handler的问题】 解决过程:
(一)查看堆栈
(1)通过Keil的Register Window查看MSP地址
文章图片
(2)打开Memory Window,查看内存
文章图片
按照网上查的资料,堆栈内的地址分别为(可能与CPU有关):R0,R1,R2,R3,R12,LR,PC 。在Disassembly中跳转到PC指向的地址,发现提示 OSStartHang 错误。
在网上查OSStartHang错误,都在说同一个问题,就是PendSVHandler中断与ucos中的OSPendSV冲突,检查自己的配置发现没有这个问题。
问题没有解决,继续找原因吧。
(二)怀疑堆栈空间不足
(1)在startup_stm32f10x_hd.s 文件中查看栈区大小为:Stack_SizeEQU0x00000400
(2)在 .map文件中查看
0x2000e300-0x00000400ZeroRW4558STACKstartup_stm32f10x_hd.o
(3)在Memory Window中查看 0x2000e300? ,发现还有很多未使用空间
(5)结果排除栈空间不足的问题
(三)怀疑多任务调度的问题。在网上查资料,发现一篇文章,有点启发
文章图片
貌似是因为TCP/IP 任务的优先级较高,在调用过程中出现了任务调度冲突了,自己尝试改一下 。
按照这个思路修改了mqtt向tcp发送的方法,增加了关闭中断。
在 mqtt_output_send()方法中,修改:
(1)
OS_ENTER_CRITICAL();
err = tcp_write(tpcb, mqtt_ringbuf_get_ptr(rb), send_len, TCP_WRITE_FLAG_COPY | (wrap ? TCP_WRITE_FLAG_MORE : 0));
OS_EXIT_CRITICAL();
(2)
OS_ENTER_CRITICAL();
err = tcp_write(tpcb, mqtt_ringbuf_get_ptr(rb), send_len, TCP_WRITE_FLAG_COPY);
OS_EXIT_CRITICAL();
(3)
OS_ENTER_CRITICAL();
tcp_output(tpcb);
OS_EXIT_CRITICAL();
修改上述三个地方,编译运行。
本以为解决了问题,结果运行了不到几个小时,出现了新问题。虽然对 lwip的调用增加了保护,但是运行过程中出现了主任务挂起的问题,其他任务可以正常被调度,但是在mqtt的任务被挂起,无法进入。
目前尚未找到原因。