Hi everyone,
I'm using LPC1837 micro controller for some application development. This micro controller has on-chip flash memory of 1MB. 1MB is shared between two memory banks Bank A and Bank B. each bank has 15 sectors 0-7 with 8kB size and 8-14 with 64kB size. boot loader code resides from sector 0 to sector 8 in bank A.
Now if i try to write application code in the sector 9 or 10 in the bank A. it is hitting the hard fault handler.
if the same application code in written in bank b any sector, it works fine without and problem.
i'm using IAP command to erase and write .
can anyone please explain about this and also how to solve this ?
i have search in any forum, they are telling to use __attributes (); .
i'm not getting how to use the __attributes() in my code so that the code will be placed in RAM area.
can you please help me out.
Hi nagendra murthy,
The user application demo programming in the sector 9 and 10 should follow the process flow:
1. Prepare sector for write operation;
2: Erase sectors;
3. Copy ram to flash;
Some IAR commands have the return code, it can indicate the status of the command execution.
Have a great day,
Ping
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi jeremyzhou,
i'm following that sequence.
actually once it enter the IAP commands it will not come out from there.
i observe the disassembly code the it shows the following
0x00000000 0000 movs r0,r0
0x00000002 0000 movs r0,r0
Hi nagendra murthy,
I'd highly recommend you to refer to the flashiap demo which is included in the LPCOpen library.
And you can find the library through the below link:
LPCOpen Software for LPC18XX|NXP
Have a great day,
Ping
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Thank you jeremyzhou,
it was very use information from you. i went through that and got the thing correct,
but still my code hang when it reach the iap calls.
it enter the inside the iap cmd and never come out of it.
for your information the clock frequency used is 180Mhz.
Hi nagendra murthy,
What's going on with the issue?
I was wondering if you can share a simple demo that can replicate the issue on my site.
I'm looking forward to your reply.
Have a great day,
Ping
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi jeremyzhou,
/*****************************************************************************
* Header File Includes
*****************************************************************************/
#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)))
/* IAP Call */
typedef void (*IAP_Entry) (unsigned long *cmd, unsigned long *stat);
#define IAP_Call ((IAP_Entry) *((unsigned long *)0x10400100))
/*****************************************************************************
* Data Declarations
*****************************************************************************/
/* Flash Clock in KHz - 180KHz */
uint32_t u4g_Flash_Clk = 180000;
/* Initialize starting address of sector numbers in const array */
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
};
/* structure of IAP call parameters */
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;
/*****************************************************************************
* Platform Function Declarations
*****************************************************************************/
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);
/*****************************************************************************
* User Function Declarations
*****************************************************************************/
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);
/*****************************************************************************
* Function Definitions
*****************************************************************************/
/*****************************************************************************
* Function Name:Flash_Initialize
* Description: This routine is to initialize Flash in LPC Micro. It should be
* called at the begining of the application, when user needs to
* do Flash erase/write/read operations
*
*
* Inputs:
* None
*
*
*
* Outputs: Initializes the Flash in LPC for IAP commands and operations
*
*
* Returns: s1l_status int8_t FLASH_STATUS_OK
* FLASH_STATUS_FAILED
*****************************************************************************/
int8_t Flash_Initialize (void)
{
/* initialize the local variables */
int8_t s1l_status;
/* Initialize on chip Flash memory */
/* This command initialize the flash for erase and write operations */
IAP.cmd = CMD_IAP_INITIALIZE;
IAP_Call (&IAP.cmd, &IAP.stat);
/* check IAP command result status*/
if (IAP.stat)
{
s1l_status = FLASH_STATUS_FAILED;
}
else
{
s1l_status = FLASH_STATUS_OK;
/* update BLlist sector numbers */
FLReport(&BLlist[0]);
}
return s1l_status;
}
/*****************************************************************************
* Function Name:Flash_PrepareforWrite
* Description: This routine is to check whether flash is ready to do erase or
* write operation. This API should be called before erasing or writing to flash
*
*
* Inputs:
* start_sec_num uint32_t 0 - 14
* end_sec_num uint32_t 0 - 14
* flash_bank_num bool 0 or 1
*
* Outputs:
* s1l_status uint32_t Status
*
* Returns: s1l_status int8_t FLASH_STATUS_OK
* FLASH_STATUS_FAILED
*
*****************************************************************************/
int8_t Flash_PrepareforWrite(uint8_t u1l_start_sec_num,uint8_t u1l_end_sec_num,
bool flash_bank_num)
{
/* Check whether the flash sector is ready to write or not */
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;
/* check is that flash can be programmed or erased */
IAP_Call(&IAP.cmd, &IAP.stat);
return IAP.stat;
}
/*****************************************************************************
* Function Name:Flash_Sector_Avaialble
* Description: This routine is to find the sector numbers which are available
* for erase/write operation. It checks the BLlist array and
* blocks the sectors that is available in BLlist.
*
* Inputs:
* u1l_sec_num uint8_t 1 - 30
*
*
* Outputs:
* Checks whether the given sector is to be protected for erase
* and write as refered to BLlist
*
* Returns: s1l_status int8_t FLASH_STATUS_OK
* SECTOR_UNAVAILABLE
*****************************************************************************/
int8_t Flash_Sector_Available(uint8_t u1l_sec_num, uint8_t u1l_page_num)
{
/* initialize the local varaiables */
int8_t s1l_status = 0;
uint8_t u1l_num = 0;
/* check the given sector reside in BLlist */
if(u1g_length_BLlist > 1)
{
for(u1l_num = 1;u1l_num <= 3;)
{
/* check whether the given sector completely resides between even and odd element */
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;
}
/* check whether the given sector is same odd and even element */
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
{
/* go to next odd point to check the given sector against the
next pair of sectors in BLlist */
u1l_num = u1l_num + 2;
}
}
}
return s1l_status;
}
/*****************************************************************************
* Function Name:Flash_Erase_Verify
* Description: This routine is to verify the given page in particular sector
* is erased or not. It checks for the contents as 0xFF after erase
* and returns the flash verified status.
*
* Inputs:
* bl_bank_num bool 0 or 1 (A or B)
* u1l_sec_num uint8_t (0 - 14)
* u1l_start_page uint8_t 1 - 16 (8KB sector)
* 1 - 128(64KB sector)
* u1l_end_page uint8_t 1 - 15 (8KB sector)
* 1 - 128(64KB sector)
*
* Outputs:
* Verify the erased page contents as 0xFF in every location
*
* Returns: s1l_status uint32_t FLASH_STATUS_OK
* FLASH_CONTENTS_NOT_VERIFY
*****************************************************************************/
int8_t Flash_Erase_Verify(bool bl_bank_num, uint8_t u1l_sec_num,
uint8_t u1l_start_page, uint8_t u1l_end_page)
{
/* initilaize local variables */
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;
/* Start of flash address from where, needs to be read and stored in RAM */
if (bl_bank_num == 0)
{
/* Sector resides in Bank 0 (Bank A) */
u4l_flash_addr = FLASH_BANK_ADDR[u1l_sec_num] +
((u1l_start_page - 1) * 512);
}
else
{
/* Sector resides in Bank 1 (Bank B) */
u4l_flash_addr = FLASH_BANK_ADDR[u1l_sec_num + 15] +
((u1l_start_page - 1) * 512);
}
/* Check for all pages lies in the given range */
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);
/* increment to next word */
u4l_flash_addr += 4U;
}
else
{
/* if not erased properly , update status and exit */
u1l_word_count = u1l_tot_num_words + 4;
s1l_status = FLASH_CONTENTS_NOT_VERIFY;
}
}
}
return s1l_status;
}
/*****************************************************************************
* Function Name:Flash_ErasePage
* Description: This routine is used to erase the flash area between the
* starting and ending page numbers in the given sector/banks
*
*
* Inputs:
* bl_bank_num bool 0 or 1 (A or B)
* u1l_sec_num uint8_t (0 - 14)
* u1l_start_page uint8_t 1 - 16 (8KB sector)
* 1 - 128(64KB sector)
* u1l_end_page uint8_t 1 - 16 (8KB sector)
* 1 - 128(64KB sector)
*
* Outputs:
* Erase the content in given range of page inside a given sector
*
* Returns: s1l_status int8_t FLASH_STATUS_OK
* FLASH_STATUS_FAILED
* TIMEOUT_OCCURED
*****************************************************************************/
uint8_t Flash_ErasePage(bool bl_bank_num, uint8_t u1l_sec_num,
uint8_t u1l_start_page, uint8_t u1l_end_page)
{
/* initialize the local variables */
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;
/* Calculate region of flash start address and end address, where it needs
to be erased */
if (bl_bank_num == 0)
{
/* Sector resides in Bank 0 (Bank A) */
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
{
/* Sector resides in Bank 1 (Bank B) */
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);
}
/* check whether the flash is ready to do erase or write, if that section
is busy wait till timeout */
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)
{
/* command write */
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);
/* check whether the erase task completed or not */
while((IAP.stat == FLASH_BUSY) && (u4l_timeout_erase--));
/* check IAP command result */
if(IAP.stat)
{
/* command failed */
s1l_status = TIMEOUT_OCCURED;
}
else
{
/* command success */
s1l_status = FLASH_STATUS_OK;
}
}
else
{
s1l_status = TIMEOUT_OCCURED;
}
return s1l_status;
}
/*****************************************************************************
* Function Name: Write_data_verify
* Description: This routine is used to verify the FLASH contents just after
* writing the data contents from RAM to FLASH
*
*
* Inputs:
* bl_bank_num bool 0 or 1 (A or B)
* u1l_sec_num uint8_t (0 - 14)
* u1l_start_page uint8_t 1 - 16 (8KB sector)
* 1 - 128(64KB sector)
* u1l_end_page uint8_t 1 - 16 (8KB sector)
* 1 - 128(64KB sector)
* Outputs:
* Verify the data in Flash against the data in Source RAM
*
* Returns: s1l_status int8_t FLASH_STATUS_OK
* FLASH_STATUS_FAILED
* TIMEOUT_OCCURED
* WRITTEN_DATA_DIDNOT_VERIFY
*****************************************************************************/
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)
{
/* intialize the varaibles */
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;
/* Start of flash address from where, needs to be read and stored in RAM */
if (bl_bank_num == 0)
{
/* Sector resides in Bank 0 (Bank A) */
u4l_flash_addr = FLASH_BANK_ADDR[u1l_sec_num] +
((u1l_start_page - 1) * 512);
}
else
{
/* Sector resides in Bank 1 (Bank B) */
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++)
{
/* send compare command */
IAP.cmd = CMD_COMPARE;
/* starting address of flash from where its data to be verified */
IAP.par[0] = u4l_flash_addr + (u1l_count * 512);
/* starting address of ram from where its data to be verified */
IAP.par[1] = u4l_ram_addr + (u1l_count * 512);
/* Size - number of words to be verified */
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;
}
/*****************************************************************************
* Function Name:Flash_ProgramPage
* Description: This routine is used to Write the Flash pages of respective
* sector/bank with the contents provided in source RAM.
*
*
* Inputs:
* bl_bank_num bool 0 or 1 (A or B)
* u1l_sec_num uint8_t (0 - 14)
* u1l_start_page uint8_t 1 - 16 (8KB sector)
* 1 - 128(64KB sector)
* u1l_end_page uint8_t 1 - 16 (8KB sector)
* 1 - 128(64KB sector)
* plSource unsigned char source RAM address
*
*
* Outputs:
* Copy data from RAM to FLASH
*
* Returns: s1l_status int8_t FLASH_STATUS_OK
* FLASH_STATUS_FAILED
* TIMEOUT_OCCURED
*****************************************************************************/
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)
{
/* initialize the local variables */
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;
/* Start of flash address from where, needs to be read and stored in RAM */
if (bl_bank_num == 0)
{
/* Sector resides in Bank 0 (Bank A) */
u4l_flash_addr = FLASH_BANK_ADDR[u1l_sec_num] +
((u1l_start_page - 1) * 512);
}
else
{
/* Sector resides in Bank 1 (Bank B) */
u4l_flash_addr = FLASH_BANK_ADDR[u1l_sec_num + 15] +
((u1l_start_page - 1) * 512);
}
/* loop continues till completes all pages */
/* 8 kb sector is 16 pages of 512 bytes */
/* 64 kb sector is 128 pages of 512 bytes */
for(u1l_page_count = 1;u1l_page_count <= u1l_tot_page_num; u1l_page_count++)
{
/* Check flash is ready to do erase or write */
/* if someother operation is doing wait till timeout and update status*/
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)
{
/* command write */
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);
/* increment pnSource_RAM address by 512 to select data
for next page */
plsource += 512;
/* increment Flash address by 512 to select next page */
u4l_flash_addr += 512;
/* Check whether the write task completed or not */
while((IAP.stat == FLASH_BUSY) && (u4l_timeout_write--));
/* check IAP command result */
if(IAP.stat)
{
/* command failed */
s1l_status = FLASH_STATUS_FAILED;
}
else
{
/* command success */
s1l_status = FLASH_STATUS_OK;
}
}
else
{
s1l_status = TIMEOUT_OCCURED;
}
}
return s1l_status;
}
/*****************************************************************************
* Function Name:ReadData
* Description: This routine is to Read pages of respective Flash sectors/banks
* and store its contents to memory locations refered by the
* RAM area
*
*
* Inputs:
* bl_bank_num bool 0 or 1 (A or B)
* u1l_sec_num uint8_t (0 - 14)
* u1l_start_page uint8_t 1 - 16 (8KB sector)
* 1 - 128(64KB sector)
* u1l_end_page uint8_t 1 - 16 (8KB sector)
* 1 - 128(64KB sector)
* pldata uint32_t address to where it needs to be stored
*
* Outputs:
* Copy the data from Flash to RAM (Reads data from Flash and store in
* RAM)
*
* Returns: s1l_status int8_t
*
*****************************************************************************/
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)
{
/* initialize the local variables */
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;
/* Start of flash address from where, needs to be read and stored in RAM */
if (bl_bank_num == 0)
{
/* Sector resides in Bank 0 (Bank A) */
u4l_flash_addr = FLASH_BANK_ADDR[u1l_sec_num] +
((u1l_start_page - 1) * 512);
}
else
{
/* Sector resides in Bank 1 (Bank B) */
u4l_flash_addr = FLASH_BANK_ADDR[u1l_sec_num + 15] +
((u1l_start_page - 1) * 512);
}
/* Copy data from Flash Sectors to given RAM memory locations */
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++)
{
/* copy data from flash to RAM */
*pldata = FLASH_DATA(u4l_flash_addr);
/* increment ram address by 4 for word length */
pldata++;
/* increment flash address by 4 for word length */
u4l_flash_addr += 4U;
}
}
return s1l_status;
}
/*****************************************************************************
* Function Name: Get_Sector_Num
* Description: This routine is to get the sector numbers of individual
* bank for given flash address
*
*
* Inputs:
* sector numbers as array elements
* sector numbers 1 to 15 - Flash Bank A
* sector numbers 16 to 30 - Flash Bank B
*
*
* Outputs:
* Finds the sector number based on given Flash address
*
* Returns: s1l_status int8_t Sector number or -1
*
*****************************************************************************/
int8_t Get_Sector_Num(uint32_t u4l_flash_addr)
{
/* initialize the variables */
int8_t s1l_sec_number = -1;
uint8_t u1l_count;
/* check whether the given flash address is pointing starting address of
any valid sectors or not */
for(u1l_count = 0; u1l_count <= 30; u1l_count++)
{
/* check for whether address matching the starting address of any sector */
if(FLASH_BANK_ADDR[u1l_count] == u4l_flash_addr)
{
/* update sector number */
s1l_sec_number = u1l_count + 1;
}
}
/* return sector number */
return s1l_sec_number;
}
/*****************************************************************************
* Function Name:Check_Flash_Access
* Description: This routine is to validate the given address/sector/page/bank
* against the memory area defined in the LPC1837 Microcontroller
*
*
* Inputs:
* nSectorSTART uint32_t Starting Sector Number
* nSectorEND uint32_t End Sector Number
* pnSource uint32_t * memory address of RAM
* u1l_test_num uint8_t number of test codintions to be
* checked
*
*
* Outputs:
* s1l_status int8_t Status
*
* Returns: Status
*
*****************************************************************************/
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)
{
/* initialize the variables */
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:
/* given sector supported or not */
if(u1l_sector_num > 30)
{
s1l_status = SECTOR_NOT_SUPPORTED;
u1l_count = u1l_max_count + 1;
}
break;
case 1:
/* verify the given start page and end page is valid one
or not */
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:
/* verify the end page appeared after start page */
if(u1l_end_page < u1l_start_page)
{
s1l_status = END_PAGE_BEFORE_START_PAGE;
u1l_count = u1l_max_count + 1;
}
else
{
/* calculate total number of pages */
u1l_tot_num_pages = (u1l_end_page - u1l_start_page) + 1;
}
/* verify the given page range limited to max of 16 pages */
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:
/* verify the given sector is about to be blocked as refered
using BLlist */
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:
/* whether the given RAM location is valid one or not */
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);
/* Check whether end memory also resides inside valid RAM
memory */
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;
}
/*****************************************************************************
* Function Name:FLReport
* Description: This routine is to update the BList[] with the sector numbers
* that can't be erased i.e, this API updates the elements of
* BLlist, based on the #Define values provided in Flash.h file.
*
* Inputs:
* pBLlist int8_t memory locaiton to store BLlist element
*
* Outputs:
* updated the BLlist sectors
*
* Returns: s1l_status int8_t 0 or -1
*
*****************************************************************************/
int8_t FLReport(Block_List *pBLlist)
{
/* initialize the variables */
int8_t s1l_status;
uint8_t u1l_count;
/* initialize array variable to store the content of BLlist */
uint32_t u4l_block_addr[4];
/* get the address from define values of BList */
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;
}
/*****************************************************************************
* Function Name:FLReadSectors
* Description: This routine is used to Read the Flash pages of sectors/bank
* store its contents to RAM memory locations refered by pointer
*
*
* Inputs:
*
* nSector uint8_t 1 - 15 (BANK A)
* 16 - 30 (BANK B)
*
* u1l_start_page uint8_t 1 - 16 (8KB sector)
* 1 - 128(64KB sector)
* u1l_end_page uint8_t 1 - 16 (8KB sector)
* 1 - 128(64KB sector)
* pnDestination uint32_t * Pointer to RAM memory locations to
* where data from flash to be stored
*
* Outputs:
*
*
* Returns: s1l_status int8_t FLASH_STATUS_OK
* FLASH_STATUS_FAILED
******************************************************************************/
int8_t FLReadSectors(uint8_t nSector,uint8_t nPageStart, uint8_t nPageEnd,
uint32_t *pnDestination)
{
/* initialize the variables */
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;
}
/* check the given sector numbers, pages and memory locations are valid
or not */
s1l_status = Check_Flash_Access(nSector, nPageStart, nPageEnd,
pnDestination, FLASH_READ);
if(s1l_status == 0)
{
/* call read data function */
s1l_status = ReadData(bg_bank_number, u1l_sec_num, nPageStart, nPageEnd,
pnDestination);
bg_busy = 0;
}
return s1l_status;
}
/*****************************************************************************
* Function Name:FLWriteSectors
* Description: This routine is to Write data in between start page and
* end page. The content of data will be copied from RAM memory
* to Flash pages.
*
*
* Inputs:
*
* nSector uint8_t 1 - 15 (BANK A)
* 16 - 30 (BANK B)
* u1l_start_page uint8_t 1 - 16 (8KB sector)
* 1 - 128(64KB sector)
* u1l_end_page uint8_t 1 - 16 (8KB sector)
* 1 - 128(64KB sector)
* pnSource uint32_t * Pointer to RAM memory locations from
* where data to be written to flash
*
* Outputs:
* Write data in the given range of pages
*
* Returns: s1l_status int8_t FLASH_STATUS_OK
* TIMEOUT_OCCURED
* WRITTEN_DATA_DIDNOT_VERIFY
* ONE_OR_MORE_PAGES_NOT_ERASED
* START_PAGE_NOT_SUPPORTED
* END_PAGE_NOT_SUPPORTED
* END_PAGE_BEFORE_START_PAGE
* SECTOR_UNAVAILABLE
* DESTINATION_POINTER_INVALID
*****************************************************************************/
int8_t FLWriteSectors(uint8_t nSector, uint8_t nPageStart, uint8_t nPageEnd,
uint32_t *pnSource)
{
/* initialize the varaibles */
int8_t s1l_status;
uint8_t u1l_sec_num;
bool bl_bank_num;
/* check in which bank the given sector resides */
if(nSector > 15)
{
bl_bank_num = 1;
u1l_sec_num = nSector - 16;
}
else
{
bl_bank_num = 0;
u1l_sec_num = nSector - 1;
}
/* check the given sector numbers, page numbers and RAM locations are valid
or not */
s1l_status = Check_Flash_Access(nSector, nPageStart, nPageEnd, pnSource,
FLASH_WRITE);
if(s1l_status == FLASH_STATUS_OK)
{
/* before writing erase pages, which needs to be written */
s1l_status = FLEraseSectors( nSector, nPageStart, nPageEnd);
}
/* if successfully erased write data from RAM to Flash */
if((s1l_status == FLASH_STATUS_OK) && (bg_busy==0))
{
s1l_status = Flash_ProgramPage(bl_bank_num, u1l_sec_num, nPageStart,
nPageEnd, (unsigned char *)pnSource );
/* make busy flag as 1 to avoid any erase, write operations*/
bg_busy = 1;
/* if success */
if(s1l_status == FLASH_STATUS_OK)
{
/* verify written flash data with source buffer */
s1l_status = Write_Data_Verify(bl_bank_num, u1l_sec_num,
nPageStart, nPageEnd, pnSource);
if(s1l_status != 0)
{
/* written data does not equal with source
buffer data */
s1l_status = WRITTEN_DATA_DIDNOT_VERIFY;
}
}
/* unblock the flag */
bg_busy = 0;
}
else if(s1l_status == FLASH_CONTENTS_NOT_VERIFY)
{
/* */
s1l_status = ONE_OR_MORE_PAGES_NOT_ERASED;
}
return s1l_status;
}
/*****************************************************************************
* Function Name: FLEraseSectors
* Description: This routine is used to Erase the Flash pages of sectors/bank
*
*
* Inputs:
*
* nSector uint8_t 1 - 15 (BANK A)
* 16 - 30 (BANK B)
*
* u1l_start_page uint8_t 1 - 16 (8KB sector)
* 1 - 128(64KB sector)
* u1l_end_page uint8_t 1 - 16 (8KB sector)
* 1 - 128(64KB sector)
*
*
* Outputs:
* s1l_status uint32_t Status
*
* Returns: s1l_status int8_t FLASH_STATUS_OK
* TIMEOUT_OCCURED
* FLASH_CONTENTS_NOT_VERIFY
* ONE_OR_MORE_PAGES_NOT_ERASED
* START_PAGE_NOT_SUPPORTED
* END_PAGE_NOT_SUPPORTED
* END_PAGE_BEFORE_START_PAGE
* SECTOR_UNAVAILABLE
* DESTINATION_POINTER_INVALID
*
*
*****************************************************************************/
int8_t FLEraseSectors(uint8_t nSector, uint8_t nPageStart, uint8_t nPageEnd)
{
/* initialization of local varaibles */
/* initialize the varaibles */
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;
}
/* check the given sector numbers are valid or not */
s1l_status = Check_Flash_Access(nSector, nPageStart, nPageEnd, 0, FLASH_ERASE);
/* check for sector verifcation and flash is not busy */
if((s1l_status == FLASH_STATUS_OK) && (bg_busy==0))
{
/* Erase Page in the sector */
s1l_status = Flash_ErasePage(bl_bank_num, u1l_sec_num, nPageStart,
nPageEnd);
/* Verify the erased content */
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
{
/* error sector number and error page number */
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.