//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 ;结束