01_SDK/modules/hal/panchip/panplat/pan1070/bsp/peripheral/src/pan_fmc.c
@@ -14,6 +14,7 @@
#define BIT(x)   (0x1UL << (x))
FLASH_IDS_T flash_ids = {0};
uint8_t ft_chip_info;
static void FMC_TrigErrorHandler(FLCTL_T *fmc)
{
@@ -26,6 +27,11 @@
        FMC_ReadByte(FLCTL, 0x1000, CMD_DREAD);
        FMC_WriteDisable(FLCTL);
    }
}
void FMC_ParamsSet(OTP_STRUCT_T *otp)
{
    ft_chip_info = otp->m.chip_info;
}
void FMC_GetFlashUniqueId(FLCTL_T *fmc)
@@ -52,6 +58,10 @@
   flash_ids.manufacturer_id = FLCTL_BUFF->X_FL_BUFFER[0];
   flash_ids.memory_type_id = FLCTL_BUFF->X_FL_BUFFER[1];
   flash_ids.memory_density_id = FLCTL_BUFF->X_FL_BUFFER[2];
    if (((ft_chip_info & 0x1F) == 0x2) && (flash_ids.manufacturer_id == 0xC4)) {
        flash_ids.memory_density_id = 0x12;
    }
}
void FMC_SetFlashCapacity(FLCTL_T *fmc)
@@ -171,6 +181,18 @@
  */
int FMC_Erase(FLCTL_T *fmc,unsigned int Addr,unsigned char cmd)
{
#if FMC_DBG_LOG
   if (cmd == CMD_ERASE_SECTOR) {
       SYS_TEST("Erase Addr: 0x%08x (Sector Erase)\n", Addr);
   } else if (cmd == CMD_ERASE_32K) {
       SYS_TEST("Erase Addr: 0x%08x (BLK32k Erase)\n", Addr);
   } else if (cmd == CMD_ERASE_64K) {
       SYS_TEST("Erase Addr: 0x%08x (BLK64k Erase)\n", Addr);
   } else {
       SYS_TEST("Unhandled Erase CMD, Addr: 0x%08x, CMD: %d\n", Addr, cmd);
   }
#endif
   unsigned char offset = 0;
   unsigned char bytes_num_w;
@@ -193,7 +215,7 @@
   fmc->X_FL_TRIG = CMD_TRIG;
   while(fmc->X_FL_TRIG){}
    FMC_TrigErrorHandler(fmc);
   while(FMC_ReadStatusReg(fmc,CMD_READ_STATUS_L) & Write_In_Process_Msk) {}
//   while(FMC_ReadStatusReg(fmc,CMD_READ_STATUS_L) & Write_In_Process_Msk) {}
   return 0;
}
@@ -213,6 +235,11 @@
    if (addr >= FMC_GetFlashCodeAreaSize(fmc)) {
        return -1;
    }
    // Ensure we will not touch the flash INFO area
    fmc->X_FL_CONFIG &= ~BIT1;  //clear info_en bit
    fmc->X_FL_CONFIG |= BIT2;   //set tx_address_transaction bit
    return FMC_Erase(fmc,addr,CMD_ERASE_SECTOR);
}
@@ -238,6 +265,11 @@
        || (addr < 0x7000)) {
        return -1;
    }
    // Ensure we will not touch the flash INFO area
    fmc->X_FL_CONFIG &= ~BIT1;  //clear info_en bit
    fmc->X_FL_CONFIG |= BIT2;   //set tx_address_transaction bit
    return FMC_Erase(fmc,addr,CMD_ERASE_32K);
}
@@ -263,25 +295,12 @@
        || (addr < 0xF000)) {
        return -1;
    }
    return FMC_Erase(fmc,addr,CMD_ERASE_64K);
}
/**
  * @brief Erase the whole flash memory.
  *
  * This function is used to erase all data in flash, include
  * Code Area and Info Area.
  *
  * @note This API should only be used when you really know what
  * you are doing.
  *
  * @param fmc: where fmc is a flash peripheral.
  * @retval 0: Success.
  * @retval -1: Fail.
  */
