/*
 * 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.
 */

#ifndef _BOOTLOADER_H_
#define _BOOTLOADER_H_

/*! \brief Contains public interface to various functions related
 *         to the _BOOTLOADER module
 */

/*******************************************************************************
 * the includes
 ******************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "bootloader_cfg.h"
#include "fls.h"

#ifdef __cplusplus
extern "C" {
#endif

/*******************************************************************************
 * the defines
 ******************************************************************************/

/*******************************************************************************
 * the typedefs
 ******************************************************************************/

typedef void           (*pFls_InitFunctionPtr)(uint32_t flashDrvInstance);
typedef Fls_StdRtnType (*pFls_EraseFunctionPtr)(uint32_t targetAddress, uint32_t sectorNum);
typedef Fls_StdRtnType (*pFls_WriteFunctionPtr)(uint32_t targetAddress, const uint8_t *sourceAddressPtr, uint32_t bytesNum);
typedef Fls_StdRtnType (*pFls_ReadFunctionPtr)(uint32_t targetAddress, uint8_t *dataBuff, uint32_t bytesNum);
typedef uint32_t       (*pCalculateCheckSumFunctionPtr)(uint32_t initCrcValue, const uint8_t *dataBuffer, uint32_t bytesNum, bool inverted);
typedef bool           (*pGetBootReqFunctionPtr)(void);
typedef void           (*pJumpFunctionPtr)(void);
typedef void           (*pSwResetFunctionPtr)(void);
typedef void           (*pSetSessionModeFunctionPtr)(uint8_t sessionMode);
typedef void           (*pSetGlobalIsrFunctionPtr)(bool isEnabled);
typedef void           (*pUds_PositiveResponsePtr)(const uint8_t *data, uint16_t len);
typedef void           (*pUds_NegativeResponsePtr)(uint8_t sid, uint8_t rsp_nrc);
typedef uint8_t        (*pUds_PgmConditionCheckPtr)(void);

typedef enum
{
    BOOTLOADER_STATE_INIT = 0u,
    BOOTLOADER_STATE_ERASE,
    BOOTLOADER_STATE_PGM,
    BOOTLOADER_STATE_ERR,
    BOOTLOADER_STATE_CHECK,
    BOOTLOADER_STATE_EXIT,

    BOOTLOADER_STATE_NUM
} Bootloader_StateType;

typedef enum
{
    BOOLOADER_OBJECT_NONE = 0u,
    BOOLOADER_OBJECT_FLASH_DRIVER,
    BOOLOADER_OBJECT_APP_CODE,
    BOOLOADER_OBJECT_CALIBRATION_DATA,

    BOOLOADER_OBJECT_NUM
} Bootloader_ObjectType;

typedef enum
{
    BOOTLOADER_FLS_DRV_INIT = 0u,
    BOOTLOADER_FLS_DRV_ERASE,
    BOOTLOADER_FLS_DRV_WRITE,
    BOOTLOADER_FLS_DRV_NUM
} Bootloader_FlsDriverType;

typedef enum
{
    BOOTLOADER_SUB_STATE_NONE = 0u,
    BOOTLOADER_SUB_STATE_DOING,
    BOOTLOADER_SUB_STATE_END
} Bootloader_SubStateType;

typedef enum
{
    BOOTLOADER_EVENT_NONE = 0u,
    BOOTLOADER_EVENT_EMERGENCY_BOOT,
    BOOTLOADER_EVENT_RESET,
    BOOTLOADER_EVENT_ERASE,
    BOOTLOADER_EVENT_PGM_READY,
    BOOTLOADER_EVENT_PGM_START,
    BOOTLOADER_EVENT_PGM_EXIT,
    BOOTLOADER_EVENT_CHECK,

    BOOTLOADER_EVENT_NUM
} Bootloader_EventType;

typedef struct
{
    uint32_t eraseStartAddress;
    uint32_t eraseLength;
    uint32_t eraseSectionNums;
    uint32_t eraseSectionCnt;
} Bootloader_EraseInfoType;

typedef struct
{
    uint32_t pgmStartAddress;
    uint32_t pgmMemSize;
    uint32_t pgmMemCnt;
    uint32_t pgmBlockByteCnt;
    uint8_t  pgmBlockSn;
    uint8_t  pgmData[BOOTLOADER_CFG_PGM_BYTES_SIZE];
    uint32_t pgmCrc;
    bool     crcResult;
    bool     pgmReadyEn;
    bool     pgmStartTriggerEn;
} Bootloader_PgmInfoType;

typedef struct
{
    bool                  activeCheckReq;
    uint32_t              CheckStartAddress;
    uint32_t              CheckmemSize;
    Bootloader_ObjectType checkObj;
    uint32_t              checkCrc;
    bool                  crcResult;
} Bootloader_CheckCrcInfoType;

typedef struct
{
    uint32_t              flashInstanceAddr;
    uint32_t              startFlsInitAddr;
    uint32_t              startFlsClearCommandStateAddr;
    uint32_t              startFlsCommandSequenceAddr;
    uint32_t              startFlsEraseAddr;
    uint32_t              startFlsWriteAddr;
    uint32_t              startFlsReadAddr;
    pFls_InitFunctionPtr  flsInitFunction;
    pFls_EraseFunctionPtr flsEraseFunction;
    pFls_WriteFunctionPtr flsWriteFunction;
    pFls_ReadFunctionPtr  flsReadFunction;
    bool                  flashDriverDownloaded;
} Bootloader_FlsDrvInfoType;

