/*
 * flash.c
 *
 *  Created on: 2019. 7. 15.
 *      Author: parkyj
 */
#include "main.h"

uint32_t GetSector(uint32_t);

uint8_t flashinit = 0;
uint32_t Address = FLASH_USER_START_ADDR;

typedef void (*fptr)(void);
fptr jump_to_app;
uint32_t jump_addr;
void Jump_App(void){
    __HAL_RCC_TIM6_CLK_DISABLE(); // 筌띲끉�뵥???�뜝�룞�삕�솒紐뚯삕?? ?�뜝�룞�삕�뜝占�??�뜝�룞�삕?�뜝�룞�삕?�뜝�룞�삕
    printf("boot loader start\n");               //筌롫뗄苑��뜝占�? �빊�뮆�젾
    jump_addr = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
    jump_to_app = (fptr) jump_addr;
    
    /* init user app's sp */
    printf("jump!\n");
    __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
    jump_to_app();
}


void FLASH_If_Init(void)
{
  /* Unlock the Program memory */
  HAL_FLASH_Unlock();

  /* Clear all FLASH flags */
  __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | 
                  FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);
  /* Unlock the Program memory */
  HAL_FLASH_Lock();
}

void Flash_InitRead(void) // ?�뜝�룞�삕疫꿸퀬釉�?�뜝�룞�삕
{
    uint32_t  Address = 0;
    Address = FLASH_USER_START_ADDR;
    for(uint32_t i = 0; i < 16; i++ ){
        printf("%08x : %02X \n",Address ,*(uint8_t*)Address);
        Address++;
    }
#if 0 // PYJ.2019.03.27_BEGIN -- 
    for(uint32_t i = 0; i < 13848; i++ ){
        printf("%08x : %02X \n",Address ,*(uint8_t*)Address);
        Address++;
    }
    Address = StartAddr;
    for(uint32_t i = 0; i < 13848; i++ ){
        printf("%02X ",*(uint8_t*)Address);
        Address++;
    }
#endif // PYJ.2019.03.27_END -- 

}

uint8_t Flash_RGB_Data_Write(uint8_t* data){
    uint16_t Firmdata = 0;
    uint8_t ret = 0;
    for(uint8_t i = 0; i < data[bluecell_length] - 2; i+=2){
        Firmdata  = ((data[(bluecell_length + 1) + i]) & 0x00FF);
        Firmdata  += ((data[(bluecell_length + 1) + (i + 1)] << 8) & 0xFF00);
        if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD,Address ,   (uint16_t)Firmdata) != HAL_OK){
            printf("HAL NOT OK \n");
            ret = 1;
        }
        Address += 2;
        //if(!(i%FirmwareUpdateDelay))
      //  HAL_Delay(1);
    }
    return ret;
}
HAL_StatusTypeDef EraseFlash()
{
  uint32_t SectorError = 0;
  
  /* Unlock to control */
  HAL_FLASH_Unlock();
  
  /* Calculate sector index */
  uint32_t UserSector = GetSector(FLASH_USER_START_ADDR);
  uint32_t NbOfSectors = GetSector(FLASH_USER_END_ADDR) - UserSector + 1;
  
  /* Erase sectors */
  FLASH_EraseInitTypeDef EraseInitStruct;
  EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
  EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
  EraseInitStruct.Sector = UserSector;
  EraseInitStruct.NbSectors = NbOfSectors;
  
  if(HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK)
  { 
    uint32_t errorcode = HAL_FLASH_GetError();            
    return HAL_ERROR;
  }
  
  /* Clear cache for flash */
  __HAL_FLASH_DATA_CACHE_DISABLE();
  __HAL_FLASH_INSTRUCTION_CACHE_DISABLE();
  
  __HAL_FLASH_DATA_CACHE_RESET();
  __HAL_FLASH_INSTRUCTION_CACHE_RESET();
  
  __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
  __HAL_FLASH_DATA_CACHE_ENABLE();
  
  /* Lock flash control register */
  HAL_FLASH_Lock();
  
  return HAL_OK;  
}


