【跑飞、死机】单片机 msp430程序跑飞原因和解决方式积累

目录

单片机 msp430程序跑飞原因和解决方式积累

MSP430 数组填充越界引起的栈溢出 导致程序跑飞

【单片机重启】MSP430重启/频繁重启/跑飞 原因分析


单片机 msp430程序跑飞原因和解决方式积累

1.中断或主函数中有死循环,现象是程序停在某处。
2.堆栈溢出。现象是程序跑飞。
**************************************************************************************************

3、是否开了中断但是没有用。如:

开了中断:

  TA0CCTL0 = CCIE;                          // CCR0 interrupt enabled
  TA0CCTL1 = CCIE;                          // CCR1 interrupt enabled//时间周期1使能
  TA0CCTL2 = CCIE;                          // CCR2 interrupt enabled//时间周期2使能
  TA0CCTL3= CCIE;                          // CCR3 interrupt enabled//时间周期3使能

但是:

定时器中:

 case 4: (  TA0CCTL2 = CCIE;  )和 case 6: (  TA0CCTL3= CCIE;  )内没有处理的程序。
    

……
  case 2:
    TA0CCR1 +=1024;                // Add Offset to CCR2
    SecondReach=1;
    CountToMunite++;
    Rquestinterval++;
    SecondTimecount++;
    break;                         // CCR4 not used
  case 4: 
     break;
  case 6:
    break;
  case 8:
    break;                         // CCR3 not used
……

4、数组越界。定义的数组只有50个单元,但是程序运行的过程中,却给他赋给50+个单元。

解决办法:
A.看中断有没有用 _EINT(),引起中断嵌套. 
B.Project--Options--General Options---Stack/Heap 将Stack size设置大一些。     (堆栈溢出)
3.中断耗时太长,刚出中断又进去了.这时的现象是程序一直在中断中执行,回不到主函数。 (中断嵌套)
4.检查CPU的电源是不是稳定,msp430在要保证程序正常运行,需保证Vcc大于1.8V。当电压低至0.8V时,程序仍有可能执行。这时的现象是PC指针乱飞,有复位,死机,停在中断,时钟频率发生变化等现象。
5.程序编译没问题,下载程序后上电不断复位,该问题是由于WDT造成的(RAM的初始化时间大于WDT默认的32MS时间,因此MSP复位)根本原因是初始化的时间过长,超过了看门狗的时间,初始化完成以后才能进入main函数,这时关狗已经来不及了。
解决的办法:
A 对你的数组用 __no init_定义,上电编译器不产生特殊的附加函数去初始化RAM.
B 在Project--Options--Linker--Config中选择 Override default programe,并将Entry lib 设置成 __program_start这时要修改Cstartup.S43(记得把它加入复制到工程而不是修改系统的),在第一条指令前加入关狗的指令,在main函数里再开(如果需要的话)。 
如果用汇编,则没有这个问题

http://topic.csdn.net/u/20100730/09/45f212a1-0354-4b73-ad62-335b5955c0f2.html

**************************************************************************************************

 6、把无用的中断允许关掉。

MSP430 数组填充越界引起的栈溢出 导致程序跑飞

1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。

//main.cpp 
int a = 0; 全局初始化区 
char *p1; 全局未初始化区 
main() 

int b; 栈 
char s[] = "abc"; 栈 
char *p2; 栈 
char *p3 = "123456"; 123456\0在常量区,p3在栈上。 
static int c =0; 全局(静态)初始化区 
p1 = (char *)malloc(10); 
p2 = (char *)malloc(20); 
分配得来得10和20字节的区域就在堆区。 
strcpy(p1, "123456"); 123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。 


二、堆和栈的理论知识 
2.1申请方式 
stack: 
由系统自动分配。 例如,声明在函数中一个局部变量 int b; 系统自动在栈中为b开辟空间 
heap: 
需要程序员自己申请,并指明大小,在c中malloc函数 
如p1 = (char *)malloc(10); 
在C++中用new运算符 
如p2 = (char *)malloc(10); 
但是注意p1、p2本身是在栈中的。

堆栈,堆栈,堆和栈的区别 - 任我行 - C++博客

