2025-02-03 20:43:43 +08:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
|
|
|
|
* exclusively with CVA's microcontroller products. This file can be freely
|
|
|
|
* distributed within development tools that are supporting such microcontroller
|
|
|
|
* products.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
|
|
|
|
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
|
|
|
|
* CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
|
|
|
|
* OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* the includes
|
|
|
|
******************************************************************************/
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "bootloader_cfg.h"
|
|
|
|
#include "fls.h"
|
|
|
|
#include "bootloader.h"
|
|
|
|
#include "uds.h"
|
|
|
|
#include "uds_user.h"
|
|
|
|
#include "mcu.h"
|
|
|
|
#include "SEGGER_RTT.h"
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* the defines
|
|
|
|
******************************************************************************/
|
|
|
|
static bool Bootloader_GetBootReq(void);
|
|
|
|
static uint32_t Bootloader_CalculateCheckSum(uint32_t initCrcValue, const uint8_t *dataBuffer, uint32_t bytesNum, bool inverted);
|
|
|
|
static void Bootloader_JumpToApp(void);
|
|
|
|
static void Bootloader_Reset(void);
|
|
|
|
static void Bootloader_InitState(void);
|
|
|
|
static void Bootloader_EraseState(void);
|
|
|
|
static void Bootloader_PgmState(void);
|
|
|
|
static void Bootloader_CheckState(void);
|
|
|
|
static void Bootloader_ExitState(void);
|
|
|
|
static void Bootloader_ErrorState(void);
|
|
|
|
|
|
|
|
extern McuType mcu;
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* the typedefs
|
|
|
|
******************************************************************************/
|
|
|
|
typedef void (*pBootloader_StateFun)(void);
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* the globals
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
#pragma location = ".no_init"
|
|
|
|
static uint32_t sBootloader_Req;
|
|
|
|
|
|
|
|
#pragma location = ".bootloaderInfo"
|
|
|
|
__root const Bootloade_CfgInfoType sBootloader_Version = {
|
|
|
|
.HWVersion = "HW01",
|
|
|
|
.BLVersion = "BL0101",
|
|
|
|
.bootBuildDate = __DATE__,
|
|
|
|
.bootBuildTime = __TIME__,
|
2025-02-05 00:13:59 +08:00
|
|
|
.ECUName = "WK-K86",
|
2025-02-03 20:43:43 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static Bootloader_CbType sBootloader_Cb;
|
|
|
|
|
|
|
|
pBootloader_StateFun sBootloader_StateFuncTbl[BOOTLOADER_STATE_NUM] = {
|
|
|
|
Bootloader_InitState,
|
|
|
|
Bootloader_EraseState,
|
|
|
|
Bootloader_PgmState,
|
|
|
|
Bootloader_ErrorState,
|
|
|
|
Bootloader_CheckState,
|
|
|
|
Bootloader_ExitState};
|
|
|
|
|
|
|
|
static const unsigned int crc32_table[] = {
|
|
|
|
0x00000000uL,
|
|
|
|
0x77073096uL,
|
|
|
|
0xEE0E612CuL,
|
|
|
|
0x990951BAuL,
|
|
|
|
0x076DC419uL,
|
|
|
|
0x706AF48FuL,
|
|
|
|
0xE963A535uL,
|
|
|
|
0x9E6495A3uL,
|
|
|
|
0x0EDB8832uL,
|
|
|
|
0x79DCB8A4uL,
|
|
|
|
0xE0D5E91EuL,
|
|
|
|
0x97D2D988uL,
|
|
|
|
0x09B64C2BuL,
|
|
|
|
0x7EB17CBDuL,
|
|
|
|
0xE7B82D07uL,
|
|
|
|
0x90BF1D91uL,
|
|
|
|
0x1DB71064uL,
|
|
|
|
0x6AB020F2uL,
|
|
|
|
0xF3B97148uL,
|
|
|
|
0x84BE41DEuL,
|
|
|
|
0x1ADAD47DuL,
|
|
|
|
0x6DDDE4EBuL,
|
|
|
|
0xF4D4B551uL,
|
|
|
|
0x83D385C7uL,
|
|
|
|
0x136C9856uL,
|
|
|
|
0x646BA8C0uL,
|
|
|
|
0xFD62F97AuL,
|
|
|
|
0x8A65C9ECuL,
|
|
|
|
0x14015C4FuL,
|
|
|
|
0x63066CD9uL,
|
|
|
|
0xFA0F3D63uL,
|
|
|
|
0x8D080DF5uL,
|
|
|
|
0x3B6E20C8uL,
|
|
|
|
0x4C69105EuL,
|
|
|
|
0xD56041E4uL,
|
|
|
|
0xA2677172uL,
|
|
|
|
0x3C03E4D1uL,
|
|
|
|
0x4B04D447uL,
|
|
|
|
0xD20D85FDuL,
|
|
|
|
0xA50AB56BuL,
|
|
|
|
0x35B5A8FAuL,
|
|
|
|
0x42B2986CuL,
|
|
|
|
0xDBBBC9D6uL,
|
|
|
|
0xACBCF940uL,
|
|
|
|
0x32D86CE3uL,
|
|
|
|
0x45DF5C75uL,
|
|
|
|
0xDCD60DCFuL,
|
|
|
|
0xABD13D59uL,
|
|
|
|
0x26D930ACuL,
|
|
|
|
0x51DE003AuL,
|
|
|
|
0xC8D75180uL,
|
|
|
|
0xBFD06116uL,
|
|
|
|
0x21B4F4B5uL,
|
|
|
|
0x56B3C423uL,
|
|
|
|
0xCFBA9599uL,
|
|
|
|
0xB8BDA50FuL,
|
|
|
|
0x2802B89EuL,
|
|
|
|
0x5F058808uL,
|
|
|
|
0xC60CD9B2uL,
|
|
|
|
0xB10BE924uL,
|
|
|
|
0x2F6F7C87uL,
|
|
|
|
0x58684C11uL,
|
|
|
|
0xC1611DABuL,
|
|
|
|
0xB6662D3DuL,
|
|
|
|
0x76DC4190uL,
|
|
|
|
0x01DB7106uL,
|
|
|
|
0x98D220BCuL,
|
|
|
|
0xEFD5102AuL,
|
|
|
|
0x71B18589uL,
|
|
|
|
0x06B6B51FuL,
|
|
|
|
0x9FBFE4A5uL,
|
|
|
|
0xE8B8D433uL,
|
|
|
|
0x7807C9A2uL,
|
|
|
|
0x0F00F934uL,
|
|
|
|
0x9609A88EuL,
|
|
|
|
0xE10E9818uL,
|
|
|
|
0x7F6A0DBBuL,
|
|
|
|
0x086D3D2DuL,
|
|
|
|
0x91646C97uL,
|
|
|
|
0xE6635C01uL,
|
|
|
|
0x6B6B51F4uL,
|
|
|
|
0x1C6C6162uL,
|
|
|
|
0x856530D8uL,
|
|
|
|
0xF262004EuL,
|
|
|
|
0x6C0695EDuL,
|
|
|
|
0x1B01A57BuL,
|
|
|
|
0x8208F4C1uL,
|
|
|
|
0xF50FC457uL,
|
|
|
|
0x65B0D9C6uL,
|
|
|
|
0x12B7E950uL,
|
|
|
|
0x8BBEB8EAuL,
|
|
|
|
0xFCB9887CuL,
|
|
|
|
0x62DD1DDFuL,
|
|
|
|
0x15DA2D49uL,
|
|
|
|
0x8CD37CF3uL,
|
|
|
|
0xFBD44C65uL,
|
|
|
|
0x4DB26158uL,
|
|
|
|
0x3AB551CEuL,
|
|
|
|
0xA3BC0074uL,
|
|
|
|
0xD4BB30E2uL,
|
|
|
|
0x4ADFA541uL,
|
|
|
|
0x3DD895D7uL,
|
|
|
|
0xA4D1C46DuL,
|
|
|
|
0xD3D6F4FBuL,
|
|
|
|
0x4369E96AuL,
|
|
|
|
0x346ED9FCuL,
|
|
|
|
0xAD678846uL,
|
|
|
|
0xDA60B8D0uL,
|
|
|
|
0x44042D73uL,
|
|
|
|
0x33031DE5uL,
|
|
|
|
0xAA0A4C5FuL,
|
|
|
|
0xDD0D7CC9uL,
|
|
|
|
0x5005713CuL,
|
|
|
|
0x270241AAuL,
|
|
|
|
0xBE0B1010uL,
|
|
|
|
0xC90C2086uL,
|
|
|
|
0x5768B525uL,
|
|
|
|
0x206F85B3uL,
|
|
|
|
0xB966D409uL,
|
|
|
|
0xCE61E49FuL,
|
|
|
|
0x5EDEF90EuL,
|
|
|
|
0x29D9C998uL,
|
|
|
|
0xB0D09822uL,
|
|
|
|
0xC7D7A8B4uL,
|
|
|
|
0x59B33D17uL,
|
|
|
|
0x2EB40D81uL,
|
|
|
|
0xB7BD5C3BuL,
|
|
|
|
0xC0BA6CADuL,
|
|
|
|
0xEDB88320uL,
|
|
|
|
0x9ABFB3B6uL,
|
|
|
|
0x03B6E20CuL,
|
|
|
|
0x74B1D29AuL,
|
|
|
|
0xEAD54739uL,
|
|
|
|
0x9DD277AFuL,
|
|
|
|
0x04DB2615uL,
|
|
|
|
0x73DC1683uL,
|
|
|
|
0xE3630B12uL,
|
|
|
|
0x94643B84uL,
|
|
|
|
0x0D6D6A3EuL,
|
|
|
|
0x7A6A5AA8uL,
|
|
|
|
0xE40ECF0BuL,
|
|
|
|
0x9309FF9DuL,
|
|
|
|
0x0A00AE27uL,
|
|
|
|
0x7D079EB1uL,
|
|
|
|
0xF00F9344uL,
|
|
|
|
0x8708A3D2uL,
|
|
|
|
0x1E01F268uL,
|
|
|
|
0x6906C2FEuL,
|
|
|
|
0xF762575DuL,
|
|
|
|
0x806567CBuL,
|
|
|
|
0x196C3671uL,
|
|
|
|
0x6E6B06E7uL,
|
|
|
|
0xFED41B76uL,
|
|
|
|
0x89D32BE0uL,
|
|
|
|
0x10DA7A5AuL,
|
|
|
|
0x67DD4ACCuL,
|
|
|
|
0xF9B9DF6FuL,
|
|
|
|
0x8EBEEFF9uL,
|
|
|
|
0x17B7BE43uL,
|
|
|
|
0x60B08ED5uL,
|
|
|
|
0xD6D6A3E8uL,
|
|
|
|
0xA1D1937EuL,
|
|
|
|
0x38D8C2C4uL,
|
|
|
|
0x4FDFF252uL,
|
|
|
|
0xD1BB67F1uL,
|
|
|
|
0xA6BC5767uL,
|
|
|
|
0x3FB506DDuL,
|
|
|
|
0x48B2364BuL,
|
|
|
|
0xD80D2BDAuL,
|
|
|
|
0xAF0A1B4CuL,
|
|
|
|
0x36034AF6uL,
|
|
|
|
0x41047A60uL,
|
|
|
|
0xDF60EFC3uL,
|
|
|
|
0xA867DF55uL,
|
|
|
|
0x316E8EEFuL,
|
|
|
|
0x4669BE79uL,
|
|
|
|
0xCB61B38CuL,
|
|
|
|
0xBC66831AuL,
|
|
|
|
0x256FD2A0uL,
|
|
|
|
0x5268E236uL,
|
|
|
|
0xCC0C7795uL,
|
|
|
|
0xBB0B4703uL,
|
|
|
|
0x220216B9uL,
|
|
|
|
0x5505262FuL,
|
|
|
|
0xC5BA3BBEuL,
|
|
|
|
0xB2BD0B28uL,
|
|
|
|
0x2BB45A92uL,
|
|
|
|
0x5CB36A04uL,
|
|
|
|
0xC2D7FFA7uL,
|
|
|
|
0xB5D0CF31uL,
|
|
|
|
0x2CD99E8BuL,
|
|
|
|
0x5BDEAE1DuL,
|
|
|
|
0x9B64C2B0uL,
|
|
|
|
0xEC63F226uL,
|
|
|
|
0x756AA39CuL,
|
|
|
|
0x026D930AuL,
|
|
|
|
0x9C0906A9uL,
|
|
|
|
0xEB0E363FuL,
|
|
|
|
0x72076785uL,
|
|
|
|
0x05005713uL,
|
|
|
|
0x95BF4A82uL,
|
|
|
|
0xE2B87A14uL,
|
|
|
|
0x7BB12BAEuL,
|
|
|
|
0x0CB61B38uL,
|
|
|
|
0x92D28E9BuL,
|
|
|
|
0xE5D5BE0DuL,
|
|
|
|
0x7CDCEFB7uL,
|
|
|
|
0x0BDBDF21uL,
|
|
|
|
0x86D3D2D4uL,
|
|
|
|
0xF1D4E242uL,
|
|
|
|
0x68DDB3F8uL,
|
|
|
|
0x1FDA836EuL,
|
|
|
|
0x81BE16CDuL,
|
|
|
|
0xF6B9265BuL,
|
|
|
|
0x6FB077E1uL,
|
|
|
|
0x18B74777uL,
|
|
|
|
0x88085AE6uL,
|
|
|
|
0xFF0F6A70uL,
|
|
|
|
0x66063BCAuL,
|
|
|
|
0x11010B5CuL,
|
|
|
|
0x8F659EFFuL,
|
|
|
|
0xF862AE69uL,
|
|
|
|
0x616BFFD3uL,
|
|
|
|
0x166CCF45uL,
|
|
|
|
0xA00AE278uL,
|
|
|
|
0xD70DD2EEuL,
|
|
|
|
0x4E048354uL,
|
|
|
|
0x3903B3C2uL,
|
|
|
|
0xA7672661uL,
|
|
|
|
0xD06016F7uL,
|
|
|
|
0x4969474DuL,
|
|
|
|
0x3E6E77DBuL,
|
|
|
|
0xAED16A4AuL,
|
|
|
|
0xD9D65ADCuL,
|
|
|
|
0x40DF0B66uL,
|
|
|
|
0x37D83BF0uL,
|
|
|
|
0xA9BCAE53uL,
|
|
|
|
0xDEBB9EC5uL,
|
|
|
|
0x47B2CF7FuL,
|
|
|
|
0x30B5FFE9uL,
|
|
|
|
0xBDBDF21CuL,
|
|
|
|
0xCABAC28AuL,
|
|
|
|
0x53B39330uL,
|
|
|
|
0x24B4A3A6uL,
|
|
|
|
0xBAD03605uL,
|
|
|
|
0xCDD70693uL,
|
|
|
|
0x54DE5729uL,
|
|
|
|
0x23D967BFuL,
|
|
|
|
0xB3667A2EuL,
|
|
|
|
0xC4614AB8uL,
|
|
|
|
0x5D681B02uL,
|
|
|
|
0x2A6F2B94uL,
|
|
|
|
0xB40BBE37uL,
|
|
|
|
0xC30C8EA1uL,
|
|
|
|
0x5A05DF1BuL,
|
|
|
|
0x2D02EF8DuL};
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* the functions
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
/*! \brief Get boot request flag from app
|
|
|
|
*
|
|
|
|
* This function get the boot request event that is from app
|
|
|
|
*
|
|
|
|
* \param[in] void
|
|
|
|
*
|
|
|
|
* \return void
|
|
|
|
*/
|
|
|
|
static bool Bootloader_GetBootReq(void)
|
|
|
|
{
|
|
|
|
bool ret = true;
|
|
|
|
|
|
|
|
/* Make sure the read action for no-init ram zone is in system reset happen */
|
|
|
|
if(ResetDrv_IsResetCaused(&mcu.resetDrv, RESETDRV_SOURCE_POR) == false)
|
|
|
|
{
|
|
|
|
if(ResetDrv_IsResetCaused(&mcu.resetDrv, RESETDRV_SOURCE_SYS) == true)
|
|
|
|
{
|
|
|
|
if(sBootloader_Req != BOOTLOADER_CFG_REQ_ACTIVE)
|
|
|
|
{
|
|
|
|
ret = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sBootloader_Req = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ret = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ret = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief Get boot block size bytes
|
|
|
|
*
|
|
|
|
* This function get the pgm block byte size
|
|
|
|
*
|
|
|
|
* \param[in] void
|
|
|
|
*
|
|
|
|
* \return void
|
|
|
|
*/
|
|
|
|
uint32_t Bootloader_GetPgmBlockSize(void)
|
|
|
|
{
|
|
|
|
return BOOTLOADER_CFG_PGM_BYTES_SIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief Calculate the app crc
|
|
|
|
*
|
|
|
|
* This function get the boot request event that is from app
|
|
|
|
*
|
|
|
|
* \param[in] initCrcValue : the old crc value
|
|
|
|
* \param[in] dataBuffer : the start addresss to take in calculating crc
|
|
|
|
* \param[in] bytesNum : how many bytes to be take in
|
|
|
|
*
|
|
|
|
* \return the calculate the crc value
|
|
|
|
*/
|
|
|
|
static uint32_t Bootloader_CalculateCheckSum(uint32_t initCrcValue, const uint8_t *dataBuffer, uint32_t bytesNum, bool inverted)
|
|
|
|
{
|
|
|
|
uint32_t tCrc = initCrcValue;
|
|
|
|
uint32_t i = 0;
|
|
|
|
|
|
|
|
for(i = 0; i < bytesNum; i++)
|
|
|
|
{
|
|
|
|
tCrc = crc32_table[(tCrc ^ dataBuffer[i]) & 0xff] ^ (tCrc >> 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(inverted == true)
|
|
|
|
{
|
|
|
|
tCrc = 0xFFFFFFFF - tCrc;
|
|
|
|
}
|
|
|
|
|
|
|
|
return tCrc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief Jump to app
|
|
|
|
*
|
|
|
|
* This function jump to app from boot
|
|
|
|
*
|
|
|
|
* \param[in] void
|
|
|
|
*
|
|
|
|
* \return void
|
|
|
|
*/
|
|
|
|
static void Bootloader_JumpToApp(void)
|
|
|
|
{
|
|
|
|
uint32_t appEntry = 0, appStack = 0;
|
|
|
|
static uint32_t statckPointer = 0;
|
|
|
|
static void (*pJumpToApp)(void);
|
|
|
|
|
|
|
|
IrqDrv_DisableGlobalInterrupt();
|
|
|
|
FlexCanDrv_SoftReset(&mcu.flexCanDrv);
|
|
|
|
memset(&sBootloader_Cb, 0, sizeof(sBootloader_Cb));
|
|
|
|
/* MSP */
|
|
|
|
appStack = *(uint32_t *)BOOTLOADER_CFG_APP_START_ADDR;
|
|
|
|
/* PC */
|
|
|
|
appEntry = *(uint32_t *)(BOOTLOADER_CFG_APP_START_ADDR + 4);
|
|
|
|
|
|
|
|
pJumpToApp = (void (*)(void))appEntry;
|
|
|
|
statckPointer = appStack;
|
|
|
|
/* Set the MSP */
|
|
|
|
__set_PSP(statckPointer);
|
|
|
|
__set_MSP(statckPointer);
|
|
|
|
|
|
|
|
SCB->VTOR = (uint32_t)BOOTLOADER_CFG_APP_START_ADDR;
|
|
|
|
/* Jump action */
|
|
|
|
pJumpToApp();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief Reset the cpu
|
|
|
|
*
|
|
|
|
* This function reset the cpu if get reset request
|
|
|
|
*
|
|
|
|
* \param[in] void
|
|
|
|
*
|
|
|
|
* \return void
|
|
|
|
*/
|
|
|
|
static void Bootloader_Reset(void)
|
|
|
|
{
|
|
|
|
/* TODO */
|
|
|
|
memset(&sBootloader_Cb, 0, sizeof(sBootloader_Cb));
|
|
|
|
IrqDrv_DisableGlobalInterrupt();//关闭中断,不加会导致无法复位
|
|
|
|
ResetDrv_SoftwareResetModule(&mcu.resetDrv, RESETDRV_SWRESET_SYS);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief Reset the cpu
|
|
|
|
*
|
|
|
|
* This function reset the cpu if get reset request
|
|
|
|
*
|
|
|
|
* \param[in] void
|
|
|
|
*
|
|
|
|
* \return void
|
|
|
|
*/
|
|
|
|
static void Bootloader_HardReset(void)
|
|
|
|
{
|
|
|
|
/* TODO */
|
2025-02-05 00:13:59 +08:00
|
|
|
//SBC_Write_RegField(SBC_M_S_CTRL, SBC_M_S_CTRL_MODE_Msk, SBC_M_S_CTRL_MODE_Pos, SBC_MODE_RESET, NULL);
|
2025-02-03 20:43:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief pgm positive respose to eol
|
|
|
|
*
|
|
|
|
* This function response to EOL when finished the current block data pgm
|
|
|
|
*
|
|
|
|
* \param[in] void
|
|
|
|
*
|
|
|
|
* \return void
|
|
|
|
*/
|
|
|
|
static void Bootloader_PositiveResp(void)
|
|
|
|
{
|
|
|
|
uint8_t rspBuffer[8];
|
|
|
|
|
|
|
|
rspBuffer[0] = 0x76;
|
|
|
|
rspBuffer[1] = sBootloader_Cb.pgmInfo.pgmBlockSn;
|
|
|
|
|
|
|
|
sBootloader_Cb.positiveRespFunction(sBootloader_Cb.udsObj, rspBuffer, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief pgm negative respose to eol
|
|
|
|
*
|
|
|
|
* This function response to EOL when finished the current block data pgm
|
|
|
|
*
|
|
|
|
* \param[in] sid : service id
|
|
|
|
* \param[in] nrc : negative response code
|
|
|
|
*
|
|
|
|
* \return void
|
|
|
|
*/
|
|
|
|
static void Bootloader_NegativeResp(uint8_t sid, uint8_t nrc)
|
|
|
|
{
|
|
|
|
sBootloader_Cb.negativeRespFunction(sBootloader_Cb.udsObj, sid, nrc);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief Update the flash driver if the flash driver is from outside
|
|
|
|
*
|
|
|
|
* This function update the flash driver interface address and init the flash module
|
|
|
|
*
|
|
|
|
* \param[in] void
|
|
|
|
*
|
|
|
|
* \return void
|
|
|
|
*/
|
|
|
|
void Bootloader_FlsDrvUpdate(void)
|
|
|
|
{
|
|
|
|
#if BOOTLOADER_CFG_FLS_COPY_AUTO_EN == 0u
|
|
|
|
uint32_t localCrc = 0;
|
|
|
|
uint8_t i = 0;
|
|
|
|
sBootloader_Cb.flsDrvInfo.flashDriverDownloaded = false;
|
|
|
|
/* Read out the flash driver first 4words data */
|
|
|
|
sBootloader_Cb.flsDrvInfo.startFlsInitAddr = *((uint32_t *)(BOOTLOADER_CFG_FLS_DRV_RAM_START_ADDR + 4));
|
|
|
|
sBootloader_Cb.flsDrvInfo.startFlsEraseAddr = *((uint32_t *)(BOOTLOADER_CFG_FLS_DRV_RAM_START_ADDR + 8));
|
|
|
|
sBootloader_Cb.flsDrvInfo.startFlsPgmAddr = *((uint32_t *)(BOOTLOADER_CFG_FLS_DRV_RAM_START_ADDR + 12));
|
|
|
|
|
|
|
|
/* Check the current download data is for flash driver */
|
|
|
|
if((sBootloader_Cb.pgmInfo.pgmStartAddress == BOOTLOADER_CFG_FLS_DRV_RAM_START_ADDR) && (sBootloader_Cb.pgmInfo.pgmMemSize == (BOOTLOADER_CFG_FLS_DRV_RAM_CODE_SIZE + BOOTLOADER_CFG_FLS_DRV_RAM_CRC_SIZE)))
|
|
|
|
{
|
|
|
|
sBootloader_Cb.pgmInfo.pgmCrc = Bootloader_CalculateCheckSum(BOOTLOADER_CFG_INIT_CRC_VALUE,
|
|
|
|
(const uint8_t *)sBootloader_Cb.pgmInfo.pgmStartAddress,
|
|
|
|
sBootloader_Cb.pgmInfo.pgmMemSize - BOOTLOADER_CFG_FLS_DRV_RAM_CRC_SIZE,
|
|
|
|
true);
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
for(i = 0; i< 4; i++)
|
|
|
|
{
|
|
|
|
localCrc <<= 8;
|
|
|
|
localCrc += (*((uint8_t *)(BOOTLOADER_CFG_FLS_DRV_RAM_CRC_ADDR + i)));
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
localCrc = (*((uint8_t *)BOOTLOADER_CFG_FLS_DRV_RAM_CRC_ADDR));
|
|
|
|
|
|
|
|
if(sBootloader_Cb.pgmInfo.pgmCrc == localCrc)
|
|
|
|
{
|
|
|
|
sBootloader_Cb.flsDrvInfo.pFls_InitFunction = (pFls_InitFunctionPtr)sBootloader_Cb.flsDrvInfo.startFlsInitAddr;
|
|
|
|
sBootloader_Cb.flsDrvInfo.pFls_EraseFunction = (pFls_EraseFunctionPtr)sBootloader_Cb.flsDrvInfo.startFlsEraseAddr;
|
|
|
|
sBootloader_Cb.flsDrvInfo.pFls_WriteFunction = (pFls_WriteFunctionPtr)sBootloader_Cb.flsDrvInfo.startFlsPgmAddr;
|
|
|
|
|
|
|
|
sBootloader_Cb.flsDrvInfo.pFls_InitFunction(sBootloader_Cb.flashDrvObj);
|
|
|
|
sBootloader_Cb.flsDrvInfo.flashDriverDownloaded = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief Bootloader init state process
|
|
|
|
*
|
|
|
|
* This function check the boot request is existed or not
|
|
|
|
*
|
|
|
|
* \param[in] void
|
|
|
|
*
|
|
|
|
* \return void
|
|
|
|
*/
|
|
|
|
static void Bootloader_InitState(void)
|
|
|
|
{
|
|
|
|
if(sBootloader_Cb.bootSubState == BOOTLOADER_SUB_STATE_NONE)
|
|
|
|
{
|
|
|
|
if((sBootloader_Cb.emergeBootReqEn == true) || (sBootloader_Cb.bootActive == true))
|
|
|
|
{
|
|
|
|
/* Emerge boot request */
|
|
|
|
sBootloader_Cb.stayInBootTimeoutCnt = 0;
|
|
|
|
#if BOOTLOADER_CFG_FLS_COPY_AUTO_EN == 0u
|
|
|
|
sBootloader_Cb.flsDrvInfo.flashDriverDownloaded = false;
|
|
|
|
#endif
|
|
|
|
sBootloader_Cb.bootActive = true;
|
|
|
|
sBootloader_Cb.bootSubState = BOOTLOADER_SUB_STATE_END;
|
|
|
|
sBootloader_Cb.udsObj->session = UDS_SESSION_PROGRAMMING;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Bootloader_SetBootState(BOOTLOADER_STATE_CHECK);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief Bootloader erase state process
|
|
|
|
*
|
|
|
|
* This function excute the action if bootloader is in erase flash state
|
|
|
|
*
|
|
|
|
* \param[in] void
|
|
|
|
*
|
|
|
|
* \return void
|
|
|
|
*/
|
|
|
|
static void Bootloader_EraseState(void)
|
|
|
|
{
|
|
|
|
if((sBootloader_Cb.bootSubState == BOOTLOADER_SUB_STATE_NONE) || (sBootloader_Cb.bootSubState == BOOTLOADER_SUB_STATE_DOING))
|
|
|
|
{
|
|
|
|
if(sBootloader_Cb.eraseInfo.eraseSectionNums > 0u)
|
|
|
|
{
|
|
|
|
if(sBootloader_Cb.eraseInfo.eraseSectionCnt < sBootloader_Cb.eraseInfo.eraseSectionNums)
|
|
|
|
{
|
|
|
|
Fls_StdRtnType ret = FLS_STD_RETURN_OK;
|
|
|
|
uint32_t eraseStartAddress = sBootloader_Cb.eraseInfo.eraseStartAddress;
|
|
|
|
|
|
|
|
if(sBootloader_Cb.downloadObj != BOOLOADER_OBJECT_FLASH_DRIVER)
|
|
|
|
{
|
|
|
|
/* Make sure no interrupt during erasing action, so disable global */
|
|
|
|
IrqDrv_DisableGlobalInterrupt();
|
|
|
|
#if BOOTLOADER_CFG_ERASE_SECTOR_NUM == BOOTLOADER_CFG_ERASE_ALL
|
|
|
|
|
|
|
|
/* First erase App Head then erased other sectors */
|
|
|
|
#if BOOTLOADER_CFG_FLS_COPY_AUTO_EN == 1u
|
|
|
|
ret = Fls_Erase(sBootloader_Cb.eraseInfo.eraseStartAddress, 1);
|
|
|
|
#else
|
|
|
|
/* Check flash driver has been download into ram */
|
|
|
|
if(sBootloader_Cb.flsDrvInfo.flashDriverDownloaded == true)
|
|
|
|
{
|
|
|
|
ret = sBootloader_Cb.flsDrvInfo.pFls_EraseFunction(sBootloader_Cb.eraseInfo.eraseStartAddress, 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ret = FLS_STD_RETURN_FLASH_DRIVER_INVALID;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if(ret == FLS_STD_RETURN_OK)
|
|
|
|
{
|
|
|
|
/* Erase other sectors */
|
|
|
|
#if BOOTLOADER_CFG_FLS_COPY_AUTO_EN == 1u
|
|
|
|
ret = Fls_Erase(eraseStartAddress + FLS_ERASE_SECTION_SIZE,
|
|
|
|
sBootloader_Cb.eraseInfo.eraseSectionNums - 1u);
|
|
|
|
#else
|
|
|
|
ret = sBootloader_Cb.flsDrvInfo.pFls_EraseFunction(eraseStartAddress + FLS_ERASE_SECTION_SIZE,
|
|
|
|
sBootloader_Cb.eraseInfo.eraseSectionNums - 1u);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
uint32_t eraseSectorNums = 0;
|
|
|
|
eraseStartAddress = sBootloader_Cb.eraseInfo.eraseStartAddress + (sBootloader_Cb.eraseInfo.eraseSectionCnt * FLS_ERASE_SECTION_SIZE);
|
|
|
|
|
|
|
|
/* Check out the rest sector nums is more than the once-erased nums, if not, erased the rest sector nums */
|
|
|
|
eraseSectorNums = sBootloader_Cb.eraseInfo.eraseSectionNums - sBootloader_Cb.eraseInfo.eraseSectionCnt;
|
|
|
|
if(eraseSectorNums > BOOTLOADER_CFG_ERASE_SECTOR_NUM)
|
|
|
|
{
|
|
|
|
eraseSectorNums = BOOTLOADER_CFG_ERASE_SECTOR_NUM;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if BOOTLOADER_CFG_FLS_COPY_AUTO_EN == 1u
|
|
|
|
ret = Fls_Erase(eraseStartAddress,
|
|
|
|
eraseSectorNums);
|
|
|
|
#else
|
|
|
|
/* Check flash driver has been download into ram */
|
|
|
|
if(sBootloader_Cb.flsDrvInfo.flashDriverDownloaded == true)
|
|
|
|
{
|
|
|
|
ret = sBootloader_Cb.flsDrvInfo.pFls_EraseFunction(eraseStartAddress,
|
|
|
|
eraseSectorNums);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ret = FLS_STD_RETURN_FLASH_DRIVER_INVALID;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif
|
|
|
|
/* After erased, restored the global interrupt */
|
|
|
|
IrqDrv_EnableGlobalInterrupt();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
#if BOOTLOADER_CFG_FLS_COPY_AUTO_EN == 0u
|
|
|
|
/* Clear flash driver in ram */
|
|
|
|
memset((uint8_t *)BOOTLOADER_CFG_FLS_DRV_RAM_START_ADDR, 0, BOOTLOADER_CFG_FLS_DRV_RAM_CODE_SIZE + BOOTLOADER_CFG_FLS_DRV_RAM_CRC_SIZE);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ret == FLS_STD_RETURN_OK)
|
|
|
|
{
|
|
|
|
#if BOOTLOADER_CFG_ERASE_SECTOR_NUM == BOOTLOADER_CFG_ERASE_ALL
|
|
|
|
/* Erased action has been finished */
|
|
|
|
sBootloader_Cb.bootSubState = BOOTLOADER_SUB_STATE_END;
|
|
|
|
sBootloader_Cb.eraseInfo.eraseSectionNums = 0;
|
|
|
|
sBootloader_Cb.eraseInfo.eraseLength = 0;
|
|
|
|
sBootloader_Cb.eraseInfo.eraseSectionCnt = 0;
|
|
|
|
#else
|
|
|
|
sBootloader_Cb.eraseInfo.eraseSectionCnt += BOOTLOADER_CFG_ERASE_SECTOR_NUM;
|
|
|
|
if(sBootloader_Cb.eraseInfo.eraseSectionCnt >= sBootloader_Cb.eraseInfo.eraseSectionNums)
|
|
|
|
{
|
|
|
|
/* Erased action has been finished */
|
|
|
|
sBootloader_Cb.bootSubState = BOOTLOADER_SUB_STATE_END;
|
|
|
|
sBootloader_Cb.eraseInfo.eraseSectionNums = 0;
|
|
|
|
sBootloader_Cb.eraseInfo.eraseLength = 0;
|
|
|
|
sBootloader_Cb.eraseInfo.eraseSectionCnt = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sBootloader_Cb.bootSubState = BOOTLOADER_SUB_STATE_DOING;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sBootloader_Cb.eraseInfo.eraseSectionNums = 0;
|
|
|
|
sBootloader_Cb.eraseInfo.eraseLength = 0;
|
|
|
|
sBootloader_Cb.eraseInfo.eraseSectionCnt = 0;
|
|
|
|
Bootloader_SetBootState(BOOTLOADER_STATE_ERR);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Nothing to do , just wait for the next event */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief Bootloader program flash state process
|
|
|
|
*
|
|
|
|
* This function excute the action if bootloader is in programming flash state
|
|
|
|
*
|
|
|
|
* \param[in] void
|
|
|
|
*
|
|
|
|
* \return void
|
|
|
|
*/
|
|
|
|
static void Bootloader_PgmState(void)
|
|
|
|
{
|
|
|
|
if(((sBootloader_Cb.pgmInfo.pgmReadyEn == true) && ((sBootloader_Cb.bootSubState == BOOTLOADER_SUB_STATE_NONE) || (sBootloader_Cb.bootSubState == BOOTLOADER_SUB_STATE_DOING))))
|
|
|
|
{
|
|
|
|
/* if received one frame datas to be need to download to mcu */
|
|
|
|
if(sBootloader_Cb.pgmInfo.pgmStartTriggerEn == true)
|
|
|
|
{
|
|
|
|
if(sBootloader_Cb.pgmInfo.pgmMemCnt < sBootloader_Cb.pgmInfo.pgmMemSize)
|
|
|
|
{
|
|
|
|
Fls_StdRtnType ret = FLS_STD_RETURN_OK;
|
|
|
|
|
|
|
|
if(sBootloader_Cb.downloadObj != BOOLOADER_OBJECT_FLASH_DRIVER)
|
|
|
|
{
|
|
|
|
uint8_t pgmPackageCnt = 0, i = 0;
|
|
|
|
|
|
|
|
pgmPackageCnt = (BOOTLOADER_CFG_PGM_BYTES_SIZE + FLS_PGM_SECTION_SIZE - 1u) / FLS_PGM_SECTION_SIZE;
|
|
|
|
IrqDrv_DisableGlobalInterrupt();
|
|
|
|
|
|
|
|
#if BOOTLOADER_CFG_FLS_COPY_AUTO_EN == 1u
|
|
|
|
for (i = 0; i< pgmPackageCnt;i++)
|
|
|
|
{
|
|
|
|
ret = Fls_Write(sBootloader_Cb.pgmInfo.pgmStartAddress + sBootloader_Cb.pgmInfo.pgmMemCnt + i * FLS_PGM_SECTION_SIZE,
|
|
|
|
(const uint8_t *)&sBootloader_Cb.pgmInfo.pgmData[i * FLS_PGM_SECTION_SIZE],
|
|
|
|
FLS_PGM_SECTION_SIZE);
|
|
|
|
|
|
|
|
if (ret != FLS_STD_RETURN_OK)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
/* Check flash driver has been download into ram */
|
|
|
|
if(sBootloader_Cb.flsDrvInfo.flashDriverDownloaded == true)
|
|
|
|
{
|
|
|
|
for(i = 0; i < pgmPackageCnt; i++)
|
|
|
|
{
|
|
|
|
ret = sBootloader_Cb.flsDrvInfo.pFls_WriteFunction(sBootloader_Cb.pgmInfo.pgmStartAddress + sBootloader_Cb.pgmInfo.pgmMemCnt + i * FLS_PGM_SECTION_SIZE,
|
|
|
|
(const uint8_t *)&sBootloader_Cb.pgmInfo.pgmData[i * FLS_PGM_SECTION_SIZE],
|
|
|
|
FLS_PGM_SECTION_SIZE);
|
|
|
|
|
|
|
|
if(ret != FLS_STD_RETURN_OK)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ret = FLS_STD_RETURN_FLASH_DRIVER_INVALID;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
IrqDrv_EnableGlobalInterrupt();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
#if BOOTLOADER_CFG_FLS_COPY_AUTO_EN == 1u
|
|
|
|
/* Nothing to do, no need to copy flash driver from outer side */
|
|
|
|
#else
|
|
|
|
/* Copy flash driver into ram */
|
|
|
|
memcpy((uint8_t *)(sBootloader_Cb.pgmInfo.pgmStartAddress + sBootloader_Cb.pgmInfo.pgmMemCnt),
|
|
|
|
(const uint8_t *)sBootloader_Cb.pgmInfo.pgmData,
|
|
|
|
BOOTLOADER_CFG_PGM_BYTES_SIZE);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ret == FLS_STD_RETURN_OK)
|
|
|
|
{
|
|
|
|
sBootloader_Cb.pgmInfo.pgmMemCnt += BOOTLOADER_CFG_PGM_BYTES_SIZE;
|
|
|
|
|
|
|
|
if(sBootloader_Cb.pgmInfo.pgmMemCnt >= sBootloader_Cb.pgmInfo.pgmMemSize)
|
|
|
|
{
|
|
|
|
sBootloader_Cb.pgmInfo.pgmReadyEn = false;
|
|
|
|
sBootloader_Cb.bootSubState = BOOTLOADER_SUB_STATE_END;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sBootloader_Cb.bootSubState = BOOTLOADER_SUB_STATE_DOING;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Indicate the EOL thant it can transfer the next block data to be written */
|
|
|
|
Bootloader_PositiveResp();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sBootloader_Cb.pgmInfo.pgmReadyEn = false;
|
|
|
|
sBootloader_Cb.pgmInfo.pgmMemSize = 0;
|
|
|
|
sBootloader_Cb.pgmInfo.pgmMemCnt = 0;
|
|
|
|
Bootloader_SetBootState(BOOTLOADER_STATE_ERR);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Clear the download trigger event, wait for the next download data if need */
|
|
|
|
sBootloader_Cb.pgmInfo.pgmStartTriggerEn = false;
|
|
|
|
sBootloader_Cb.pgmInfo.pgmBlockByteCnt = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Nothing to do , just wait for the next event */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief Bootloader check state process
|
|
|
|
*
|
|
|
|
* This function excute the action if bootloader is in check state
|
|
|
|
*
|
|
|
|
* \param[in] void
|
|
|
|
*
|
|
|
|
* \return void
|
|
|
|
*/
|
|
|
|
static void Bootloader_CheckState(void)
|
|
|
|
{
|
|
|
|
if((sBootloader_Cb.bootSubState == BOOTLOADER_SUB_STATE_NONE) || (sBootloader_Cb.bootSubState == BOOTLOADER_SUB_STATE_DOING))
|
|
|
|
{
|
|
|
|
sBootloader_Cb.bootSubState = BOOTLOADER_SUB_STATE_DOING;
|
|
|
|
if((sBootloader_Cb.downloadObj == BOOLOADER_OBJECT_APP_CODE) || (sBootloader_Cb.downloadObj == BOOLOADER_OBJECT_NONE))
|
|
|
|
{
|
|
|
|
if((Fls_CheckWriteState(BOOTLOADER_CFG_APP_HEAD_ADDR) == FLS_STD_RETURN_OK) && (Fls_CheckWriteState(BOOTLOADER_CFG_APP_CRC_ADDR - 4u) == FLS_STD_RETURN_OK))
|
|
|
|
{
|
|
|
|
/* Check App Head */
|
|
|
|
if((*((uint32_t *)BOOTLOADER_CFG_APP_HEAD_ADDR)) != BOOTLOADER_CFG_HEAD_MASK)
|
|
|
|
{
|
|
|
|
/* Active mcu enter into boot */
|
|
|
|
sBootloader_Cb.bootActive = true;
|
|
|
|
sBootloader_Cb.bootSubState = BOOTLOADER_SUB_STATE_END;
|
|
|
|
sBootloader_Cb.pgmInfo.crcResult = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
uint32_t localCrc = (*((uint32_t *)BOOTLOADER_CFG_APP_CRC_ADDR));
|
|
|
|
uint32_t app_size = (*((uint32_t *)(BOOTLOADER_CFG_APP_CRC_ADDR-4))) - BOOTLOADER_CFG_APP_START_ADDR;
|
|
|
|
|
|
|
|
if (app_size < 0x28000 && app_size > 0x4000)
|
|
|
|
{
|
|
|
|
sBootloader_Cb.pgmInfo.pgmCrc = Bootloader_CalculateCheckSum(BOOTLOADER_CFG_INIT_CRC_VALUE,
|
|
|
|
(const uint8_t *)BOOTLOADER_CFG_APP_START_ADDR,
|
|
|
|
app_size,
|
|
|
|
true);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sBootloader_Cb.pgmInfo.pgmCrc = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(localCrc != sBootloader_Cb.pgmInfo.pgmCrc)
|
|
|
|
{
|
|
|
|
/* Active mcu enter into boot */
|
|
|
|
sBootloader_Cb.bootActive = true;
|
|
|
|
sBootloader_Cb.bootSubState = BOOTLOADER_SUB_STATE_END;
|
|
|
|
sBootloader_Cb.pgmInfo.crcResult = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sBootloader_Cb.pgmInfo.crcResult = true;
|
|
|
|
/* If the current app is ok and no bootloader process action, then enter into exit state */
|
|
|
|
if(sBootloader_Cb.bootActive == false)
|
|
|
|
{
|
|
|
|
Bootloader_SetBootState(BOOTLOADER_STATE_EXIT);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Stay in check state, wait for next command */
|
|
|
|
sBootloader_Cb.bootActive = true;
|
|
|
|
sBootloader_Cb.bootSubState = BOOTLOADER_SUB_STATE_END;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Active mcu enter into boot */
|
|
|
|
sBootloader_Cb.bootActive = true;
|
|
|
|
sBootloader_Cb.bootSubState = BOOTLOADER_SUB_STATE_END;
|
|
|
|
sBootloader_Cb.pgmInfo.crcResult = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(sBootloader_Cb.downloadObj == BOOLOADER_OBJECT_CALIBRATION_DATA)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
#if BOOTLOADER_CFG_FLS_COPY_AUTO_EN == 0u
|
|
|
|
else if(sBootloader_Cb.downloadObj == BOOLOADER_OBJECT_FLASH_DRIVER)
|
|
|
|
{
|
|
|
|
Bootloader_FlsDrvUpdate();
|
|
|
|
if(sBootloader_Cb.flsDrvInfo.flashDriverDownloaded == true)
|
|
|
|
{
|
|
|
|
sBootloader_Cb.pgmInfo.crcResult = true;
|
|
|
|
sBootloader_Cb.bootSubState = BOOTLOADER_SUB_STATE_END;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sBootloader_Cb.pgmInfo.crcResult = false;
|
|
|
|
sBootloader_Cb.bootSubState = BOOTLOADER_SUB_STATE_END;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
else if(sBootloader_Cb.downloadObj == BOOLOADER_OBJECT_FLASH_DRIVER)
|
|
|
|
{
|
|
|
|
sBootloader_Cb.pgmInfo.crcResult = true;
|
|
|
|
sBootloader_Cb.bootSubState = BOOTLOADER_SUB_STATE_END;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Nothing to do , just wait for the next event */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief Bootloader exit state process
|
|
|
|
*
|
|
|
|
* This function excute the action if bootloader is in exist state
|
|
|
|
*
|
|
|
|
* \param[in] void
|
|
|
|
*
|
|
|
|
* \return void
|
|
|
|
*/
|
|
|
|
static void Bootloader_ExitState(void)
|
|
|
|
{
|
|
|
|
if((sBootloader_Cb.bootSubState == BOOTLOADER_SUB_STATE_NONE) || (sBootloader_Cb.bootSubState == BOOTLOADER_SUB_STATE_DOING))
|
|
|
|
{
|
|
|
|
if((sBootloader_Cb.stayInBootTimeoutCnt >= BOOTLOADER_CFG_BOOT_DURATION_MS) && (sBootloader_Cb.bootActive == false))
|
|
|
|
{
|
|
|
|
SEGGER_RTT_printf(0,"-----JumpToApp-----\n");
|
|
|
|
/* Disable wdg */
|
|
|
|
|
|
|
|
/* Disable global interrupt */
|
|
|
|
IrqDrv_DisableGlobalInterrupt();
|
|
|
|
|
|
|
|
/* Jump to App */
|
|
|
|
Bootloader_JumpToApp();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sBootloader_Cb.bootSubState = BOOTLOADER_SUB_STATE_DOING;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Nothing to do , just wait for the next event */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief Bootloader error state process
|
|
|
|
*
|
|
|
|
* This function excute the action if bootloader is in errored state
|
|
|
|
*
|
|
|
|
* \param[in] void
|
|
|
|
*
|
|
|
|
* \return void
|
|
|
|
*/
|
|
|
|
static void Bootloader_ErrorState(void)
|
|
|
|
{
|
|
|
|
/* TODO: */
|
|
|
|
if((sBootloader_Cb.bootSubState == BOOTLOADER_SUB_STATE_NONE) || (sBootloader_Cb.bootSubState == BOOTLOADER_SUB_STATE_DOING))
|
|
|
|
{
|
|
|
|
/* TODO: */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Nothing to do , just wait for the next event */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief Initialize bootloader control block information
|
|
|
|
*
|
|
|
|
* This function Initialize bootloader control block information
|
|
|
|
*
|
|
|
|
* \param[in] obj : flashdriver instance
|
|
|
|
* \param[in] udsObj : uds instance
|
|
|
|
* \param[in] positiveRespFunction : uds positve response interface
|
|
|
|
* \param[in] negativeRespFunction : uds negative response interface
|
|
|
|
*
|
|
|
|
* \return void
|
|
|
|
*/
|
|
|
|
void Bootloader_Init(FlashDrvType *obj, UdsType *udsObj, pUds_PositiveResponsePtr positiveRespFunction, pUds_NegativeResponsePtr negativeRespFunction)
|
|
|
|
{
|
|
|
|
memset(&sBootloader_Cb, 0, sizeof(sBootloader_Cb));
|
|
|
|
|
|
|
|
#if BOOTLOADER_CFG_FLS_COPY_AUTO_EN == 0u
|
|
|
|
/* Clear flash driver in ram */
|
|
|
|
memset((uint8_t *)BOOTLOADER_CFG_FLS_DRV_RAM_START_ADDR, 0, BOOTLOADER_CFG_FLS_DRV_RAM_CODE_SIZE + BOOTLOADER_CFG_FLS_DRV_RAM_CRC_SIZE);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
sBootloader_Cb.flashDrvObj = obj;
|
|
|
|
sBootloader_Cb.udsObj = udsObj;
|
|
|
|
sBootloader_Cb.positiveRespFunction = positiveRespFunction;
|
|
|
|
sBootloader_Cb.negativeRespFunction = negativeRespFunction;
|
|
|
|
sBootloader_Cb.pgmInfo.pgmCrc = 0;
|
|
|
|
|
|
|
|
#if BOOTLOADER_CFG_FLS_COPY_AUTO_EN != 0u
|
|
|
|
Fls_Init(obj);
|
|
|
|
#else
|
|
|
|
/* Update the flash instance */
|
|
|
|
*((uint32_t *)BOOTLOADER_CFG_FLS_DRV_RAM_START_ADDR) = (uint32_t)obj;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if(Bootloader_GetBootReq() == true)
|
|
|
|
{
|
|
|
|
/* Emerge boot request */
|
|
|
|
sBootloader_Cb.stayInBootTimeoutCnt = 0;
|
|
|
|
sBootloader_Cb.bootActive = true;
|
|
|
|
sBootloader_Cb.udsObj->session = UDS_SESSION_PROGRAMMING;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief Set the bootloader into the target state
|
|
|
|
*
|
|
|
|
* This function Set the bootloader into the target state
|
|
|
|
*
|
|
|
|
* \param[in] state : the target state to be switch to
|
|
|
|
*
|
|
|
|
* \return void
|
|
|
|
*/
|
|
|
|
void Bootloader_SetBootState(Bootloader_StateType state)
|
|
|
|
{
|
|
|
|
sBootloader_Cb.bootSubState = BOOTLOADER_SUB_STATE_NONE;
|
|
|
|
sBootloader_Cb.bootState = state;
|
|
|
|
sBootloader_Cb.stayInBootTimeoutCnt = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief Get the bootloader current state
|
|
|
|
*
|
|
|
|
* This function Get the bootloader current state
|
|
|
|
*
|
|
|
|
* \param[in] void
|
|
|
|
*
|
|
|
|
* \return : return the current state
|
|
|
|
*/
|
|
|
|
Bootloader_StateType Bootloader_GetBootState(void)
|
|
|
|
{
|
|
|
|
return sBootloader_Cb.bootState;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief Get the bootloader current sub state
|
|
|
|
*
|
|
|
|
* This function Get the bootloader current sub state
|
|
|
|
*
|
|
|
|
* \param[in] void
|
|
|
|
*
|
|
|
|
* \return : return the current sub state
|
|
|
|
*/
|
|
|
|
Bootloader_SubStateType Bootloader_GetBootSubState(void)
|
|
|
|
{
|
|
|
|
return sBootloader_Cb.bootSubState;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief Get the bootloader current crc result
|
|
|
|
*
|
|
|
|
* This function Get the bootloader current crc result
|
|
|
|
*
|
|
|
|
* \param[in] void
|
|
|
|
*
|
|
|
|
* \return : return the current crc result
|
|
|
|
*/
|
|
|
|
bool Bootloader_GetCrcResult(void)
|
|
|
|
{
|
|
|
|
return sBootloader_Cb.pgmInfo.crcResult;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief Set emerge boot request
|
|
|
|
*
|
|
|
|
* This function Set emerge boot request
|
|
|
|
*
|
|
|
|
* \param[in] void
|
|
|
|
*
|
|
|
|
* \return void
|
|
|
|
*/
|
|
|
|
void Bootloader_EventEmergeBootRequest(bool requestEn)
|
|
|
|
{
|
|
|
|
if(sBootloader_Cb.bootActive == false)
|
|
|
|
{
|
|
|
|
sBootloader_Cb.emergeBootReqEn = requestEn;
|
|
|
|
sBootloader_Cb.stayInBootTimeoutCnt = 0;
|
|
|
|
sBootloader_Cb.bootActive = true;
|
|
|
|
#if BOOTLOADER_CFG_FLS_COPY_AUTO_EN == 0u
|
|
|
|
sBootloader_Cb.flsDrvInfo.flashDriverDownloaded = false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the current state into end sub state */
|
|
|
|
sBootloader_Cb.bootSubState = BOOTLOADER_SUB_STATE_END;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief Set the reset cup request
|
|
|
|
*
|
|
|
|
* This function Set the reset cup request
|
|
|
|
*
|
|
|
|
* \param[in] void
|
|
|
|
*
|
|
|
|
* \return void
|
|
|
|
*/
|
|
|
|
void Bootloader_EventResetRequest(bool requestEn,uint8_t resetMode)
|
|
|
|
{
|
|
|
|
sBootloader_Cb.resetReqEn = requestEn;
|
|
|
|
sBootloader_Cb.resetReqMode = resetMode;
|
|
|
|
#if BOOTLOADER_CFG_FLS_COPY_AUTO_EN == 0u
|
|
|
|
sBootloader_Cb.flsDrvInfo.flashDriverDownloaded = false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief Set the erase information
|
|
|
|
*
|
|
|
|
* This function set the erase information about where to be start to be erased and how many bytes to be erased
|
|
|
|
*
|
|
|
|
* \param[in] startAddress : where to be start to be erased
|
|
|
|
* \param[in] bytesNum : how many bytes to be erased
|
|
|
|
*
|
|
|
|
* \return void
|
|
|
|
*/
|
|
|
|
void Bootloader_EventEraseRequest(uint32_t startAddress, uint32_t bytesNum)
|
|
|
|
{
|
|
|
|
sBootloader_Cb.eraseInfo.eraseLength = bytesNum;
|
|
|
|
sBootloader_Cb.eraseInfo.eraseStartAddress = startAddress;
|
|
|
|
sBootloader_Cb.pgmInfo.pgmStartTriggerEn = false;
|
|
|
|
sBootloader_Cb.pgmInfo.pgmReadyEn = false;
|
|
|
|
|
|
|
|
/* Update the dowmloader object */
|
|
|
|
if((startAddress == BOOTLOADER_CFG_APP_START_ADDR) && (bytesNum == (BOOTLOADER_CFG_APP_SIZE + BOOTLOADER_CFG_APP_CRC_SIZE)))
|
|
|
|
{
|
|
|
|
sBootloader_Cb.downloadObj = BOOLOADER_OBJECT_APP_CODE;
|
|
|
|
sBootloader_Cb.eraseInfo.eraseSectionNums = (sBootloader_Cb.eraseInfo.eraseLength + FLS_ERASE_SECTION_ADDR_ALIGNED_MASK) / FLS_ERASE_SECTION_SIZE;
|
|
|
|
}
|
|
|
|
else if((startAddress == BOOTLOADER_CFG_CALIBRATION_DATA_START_ADDR) && (bytesNum == (BOOTLOADER_CFG_CALIBRATION_DATA_SIZE + BOOTLOADER_CFG_CALIBRATION_DATA_CRC_SIZE)))
|
|
|
|
{
|
|
|
|
sBootloader_Cb.downloadObj = BOOLOADER_OBJECT_CALIBRATION_DATA;
|
|
|
|
sBootloader_Cb.eraseInfo.eraseSectionNums = (sBootloader_Cb.eraseInfo.eraseLength + FLS_ERASE_SECTION_ADDR_ALIGNED_MASK) / FLS_ERASE_SECTION_SIZE;
|
|
|
|
}
|
|
|
|
#if BOOTLOADER_CFG_FLS_COPY_AUTO_EN == 0u
|
|
|
|
else if((startAddress == BOOTLOADER_CFG_FLS_DRV_RAM_START_ADDR) && (bytesNum <= (BOOTLOADER_CFG_FLS_DRV_RAM_CODE_SIZE + BOOTLOADER_CFG_FLS_DRV_RAM_CRC_SIZE)))
|
|
|
|
{
|
|
|
|
sBootloader_Cb.downloadObj = BOOLOADER_OBJECT_FLASH_DRIVER;
|
|
|
|
sBootloader_Cb.flsDrvInfo.flashDriverDownloaded = false;
|
|
|
|
sBootloader_Cb.eraseInfo.eraseSectionNums = ((BOOTLOADER_CFG_FLS_DRV_RAM_CODE_SIZE + BOOTLOADER_CFG_FLS_DRV_RAM_CRC_SIZE) + FLS_ERASE_SECTION_ADDR_ALIGNED_MASK) / FLS_ERASE_SECTION_SIZE;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
else if((startAddress == BOOTLOADER_CFG_FLS_DRV_RAM_START_ADDR) && (bytesNum <= (BOOTLOADER_CFG_FLS_DRV_RAM_CODE_SIZE + BOOTLOADER_CFG_FLS_DRV_RAM_CRC_SIZE)))
|
|
|
|
{
|
|
|
|
sBootloader_Cb.downloadObj = BOOLOADER_OBJECT_FLASH_DRIVER;
|
|
|
|
sBootloader_Cb.eraseInfo.eraseSectionNums = ((BOOTLOADER_CFG_FLS_DRV_RAM_CODE_SIZE + BOOTLOADER_CFG_FLS_DRV_RAM_CRC_SIZE) + FLS_ERASE_SECTION_ADDR_ALIGNED_MASK) / FLS_ERASE_SECTION_SIZE;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
Bootloader_SetBootState(BOOTLOADER_STATE_ERASE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief Set program information
|
|
|
|
*
|
|
|
|
* This function Set program information about where to be start to be write and how many bytes to be write
|
|
|
|
*
|
|
|
|
* \param[in] startAddress : where to be start to be write
|
|
|
|
* \param[in] bytesNum : how many bytes to be write
|
|
|
|
*
|
|
|
|
* \return void
|
|
|
|
*/
|
|
|
|
void Bootloader_EventPgmReady(uint32_t startAddress, uint32_t bytesNum)
|
|
|
|
{
|
|
|
|
sBootloader_Cb.pgmInfo.pgmReadyEn = true;
|
|
|
|
sBootloader_Cb.pgmInfo.pgmStartTriggerEn = false;
|
|
|
|
sBootloader_Cb.pgmInfo.pgmStartAddress = startAddress;
|
|
|
|
sBootloader_Cb.pgmInfo.pgmMemSize = bytesNum;
|
|
|
|
sBootloader_Cb.pgmInfo.pgmMemCnt = 0;
|
|
|
|
|
|
|
|
Bootloader_SetBootState(BOOTLOADER_STATE_PGM);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief Trigger the pgm start
|
|
|
|
*
|
|
|
|
* This function indication that can be write datas into flash
|
|
|
|
*
|
|
|
|
* \param[in] pDatabuffer : stored the datas to be written into flash
|
|
|
|
* \param[in] bytesNum : how many bytes to be write into local buffer
|
|
|
|
* \param[in] blockSn : current block sn number
|
|
|
|
*
|
|
|
|
* \return true: ecu start to pgm, false: ecu don't start to pgm
|
|
|
|
*/
|
|
|
|
bool Bootloader_EventPgmData(const uint8_t *pDatabuffer, uint16_t bytesNum, uint8_t blockSn)
|
|
|
|
{
|
|
|
|
uint32_t i = 0;
|
|
|
|
bool ret = false;
|
|
|
|
|
|
|
|
/* Copy data into local */
|
|
|
|
for(i = 0; i < bytesNum; i++)
|
|
|
|
{
|
|
|
|
sBootloader_Cb.pgmInfo.pgmData[sBootloader_Cb.pgmInfo.pgmBlockByteCnt + i] = pDatabuffer[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
sBootloader_Cb.pgmInfo.pgmBlockByteCnt += bytesNum;
|
|
|
|
sBootloader_Cb.pgmInfo.pgmBlockSn = blockSn;
|
|
|
|
if(sBootloader_Cb.pgmInfo.pgmBlockByteCnt >= BOOTLOADER_CFG_PGM_BYTES_SIZE)
|
|
|
|
{
|
|
|
|
sBootloader_Cb.pgmInfo.pgmStartTriggerEn = true;
|
|
|
|
ret = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief data check request
|
|
|
|
*
|
|
|
|
* This function indication that data check request
|
|
|
|
*
|
|
|
|
* \param[in] void
|
|
|
|
*
|
|
|
|
* \return void
|
|
|
|
*/
|
|
|
|
void Bootloader_EventDataCheckRequest(void)
|
|
|
|
{
|
|
|
|
sBootloader_Cb.bootSubState = BOOTLOADER_SUB_STATE_NONE;
|
|
|
|
sBootloader_Cb.bootState = BOOTLOADER_STATE_CHECK;
|
|
|
|
sBootloader_Cb.pgmInfo.crcResult = false;
|
|
|
|
sBootloader_Cb.pgmInfo.pgmCrc = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief Bootloader main state process
|
|
|
|
*
|
|
|
|
* This function process the bootloader variant state
|
|
|
|
*
|
|
|
|
* \param[in] void
|
|
|
|
*
|
|
|
|
* \return void
|
|
|
|
*/
|
|
|
|
void Bootloader_StateProc(void)
|
|
|
|
{
|
|
|
|
if(sBootloader_Cb.bootState < BOOTLOADER_STATE_NUM)
|
|
|
|
{
|
|
|
|
if(sBootloader_StateFuncTbl[sBootloader_Cb.bootState] != 0u)
|
|
|
|
{
|
|
|
|
sBootloader_StateFuncTbl[sBootloader_Cb.bootState]();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief Calculate the stay in boot duration
|
|
|
|
*
|
|
|
|
* This function calculate the timeout when before jump to app if app is ok
|
|
|
|
*
|
|
|
|
* \param[in] periodms : add in every period
|
|
|
|
*
|
|
|
|
* \return void
|
|
|
|
*/
|
|
|
|
void Bootloader_TimingProcess(uint8_t periodms)
|
|
|
|
{
|
|
|
|
if((sBootloader_Cb.bootState == BOOTLOADER_STATE_INIT) || (sBootloader_Cb.bootState == BOOTLOADER_STATE_EXIT))
|
|
|
|
{
|
|
|
|
sBootloader_Cb.stayInBootTimeoutCnt += periodms;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(sBootloader_Cb.resetReqEn == true)
|
|
|
|
{
|
|
|
|
sBootloader_Cb.resetReqEn = false;
|
2025-02-05 00:13:59 +08:00
|
|
|
/*//SBC RESET
|
2025-02-03 20:43:43 +08:00
|
|
|
if (sBootloader_Cb.resetReqMode == 1)
|
|
|
|
{
|
|
|
|
Bootloader_HardReset();
|
2025-02-05 00:13:59 +08:00
|
|
|
|
2025-02-03 20:43:43 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Bootloader_Reset();
|
2025-02-05 00:13:59 +08:00
|
|
|
}*/
|
|
|
|
Bootloader_Reset();
|
2025-02-03 20:43:43 +08:00
|
|
|
}
|
|
|
|
}
|