uint8_t Flash_write(uint8_t* data) // ?�뜝�룞�삕疫꿸퀬釉�?�뜝�룞�삕
{
    uint32_t SectorError = 0;
    uint32_t UserSector = GetSector(FLASH_USER_START_ADDR);

    /*Variable used for Erase procedure*/
    static FLASH_EraseInitTypeDef EraseInitStruct;
    static uint32_t PAGEError = 0;
    uint8_t ret = 0;
    /* Fill EraseInit structure*/
    EraseInitStruct.TypeErase   = FLASH_TYPEERASE_SECTORS;
    EraseInitStruct.Sector      = FLASH_USER_START_ADDR;
//    EraseInitStruct.NbPages     = (FLASH_USER_END_ADDR - FLASH_USER_START_ADDR) / FLASH_PAGE_SIZE;
    EraseInitStruct.NbSectors     = GetSector(FLASH_USER_END_ADDR) - UserSector + 1;
    uint32_t NbOfSectors = 

    __HAL_RCC_TIM6_CLK_DISABLE(); // 筌띲끉�뵥???�뜝�룞�삕�솒紐뚯삕?? ?�뜝�룞�삕�뜝占�??�뜝�룞�삕?�뜝�룞�삕?�뜝�룞�삕
    HAL_FLASH_Unlock(); // lock ??�뜝占�?
    if(flashinit == 0){
        flashinit= 1;
        //FLASH_PageErase(StartAddr);
//        if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK){
//            printf("Erase Failed \r\n");
//        }
        EraseFlash();

    }
//    FLASH_If_Erase();
    ret = Flash_RGB_Data_Write(&data[bluecell_stx]);
    HAL_FLASH_Lock(); // lock ?�뜝�룞�삕域밸㈇由�
    __HAL_RCC_TIM6_CLK_ENABLE(); // 筌띲끉�뵥???�뜝�룞�삕�솒紐뚯삕?? ?�뜝�룞�삕?�뜝�룞�삕?�뜝�룞�삕?�뜝�룞�삕?�뜝�룞�삕?�뜝�룞�삕

    return ret;

}
uint32_t GetSector(uint32_t Address)
{
  uint32_t sector = 0;
  
  if((Address < FLASH_SECTOR_1) && (Address >= FLASH_SECTOR_0))
  {
    sector = FLASH_SECTOR_0;  
  }
  else if((Address < FLASH_SECTOR_2) && (Address >= FLASH_SECTOR_1))
  {
    sector = FLASH_SECTOR_1;  
  }
  else if((Address < FLASH_SECTOR_3) && (Address >= FLASH_SECTOR_2))
  {
    sector = FLASH_SECTOR_2;  
  }
  else if((Address < FLASH_SECTOR_4) && (Address >= FLASH_SECTOR_3))
  {
    sector = FLASH_SECTOR_3;  
  }
  else if((Address < FLASH_SECTOR_5) && (Address >= FLASH_SECTOR_4))
  {
    sector = FLASH_SECTOR_4;  
  }
  else if((Address < FLASH_SECTOR_6) && (Address >= FLASH_SECTOR_5))
  {
    sector = FLASH_SECTOR_5;  
  }
  else if((Address < FLASH_SECTOR_7) && (Address >= FLASH_SECTOR_6))
  {
    sector = FLASH_SECTOR_6;  
  }
  else if((Address < FLASH_SECTOR_8) && (Address >= FLASH_SECTOR_7))
  {
    sector = FLASH_SECTOR_7;  
  }
  else if((Address < FLASH_SECTOR_9) && (Address >= FLASH_SECTOR_8))
  {
    sector = FLASH_SECTOR_8;  
  }
  else if((Address < FLASH_SECTOR_10) && (Address >= FLASH_SECTOR_9))
  {
    sector = FLASH_SECTOR_9;  
  }
  else if((Address < FLASH_SECTOR_11) && (Address >= FLASH_SECTOR_10))
  {
    sector = FLASH_SECTOR_10;  
  }
  else /* (Address < FLASH_END_ADDR) && (Address >= FLASH_SECTOR_11) */
  {
    sector = FLASH_SECTOR_11;
  }
  
  return sector;
}

uint32_t GetSectorSize(uint32_t Sector)
{
  uint32_t sectorsize = 0x00;
  
  if((Sector == FLASH_SECTOR_0) || (Sector == FLASH_SECTOR_1) || (Sector == FLASH_SECTOR_2) || (Sector == FLASH_SECTOR_3))
  {
    sectorsize = 16 * 1024;
  }
  else if(Sector == FLASH_SECTOR_4)
  {
    sectorsize = 64 * 1024;
  }
  else
  {
    sectorsize = 128 * 1024;
  }  
  return sectorsize;
}