12月3日  MSP430 堆栈溢出 解决

 MSP430程序在运行的过程中,出现死机的现象,通过IAR编译器观察,死机的原因是栈溢出。

因为定义的局部变量是在栈内的,所以分析可能是局部变量导致栈溢出,最有可能导致编译器不能事先判断

使用了多少栈的(超出设定值会报警),就是程序中产生新的占用栈的变量,由之前的经验推测是数组越界,因为如果程序不顾数组的边界,越界不断的往里填东西,越界的部分就会被当成局部变量,占用栈的内存。

因为栈是从RAM的底部网上长(存数据)的,而其他程序运行的数据是从顶部往下的,所以当栈越存越多,越积越高的时候,栈就会和程序运行时的数据碰头,二者占满整个RAM内存,此时栈再继续消耗,栈再向上长,直接覆盖掉程序运行时所需的变量,程序就要跑飞了。

(iar430中定义的变量是从ram的起始地址向上(由小到大),而堆栈是从ram的终止地址向下(由大到小)。
以msp430F5438为例,它是16KB的ram,起始地址为0x1C00h,终止地址为005BFFh(data sheet 15页),所以它的变量是从0x1C00h开始,向0x005BFFh方向存放,而堆栈是从0x005BFFh开始,向0x1C00h方向压栈。当变量存储空间和堆栈最大占用空间在中间相遇时,就发生了堆栈溢出。)

下面就详细介绍如何查看ram使用情况:

1   当然是烧程序到目标板里呀
2   选择view/memory,打开memory窗口

3   从ram的起始地址0x1C00h开始,输入0x3fff(16KB),再回车

4  选中0x1C00h~0x005BFFh区域,右键选择memory fill……

5  在memory fill中的start写入:0x1C00h,length写:0x3fff,value填入FF(也可填入其他值),被选中的区域全填充FF

6  运行程序,跑一遍设计的所有功能,再停止cspy,看看memory窗口

7  如果再填充的区域内已经没有FF存在,就说明已经发生堆栈溢出或是会有溢出的危险(ram刚好够用)。最好保留一定余量的ram不被改变,以防发生溢出

验证:定义一个UART0_RX_HEX_BUF[400];

 在程序中加入这个代码。

 unsigned int i;

  for(i=0;i<17000;i++)

  UART0_RX_HEX_BUF[i]=0xFA;

因为MSP430的RAM只有16KB,所以填17000次(char)足以保证栈全部占满RAM,覆盖掉所以运行程序的变量,导致跑飞。

程序运行结果是,程序跑飞。产看栈STACK,栈溢出。假设应该是正确的。

因而分析导致栈溢出的程序段应该是这里:

红色部分当时是为了避免中断程序过长跟不上中断,使得数据收不全而去掉的,现在分析if(UART0_RX_HEX_Len >= UART0_RX_HEX_MAXLen)

UART0_RX_HEX_Len = 0;

这两句子不能去掉,因为,在没有接收到协议数据(配置数据,FE……FA)之前,UART0_RX_HEX_BUF和UART0_RX_BUF一样在接收返回的AT指令返回,数组在不断的填装,UART0_RX_BUF每隔一段时间就会被读取一次,并清空,因而不会出现溢出。但是在没有收到配置数据之前,UART0_RX_HEX_BUF不会清空,且在配置完之后,只要服务站不发协议数据,也不会清空,因而UART0_RX_HEX_BUF基本处于只填装不清空的状态,最后远远越界,最终导致开头分析的结果。

加了清零语句:

if(UART0_RX_HEX_Len >= UART0_RX_HEX_MAXLen)

UART0_RX_HEX_Len = 0;

后,死机在12小时内在没有出现,其他比对机器全部死机,初步证明分析应该是正确的。

#pragma vector=USCI_A0_VECTOR

__interrupt void USCI_A0_ISR()

