//NC1020闪存的擦除

    NC1020闪存的擦除比CC800,PC1000的更复杂些,闪存的擦除包括 内核区闪存的擦除 非内核区闪存的擦除.

先介绍非内核区闪存的擦除.内核区闪存的擦除将在介绍完了NC1020内核保护原理后才能讲解!

    NC1020的闪存是以 2K 为一个闪存块的,分别如下:

        4000-47FF        1

        4800-4FFF        2

        5000-57FF        3

        5800-5FFF        4

        .

        B000-B7FF       15

        B800-BFFF       16

    可见,一个页码的闪存有16块,闪存的擦除是以块为单位的,也就是说,最小可擦除的闪存大小是2K,不能想擦除哪个字节就擦除哪个字节.

我们先要会判断 哪块闪存 已经被擦除了,其实很简单,若该块地址的内容全为 FF,则说明该块闪存已经被擦除了.

    例 擦除某段页码的4000-47FF

    这里我们进入NCTOOLS,先找一个没有被系统利用的页码,方法是 D 4000 03,然后按 K 往下翻页码

当看到 地址4000后的内容全部为 FF 时,那就说明可以利用这块闪存做擦除闪存的实验了.

这里我们发现 06 页码的 4000后内容全为 FF,如图:

  为了证明我们成功的擦除了该块闪存,我们往里面写些数据,输入 E C 4000 06,输入 01 02 03 04 05 06 07 08,如图:

    现在我们开始编写程序,需要注意的是,擦除闪存的程序必须在RAM执行,而不能在闪存里被执行

  先说明擦除闪存的步骤:

  1.设置中断标志  即 SEI

  2.保护地址00 0A 0D的内容,地址0A的内容的最高位为0

  3.把擦除的闪存的页码送地址00,以切换到擦除的闪存的页码

  4.开始 擦除闪存的代码

  5.把立即数 30 送擦除闪存的块头地址,例如 若是01闪存块,块头地址是 4000,若是02闪存块,块头地址4800

  6.恢复地址 00 0A 0D 的内容

  7.取消中断标志 即  CLI

 

  程序如下:

  2000:SEI

 

  2001:LDA $00

  2003:PHA

  2004:LDA $0A

  2006:PHA

  2007:LDA $0D

  2009:PHA

  200A:LDA $0A

  200C:AND #$7F

  200E:STA $0A

 

  2010:LDA #$06     //把擦除闪存块所在页码数送地址00,以切换到闪存块所在页码

  2012:STA $00

 

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

  2016:STA $8000

  2019:LDA #$AA

  201B:STA $5555

  201E:LDA #$55

  2020:STA $AAAA

  2023:LDA #$80

  2025:STA $5555

  2028:LDA #$AA

  202A:STA $5555

  202D:LDA #$55

  202F:STA $AAAA

 

  2032:LDA #$30     //这里是很关键的一步,把立即数30送要擦除的闪存块的块头地址 这里是第1块,所以是 4000,第2块就是4800,类推!

  2034:STA $4000

 

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

  203A:AND #$88

  203C:CMP #$88

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

  2040:LDA #$F0

  2042:STA $8000

 

  2045:CLI         //取消中断标志,也是必须的

  2046:PLA         //下面就是恢复被保护的地址的内容了

  2047:STA $0D

  2049:PLA

  204A:STA $0A

  204C:PLA

  204D:STA $00

  204F:RTS

 

   在NCTOOLS下, G 2000, 然后 D 4000 06,激动人心的事情发生了,我们已经成功擦除了06页码的4000-47FF了,如图:

  我写了个子程序,可以实现擦除任意连续的闪存块,希望能给大家点启发,入口参数是这样规定的

  地址 F0 F1,开始块头地址

  地址 F2 F3,结束块头块头地址

  地址 F4   ,页码数

 

 例如 擦除 06页码 的 4800-87FF

 那么  开始块头地址是   4800

       结束块头地址是   8000

入口参数就是 :

  F0: 00    F1: 48

  F2: 00    F3: 80

  F4: 06

 

  大家看程序,和上面的几乎是一样的,不同的地方为粗体

  2000:SEI

 

  2001:LDA $00

  2003:PHA

  2004:LDA $0A

  2006:PHA

  2007:LDA $0D

  2009:PHA

  200A:LDA $0A

  200C:AND #$7F

  200E:STA $0A

 

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

  2012:STA $00

 

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

  2016:STA $8000

  2019:LDA #$AA

  201B:STA $5555

  201E:LDA #$55

  2020:STA $AAAA

  2023:LDA #$80

  2025:STA $5555

  2028:LDA #$AA

  202A:STA $5555

  202D:LDA #$55

  202F:STA $AAAA

 

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

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

  2036:STA ($F0),Y

 

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

  203B:AND #$88

  203D:CMP #$88

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

  2041:LDA #$F0

  2043:STA $8000

 

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

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

  204A:BEQ $2054

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

  204D:ADC #$08

  204F:STA $F1

  2051:JMP $2014   //继续擦除下一闪存块

 

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

  2055:PLA

  2056:STA $0D

  2058:PLA

  2059:STA $0A

  205B:PLA

  205C:STA $00

  205E:RTS

 

  现在我们实验擦除一段连续的闪存块

  进入NCTOOLS, D 4000 03,按 K 翻页码,知道发现地址 4000-6FFF全部为 FF 的页码,这里我们假设是 0D 页码

  这里我们是擦除 地址 4000-6FFF

  那么我们从地址3000开始:

  3000:LDA #$00        //块头地址送F0 F1 F2 F3

  3002:STA $F0

  3004:LDA #$40

  3006:STA $F1

  3008:LDA #$00

  300A:STA $F2

  300C:LDA #$68

  300E:STA $F3

  3010:LDA #$0D       //页码送  F4

  3012:STA $F4

  3014:JSR $2000     //执行擦除闪存程序

  3017:RTS

注:以上程序均在NCTOOLS里测试通过