/* * 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 #include #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(); } }