{

  UCA3TXBUF=UCA0RXBUF;//把接收的数据发到U3便于观察(LCX注)

  //接收字符数据时

  UART0_RX_BUF[UART0_RX_Len] = UCA0RXBUF;

  UART0_RX_Len++;

  ReadUART0_new=Read_Cycle;

  //接收协议数据时(16进制)

  UART0_RX_HEX_BUF[UART0_RX_HEX_Len] = UCA0RXBUF;

  if((UART0_RX_HEX_BUF[UART0_RX_HEX_Len]==0xFF)&&(UART0_RX_HEX_BUF[UART0_RX_HEX_Len-1]==0xFE))

  {

    UART0_RX_HEX_BUF[0]=UART0_RX_HEX_BUF[UART0_RX_HEX_Len-1];

    UART0_RX_HEX_BUF[1]=UART0_RX_HEX_BUF[UART0_RX_HEX_Len];

    UART0_RX_HEX_Len=1;

  }

  else if((UART0_RX_HEX_BUF[UART0_RX_HEX_Len]==0xFA)&&(UART0_RX_HEX_BUF[UART0_RX_HEX_Len-1]==0xFF))

  {

    ReadUART0_Permit=1;

    UCA0IE &= ~ UCRXIE;     

  }

  UART0_RX_HEX_Len++;

  if(UART0_RX_HEX_Len >= UART0_RX_HEX_MAXLen)

    UART0_RX_HEX_Len = 0;

  

}

【单片机重启】MSP430重启/频繁重启/跑飞 原因分析

2012-04-13 21:49:03

 1、堆栈溢出导致频繁重启:

案例1:

concern_tower_num为从铁电内读取的数据,因为铁电没有初始化,所以concern_tower_num的值很大

