- #include "bsp_flash.h"
- const uint16_t FlashSec_Tab[24][2] =
- {
- {0,FLASH_Sector_0},
- {1,FLASH_Sector_1},
- {2,FLASH_Sector_2},
- {3,FLASH_Sector_3},
- {4,FLASH_Sector_4},
- {5,FLASH_Sector_5},
- {6,FLASH_Sector_6},
- {7,FLASH_Sector_7},
- {8,FLASH_Sector_8},
- {9,FLASH_Sector_9},
- {10,FLASH_Sector_10},
- {11,FLASH_Sector_11},
- {12,FLASH_Sector_12},
- {13,FLASH_Sector_13},
- {14,FLASH_Sector_14},
- {15,FLASH_Sector_15},
- {16,FLASH_Sector_16},
- {17,FLASH_Sector_17},
- {18,FLASH_Sector_18},
- {19,FLASH_Sector_19},
- {20,FLASH_Sector_20},
- {21,FLASH_Sector_21},
- {22,FLASH_Sector_22},
- {23,FLASH_Sector_23},
- };
- static uint8_t Fmc_get_Sector_index( int sector_num)
- {
- uint8_t index = 0;
- for(int i = 0; i < 24; i++)
- {
- if(sector_num == FlashSec_Tab[i][1])
- {
- index = i;
- break;
- }
- }
- return index;
- }
- /*!
- \brief 连续擦除多个扇区
- \param[in] sec_num 起始扇区号( FLASH_Sector_0 ~ FLASH_Sector_23)
- \param[in] sec_count 扇区数量
- \retval none
- */
- ErrStatus BSP_fmc_erase_sectors(uint32_t sec_num, int sec_count)
- {
- uint8_t index = 0;
- fmc_unlock();
- /* clear pending flags */
- fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_OPERR | FMC_FLAG_WPERR\
- | FMC_FLAG_PGMERR | FMC_FLAG_PGSERR);
- index = Fmc_get_Sector_index( sec_num );
- for(int i = 0; i < sec_count; i++)
- {
- fmc_sector_erase(CTL_SN(index + i));
- //printf("Erase sector index = %d!\r\n", (index+i));
- }
- /* lock the flash program erase controller */
- fmc_lock();
- return SUCCESS;
- }
- /********************************************************************
- \brief 从address 起始地址处 连续读出length个字到 Outbuff中,
- \param[1] length 为字的数量, sizeof = length*4
- \param[2] 读出来的 Outbuff指针
- \retval none
- ********************************************************************/
- void BSP_fmc_read_Wrod(uint32_t address, uint16_t length, uint32_t* Outbuff)
- {
- for(int i = 0; i < length; i++)
- {
- Outbuff[i] = *(volatile uint32_t*)(address);
- address = address + 4;
- }
- }
- /********************************************************************
- \brief 不检查 连续写入length个字到flash
- \param[1] length 为字的数量, sizeof = length*4
- \param[2] 要写入的 u32 buff
- \retval none
- ********************************************************************/
- void BSP_fmc_write_Word_NoCheck(uint32_t address, uint32_t length, uint32_t* data_32)
- {
- /* unlock the flash program erase controller */
- fmc_unlock();
- /* clear pending flags */
- fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_OPERR | FMC_FLAG_WPERR | FMC_FLAG_PGMERR | FMC_FLAG_PGSERR);
- /* write data_32 to the corresponding address */
- for(int i=0; i<length; i++)
- {
- if(FMC_READY == fmc_word_program(address, data_32[i]))
- {
- address = address + 4;
- }
- }
- fmc_lock();
- }
- /********************************************************************
- \brief 擦除某个扇区中的某一页(4KB)
- \param[1] Sector起始地址
- \param[2] 页 index: 0 ~ 31
- \retval none
- ********************************************************************/
- void BSP_fmc_erase_page(uint32_t sector_addr, int index)
- {
- fmc_unlock();
- fmc_flag_clear(FMC_FLAG_END| FMC_FLAG_WPERR| FMC_FLAG_PGMERR);
- fmc_page_erase(sector_addr + FMC_PAGE_SIZE*index);
- fmc_lock();
- }
- /********************************************************************
- \brief 擦除某个扇区中的多页(4KB)
- \param[1] Sector起始地址
- \param[2] start_page_index 起始页 : 0 ~ 63
- \param[3] page_num 页数量 : 1 ~ 64(256kb)
- \note 跨扇区擦除,最多支持2个连续的扇区
- \retval none
- ********************************************************************/
- void BSP_fmc_erase_multi_pages(uint32_t sector_addr, int start_page_index, int page_num)
- {
- fmc_unlock();
- fmc_flag_clear(FMC_FLAG_END| FMC_FLAG_WPERR| FMC_FLAG_PGMERR);
- for(int i = start_page_index; i < (page_num + start_page_index); i++)
- {
- fmc_page_erase(sector_addr + FMC_PAGE_SIZE*i);
- }
- fmc_lock();
- }
- /********************************************************************
- \brief 擦除整个bank
- \param[1] void
- \note erase whole bank1
- \retval none
- ********************************************************************/
- void BSP_fmc_erase_bank1(void)
- {
- fmc_unlock();
- fmc_flag_clear(FMC_FLAG_END| FMC_FLAG_WPERR| FMC_FLAG_PGMERR);
- fmc_bank1_erase();
- fmc_lock();
- }
- /*!
- \brief CHECK 4KB 页内容是否为空(FF)
- \param[in] address 实际地址(Must 4KB 对齐)
- \param[in] sec_count 扇区数量
- \retval TRUE Blank FALSE Not Blank
- */
- bool BSP_fmc_page_is_blank_Check(uint32_t address)
- {
- uint32_t readout = 0;
- for(int i = 0; i < FMC_PAGE_SIZE; i+=4)
- {
- readout = *(volatile int32_t*)(address + i);
- if(readout != 0xffffffff)
- {
- return false;
- }
- }
- return true;
- }
- /*!
- \brief CHECK 一个扇区内容是否为空(FF)
- \param[in] address 实际地址(Must 扇区 对齐)
- \retval TRUE Blank FALSE Not Blank
- \note: 此函数只针对128kb大小的扇区
- */
- bool BSP_fmc_sectors_is_blank_Check(uint32_t address)
- {
- uint32_t buff;
- for(int i = 0; i < SIZE_128KB; i+=4)
- {
- buff = *(volatile uint32_t*)(address + i);
- if(buff != 0xffffffff)
- {
- return false;
- }
- }
- return true;
- }
- /*!
- \brief get the sector number, size and range of the given address
- \param[in] address: The flash address
- \param[out] none
- \retval fmc_sector_info_struct: The information of a sector
- */
- fmc_sector_info_struct fmc_sector_info_get(uint32_t addr)
- {
- fmc_sector_info_struct sector_info;
- uint32_t temp = 0x00000000U;
- if((FMC_START_ADDRESS <= addr)&&(FMC_END_ADDRESS >= addr)) {
- if ((FMC_BANK1_START_ADDRESS > addr)) {
- /* bank0 area */
- temp = (addr - FMC_BANK0_START_ADDRESS) / SIZE_16KB;
- if (4U > temp) {
- sector_info.sector_name = (uint32_t)temp;
- sector_info.sector_num = CTL_SN(temp);
- sector_info.sector_size = SIZE_16KB;
- sector_info.sector_start_addr = FMC_BANK0_START_ADDRESS + (SIZE_16KB * temp);
- sector_info.sector_end_addr = sector_info.sector_start_addr + SIZE_16KB - 1;
- } else if (8U > temp) {
- sector_info.sector_name = 0x00000004U;
- sector_info.sector_num = CTL_SN(4);
- sector_info.sector_size = SIZE_64KB;
- sector_info.sector_start_addr = 0x08010000U;
- sector_info.sector_end_addr = 0x0801FFFFU;
- } else {
- temp = (addr - FMC_BANK0_START_ADDRESS) / SIZE_128KB;
- sector_info.sector_name = (uint32_t)(temp + 4);
- sector_info.sector_num = CTL_SN(temp + 4);
- sector_info.sector_size = SIZE_128KB;
- sector_info.sector_start_addr = FMC_BANK0_START_ADDRESS + (SIZE_128KB * temp);
- sector_info.sector_end_addr = sector_info.sector_start_addr + SIZE_128KB - 1;
- }
- } else {
- /* bank1 area */
- temp = (addr - FMC_BANK1_START_ADDRESS) / SIZE_16KB;
- if (4U > temp) {
- sector_info.sector_name = (uint32_t)(temp + 12);
- sector_info.sector_num = CTL_SN(temp + 16);
- sector_info.sector_size = SIZE_16KB;
- sector_info.sector_start_addr = FMC_BANK0_START_ADDRESS + (SIZE_16KB * temp);
- sector_info.sector_end_addr = sector_info.sector_start_addr + SIZE_16KB - 1;
- } else if (8U > temp) {
- sector_info.sector_name = 0x00000010;
- sector_info.sector_num = CTL_SN(20);
- sector_info.sector_size = SIZE_64KB;
- sector_info.sector_start_addr = 0x08110000U;
- sector_info.sector_end_addr = 0x0811FFFFU;
- } else if (64U > temp){
- temp = (addr - FMC_BANK1_START_ADDRESS) / SIZE_128KB;
- sector_info.sector_name = (uint32_t)(temp + 16);
- sector_info.sector_num = CTL_SN(temp + 20);
- sector_info.sector_size = SIZE_128KB;
- sector_info.sector_start_addr = FMC_BANK1_START_ADDRESS + (SIZE_128KB * temp);
- sector_info.sector_end_addr = sector_info.sector_start_addr + SIZE_128KB - 1;
- } else {
- temp = (addr - FMC_BANK1_START_ADDRESS) / SIZE_256KB;
- sector_info.sector_name = (uint32_t)(temp + 20);
- sector_info.sector_num = CTL_SN(temp + 8);
- sector_info.sector_size = SIZE_256KB;
- sector_info.sector_start_addr = FMC_BANK1_START_ADDRESS + (SIZE_256KB * temp);
- sector_info.sector_end_addr = sector_info.sector_start_addr + SIZE_256KB - 1;
- }
- }
- } else {
- /* invalid address */
- sector_info.sector_name = FMC_WRONG_SECTOR_NAME;
- sector_info.sector_num = FMC_WRONG_SECTOR_NUM;
- sector_info.sector_size = FMC_INVALID_SIZE;
- sector_info.sector_start_addr = FMC_INVALID_ADDR;
- sector_info.sector_end_addr = FMC_INVALID_ADDR;
- }
- return sector_info;
- }
- /*!
- \brief get the sector number by a given sector name
- \param[in] address: a given sector name
- \param[out] none
- \retval uint32_t: sector number
- */
- uint32_t sector_name_to_number(uint32_t sector_name)
- {
- if(11 >= sector_name){
- return CTL_SN(sector_name);
- }else if(23 >= sector_name){
- return CTL_SN(sector_name + 4);
- }else if(27 >= sector_name){
- return CTL_SN(sector_name - 12);
- }else{
- while(1);
- }
- }
- int bsw_drv_flash_erase ( uint32_t address )
- {
- fmc_sector_info_struct sector_info;
- // printf("\r\nFMC erase operation:\n");
- /* get information about the sector in which the specified address is located */
- sector_info = fmc_sector_info_get(address);
- if(FMC_WRONG_SECTOR_NAME == sector_info.sector_name){
- // printf("\r\nWrong address!\n");
- return CL_FAIL;
- }else{
- // printf("\r\nErase start ......\n");
- /* unlock the flash program erase controller */
- fmc_unlock();
- /* clear pending flags */
- fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_OPERR | FMC_FLAG_WPERR | FMC_FLAG_PGMERR | FMC_FLAG_PGSERR);
- /* wait the erase operation complete*/
- if(FMC_READY != fmc_sector_erase(sector_info.sector_num)){
- return CL_FAIL;
- }
- /* lock the flash program erase controller */
- fmc_lock();
- // printf("\r\nAddress 0x%08X is located in the : SECTOR_NUMBER_%d !\n", address, sector_info.sector_name);
- // printf("\r\nSector range: 0x%08X to 0x%08X\n", sector_info.sector_start_addr, sector_info.sector_end_addr);
- // printf("\r\nSector size: %d KB\n", (sector_info.sector_size/1024));
- // printf("\r\nErase success!\n");
- // printf("\r\n");
- return CL_OK;
- }
- }
- //写数据前会自动先擦除
- int bsw_drv_flash_write ( uint32_t address , uint8_t* buf , uint16_t length )
- {
- uint16_t writeNum;
- uint32_t data = 0;
- fmc_sector_info_struct start_sector_info;
- fmc_sector_info_struct end_sector_info;
- uint32_t sector_num,i;
-
- // printf("\r\nFMC word programe operation:\n");
- /* unlock the flash program erase controller */
- fmc_unlock();
- /* clear pending flags */
- fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_OPERR | FMC_FLAG_WPERR | FMC_FLAG_PGMERR | FMC_FLAG_PGSERR);
- /* get the information of the start and end sectors */
- start_sector_info = fmc_sector_info_get(address);
- end_sector_info = fmc_sector_info_get(address + length);
- /* erase sector */
- for(i = start_sector_info.sector_name; i <= end_sector_info.sector_name; i++){
- sector_num = sector_name_to_number(i);
- if(FMC_READY != fmc_sector_erase(sector_num)){
- return CL_FAIL;
- }
- }
- if ( length % 4 == 0 )
- {
- writeNum = length / 4;
- }
- else
- {
- writeNum = length / 4 + 1;
- }
- /* write data_32 to the corresponding address */
- for(i=0; i<writeNum; i++){
- memcpy ( &data , buf + i * 4 , 4 );
- if(FMC_READY == fmc_word_program(address, data)){
- address = address + 4;
- }else{
- return CL_FAIL;
- }
- }
- /* lock the flash program erase controller */
- fmc_lock();
- // printf("\r\nWrite complete!\n");
- // printf("\r\n");
- return CL_OK;
- }
- int bsw_drv_flash_read ( uint32_t address , uint8_t* data_8 , uint16_t length )
- {
- uint16_t i;
- if ( address < FLASH_BASE ) //非法地址
- {
- return CL_FAIL;
- }
-
- for(i=0; i<length; i++){
- data_8[i] = (*(volatile uint8_t *)(uint32_t)(address));
- address++;
- }
- return CL_OK;
- }