不知道各位使用带有ROM LM3S系列单片机的坛友们有没有碰到这个问题,flash能下载,但是验证失败。折腾了一宿,终于将这个问题解决。
将过程写下来,让以后的同学们少走弯路。
在调新的LM3S9B95开发板的时候,经常碰到的一个问题是flash编程后验证校验失败,提示信息如下:
(gdb) flash
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x61000000 pc: 0x00000748 msp: 0x20017fd0
erased address 0x00000000 length 262144 in 0.041978s
requesting target halt and executing a soft reset
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x01000c4c msp: 0x20000800
Algorithm flash write 111 words to 0x0, 0 remaining
wrote 446 byte from file main.axf in 0.195948s (2.222768 kb/s)
checksum mismatch - attempting binary compare
Verify operation failed address 0x00000001. Was 0x08 instead of 0x80
这也是这两天我一直在RAM里调试的原因,但是今天在必须编程固件的时候,我就必须得面对这个问题了.
用二进制文件查看器打开raw格式的固件,这里我使用的是hexdump,发现固件的前4个字是:
0000000 8000 2001 00f1 0000 01b9 0000 01bb 0000
由于hexdump没有显示4个字节的功能,所以这里就可以翻译为:
20018000 000000F1 000001B9 000001BB
第一个长字为堆栈的指针,LM3S9B95有96KB的RAM,16进制就是0x18000,基址为0x20000000.第2,3,4个长字为中断向量0,1,2的地址,可以看到程序编译结构没有问题.
根据上面的出错信息,flash的第2个字节0x00000001应该是0x80,但是读出来的却是0x08,这肯定有问题了.
是不是flash没擦除干净呢?
那就将flash全部清空:
(gdb) monitor stellaris mass_erase 0
stellaris mass erase complete
再次下载,还是出错.
是不是没有清除干净呢,再次执行monitor stellaris mass_erase 0将flash进行全部清除,然后查看flash的清除状态:
(gdb) monitor halt
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x61000000 pc: 0x20002062 msp: 0x20000800
(gdb) monitor stellaris mass_erase 0
stellaris mass erase complete
(gdb) monitor flash erase_check 0
AHBAP Cached values: dp_select 0x0, ap_csw 0xa2000012, ap_tar 0xffffffff
SWJ-DP STICKY ERROR
Read MEM_AP_CSW 0x23000052, MEM_AP_TAR 0x6a04
AHBAP Cached values: dp_select 0x0, ap_csw 0xa2000012, ap_tar 0xffffffff
SWJ-DP STICKY ERROR
Read MEM_AP_CSW 0x23000052, MEM_AP_TAR 0x6a04
Block read error address 0x6800, count 0x100
unknown error when checking erase state of flash bank #0 at 0x00000000
# 0: 0x00000000 (0x400 1kB) not erased
# 1: 0x00000400 (0x400 1kB) not erased
# 2: 0x00000800 (0x400 1kB) not erased
# 3: 0x00000c00 (0x400 1kB) not erased
# 4: 0x00001000 (0x400 1kB) not erased
# 5: 0x00001400 (0x400 1kB) not erased
# 6: 0x00001800 (0x400 1kB) not erased
# 7: 0x00001c00 (0x400 1kB) not erased
# 8: 0x00002000 (0x400 1kB) not erased
# 9: 0x00002400 (0x400 1kB) not erased
# 10: 0x00002800 (0x400 1kB) not erased
# 11: 0x00002c00 (0x400 1kB) not erased
# 12: 0x00003000 (0x400 1kB) not erased
# 13: 0x00003400 (0x400 1kB) not erased
# 14: 0x00003800 (0x400 1kB) not erased
# 15: 0x00003c00 (0x400 1kB) not erased
# 16: 0x00004000 (0x400 1kB) not erased
# 17: 0x00004400 (0x400 1kB) not erased
# 18: 0x00004800 (0x400 1kB) not erased
# 19: 0x00004c00 (0x400 1kB) not erased
# 20: 0x00005000 (0x400 1kB) not erased
# 21: 0x00005400 (0x400 1kB) not erased
# 22: 0x00005800 (0x400 1kB) not erased
# 23: 0x00005c00 (0x400 1kB) not erased
# 24: 0x00006000 (0x400 1kB) not erased
# 25: 0x00006400 (0x400 1kB) not erased
# 26: 0x00006800 (0x400 1kB) erased
# 27: 0x00006c00 (0x400 1kB) erased
# 28: 0x00007000 (0x400 1kB) erased
# 29: 0x00007400 (0x400 1kB) erased
# 30: 0x00007800 (0x400 1kB) erased
# 31: 0x00007c00 (0x400 1kB) erased
# 32: 0x00008000 (0x400 1kB) erased
# 33: 0x00008400 (0x400 1kB) erased
# 34: 0x00008800 (0x400 1kB) erased
# 35: 0x00008c00 (0x400 1kB) erased
# 36: 0x00009000 (0x400 1kB) erased
# 37: 0x00009400 (0x400 1kB) erased
# 38: 0x00009800 (0x400 1kB) erased
# 39: 0x00009c00 (0x400 1kB) erased
# 40: 0x0000a000 (0x400 1kB) erased
# 41: 0x0000a400 (0x400 1kB) erased
# 42: 0x0000a800 (0x400 1kB) erased
# 43: 0x0000ac00 (0x400 1kB) erased
# 44: 0x0000b000 (0x400 1kB) erased
# 45: 0x0000b400 (0x400 1kB) erased
# 46: 0x0000b800 (0x400 1kB) erased
# 47: 0x0000bc00 (0x400 1kB) erased
# 48: 0x0000c000 (0x400 1kB) erased
# 49: 0x0000c400 (0x400 1kB) erased
# 50: 0x0000c800 (0x400 1kB) erased
# 51: 0x0000cc00 (0x400 1kB) erased
# 52: 0x0000d000 (0x400 1kB) erased
# 53: 0x0000d400 (0x400 1kB) erased
# 54: 0x0000d800 (0x400 1kB) erased
# 55: 0x0000dc00 (0x400 1kB) erased
# 56: 0x0000e000 (0x400 1kB) erased
# 57: 0x0000e400 (0x400 1kB) erased
# 58: 0x0000e800 (0x400 1kB) erased
# 59: 0x0000ec00 (0x400 1kB) erased
# 60: 0x0000f000 (0x400 1kB) erased
# 61: 0x0000f400 (0x400 1kB) erased
# 62: 0x0000f800 (0x400 1kB) erased
# 63: 0x0000fc00 (0x400 1kB) erased
# 64: 0x00010000 (0x400 1kB) erased
# 65: 0x00010400 (0x400 1kB) erased
# 66: 0x00010800 (0x400 1kB) erased
# 67: 0x00010c00 (0x400 1kB) erased
# 68: 0x00011000 (0x400 1kB) erased
# 69: 0x00011400 (0x400 1kB) erased
# 70: 0x00011800 (0x400 1kB) erased
# 71: 0x00011c00 (0x400 1kB) erased
# 72: 0x00012000 (0x400 1kB) erased
# 73: 0x00012400 (0x400 1kB) erased
# 74: 0x00012800 (0x400 1kB) erased
# 75: 0x00012c00 (0x400 1kB) erased
# 76: 0x00013000 (0x400 1kB) erased
# 77: 0x00013400 (0x400 1kB) erased
# 78: 0x00013800 (0x400 1kB) erased
# 79: 0x00013c00 (0x400 1kB) erased
# 80: 0x00014000 (0x400 1kB) erased
# 81: 0x00014400 (0x400 1kB) erased
# 82: 0x00014800 (0x400 1kB) erased
# 83: 0x00014c00 (0x400 1kB) erased
# 84: 0x00015000 (0x400 1kB) erased
# 85: 0x00015400 (0x400 1kB) erased
# 86: 0x00015800 (0x400 1kB) erased
# 87: 0x00015c00 (0x400 1kB) erased
# 88: 0x00016000 (0x400 1kB) erased
# 89: 0x00016400 (0x400 1kB) erased
# 90: 0x00016800 (0x400 1kB) erased
# 91: 0x00016c00 (0x400 1kB) erased
# 92: 0x00017000 (0x400 1kB) erased
# 93: 0x00017400 (0x400 1kB) erased
# 94: 0x00017800 (0x400 1kB) erased
# 95: 0x00017c00 (0x400 1kB) erased
# 96: 0x00018000 (0x400 1kB) erased
# 97: 0x00018400 (0x400 1kB) erased
# 98: 0x00018800 (0x400 1kB) erased
# 99: 0x00018c00 (0x400 1kB) erased
#100: 0x00019000 (0x400 1kB) erased
#101: 0x00019400 (0x400 1kB) erased
#102: 0x00019800 (0x400 1kB) erased
#103: 0x00019c00 (0x400 1kB) erased
#104: 0x0001a000 (0x400 1kB) erased
#105: 0x0001a400 (0x400 1kB) erased
#106: 0x0001a800 (0x400 1kB) erased
#107: 0x0001ac00 (0x400 1kB) erased
#108: 0x0001b000 (0x400 1kB) erased
#109: 0x0001b400 (0x400 1kB) erased
#110: 0x0001b800 (0x400 1kB) erased
#111: 0x0001bc00 (0x400 1kB) erased
#112: 0x0001c000 (0x400 1kB) erased
#113: 0x0001c400 (0x400 1kB) erased
#114: 0x0001c800 (0x400 1kB) erased
#115: 0x0001cc00 (0x400 1kB) erased
#116: 0x0001d000 (0x400 1kB) erased
#117: 0x0001d400 (0x400 1kB) erased
#118: 0x0001d800 (0x400 1kB) erased
#119: 0x0001dc00 (0x400 1kB) erased
#120: 0x0001e000 (0x400 1kB) erased
#121: 0x0001e400 (0x400 1kB) erased
#122: 0x0001e800 (0x400 1kB) erased
#123: 0x0001ec00 (0x400 1kB) erased
#124: 0x0001f000 (0x400 1kB) erased
#125: 0x0001f400 (0x400 1kB) erased
#126: 0x0001f800 (0x400 1kB) erased
#127: 0x0001fc00 (0x400 1kB) erased
#128: 0x00020000 (0x400 1kB) erased
#129: 0x00020400 (0x400 1kB) erased
#130: 0x00020800 (0x400 1kB) erased
#131: 0x00020c00 (0x400 1kB) erased
#132: 0x00021000 (0x400 1kB) erased
#133: 0x00021400 (0x400 1kB) erased
#134: 0x00021800 (0x400 1kB) erased
#135: 0x00021c00 (0x400 1kB) erased
#136: 0x00022000 (0x400 1kB) erased
#137: 0x00022400 (0x400 1kB) erased
#138: 0x00022800 (0x400 1kB) erased
#139: 0x00022c00 (0x400 1kB) erased
#140: 0x00023000 (0x400 1kB) erased
#141: 0x00023400 (0x400 1kB) erased
#142: 0x00023800 (0x400 1kB) erased
#143: 0x00023c00 (0x400 1kB) erased
#144: 0x00024000 (0x400 1kB) erased
#145: 0x00024400 (0x400 1kB) erased
#146: 0x00024800 (0x400 1kB) erased
#147: 0x00024c00 (0x400 1kB) erased
#148: 0x00025000 (0x400 1kB) erased
#149: 0x00025400 (0x400 1kB) erased
#150: 0x00025800 (0x400 1kB) erased
#151: 0x00025c00 (0x400 1kB) erased
#152: 0x00026000 (0x400 1kB) erased
#153: 0x00026400 (0x400 1kB) erased
#154: 0x00026800 (0x400 1kB) erased
#155: 0x00026c00 (0x400 1kB) erased
#156: 0x00027000 (0x400 1kB) erased
#157: 0x00027400 (0x400 1kB) erased
#158: 0x00027800 (0x400 1kB) erased
#159: 0x00027c00 (0x400 1kB) erased
#160: 0x00028000 (0x400 1kB) erased
#161: 0x00028400 (0x400 1kB) erased
#162: 0x00028800 (0x400 1kB) erased
#163: 0x00028c00 (0x400 1kB) erased
#164: 0x00029000 (0x400 1kB) erased
#165: 0x00029400 (0x400 1kB) erased
#166: 0x00029800 (0x400 1kB) erased
#167: 0x00029c00 (0x400 1kB) erased
#168: 0x0002a000 (0x400 1kB) erased
#169: 0x0002a400 (0x400 1kB) erased
#170: 0x0002a800 (0x400 1kB) erased
#171: 0x0002ac00 (0x400 1kB) erased
#172: 0x0002b000 (0x400 1kB) erased
#173: 0x0002b400 (0x400 1kB) erased
#174: 0x0002b800 (0x400 1kB) erased
#175: 0x0002bc00 (0x400 1kB) erased
#176: 0x0002c000 (0x400 1kB) erased
#177: 0x0002c400 (0x400 1kB) erased
#178: 0x0002c800 (0x400 1kB) erased
#179: 0x0002cc00 (0x400 1kB) erased
#180: 0x0002d000 (0x400 1kB) erased
#181: 0x0002d400 (0x400 1kB) erased
#182: 0x0002d800 (0x400 1kB) erased
#183: 0x0002dc00 (0x400 1kB) erased
#184: 0x0002e000 (0x400 1kB) erased
#185: 0x0002e400 (0x400 1kB) erased
#186: 0x0002e800 (0x400 1kB) erased
#187: 0x0002ec00 (0x400 1kB) erased
#188: 0x0002f000 (0x400 1kB) erased
#189: 0x0002f400 (0x400 1kB) erased
#190: 0x0002f800 (0x400 1kB) erased
#191: 0x0002fc00 (0x400 1kB) erased
#192: 0x00030000 (0x400 1kB) erased
#193: 0x00030400 (0x400 1kB) erased
#194: 0x00030800 (0x400 1kB) erased
#195: 0x00030c00 (0x400 1kB) erased
#196: 0x00031000 (0x400 1kB) erased
#197: 0x00031400 (0x400 1kB) erased
#198: 0x00031800 (0x400 1kB) erased
#199: 0x00031c00 (0x400 1kB) erased
#200: 0x00032000 (0x400 1kB) erased
#201: 0x00032400 (0x400 1kB) erased
#202: 0x00032800 (0x400 1kB) erased
#203: 0x00032c00 (0x400 1kB) erased
#204: 0x00033000 (0x400 1kB) erased
#205: 0x00033400 (0x400 1kB) erased
#206: 0x00033800 (0x400 1kB) erased
#207: 0x00033c00 (0x400 1kB) erased
#208: 0x00034000 (0x400 1kB) erased
#209: 0x00034400 (0x400 1kB) erased
#210: 0x00034800 (0x400 1kB) erased
#211: 0x00034c00 (0x400 1kB) erased
#212: 0x00035000 (0x400 1kB) erased
#213: 0x00035400 (0x400 1kB) erased
#214: 0x00035800 (0x400 1kB) erased
#215: 0x00035c00 (0x400 1kB) erased
#216: 0x00036000 (0x400 1kB) erased
#217: 0x00036400 (0x400 1kB) erased
#218: 0x00036800 (0x400 1kB) erased
#219: 0x00036c00 (0x400 1kB) erased
#220: 0x00037000 (0x400 1kB) erased
#221: 0x00037400 (0x400 1kB) erased
#222: 0x00037800 (0x400 1kB) erased
#223: 0x00037c00 (0x400 1kB) erased
#224: 0x00038000 (0x400 1kB) erased
#225: 0x00038400 (0x400 1kB) erased
#226: 0x00038800 (0x400 1kB) erased
#227: 0x00038c00 (0x400 1kB) erased
#228: 0x00039000 (0x400 1kB) erased
#229: 0x00039400 (0x400 1kB) erased
#230: 0x00039800 (0x400 1kB) erased
#231: 0x00039c00 (0x400 1kB) erased
#232: 0x0003a000 (0x400 1kB) erased
#233: 0x0003a400 (0x400 1kB) erased
#234: 0x0003a800 (0x400 1kB) erased
#235: 0x0003ac00 (0x400 1kB) erased
#236: 0x0003b000 (0x400 1kB) erased
#237: 0x0003b400 (0x400 1kB) erased
#238: 0x0003b800 (0x400 1kB) erased
#239: 0x0003bc00 (0x400 1kB) erased
#240: 0x0003c000 (0x400 1kB) erased
#241: 0x0003c400 (0x400 1kB) erased
#242: 0x0003c800 (0x400 1kB) erased
#243: 0x0003cc00 (0x400 1kB) erased
#244: 0x0003d000 (0x400 1kB) erased
#245: 0x0003d400 (0x400 1kB) erased
#246: 0x0003d800 (0x400 1kB) erased
#247: 0x0003dc00 (0x400 1kB) erased
#248: 0x0003e000 (0x400 1kB) erased
#249: 0x0003e400 (0x400 1kB) erased
#250: 0x0003e800 (0x400 1kB) erased
#251: 0x0003ec00 (0x400 1kB) erased
#252: 0x0003f000 (0x400 1kB) erased
#253: 0x0003f400 (0x400 1kB) erased
#254: 0x0003f800 (0x400 1kB) erased
#255: 0x0003fc00 (0x400 1kB) erased
可以看到0x6800是一个比较可疑的地方,这个地址之前的flash都没有被清空,而且还提示了出错信息.
为了对比,就直接读取了flash的前4个字:
(gdb) monitor mdw 0 4
0x00000000: 20000800 01000c4d 01000cc5 01000d13
果然不出所料,0x00000001地址的字节果然是0x08,和刚刚的出错信息"Verify operation failed address 0x00000001. Was 0x08 instead of 0x80"一致.
继续向后看,竟然发现中断地址的基址为0x01000000,这是什么地方呢?原来这是LM3S9B95的ROM区,flash区竟然被映射到这里来了,由于以前一直使用LM3S8962的板子,上面没有ROM,所以没有碰到这个问题.碰到问题怎么办,最权威的就是数据手册了,在LM3S9B95数据手册的第六章,内部存储器,终于找到了ROM控制的寄存器RMCTL,地址为0x400FE0F0,只有一个有效bit,当此位为1时,MCU的ROM区就给映射到了0x0,为0,映射到0x0的将是flash区.
查看一下这个寄存器:
(gdb) monitor mdw 0x400FE0F0 1
0x400fe0f0: 00000001
果然问题在这.也就是说,在下载前只要将此bit置0,那么就能正常进行flash下载了.
在.gdbinit文件里,修改以前的flash下载函数为:
define flash
monitor mww 0x400fe0f0 1 1
monitor halt
monitor mww 0x400fe0f0 1 1
monitor stellaris mass_erase 0
#monitor flash erase_address 0 262144
monitor soft_reset_halt
monitor mww 0x400fe0f0 1 1
monitor flash write_image main.axf
monitor mww 0x400fe0f0 1 1
monitor verify_image main.axf
monitor reset
x/4 0
end
由于下载flash需要几个步骤,停止MCU,复位,擦除,下载.所以这个函数里有4个地方添加了monitor mww 0x400fe0f0 1 1,意思是向0x400fe0f0这个寄存器里写1,有些人可能有疑惑了,不是说让这个寄存器置0才有用吗?
本来我写的是monitor mww 0x400fe0f0 0 1,即向这个寄存器里写1,但是写完后发现没有改变,再仔细读数据手册,才发现"This bit is cleared by writing a 1 to this bit position".
修改完后,下载测试,完全正常!问题解决.
数据手册是解决问题的一手资料,出现问题后,大家一般都下意识的到论坛上发问,当然这样很好,能够省去好多时间,加快开发的进度,但是如果是新问题的话,还是得自己一步一步解决,这个时候就应该耐心的查看数据手册了.想起当年花了50块钱将Atmega128的数据手册完完整整的打印了一份,看着这么多页的LM3S系列单片机数据手册,只能作罢.