下面的程序一直循环到铁电内concern_tower_num所在位置的值,所以超过了option内所设置的stack的最大容量导致堆栈溢出,重启。

  for(int i=0;i
  {
    data[m]=crane_tower[i].crane_x;
    m++;
    data[m]=crane_tower[i].crane_y;
    m++;
    data[m]=crane_tower[i].front_arm_length;
    m++;    
  }

 2012.4.20 UESTC

 2、数组越界:

定义了一个29字节长度的数组: char back_info[29]={0};

结果给其填充50个字节的内容 memcpy( back_info+19,send_back_data,data_len);  ,现象是堆栈没有溢出,机器重启。

 2012.4.24 UESTC

MSP430F147程序总是莫名其妙的重新启动?
已经检查了堆栈没有溢出,WDT依然还是HOLD状态
哪位高手指点一下,还有哪种可能性?

答 1:

先看IFG1.0位状态,看是什么原因导致复位

答 2:

您测量一下复位脚上的波形,看是否是硬件复位。

答 3:

你的工作环境??是不是干扰问题?
是不是指针弄飞了??

答 4:

外部有看门狗吗?有的话要先关掉。

答 5:

谢谢以上各位的回答:
我的具体情况是原来程序是用查询方式,已经通过测试,没有这个问题
而现在需要添加部分功能,为此把查询方式改为了中断方式(新功能还未添加),

现在已经检查过IFG1.0位0,不是内部看门狗导致复位
外部无看门狗,也无明显干扰源
硬件复位可能性也不大,不过这个可以再测一下!

有可能是指针弄飞等程序错误,但是这种内部程序错误会导致系统复位吗?

答 6:

错误写FLASH也能复位,程序超出,复位向量错误等也可能导致复位。

答 7:

可能是复位电路问题!

答 8:

经测试,不是外部复位电路的问题!
现在问题应该在中断子程序对主函数造成了不确定的影响上,
但是目前仍无法定位问题在哪?
郁闷ing!!!

答 9:

是无法进入中断吗还是其他的原因,能具体说的详细些吗。

答 10:

呵呵,我的问题是430出现不确定的复位,有时运行几分钟就复位,有时能到几十分钟
而在这之前,我的程序是用的查询方式处理外部事务,一直运行正常,没有这个问题
现在改为中断来处理外部事务,就出现了莫名的复位问题

中断是能正常进入的!!

通过几天的排查,现在问题应该在中断子程序对主函数造成了不确定的影响,
从而导致了系统复位。但无法定位问题所在!

答 11:

检查一下数据指针吧,是否超出内存范围,看现象可能是这方面的影响

答 12:

程序发出来看看,不然干说也是查不出来

答 13:

一个中断一个中断使能,一个一个排查。多试几次就是了。把问题分块一个一个来。看哪个出的问题

这个跟单片机支持的断点个数也是有关的。如果只支持一个断点,你设置了2个,然后复位的话就容易跑到Cstart而不是Main。另外要注意IAR run to Main的复选框你勾上没?

案例二:跑飞 

void  send_basic_data_to_dis_part()

{

      

      char basic_data_buf[60]={0};    

      char frame_head[2]={0xFE,0xFB},frame_end[2]={0xFE,0xFA};

      char frame_len[1]={0x45},frame_type[1]={0x40};

      char bCRC[2]={0,0};

      char tower_num[1]={0x08};   

      unsigned int addr=0;

      addr=split_joint_hex_data(  basic_data_buf,addr,frame_head,2);       

      addr=split_joint_hex_data(  basic_data_buf,addr,frame_len,1);  

      addr=split_joint_hex_data(  basic_data_buf,addr,frame_type,1); 

      addr=split_joint_hex_data(  basic_data_buf,addr,tower_num,1); 

      for(uint8 i=0;i

      {

            

            addr=split_joint_hex_data(  basic_data_buf,addr,(char*)(&crane_tower[i].lcd_x),2);       

            addr=split_joint_hex_data(  basic_data_buf,addr,(char*)(&crane_tower[i].lcd_y),2);  

            addr=split_joint_hex_data(  basic_data_buf,addr,(char*)(&crane_tower[i].dis_fore_r),2); 

            addr=split_joint_hex_data(  basic_data_buf,addr,(char*)(&crane_tower[i].dis_back_r),2);   

            

      }

      CRC16(bCRC,basic_data_buf+2, addr-2);                                 //数据CRC校验

      addr=split_joint_hex_data(  basic_data_buf,addr,bCRC,2);                   

      addr=split_joint_hex_data(  basic_data_buf,addr,frame_end,2);                   

      

      UART2_Send_Buf(basic_data_buf,addr);

      

}

//basic_data_buf[60] 数组所开辟的长度为60,但是在下面从basic_data_buf首地址起填装数据的过程当中,填写的数据长度超过了60,数组越界,破坏了栈内保持的进入send_basic_data_to_dis_part()函数之前保存的现场数据,结果跳出该函数调用,要执行下步的时候,由于SP内的值已经被修改,导致程序跑飞。(这种情况症状往往表现为:进入某个函数内正常,在跳出的时候就跑飞,多为在函数内SP的指针被修改)


跑飞三:

程序中有 mallco()动态申请内存空间,却没有相应的释放,结果内存消耗完毕,程序跑飞。

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
msp430单片机程序设计流程分为以下几个步骤: 1. 确定需求:首先需要明确程序的需求和目标,包括所需的功能、输入输出要求和性能要求等。这有助于我们指导后续的设计和编程工作。 2. 配置开发环境:将所需的开发工具和软件环境配置好,包括编程软件、调试工具和适配器等。 3. 编写程序框架:根据需求,编写程序的基本框架结构,包括主函数和各个子函数的定义。这有助于程序的逻辑清晰和代码的复用。 4. 设计硬件接口:根据需求,确定所需的硬件接口和外设,比如输入输出口、计时器、串口等。然后根据硬件接口的规格书,设计和连接相应的电路。 5. 编写程序逻辑:根据需求和硬件接口的设计,编写程序的具体逻辑。可以使用C语言或汇编语言来编写,根据实际情况选择合适的编程语言。 6. 调试和测试:编写完程序后,进行调试和测试,以确保程序的正常运行。可以通过在开发环境中模拟测试,或者将程序下载到实际的硬件设备上进行测试。 7. 优化和改进:根据调试和测试的结果,对程序进行优化和改进。可以通过优化代码结构、减少资源占用等方式来提高程序的性能和效率。 8. 部署和应用:经过调试和改进后,将程序部署到实际的应用场景中,并进行实际应用。 以上就是msp430单片机程序设计的基本流程。不同的项目和需求可能会有所不同,但大致流程是相似的。通过以上流程,可以有效地进行msp430单片机程序的设计和开发。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值