zoukankan      html  css  js  c++  java
  • 2018-2019-1 20165207 20165209 20165215 实验二——固件程序设计

    2018-2019-1 20165207 20165209 20165215 实验二——固件程序设计


    任务一 MDK

    实验目的

    1. 参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.1-1.5安装MDK,JLink驱动,注意,要用系统管理员身分运行uVision4,破解MDK(破解程序中target一定选ARM)
    2. 提交破解程序中产生LIC的截图
    3. 提交破解成功的截图
    

    实验步骤

    • 将"mdk474.exe"文件安装在自己创建的名为“Keil 4”的文件夹中
    • 在同一文件夹下安装ULINK 驱动
    • 右键点击桌面上创建的快捷方式“Keil uVision4”,选择“以管理员身份运行”
    • 点击File->License Management…,在弹出的窗口中复制CID

    • 再运行 keil-MDK 注册机,粘贴 CID 并选择 ARM,然后点击 generate 生成 LIC

    • 将注册机生成的 LIC 复制到 keil4中的 LIC 输入框中,点击 Add LIC,破解完成

    任务二

    实验目的

    参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.4” KEIL-MDK 中添加 Z32 SC-000 芯片库,提交安装截图
    参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.9”完成LED实验,注意“打开Z32的电源开关前,按住Reboot按键不放,两次打开电源开关,Z32即可被电脑识别,进行下载调试。提交运行结果截图
    实验报告中分析代码
    

    实验步骤

    • 在"Keil 4"文件夹下安装 MDK-ARM_AddOn_SC000_Support.exe 文件
    • 以管理员身份运行“Keil uVision4”后,选择 Project——>New uVision Project新建工程
    • 在芯片库选择框选择Generic SC000 Device Database ,点击Ok
    • 点开 ARM 结构目录,选择 SC000,点击 OK,安装完成

    • 打开“Z32 开发指南实验 1-LED 闪烁”目录的工程文件,编译主函数产生后缀名为.bin 的可执行代码

    • 用USB线连接电脑和试验箱,打开NZDloadTool.exe
    • 按住Reboot按钮的同时两次开关试验箱左上角部分的电源开关,Z32被识别,Download tool界面左侧显示已连接设备,然后浏览之前编译生成的.bin文件,点击下载

    • 对实验箱重新给电,即可观察到L2灯开始闪烁

    代码分析

    int main(void)
    {
    	SystemInit (); //系统中断向量设置,使能所有中断
        
    	if(0 == GPIO_GetVal(0))
    	{
    		BtApiBack(0x55555555, 0xAAAAAAAA);
    	}
    	//判断按键,返回 boot 条件,确认是否进行程序下载;
    	GPIO_PuPdSel(0,0);	//设置GPIO0为上拉
    	GPIO_InOutSet(0,0); //设置GPIO0为输出
    	while(1)
    	{
    		delay(100);
    		GPIO_SetVal(0,0);  //输出低电平,点亮LED
    		delay(100);
    		GPIO_SetVal(0,1);  //输出高电平,熄灭LED	
    	}
    	//进入循环程序, LED 灯间隔 100ms 闪烁。
    }
    

    任务三

    实验目的

    1. 参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.4” KEIL-MDK 中添加 Z32 SC-000 芯片库,提交安装截图
    2.参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.10”完成UART发送与中断接收实验,注意“打开Z32的电源开关前,按住Reboot按键不放,两次打开电源开关,Z32即可被电脑识别,进行下载调试。提交运行结果截图
    3.实验报告中分析代码
    

    实验步骤

    • 打开“UART发送与中断接收”目录下的Z32HUA.uvproj工程文件并编译,将生成的.bin文件下载到实验箱

    • 除了用USB公线连接电脑和实验箱外,还需要用9针串口线将 Z32 模块的串口与电脑USB接口连接
    • 在电脑上打开串口助手,选择对应的串口号,设置波特率为115200, 偶校验(Even),选中“发送新行”,然后打开串口
    • 对Z32重新给电,程序自动运行,可以在串口调试助手中看到PC机 串口接收到 Z32 串口发送来的信息

    代码分析

    串口相关函数包括中断服务、波特率设置初始化发送 /接收单 字节、发送符串单个十进制整数、发送某一长度的字符串、接收多字节函数:

    • void UART_IrqService(void) 是串口中 断服务函数,本实验现断执行子程序,从 PC 端串口调试助手发送数据至 Z32 ,Z32 再经串口 发送给 PC 机
    void UART_IrqService(void)
    {
        UARTCR &= ~TRS_EN;
        {
            do
            {
                shuju[uart_rx_num] = UARTDR;
                    if(shuju[uart_rx_num]=='
    '||shuju[uart_rx_num]=='
    ')
                    {
                        shuju_lens = uart_rx_num;
                        uart_rx_num=0;
                        uart_rx_end=1;
                    }
                    else uart_rx_num++;
            }
            while(FIFO_NE & UARTISR);               
        }
        UARTCR |= TRS_EN;
    }
    
    • void UART_BrpSet(UINT16 set) 是波特率设置 函数,串口实验波特率设置为115200
    void UART_BrpSet(UINT16 set)
    {
        UINT16 brp=0;
        UINT8 fd=0; 
        if(0 == set)
        {
            //uartband@115200bps
            fd = SCU->UARTCLKCR & 0x80; 
            switch(fd)
            {
                case 0x80:        /*内部时钟12M晶振*/
                    brp = 0x0068;
                    break;
                case 0x00:        /*内部时钟*/
                    brp = 0x00AD;  
                    break;        
                default:
                    brp = 0x00AD;
                    break;
            }
            fd = SCU->UARTCLKCR & 0x7f ; 
            brp =   brp/(fd+1);
        }
        else
        {
            brp = set;
        }
        UARTBRPH = (UINT8)((brp >> 8) & 0xFF);
        UARTBRPL = (UINT8)((brp) & 0xFF);
    }
    
    • void UART_Init(void) 是串口初始化函数,,实现配 置串口时钟、使能中断
    void UART_Init(void)
    {
        IOM->CRA |= (1<<0); //使能Uart接口
        SCU->MCGR2 |= (1<<3); //使能Uart总线时钟
    
        /******配置Uart时钟(建议使用外部晶振)******/
        SCU->SCFGOR |= (1<<6);//使用外部晶振
        SCU->UARTCLKCR |= (1<<7);//使用外部时钟
    //  SCU->UARTCLKCR &= ~(1<<7);//使用默认OSC时钟
    
        UART_BrpSet(0);  //设置波特率为默认115200
        UARTISR = 0xFF;  //状态寄存器全部清除
        UARTCR |= FLUSH; //清除接收fifo
        UARTCR = 0;      //偶校验
    
    
        /******配置中断使能******/
        UARTIER |= FIFO_NE;
    //  UARTIER |= FIFO_HF;
    //  UARTIER |= FIFO_FU;
    //  UARTIER |= FIFO_OV;
    //  UARTIER |= TXEND;
    //  UARTIER |= TRE; 
        ModuleIrqRegister(Uart_Exception, UART_IrqService); //挂载终端号
    }  
    
    • void UART_SendByte(UINT8 dat) 是发送单字节函数,使用此函数一次发 送一个字节数据
    void UART_SendByte(UINT8 dat)
    {  
        UARTCR |= TRS_EN;
        UARTDR = dat;
        do
        {
           if(UARTISR & TXEND)
            {                                         
                UARTISR |= TXEND;//清楚发送完成标志,写1清除
                break;
            }
        }
        while (1);
        UARTCR &= (~TRS_EN);    
    }
    
    • void UART_SendString(UINT8 * str) 是发送字符串函数 ,使用此函数发送 字符串数据
    void UART_SendString(UINT8 * str)
    {
        UINT8 *p ;
        p=str;
        while(*p!=0)
        {
            UART_SendByte(*p++);
        }
    }
    
    • void uart_SendString(UINT8 buf[],length) 是发送某一长度的字符 串函数,实现发送一定长度的字符据
    void uart_SendString(UINT8 buf[],UINT8 length)
    {
        UINT8 i=0;
        while(length>i)
        {
            
            UART_SendByte(buf[i]);
            i=i+1;
        }
    }
    
    • void UART_SendHex(UINT8 dat) 是发送单个十六进制整数 函数,使用此 函数 发送一个十六进制整数
    void UART_SendHex(UINT8 dat)
    {
        UINT8 ge,shi;
        UART_SendByte('0');
        UART_SendByte('x');
        ge = dat%16;
        shi = dat/16;
        if(ge>9) ge+=7;    //换成大写字母
        if(shi>9) shi+=7;
        UART_SendByte(0x30+shi);
        UART_SendByte(0x30+ge);
        UART_SendByte(' ');
    }
    
    • UINT8 UART_GetByte(*data) 是接收单字节函数 是接收单字节函数 数,使用此函数接 收单字节数据
    UINT8 UART_GetByte(UINT8 *data)
    {
    
        UINT8 ret= 0; 
        if(0 != (UARTISR & FIFO_NE))
        {
            *data = UARTDR;
            ret = 1;
        } 
        return ret;
    }
    
    • void UART_Receive(UINT8 *receive, len) 是接收多字节函数 ,使 用此函数接收多个字节据
    void UART_Receive(UINT8 *receive, UINT8 len)
    {  
        while(len != 0)
        {
            if(len >= 4)
            {
                while (!(UARTISR & FIFO_FU));
                *receive++ = UARTDR;
                *receive++ = UARTDR;
                *receive++ = UARTDR;
                *receive++ = UARTDR;             
                len -= 4;
          
            }   
            else if(len >= 2)
            {
                while (!(UARTISR & FIFO_HF));               
                *receive++ = UARTDR;
                *receive++ = UARTDR;             
                len -= 2;
            }       
            else
            {
                 while (!(UARTISR & FIFO_NE));
                 *receive++ = UARTDR;
                 len--;
            }
        }
    }
    
    • 主函数
    int main(void) 
    { 
        SystemInit (); //系统中断向量设置,使能所有中断 
        if (0 == GPIO_GetVal(0)) 
        { 
         	BtApiBack(0x55555555, 0xAAAAAAAA); 
        } 
        // 	判断按键,返回boot条件,确认是否进行程序下载
        UART_Init();    //初始化 Uart, 使能 Uart 接口,配置 Uart 中断并使能; 
        UART_SendByte('A');  //Uart 发送一个字符 A 
        UART_SendByte('
    ');UART_SendByte('
    ');//换行 
        UART_SendString("Welcome to Z32HUA!");  //Uart 发送字符串 
        UART_SendByte('
    ');UART_SendByte('
    ');//换行 
        UART_SendNum(1234567890);       //Uart发送一个十进制数 
        UART_SendByte('
    ');UART_SendByte('
    ');//换行 
        UART_SendHex(0xAA);     //Uart 发送一个十六进制数 
        UART_SendByte('
    ');UART_SendByte('
    ');//换行 
        while(1)  {   	if(uart_rx_end) 
    	  	{ 
    	  	 	uart_rx_end=0; 
    	  	 	uart_SendString(shuju,shuju_lens); 
    	  	} 
         }  //循环程序,等待串口中断到来并判断数据是否接收完毕,若中断到来,转入执行串口中断服务程序,待接收数据完毕,Z32 将数据发回串口助手。 
    } 
    

    任务四

    • SM1算法
      • 类型:分组对称加解密算法
      • 用途:电子政务、电子商务、VPN加密、文件加密、通信加密、数字电视、电子认证及国民经济的各个应用领域。
      • 对应《密码学》课程中的AES、DES算法
    • SM2算法
      • 类型:基于ECC的非对称加解密算法
      • 用途:密钥管理,数字签名,电子商务,PKI,信息及身份认证等信息安全应用领域
      • 对应《密码学》课程中的ECC椭圆曲线算法
    • SM3算法
      • 类型:消息摘要、杂凑函数
      • 用途用于商用密码应用中的数字签名和验证、消息认证码的生成与验证以及随机数的生成
      • 对应《密码学》课程中的MD5算法
    • SM4算法
      • 类型:分组对称加解密算法
      • 用途:用于无线局域网和可信计算系统的专用分组密码算法
      • 对应《密码学》课程中的3-DES算法

    在Ubuntu中运行国密算法测试程序

    任务五

    实验目的

    1. 参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.4” KEIL-MDK 中添加 Z32 SC-000 芯片库,提交安装截图
    2. 参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.16”完成SM1加密实验,注意“打开Z32的电源开关前,按住Reboot按键不放,两次打开电源开关,Z32即可被电脑识别,进行下载调试。提交运行结果截图
    3. 实验报告中分析代码
    

    实验步骤

    • 打开“exp2SM1”目录下的Z32HUA.uvproj工程文件并编译,将生成的.bin文件下载到实验箱
    • 用9针串口线将电脑与Z32部分连接
    • 打开sscom42.exe串口助手,完成相关设定后关闭再打开实验箱Z32部分的电源开关
    • 按照电子屏的提示插入IC卡。
    • 插入正确的卡后显示相应信息,然后按A校验密码
    • 按照步骤进行进一步的加解

    代码分析

    int main(void) 
    { 
        SystemInit (); //系统初始化,中断设置使能所有
        if(0 == GPIO_GetVal(0)) 
        { 
    	  	BtApiBack(0x55555555, 0xAAAAAAAA); 
        } 
        // 判断按键,返回 boot条件,确认是否进行程序下载;
    	GPIO_Config(6); /*初始化 IC 卡插入检测 IO口GPIO6*/ 	 	 
        GPIO_PuPdSel(6,0); //上拉 
        GPIO_InOutSet(6,1); //输入     
        UART_Init(); //串口初始化
        lcd_init();  //LCD12864 初始化
        KEY_Init();  // 矩阵键盘初始化
        lcd_pos(0,0);//定位第一行  
        lcd_string("SLE4428 实验!"); //显示字符串“ SLE4428 实验!”
     
    	A:while(1) 
        { 
     	    lcd_pos(1,0);//定位第二行  
     	    lcd_string("请插入 IC 卡.  ");  //显示“请插入 IC 卡”等待片插入
     	    delay(1000);
     	    if(GPIO_GetVal(6)==0) break; 
      	    lcd_pos(1,0);//定位第二行   
      	    lcd_string("请插入 IC 卡.. ");   
      	    delay(1000);   	
      	    if(GPIO_GetVal(6)==0) break; 
         	lcd_pos(1,0);//定位第二行   
         	lcd_string("请插入 IC 卡...");   
         	delay(1000);  
         	if(GPIO_GetVal(6)==0) break; 
        } 
        if(SLE4428_InitAndRST(2)!=0xFFFFFFFF)  //收到 ATR 
        {   
        lcd_pos(1,0);//定位第二行   
        lcd_string("已插入 SLE4428"); //显示“已SLE4428 
        }
        else  {   
        lcd_pos(1,0);//定位第二行  
        lcd_string("卡不正确 ");  //卡片插入错 误则第二行显示“卡不正确 ”
        SLE4428_Deactivation(); //下电,去激活   delay(1000);  
        goto A;  
     } 
        lcd_pos(2,0);//定位第三行 
        lcd_string("用户代码为:"); 
        SLE4428_ReadData(0x15,UserCode,6); //读取用户代码 
        lcd_pos(3,0);//定位第四行
        for(UINT8 i=0;i<6;i++) 
        lcd_Hex(UserCode[i]) ; 
        while(KEY_ReadValue()!='A'); //等待 A 键按下 
        lcd_wcmd(0x01);//清屏 
        lcd_pos(0,0);//定位第一行 
        lcd_string("按-A 键校验密码");  
        lcd_pos(1,0);//定位第二行  
        lcd_string("校验 0xFF,0xFF"); 
        while(KEY_ReadValue()!='A'); //等待 A 键按下 
            lcd_pos(2,0);//定位第三行  
        if(SLE4428_PassWord(0xFF,0xFF)==1) 	     	
            lcd_string("校验成功"); 
        else 
    	  	{lcd_string("校验失败"); return 0;} 
        lcd_pos(3,0);//定位第四行 
        switch(SLE4428_ReadByte(0x03fd))//查看剩余密码验证机会 
        { 
          	case 0xff:
          	    lcd_string("剩余机会: 8 次");
          	    break;   
          	case 0x7f:
          	    lcd_string("剩余机会: 7 次");
          	    break;   
          	case 0x3f:    
          	    lcd_string("剩余机会: 6 次");
          	    break;   
            case 0x1f:
                lcd_string("剩余机会: 5 次");
                break;
            case 0x0f:
                lcd_string("剩余机会: 4 次");
                break;   
            case 0x07: 
                lcd_string("剩余机会: 3 次");
                break;  
            case 0x03: 
                lcd_string("剩余机会: 2 次");
                break;  
            case 0x01: 
                lcd_string("剩余机会: 1 次");
                break;  
            case 0x00: 
                lcd_string("剩余机会: 0 次");
                break;  
            default: break; 
        } 
        while(KEY_ReadValue()!='A'); //等待 A 键按下 B: 
            lcd_wcmd(0x01);//清屏  
        lcd_pos(0,0);//定位第一行  
        lcd_string("加密解密实验");  
        lcd_pos(1,0);//定位第二行 
        lcd_string("1.加密"); 
        lcd_pos(2,0);//定位第三行 
        lcd_string("2.解密"); 
        do 
        { 
    	  	C=KEY_ReadValue(); 
        } while(C!='1'&&C!='2'); //等待 1 或 2 键按下  
        lcd_wcmd(0x01);//清屏 
        if(C=='1') 	goto jiami;  
        else if(C=='2')	goto jiemi; 
        else ; 
    jiami: 
        lcd_pos(0,0);//定位第一行  
        lcd_string("观看串口调试助手");  
        lcd_pos(1,0);//定位第二行 
        lcd_string("A 键确认加密");  
        UART_SendString("将加密以下数据:
    ");  
        for(UINT8 i=0;i<16;i++) 
        { 
    	  	UART_SendHex(jiamiqian[i]); 
        } 
        UART_SendString("
    "); 
        UART_SendString("加密密钥:
    "); 
        for(UINT8 i=0;i<16;i++) 
        { 
    	 	UART_SendHex(jiamimiyue[i]); 
        } 
        UART_SendString("
    ");  
        while(KEY_ReadValue()!='A'); //等待 A 键按下 
    	SM1_Init(jiamimiyue); 	 	 //SM1 初始化 
        SM1_Crypto(jiamiqian, 16, 0, 0, 0,jiamihou);//进行加密 
        SM1_Close(); //关闭安全模块  
        UART_SendString("加密后的数据:
    ");
        for(UINT8 i=0;i<16;i++) 
        { 
    	  	UART_SendHex(jiamihou[i]); 
        } 
        UART_SendString("
    ");  
        lcd_pos(2,0);//定位第三行 
        lcd_string("加密完成"); 
        lcd_pos(3,0);//定位第四行  
        lcd_string("A 键存入 IC 卡");  
        while(KEY_ReadValue()!='A'); //等待 A 键按下  
            for(UINT8 i=0;i<16;i++) 
            { 
                SLE4428_Write_Byte(0x20+i,jiamihou[i]); //设置 IC 卡 0x20 地址为存储加密数据的地址 
            } 
        UART_SendString("已将数据写入 IC 卡。
    "); 
        UART_SendString("
    ");
        goto B; 
    
    jiemi: 
        lcd_pos(0,0);//定位第一行 
        lcd_string("观看串口调试助手"); 
        lcd_pos(1,0);//定位第二行 
        lcd_string(" A 键读取 IC 卡数据"); 
        while(KEY_ReadValue()!='A'); //等待 A 键按下 
        SLE4428_ReadData(0x20,jiemiqian,16); 
        UART_SendString("读取的数据为:
    "); 
        for(UINT8 i=0;i<16;i++) 
        { 
    	  	UART_SendHex(jiemiqian[i]); 
        } 
        UART_SendString("
    ");  
        lcd_wcmd(0x01);//清屏  
        lcd_pos(0,0);//定位第一行  
        lcd_string("读取成功"); 
        lcd_pos(1,0);//定位第二行 
        lcd_string("选择密钥解密:");
        lcd_pos(2,0);//定位第三行 
        lcd_string("1.正确密钥");  
        lcd_pos(3,0);//定位第四行 
        lcd_string("2.错误密钥"); 
        do 
        { 
    	  	C=KEY_ReadValue(); 
        } while(C!='1'&&C!='2'); //等待 1 或 2 键按下  
        lcd_wcmd(0x01);//清屏 
        if(C=='1') 	  
        {  
            for(UINT8 i=0;i<16;i++)   
            jiemimiyue[i] = jiamimiyue[i]; 	 
        } 
        else if(C=='2') { 
            for(UINT8 i=0;i<16;i++)  
            jiemimiyue[i] = cuowumiyue[i]; 
        }
        else ; 
        UART_SendString("将使用以下密钥进行解密:
    "); 
        for(UINT8 i=0;i<16;i++) 
        { 
    	  	UART_SendHex(jiemimiyue[i]); 
        } 
        UART_SendString("
    ");
        lcd_pos(0,0);//定位第一行  
        lcd_string("A 键确认解密");
        while(KEY_ReadValue()!='A'); //等待 A 键按下  
        SM1_Init(jiemimiyue); 	 	 //SM1 初始化 
        SM1_Crypto(jiemiqian, 16, 1, 0, 0,jiemihou); //进行解密  
        SM1_Close(); //关闭安全模块 
        lcd_pos(1,0);//定位第二行
        lcd_string("解密完成");
        lcd_pos(2,0);//定位第三行
        lcd_string("A 键返回"); 
        UART_SendString("解密后的数据为:
    "); 
        for(UINT8 i=0;i<16;i++) 
        { 
    	  	UART_SendHex(jiemihou[i]); 
        } 
        UART_SendString("
    "); 
        UART_SendString("
    ");
        while(KEY_ReadValue()!='A'); //等待 A 键按下 
        goto B; 
        SLE4428_Deactivation(); //下电,去激活,实验结束 
        while(1) {}
    } 
     //延时函数,当系统时钟为内部 OSC 时钟时,延时 1ms void delay(int ms) 
    { 
     int i; 
     while(ms--) 
     { 
     for(i=0;i<950;i++) ; 
     } 
    }  
    

    实验中遇到的问题及解决方法

    问题:无法打开NZDownloadTool.exe
    解决方法:运行串口驱动之后即可打开

  • 相关阅读:
    剑指Offer-11.二进制中1的个数(C++/Java)
    剑指Offer-10.矩形覆盖(C++/Java)
    剑指Offer-9.变态跳台阶(C++/Java)
    UVA 1608 Non-boring sequence 不无聊的序列(分治,中途相遇)
    UVA1607 Gates 与非门电路 (二分)
    UVA 1451 Average平均值 (数形结合,斜率优化)
    UVA 1471 Defense Lines 防线 (LIS变形)
    UVA 1606 Amphiphilic Carbon Molecules 两亲性分子 (极角排序或叉积,扫描法)
    UVA 11134 FabledRooks 传说中的车 (问题分解)
    UVA 1152 4 Values Whose Sum is Zero 和为0的4个值 (中途相遇)
  • 原文地址:https://www.cnblogs.com/fyss/p/9905739.html
Copyright © 2011-2022 走看看