环境: CCS 5.2 ( TI 的 HalCoGen 生成代码)
芯片: TMS570LS3137
现象: 编译正常,下载到芯片后,程序就跑飞了
原因: 程序中定义了长度比较大的缓冲区
最近在 TMS570LS3137 的板子上,写了一个 CAN 相关的小程序,主要完成功能为:
将CAN总线上的数据,全部(不过滤)接收下来,然后通过 UART 发送到 PC ,最终由串口助手接收数据。
写这个小程序的初衷就是就是监控 CAN 总线上的数据,最后根据数据内容,对其他板子的调试提供一个参考作用。
需要检测的 CAN 总线有独立的两路,一开始,简单起见,程序的第一个版本只对其中一路 CAN 进行了监控,程序运行良好。
第一版的主体程序为:
1 #define D_SIZE 8 2 #define BUF_SIZE 1024 3 4 typedef struct DataBufStr { 5 uint8 Buffer[BUF_SIZE]; 6 uint8 * Head; 7 uint8 * Tail; 8 }DataBuf_t; 9 10 uint8 rx_data[D_SIZE] = {0}; 11 uint8 rx_done = 0; 12 13 void main(void) 14 { 15 uint32 i;20 DataBuf_t CanRXBuf; 21 _enable_interrupt_(); 22 canInit(); 23 gioInit(); 24 sciInit(); 25 gioSetDirection(gioPORTB, 0xFFFFFFFF); 26 CanRXBuf.Head = CanRXBuf.Buffer; 27 CanRXBuf.Tail = CanRXBuf.Buffer; 28 29 i = 0; 30 31 while(1) 32 { 33 if (rx_done == 1) { 34 rx_done = 0; 35 if ((CanRXBuf.Tail + D_SIZE) <= (CanRXBuf.Buffer + BUF_SIZE)) { 36 memcpy(CanRXBuf.Tail, rx_data, D_SIZE); 37 CanRXBuf.Tail += D_SIZE; 38 } 39 } 40 if (CanRXBuf.Tail > CanRXBuf.Head) { 41 sciSendByte(scilinREG, *(CanRXBuf.Head)); 42 CanRXBuf.Head += 1; 43 if (CanRXBuf.Tail == CanRXBuf.Head) { 44 CanRXBuf.Tail = CanRXBuf.Buffer; 45 CanRXBuf.Head = CanRXBuf.Buffer; 46 } 47 } 48 i++; 49 if (i == 0x3FFFFFU) { 50 i = 0U; 51 } 52 } 53 }
其中的 rx_done 和 rx_data[] 是在中断程序分别进行置位和赋值的。然后于主程序中,将 rx_data[] 中数据复制到长度为 1024 字节的缓冲区中,最后再由 SCI 串口(或者说 UART )依次将缓冲区的数据发送出去。
第二版程序的改进有:增加一路 CAN 接收数据,同时增加一个缓冲区,又考虑到CAN数据发送频率可能会比较高,为了防止缓冲区溢出,所以每个缓冲区的长度增至 8192 字节,相当于两路 CAN 同时监控各自的总线,将接收的数据先存放于各自的缓冲区(长度均为 8192 字节)中,最后这些数据又分别通过不同的串口发送出去。
第二版程序编译没有问题,也生成了可执行代码文件,但是将程序下载到芯片后,执行程序,然后就跑飞了,基本是在 gioSetDirection(gioPORTB, 0xFFFFFFFF); 这一句代码执行完成后就飞了,进入了 sys_intvecs.asm 文件的这个地方:
prefetchEntry
b prefetchEntry
b _dabort
进入了 _babort() 函数,这个函数应该是链接库中自带的,工程目录中找不到相应的源代码。
调试了很长时间,怀疑过 CAN 或 SCI 的寄存器配置有问题,尝试过几次新的配置都无济于事,看 TMS570 的 System Exception Status Register 寄存器,也只有第3位置1,说明不了问题。所以在这里卡了一段时间。
后来,突然想试一试小一点的缓冲区,试了一下 4096 字节,程序也会跑飞。然后将两个缓冲区改成了 2048 字节,最后编译、下载,程序竟然正常了!这种事情还是第一次遇到,现在貌似可以这样解释,两个缓冲区都是定义在 main() 函数中,而分配给 main 的程序空间可能比较小,已经无法承受高达8K字节的空间分配,最终导致跑飞。当然现在只是一种猜测,毕竟 TMS570LS3137 的片内 Flash 有256K字节呢,后面有时间还需要研究一下 TMS570 对应程序空间、堆、栈的分配。
基本情况就是这样了,总之是代码中定义过大的变量,导致程序跑飞。