一、前文

第一次接触MSP430的芯片,第一次使用CCS开发环境,花了将近一个星期的时间,才把MSP430串口升级做出来。

同样分成BOOT(引导程序)、APP(主程序)、上位机(PC端工具),三个部分来讲解。

本博文主要是讲述遇到的一些问题。

基于CCS工程MSP430串口升级(一)

基于CCS工程MSP430串口升级(二)

二、正文

折腾这个功能的时候,遇到了很多问题,现在来一一描述

  1. C和汇编语言混合编程
    C语言嵌入汇编语言是asm(“xxx”);,这样一开始编译一直不过。
    然后几经百度谷歌后,发现在xxx前面加上制表符\t,asm(" xxx");,编译就过了。
    IAR没有这个问题,CCS就这样。看来CCS编译器还有待改进。
  2. 汇编语言,#和&傻傻分不清
    mov #0xEFFE,PC和mov &0xEFFE,PC
    一开始搞不清楚,啥区别。后来才知道#是直接把0xEFFE赋值给PC,&是把0xEFFE地址上面的值赋值给PC,就跟指针是一个概念。
  3. Flash整块写入,Flash要整块擦除和写入
  4. 从BOOT的串口接收中断函数跳转到APP的串口接收中断函数,堆栈出错。
    原本的做法是,BOOT和APP各有一个串口接收中断函数,然后在BOOT里面根据一个标志位做判断,跳转到APP的串口接收中断。
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI_A0_rx (void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCIAB0RX_VECTOR))) USCI_A0_rx (void)
#else
#error Compiler not supported!
#endif
{
//	printf("%c",UCA0RXBUF);
//	if(isBoot==2)
//	{
		asm("	br &0xEFF2;");
//	}
//	else
//	{
//		rx_buf[rx_buf_index++] = UCA0RXBUF;
//		if(rx_buf_index>=RX_SIZE)
//			rx_buf_index = 0;
//	}
}

后面调试的时候,发现每次从BOOT串口接收中断跳转到APP的串口接收中断后,程序都会重启,百思不得其解,然后就单步调试,在BOOT的程序里面还能看到C代码,跳转到APP里面去后,就只剩汇编代码了,只能硬着头皮看汇编。
后面发现,在BOOT和APP两个的串口接收中断函数里面,都会直接执行pop push R14和R15的动作,BOOT里面做过这个动作后,再进到APP里面,应该要pop push R12 和R13其他的寄存器,来保存现场,而不是覆盖修改掉了R14和R15,导致中断函数返回后,无法恢复现场,程序直接重启了。
这个问题跟编译器有关,但是又不能怪编译器,因为BOOT和APP是分开两个项目来编译的,从BOOT的中断接收函数直接跳转br到APP的中断接收函数,编译器无法预知哪些寄存器可以动,哪些寄存器不能动。
想了半天,没有想到什么好办法,只能禁用了BOOT的串口接收中断,在main里面轮询串口缓存区。这样在BOOT的串口接收中断中,就只有br到APP这一条汇编指令,就少了R14 R15的pop push操作,可以保证中断函数正确返回。

pop R14 
pop R15
......
push R14 
push R15

基于CCS工程MSP430串口升级(三)_串口升级