目录
1.eMMC、Nand Flash都属于Flash,Flash的具体类别如下
2.Bootloader在APP程序下载更新或重装中存在的意义
1.eMMC、Nand Flash都属于Flash,Flash的具体类别如下
在单片机板子的Flash中,已预先包含Bootloader和APP程序(Bootloader存在的意义为帮助APP程序实现更新或重装,原因见下文2)
2.Bootloader在APP程序下载更新或重装中存在的意义
3.Bootloader下载更新或重装APP程序的思路框架
上图中第6步的启动程序的具体方法如下图:
4.Bootloader下载更新或重装APP程序代码实现
/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os2.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "draw.h"
#include "stdio.h"
#include "draw.h"
#include "ux_api.h"
#include "modbus.h"
#include "errno.h"
#include "uart_device.h"
#include "semphr.h"
#include "bootloader.h"
#define CFG_OFFSET 0x081FE000
#define SECTOR_SIZE (8*1024)
#define UPDATE_TIMEOUT 1000
static struct UART_Device *g_pUpdateUART;
int isSoftReset(void)
{
return HAL_RCC_GetResetSource() & RCC_RESET_FLAG_SW;
}
uint32_t get_app_vector(void)
{
PFirmwareInfo ptFlashInfo = (PFirmwareInfo)CFG_OFFSET;
return ptFlashInfo->load_addr;
}
static void SoftReset(void)
{
__set_FAULTMASK(1);//关闭所有中断
HAL_NVIC_SystemReset();
}
static void start_app_c(void)
{
/* 触发软件复位 */
SoftReset();
}
static uint32_t BE32toLE32(uint8_t *buf)
{
return ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) | ((uint32_t)buf[2] << 8) | ((uint32_t)buf[3] << 0);
}
static int GetLocalFirmwareInfo(PFirmwareInfo ptFirmwareInfo)
{
volatile PFirmwareInfo ptFlashInfo = (PFirmwareInfo)CFG_OFFSET;
if (ptFlashInfo->file_len == 0xFFFFFFFF)
return -1;
*ptFirmwareInfo = *ptFlashInfo;
return 0;
}
static int GetServerFirmwareInfo(PFirmwareInfo ptFirmwareInfo)
{
uint8_t data = '1';
uint8_t buf[sizeof(FirmwareInfo)];
/* send 0x01 cmd to PC */
if (0 != g_pUpdateUART->Send(g_pUpdateUART, &data, 1, UPDATE_TIMEOUT))
return -1;
/* wait for response */
while (1)
{
if (0 != g_pUpdateUART->RecvByte(g_pUpdateUART, &data, UPDATE_TIMEOUT*10))
return -1;
if (data != 0x5a)
{
buf[0] = data;
break;
}
}
/* get firmware info */
for (int i = 1; i < sizeof(FirmwareInfo); i++)
{
if (0 != g_pUpdateUART->RecvByte(g_pUpdateUART, &buf[i], UPDATE_TIMEOUT))
return -1;
}
ptFirmwareInfo->version = BE32toLE32(&buf[0]);
ptFirmwareInfo->file_len = BE32toLE32(&buf[4]);
ptFirmwareInfo->load_addr = BE32toLE32(&buf[8]);
ptFirmwareInfo->crc32 = BE32toLE32(&buf[12]);
strncpy((char *)ptFirmwareInfo->file_name, (char *)&buf[16], 16);
return 0;
}
static int GetServerFirmware(uint8_t *buf, uint32_t len)
{
uint8_t data = '2';
/* send 0x02 cmd to PC */
if (0 != g_pUpdateUART->Send(g_pUpdateUART, &data, 1, UPDATE_TIMEOUT))
return -1;
/* get firmware info */
for (int i = 0; i < len; i++)
{
if (0 != g_pUpdateUART->RecvByte(g_pUpdateUART, &buf[i], UPDATE_TIMEOUT*10))
return -1;
}
return 0;
}
/* https://lxp32.github.io/docs/a-simple-example-crc32-calculation/ */
static int GetCRC32(const char *s,size_t n)
{
uint32_t crc=0xFFFFFFFF;
for(size_t i=0;i<n;i++) {
char ch=s[i];
for(size_t j=0;j<8;j++) {
uint32_t b=(ch^crc)&1;
crc>>=1;
if(b) crc=crc^0xEDB88320;
ch>>=1;
}
}
return ~crc;
}
static int WriteFirmware(uint8_t *firmware_buf, uint32_t len, uint32_t flash_addr)
{
FLASH_EraseInitTypeDef tEraseInit;
uint32_t SectorError;
uint32_t sectors = (len + (SECTOR_SIZE - 1)) / SECTOR_SIZE;
uint32_t flash_offset = flash_addr - 0x08000000;
uint32_t bank_sectors;
uint32_t erased_sectors = 0;
HAL_FLASH_Unlock();
/* erase bank1 */
if (flash_offset < 0x100000)
{
tEraseInit.TypeErase = FLASH_TYPEERASE_SECTORS;
tEraseInit.Banks = FLASH_BANK_1;
tEraseInit.Sector = flash_offset / SECTOR_SIZE;
bank_sectors = (0x100000 - flash_offset) / SECTOR_SIZE;
if (sectors <= bank_sectors)
erased_sectors = sectors;
else
erased_sectors = bank_sectors;
tEraseInit.NbSectors = erased_sectors;
if (HAL_OK != HAL_FLASHEx_Erase(&tEraseInit, &SectorError))
{
g_pUpdateUART->Send(g_pUpdateUART, (uint8_t *)"HAL_FLASHEx_Erase Failed\r\n", strlen("HAL_FLASHEx_Erase Failed\r\n"), UPDATE_TIMEOUT);
HAL_FLASH_Lock();
return -1;
}
flash_offset += erased_sectors*SECTOR_SIZE;
}
sectors -= erased_sectors;
flash_offset -= 0x100000;
/* erase bank2 */
if (sectors)
{
tEraseInit.TypeErase = FLASH_TYPEERASE_SECTORS;
tEraseInit.Banks = FLASH_BANK_2;
tEraseInit.Sector = flash_offset / SECTOR_SIZE;
bank_sectors = (0x100000 - flash_offset) / SECTOR_SIZE;
if (sectors <= bank_sectors)
erased_sectors = sectors;
else
erased_sectors = bank_sectors;
tEraseInit.NbSectors = erased_sectors;
if (HAL_OK != HAL_FLASHEx_Erase(&tEraseInit, &SectorError))
{
g_pUpdateUART->Send(g_pUpdateUART, (uint8_t *)"HAL_FLASHEx_Erase Failed\r\n", strlen("HAL_FLASHEx_Erase Failed\r\n"), UPDATE_TIMEOUT);
HAL_FLASH_Lock();
return -1;
}
}
/* program */
len = (len + 15) & ~15;
for (int i = 0; i < len; i+=16)
{
if (HAL_OK != HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, flash_addr, (uint32_t)firmware_buf))
{
g_pUpdateUART->Send(g_pUpdateUART, (uint8_t *)"HAL_FLASH_Program Failed\r\n", strlen("HAL_FLASH_Program Failed\r\n"), UPDATE_TIMEOUT);
HAL_FLASH_Lock();
return -1;
}
flash_addr += 16;
firmware_buf += 16;
}
HAL_FLASH_Lock();
return 0;
}
static int WriteFirmwareInfo(PFirmwareInfo ptFirmwareInfo)
{
FLASH_EraseInitTypeDef tEraseInit;
uint32_t SectorError;
uint32_t flash_addr = CFG_OFFSET;
uint8_t *src_buf = (uint8_t *)ptFirmwareInfo;
HAL_FLASH_Unlock();
/* erase bank2 */
tEraseInit.TypeErase = FLASH_TYPEERASE_SECTORS;
tEraseInit.Banks = FLASH_BANK_2;
tEraseInit.Sector = (flash_addr - 0x08000000 - 0x100000) / SECTOR_SIZE;
tEraseInit.NbSectors = 1;
if (HAL_OK != HAL_FLASHEx_Erase(&tEraseInit, &SectorError))
{
g_pUpdateUART->Send(g_pUpdateUART, (uint8_t *)"HAL_FLASHEx_Erase Failed\r\n", strlen("HAL_FLASHEx_Erase Failed\r\n"), UPDATE_TIMEOUT);
HAL_FLASH_Lock();
return -1;
}
/* program */
for (int i = 0; i < sizeof(FirmwareInfo); i+=16)
{
if (HAL_OK != HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, flash_addr, (uint32_t)src_buf))
{
g_pUpdateUART->Send(g_pUpdateUART, (uint8_t *)"HAL_FLASH_Program Failed\r\n", strlen("HAL_FLASH_Program Failed\r\n"), UPDATE_TIMEOUT);
HAL_FLASH_Lock();
return -1;
}
flash_addr += 16;
src_buf += 16;
}
HAL_FLASH_Lock();
return 0;
}
void BootLoaderTask( void *pvParameters )
{
struct UART_Device *pUSBUART = GetUARTDevice("usb");
FirmwareInfo tLocalInfo;
FirmwareInfo tServerInfo;
int err;
int need_update = 0;
uint8_t *firmware_buf;
vTaskDelay(10000); /* wait for pc ready */
pUSBUART->Init(pUSBUART, 115200, 'N', 8, 1);
g_pUpdateUART = pUSBUART;
while (1)
{
/* read cfg info, to detect app's version */
err = GetLocalFirmwareInfo(&tLocalInfo);
if (err)
{
/* update */
need_update = 1;
}
else
{
pUSBUART->Send(pUSBUART, (uint8_t *)"GetLocalFirmwareInfo OK\r\n", strlen("GetLocalFirmwareInfo OK\r\n"), UPDATE_TIMEOUT);
}
err = GetServerFirmwareInfo(&tServerInfo);
if (!err)
{
/* compare version */
if (tServerInfo.version > tLocalInfo.version)
{
/* update */
need_update = 1;
}
}
else
{
need_update = 0;
pUSBUART->Send(pUSBUART, (uint8_t *)"GetServerFirmwareInfo Failed\r\n", strlen("GetServerFirmwareInfo Failed\r\n"), UPDATE_TIMEOUT);
}
if (need_update)
{
firmware_buf = pvPortMalloc(tServerInfo.file_len);
if (!firmware_buf)
{
/* error */
pUSBUART->Send(pUSBUART, (uint8_t *)"Malloc Failed\r\n", strlen("Malloc Failed\r\n"), UPDATE_TIMEOUT);
}
err = GetServerFirmware(firmware_buf, tServerInfo.file_len);
if (!err)
{
/* calc CRC */
uint32_t crc = GetCRC32((const char *)firmware_buf, tServerInfo.file_len);
if (crc == tServerInfo.crc32)
{
/* OK */
/* burn */
pUSBUART->Send(pUSBUART, (uint8_t *)"Download OK\r\n", 13, UPDATE_TIMEOUT);
WriteFirmware(firmware_buf, tServerInfo.file_len, tServerInfo.load_addr);
WriteFirmwareInfo(&tServerInfo);
/* start app */
pUSBUART->Send(pUSBUART, (uint8_t *)"Start app\r\n", strlen("Start app"), UPDATE_TIMEOUT);
start_app_c();
}
else
{
pUSBUART->Send(pUSBUART, (uint8_t *)"GetCRC32 Failed\r\n", strlen("GetCRC32 Failed\r\n"), UPDATE_TIMEOUT);
}
}
else
{
pUSBUART->Send(pUSBUART, (uint8_t *)"GetServerFirmware Failed\r\n", strlen("GetServerFirmware Failed\r\n"), UPDATE_TIMEOUT);
}
}
else
{
/* start app */
pUSBUART->Send(pUSBUART, (uint8_t *)"Start app\r\n", strlen("Start app"), UPDATE_TIMEOUT);
start_app_c();
}
}
}
标签:Flash,HAL,pUSBUART,APP,FLASH,uint8,return,Bootloader,buf
From: https://blog.csdn.net/qq_45031559/article/details/140426083