int FMC_EraseChip(FLCTL_T *fmc)
{
    return FMC_Erase(fmc,0x0,CMD_ERASE_CHIP);
    // Ensure we will not touch the flash INFO area
    fmc->X_FL_CONFIG &= ~BIT1;  //clear info_en bit
    fmc->X_FL_CONFIG |= BIT2;   //set tx_address_transaction bit
    return FMC_Erase(fmc,addr,CMD_ERASE_64K);
}
static void find_special_chunk_in_range(size_t chunk_pattern, uint32_t range_start_sector_idx, uint16_t range_sector_num,
@@ -331,7 +350,7 @@
        return -1;
    }
    // Fine 32K blocks from the initial data chunk
    // Find 32K blocks from the initial data chunk
    find_special_chunk_in_range(8, start_phy_sector_idx, sector_num, &block_32k_start_sector_idx, &block_32k_sector_num);
    if (block_32k_sector_num == 0) { // No 32k-block found
@@ -418,7 +437,7 @@
  * @brief  This function is used to read flash,
  * @param  fmc: where fmc is a flash peripheral.
   * @param  Addr: where Addr is start address to read
   * @param  cmd: where cmd can be CMD_FAST_READ or CMD_NOR_READ
   * @param  cmd: where cmd can be \ref CMD_FAST_READ or \ref CMD_DREAD
  * @retval 4byte data
  */
unsigned int FMC_ReadWord(FLCTL_T *fmc,unsigned int Addr, unsigned char cmd)
@@ -451,7 +470,7 @@
  * @brief  This function is used to read flash,
  * @param  fmc: where fmc is a flash peripheral.
   * @param  Addr: where Addr is start address to read
   * @param  cmd: where cmd can be CMD_FAST_READ or CMD_NOR_READ
   * @param  cmd: where cmd can be \ref CMD_FAST_READ or \ref CMD_DREAD
  * @retval 1byte data
  */
unsigned char FMC_ReadByte(FLCTL_T *fmc,unsigned int Addr,unsigned char cmd)
@@ -485,7 +504,7 @@
  * @brief  This function is used to read a page size (256 bytes) of data from flash
  * @param  fmc     where fmc is a flash peripheral.
  * @param  Addr    where Addr is start address to read
  * @param  cmd     where cmd can be CMD_FAST_READ or CMD_NORM_READ
  * @param  cmd     where cmd can be \ref CMD_FAST_READ or \ref CMD_DREAD
  * @retval Internal Buffer address
  */
unsigned char *FMC_ReadPage(FLCTL_T *fmc,unsigned int Addr,unsigned char cmd)
@@ -544,16 +563,7 @@
   return (unsigned char *)&(FLCTL_BUFF->X_FL_BUFFER[0]);
}
/**
  * @brief  This function is used to read data stream from flash
  * @param  fmc     where fmc is a flash peripheral.
  * @param  Addr    where Addr is start address to read
  * @param  cmd     where cmd can be CMD_FAST_READ or CMD_NORM_READ
  * @param  buf     where buf is a buffer to store read data
  * @param  len     where len is data length of bytes to read
  * @retval None
  */
int FMC_ReadStream(FLCTL_T *fmc, unsigned int Addr, unsigned char cmd, unsigned char *buf, unsigned int len)
static int FMC_ReadStreamInternal(FLCTL_T *fmc, unsigned int Addr, unsigned char cmd, unsigned char *buf, unsigned int len)
{
    unsigned int tmp_addr = Addr;
    unsigned int tmp_size = len;
@@ -577,6 +587,24 @@
    }
    return 0;
}
/**
  * @brief  This function is used to read data stream from flash
  * @param  fmc     where fmc is a flash peripheral.
  * @param  Addr    where Addr is start address to read
  * @param  cmd     where cmd can be \ref CMD_FAST_READ or \ref CMD_DREAD
  * @param  buf     where buf is a buffer to store read data
  * @param  len     where len is data length of bytes to read
  * @retval None
  */
int FMC_ReadStream(FLCTL_T *fmc, unsigned int Addr, unsigned char cmd, unsigned char *buf, unsigned int len)
{
    // Ensure we will not touch the flash INFO area
    fmc->X_FL_CONFIG &= ~BIT1;  //clear info_en bit
    fmc->X_FL_CONFIG |= BIT2;   //set tx_address_transaction bit
    return FMC_ReadStreamInternal(fmc, Addr, cmd, buf, len);
}
/**
  * @brief  This function is used to write data to buffer,
@@ -707,17 +735,43 @@
    if (OffsetOfCurrPage + size > 256)
        return -1;
    if(FMC_WriteEnable(fmc) == 0)
        return -1;
    // Fill the 256-Bytes FMC Write Buffer
    for(size_t i = 0; i < 256; i++)
    if (flash_ids.manufacturer_id == 0x85)
    {
        if ((i >= OffsetOfCurrPage) && (i < OffsetOfCurrPage + size))
            FLCTL_BUFF->X_FL_BUFFER[i] = *(buf++);
        if (size < 256)
        {
            // Read page back
            FMC_ReadPage(fmc, PageStartAddr, CMD_DREAD);
            // Fill anticipatory data to fmc write buffer
            for (size_t i = 0; i < size; i++)
            {
                FLCTL_BUFF->X_FL_BUFFER[OffsetOfCurrPage + i] = *(buf++);
            }
            // Erase current page
            FMC_Erase(FLCTL, PageStartAddr, CMD_ERASE_PAGE);
        }
        else
            FLCTL_BUFF->X_FL_BUFFER[i] = 0xFF;
        {
            // Fill the 256-Bytes FMC Write Buffer
            for (size_t i = 0; i < 256; i++)
            {
                FLCTL_BUFF->X_FL_BUFFER[i] = *(buf++);
            }
        }
    }
    else
    {
        // Fill the 256-Bytes FMC Write Buffer
        for (size_t i = 0; i < 256; i++)
        {
            if ((i >= OffsetOfCurrPage) && (i < OffsetOfCurrPage + size))
                FLCTL_BUFF->X_FL_BUFFER[i] = *(buf++);
            else
                FLCTL_BUFF->X_FL_BUFFER[i] = 0xFF;
        }
    }
    if (FMC_WriteEnable(fmc) == 0)
        return -1;
    fmc->X_FL_CTL = (0<<8) | (0x04<<0);
    fmc->X_FL_CONFIG |= 0x1; //pp active
@@ -733,15 +787,7 @@
    return 0;
}
/**
  * @brief  This function is used to write data stream to flash
  * @param  fmc     where fmc is a flash peripheral
  * @param  Addr    where Addr is start address to write, can be any valid address
  * @param  buf     where buf is a buffer to store data to write
  * @param  len     where len is data length of bytes to write
  * @retval None
  */
