#include "dev_boot.h"

static uint32_t pdwCrc32Tbl[256]={0};

static void InitCrc32Table(void)
{
    for (int wCnt = 0; wCnt != 256; wCnt++)
    {
        uint32_t dwCrc = wCnt;

        for (int ucCnt = 0; ucCnt != 8; ucCnt++)
        {
            if (dwCrc & 1)
            {
                dwCrc = (dwCrc >> 1) ^ 0xEDB88320;
            }
            else
            {
                dwCrc >>= 1;
            }
        }

        pdwCrc32Tbl[wCnt] = dwCrc;
    }
}

void dev_boot_read_param(boot_para_t *pParam)
{
	hdl_flash_read_data(FLASH_BINFO_BASE,(uint8_t *)pParam,sizeof(boot_para_t));
}

int dev_boot_write_param(boot_para_t Param)
{
    int res = LL_OK;
    
	int wLen;
	uint32_t *pData;
	
	pData= (uint32_t *)&Param;
    
	wLen = sizeof(boot_para_t);
   
    hdl_flash_unlock();
	/* Erase sector. */
	res = hdl_flash_erase_sector(FLASH_BINFO_BASE,FLASH_BINFO_SIZE);
   
    if(res == LL_OK){
    
      res = hdl_flash_write_data (FLASH_BINFO_BASE, (uint8_t *)pData, wLen);
    }
    
     hdl_flash_lock();
    
    return res;
}


void dev_boot_erase_app(void)
{
	hdl_flash_unlock();
	
	for(int Addr = FLASH_APP_BASE; Addr < FLASH_APP_SIZE; Addr += FLASH_SECTOR_SIZE) {
        
		EFM_SectorErase(Addr);
        
        SWDT_FeedDog();

	}
		/* Lock EFM. */
    hdl_flash_lock();
}

void  dev_boot_write_app(uint32_t AddrOffset, uint8_t* wData, int wLen)
{
    hdl_flash_unlock();
    
    hdl_flash_write_data (FLASH_APP_BASE + AddrOffset, (uint8_t *)wData, wLen);
    
    hdl_flash_lock();
}


uint8_t dev_boot_check_app(void)
{
    uint32_t AppAddr =FLASH_APP_BASE;
    
    uint32_t u32StackTop = *((__IO uint32_t*)AppAddr);

    if ((u32StackTop > SRAM_BASE) && (u32StackTop <= (SRAM_BASE + SRAM_SIZE)))
    {

        return 1;
    }

    return 0;
}


void dev_boot_run_app(void)
{
    volatile uint32_t JumpAddress;
    
    func_ptr_t JumpToApplication;

    uint32_t AppAddr =FLASH_APP_BASE;
    
    uint32_t u32StackTop = *((__IO uint32_t*)AppAddr);

    if ((u32StackTop > SRAM_BASE) && (u32StackTop <= (SRAM_BASE + SRAM_SIZE)))
    {
        JumpAddress = *(__IO uint32_t*)(AppAddr + 4);

        JumpToApplication = (func_ptr_t)JumpAddress;

        __disable_fiq();

        __set_MSP(*(__IO uint32_t*)AppAddr);

        JumpToApplication();
    }
}


uint32_t dev_boot_get_app_crc32(int dwLen)
{
    if(dwLen >= 0xFFFFFFFF)
    return 0;

    InitCrc32Table();  
    
    uint32_t Data;
    uint32_t dwCrc32Data = 0xFFFFFFFF;

    for (int dwCnt = 0; dwCnt != dwLen; ++dwCnt)
    {
        Data = *((volatile uint8_t*)(FLASH_APP_BASE + dwCnt));
        
        uint32_t dwTbl = (dwCrc32Data ^ Data) & 0xFF;
        
        dwCrc32Data = ((dwCrc32Data >> 8) & 0xFFFFFF) ^ pdwCrc32Tbl[dwTbl];
    }

    return ~dwCrc32Data;
}
