对于根据图1的体系结构中出现的死锁问题的解决方法就是,把执行程序操作的代码部分下载到RAM 107中,然后分支到RAM 107中这个程序例程的第一指令,自RAM 107内部执行程序操作,并且最后,在快闪存储器102的编程之后,再次跳转到快闪存储器102中的代码。这在图3中示出了。
这种软件手段的主要限制就在于:正确管理代码和地址的难度。如果代码是用高级语言(例如,用C语言)编写的,那么软件工程师就必须处理大量的指针使用以及经由指针的函数调用,以便执行不是来自快闪存储器102内部而是来自RAM 107内的程序例程。
此外,图4中所示的程序例程正在使用存储在快闪存储器地址空间中的一些变量,这是常见的情况,借此编译器并不知道将从哪里执行例程。一旦在执行程序例程期间调用这类变量,就会发生异常错误,这是因为快闪存储器102在读取模式下是不可访问的。
最后,为了写入拷贝例程,所述拷贝例程应把程序例程从快闪存储器102拷贝到RAM 107,软件工程师必须知道关于程序例程的信息,比如像起始地址、结束地址和将要转送的代码部分的大小。但是,当软件进行写入时这些都是不可用的。所以,唯一的可能性就是编译完整代码的初稿(first draft)版本,然后从编译的代码的汇编版本中提取所需要的信息,重写代码并且重新编译它。对代码的更进一步修改将改变指令的相对寻址,并且将再次需要这类迭代近似的方法。
下列是如何管理例程转储的示例,所述例程须通过高级语言手段从RAM 107执行而不是从快闪存储器102执行。存储器拷贝(memcopy)命令将拷贝在RAM 107中的例程,并且通过适当的指针赋值,将可以调用将从这个RAM地址起执行的例程。令人遗憾的是,如果变量调用将试图访问快闪存储器地址空间,那么这样并不会避免错误的发生。存储器拷贝命令需要将要拷贝的例程的起始地址和大小。所以,必须完成初稿编译以便获取例程的起始地址和大小,这是因为这些仅在编译之后才变得可用。现在,能够把正确的信息插入在代码中,并再次编译它。代码中的每次修改将会改变编译的代码中的指令的地址,所以到目前为止必须再次执行所描述的程序。
一种缺乏用户友好性但却更准确的手段就是直接用汇编语言来编写代码部分。为代替通过像存储器拷贝这类的库命令以及经由指针的函数调用来进行管理,而将下列序列分成两个例程:
(1)拷贝在RAM中的闪存程序例程;
(2)调用将从RAM执行的闪存程序例程;
(3)跳回到快闪存储器;
为了实现上述序列,在main C语言代码中,调用下列汇编程序:
(a)汇编例程:
(a.1)将代码从快闪存储器拷贝到RAM;
(a.2)将处理器的程序计数器强行设为RAM的第一指令地址,其中已经在所述第一指令地址上拷贝了所述例程。
现在,从RAM执行闪存程序例程。
(b)从RAM中运行闪存程序例程:
(b.1)对快闪存储器进行编程;
(b.2)调用其它的汇编例程来将处理器的程序计数器强行设为快闪存储器地址空间中的其余代码的第一指令地址。
从现在开始执行将从快闪存储器继续下去。
照此,从RAM 107执行的例程将首先对快闪存储器102进行编程,然后调用在快闪存储器地址空间中强行设置程序计数器的汇编例程,然后继续执行代码,不过是从快闪存储器102继续执行。
与上述解决方案相比,这种手段的优点在于指令地址的直接控制,编译器并未涉及到拷贝以及跳至RAM 107和从RAM 107那里跳转,并且在程序操作期间几乎没有错误尝试访问快闪存储器102的可能性。
此外,在这种情况下,为了知道在RAM 107中跳转到哪里以及跳回到快闪存储器102中的哪里,在每次修改代码时都需要初稿编译。
最后,为了防止在从RAM 107执行代码期间对快闪存储器102进行访问的错误尝试,可靠的方式就是不仅把程序例程拷贝到RAM 107中,而且还把其余的代码拷贝到RAM 107中。这种手段的缺点在于高的RAM区域耗费。
下面给出了如何管理例程的转储的示例,所述例程必须通过低级语言手段从RAM 107执行所述例程而不是从快闪存储器102执行它。
(a)C语言主程序将调用第一汇编例程。
(b)这将把感兴趣的快闪存储器内容块拷贝到RAM 107中,然后将把程序计数器强行设为目前拷贝到RAM 107中的程序的第一指令。
(c)从现在开始,将从RAM 107执行代码,并且可以对快闪存储器102进行编程。
(d)当程序操作结束时,将仅仅为把程序计数器强行设为C语言代码的下一条有效指令而调用第二汇编例程,但是这次是在目前再次可用的快闪存储器102中进行的。如前所述,仅在初稿编译之后,关于跳转到RAM 107和快闪存储器102中的哪里的全部信息都才变为可用的,并且必须在每次代码修改时受到检查。
如下所述的体系结构的目的是,为软件开发提供这样一种装置,它允许在不从另一的存储器中进行编程而是简单地将其作为RAM来接口并且仅仅等待所需的编程时间的情况下,对非易失性指令存储器进行编程。
将使用下列定义。一种接口允许通过适当的装入命令来把将要编程的数据写入数据锁存器的嵌入式寄存器中。这将称为加载操作。使用适当的程序命令,将启动程序本身。这两种操作都需要把快闪存储器设置成写入模式。在把快闪存储器设置成写入模式之后,将无法从快闪存储器内部执行这两条命令。
本发明不局限于任何特定种类的嵌入式快闪存储器,而是可以采用任何非易失性存储器。
该体系结构包括如下的接口,所述接口将在加载操作期间通过一种直接存储器访问(DMA)转送要在RAM中而非快闪存储器的嵌入式寄存器中编程的数据,记录下必须在快闪存储器中里写入这个数据的地址,而不必将快闪存储器设置成写入模式,因此仍然保持快闪存储器是可供读取指令使用的。一旦已经从微处理器发送出了将要编程的所有数据,下一条命令就将是用于快闪存储器的实际编程的。在这种情况下,所述接口将向微处理器发回一个等待信号,以便后者将不会尝试从快闪存储器中取指令。在把快闪存储器设置成写入模式之后,所述接口将为实际的加载操作启动从RAM到快闪存储器中的嵌入式寄存器的转送。在加载操作结尾之时,所述接口将向快闪存储器发送程序命令,并且在程序操作结尾之时,所述接口将把等待信号从微处理器总线上删除。
从处理器的角度来看,已经执行了简单的写操作。由于快闪存储器的程序时间而导致所述写操作比对RAM的写操作持续时间更长,但是不再有拷贝/转储/编程/跳转操作所需要的特殊的费时的技巧(trick)。
以下描述了图5a和5b的流程图中所示的操作以及由接口605所执行的图6a和6b的框图。在图5a和5b的流程图中,用点划线隔开了六个不同部分。
第1部分:微处理器603正在执行加载请求指令load/prog指令,并且正在快闪控制器寄存器shadow fctr_reg 608中写入合适的值。此后,接口605等待将要加载到快闪存储器602中的数据DATA。
第2部分:微处理器603将快闪存储器602选择为写入模式,并且在总线604上发送数据DATA和地址ADDR。接口605将把写入模式屏蔽到快闪存储器602,并且将捕获数据DATA和地址ADDR。所述接口605还将生成所述微处理器603的等待信号wait,并且将在RAM 601中存储数据DATA。并且所述接口605将删除所述微处理器603的等待信号wait。快闪存储器602仍未处于写入模式下,并且微处理器603能够仍然提取(例如)用于加载数据DATA的指令。
第3部分:现在,微处理器603正在执行程序请求指令load/prog指令。它正在快闪控制器寄存器shadow fctr_reg 608写入一个合适的值。在那之后,接口605将再次生成微处理器603的等待信号wait。当微处理器603处于等待状态下时,接口605将把快闪存储器602设置成写入模式。接口605将从RAM 601中读取数据DATA。
第4部分:接口605将在快闪存储器数据锁存器中加载数据DATA。
第5部分:在已经将最后的数据DATA从RAM 601加载到快闪存储器602中之后,接口605将为快闪存储器602生成程序命令,并且将轮询来自于快闪存储器602的就绪信号,所述信号表明快闪存储器602的编程已经结束。
第6部分:当快闪存储器602生成就绪信号时,接口605将再次把快闪存储器602设置成读取模式,并且将删除微处理器603的等待信号wait。
下面,将描述对于RAM 601和快闪存储器602这二者的地址管理。
将要解决的主要问题就是:
1.临时在RAM 601中把数据DATA存储在哪里。
2.保持RAM地址以便事后能够从RAM 601中取回数据DATA。
3.保持关于要对在快闪存储器602中哪里的DATA进行编程的信息。
第一个问题是通过接口605中嵌入的直接存储器访问(DMA)方法来管理的,而第二个和第三个问题都是通过接口605中的嵌入式算法来解决的。
为了管理直接存储器访问(DMA),接口605嵌入了DMA引擎610。一般而言,如果DMA控制器和微处理器共享到存储器的信号线,那么必定存在一种机制来仲裁哪个装置将有权访问存储器。在这里所描述的本发明的实施例中,接口605只有在通过通用的等待信号wait将微处理器603设为等待状态之后才会访问存储器601和602。在系统总线上,信号wait总是有效的,所以不需要其它的仲裁特征。在另一方面,微处理器603必须向DMA引擎610传输RAM 601中的起始地址。利用这个信息,接口605能够将微处理器603所发送的数据DATA重定向到RAM 601,存储RAM起始地址,并且记录下还将发送的字数量。此外,不存在把RAM 601中的坏数据写入错误地方的风险。DMA引擎610的目的在于选择适当的装置,RAM 601或快闪存储器602,把数据发送到这个装置或从这个装置中读取数据,等待来自该装置的就绪信息,并且向接口605中的主状态机617传输就绪信息以作为确认通知。
在图6a、6b、7和8中,展示了接口605体系结构的实施方式。在图6a和6b中所示的框图中,接口605、微处理器603和RAM 601与控制信号wait、nREAD/WRITE、数据信号DATA和地址信号ADDR一起都连接于系统总线604。此外接口605需要访问快闪存储器602的的片选(chip select)-称为SEL_FLASH,和需要访问RAM601的片选(chip select)-称为SEL_RAM。接口605主要以主状态机(MSM)617、DMA引擎610和计数器606为基础。主状态机606检查来自微处理器603的请求,并且为地址寄存器和数据寄存器控制输入。计数器606记录下在RAM 601中写入的字数量,以便为快闪存储器加载而取回它们。
所述寄存器是:
快闪存储器起始地址寄存器611存储起始地址Flash_start_addr,其表明在哪里对快闪存储器602进行编程的。
RAM起始地址(RAM_start_addr)寄存器612存储起始地址RAM_start_addr,其表明要数据DATA临时保存在把RAM 601中的哪里。在发送数据DATA之前必须将这个起始地址从微处理器603发送到接口605。
在把数据DATA发送到RAM 601或快闪存储器602之前,数据缓冲器613在每个加载周期内存储数据DATA。
最后计数寄存器607存储所执行的RAM写入步骤的最大数。这个寄存器用于经由比较器616来检查连续的快闪存储器加载的结尾。
快闪当前地址寄存器614存储由DMA引擎610当前用来访问快闪存储器602的地址。这就是:
-供第一次加载的快闪存储器起始地址Flash_start_addr;和
-在连续的加载周期期间的(快闪存储器起始地址Flash_start_addr)+(当前计数值);
所述RAM当前地址寄存器615存储由DMA引擎610当前用来RAM访问RAM 601的地址RAM_current_addr。这就是:
-第一次写或读操作的RAM起始地址RAM_start_addr;和
-在连续的写或读操作期间的(RAM起始地址RAM_start_addr)+(当前计数值);
影子快闪控制寄存器shadow_fctr_reg 608存储由微处理器603所发送的和接口605所高速缓存的加载命令和程序命令。
实际快闪控制寄存器Real_fctr_reg 609存储将由接口605发送到快闪存储器602的加载命令和程序命令。
图7示出了主状态机(MSM)617的行为表示,即MSM所执行的操作以及它与直接存储器访问状态机(DMA SM)610的协同作业。
状态0:MSM是空闲的。
状态1:MSM已经检测到来自于微处理器(在下文中称为μP)的加载请求。μP 603已经把指定的加载指令写入到接口605的影子快闪控制寄存器shadow_fctr_reg中。
a)MSM将设置使能信号en_data_in和信号update_addr和data_in_sel,以允许从数据总线604到RAM_start_addr寄存器和RAM_current_addr的转送。现在,μP必须向MSM发送将用作为缓冲区的RAM空间的起始地址。MSM将从数据总线上捕获这个值,并将其存储在寄存器RAM_start_addr和RAM_current_addr中。此外,MSM将重置用于增量地址计算的计数器606。
状态2:现在μP必须向MSM发送将用作为缓冲区的RAM空间的起始地址。MSM将从数据总线上捕获这个值,并将其存储在RAM起始地址(RAM_start_addr)寄存器中。
状态3:MSM检测到μP已将快闪存储器602选为写入模式(该检测是通过在总线系统级上检查有效的信号SEL_FLASH和nREAD/WRITE来进行的,参见图6b)。此外,μP已经将DATA和ADDR发送到总线上。
a)MSM将生成μP的等待信号WAIT。
b)MSM将设置使能信号en_addr_in和en_data_in,并且将从DATA和ADDR系统总线上捕获。这些都是将要存储在DATA_buffer和FLASH_start_addr寄存器中的值。
状态4:现在MSM必须将所捕获的数据重写到RAM 601中。
a)按照下式来计算RAM的地址:
寄存器RAM_current_addr的值+计数器的值。
对于第一个循环而言,RAM_current_addr=RAM_start_addr,而计数器的值=0(参见状态1.a)
b)现在MSM将利用地址RAM_current_addr缓冲器和数据DATA缓冲器向DMA SM发送ram_write请求。
状态5:MSM等待来自于DMA SM的、RAM写操作已被执行的确认。
状态6:当MSM已经检测到来自于DMA SM的确认时,可以删除μP的信号WAIT。注意,快闪存储器不是写入模式,并且仍然可以取指令以供加载DATA。
现在,μP将继续将DATA和ADDR发送到系统总线上,就仿佛它实际把将要编程的DATA加载到快闪存储器中一样。MSM将在状态4至6之间循环,使DATA脱离RAM,并且将加载操作屏蔽到快闪存储器,这将保持在读取模式下。在μP已经发送将要加载和执行或所期望的诸如此类的其它操作的所有数据之后,它将向接口的shadow_fctr_reg发送最后的程序指令Prog指令。
状态7:MSM已经检测到来自于μP的Prog指令:
a)MSM将把μP置于等待状态下,因为此后快闪存储器在读取模式下将不是可用的,从而将不会向μP递送指令。
b)MSM将在Last_count寄存器中存储Flash_current_addr。
c)MSM将分别把(在状态3.b下存储的)Flash_start_addr和RAM_start_addr转送到Flash_current_addr和RAM_current_addr。此外,它将重置计数器。
d)MSM将向DMA发送RAM_read请求,其中将把RAM_current_addr作为地址,并且将等待DMA确认DMA Ack。
状态8:MSM现在将循环直到来自于DMA SM的DMA Ack将被设置为止(RAM读操作已被执行)。所述接口将把DATA加载到快闪存储器数据锁存器中。
状态9:MSM现在将利用由RAM取回的DATA和Flash_current_addr中的地址来执行对快闪存储器数据锁存器的实际加载。这将由DMA SM通过MSM的flash_load请求来执行。此外,MSM将比较Flash_current_addr与(在状态7.b下存储的)Last_count值,以便检测它是否是最后将要加载的DATA。
如果Flash_current_addr等于Last_count,则MSM将转到状态11。
b)如果Flash_current_addr不同于Last_count,则MSM将转到状态10。
状态10:MSM现在将使计数器加1,并且将更新寄存器:
a)Flash_current_addr=Flash_current_addr+计数值;
b)RAM_current_addr=RAM_current_addr+计数值;
c)MSM将向DMA SM发送ram_read请求,其中把RAM_current_addr作为地址,并且将再次转到状态8以便等待DMA确认。
状态11:如果Flash_current_addr=Last_count,则所有数据都已被加载到快闪存储器中,并且现在是对它进行编程的时候,向快闪存储器发送实际的程序命令。
状态12:现在,取决于快闪存储器的体系结构(这与快闪存储器模块无关),MSM要么将循环依据为快闪存储器规定的程序时间的固定时钟周期数,要么将循环直到在程序时间结尾之时、潜在的就绪信号出现自快闪存储器中(如果这个信号存在的话,那么它能够直达DMA SM并且MSM将照常等待来自于DMA SM的DMA确认)。
状态13:已经接收了来自于DMA SM的DMA Ack或者已经到达了程序时间时,MSM现在能够使快闪存储器返回到读取模式(就加载和编程而言,这就通过把适当的位写入到Real_fctr_reg中来完成的)。MSM现在将删除μP的信号wait,并且将成为空闲状态(状态0)。
图8目前示出了根据本发明的嵌入式直接存储器访问(DMA)状态机610的行为。DMA SM功能的更详细说明如下。
状态0:DMA SM处于空闲状态。
状态1:DMA SM已经检测到来自于MSM的RAM_write请求。
a)DMA SM重置由MSM所使用的信号dma_ack以作为确认。
b)DMA SM设置信号addr_out_sel以便向地址系统总线发送RAM_current_addr的值。
c)DMA SM现在可以设置信号enable_addr_out和enable_data_out,以便向地址系统总线和数据系统总线发送RAM_current_addr的值和DATA_BUFFER寄存器的值。
d)取决于RAM结构,写操作能够采取固定的时钟周期数或者由从RAM那里返回的就绪信号来决定。在任何情况下,在写周期结尾之时,DMA SM都将转到状态4。
状态2:DMA SM已经检测到来自于MSM的RAM_read请求。
a)DMA SM重置MSM所使用的信号dma_ack以作为确认。
b)DMA SM设置信号addr_out_sel,以便向地址系统总线发送RAM_current_addr的值。
c)DMA SM现在能够设置信号enable_addr_out,以便向地址系统总线发送RAM_current_addr的值。
d)取决于RAM体系结构,读操作能够采取固定时钟周期数或者由从RAM那里返回的就绪信号来决定。在任何情况下,DMA SM都将在读周期结尾之时转到状态4。
状态3:DMA SM已经检测到来自于MSM的Flash_load请求。
a)DMA SM重置由MSM所使用的信号dma_ack以作为确认。
b)DMA SM设置信号addr_out_sel,以便向地址系统总线发送Flash_current_addr的值。
c)DMA SM现在可以设置信号enable_addr_out和enable_data_out,以便向地址系统总线和数据系统总线发送Flash_current_addr的值和DATA_BUFFER寄存器的值。
d)取决于快闪存储器体系结构,加载操作能够采取固定的时钟周期数或者由从快闪存储器那里返回的就绪信号来决定。在任何情况下,在加载周期结尾之时,DMA SM将转到状态4。
状态4:当存储操作结束时,DMA SM将为MSM把信号dma_ack设置为1,并且返回到空闲状态(状态0)。
这里结束了对主状态机(MSM)和直接存储器访问状态机(DMA SM)两者的操作的说明。
所描述的体系结构具有几个优点。缩减的软件开发时间,并且利用可重用的应用代码开发了稳健的系统,这都集中在应用上而非对硬件的限制上。
根据本发明的方法及其体系结构上的实现方式最适合用于所有其中微处理器把嵌入式快闪存储器用作为指令存储器的应用。