//-------------------------------------------------------------------------*
// 工 程 名:Flash        				                           		             *
// 硬件连接: AW60的串口1接PC的串口                                         *
// 程序描述: Flash的擦除,写入,加密,块保护等基本操作                        *
// 目    的: 初步掌握Flash擦除、写入等操作的基本知识                       *
// 说    明: (1)使用SCI1口,波特率为9600                                    *
//           (2)不能擦除程序所在的页,可通过查看s19文件确定程序所在的页     *                                                              *
//----------------苏州大学飞思卡尔嵌入式系统实验室2010年-------------------*

//头文件
#include "Includes.h"

//主函数  
void main()
{
    //1. 主程序使用的变量定义
    uint8 revstat;
    uint16 tmp,i,j,count,state,cmd,page;
    uint8  rev[512],writebuf[512];
    uint16 len,pstartadd;
    uint32 addr;

    //2. 关总中断
    DisableInterrupt();     //禁止总中断
    
    //3. 芯片初始化
    MCUInit();
    
    //4.串行口初始化
    //  使用SCI1模块,使用系统时钟作为SCI的时钟源
    //  波特率为9600
    SCIInit(SCI_NUM_1,SYSTEM_CLOCK,9600);
     
    //5.Flash初始化
    FlashInit(SYSTEM_CLOCK*1000);

    //6.变量初始化
    revstat = 1;
    
    SCISendString(SCI_NUM_1,"Press ? to get help\r\n");
    //7.主循环
    while (1)			          
    {
        addr = 0;
    	len = 0;
    	i = 0;	
        count = 0;
        page = 0;
        pstartadd = 0;	
        while(revstat)
            cmd = SCIRe1(SCI_NUM_1,&revstat);
        revstat = 1;
        switch (cmd)
        {
            case '?'://命令帮助
            	SCISendString(SCI_NUM_1,"擦除,读取,写入,设置密钥,密钥验证,块保护命令格式如下:\r\n");
    			SCISendString(SCI_NUM_1,"   擦    除 E:8\r\n");
    			SCISendString(SCI_NUM_1,"   读    取 R:8:0:8\r\n");
    			SCISendString(SCI_NUM_1,"   写    入 W:8:0:4:1,2,3,4\r\n");
    			SCISendString(SCI_NUM_1,"   密钥设置 B:8,7,6,5,4,3,2,1\r\n");
    			SCISendString(SCI_NUM_1,"   密钥验证 M:8,7,6,5,4,3,2,1\r\n");
    			SCISendString(SCI_NUM_1,"   密钥删除 D\r\n");
    			SCISendString(SCI_NUM_1,"   加密解除 U\r\n");
    			SCISendString(SCI_NUM_1,"   块 保 护 P:8\r\n");
    			SCISendString(SCI_NUM_1,"注意:页号(0~127),页内开始地址(0~511)\r\n");
    			break;	
            case 'E'://擦除
                //跳过冒号
    			cmd = SCIRe1(SCI_NUM_1,&revstat);
    			//接收串口数据
    			while(revstat == 0)
    			{
    			    rev[count++] = SCIRe1(SCI_NUM_1,&revstat);
    			}
    			//计算地址
    			while(i<(count-1))
    			{
    			    page = page*10 +rev[i++]-'0';
    			}
    			//擦除flash
    			state = Flash_PageErase(page);
    			if(state == 0)
    				SCISendString(SCI_NUM_1," Erase Succeed\r\n");
    			else
    				SCISendString(SCI_NUM_1," Erase Failed\r\n");
    			break;	
            case 'R': //读取
                //跳过冒号
    			cmd = SCIRe1(SCI_NUM_1,&revstat);
    			i = 0;
    			count = 0;
    			//接收串口数据
    			while(revstat == 0)
    			{
    			    rev[count++] = SCIRe1(SCI_NUM_1,&revstat);
    			}
    			//计算页号
    			while(rev[i] != ':')
    			{
    			    page = page*10 +rev[i++]-'0';
    			}
    			i++;
    			//计算开始地址
    			while(rev[i] != ':')
    			{
    			    pstartadd = pstartadd*10 +rev[i++]-'0';
    			}
    			i++;
    			//计算读的字节个数
    			while((rev[i] >= '0')&&(rev[i] <= '9')&&(i<count))
    			{
    			    len = len*10 +rev[i++]-'0';  
    			}
    			SCISendString(SCI_NUM_1,"R:");
    		    SCISendN(SCI_NUM_1,len,(uint8*)(page*512+pstartadd));
    		    SCISendString(SCI_NUM_1,"\r\n");	    
                break;  
            case 'W'://写入
                //跳过冒号
    			cmd = SCIRe1(SCI_NUM_1,&revstat);
    			i = 0;
                //接收串口数据
    			while(revstat == 0)
    			{
    			    rev[count++] = SCIRe1(SCI_NUM_1,&revstat);
    			}	
    			//计算页号
    			while(rev[i] != ':')
    			{
    			    page = page *10 +rev[i++]-'0';
    			}
    			i++;
    			//计算页内开始写的偏移地址
    			while(rev[i] != ':')
    			{
    			    pstartadd = pstartadd *10 +rev[i++]-'0';
    			}
    			i++;
    			//计算要写的字节个数
    			while(rev[i] != ':')
    			{
    			    len = len *10 +rev[i++]-'0';  
    			}
    			i++;
    			//取得要写入的数据
    			j = 0;
    			while(i<(count-1))
    			{
    			    if(rev[i] == ',')
    			    {
    			        i++; 
    			    }    			        
    			    else
    			    {
    			        writebuf[j] = rev[i];
    			        j++; i++;
    			    }
    			}
    			//写入Flash
				state = Flash_ByteWrite((uint8*)&writebuf[0],page,pstartadd,len);
				if(0 == state)
				    SCISendString(SCI_NUM_1," Write Succeed\r\n");
				else
				    SCISendString(SCI_NUM_1," Write Failed\r\n");
                break;  
            case 'B'://设置后门密钥
                //跳过冒号
    			cmd = SCIRe1(SCI_NUM_1,&revstat);
                //接收串口数据
    			while(revstat == 0)
    			{
    			    rev[count++] = SCIRe1(SCI_NUM_1,&revstat);
    			}
                //取得要写入的数据
                i = 0;
    			j = 0;
    			while(i<(count-1))
    			{
    			    if(rev[i] == ',')
    			    {
    			        i++;
    			        continue;
    			    }    			        
    			    else
    			    {
    			        writebuf[j++] = rev[i++];
    			    }
    			}
                //设置后门密钥
                state = Flash_Secure((uint8*)&writebuf);
                if(state == 0)
                    SCISendString(SCI_NUM_1,"Set Backdoor Key Succeed\r\n");
                else if(1 == state)
                    SCISendString(SCI_NUM_1,"Set Backdoor Key Failed--Erase-Error\r\n");
                else if(2 == state)
                    SCISendString(SCI_NUM_1,"Set Backdoor Key Failed--Write-Error\r\n");
                else if(3 == state)
                    SCISendString(SCI_NUM_1,"Set Backdoor Key Failed--Block Protect-Error\r\n");
                else 
                    SCISendString(SCI_NUM_1,"Set Backdoor Key Failed--Else-Error\r\n");
                break; 
            case 'M'://后门密钥验证
                //跳过冒号
    			cmd = SCIRe1(SCI_NUM_1,&revstat);
                //接收串口数据
    			while(revstat == 0)
    			{
    			    rev[count++] = SCIRe1(SCI_NUM_1,&revstat);
    			}
                //取得要写入的数据
                i = 0;
    			j = 0;
    			while(i<(count-1))
    			{
    			    if(rev[i] == ',')
    			    {
    			        i++;
    			        continue;
    			    }    			        
    			    else
    			    {
    			        writebuf[j++] = rev[i++];
    			    }
    			}
                state = Flash_KEY_Match(writebuf); //密钥匹配
                if(0 == state)
                    SCISendString(SCI_NUM_1," KEY Match Succeed\r\n");
                else if(1 == state)
                    SCISendString(SCI_NUM_1," KEY Match Failed--Error-BackDoor Disable\r\n"); 
                else if(2 == state)
                    SCISendString(SCI_NUM_1," KEY Match Failed--Error-BackDoor Wrong\r\n");
                else
                    SCISendString(SCI_NUM_1," KEY Match Failed--Error-Else\r\n"); 
                break;
            case 'P'://块保护
                //跳过冒号
    			cmd = SCIRe1(SCI_NUM_1,&revstat);
    			//接收串口数据
    			while(revstat == 0)
    			{
    			    rev[count++] = SCIRe1(SCI_NUM_1,&revstat);
    			}
    			//计算地址
    			while(i<(count-1))
    			{
    			    page = page*10 +rev[i++]-'0';
    			}
    			//块保护
    			state = Flash_SetBlockProtect(page,0);
    			if(0 == state)
                    SCISendString(SCI_NUM_1,"Succeed to Set Block Protect\r\n");
                else if(1 == state)
                    SCISendString(SCI_NUM_1,"Failed to Set Block Protect--Erase-Error\r\n");
                else if(2 == state)
                    SCISendString(SCI_NUM_1,"Failed to Set Block Protect--Write-Error\r\n");
                else 
                    SCISendString(SCI_NUM_1,"Failed to Set Block Protect--Else-Error\r\n");
    			break; 
            case 'D':  //删除密钥
                state = Flash_Key_Delete();
                if(0 == state)
                    SCISendString(SCI_NUM_1,"Delete key Succeed\r\n");
                else if(1 == state)
                    SCISendString(SCI_NUM_1,"Delete key Failed--Erase-Error\r\n");
                else if(2 == state)
                    SCISendString(SCI_NUM_1,"Delete key Failed--Write-Error\r\n");
                else if(3 == state)
                    SCISendString(SCI_NUM_1,"Delete key Failed--Block Protect-Error\r\n");
                else 
                    SCISendString(SCI_NUM_1,"Delete key Failed--Else-Error\r\n");
                break;
            case 'U':  //解除加密
                state = Flash_UnSecure();
                if(0 == state)
                    SCISendString(SCI_NUM_1,"UnSecure Succeed\r\n");
                else if(1 == state)
                    SCISendString(SCI_NUM_1,"UnSecure Failed--Erase-Error\r\n");
                else if(2 == state)
                    SCISendString(SCI_NUM_1,"UnSecure Failed--Write-Error\r\n");
                else if(3 == state)
                    SCISendString(SCI_NUM_1,"UnSecure Failed--Block Protect-Error\r\n");
                else 
                    SCISendString(SCI_NUM_1,"UnSecure Failed--Else-Error\r\n");
                break; 
            case 'S': //查看块保护地址和保密字节
                SCISend1(SCI_NUM_1,0x33); 
                SCISend1(SCI_NUM_1,FPROT );//FPROT  -保护页  *(uint8 *)0x1824
                SCISend1(SCI_NUM_1,NVPROT);//NVPROT *(uint8 *)0xFFBD
                                             
                SCISend1(SCI_NUM_1,FOPT);//FOPT keyen sec01 sec00  *(uint8 *)0x1821
                SCISend1(SCI_NUM_1,NVOPT);//NVOPT  *(uint8 *)0xFFBF
                SCISend1(SCI_NUM_1,0x33);
                break;
             case 'K': //查看密钥
                SCISend1(SCI_NUM_1,0x33); 
                SCISendN(SCI_NUM_1,8,(uint8 *)0xFFB0);
                SCISend1(SCI_NUM_1,0x33);
                break;    
            default:
                break;
        } 
    }/**/
}