Hi jeremyzhou,
#include <stdint.h>
#include <stdbool.h>
#include "Flash.h"
#include "pos_inde.h"
#define BANK_A 0x1A000000
#define BANK_B 0x1B000000
#define FLASH_DATA(addr) (*((volatile uint32_t *) (addr)))
typedef void (*IAP_Entry) (unsigned long *cmd, unsigned long *stat);
#define IAP_Call ((IAP_Entry) *((unsigned long *)0x10400100))
uint32_t u4g_Flash_Clk = 180000;
const uint32_t FLASH_BANK_ADDR[31] = {
0x1A000000,0x1A002000,0x1A004000,0x1A006000,
0x1A008000,0x1A00A000,0x1A00C000,0x1A00E000,
0x1A010000,0x1A020000,0x1A030000,0x1A040000,
0x1A050000,0x1A060000,0x1A070000,
0x1B000000,0x1B002000,0x1B004000,0x1B006000,
0x1B008000,0x1B00B000,0x1B00C000,0x1B00E000,
0x1B010000,0x1B020000,0x1B030000,0x1B040000,
0x1B050000,0x1B060000,0x1B070000,0x1B080000
};
struct sIAP {
unsigned long cmd;
unsigned long par[5];
unsigned long stat;
unsigned long res[4];
} IAP;
bool bg_busy=0;
bool bg_pblist_updated;
Block_List BLlist[4];
uint8_t u1g_length_BLlist = 4;
bool bg_bank_number = 0;
int8_t Flash_Initialize (void);
int8_t FLReport(Block_List *pBLlist);
int8_t FLEraseSectors(uint8_t nSector, uint8_t nPageStart, uint8_t nPageEnd);
int8_t FLReadSectors(uint8_t nSector,uint8_t nPageStart, uint8_t nPageEnd,
uint32_t *pnDestination);
int8_t FLWriteSectors(uint8_t nSector, uint8_t nPageStart, uint8_t nPageEnd,
uint32_t *pnSource);
int8_t Flash_PrepareforWrite(uint8_t start_sec_num, uint8_t end_sec_num,
bool flash_bank_num);
int8_t Get_Sector_Num(uint32_t u4l_flash_addr);
int8_t Flash_Sector_Available(uint8_t u1l_sec_num, uint8_t u1l_page_num);
int8_t Flash_Content_Verify(uint32_t u4l_addr, uint8_t u1l_start_sec_num,
uint8_t u1l_end_sec_num);
int8_t Check_Flash_Access(uint8_t u1l_sector_num, uint8_t u1l_start_page,
uint8_t u1l_end_page, uint32_t *pnDestination,
Flash_operation u1l_flash_operation);
uint8_t Flash_ErasePage(bool bl_bank_num, uint8_t u1l_sec_num,
uint8_t u1l_start_page, uint8_t u1l_end_page);
int8_t Write_Data_Verify(bool bl_bank_num, uint8_t u1l_sec_num,
uint8_t u1l_start_page, uint8_t u1l_end_page,
void *pnSource);
int8_t Flash_ProgramPage (bool bl_bank_num, uint8_t u1l_sec_num,
uint8_t u1l_start_page, uint8_t u1l_end_page,
unsigned char *plsource);
int8_t ReadData(bool bl_bank_num, uint8_t u1l_sec_num, uint8_t u1l_start_page,
uint8_t u1l_end_page, uint32_t *pldata);
Block_List Get_Sec_Page_num(uint32_t u4l_flash_addr);
int8_t Flash_Initialize (void)
{
int8_t s1l_status;
IAP.cmd = CMD_IAP_INITIALIZE;
IAP_Call (&IAP.cmd, &IAP.stat);
if (IAP.stat)
{
s1l_status = FLASH_STATUS_FAILED;
}
else
{
s1l_status = FLASH_STATUS_OK;
FLReport(&BLlist[0]);
}
return s1l_status;
}
int8_t Flash_PrepareforWrite(uint8_t u1l_start_sec_num,uint8_t u1l_end_sec_num,
bool flash_bank_num)
{
IAP.cmd = CMD_PREPARE_FOR_WRITE;
IAP.par[0] = u1l_start_sec_num;
IAP.par[1] = u1l_end_sec_num;
IAP.par[2] = flash_bank_num;
IAP_Call(&IAP.cmd, &IAP.stat);
return IAP.stat;
}
int8_t Flash_Sector_Available(uint8_t u1l_sec_num, uint8_t u1l_page_num)
{
int8_t s1l_status = 0;
uint8_t u1l_num = 0;
if(u1g_length_BLlist > 1)
{
for(u1l_num = 1;u1l_num <= 3;)
{
if((u1l_sec_num > BLlist[u1l_num-1].sec_num) &&
(u1l_sec_num < BLlist[u1l_num].sec_num))
{
s1l_status = SECTOR_UNAVAILABLE;u1l_num=4;
}
else if((u1l_sec_num == BLlist[u1l_num-1].sec_num) && (u1l_sec_num == BLlist[u1l_num].sec_num))
{
if((u1l_page_num >= BLlist[u1l_num-1].page_num)&&(u1l_page_num <= BLlist[u1l_num].page_num))
{
s1l_status = SECTOR_UNAVAILABLE;
u1l_num=4;
}
}
else if((u1l_sec_num == BLlist[u1l_num-1].sec_num) && (u1l_page_num >= BLlist[u1l_num-1].page_num ))
{
s1l_status = SECTOR_UNAVAILABLE;
u1l_num=4;
}
else if((u1l_sec_num == BLlist[u1l_num].sec_num) && (u1l_page_num <= BLlist[u1l_num].page_num ))
{
s1l_status = SECTOR_UNAVAILABLE;
u1l_num=4;
}
else
{
u1l_num = u1l_num + 2;
}
}
}
return s1l_status;
}
int8_t Flash_Erase_Verify(bool bl_bank_num, uint8_t u1l_sec_num,
uint8_t u1l_start_page, uint8_t u1l_end_page)
{
uint32_t s1l_status = 0;
uint32_t u4l_value = 0xFFFFFFFF;
uint8_t u1l_tot_num_pages = (u1l_end_page - u1l_start_page) + 1;
uint32_t u4l_flash_addr;
uint8_t u1l_page_count;
uint8_t u1l_word_count;
uint8_t u1l_tot_num_words = PAGE_SIZE / 4;
if (bl_bank_num == 0)
{
u4l_flash_addr = FLASH_BANK_ADDR[u1l_sec_num] +
((u1l_start_page - 1) * 512);
}
else
{
u4l_flash_addr = FLASH_BANK_ADDR[u1l_sec_num + 15] +
((u1l_start_page - 1) * 512);
}
for(u1l_page_count = 1;u1l_page_count <= u1l_tot_num_pages;
u1l_page_count++)
{
for(u1l_word_count = 0; u1l_word_count < u1l_tot_num_words;
u1l_word_count++)
{
if((u4l_value == 0xFFFFFFFF)&&(s1l_status == 0))
{
u4l_value = FLASH_DATA(u4l_flash_addr);
u4l_flash_addr += 4U;
}
else
{
u1l_word_count = u1l_tot_num_words + 4;
s1l_status = FLASH_CONTENTS_NOT_VERIFY;
}
}
}
return s1l_status;
}
uint8_t Flash_ErasePage(bool bl_bank_num, uint8_t u1l_sec_num,
uint8_t u1l_start_page, uint8_t u1l_end_page)
{
int8_t s1l_status = 0;
uint32_t u4l_timeout_prepare = 1000;
uint32_t u4l_timeout_erase = 1000;
uint32_t u4l_flash_start_addr;
uint32_t u4l_flash_end_addr;
uint8_t u1l_tot_page_num = (u1l_end_page - u1l_start_page) + 1;
if (bl_bank_num == 0)
{
u4l_flash_start_addr = FLASH_BANK_ADDR[u1l_sec_num] +
((u1l_start_page - 1) * 512);
u4l_flash_end_addr = u4l_flash_start_addr + ((u1l_tot_page_num - 1) * 512);
}
else
{
u4l_flash_start_addr = FLASH_BANK_ADDR[u1l_sec_num + 15] +
((u1l_start_page - 1) * 512);
u4l_flash_end_addr = u4l_flash_start_addr + ((u1l_tot_page_num - 1) * 512);
}
do
{
IAP.stat = Flash_PrepareforWrite(u1l_sec_num, u1l_sec_num,
bl_bank_num);
}while((IAP.stat == FLASH_BUSY) && (u4l_timeout_prepare--));
if(IAP.stat == FLASH_STATUS_OK)
{
IAP.cmd = CMD_ERASE_PAGE;
IAP.par[0] = u4l_flash_start_addr;
IAP.par[1] = u4l_flash_end_addr;
IAP.par[2] = u4g_Flash_Clk;
IAP_Call (&IAP.cmd, &IAP.stat);
while((IAP.stat == FLASH_BUSY) && (u4l_timeout_erase--));
if(IAP.stat)
{
s1l_status = TIMEOUT_OCCURED;
}
else
{
s1l_status = FLASH_STATUS_OK;
}
}
else
{
s1l_status = TIMEOUT_OCCURED;
}
return s1l_status;
}
int8_t Write_Data_Verify(bool bl_bank_num, uint8_t u1l_sec_num,
uint8_t u1l_start_page, uint8_t u1l_end_page,
void *pnSource)
{
int8_t s1l_status = 0;
uint8_t u1l_count;
uint32_t u4l_ram_addr = ( uint32_t )pnSource;
uint32_t u4l_flash_addr;
uint8_t u1l_tot_num_pages;
u4l_ram_addr = (uint32_t )pnSource;
u1l_tot_num_pages = (u1l_end_page - u1l_start_page) + 1;
if (bl_bank_num == 0)
{
u4l_flash_addr = FLASH_BANK_ADDR[u1l_sec_num] +
((u1l_start_page - 1) * 512);
}
else
{
u4l_flash_addr = FLASH_BANK_ADDR[u1l_sec_num + 15] +
((u1l_start_page - 1) * 512);
}
for(u1l_count = 0; u1l_count < u1l_tot_num_pages; u1l_count++)
{
IAP.cmd = CMD_COMPARE;
IAP.par[0] = u4l_flash_addr + (u1l_count * 512);
IAP.par[1] = u4l_ram_addr + (u1l_count * 512);
IAP.par[2] = 512;
IAP_Call (&IAP.cmd, &IAP.stat);
if(IAP.stat != 0)
{
u1l_count = u1l_tot_num_pages + 1;
}
}
if(IAP.stat == 0)
{
s1l_status = 0;
}
else
{
s1l_status = IAP.stat;
}
return s1l_status;
}
int8_t Flash_ProgramPage (bool bl_bank_num, uint8_t u1l_sec_num,
uint8_t u1l_start_page, uint8_t u1l_end_page,
unsigned char *plsource)
{
int8_t s1l_status = 0;
uint8_t u1l_page_count;
uint32_t u4l_timeout_prepare = 1000;
uint32_t u4l_timeout_write = 1000;
uint32_t u4l_flash_addr;
uint8_t u1l_tot_page_num = (u1l_end_page - u1l_start_page) + 1;
if (bl_bank_num == 0)
{
u4l_flash_addr = FLASH_BANK_ADDR[u1l_sec_num] +
((u1l_start_page - 1) * 512);
}
else
{
u4l_flash_addr = FLASH_BANK_ADDR[u1l_sec_num + 15] +
((u1l_start_page - 1) * 512);
}
for(u1l_page_count = 1;u1l_page_count <= u1l_tot_page_num; u1l_page_count++)
{
do
{
IAP.stat = Flash_PrepareforWrite(u1l_sec_num, u1l_sec_num,
bl_bank_num);
}while((IAP.stat == FLASH_BUSY) && (u4l_timeout_prepare--));
if(IAP.stat == FLASH_STATUS_OK)
{
IAP.cmd = CMD_WRITE;
IAP.par[0] = u4l_flash_addr;
IAP.par[1] = (unsigned long)plsource;
IAP.par[2] = PAGE_SIZE;
IAP.par[3] = u4g_Flash_Clk;
IAP.par[4] = bl_bank_num;
IAP_Call (&IAP.cmd, &IAP.stat);
plsource += 512;
u4l_flash_addr += 512;
while((IAP.stat == FLASH_BUSY) && (u4l_timeout_write--));
if(IAP.stat)
{
s1l_status = FLASH_STATUS_FAILED;
}
else
{
s1l_status = FLASH_STATUS_OK;
}
}
else
{
s1l_status = TIMEOUT_OCCURED;
}
}
return s1l_status;
}
int8_t ReadData(bool bl_bank_num, uint8_t u1l_sec_num, uint8_t u1l_start_page,
uint8_t u1l_end_page, uint32_t *pldata)
{
uint32_t u4l_flash_addr;
int8_t s1l_status = 0;
uint8_t u1l_page_count;
uint8_t u1l_word_count;
uint8_t u1l_tot_num_words = PAGE_SIZE / 4;
uint8_t u1l_tot_num_pages = (u1l_end_page - u1l_start_page) + 1;
if (bl_bank_num == 0)
{
u4l_flash_addr = FLASH_BANK_ADDR[u1l_sec_num] +
((u1l_start_page - 1) * 512);
}
else
{
u4l_flash_addr = FLASH_BANK_ADDR[u1l_sec_num + 15] +
((u1l_start_page - 1) * 512);
}
for(u1l_page_count = 1; u1l_page_count <= u1l_tot_num_pages;
u1l_page_count++)
{
for(u1l_word_count = 0; u1l_word_count < u1l_tot_num_words;
u1l_word_count++)
{
*pldata = FLASH_DATA(u4l_flash_addr);
pldata++;
u4l_flash_addr += 4U;
}
}
return s1l_status;
}
int8_t Get_Sector_Num(uint32_t u4l_flash_addr)
{
int8_t s1l_sec_number = -1;
uint8_t u1l_count;
for(u1l_count = 0; u1l_count <= 30; u1l_count++)
{
if(FLASH_BANK_ADDR[u1l_count] == u4l_flash_addr)
{
s1l_sec_number = u1l_count + 1;
}
}
return s1l_sec_number;
}
int8_t Check_Flash_Access(uint8_t u1l_sector_num, uint8_t u1l_start_page,
uint8_t u1l_end_page, uint32_t *pnRam_memory,
Flash_operation u1l_flash_operation)
{
int8_t s1l_status = FLASH_STATUS_OK;
uint8_t u1l_count;
uint8_t u1l_tot_num_pages = 0;
uint8_t u1l_max_count = 5;
uint32_t pn_req_memory = (uint32_t )pnRam_memory;
for(u1l_count = 0; u1l_count < u1l_max_count; u1l_count++)
{
switch (u1l_count)
{
case 0:
if(u1l_sector_num > 30)
{
s1l_status = SECTOR_NOT_SUPPORTED;
u1l_count = u1l_max_count + 1;
}
break;
case 1:
if(((u1l_sector_num > 0) && (u1l_sector_num <= 8)) ||
((u1l_sector_num > 16) && (u1l_sector_num <= 23)))
{
if(u1l_start_page > 16 )
{
s1l_status = START_PAGE_NOT_SUPPORTED;
u1l_count = u1l_max_count + 1;
}
else if(u1l_end_page > 16)
{
s1l_status = END_PAGE_NOT_SUPPORTED;
u1l_count = u1l_max_count + 1;
}
}
else
{
if(u1l_start_page > 128 )
{
s1l_status = START_PAGE_NOT_SUPPORTED;
u1l_count = u1l_max_count + 1;
}
else if(u1l_end_page > 128)
{
s1l_status = END_PAGE_NOT_SUPPORTED;
u1l_count = u1l_max_count + 1;
}
}
break;
case 2:
if(u1l_end_page < u1l_start_page)
{
s1l_status = END_PAGE_BEFORE_START_PAGE;
u1l_count = u1l_max_count + 1;
}
else
{
u1l_tot_num_pages = (u1l_end_page - u1l_start_page) + 1;
}
if((u1l_tot_num_pages > 16)&&
(u1l_flash_operation != FLASH_ERASE))
{
s1l_status = PAGE_LIMIT_NOT_SUPPORTED;
u1l_count = u1l_max_count + 1;
}
break;
case 3:
if((bg_pblist_updated == 1) &&
(u1l_flash_operation != FLASH_READ))
{
s1l_status = Flash_Sector_Available(u1l_sector_num, u1l_start_page);
s1l_status |= Flash_Sector_Available(u1l_sector_num, u1l_end_page);
if(s1l_status)
{
s1l_status = SECTOR_UNAVAILABLE;
u1l_count = u1l_max_count + 1;
}
}
break;
case 4:
if(u1l_flash_operation != FLASH_ERASE)
{
if(!((pnRam_memory >= RAM1_START_LOCATION)&&
(pnRam_memory <= RAM1_END_LOCATION)))
{
if(!((pnRam_memory >= RAM2_START_LOCATION)&&
(pnRam_memory <= RAM2_END_LOCATION)))
{
if(!((pnRam_memory >= RAM3_START_LOCATION)&&
(pnRam_memory <= RAM3_END_LOCATION)))
{
s1l_status = DESTINATION_POINTER_INVALID;
u1l_count = u1l_max_count + 1;
}
}
}
pn_req_memory += ((u1l_tot_num_pages) * 512);
if(!((pn_req_memory >= (uint32_t )RAM1_START_LOCATION)&&
(pn_req_memory <= (uint32_t )RAM1_END_LOCATION)))
{
if(!((pn_req_memory >= (uint32_t )RAM2_START_LOCATION)&&
(pn_req_memory <= (uint32_t )RAM2_END_LOCATION)))
{
if(!((pn_req_memory >= (uint32_t )RAM3_START_LOCATION)&&
(pn_req_memory <= (uint32_t )RAM3_END_LOCATION)))
{
s1l_status = DESTINATION_POINTER_INVALID;
u1l_count = u1l_max_count + 1;
}
}
}
}
break;
default:
break;
}
}
return s1l_status;
}
int8_t FLReport(Block_List *pBLlist)
{
int8_t s1l_status;
uint8_t u1l_count;
uint32_t u4l_block_addr[4];
u4l_block_addr[0] = START_ADDRESS_BOOTPACK;
u4l_block_addr[1] = START_ADDRESS_BOOTPACK + SIZE_BOOTPACK;
u4l_block_addr[2] = CRC_LOCATION_CURRENTPACK;
u4l_block_addr[3] = CRC_LOCATION_CURRENTPACK + FLASH_DATA(START_ADDRESS_CURRENTPACK+4);
for(u1l_count = 0; u1l_count < 4; u1l_count++)
{
pBLlist[u1l_count] = Get_Sec_Page_num(u4l_block_addr[u1l_count]);
if((pBLlist[u1l_count].page_num == 0) || (pBLlist[u1l_count].sec_num == 0))
{
s1l_status = -1;
u1l_count = 5;
}
else
{
s1l_status = 0;
}
}
return s1l_status;
}
int8_t FLReadSectors(uint8_t nSector,uint8_t nPageStart, uint8_t nPageEnd,
uint32_t *pnDestination)
{
int8_t s1l_status;
uint8_t u1l_sec_num;
bg_busy = 1;
if(nSector > 15)
{
bg_bank_number = 1;
u1l_sec_num = nSector - 16;
}
else
{
bg_bank_number = 0;
u1l_sec_num = nSector - 1;
}
s1l_status = Check_Flash_Access(nSector, nPageStart, nPageEnd,
pnDestination, FLASH_READ);
if(s1l_status == 0)
{
s1l_status = ReadData(bg_bank_number, u1l_sec_num, nPageStart, nPageEnd,
pnDestination);
bg_busy = 0;
}
return s1l_status;
}
int8_t FLWriteSectors(uint8_t nSector, uint8_t nPageStart, uint8_t nPageEnd,
uint32_t *pnSource)
{
int8_t s1l_status;
uint8_t u1l_sec_num;
bool bl_bank_num;
if(nSector > 15)
{
bl_bank_num = 1;
u1l_sec_num = nSector - 16;
}
else
{
bl_bank_num = 0;
u1l_sec_num = nSector - 1;
}
s1l_status = Check_Flash_Access(nSector, nPageStart, nPageEnd, pnSource,
FLASH_WRITE);
if(s1l_status == FLASH_STATUS_OK)
{
s1l_status = FLEraseSectors( nSector, nPageStart, nPageEnd);
}
if((s1l_status == FLASH_STATUS_OK) && (bg_busy==0))
{
s1l_status = Flash_ProgramPage(bl_bank_num, u1l_sec_num, nPageStart,
nPageEnd, (unsigned char *)pnSource );
bg_busy = 1;
if(s1l_status == FLASH_STATUS_OK)
{
s1l_status = Write_Data_Verify(bl_bank_num, u1l_sec_num,
nPageStart, nPageEnd, pnSource);
if(s1l_status != 0)
{
s1l_status = WRITTEN_DATA_DIDNOT_VERIFY;
}
}
bg_busy = 0;
}
else if(s1l_status == FLASH_CONTENTS_NOT_VERIFY)
{
s1l_status = ONE_OR_MORE_PAGES_NOT_ERASED;
}
return s1l_status;
}
int8_t FLEraseSectors(uint8_t nSector, uint8_t nPageStart, uint8_t nPageEnd)
{
int8_t s1l_status;
uint8_t u1l_sec_num;
bool bl_bank_num;
if(nSector > 15)
{
bl_bank_num = 1;
u1l_sec_num = nSector - 16;
}
else
{
bl_bank_num = 0;
u1l_sec_num = nSector - 1;
}
s1l_status = Check_Flash_Access(nSector, nPageStart, nPageEnd, 0, FLASH_ERASE);
if((s1l_status == FLASH_STATUS_OK) && (bg_busy==0))
{
s1l_status = Flash_ErasePage(bl_bank_num, u1l_sec_num, nPageStart,
nPageEnd);
s1l_status = Flash_Erase_Verify(bl_bank_num, u1l_sec_num, nPageStart,
nPageEnd);
}
return s1l_status;
}
Block_List Get_Sec_Page_num(uint32_t u4l_flash_addr)
{
uint8_t u1l_count;
Block_List protect_list = {0,0};
if(((u4l_flash_addr >= 0x1A000000) && (u4l_flash_addr <= 0x1A07FFFF)) ||
((u4l_flash_addr >= 0x1B000000) && (u4l_flash_addr <= 0x1B07FFFF)))
{
for(u1l_count = 0; u1l_count < 31; u1l_count++)
{
if(FLASH_BANK_ADDR[u1l_count] == u4l_flash_addr)
{
protect_list.sec_num = u1l_count+1;
protect_list.page_num = 1;
u1l_count = 31;
}
else if(FLASH_BANK_ADDR[u1l_count] < u4l_flash_addr)
{
protect_list.sec_num++;
u1l_count = u1l_count;
}
else
{
protect_list.page_num = u4l_flash_addr - FLASH_BANK_ADDR[(u1l_count-1)];
protect_list.page_num = (protect_list.page_num/512);
if(u4l_flash_addr >= (FLASH_BANK_ADDR[(u1l_count-1)] + (512 * protect_list.page_num)))
{
protect_list.page_num++;
u1l_count = 31;
}
}
}
}
else
{
protect_list.page_num = 0;
protect_list.sec_num = 0;
}
return protect_list;
}
when the execution reaches line number 391 or 571 the micro controller hangs or you can say it never comes out of that line.