int FMC_WriteStream(FLCTL_T *fmc, unsigned int Addr, unsigned char *buf, unsigned int len)
static int FMC_WriteStreamInternal(FLCTL_T *fmc, unsigned int Addr, unsigned char *buf, unsigned int len)
{
    unsigned int OffsetOfFirstPage = Addr % 256;
    unsigned int WriteSizeInFirstPage = (len < (256 - OffsetOfFirstPage)) ? len : (256 - OffsetOfFirstPage);
@@ -786,10 +832,27 @@
}
/**
  * @brief  This function is used to write data stream to flash
  * @param  fmc     where fmc is a flash peripheral
  * @param  Addr    where Addr is start address to write, can be any valid address
  * @param  buf     where buf is a buffer to store data to write
  * @param  len     where len is data length of bytes to write
  * @retval None
  */
int FMC_WriteStream(FLCTL_T *fmc, unsigned int Addr, unsigned char *buf, unsigned int len)
{
    // Ensure we will not touch the flash INFO area
    fmc->X_FL_CONFIG &= ~BIT1;  //clear info_en bit
    fmc->X_FL_CONFIG |= BIT2;   //set tx_address_transaction bit
    return FMC_WriteStreamInternal(fmc, Addr, buf, len);
}
/**
  * @brief  This function is used to read data from the flash 4KB INFO area.
  * @param  fmc     where fmc is a flash peripheral.
  * @param  Addr    where Addr is start address to read, can be 0 ~ 4095
  * @param  cmd     where cmd can be CMD_FAST_READ or CMD_NORM_READ
  * @param  cmd     where cmd can be \ref CMD_FAST_READ or \ref CMD_DREAD
  * @param  buf     where buf is a buffer to store read data
  * @param  len     where len is data length of bytes to read
  * @retval 0   read success
@@ -805,7 +868,7 @@
    fmc->X_FL_CONFIG |= BIT1;   //set info_en bit
    fmc->X_FL_CONFIG |= BIT2;   //set tx_address_transaction bit
    FMC_ReadStream(fmc, Addr, cmd, buf, len);
    FMC_ReadStreamInternal(fmc, Addr, cmd, buf, len);
    fmc->X_FL_CONFIG &= ~BIT1;  //clear info_en bit
    fmc->X_FL_CONFIG |= BIT2;   //set tx_address_transaction bit
@@ -819,6 +882,9 @@
  * @param  Addr    where Addr is start address to write, can be 0 ~ 4095
  * @param  buf     where buf is a buffer to store data to write
  * @param  len     where len is data length of bytes to write
  * @note   [CAUTION!] This is a dangerous API! It may destroy the calibrate
  *         data of SoC, do not call this API if you are not sure the actual
  *         behavior of it!
  * @retval 0   write success
  * @retval -1  write fail
  */
@@ -832,7 +898,7 @@
    fmc->X_FL_CONFIG |= BIT1;   //set info_en bit
    fmc->X_FL_CONFIG |= BIT2;   //set tx_address_transaction bit
    FMC_WriteStream(fmc, Addr, buf, len);
    FMC_WriteStreamInternal(fmc, Addr, buf, len);
    fmc->X_FL_CONFIG &= ~BIT1;  //clear info_en bit
    fmc->X_FL_CONFIG |= BIT2;   //set tx_address_transaction bit
@@ -853,7 +919,7 @@
    fmc->X_FL_CONFIG |= BIT1;   //set info_en bit
    fmc->X_FL_CONFIG |= BIT2;   //set tx_address_transaction bit
    ret = FMC_EraseSector(fmc, 0x0);
    ret = FMC_Erase(fmc, 0x0, CMD_ERASE_SECTOR);
    fmc->X_FL_CONFIG &= ~BIT1;  //clear info_en bit
    fmc->X_FL_CONFIG |= BIT2;   //set tx_address_transaction bit