//非内核区闪存的修改

  闪存的修改也包括内核区闪存的修改和非内核区闪存的修改,这里讨论内核区闪存的修改.

   要修改闪存区域的某个地址或某段地址的内容,首先必须保证该个地址或该段地址的内容为 FF

如果不是,那么必须擦除该个地址或该段地址所在的闪存块.

  如图1:

  这里由于地址4010-4017内容是 FF,所以这里我们就修改0E页码地址4010 -地址 4017的内容为 00 01 02 03 04 05 06 07

但是大家要注意的是,我这里的0E页码是没有被系统占用的,大家实验的时候,先找块没有被系统用的页码,然后才可以实验

程序如下:

    A 2000

 

    2000:SEI                          //设置中断标志

    2001:LDA $00                      //保护地址00 0A 0D 的内容,方法是先压入堆栈

    2003:PHA

    2004:LDA $0A

    2006:PHA

    2007:LDA $0D

    2009:PHA

    200A:LDA $0A                     //地址0A的最高位置 0

    200C:AND #$7F

    200E:STA $0A

 

    2010:LDA #$10                   //这里把目标地址的高8位送地址 41, 低8位送地址 40

    2012:STA $40

    2014:LDA #$40

    2016:STA $41

 

    2018:LDA #$0E                //把页码数送寄存器A

    201A:STA $00                //切换到了 09 页码了

 

    201C:LDY #$00               //X,Y寄存器初始化均为 00

    201E:LDX #$00

 

    2020:TXA                    //寄存器 X的内容送 A

    2021:PHA                   //A 的内容送堆栈

 

    2022:LDA #$AA            //这里就是 修改闪存的 代码了,大家不能改,照着抄

    2024:STA $5555

    2027:LDA #$55

    2029:STA $AAAA

    202C:LDA #$A0

    202E:STA $5555

 

    2031:PLA                //把原来压入堆栈 的  X 的内容弹出堆栈,并送寄存器A

    2032:STA ($40),Y       //寄存器 A 的内容送以 地址 40的内容为低8位,41的内容为高8位的16地址,实现修改闪存

   

    2034:LDA $8000         //这段代码是检测是否修改成功,大家不要变

    2037:AND #$88

    2039:CMP #$88

    203B:BNE $2034       //这里是可能要变的,反正是跳转到 LDA $8000那里的地址

    203D:LDA #$F0

    203F:STA $8000

 

    2042:CPX #$07         //寄存器X的内容为07 吗,如果是,那就说明全部修改完了,转结束

    2044:BCS $2050

    2046:INX             //没有,那么,寄存器X的内容加1

    2047:INC $40        //地址40的内容加1,为写入下一个地址做准备

    2049:BNE $204D

    204B:INC $41

    204D:JMP $2020       //继续开始修改闪存

 

    2050:CLI             //程序结束

    2051:PLA

    2052:STA $0D

    2054:PLA

    2055:STA $0A

    2057:PLA

    2058:STA $00

    205A:RTS

  然后我们  G 2000

  再 D 4000 0E,发现已经修改成功,如图2:

  这里要提醒大家的是,在运行 修改闪存代码前,请将要修改的数据压入堆栈,然后运行完 修改闪存代码后

把压入堆栈的数据弹出,而且必须采用 后变址Y间接寻址方式,将数据写入 闪存地址,这里不支持 直接X变址 和 直接Y变址

但还支持 直接寻址,不过我们一般就是用 后变址Y间接寻址 方式

 

  前面的程序比较的简单,因为闪存地址的内容已经是 FF,所以我们不需要擦除闪存,不过下面我们要修改一段内容不为 FF 的闪存地址的

内容为 00 01 02 03 04 05 06 07,那么我们应该怎么做,请看我们分析:

  假如我们要修改 图 2 的地址4018-401F 的内容为 00 01 02 03 04 05 06 07

  由于地址 4018-401F 的内容不为 FF,所以我们要先擦除 该段地址所处的闪存块,很明显,处与 01 闪存块,那么我们就需要先擦除

