309 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			309 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
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @}
 | |
|  */
 |