311 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			311 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/**********************************************************************
							 | 
						||
| 
								 | 
							
								* $Id$      lpc17xx_iap.c           2012-04-18
							 | 
						||
| 
								 | 
							
								*//**
							 | 
						||
| 
								 | 
							
								* @file     lpc17xx_iap.c
							 | 
						||
| 
								 | 
							
								 * @brief   Contains all functions support for IAP on lpc17xx
							 | 
						||
| 
								 | 
							
								* @version  1.0
							 | 
						||
| 
								 | 
							
								* @date     18. April. 2012
							 | 
						||
| 
								 | 
							
								* @author   NXP MCU SW Application Team
							 | 
						||
| 
								 | 
							
								* 
							 | 
						||
| 
								 | 
							
								* Copyright(C) 2011, NXP Semiconductor
							 | 
						||
| 
								 | 
							
								* All rights reserved.
							 | 
						||
| 
								 | 
							
								*
							 | 
						||
| 
								 | 
							
								***********************************************************************
							 | 
						||
| 
								 | 
							
								* 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.
							 | 
						||
| 
								 | 
							
								* Permission to use, copy, modify, and distribute this software and its
							 | 
						||
| 
								 | 
							
								* documentation is hereby granted, under NXP Semiconductors'
							 | 
						||
| 
								 | 
							
								* relevant copyright in the software, without fee, provided that it
							 | 
						||
| 
								 | 
							
								* is used in conjunction with NXP Semiconductors microcontrollers.  This
							 | 
						||
| 
								 | 
							
								* copyright, permission, and disclaimer notice must appear in all copies of
							 | 
						||
| 
								 | 
							
								* this code.
							 | 
						||
| 
								 | 
							
								**********************************************************************/
							 | 
						||
| 
								 | 
							
								#include "lpc17xx_iap.h"
							 | 
						||
| 
								 | 
							
								#include "system_LPC17xx.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//  IAP Command
							 | 
						||
| 
								 | 
							
								typedef void (*IAP)(uint32_t *cmd,uint32_t *result);
							 | 
						||
| 
								 | 
							
								IAP iap_entry = (IAP) IAP_LOCATION;
							 | 
						||
| 
								 | 
							
								#define IAP_Call    iap_entry
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** @addtogroup IAP_Public_Functions IAP Public Function
							 | 
						||
| 
								 | 
							
								 * @ingroup IAP
							 | 
						||
| 
								 | 
							
								 * @{
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*********************************************************************//**
							 | 
						||
| 
								 | 
							
								 * @brief       Get Sector Number
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] adr              Sector Address
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @return  Sector Number.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 **********************************************************************/
							 | 
						||
| 
								 | 
							
								 uint32_t GetSecNum (uint32_t adr)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    uint32_t n;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    n = adr >> 12;                               //  4kB Sector
							 | 
						||
| 
								 | 
							
								    if (n >= 0x10) {
							 | 
						||
| 
								 | 
							
								      n = 0x0E + (n >> 3);                       // 32kB Sector
							 | 
						||
| 
								 | 
							
								    } 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return (n);                                  // Sector Number
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*********************************************************************//**
							 | 
						||
| 
								 | 
							
								 * @brief       Prepare sector(s) for write operation
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] start_sec           The number of start sector
							 | 
						||
| 
								 | 
							
								 * @param[in] end_sec             The number of end sector
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @return  CMD_SUCCESS/BUSY/INVALID_SECTOR.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 **********************************************************************/
							 | 
						||
| 
								 | 
							
								IAP_STATUS_CODE PrepareSector(uint32_t start_sec, uint32_t end_sec)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    IAP_COMMAND_Type command;
							 | 
						||
| 
								 | 
							
								    command.cmd    = IAP_PREPARE;                    // Prepare Sector for Write
							 | 
						||
| 
								 | 
							
								    command.param[0] = start_sec;                    // Start Sector
							 | 
						||
| 
								 | 
							
								    command.param[1] = end_sec;                      // End Sector
							 | 
						||
| 
								 | 
							
								    IAP_Call (&command.cmd, &command.status);        // Call IAP Command
							 | 
						||
| 
								 | 
							
								    return (IAP_STATUS_CODE)command.status;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*********************************************************************//**
							 | 
						||
| 
								 | 
							
								 * @brief        Copy RAM to Flash
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] dest            destination buffer (in Flash memory).
							 | 
						||
| 
								 | 
							
								 * @param[in] source       source buffer (in RAM).
							 | 
						||
| 
								 | 
							
								 * @param[in] size            the write size.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @return  CMD_SUCCESS.
							 | 
						||
| 
								 | 
							
								 *                  SRC_ADDR_ERROR/DST_ADDR_ERROR
							 | 
						||
| 
								 | 
							
								 *                  SRC_ADDR_NOT_MAPPED/DST_ADDR_NOT_MAPPED
							 | 
						||
| 
								 | 
							
								 *                  COUNT_ERROR/SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION
							 | 
						||
| 
								 | 
							
								 *                  BUSY
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 **********************************************************************/
							 | 
						||
| 
								 | 
							
								IAP_STATUS_CODE CopyRAM2Flash(uint8_t * dest, uint8_t* source, IAP_WRITE_SIZE size)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    uint32_t sec;
							 | 
						||
| 
								 | 
							
								    IAP_STATUS_CODE status;
							 | 
						||
| 
								 | 
							
								    IAP_COMMAND_Type command;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Prepare sectors
							 | 
						||
| 
								 | 
							
								    sec = GetSecNum((uint32_t)dest);
							 | 
						||
| 
								 | 
							
								    status = PrepareSector(sec, sec);
							 | 
						||
| 
								 | 
							
								    if(status != CMD_SUCCESS)
							 | 
						||
| 
								 | 
							
								        return status;
							 | 
						||
| 
								 | 
							
								   
							 | 
						||
| 
								 | 
							
								    // write
							 | 
						||
| 
								 | 
							
								    command.cmd    = IAP_COPY_RAM2FLASH;             // Copy RAM to Flash
							 | 
						||
| 
								 | 
							
								    command.param[0] = (uint32_t)dest;                 // Destination Flash Address
							 | 
						||
| 
								 | 
							
								    command.param[1] = (uint32_t)source;               // Source RAM Address
							 | 
						||
| 
								 | 
							
								    command.param[2] =  size;                          // Number of bytes
							 | 
						||
| 
								 | 
							
								    command.param[3] =  SystemCoreClock / 1000;         // CCLK in kHz
							 | 
						||
| 
								 | 
							
								    IAP_Call (&command.cmd, &command.status);              // Call IAP Command
							 | 
						||
| 
								 | 
							
								      
							 | 
						||
| 
								 | 
							
								    return (IAP_STATUS_CODE)command.status;             // Finished without Errors    
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*********************************************************************//**
							 | 
						||
| 
								 | 
							
								 * @brief        Erase sector(s)
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] start_sec    The number of start sector
							 | 
						||
| 
								 | 
							
								 * @param[in] end_sec      The number of end sector
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @return  CMD_SUCCESS.
							 | 
						||
| 
								 | 
							
								 *                  INVALID_SECTOR
							 | 
						||
| 
								 | 
							
								 *                  SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION
							 | 
						||
| 
								 | 
							
								 *                  BUSY
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 **********************************************************************/
							 | 
						||
| 
								 | 
							
								IAP_STATUS_CODE EraseSector(uint32_t start_sec, uint32_t end_sec)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    IAP_COMMAND_Type command;
							 | 
						||
| 
								 | 
							
								    IAP_STATUS_CODE status;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Prepare sectors
							 | 
						||
| 
								 | 
							
								    status = PrepareSector(start_sec, end_sec);
							 | 
						||
| 
								 | 
							
								    if(status != CMD_SUCCESS)
							 | 
						||
| 
								 | 
							
								        return status;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Erase sectors
							 | 
						||
| 
								 | 
							
								    command.cmd    = IAP_ERASE;                    // Prepare Sector for Write
							 | 
						||
| 
								 | 
							
								    command.param[0] = start_sec;                  // Start Sector
							 | 
						||
| 
								 | 
							
								    command.param[1] = end_sec;                    // End Sector
							 | 
						||
| 
								 | 
							
								    command.param[2] =  SystemCoreClock / 1000;         // CCLK in kHz
							 | 
						||
| 
								 | 
							
								    IAP_Call (&command.cmd, &command.status);      // Call IAP Command
							 | 
						||
| 
								 | 
							
								    return (IAP_STATUS_CODE)command.status;  
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*********************************************************************//**
							 | 
						||
| 
								 | 
							
								 * @brief         Blank check sector(s)
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] start_sec    The number of start sector
							 | 
						||
| 
								 | 
							
								 * @param[in] end_sec      The number of end sector
							 | 
						||
| 
								 | 
							
								 * @param[out] first_nblank_loc  The offset of the first non-blank word
							 | 
						||
| 
								 | 
							
								  * @param[out] first_nblank_val  The value of the first non-blank word
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @return  CMD_SUCCESS.
							 | 
						||
| 
								 | 
							
								 *                  INVALID_SECTOR
							 | 
						||
| 
								 | 
							
								 *                  SECTOR_NOT_BLANK
							 | 
						||
| 
								 | 
							
								 *                  BUSY
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 **********************************************************************/
							 | 
						||
| 
								 | 
							
								IAP_STATUS_CODE BlankCheckSector(uint32_t start_sec, uint32_t end_sec,
							 | 
						||
| 
								 | 
							
								                                 uint32_t *first_nblank_loc, 
							 | 
						||
| 
								 | 
							
								                                 uint32_t *first_nblank_val)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    IAP_COMMAND_Type command;
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    command.cmd    = IAP_BLANK_CHECK;                // Prepare Sector for Write
							 | 
						||
| 
								 | 
							
								    command.param[0] = start_sec;                    // Start Sector
							 | 
						||
| 
								 | 
							
								    command.param[1] = end_sec;                      // End Sector
							 | 
						||
| 
								 | 
							
								    IAP_Call (&command.cmd, &command.status);        // Call IAP Command
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if(command.status == SECTOR_NOT_BLANK)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      // Update out value
							 | 
						||
| 
								 | 
							
								      if(first_nblank_loc != NULL)
							 | 
						||
| 
								 | 
							
								          *first_nblank_loc =  command.result[0];
							 | 
						||
| 
								 | 
							
								      if(first_nblank_val != NULL)
							 | 
						||
| 
								 | 
							
								          *first_nblank_val =  command.result[1];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return (IAP_STATUS_CODE)command.status;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*********************************************************************//**
							 | 
						||
| 
								 | 
							
								 * @brief          Read part identification number
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[out] partID  Part ID
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @return  CMD_SUCCESS
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 **********************************************************************/
							 | 
						||
| 
								 | 
							
								IAP_STATUS_CODE ReadPartID(uint32_t *partID)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   IAP_COMMAND_Type command;
							 | 
						||
| 
								 | 
							
								   command.cmd = IAP_READ_PART_ID;
							 | 
						||
| 
								 | 
							
								   IAP_Call (&command.cmd, &command.status);        // Call IAP Command
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   if(command.status == CMD_SUCCESS)
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      if(partID != NULL)
							 | 
						||
| 
								 | 
							
								         *partID = command.result[0];
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   return (IAP_STATUS_CODE)command.status;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*********************************************************************//**
							 | 
						||
| 
								 | 
							
								 * @brief          Read boot code version. The version is interpreted as <major>.<minor>.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[out] major  The major
							 | 
						||
| 
								 | 
							
								 * @param[out] minor  The minor
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @return  CMD_SUCCESS
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 **********************************************************************/
							 | 
						||
| 
								 | 
							
								IAP_STATUS_CODE ReadBootCodeVer(uint8_t *major, uint8_t* minor)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   IAP_COMMAND_Type command;
							 | 
						||
| 
								 | 
							
								   command.cmd = IAP_READ_BOOT_VER;
							 | 
						||
| 
								 | 
							
								   IAP_Call (&command.cmd, &command.status);        // Call IAP Command
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   if(command.status == CMD_SUCCESS)
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      if(major != NULL)
							 | 
						||
| 
								 | 
							
								         *major = (command.result[0] >> 8) & 0xFF;
							 | 
						||
| 
								 | 
							
								      if(minor != NULL)
							 | 
						||
| 
								 | 
							
								         *minor = (command.result[0]) & 0xFF;
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   return (IAP_STATUS_CODE)command.status;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*********************************************************************//**
							 | 
						||
| 
								 | 
							
								 * @brief          Read Device serial number.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[out] uid   Serial number.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @return  CMD_SUCCESS
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 **********************************************************************/
							 | 
						||
| 
								 | 
							
								IAP_STATUS_CODE ReadDeviceSerialNum(uint32_t *uid)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   IAP_COMMAND_Type command;
							 | 
						||
| 
								 | 
							
								   command.cmd = IAP_READ_SERIAL_NUMBER;
							 | 
						||
| 
								 | 
							
								   IAP_Call (&command.cmd, &command.status);        // Call IAP Command
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   if(command.status == CMD_SUCCESS)
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      if(uid != NULL)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        uint32_t i = 0;
							 | 
						||
| 
								 | 
							
								        for(i = 0; i < 4; i++)
							 | 
						||
| 
								 | 
							
								           uid[i] =  command.result[i];
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   return (IAP_STATUS_CODE)command.status;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*********************************************************************//**
							 | 
						||
| 
								 | 
							
								 * @brief          compare the memory contents at two locations.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] addr1   The address of the 1st buffer (in RAM/Flash).
							 | 
						||
| 
								 | 
							
								 * @param[in] addr2   The address of the 2nd buffer (in RAM/Flash).
							 | 
						||
| 
								 | 
							
								 * @param[in] size      Number of bytes to be compared; should be a multiple of 4.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @return  CMD_SUCCESS
							 | 
						||
| 
								 | 
							
								 *                  COMPARE_ERROR
							 | 
						||
| 
								 | 
							
								 *                  COUNT_ERROR (Byte count is not a multiple of 4)
							 | 
						||
| 
								 | 
							
								 *                  ADDR_ERROR
							 | 
						||
| 
								 | 
							
								 *                  ADDR_NOT_MAPPED
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 **********************************************************************/
							 | 
						||
| 
								 | 
							
								IAP_STATUS_CODE Compare(uint8_t *addr1, uint8_t *addr2, uint32_t size)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   IAP_COMMAND_Type command;
							 | 
						||
| 
								 | 
							
								   command.cmd = IAP_COMPARE;
							 | 
						||
| 
								 | 
							
								   command.param[0] = (uint32_t)addr1;
							 | 
						||
| 
								 | 
							
								   command.param[1] = (uint32_t)addr2;
							 | 
						||
| 
								 | 
							
								   command.param[2] = size;
							 | 
						||
| 
								 | 
							
								   IAP_Call (&command.cmd, &command.status);        // Call IAP Command
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   return (IAP_STATUS_CODE)command.status;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*********************************************************************//**
							 | 
						||
| 
								 | 
							
								 * @brief          Re-invoke ISP.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param[in] None.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @return  None.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 **********************************************************************/
							 | 
						||
| 
								 | 
							
								void InvokeISP(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   IAP_COMMAND_Type command;
							 | 
						||
| 
								 | 
							
								   command.cmd = IAP_REINVOKE_ISP;
							 | 
						||
| 
								 | 
							
								   IAP_Call (&command.cmd, &command.status);        // Call IAP Command
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @}
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								 
							 | 
						||
| 
								 | 
							
								
							 |