123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505 |
- #include "leaf_ota.h"
- #include "usart.h"
- #include "stdio.h"
- #include "string.h"
- #include "TerminalSlave485.h"
- #include "md5c.h"
- #include "main.h"
- /**
- * @brief 根据输入的地址给出它所在的sector
- * 例如:
- uwStartSector = GetSector(FLASH_USER_START_ADDR);
- uwEndSector = GetSector(FLASH_USER_END_ADDR);
- * @param Address:地址
- * @retval 地址所在的sector
- */
- static uint32_t GetSector(uint32_t Address)
- {
- uint32_t sector = 0;
-
- if((Address < ADDR_FLASH_SECTOR_1) && (Address >= ADDR_FLASH_SECTOR_0))
- {
- sector = FLASH_SECTOR_0;
- }
- else if((Address < ADDR_FLASH_SECTOR_2) && (Address >= ADDR_FLASH_SECTOR_1))
- {
- sector = FLASH_SECTOR_1;
- }
- else if((Address < ADDR_FLASH_SECTOR_3) && (Address >= ADDR_FLASH_SECTOR_2))
- {
- sector = FLASH_SECTOR_2;
- }
- else if((Address < ADDR_FLASH_SECTOR_4) && (Address >= ADDR_FLASH_SECTOR_3))
- {
- sector = FLASH_SECTOR_3;
- }
- else if((Address < ADDR_FLASH_SECTOR_5) && (Address >= ADDR_FLASH_SECTOR_4))
- {
- sector = FLASH_SECTOR_4;
- }
- else if((Address < ADDR_FLASH_SECTOR_6) && (Address >= ADDR_FLASH_SECTOR_5))
- {
- sector = FLASH_SECTOR_5;
- }
- else if((Address < ADDR_FLASH_SECTOR_7) && (Address >= ADDR_FLASH_SECTOR_6))
- {
- sector = FLASH_SECTOR_6;
- }
- else/*(Address < FLASH_END_ADDR) && (Address >= ADDR_FLASH_SECTOR_23))*/
- {
- sector = FLASH_SECTOR_7;
- }
- return sector;
- }
- //uint8_t Erase_page(uint32_t pageaddr, uint32_t num)
- //{
- // /*要擦除的起始扇区(包含)及结束扇区(不包含),如8-12,表示擦除8、9、10、11扇区*/
- // uint32_t FirstSector = 0;
- // uint32_t NbOfSectors = 0;
- // uint32_t SECTORError = 0;
- // static FLASH_EraseInitTypeDef EraseInitStruct;
- // __disable_irq();
- // HAL_FLASH_Unlock();
- //
- // FirstSector = GetSector(pageaddr);
- // NbOfSectors = GetSector(num)- FirstSector + 1;
- // /* 擦除用户区域 (用户区域指程序本身没有使用的空间,可以自定义)**/
- // /* Fill EraseInit structure*/
- // EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
- // EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;/* 以“字”的大小进行操作 */
- // EraseInitStruct.Sector = FirstSector;
- // EraseInitStruct.NbSectors = 1;
- // /* 开始擦除操作 */
- // if (HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError) != HAL_OK)
- // {
- // /*擦除出错,返回,实际应用中可加入处理 */
- // return -1;
- // }
- //
- //
- // HAL_FLASH_Lock();
- // __enable_irq();
- // return 1;
- //}
- int App2_MD5_Check(uint32_t addr,unsigned int all_len)
- {
- unsigned char digest[16];
- // unsigned char *md5_ptr=(unsigned char *)(StartMode_Addr+72);
- unsigned int i,update_len;
- MD5_CTX md5c;
- all_len -= 16;
- MD5Init(&md5c);
- for(i=0;i<all_len;)
- {
- if(all_len>(i+512))
- update_len = 512;
- else
- update_len = all_len-i;
- memcpy(USART1_TX_BUF,(const void *)(addr+i),update_len);
- MD5Update (&md5c, USART1_TX_BUF, update_len);
- i += update_len;
- HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
- }
- MD5Final(digest,&md5c);
- memcpy(USART1_TX_BUF,(const void *)(addr+all_len),16);
- for(i=0;i<16;++i)
- {
- if(digest[i]!=USART1_TX_BUF[i])
- break;
- }
- if(i>=16)
- return 1;
- else
- return 0;
- }
- /**
- * @bieaf 擦除页
- *
- * @param pageaddr 起始地址
- * @param num 擦除的页数
- * @return 1
- */
- uint8_t Erase_page(uint32_t pageaddr, uint32_t num)
- {
- __disable_irq();
- HAL_FLASH_Unlock();
-
- /* 擦除FLASH*/
- FLASH_EraseInitTypeDef FlashSet;
- FlashSet.TypeErase = FLASH_TYPEERASE_SECTORS;
- FlashSet.VoltageRange = FLASH_VOLTAGE_RANGE_3;
- FlashSet.Sector = GetSector(pageaddr);
- //FlashSet.NbSectors =(pageaddr+num-1);
- FlashSet.NbSectors=1;
- /*设置PageError,调用擦除函数*/
- uint32_t PageError = 0;
- HAL_FLASHEx_Erase(&FlashSet, &PageError);
-
- HAL_FLASH_Lock();
- __enable_irq();
- return 1;
- }
- /**
- * @bieaf 写若干个数据
- *
- * @param addr 写入的地址
- * @param buff 写入数据的起始地址
- * @param word_size 长度
- * @return
- */
- static void WriteFlash(uint32_t addr, uint32_t * buff, int word_size)
- {
- /* 1/4解锁FLASH*/
- HAL_FLASH_Unlock();
-
- for(int i = 0; i < word_size; i++)
- {
- /* 3/4对FLASH烧写*/
- HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr + 4 * i, buff[i]);
- }
- /* 4/4锁住FLASH*/
- HAL_FLASH_Lock();
- }
- /**
- * @bieaf 读若干个数据
- *
- * @param addr 读数据的地址
- * @param buff 读出数据的数组指针
- * @param word_size 长度
- * @return
- */
- static void ReadFlash(uint32_t addr, uint32_t * buff, uint16_t word_size)
- {
- //uint32_t get=0;
- for(int i =0; i < word_size; i++)
- {
- buff[i] = *(__IO uint32_t*)(addr + 4 * i);
- //buff[i] =((get&0x000000ff)<< 24)| ((get&0x0000ff00 ) << 8 )| (( get&0x00ff0000 ) >> 8 ) | ((get&0xff000000 )>> 24 );
- }
- return;
- }
- /* 读取启动模式 */
- unsigned int Read_Start_Mode(void)
- {
- unsigned int mode = 0;
- //ReadFlash((Application_2_Addr + Application_Size - 4), &mode, 1);
- ReadFlash(StartMode_Addr, &mode, 1);
-
- return mode;
- }
- /**
- * @bieaf 写若干个数据
- *
- * @param addr 写入的地址
- * @param buff 写入数据的起始地址
- * @param word_size 长度
- * @return
- */
- void WriteFlash2(uint32_t addr, uint32_t *buff, int word_size)
- {
- /* 1/4解锁FLASH*/
- HAL_FLASH_Unlock();
- for(int i = 0; i < word_size; i++)
- {
- /* 3/4对FLASH烧写*/
- HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr + 4 * i, buff[i]);
- }
- /* 4/4锁住FLASH*/
- HAL_FLASH_Lock();
- }
- /* 标记升级完成 */
- void Set_Update_Down(void)
- {
- unsigned int update_flag = Startup_Update; ///< 对应bootloader的启动步骤
- memcpy(USART1_TX_BUF,(void *)StartMode_Addr,256);
- memcpy(USART1_TX_BUF,&update_flag,4);
- Erase_page(StartMode_Addr, Appear_si);
- WriteFlash2(StartMode_Addr, (uint32_t *)USART1_TX_BUF, 64);
- }
- /**
- * @bieaf 进行程序的覆盖
- * @detail 1.擦除目的地址
- * 2.源地址的代码拷贝到目的地址
- * 3.擦除源地址
- *
- * @param 搬运的源地址
- * @param 搬运的目的地址
- * @return 搬运的程序大小
- */
- void MoveCode(unsigned int src_addr, unsigned int des_addr, unsigned int byte_size)
- {
- /*1.擦除目的地址*/
- //printf("> Start erase des flash......\r\n");
- //Erase_page(des_addr, (byte_size/PageSize));
- HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
- Erase_page(des_addr, Appear_si);
- HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
- //printf("> Erase des flash down......\r\n");
-
- /*2.开始拷贝*/
- unsigned int temp[128]={0};
-
- //printf("> Start copy......\r\n");
- for(int i = 0; i < (byte_size+511)/512; i++)
- {
- HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
- ReadFlash((src_addr + i*512), temp, 128);
- HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
- WriteFlash((des_addr + i*512), temp, 128);
- HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
- }
- //printf("> Copy down......\r\n");
-
- /*3.擦除源地址*/
- //printf("> Start erase src flash......\r\n");
- //Erase_page(src_addr, (byte_size/PageSize));
- HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
- ;//Erase_page(src_addr, Appear_si);
- HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
-
- //HAL_NVIC_SystemReset();
- //printf("> Erase src flash down......\r\n");
-
- }
- ///* 采用汇编设置栈的值 */
- //__asm void MSR_MSP (uint32_t ulAddr)
- //{
- // MSR MSP, r0 //set Main Stack value
- // BX r14
- //}
- ///* 程序跳转函数 */
- //typedef void (*Jump_Fun)(void);
- //void IAP_ExecuteApp (uint32_t App_Addr)
- //{
- // Jump_Fun JumpToApp;
- //
- //// if ( ( ( * ( __IO uint32_t * ) App_Addr ) & 0x2FE00000 ) == 0x20000000 ) //检查栈顶地址是否合法.
- //// {
- // JumpToApp = (Jump_Fun) * ( __IO uint32_t *)(App_Addr + 4); //用户代码区第二个字为程序开始地址(复位地址)
- // MSR_MSP( * ( __IO uint32_t * ) App_Addr ); //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
- // __disable_irq();
- // JumpToApp(); //跳转到APP.
- //// }
- //}
- /*
- *********************************************************************************************************
- * 函 数 名: JumpToBootloader
- * 功能说明: 跳转到系统BootLoader
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void JumpToBootloader(void)
- {
- uint32_t i=0;
- GPIO_InitTypeDef GPIO_InitStruct = {0};
- void (*SysMemBootJump)(void); /* 声明一个函数指针 */
- __IO uint32_t BootAddr = Application_1_Addr; /* STM32F4的系统BootLoader地址 */
-
-
- HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
- /* 关闭全局中断 */
- DISABLE_INT();
- /* 关闭滴答定时器,复位到默认值 */
- SysTick->CTRL = 0;
- SysTick->LOAD = 0;
- SysTick->VAL = 0;
-
- HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
- /* 设置所有时钟到默认状态,使用HSI时钟 */
- HAL_RCC_DeInit();
-
- __HAL_RCC_GPIOC_CLK_ENABLE();
-
-
- //看门狗配置 初始化
- /*Configure GPIO pin : PtPin */
- GPIO_InitStruct.Pin = GPIO_PIN_2;
-
- if(0)//看门狗sp706
- //if(1)//打开看门狗sp706
- {
- //
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
-
- }
- else
- {
- GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
-
- }
-
-
-
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
- HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
-
-
-
- // HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
- /* 关闭所有中断,清除所有中断挂起标志 */
- for (i = 0; i < 8; i++)
- {
- NVIC->ICER[i]=0xFFFFFFFF;
- NVIC->ICPR[i]=0xFFFFFFFF;
- }
-
- // HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
- /* 使能全局中断 */
- ENABLE_INT();
- /* 跳转到系统BootLoader,首地址是MSP,地址+4是复位中断服务程序地址 */
- SysMemBootJump = (void (*)(void)) (*((uint32_t *) (BootAddr + 4)));
- /* 设置主堆栈指针 */
- __set_MSP(*(uint32_t *)BootAddr);
-
- // /* 在RTOS工程,这条语句很重要,设置为特权级模式,使用MSP指针 */
- __set_CONTROL(0);
- /* 跳转到系统BootLoader */
- // HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
- SysMemBootJump();
- /* 跳转成功的话,不会执行到这里,用户可以在这里添加代码 */
- while (1)
- {
- }
- }
- /**
- * @bieaf 进行BootLoader的启动
- *
- * @param none
- * @return none
- */
- void Start_BootLoader(void)
- {
- unsigned int update_flag = 0xAAAAAAAA; ///< 对应bootloader的启动步骤
- unsigned int ModeStart;
- unsigned int i,all_len;
- // HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
-
- ModeStart=Read_Start_Mode();
- switch(ModeStart) ///< 读取是否启动应用程序 */
- {
- case Startup_Normal: ///< 正常启动 */ //在APP2中可以设定此标志位 使得下次重启之后进入APP1
- {
- ;//printf("> Normal start......\r\n");
- break;
- }
- case Startup_Update: ///< 升级再启动 */
- {
-
- HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2); //看门狗sp706
- for (i = 0, all_len = 0; i < 4; ++i)
- {
- all_len = all_len << 8;
- all_len |= *(unsigned char *)(StartMode_Addr + 68 + i);
- }
- if ((*(unsigned int*)(Application_Buffer_Addr+6144)==Application_2_Addr) && App2_MD5_Check(Application_Buffer_Addr,all_len))
- {
- MoveCode(Application_Buffer_Addr, Application_2_Addr, all_len);//假定程序大小为100k
- HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
- // printf("> Update down......\r\n");
-
- update_flag = Startup_APP2;
- memcpy(USART1_TX_BUF,(void *)StartMode_Addr,256);
- Erase_page(StartMode_Addr, Appear_si);
- memcpy(USART1_TX_BUF,&update_flag,4);
- memcpy(USART1_TX_BUF+132,USART1_TX_BUF+68,4);
- WriteFlash2(StartMode_Addr, (uint32_t *)USART1_TX_BUF, 64);
- HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);
- /*for (i = 0, all_len = 0; i < 4; ++i)
- {
- all_len = all_len << 8;
- all_len |= *(unsigned char *)(StartMode_Addr + 68 + i);
- }
- if(App2_MD5_Check(Application_2_Addr,all_len))
- JumpToAPP2();//
- */
- }
- // break;
- }
- case Startup_APP2: ///跳转到APP2
- {
- for (i = 0, all_len = 0; i < 4; ++i)
- {
- all_len = all_len << 8;
- all_len |= *(unsigned char *)(StartMode_Addr + 132 + i);
- }
- if((*(unsigned int*)(Application_2_Addr+6144)==Application_2_Addr) && App2_MD5_Check(Application_2_Addr,all_len))
- JumpToAPP2();//
- break;
- }
-
-
- case Startup_Reset: ///< 恢复出厂设置 目前没使用 */
- {
- // printf("> Restore to factory program......\r\n");
- break;
- }
- default: ///< 启动失败
- {
- // printf("> Error:%X!!!......\r\n", Read_Start_Mode());
- return;
- }
- }
-
- // /* 跳转到应用程序 */
- //// HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
- // printf("> Start up......\r\n\r\n");
- // //IAP_ExecuteApp(Application_1_Addr);
- // JumpToBootloader();
- }
|