2025-02-05 00:13:59 +08:00

1295 lines
40 KiB
C

/*
* 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__,
.ECUName = "WK-K86",
};
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 */
//SBC_Write_RegField(SBC_M_S_CTRL, SBC_M_S_CTRL_MODE_Msk, SBC_M_S_CTRL_MODE_Pos, SBC_MODE_RESET, NULL);
}
/*! \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;
/*//SBC RESET
if (sBootloader_Cb.resetReqMode == 1)
{
Bootloader_HardReset();
}
else
{
Bootloader_Reset();
}*/
Bootloader_Reset();
}
}