//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里测试通过