typedef struct
{
    pSetGlobalIsrFunctionPtr      setGlobalIsrFunction;
    pCalculateCheckSumFunctionPtr calculateCheckSumFunction;
    pGetBootReqFunctionPtr        getBootReqFunction;
    pJumpFunctionPtr              jumpFunction;
    pSetSessionModeFunctionPtr    setSessionModeFunction;

    pUds_PositiveResponsePtr udsPositiveRespFunction;
    pUds_NegativeResponsePtr udsNegativeRespFunction;

    pSwResetFunctionPtr swResetFunction;

    pUds_PgmConditionCheckPtr pgmConditionChecFunction;

#if BOOTLOADER_CFG_FLS_COPY_AUTO_EN != 0u
    pFls_InitFunctionPtr  flsInitFunction;
    pFls_EraseFunctionPtr flsEraseFunction;
    pFls_WriteFunctionPtr flsWriteFunction;
    pFls_ReadFunctionPtr  flsReadFunction;
#endif
} Bootloader_CallBackFuncListType;

typedef struct
{
    uint32_t flashInstanceAddress;

    const Bootloader_CallBackFuncListType *pCallBackFunctionList;
    Bootloader_StateType                   bootState;
    Bootloader_SubStateType                bootSubState;
    Bootloader_EraseInfoType               eraseInfo;
    Bootloader_PgmInfoType                 pgmInfo;
    Bootloader_CheckCrcInfoType            checkInfo;
    bool                                   emergeBootReqEn;
    bool                                   resetReqEn;
    bool                                   resetActionReady;
    uint8_t                                resetReqMode;
    bool                                   bootActive;
#if BOOTLOADER_CFG_FLS_COPY_AUTO_EN == 0u
    Bootloader_FlsDrvInfoType flsDrvInfo;
#endif

    Bootloader_ObjectType downloadObj;
    uint32_t              stayInBootTimeoutCnt;
    Bootloader_EventType  eventReq;
} Bootloader_CbType;

/*******************************************************************************
 * the globals
 ******************************************************************************/

/*******************************************************************************
 * the function prototypes
 ******************************************************************************/
/*! \brief Initialize bootloader control block information
 *
 * This function Initialize bootloader control block information
 *
 * \param[in] flashInstanceAddress : flashdriver instance address
 * \param[in] pCallbackFuncList : call back function list
 *
 * \return void
 */
extern void Bootloader_Init(uint32_t flashInstanceAddress, const Bootloader_CallBackFuncListType *pCallbackFuncList);

/*! \brief Get the pgm condition
 *
 * This function get the pgm condition
 *
 * \param[in] void
 *
 * \return voltage state
 *         0: voltage normal
 *         1: voltage low
 *         2: voltage high
 */
extern uint8_t Bootloader_GetPgmCondition(void);

/*! \brief Get boot block size bytes
 *
 * This function get the pgm block byte size
 *
 * \param[in] void
 *
 * \return void
 */
extern uint32_t Bootloader_GetPgmBlockSize(void);

/*! \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
 */
extern void Bootloader_TimingProcess(uint8_t periodms);

/*! \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
 */
extern void Bootloader_SetBootState(Bootloader_StateType state);

/*! \brief Get the bootloader current state
 *
 * This function Get the bootloader current state
 *
 * \param[in] void
 *
 * \return : return the current state
 */
extern Bootloader_StateType Bootloader_GetBootState(void);

/*! \brief Get the bootloader current sub state
 *
 * This function Get the bootloader current sub state
 *
 * \param[in] void
 *
 * \return : return the current sub state
 */
extern Bootloader_SubStateType Bootloader_GetBootSubState(void);

/*! \brief Get the bootloader current crc result
 *
 * This function Get the bootloader current crc result
 *
 * \param[in] void
 *
 * \return : return the current crc result
 */
extern bool Bootloader_GetCrcResult(void);

/*! \brief Set emerge boot request
 *
 * This function Set emerge boot request
 *
 * \param[in] void
 *
 * \return void
 */
extern void Bootloader_EventEmergeBootRequest(bool requestEn);

/*! \brief Set the reset cup request
 *
 * This function Set the reset cup request
 *
 * \param[in] void
 *
 * \return void
 */
extern void Bootloader_EventResetRequest(bool requestEn,uint8_t resetMode);

/*! \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
 */
extern void Bootloader_EventEraseRequest(uint32_t startAddress, uint32_t bytesNum);

/*! \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
 */
extern void Bootloader_EventPgmReady(uint32_t startAddress, uint32_t bytesNum);

/*! \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
 */
extern bool Bootloader_EventPgmData(const uint8_t *pDatabuffer, uint16_t bytesNum, uint8_t blockSn);

/*! \brief data check request
 *
 * This function indication that data check request
 *
 * \param[in] memStart : memory start address
 * \param[in] memSize : memory size
 * \param[in] crc : crc result from EOL
 *
 * \return void
 */
extern void Bootloader_EventDataCheckRequest(uint32_t memStart, uint32_t memSize, uint32_t crc);

/*! \brief Bootloader main state process
 *
 * This function process the bootloader variant state
 *
 * \param[in] void
 *
 * \return void
 */
extern void Bootloader_StateProc(void);

#ifdef __cplusplus
}
#endif /* extern "C" */

#endif /* _BOOTLOADER_H_ */
