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不通的情况,而且根据网上大佬的方法进行调整,还是无法实现,就只能换一台电脑重新开始,耗费了我们很多时间,最终下课的时候,第三步只做了一半,没能完成最后步骤,在第二天,借用他们向实验室借的实验箱继续做,最终才把最后一步完成。