//NC1020闪存的分布与切换

  这里我们先讨论NC1020闪存的基本情况.

1.闪存的基本参数

  闪存的类型: NOR FLASH

  闪存的大小: 512KB

  闪存块大小: 2K

 

2.NC1020闪存的分布

 由于6502最大寻址空间是64K,但NC1020有512K的闪存区域,那么是这样分布的呢?

很显然,NC1020采用了分页码的方法,可以这样说,一个班只能容纳64个人,现在要招收512个人

显然,一个班是不够的,要有16个班,分别为00班,01 班,02 班......0F 班.

  NC1020的闪存也是这样分配的,分为 0F 个页码,每个页码32K

  顺便说说NC1020存储器的分布:

  ①RAM的分布情况

    NC1020RAM的大小:24K

    地址0000-地址3FFFF  :  16K

    00页码的 4000-5FFF(6000-7FFF)   :  8K

    这里要说明的是,00页码的4000-5FFF的内容是会随着地址6000-7FFF的内容的改变而改变

例如 在NCTOOLS下  E C 6000 00, 输入30, 然后 D 4000 00,发现也变为30了,不过这在NC1020模拟器上是看不出来的.

因为模拟器和实际机型不一样.

  ②闪存的分布

    01-0F 页码的 4000-BFFF                总计:       32 * 15 = 480K

    00 页码的8000-BFFF                    总计:       32 / 2 = 16K

    当地址0A的内容=00时的 地址C000-DFFF  总计:       16K

  所以总的 闪存容量 = 480 + 16 + 16 = 512K

 

3.闪存的切换

  和CC800,PC1000等一样,是通过地址00来切换的.

  切换闪存有2种情况:

  ●当前代码处于 随机存储器RAM范围中

    这种情况,切换到不同的页码比较简单,请看下面的例子:

  例:  当前处于RAM区域,现在要读取03页码的4000-40FF的内容送到地址3000-3FFF

  分析:要读取03页码的4000-40FF的数据,我们必须要先切换页码到03,这样才能读取03页码的数据

  程序如下:

  说明: 在切换闪存前,保护原来的页码和几个重要的地址,还要保证地址0A的内容为负数,即地址0A的最高位为0

为什么要这样做,对于该例,完全可以不这样做,因为代码本身在RAM区域,不需要保护当前页码,但对于代码在闪存

的那种情况,就一定要这样做了.因为我们在执行完该段程序返回后,要继续执行原来页码的程序,但由于我们切换到

了另一个页码,如果不在程序返回前,切换入原来的页码,程序就无法执行.

   我举个形象点的例子:现在有16间房子,某人住在第3间房子,他每天的工作是打扫第3间房子的卫生,但打扫卫生的工具

却放在04间房子,所以他打扫卫生的步骤是这样的:

  ①先进入第4间房子,拿卫生工具       ;相当于程序中的切换页码

  ②回到原来自己的房子              ;返回原来的页码

  ③继续工作                       ;继续执行原来页码的程序

 

  所以大家可以明白,如果某人到第4间房间拿了工具,却不返回原来的房间,后果是什么?

 

  2000:LDA $00              ;地址00的内容送入堆栈,保护地址00的内容

  2002:PHA                 

  2003:LDA $0A              ;地址0A的内容送入堆栈,保护地址0A的内容

  2005:PHA

  2006:LDA $0D              ;地址0D的内容送入堆栈,保护地址0D的内容

  2008:PHA

  2009:LDA $0A              ;地址0A的内容送寄存器A

  200B:AND #$7F             ;寄存器A的值和7F进行逻辑与运算,这里功能是将地址0A的最高位置0

  200D:STA $0A       

 

  200F:LDA #$03            ;将页码03送寄存器A

  2011:STA $00             ;03送地址00,这里就切换到了03页码

 

  2013:LDX #$00           ;开始数据的传输

  2015:LDA $4000,X

  2018:STA $3000,X

  201B:INX

  201C:BNE $2015

 

  201E:PLA                 ;数据传输完毕,把最开始压入堆栈的内容弹出,这里注意弹出的顺序

  201F:STA $0D

  2021:PLA

  2022:STA $0A

  2024:PLA

  2025:STA $00

  2027:RTS                ;先前保护的地址内容已经完全恢复,程序结束返回

 

●当前代码处于 闪存区域内

  这种情况比上面的麻烦些,切换闪存的程序不可以在闪存区域执行,因为本身程序已经处于某页码的闪存区域

又怎么可以切换到另外的页码呢?就好象你已经处于第3间房子,你不出去,在第3间房子里怎么可以到达第4间房子呢

大家可能注意到 "出去"这两个字,不错,我们要先出去,这里我们可以想切换闪存的程序发送到 RAM里,然后程序调用

该RAM里的程序即可实现页码的切换.

 

例: 处于闪存区域的页码的切换,当前页码为0F页码,现在要读取03页码的4000-40FF的内容送到地址3000-3FFF

  送入RAM的切换闪存的代码从地址4000开始

  但实际执行切换闪存,读取数据的主程序是从地址4030开始

  在写下面的代码前,要确定发送到的RAM的首地址,否则就无法写代码!!

  这里我们确定将代码送地址1700开始的RAM区域

  4000:LDA $00              ;地址00的内容送入堆栈,保护地址00的内容

  4002:PHA                 

  4003:LDA $0A              ;地址0A的内容送入堆栈,保护地址0A的内容

  4005:PHA

  4006:LDA $0D              ;地址0D的内容送入堆栈,保护地址0D的内容

  4008:PHA

  4009:LDA $0A              ;地址0A的内容送寄存器A

  400B:AND #$7F             ;寄存器A的值和7F进行逻辑与运算,这里功能是将地址0A的最高位置0

  400D:STA $0A       

 

  400F:LDA #$03            ;将页码03送寄存器A

  4011:STA $00             ;03送地址00,这里就切换到了03页码

 

  4013:LDX #$00            ;开始数据的传输

  4015:LDA $4000,X

  4018:STA $3000,X

  401B:INX

  401C:BNE $1715        ;注意,这里不是BNE $4015,因为代码是从RAM地址1700开始执行的,所以是 BNE $1715

 

  401E:PLA                 ;数据传输完毕,把最开始压入堆栈的内容弹出,这里注意弹出的顺序

  401F:STA $0D

  4021:PLA

  4022:STA $0A

  4024:PLA

  4025:STA $00

  4027:RTS                ;先前保护的地址内容已经完全恢复,程序结束返回

 

 然后就是主程序,这里从地址4030开始吧

 在写主程序前,要先计算出发送到RAM区域的程序代码的字节数,这里是 十六进制28个字节,即十进制的40个字节

4030:LDX #$00         ;将地址4000-4027的数据送地址1700-1727

4032:LDA $4000,X

4035:STA $1700,X

4038:INX

4039:CPX #$28

403B:BNE $4032

 

403D:JSR $1700    ;执行地址1700开始的程序

4040:RTS          ;结束