2019-2020-1 20175208 20175218 20175230 实验二 固件程序设计
一、实验内容
1、固件程序设计-1-MDK
- 注意不经老师允许不准烧写自己修改的代码
- 三人一组
- 参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.1-1.5安装MDK,JLink驱动,注意,要用系统管理员身分运行uVision4,破解MDK(破解程序中target一定选ARM)
- 提交破解程序中产生LIC的截图
- 提交破解成功的截图
2、固件程序设计-2-LED
- 注意不经老师允许不准烧写自己修改的代码
- 参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.4” KEIL-MDK 中添加 Z32 SC-000 芯片库,提交安装截图
- 参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.9”完成LED实验,注意“打开Z32的电源开关前,按住Reboot按键不放,两次打开电源开关,Z32即可被电脑识别,进行下载调试。提交运行结果截图
- 实验报告中分析代码
3、固件程序设计-3-UART
- 注意不经老师允许不准烧写自己修改的代码
- 参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.4” KEIL-MDK 中添加 Z32 SC-000 芯片库,提交安装截图
- 参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.0”完成UART发送与中断接收实验,注意“打开Z32的电源开关前,按住Reboot按键不放,两次打开电源开关,Z32即可被电脑识别,进行下载调试。提交运行结果截图
- 实验报告中分析代码
4、固件程序设计-4-国密算法
- 网上搜集国密算法标准SM1,SM2,SM3,SM4
- 网上找一下相应的代码和标准测试代码,在Ubuntu中分别用gcc和gcc-arm编译
- 四个算法的用途?
- 《密码学》课程中分别有哪些对应的算法?
- 提交2,3两个问题的答案
- 提交在Ubuntu中运行国密算法测试程序的截图
5、固件程序设计-5-SM1
- 注意不经老师允许不准烧写自己修改的代码
- 参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.4” KEIL-MDK 中添加 Z32 SC-000 芯片库,提交安装截图
- 参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.16”完成SM1加密实验,注意“打开Z32的电源开关前,按住Reboot按键不放,两次打开电源开关,Z32即可被电脑识别,进行下载调试。提交运行结果截图
- 实验报告中分析代码
6、固件程序设计-6-清理
- 实验结束后,把实验室原来的网线插回,否则以后做实验的同学无法开机
- 只有用实验室机器的小组做
- 提交你们小组使用的计算机的编号照片
- 提交插好网线的照片
- 提交盖好后盖的照片
二、实验小组成员及分工
- 成员列表
学号 | 姓名 |
---|---|
20175208 | 张家华 |
20175218 | 陈敬勇 |
20175230 | 滕星 |
- 实验分工
实验内容:三人共同完成实验
撰写博客:陈敬勇
三、实验步骤
1、固件程序设计-1-MDK
- 参考信息安全系统实验箱指导书的第一章,1.1-1.5安装好MDK,JLink驱动
- 运行keil-MDK注册机破解MDK
- 破解程序中产生LIC的截图
- 破解成功的截图
2、开发化境的熟悉-目标机宿主机联通
安装sc000库,打开Z32文件夹下的软件资料,找到Support.exe文件,双击进行安装
安装完成后,运行keil uVision4,进行工程基础编程环境搭建。其中,芯片库选择 Generic SC000 Device Database。ARM 结构目录,选择 SC000。
- 打开“ Z32 开发指南 实验1-LED闪烁”目录的工程文件。双击打开Z32HUA.uvproj文件。点击编译,进行编译。
将实验箱接入电源,把笔记本电脑与实验箱连接好,在软件资料文件夹下的Z32下载调试工具中打开Z32下载调试工具 NZDownloadTool.exe 。打开实验箱的电源开关前,按住 Reboot 键不放,两次打开电源开关, Z32 即可被电脑识别,进行下载调试。
出现设备已连接,设备选择中显示芯片型号后,点击浏览,选择LED闪烁文件夹下bin文件夹中的Z32HUA.bin,最后点击下载。
关闭实验箱 Z32 的电源开关,再打开,程序自动运行,此时可以看到实验箱 Z32 核心板上 L2 灯开始闪烁。
- 代码分析
main 函数代码如下:
int main(void) { /*********************此段代码勿动*********************/ //系统中断向量设置,使能所有中断 SystemInit(); //返回 boot 条件 if(0 == GPIO_GetVal(0)) { BtApiBack(0x55555555, 0xAAAAAAAA); } /*********************此段代码勿动*********************/ 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 } } //延时函数,当系统时钟为内部延时函数,当系统时钟为内部OSC时钟时,延时1ms void delay(int ms) { int i; while(ms----) { for(i=0;i<950;i++) ;for(i=0;i<950;i++) ; } }
主函数代码的执行过程为:
- 系统初始化,中断设置,使能所有中断;
- 判断按键,返回 boot 条件,确认是否进行程序下载;
- 设置 GPIO0 状态为上拉输出;
- 进入循环程序, LED 灯间隔 100ms 闪烁;
3、固件程序设计-3-UART
- Z32 SC-000 芯片库,安装截图
- 打开“ Z32 开发指南 实验 2 UART 发送与中断接收 ”,双击打开Z32HUA.uvproj文件。点击编译,进行编译。
- 保持上面实验电脑与实验箱的连接状态,在软件资料文件夹下的Z32下载调试工具中打开Z32下载调试工具 NZDownloadTool.exe 。打开实验箱的电源开关前,按住 Reboot 键不放,两次打开电源开关, Z32 即可被电脑识别,进行下载调试。
- 出现设备已连接,设备选择中显示芯片型号后,点击浏览,选择 UART 发送与中断接收文件夹下bin文件夹中的 Z32HUA.bin,最后点击下载。
用 9 针串口线将 Z32 模块的串口与电脑 USB 接口连接。
首先在电脑上打开串口助手,选择对应的串口号,设置波特率为 115200 ,偶校验( Even ),选中“发送新行”,然后打开串口。其中串口号可通过设备管理器查看。
关闭实验箱 Z32 电源开关,再打开,程序自动运行,可以在串口调试助手看到显示“ 0 0xAA ”。
代码分析
Uart.c
extern UINT8 shuju[64]; extern UINT8 shuju_lens; extern UINT8 uart_rx_num; extern UINT8 uart_rx_end; void UART_IrqService(void) { //*****your code*****/ UARTCR &= ~TRS_EN; { do { shuju[uart_rx_num] = UARTDR; if(shuju[uart_rx_num]=='\r'||shuju[uart_rx_num]=='\n') { shuju_lens = uart_rx_num; uart_rx_num=0; uart_rx_end=1; } else uart_rx_num++; } while(FIFO_NE & UARTISR); } UARTCR |= TRS_EN; } /** * @函数:波特率设置 * @set:0-默认波特率115200,其他:需根据时钟源和分频计算出set = 时钟(hz)/波特率 * @返回: none */ 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); } /** * @函数:初始化 * @返回:none */ 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);//挂载中断号 } /** * @函数:Uart发送一个字节 * @dat: 要发送的数据字节 * @返回:None */ void UART_SendByte(UINT8 dat) { UARTCR |= TRS_EN; UARTDR = dat; do { if(UARTISR & TXEND) { UARTISR |= TXEND;//清除发送完成标志,写1清除 break; } } while (1); UARTCR &= (~TRS_EN); } /** * @函数:Uart发送一个字符串 * @str: 要发送的字符串 * @返回:None */ void UART_SendString(UINT8 * str) { UINT8 *p ; p=str; while(*p!=0) { UART_SendByte(*p++); } } /** * @函数:Uart发送某一长度的字符串 * @buf: 要发送的字符串 * @length: 要发送的长度 * @返回:None */ void uart_SendString(UINT8 buf[],UINT8 length) { UINT8 i=0; while(length>i) { UART_SendByte(buf[i]); i=i+1; } } /** * @函数:Uart发送一个十进制整数 * @num: 要发送的整数 * @返回:None */ void UART_SendNum(INT32 num) { INT32 cnt = num,k; UINT8 i,j; if(num<0) { UART_SendByte('-'); num=-num; } //计算出i为所发数据的位数 for(i=1;; i++) { cnt = cnt/10; if(cnt == 0) break; } //算出最大被除数从高位分离 k = 1; for(j=0; j<i-1; j++) { k = k*10; } //分离并发送各个位 cnt = num; for(j=0; j<i; j++) { cnt = num/k; num = num%k; UART_SendByte(0x30+cnt); k /= 10; } } /** * @函数:Uart发送一个16进制整数 * @dat: 要发送的16进制数 * @返回:None */ 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(' '); } /** * @函数:Uart接收一个字节 * @param receive addsress * @返回:flag */ UINT8 UART_GetByte(UINT8 *data) { UINT8 ret= 0; if(0 != (UARTISR & FIFO_NE)) { *data = UARTDR; ret = 1; } return ret; } /** * @函数:Uart 接收多个字节 * @param receive addsress * @len:长度 * @返回:none */ 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--; } } }
主函数
UINT8 shuju_lens; UINT8 shuju[64]; UINT8 uart_rx_num; UINT8uart_rx_end; int main(void) { /*********************此段代码勿动***********************/ //系统中断向量设置,使能所有中断 SystemInit (); // 返回boot条件 if(0 == GPIO_GetVal(0)) { BtApiBack(0x55555555, 0xAAAAAAAA); } /*********************此段代码勿动***********************/ UART_Init(); //初始化Uart UART_SendByte('A');//Uart发送一个字符A UART_SendByte('\r'); UART_SendByte('\n');//换行 UART_SendString("Welcome to Z32HUA!"); //Uart发送字符串 UART_SendByte('\r'); UART_SendByte('\n');//换行 UART_SendNum(1234567890);//Uart发送一个十进制数 UART_SendByte('\r'); UART_SendByte('\n');//换行 UART_SendHex(0xAA);//Uart发送一个十六进制数 UART_SendByte('\r'); UART_SendByte('\n');//换行 while(1) { if(uart_rx_end) { uart_rx_end=0; uart_SendString(shuju,shuju_lens); } } //等待接收中断。 } //延时函数,当系统时钟为内部OSC时钟时,延时1ms void delay(int ms) { int i; while(ms--) { for(i=0; i<950; i++) ; } }
代码的执行过程为:
- 系统初始化,中断设置,使能所有中断;
- 判断按键,返回 boot 条件,确认是否进行程序下载;
- 初始化 Uart ,使能 Uart 接口,配置 Uart 中断并使能;
- 先发送单个字符“ A ”,换行,再发送字符串 Welcome to Z32H UA!换行,发送数字串“ 1234567890 ”,换行,再发送 16 位数“ 0xAA ”,换行。
- 进入 while 循环程序,等待串口中断到来并判断数据是否接收完毕,若中断到来,转入执行串口中断服务程序,待接收数据完毕, Z32 将数据发回串口助手。
四、实验中遇到的问题及解决方法
问题:
解决方法:
五、实验感想
通过本次实验,我们知道了交叉编译环境以及了解了开发环境的配置,我们知道了如何在Linux中编译程序并将生成的可执行文件在arm超级终端上运行。
在这次实验中,我们通过自己的笔记本电脑打开两个虚拟机主机,也就是提供了虚拟机运行的环境,然后把arm编译工具共享给win7虚拟机,在win7虚拟机下用arm编译工具编译helloword.c文件,将生成的可执行文件在arm超级终端上运行。由于电脑配置的原因,在做实验时,遇到ping不通的情况,而且根据网上大佬的方法进行调整,还是无法实现,就只能换一台电脑重新开始,耗费了我们很多时间,最终下课的时候,第三步只做了一半,没能完成最后步骤,在第二天,借用他们向实验室借的实验箱继续做,最终才把最后一步完成。