地址 4000-47FF 的内容全部为 FF,那么就出现一个问题,我们这样做,势必会破坏其他地址的内容啊?

  所以我们需要先保护地址4000-47FF的内容,在 NC1020中,我们可以这样做:

 

  1.先把 地址 4000-47FF的内容 发送到 地址 3000-37FF

  2.把 00 01 02 03 04 05 06 07 发送到地址  3018-301F,注意,这里是3018-301F

  3.擦除 地址 4000-47FF

  4.把地址 3000-37FF 的内容 送地址 4000-47FF

  5.修改完毕,OK!

 

  由于上面有大量的数据传送程序,我们先来编写一个数据传输的子程序,可以实现任意地址数据之间的传输,这个子程序也被广泛

用于我的 XASM,NCTOOLS等DEBUG工具中.

  我这里是这样规定的:

  地址 40 41     源开始的地址

  地址 42 43     源结束地址

  地址 44 45     目标开始地址

  地址 46        源页码,若是 RAM,页码为 FF

  地址 47        目标页码,若是 RAM,页码为 FF

 

  A 2000

  2000:SEI               //这里设置中断标志,保护地址 0D 0A 00的内容

  2001:LDA $00

  2003:PHA

  2004:LDA $0A

  2006:PHA

  2007:LDA $0D

  2009:PHA

  200A:LDA $0A        //保证地址OA 最高位为 0

  200C:AND #$7F

  200E:STA $0A

 

  2010:LDY #$00       //寄存器 Y的内容为00,因为后面要用到的 后变址Y间接寻址 要求 (Y)=00

 

  2012:LDA $46       //这里 切换到 源页码

  2014:STA $00

  2016:LDA ($40),Y     //读取源页码的相应地址数据到 寄存器 A

  2018:PHA            //寄存器A的内容压入堆栈,准备写入 目标页码的闪存

 

  2019:LDA $47          //目标页码 数是放在地址47,这里如果地址47的内容 大于  10,那说明目标地址所在区域为 RAM

  201B:CMP #$10           那么就不需要运行 修改闪存 的代码

  201D:BCS $2048        //若页码数 >10,那么转地址 2048,可以直接把数据写入目标地址

  201F:STA $00          //那么说明目标地址处于闪存 或者 00页码

  2021:CMP #$00         //如果是 00 页码,由于地址 4000-7FFF也是 RAM,所以也可以直接写入

  2023:BEQ $2048    

  2025:LDA #$AA        //这里就是  写闪存的 代码,不能变

  2027:STA $5555

  202A:LDA #$55

  202C:STA $AAAA

  202F:LDA #$A0

  2031:STA $5555

 

  2034:PLA             //把压入堆栈的数据出栈,写入 目标闪存

  2035:STA ($44),Y

 

  2037:LDA $8000       //检测 是否已经 修改 完毕,和前面的一样

  203A:AND #$88

  203C:CMP #$88

  203E:BNE $2037      

  2040:LDA #$F0

  2042:STA $8000

  2045:JMP $204B        //跳过下面的两行代码

 

  2048:PLA               //这里当目标地址 是RAM,直接把数据写入

  2049:STA ($44),Y

 

  204B:LDA $40           //把地址40 41的内容和地址 42 43的数据比较,如果相同,说明数据全部发送完毕

  204D:CMP $42

  204F:BNE $2062

  2051:LDA $41

  2053:CMP $43

  2055:BNE $2062

 

  2057:CLI             //如果地址 40 41的内容和地址 42 43的内容相同,程序结束

  2058:PLA

  2059:STA $0D

  205B:PLA

  205C:STA $0A

  205E:PLA

  205F:STA $00

  2061:RTS

 

  2062:INC $40             //地址40, 44的内容加1,为读取和写入 下一字节做 准备

  2064:BNE $2069

  2066:INC $41

  2068:INC $44

  206A:BNE $206F

  206C:INC $45

  206E:JMP $2012          //继续转地址2012

 

  有了前面的基础,我想上面的程序大家应该可以看懂吧!

  在前面的擦除闪存 教程中,已经介绍了擦除任意连续闪存块的子程序,现在我们派上用场了,程序如下:

 

  2100:SEI

 

  2101:LDA $00

  2103:PHA

  2104:LDA $0A

  2106:PHA

  2107:LDA $0D

  2109:PHA

  210A:LDA $0A

  210C:AND #$7F

  210E:STA $0A

 

  2110:LDA $F4      //这里读取地址F4的内容作为页码,在调用这个子程序前,要先把页码送地址F4

  2112:STA $00

 

  2114:LDA #$F0    //下面的代码就是擦除闪存的代码,是不能变的,大家也别问为什么是这样的代码,照抄就是!!!

  2116:STA $8000

  2119:LDA #$AA

  211B:STA $5555

  211E:LDA #$55

  2120:STA $AAAA

  2123:LDA #$80

  2125:STA $5555

  2128:LDA #$AA

  212A:STA $5555

  212D:LDA #$55

  212F:STA $AAAA

 

  2132:LDY #$00       //寄存器Y的内容 = 0

  2134:LDA #$30       //地址 F0为块头地址低8位, F1为块头地址高8位,然后把立即数30送块头地址

  2136:STA ($F0),Y

 

  2138:LDA $8000    //这段代码是固定的,大家照抄!!

  213B:AND #$88

  213D:CMP #$88

  213F:BNE $2138    //注意,这里是变化的,因为代码开始执行地址是不同的,不要这个也照抄,那就完了!!反正是跳转到 LDA $8000 那个地址

  2141:LDA #$F0

  2143:STA $8000

 

  2146:LDA $F1     //由于是擦除连续的闪存块,所以这里要检查是不是已经全部擦除完毕,方法是把地址F1的内容和地址F3比较

  2148:CMP $F3       如果相同,则说明已经擦除完,转地址2152,准备结束程序

  214A:BEQ $2154

  214C:CLC         //如不同, 地址 F1的内容加 8,请想想为什么是加 8

  214D:ADC #$08

  214F:STA $F1

  2151:JMP $2114   //继续擦除下一闪存块

 

  2154:CLI           //清除中断标志,恢复被保护的地址内容,程序结束

  2155:PLA

  2156:STA $0D

  2158:PLA

  2159:STA $0A

  215B:PLA

  215C:STA $00

  215E:RTS

 

  现在我们可以很容易的实现修改闪存了,下面我们就实现 修改 0E 页码 的4018-401F 的内容为 00 01 02 03 04 05 06 07

  A 220B

  220B:LDA #$00

  220D:STA $40

  220F:LDA #$40

  2211:STA $41

 

  2213:LDA #$FF

  2215:STA $42

  2217:LDA #$47

  2219:STA $43

 

  221B:LDA #$00

  221D:STA $44

  221F:LDA #$30

  2221:STA $45

 

  2223:LDA #$0E

  2225:STA $46

  2227:LDA #$FF

  2229:STA $47

 

  222B:JSR $2000        //实现了将0E页码地址4000-47FF 送地址3000-37FF

 

  222E:LDA #$00

  2230:STA $F0

  2232:LDA #$40

  2234:STA $F1

  2236:LDA #$00

  2238:STA $F2

  223A:LDA #$40

  223C:STA $F3

  223E:LDA #$0E

  2240:STA $F4

 

  2242:JSR $2100         //实现 擦除 0E 页码 4000-47FF

 

  2245:LDX #$00         //实现将 0 1 2 3 4 5 6 7 写入地址 3018-301F

  2247:TXA

  2248:STA $3018,X

  224B:INX

  224D:CPX #$08

  224F:BNE $2247

 

  2251:LDA #$00

  2252:STA $40

  2254:LDA #$30

  2256:STA $41

  2258:LDA #$FF

  225A:STA $42

  225C:LDA #$37

  225E:STA $43

  2260:LDA #$00

  2262:STA $44

  2264:LDA #$40

  2266:STA $45

  2268:LDA #$FF

  226A:STA $46

  226C:LDA #$0E

  226E:STA $47

 

  2270:JSR $2000        //实现将地址 3000-37FF 送0E 页码 4000-47FF

  2273:RTS              //结束