
/*************************************************************
Function : IAP_Init
Description: IAP初始化函数,初始化串口1
Input : none
return : none
*************************************************************/
void IAP_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(COM1_RCC, ENABLE);//使能 USART2 时钟
RCC_APB2PeriphClockCmd(COM1_GPIO_RCC, ENABLE);//使能串口2引脚时钟
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//配置 USART2 的Tx 引脚类型为推挽式的
GPIO_InitStructure.GPIO_Pin = COM1_TX_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(COM1_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//配置 USART2 的Rx 为输入悬空
GPIO_InitStructure.GPIO_Pin = COM1_RX_PIN;
GPIO_Init(COM1_GPIO_PORT, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 115200;//设置波特率为115200
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//设置数据位为8位
USART_InitStructure.USART_StopBits = USART_StopBits_1;//设置停止位为1位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //没有硬件流控
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//发送与接收
USART_Init(COM1,&USART_InitStructure);//串口2相关寄存器的配置
USART_Cmd(COM1,ENABLE);//使能串口2
}
/*************************************************************
Function : IAP_SerialSendByte
Description: 串口发送字节
Input : c-要发送的字节
return : none
*************************************************************/
void IAP_SerialSendByte(u8 c)
{
USART_SendData(COM1, c);
while (USART_GetFlagStatus(COM1, USART_FLAG_TXE) == RESET) {}
}
/*************************************************************
Function : IAP_SerialSendStr
Description: 串口发送字符串
Input : none
return : none
*************************************************************/
void IAP_SerialSendStr(u8 *s)
{
while(*s != '\0')
{
IAP_SerialSendByte(*s);
s++;
}
}
/*************************************************************
Function : IAP_SerialGetByte
Description: 接收一个字节数据
Input : none
return : 返回结果值,0-没有接收到数据;1-接收到数据
*************************************************************/
u8 IAP_SerialGetByte(u8 *c)
{
if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != RESET)
{
*c = USART_ReceiveData(USART1);
return 1;
}
return 0;
}
/*************************************************************
Function : IAP_GetKey
Description: 获取键入值
Input : none
return : 返回键值
*************************************************************/
u8 IAP_GetKey(void)
{
u8 data;
while(!IAP_SerialGetByte(&data)){ }
return data;
}
/*************************************************************
Function : IAP_ShowMenu
Description: 显示菜单界面
Input : none
return : none
*************************************************************/
void IAP_ShowMenu(void)
{
IAP_SerialSendStr("\r\n+================(C) COPYRIGHT 2014 Ziye334 ================+");
IAP_SerialSendStr("\r\n| In-Application Programing Application (Version 1.0) |");
IAP_SerialSendStr("\r\n+----command----+-----------------function------------------+");
IAP_SerialSendStr("\r\n| 1: FWUPDATA | Update the firmware to flash by YModem |");
IAP_SerialSendStr("\r\n| 2: FWDWLOAD | Download the firmware from Flash by YModem|");
IAP_SerialSendStr("\r\n| 3: FWERASE | Erase the current firmware |");
IAP_SerialSendStr("\r\n| 4: BOOT | Excute the current firmware |");
IAP_SerialSendStr("\r\n| 5:REBOOT | Reboot |");
IAP_SerialSendStr("\r\n| ?: HELP | Display this help |");
IAP_SerialSendStr("\r\n+===========================================================+");
IAP_SerialSendStr("\r\n\r\n");
IAP_SerialSendStr("STM32-IAP>>");
}
/*************************************************************
Function : IAP_DisableFlashWPR
Description: 关闭flash的写保护
Input : none
return : none
*************************************************************/
void IAP_DisableFlashWPR(void)
{
u32 blockNum = 0, UserMemoryMask = 0;
blockNum = (IAP_ADDR - FLASH_BASE_ADDR) >> 12; //计算flash块
UserMemoryMask = ((u32)(~((1 << blockNum) - 1)));//计算掩码
if((FLASH_GetWriteProtectionOptionByte() & UserMemoryMask) != UserMemoryMask)//查看块所在区域是否写保护
{
FLASH_EraseOptionBytes ();//擦除选择位
}
}
s8 IAP_UpdataParam(s32 *param)
{
u32 i;
u32 flashptr = IAP_PARAM_ADDR;
FLASH_Unlock();//flash上锁
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);//清除flash相关标志位
for(i = 0; i < IAP_PARAM_SIZE; i++)
{
FLASH_ProgramWord(flashptr + 4 * i, *param);
if(*(u32 *)(flashptr + 4 * i) != *param)
{
return -1;
}
param++;
}
FLASH_Lock();//flash解锁
return 0;
}
/*************************************************************
Function : IAP_UpdataProgram
Description: 升级程序
Input : addr-烧写的地址 size-大小
return : 0-OK 1-error
*************************************************************/
s8 IAP_UpdataProgram(u32 addr, u32 size)
{
u32 i;
static u32 flashptr = IAP_ADDR;
FLASH_Unlock();//flash上锁
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);//清除flash相关标志位
for(i = 0; i < size; i += 4)
{
FLASH_ProgramWord(flashptr, *(u32 *)addr);//烧写1个字
if(*(u32 *)flashptr != *(u32 *)addr)//判断是否烧写成功
{
return -1;
}
flashptr += 4;
addr += 4;
}
FLASH_Lock();//flash解锁
return 0;
}
/*************************************************************
Function : IAP_FlashEease
Description: 擦除Flash
Input : size-擦除的大小
return : none
*************************************************************/
void IAP_FlashEease(u32 size)
{
u16 eraseCounter = 0;
u16 nbrOfPage = 0;
FLASH_Status FLASHStatus = FLASH_COMPLETE;
if(size % PAGE_SIZE != 0)//计算需要擦写的页数
{
nbrOfPage = size / PAGE_SIZE + 1;
}
else
{
nbrOfPage = size / PAGE_SIZE;
}
FLASH_Unlock();//解除flash擦写锁定
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);//清除flash相关标志位
for(eraseCounter = 0; (eraseCounter < nbrOfPage) && ((FLASHStatus == FLASH_COMPLETE)); eraseCounter++)//开始擦除
{
FLASHStatus = FLASH_ErasePage(IAP_ADDR + (eraseCounter * PAGE_SIZE));//擦除
IAP_SerialSendStr(".");//打印'.'以显示进度
}
FLASH_ErasePage(IAP_PARAM_ADDR);//擦除参数所在的flash页
FLASH_Lock();//flash擦写锁定
}
typedef void (*pFunction)(void);
pFunction Jump_To_Application;
/*************************************************************
Function : IAP_JumpToApplication
Description: 跳转到升级程序处
Input : none
return : none
*************************************************************/
void IAP_JumpToApplication(void)
{
u32 JumpAddress;//跳转地址
if(((*(__IO u32 *)IAP_ADDR) & 0x2FFE0000) == 0x20000000)//有升级代码,IAP_ADDR地址处理应指向主堆栈区,即0x20000000
{
JumpAddress = *(__IO u32 *)(IAP_ADDR + 4);//获取复位地址
Jump_To_Application = (pFunction)JumpAddress;//函数指针指向复位地址
__set_MSP(*(__IO u32*)IAP_ADDR);//设置主堆栈指针MSP指向升级机制IAP_ADDR
Jump_To_Application();//跳转到升级代码处
}
}
/*************************************************************
Function : ShwHelpInfo
Description: 显示帮助信息
Input : none
return : none
*************************************************************/
static void ShwHelpInfo(void)
{
IAP_SerialSendStr("\r\nEnter '1' to updtate you apllication code!");
IAP_SerialSendStr("\r\nRnter '2' to download the firmware from interal flash!");
IAP_SerialSendStr("\r\nRnter '3' to erase the current application code!");
IAP_SerialSendStr("\r\nEnter '4' to go to excute the current application code!");
IAP_SerialSendStr("\r\nEnter '5' to restart the system!");
IAP_SerialSendStr("\r\nEnter '?' to show the help infomation!\r\n");
}
/*************************************************************
Function : IAP_WiatForChoose
Description: 功能选择
Input : none
return : none
*************************************************************/
void IAP_WiatForChoose(void)
{
u8 c = 0;
while (1)
{
c = IAP_GetKey();//获取键值
转自: