/**************************************************************************//**
* $Id: lpc12xx_flash.c 387 2010-08-27 03:15:52Z cnh20509 $
*
* @file lpc12xx_flash.c
* @brief Contains all functions support for FLASH firmware library on LPC12xx.
* @version 1.0
* @date 26. Sep. 2010
* @author NXP MCU Team
*
* @note
* Copyright (C) 2010 NXP Semiconductors(NXP). All rights reserved.
*
* @par
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* products. This software is supplied "AS IS" without any warranties.
* NXP Semiconductors assumes no responsibility or liability for the
* use of the software, conveys no license or title under any patent,
* copyright, or mask work right to the product. NXP Semiconductors
* reserves the right to make changes in the software without
* notification. NXP Semiconductors also make no representation or
* warranty that such application will be suitable for the specified
* use without further testing or modification.
******************************************************************************/
/* Peripheral group --------------------------------------------------------- */
/** @addtogroup FLASH
* @{
*/
/* Includes ----------------------------------------------------------------- */
#include "lpc12xx_flash.h"
#include "lpc12xx_libcfig.h"
/** @defgroup FLASH_Private_Macros
* @{
*/
#define IAP_CLK SystemCoreClock
#define IAP_CLK_KHZ (IAP_CLK / 1000)
#define IAP_LOCATION 0x1FFF1FF1
#define iap_entry(a, b) ((void (*)())(IAP_LOCATION))(a, b)
/**
* @}
*/
/** @defgroup FLASH_Private_Variables
* @{
*/
static IAP_U32 command[5] = {0,0,0,0,0};
static IAP_U32 result[5] = {0,0,0,0,0};
/**
* @}
*/
/** @defgroup FLASH_Private_Functions
* @{
*/
/**
* @brief Prepare sector(s) for erase/write operation.
*
* @param Start: The start sector number.
* @param End : The end sector number.
* It should be greater than or equal to start sector number.
* @retval Status code of this operation, see @ref IAP_Status_Codes.
* This parameter can be one of the following values:
* @arg IAP_STAT_CMD_SUCCESS
* @arg IAP_STAT_INVALID_SECTOR
* @arg IAP_STAT_BUSY
*
* This command must be executed before executing "Copy RAM to flash"
* or "Erase Sector(s)" command.
*/
IAP_Status IAP_PrepareSector (IAP_U32 Start, IAP_U32 End)
{
command[0] = IAP_CMD_PrepareSecor;
command[1] = Start;
command[2] = End;
iap_entry(command, result);
return result[0];
}
/**
* @brief Program the flash program.
*
* @param Dst: Destination flash address. Should be a 4 byte boundary.
* @param Src: Source RAM address. Should be a word boundary.
* @param Number: Number of byte to be written. Must be a multiple of 4 bytes.
* @retval Status code of this operation, see @ref IAP_Status_Codes.
* This parameter can be one of the following values:
* @arg IAP_STAT_CMD_SUCCESS
* @arg IAP_STAT_SRC_ADDR_ERROR
* @arg IAP_STAT_DST_ADDR_ERROR
* @arg IAP_STAT_SRC_ADDR_NOT_MAPPED
* @arg IAP_STAT_DST_ADDR_NOT_MAPPED
* @arg IAP_STAT_COUNT_ERROR
* @arg IAP_STAT_SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION
* @arg IAP_STAT_BUSY
*
* The affected sectors should be prepared first by calling
* "Prepare Sector for Write Operation" command.
* The boot sector can not be written by this command.
*/
IAP_Status IAP_CopyRAMToFlash (IAP_U32 Dst, IAP_U32 Src, IAP_U32 Number)
{
command[0] = IAP_CMD_CopyRAMToFlash;
command[1] = Dst;
command[2] = Src;
command[3] = Number;
command[4] = IAP_CLK_KHZ; // Fcclk in KHz
iap_entry(command, result);
return result[0];
}
/**
* @brief Erase a sector or multiple sectors of on-chip flash memory..
*
* @param Start: The start sector number.
* @param End : The end sector number.
* It should be greater than or equal to start sector number.
* @retval Status code of this operation, see @ref IAP_Status_Codes.
* This parameter can be one of the following values:
* @arg IAP_STAT_CMD_SUCCESS
* @arg IAP_STAT_INVALID_SECTOR
* @arg IAP_STAT_SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION
* @arg IAP_STAT_BUSY
*
* The boot sector can not be erased by this command. To erase a single
* sector use the same "Start" and "End" sector numbers.
*/
IAP_Status IAP_EraseSector (IAP_U32 Start, IAP_U32 End)
{
command[0] = IAP_CMD_EraseSecor;
command[1] = Start;
command[2] = End;
command[3] = IAP_CLK_KHZ; // IAP_CLK / 1000;
iap_entry(command, result);
return result[0];
}
/**
* @brief Blank check a sector or multiple sectors of on-chip flash memory.
*
* @param Start: The start sector number.
* @param End : The end sector number.
* It should be greater than or equal to start sector number.
* @param NonBlank: Pointer to buffer which contains the offset of the first
* non blank word location if the Status Code is SECTOR_NOT_BLANK and
* Contents of non blank word location.
* @retval Status code of this operation, see @ref IAP_Status_Codes.
* This parameter can be one of the following values:
* @arg IAP_STAT_CMD_SUCCESS
* @arg IAP_STAT_INVALID_SECTOR
* @arg IAP_STAT_SECTOR_NOT_BLANK
* @arg IAP_STAT_BUSY
*
* The boot sector can not be erased by this command. To erase a single
* sector use the same "Start" and "End" sector numbers.
*/
IAP_Status IAP_BlankCheckSecor (IAP_U32 Start, IAP_U32 End, IAP_U32 * NonBlank)
{
command[0] = IAP_CMD_BlankCheckSecor;
command[1] = Start;
command[2] = End;
iap_entry(command, result);
if (result[0] == IAP_STAT_SECTOR_NOT_BLANK)
{
*NonBlank = result[1];
*(NonBlank+1) = result[2];
}
return result[0];
}
/**
* @brief Read the part identification number.
*
* @param PartID: Pointer to one-word Part Identification Number
* @retval Status code of this operation, see @ref IAP_Status_Codes.
* This parameter can be one of the following values:
* @arg IAP_STAT_CMD_SUCCESS
*/
IAP_Status IAP_ReadParID (IAP_U32 * PartID)
{
command[0] = IAP_CMD_ReadPartID;
iap_entry(command, result);
*PartID = result[1];
return result[0];
}
/**
* @brief Read the boot code version number.
*
* @param Version: Pointer to one-word boot code version number in ASCII format.
* It is to be interpreted as ..
* @retval Status code of this operation, see @ref IAP_Status_Codes.
* This parameter can be one of the following values:
* @arg IAP_STAT_CMD_SUCCESS
*/
IAP_Status IAP_ReadBootVersion (IAP_U32 *Version)
{
command[0] = IAP_CMD_ReadBootVersion;
iap_entry(command, result);
*Version = result[1] & 0xFFFF;
return result[0];
}
/**
* @brief Compare the memory contents at two locations.
*
* @param Dst: Starting flash or RAM address of data bytes to be compared.
* This address should be a word boundary.
* @param Src: Starting flash or RAM address of data bytes to be compared.
* This address should be a word boundary.
* @param Number: Number of bytes to be compared; should be a multiple of 4.
* @param Offset: Pointer to one-word offset of the first mismatch if the Status Code
* is COMPARE_ERROR.
* @retval Status code of this operation, see @ref IAP_Status_Codes.
* This parameter can be one of the following values:
* @arg IAP_STAT_CMD_SUCCESS
* @arg IAP_STAT_COMPARE_ERROR
* @arg IAP_STAT_COUNT_ERROR
* @arg IAP_STAT_SRC_ADDR_NOT_MAPPED
* @arg IAP_STAT_DST_ADDR_NOT_MAPPED
* @arg IAP_STAT_SRC_ADDR_NOT_MAPPED
* @arg IAP_STAT_DST_ADDR_NOT_MAPPED
*
* The result may not be correct when the source or destination includes any
* of the first 512 bytes starting from address zero. The first 512 bytes can
* be re-mapped to RAM.
*/
IAP_Status IAP_Compare (IAP_U32 Dst, IAP_U32 Src, IAP_U32 Number, IAP_U32 *Offset)
{
command[0] = IAP_CMD_Compare;
command[1] = Dst;
command[2] = Src;
command[3] = Number;
iap_entry(command, result);
if (result[0] == IAP_STAT_COMPARE_ERROR)
*Offset = result[1];
return result[0];
}
/**
* @brief Invoke the bootloader in ISP mode.
*
* @param None
* @retval None
*/
void IAP_ReinvokeISP(void)
{
command[0] = IAP_CMD_ReinvokeISP;
iap_entry(command, result);
}
/**
* @brief Read the unique ID.
*
* @param UID: Pointer to a 4-word unique ID.
* @retval Status code of this operation, see @ref IAP_Status_Codes.
* This parameter can be one of the following values:
* @arg IAP_STAT_CMD_SUCCESS
*/
IAP_Status IAP_ReadUID (IAP_U32 * UID)
{
command[0] = IAP_CMD_ReadUID;
iap_entry(command, result);
*(UID + 0) = result[1];
*(UID + 1) = result[2];
*(UID + 2) = result[3];
*(UID + 3) = result[4];
return result[0];
}
/**
* @brief Erase page(s).
*
* @param Start: The start page number.
* @param End : The end page number.
* It should be greater than or equal to start sector number.
* @retval Status code of this operation, see @ref IAP_Status_Codes.
* This parameter can be one of the following values:
* @arg IAP_STAT_CMD_SUCCESS
* @arg IAP_STAT_INVALID_SECTOR
* @arg IAP_STAT_SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION
* @arg IAP_STAT_BUSY
*
* To erase a single page use the same "Start" and "End" sector numbers.
*/
IAP_Status IAP_ErasePage (IAP_U32 Start, IAP_U32 End)
{
command[0] = IAP_CMD_ErasePage;
command[1] = Start;
command[2] = End;
command[3] = IAP_CLK_KHZ; // IAP_CLK / 1000;
iap_entry(command, result);
return result[0];
}
/**
* @brief Erase a page or multiple pages of the information block. .
*
* @param Start: The start page number.
* @param End : The end page number.
* It should be greater than or equal to start sector number.
* @retval Status code of this operation, see @ref IAP_Status_Codes.
* This parameter can be one of the following values:
* @arg IAP_STAT_CMD_SUCCESS
* @arg IAP_STAT_INVALID_SECTOR
* @arg IAP_STAT_SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION
* @arg IAP_STAT_BUSY
*
* To erase a single page use the same "Start" and "End" sector numbers.
*/
IAP_Status IAP_EraseInfoPage (IAP_U32 Start, IAP_U32 End)
{
command[0] = IAP_CMD_EraseInfoPage;
command[1] = Start;
command[2] = End;
command[3] = IAP_CLK_KHZ; // IAP_CLK / 1000;
iap_entry(command, result);
return result[0];
}
/**
* @}
*/
/**
* @}
*/
/* --------------------------------- End Of File ------------------------------ */
|