1.现象
代码片段:
uint8_t CmdListener(char c)
{
#define CMD_SIZE 5
static uint8_t cmdQueue[9];
static uint8_t cmdReset[] = { '!', 'b', 'o', 'o', 't'};
static uint8_t cmdYModem[] = { 0x01, 0x00, 0xff };
static uint8_t cmdIdx = 0;
int i;
xlog("%c", 0xcc);
for(int i = 0; i<sizeof(cmdReset); ++i)
{
xlog("%c", cmdReset[i]);
}
xlog("%c", 0xcd);
xlog("%c", c);
return;
实测结果:
2.排错
2.1 检查.hex文件,确认相关初始化字符在
map文件:
CmdListener@cmdReset dataBANK0 0000D6
上面是.map文件的记录。
Hex文件:
:040000000EEF00F00F
:0400080004EF1CF0F5
:080018000CEF1CF0BCEF0CF032
:100600000001000A006400E80310272747273A6723
:100610006F746F204170700D0A274C273A6C6F6120
:1006200064206669726D776172650D0A27487C3FA8
.hex文件,
代码从0x600开始排。代码是如何进入DataRam的?但是总归,这个21 62 6f 6f 74应该会在指令ROM里,对吧?搜索:
指令ROM, HEX文件里确实不存在这些信息。
2.2 重新编译,检查Warning.
无相关的Warning,但是检查出来额外的一处编码错误:
bool IsAppExisted(void)
{
char *dstAddr = NEW_RESET_VECTOR;
if(*dstAddr != 0xff) return true;
return false;
}
相关的单片机是哈佛结构,很可能无法直接取指令ROM空间的地址,参与运算。查阅示例文件,改为如下形式:
bool IsAppExisted(void)
{
// ******************************************************************
// Check the reset vector for code to initiate bootloader
// ******************************************************************
// This section reads the application start
// vector to see if the location is blank
TBLPTR = NEW_RESET_VECTOR; // (0xFF) or not. If blank, it runs the
// bootloader. Otherwise, it assumes the
// application is loaded and instead runs the
// application.
EECON1 = 0x80;
asm("TBLRD *+");
if (TABLAT == 0xFF)
{
return (false);
}
return (true);
}
2.3 关编译优化选项,重试
无改观。
2.4 查阅C99标准
查阅 C99标准,支持。
2.5 查阅这几天调整过的有关初始化的编译开关
正常。
3.检查编译器,寻找解决方案
查阅XC8 CC文档,发现:
我现在知道这个编译开关是为了什么目的存在的。所有的代码都在ROM里,所以,引入Bootloader后,你可以控制全局初始化中比如类似在Bootloader和APP中公用的部分,是否需要加载两次。比如:类似字库这类东西。