486 lines
13 KiB
C
486 lines
13 KiB
C
/*******************************************************************************
|
||
** 文件名: common.c
|
||
** 版本: 1.0
|
||
** 工作环境: RealView MDK-ARM 4.14
|
||
** 作者: wuguoyana
|
||
** 生成日期: 2011-04-29
|
||
** 功能: 显示主菜单。主菜单上显示一系列操作,如加载二进制文件、
|
||
执行应用程序以及禁止写保护(如果事先Flash被写保护)。
|
||
** 相关文件: common.h,ymodem.h
|
||
** 修改日志: 2011-04-29 创建文档
|
||
*******************************************************************************/
|
||
|
||
/* 包含头文件 *****************************************************************/
|
||
#include "common.h"
|
||
#include "stm32f10x_flash.h"
|
||
|
||
/* 变量 ----------------------------------------------------------------------*/
|
||
pFunction Jump_To_Application;
|
||
uint32_t JumpAddress;
|
||
uint32_t BlockNbr = 0, UserMemoryMask = 0;
|
||
__IO uint32_t FlashProtection = 0;
|
||
uint32_t FlashDestination;
|
||
|
||
|
||
/*******************************************************************************
|
||
* @函数名称 Int2Str
|
||
* @函数说明 整形数据转到字符串
|
||
* @输入参数 intnum:数据
|
||
* @输出参数 str:转换为的字符串
|
||
* @返回参数 无
|
||
*******************************************************************************/
|
||
void Int2Str(uint8_t* str, int32_t intnum)
|
||
{
|
||
uint32_t i, Div = 1000000000, j = 0, Status = 0;
|
||
|
||
for (i = 0; i < 10; i++)
|
||
{
|
||
str[j++] = (intnum / Div) + 48;
|
||
|
||
intnum = intnum % Div;
|
||
Div /= 10;
|
||
if ((str[j-1] == '0') & (Status == 0))
|
||
{
|
||
j = 0;
|
||
}
|
||
else
|
||
{
|
||
Status++;
|
||
}
|
||
}
|
||
}
|
||
|
||
/*******************************************************************************
|
||
* @函数名称 Int2Str
|
||
* @函数说明 字符串转到数据
|
||
* @输入参数 inputstr:需转换的字符串
|
||
* @输出参数 intnum:转好的数据
|
||
* @返回参数 转换结果
|
||
1:正确
|
||
0:错误
|
||
*******************************************************************************/
|
||
uint32_t Str2Int(uint8_t *inputstr, int32_t *intnum)
|
||
{
|
||
uint32_t i = 0, res = 0;
|
||
uint32_t val = 0;
|
||
|
||
if (inputstr[0] == '0' && (inputstr[1] == 'x' || inputstr[1] == 'X'))
|
||
{
|
||
if (inputstr[2] == '\0')
|
||
{
|
||
return 0;
|
||
}
|
||
for (i = 2; i < 11; i++)
|
||
{
|
||
if (inputstr[i] == '\0')
|
||
{
|
||
*intnum = val;
|
||
//返回1
|
||
res = 1;
|
||
break;
|
||
}
|
||
if (ISVALIDHEX(inputstr[i]))
|
||
{
|
||
val = (val << 4) + CONVERTHEX(inputstr[i]);
|
||
}
|
||
else
|
||
{
|
||
//无效输入返回0
|
||
res = 0;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (i >= 11)
|
||
{
|
||
res = 0;
|
||
}
|
||
}
|
||
else//最多10为2输入
|
||
{
|
||
for (i = 0; i < 11; i++)
|
||
{
|
||
if (inputstr[i] == '\0')
|
||
{
|
||
*intnum = val;
|
||
//返回1
|
||
res = 1;
|
||
break;
|
||
}
|
||
else if ((inputstr[i] == 'k' || inputstr[i] == 'K') && (i > 0))
|
||
{
|
||
val = val << 10;
|
||
*intnum = val;
|
||
res = 1;
|
||
break;
|
||
}
|
||
else if ((inputstr[i] == 'm' || inputstr[i] == 'M') && (i > 0))
|
||
{
|
||
val = val << 20;
|
||
*intnum = val;
|
||
res = 1;
|
||
break;
|
||
}
|
||
else if (ISVALIDDEC(inputstr[i]))
|
||
{
|
||
val = val * 10 + CONVERTDEC(inputstr[i]);
|
||
}
|
||
else
|
||
{
|
||
//无效输入返回0
|
||
res = 0;
|
||
break;
|
||
}
|
||
}
|
||
//超过10位无效,返回0
|
||
if (i >= 11)
|
||
{
|
||
res = 0;
|
||
}
|
||
}
|
||
|
||
return res;
|
||
}
|
||
|
||
/*******************************************************************************
|
||
* @函数名称 Int2Str
|
||
* @函数说明 字符串转到数据
|
||
* @输入参数 inputstr:需转换的字符串
|
||
* @输出参数 intnum:转好的数据
|
||
* @返回参数 转换结果
|
||
1:正确
|
||
0:错误
|
||
*******************************************************************************/
|
||
/**
|
||
* @brief Get an integer from the HyperTerminal
|
||
* @param num: The inetger
|
||
* @retval 1: Correct
|
||
* 0: Error
|
||
*/
|
||
uint32_t GetIntegerInput(int32_t * num)
|
||
{
|
||
uint8_t inputstr[16];
|
||
|
||
while (1)
|
||
{
|
||
GetInputString(inputstr);
|
||
if (inputstr[0] == '\0') continue;
|
||
if ((inputstr[0] == 'a' || inputstr[0] == 'A') && inputstr[1] == '\0')
|
||
{
|
||
SerialPutString("User Cancelled \r\n");
|
||
return 0;
|
||
}
|
||
|
||
if (Str2Int(inputstr, num) == 0)
|
||
{
|
||
SerialPutString("Error, Input again: \r\n");
|
||
}
|
||
else
|
||
{
|
||
return 1;
|
||
}
|
||
}
|
||
}
|
||
|
||
/*******************************************************************************
|
||
* @函数名称 SerialKeyPressed
|
||
* @函数说明 测试超级终端是否有按键按下
|
||
* @输入参数 key:按键
|
||
* @输出参数 无
|
||
* @返回参数 1:正确
|
||
0:错误
|
||
*******************************************************************************/
|
||
uint32_t SerialKeyPressed(uint8_t *key)
|
||
{
|
||
|
||
if ( USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != RESET)
|
||
{
|
||
*key = (uint8_t)USART1->DR;
|
||
return 1;
|
||
}
|
||
else
|
||
{
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
/*******************************************************************************
|
||
* @函数名称 GetKey
|
||
* @函数说明 通过超级中断回去键码
|
||
* @输入参数 无
|
||
* @输出参数 无
|
||
* @返回参数 按下的键码
|
||
*******************************************************************************/
|
||
uint8_t GetKey(void)
|
||
{
|
||
uint8_t key = 0;
|
||
|
||
//等待按键按下
|
||
while (1)
|
||
{
|
||
if (SerialKeyPressed((uint8_t*)&key)) break;
|
||
}
|
||
return key;
|
||
|
||
}
|
||
|
||
/*******************************************************************************
|
||
* @函数名称 SerialPutChar
|
||
* @函数说明 串口发送一个字符
|
||
* @输入参数 C:需发送的字符
|
||
* @输出参数 i无
|
||
* @返回参数 无
|
||
*******************************************************************************/
|
||
void SerialPutChar(uint8_t c)
|
||
{
|
||
USART_SendData(USART1, c);
|
||
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
|
||
{
|
||
}
|
||
}
|
||
|
||
/*******************************************************************************
|
||
* @函数名称 SerialPutChar
|
||
* @函数说明 串口发送一个字符串
|
||
* @输入参数 *s:需发送的字符串
|
||
* @输出参数 无
|
||
* @返回参数 无
|
||
*******************************************************************************/
|
||
void Serial_PutString(uint8_t *s)
|
||
{
|
||
while (*s != '\0')
|
||
{
|
||
SerialPutChar(*s);
|
||
s++;
|
||
}
|
||
}
|
||
|
||
|
||
/*******************************************************************************
|
||
* @函数名称 GetInputString
|
||
* @函数说明 从串口获取一个字符串
|
||
* @输入参数 *s:存字符串的地址
|
||
* @输出参数 无
|
||
* @返回参数 无
|
||
*******************************************************************************/
|
||
void GetInputString (uint8_t * buffP)
|
||
{
|
||
uint32_t bytes_read = 0;
|
||
uint8_t c = 0;
|
||
do
|
||
{
|
||
c = GetKey();
|
||
if (c == '\r')
|
||
break;
|
||
if (c == '\b')// Backspace 按键
|
||
{
|
||
if (bytes_read > 0)
|
||
{
|
||
SerialPutString("\b \b");
|
||
bytes_read --;
|
||
}
|
||
continue;
|
||
}
|
||
if (bytes_read >= CMD_STRING_SIZE )
|
||
{
|
||
SerialPutString("Command string size overflow\r\n");
|
||
bytes_read = 0;
|
||
continue;
|
||
}
|
||
if (c >= 0x20 && c <= 0x7E)
|
||
{
|
||
buffP[bytes_read++] = c;
|
||
SerialPutChar(c);
|
||
}
|
||
}
|
||
while (1);
|
||
SerialPutString(("\n\r"));
|
||
buffP[bytes_read] = '\0';
|
||
}
|
||
|
||
/*******************************************************************************
|
||
* @函数名称 FLASH_PagesMask
|
||
* @函数说明 计算Falsh页
|
||
* @输入参数 Size:文件长度
|
||
* @输出参数 无
|
||
* @返回参数 页的数量
|
||
*******************************************************************************/
|
||
uint32_t FLASH_PagesMask(__IO uint32_t Size)
|
||
{
|
||
uint32_t pagenumber = 0x0;
|
||
uint32_t size = Size;
|
||
|
||
if ((size % PAGE_SIZE) != 0)
|
||
{
|
||
pagenumber = (size / PAGE_SIZE) + 1;
|
||
}
|
||
else
|
||
{
|
||
pagenumber = size / PAGE_SIZE;
|
||
}
|
||
return pagenumber;
|
||
|
||
}
|
||
|
||
/*******************************************************************************
|
||
* @函数名称 FLASH_DisableWriteProtectionPages
|
||
* @函数说明 接触Flash写保护
|
||
* @输入参数 无
|
||
* @输出参数 无
|
||
* @返回参数 无
|
||
*******************************************************************************/
|
||
|
||
void FLASH_DisableWriteProtectionPages(void)
|
||
{
|
||
uint32_t useroptionbyte = 0, WRPR = 0;
|
||
uint16_t var1 = OB_IWDG_SW, var2 = OB_STOP_NoRST, var3 = OB_STDBY_NoRST;
|
||
FLASH_Status status = FLASH_BUSY;
|
||
|
||
WRPR = FLASH_GetWriteProtectionOptionByte();
|
||
|
||
//测试是否写保护
|
||
if ((WRPR & UserMemoryMask) != UserMemoryMask)
|
||
{
|
||
useroptionbyte = FLASH_GetUserOptionByte();
|
||
|
||
UserMemoryMask |= WRPR;
|
||
|
||
status = FLASH_EraseOptionBytes();
|
||
|
||
if (UserMemoryMask != 0xFFFFFFFF)
|
||
{
|
||
status = FLASH_EnableWriteProtection((uint32_t)~UserMemoryMask);
|
||
}
|
||
//用处选项字是否有编程
|
||
if ((useroptionbyte & 0x07) != 0x07)
|
||
{
|
||
//重新保存选项字
|
||
if ((useroptionbyte & 0x01) == 0x0)
|
||
{
|
||
var1 = OB_IWDG_HW;
|
||
}
|
||
if ((useroptionbyte & 0x02) == 0x0)
|
||
{
|
||
var2 = OB_STOP_RST;
|
||
}
|
||
if ((useroptionbyte & 0x04) == 0x0)
|
||
{
|
||
var3 = OB_STDBY_RST;
|
||
}
|
||
|
||
FLASH_UserOptionByteConfig(var1, var2, var3);
|
||
}
|
||
|
||
if (status == FLASH_COMPLETE)
|
||
{
|
||
SerialPutString("Write Protection disabled...\r\n");
|
||
|
||
SerialPutString("...and a System Reset will be generated to re-load the new option bytes\r\n");
|
||
//系统复位重新加载选项字
|
||
NVIC_SystemReset();
|
||
}
|
||
else
|
||
{
|
||
SerialPutString("Error: Flash write unprotection failed...\r\n");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
SerialPutString("Flash memory not write protected\r\n");
|
||
}
|
||
}
|
||
|
||
/*******************************************************************************
|
||
* @函数名称 Main_Menu
|
||
* @函数说明 显示菜单栏在超级终端
|
||
* @输入参数 无
|
||
* @输出参数 无
|
||
* @返回参数 无
|
||
*******************************************************************************/
|
||
void Main_Menu(void)
|
||
{
|
||
uint8_t key = 0;
|
||
BlockNbr = (FlashDestination - 0x08000000) >> 12;
|
||
|
||
|
||
#if defined (STM32F10X_MD) || defined (STM32F10X_MD_VL)
|
||
UserMemoryMask = ((uint32_t)~((1 << BlockNbr) - 1));
|
||
#else /* USE_STM3210E_EVAL */
|
||
if (BlockNbr < 62)
|
||
{
|
||
UserMemoryMask = ((uint32_t)~((1 << BlockNbr) - 1));
|
||
}
|
||
else
|
||
{
|
||
UserMemoryMask = ((uint32_t)0x80000000);
|
||
}
|
||
#endif /* (STM32F10X_MD) || (STM32F10X_MD_VL) */
|
||
|
||
if ((FLASH_GetWriteProtectionOptionByte() & UserMemoryMask) != UserMemoryMask)
|
||
{
|
||
FlashProtection = 1;
|
||
}
|
||
else
|
||
{
|
||
FlashProtection = 0;
|
||
}
|
||
|
||
while (1)
|
||
{
|
||
SerialPutString("\r\n================== Main Menu ============================\r\n\n");
|
||
SerialPutString(" Download Image To the STM32F10x Internal Flash ------- 1\r\n\n");
|
||
SerialPutString(" Upload Image From the STM32F10x Internal Flash ------- 2\r\n\n");
|
||
SerialPutString(" Execute The New Program ------------------------------ 3\r\n\n");
|
||
|
||
if (FlashProtection != 0)
|
||
{
|
||
SerialPutString(" Disable the write protection ------------------------- 4\r\n\n");
|
||
}
|
||
|
||
SerialPutString("==========================================================\r\n\n");
|
||
|
||
key = GetKey();
|
||
|
||
if (key == 0x31)
|
||
{
|
||
//下载程序
|
||
// SerialDownload();
|
||
}
|
||
else if (key == 0x32)
|
||
{
|
||
//上传程序
|
||
// SerialUpload();
|
||
}
|
||
else if (key == 0x33)
|
||
{
|
||
SerialPutString("Execute user Program\r\n\n");
|
||
JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);
|
||
|
||
//跳转到用户程序
|
||
Jump_To_Application = (pFunction) JumpAddress;
|
||
//初始化用户程序的堆栈指针
|
||
__set_MSP(*(__IO uint32_t*) ApplicationAddress);
|
||
Jump_To_Application();
|
||
}
|
||
else if ((key == 0x34) && (FlashProtection == 1))
|
||
{
|
||
//解除写保护
|
||
FLASH_DisableWriteProtectionPages();
|
||
}
|
||
else
|
||
{
|
||
if (FlashProtection == 0)
|
||
{
|
||
SerialPutString("Invalid Number ! ==> The number should be either 1, 2 or 3\r");
|
||
}
|
||
else
|
||
{
|
||
SerialPutString("Invalid Number ! ==> The number should be either 1, 2, 3 or 4\r");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/*******************************文件结束***************************************/
|