人工模拟降雨器中3074对FRAM访问以及可靠性加密
- UID
- 799481
|
人工模拟降雨器中3074对FRAM访问以及可靠性加密
我们在研发人工模拟降雨器的时候,选择了VRS51L3074。在它的内部,有一个8000多个字节的FRAM,这样将数据存储和单片机集成到了一起,那么我们在里说说如何访问FRAM,并且如何使用FRAM进行加密,能够保证系统可靠运行。同时防止我们的软件和硬件在被同行不正当解密的可能。在现在的竞争中,我们公司开发的一些产品不断被同行业解密,导致我们公司蒙受了一定的损失。当然,解密是一把双刃剑,同样促使我们不断完善我们自己的产品,将自己产品性能努力提升,同样对产品的设计业不断加强。在这款3074的单片机中,我们发现了3074的最重要的一个方面,那就是这个单片机的内部FRAM。
下面我们先看看对FRAM的访问。
当系统存储配置寄存器DEVMEMCFG中的EXTBUSEN和FRAMEN同时被置位的时候,对外部的数据存储空间中的8000H~9FFFH范围内的寻址将定位到片内的8KB的FRAM铁电存储器中。此时只要按照要求配置FRAMCFG1寄存器和FRAMCFG2寄存器就可以了。
1.FRAM正常模式读写操作
对FRAM的读写通过外部数据接口采用MOVX指令在累加器A与FRAM单元之间进行数据传送,寻址范围为8000h~9FFFh。以下为正常模式下访问FRAM的代码片断:
;---------读操作---------
;--FRAM初始化
ORL DEVMEMCFG, #C0h ;FRAM使能
MOV FRAMCFG1, #00h ;设置FRAM正常访问模式,FRAMCLK=SysClk/2
FRAMRDY:
MOV A, FRAMCFG1 ;--检测FRAM否空闲
ANL A, #80h ;若FREADIDLE=0则
JZ FRAMRDY ;等待,否则
FRAMREAD:
MOV DPTR, #8100h ;读FRAM存储器8100h单元
MOVX A,@DPTR
(…)
;---------写操作---------
;--FRAM初始化
ORL DEVMEMCFG, #C0h ;FRAM使能
MOV FRAMCFG1, #01h ;置位FRAMWEL
FRAMRDY:
MOV A, FRAMCFG1 ;--检测FRAM否空闲
ANL A, #80h ;若FREADIDLE=0则
JZ FRAMRDY ;等待,否则
MOV A, DATA ;将待写入数据送A
MOV DPTR, #8100h ;写8100h单元
MOVX @DPTR, A
(…)
2.FRAM猝发模式读/写
猝发模式适用于对FRAM连续单元进行读写的情况下,可加快对FRAM的访问速度,置位BURSTEN位时将启动FRAM猝发访问模式。
猝发模式写操作
猝发模式写操作利用了FRAM的双缓冲性能——允许处理器在当前写周期结束前向FRAM写入下一个数据。但注意需满足以下3个条件:
(1)必须是向FRAM存储器中地址连续递增的单元写入;
(2)下一条MOVX写指令必须在规定的系统周期内开始执行;
(3)一旦开始执行猝发写操作后,在退出猝发模式之前,不能再启动任何其它FRAM操作。
第(2)个条件表明编程时应合理安排程序代码,以确保下一条写指令在规定的时间内开始执行。下表列出了FRAM运行于不同速度时,MOVX写指令之间允许间隔的系统周期数。
如果未在规定的时间内写入下一个数据或对非连续单元执行猝发写操作会导致数据丢失,并且无任何标志或中断来表明这种状态。
例:猝发模式写操作
MOV DEVMEMCFG,#0C0h ;FRAM使能
(…)
MOV FRAMCFG1,#08h ;设置FRAM猝发模式
MOV R0,#0A0h ;初始化内部RAM指针
MOV R2,#100 ;准备执行100次写操作
MOV DPTR,#8000h ;DPTR指向写操作起始地址
BURSTWRITE: MOV A,@R0 ;3周期
MOVX @DPTR,A ;写FRAM单元
INC DPTR ;2周期
INC R0 ;2周期
DJNZ R2,BURSTREAD ;3周期
猝发模式读操作
猝发模式读操作又可分为基本和快速两种方式,在猝发模式下,将FRAMCFG1寄存器中的FREADIDLE置位,则启动猝发模式下的快速读操作。猝发模式读操作也利用了FRAM的双缓冲性能——使得FRAM模块可以在当前读周期结束前就开始准备下一次要读取的数据。与猝发方式写操作相似,猝发读操作也需要满足三个条件:
(1)必须是从FRAM存储器中地址连续递增的单元读出;
(2)下一条MOVX读指令必须在规定的系统周期内开始执行,且快速方式下允许间隔周期数约为基本方式下的一半;
(3)一旦开始执行猝发读操作后,则在退出猝发模式之前,不能再启动任何其它FRAM操作。表 0
22列出了FRAM运行于不同速度时,MOVX读指令之间允许间隔的系统周期数:
若未在规定的时间内从FRAM读取下一个数据或对非连续单元执行猝发读操作也会导致数据丢失,并且也没有任何标志或中断来表明这种状态。
在退出FRAM猝发操作模式之前、或在猝发模式下进行读/写操作的切换时应等到FREADIDLE=1,以确保FRAM模块空闲。
4.FRAM写保护
FRAM写保护设置可以采用两种方法:一种是在系统编程时利用Versa Ware
JTAG软件将FRAM访问权限设为只读;另一种方法是通过对寄存器FRAMCFG1和FRAMCFG2的设置来实现。
采用第二种方法时操作流程为:
(1)写入01h到FRAMCFG1寄存器,置位FRAMWEL位;
(2)等待FRAM模块空闲;
(3)设置FRAMCFG2:设置FRAMBP[1:0]位确定FRAM写保护区域;
(4)将07h写入FRAMCFG1寄存器以执行FRAM模块写保护配置;
(5) 等待FRAM模块空闲;
(6)将03h写入FRAMCFG1寄存器,将FRAMWEL位清零(以避免误写入)
(7)读取FRAMCFG2寄存器,验证块保护是否成功。
例:FRAM写保护设置模块
//-------------------------------------------------------------------//
// 函数:void FramProtect(char frambp) //
// 功能:FRAM写保护设置 //
// 入口参数:frambp,写保护区域代码(对应FRAMCFG2寄存器FRAMBP[1:0]位 //
// 出口参数:无 //
//------------------------------------------------------------------//
void FramProtect(char frambp)
{
Frambp &=0x03; //FRAM写保护区域代码
frambp=frambp << 2; //对齐FRAMCFG2寄存器FRAMBP[1:0]位
FRAMCFG1=0x01; //置位FRAMWEL
while(!(FRAMCFG1&0x80)); //等待FREADIDLE==1
FRAMCFG2=frambp; //设置FRAM写保护参数
FRAMCFG1=0x07; //将写保护参数传送到铁电模块
while(!(FRAMCFG1&0x80)); //等待FREADIDLE==1
FRAMCFG1=0x03; //清零FRAMWEL
while(!(FRAMCFG1&0x80)); //等待FREADIDLE==1
//可选操作:
//FRAMCFG1=0x05; //更新FRAMCFG2
//while(!(FRAMCFG1&0x80)); //等待FREADIDLE==1
//读FRAMCFG2寄存器,验证块保护是否成功
// ……
} //end of FramProtect
5.FRAM访问例程
以下例程用于说明FRAM铁电存储器的访问,该程序执行以下操作:
使能FRAM铁电存储器;
设置FRAM铁电存储器为非保护方式;
将0x55写入铁电存储器所有单元并读取0x8100单元的内容;然后写0x23到铁电存储器0x8100单元,再读取该单元的内容;
将铁电存储器设为写保护方式后,尝试清除其中的内容;取消铁电存储器写保护方式,再清除其中的内容;
读取写保护配置参数(可选)。
程序代码如下:
//---------- V3K_FRAM_Use_Example_Keil.c-----------//
#include
//初始化FRAM基址指针
xdata at 0x8000 unsigned char frambase;
xdata unsigned char * data framptr = &frambase;
//-----------------------主函数--------------------//
void main (void)
{
volatile idata int cptr= 0x00; //定义变量cptr为通用计数器
volatile idata char framread = 0x00; //定义变量framread
char x;
DEVMEMCFG |= 0xC0; //使能FRAM
//设置FRAM为非保护方式(可选)
FRAMCFG1 = 0x01; //置位FRAMWEL,FRAMOP[1:0]=00
while(!(FRAMCFG1&0x80)); //等待FREADIDLE==1
FRAMCFG2 = 0x00; //配置FRAMCFG2,FRAMBP[1:0]=00
FRAMCFG1 = 0x07; //传送写保护参数到铁电模块
while(!(FRAMCFG1&0x80)); //等待FREADIDLE==1
FRAMCFG1 = 0x03; //清零FRAMWEL,FRAMOP[1:0]=01
while(!(FRAMCFG1&0x80)); //等待FREADIDLE==1
//将0x55写入FRAM所有单元
for(cptr = 0; cptr<0x2000;cptr++)
*(framptr+cptr) = 0x55;
//读0x8100单元的内容,保存在变量framread中
framread = *(framptr + 0x0100) //framread值为0x55
//将0x23写入FRAM的0x8100单元
*(framptr + 0x0100) = 0x23;
//读0x8100单元的内容,保存在变量framread中
framread = *(framptr + 0x0100); //framread值为0x23
framread = *(framptr + 0x0101); //framread值为0x55
//设置FRAM写保护
FRAMCFG1 = 0x01; //置FRAMWEL
while(!(FRAMCFG1&0x80)); //等待FREADIDLE==1
FRAMCFG2 = 0x0C; //配置FRAMCFG2,FRAMBP[1:0]=11
FRAMCFG1 = 0x07; //传送写保护参数到铁电模块
while(!(FRAMCFG1&0x80)); //等待FREADIDLE==1
FRAMCFG1 = 0x03; //清零FRAMWEL
while(!(FRAMCFG1&0x80)); //等待FREADIDLE==1
//清除FRAM存储器中的内容(在写保护方式下无效)
for(cptr = 0; cptr < 0x2000; cptr++)
*(framptr+cptr) = 0x00;
//设置FRAM为非保护方式
FRAMCFG1 = 0x01; //置FRAMWEL,FRAMOP[1:0]=00
while(!(FRAMCFG1&0x80)); //等待FREADIDLE==1
FRAMCFG2 = 0x00; //配置FRAMCFG2,FRAMBP[1:0]=00
FRAMCFG1 = 0x07; //传送写保护参数到铁电模块
while(!(FRAMCFG1&0x80)); //等待FREADIDLE==1
FRAMCFG1 = 0x03; //清FRAMWEL,FRAMOP[1:0]=01
while(!(FRAMCFG1&0x80)); //等待FREADIDLE==1
//清除FRAM存储器中的内容
for(cptr = 0; cptr < 0x2000; cptr++)
*(framptr+cptr) = 0x00;
while(1);
//读取FRAM写保护参数
FRAMCFG1 = 0x05; //更新FRAMCFG2
while(!(FRAMCFG1&0x80)); //等待FREADIDLE==1
x = FRAMCFG2 //读FRAMCFG2
//(可进一步验证写保护是否成功)
}//end of Main
现在我们简单描述一些FRAM里面加密的事情,我们在FRAM里面设置一个密码数据,然后在每次软件编译的时候也设置一个号,结合一个硬盘号、时间日期加以运算,得出双方的密码。如果芯片被解密,那么号不对,自然就用不起来了 |
|
|
|
|
|