lpc-field

Template project for programming NXP's LPC1768 MCUs
git clone git://git.mdnr.space/lpc-field
Log | Files | Refs | README | LICENSE

lpc17xx_iap.c (10421B)


      1 /**********************************************************************
      2 * $Id$		lpc17xx_iap.c			2012-04-18
      3 *//**
      4 * @file		lpc17xx_iap.c
      5  * @brief	Contains all functions support for IAP on lpc17xx
      6 * @version	1.0
      7 * @date		18. April. 2012
      8 * @author	NXP MCU SW Application Team
      9 * 
     10 * Copyright(C) 2011, NXP Semiconductor
     11 * All rights reserved.
     12 *
     13 ***********************************************************************
     14 * Software that is described herein is for illustrative purposes only
     15 * which provides customers with programming information regarding the
     16 * products. This software is supplied "AS IS" without any warranties.
     17 * NXP Semiconductors assumes no responsibility or liability for the
     18 * use of the software, conveys no license or title under any patent,
     19 * copyright, or mask work right to the product. NXP Semiconductors
     20 * reserves the right to make changes in the software without
     21 * notification. NXP Semiconductors also make no representation or
     22 * warranty that such application will be suitable for the specified
     23 * use without further testing or modification.
     24 * Permission to use, copy, modify, and distribute this software and its
     25 * documentation is hereby granted, under NXP Semiconductors'
     26 * relevant copyright in the software, without fee, provided that it
     27 * is used in conjunction with NXP Semiconductors microcontrollers.  This
     28 * copyright, permission, and disclaimer notice must appear in all copies of
     29 * this code.
     30 **********************************************************************/
     31 #include "lpc17xx_iap.h"
     32 #include "system_LPC17xx.h"
     33 
     34 //  IAP Command
     35 typedef void (*IAP)(uint32_t *cmd,uint32_t *result);
     36 IAP iap_entry = (IAP) IAP_LOCATION;
     37 #define IAP_Call 	iap_entry
     38 
     39 /** @addtogroup IAP_Public_Functions IAP Public Function
     40  * @ingroup IAP
     41  * @{
     42  */
     43  
     44 
     45 /*********************************************************************//**
     46  * @brief		Get Sector Number
     47  *
     48  * @param[in] adr	           Sector Address
     49  *
     50  * @return 	Sector Number.
     51  *
     52  **********************************************************************/
     53  uint32_t GetSecNum (uint32_t adr)
     54 {
     55     uint32_t n;
     56 
     57     n = adr >> 12;                               //  4kB Sector
     58     if (n >= 0x10) {
     59       n = 0x0E + (n >> 3);                       // 32kB Sector
     60     } 
     61 
     62     return (n);                                  // Sector Number
     63 }
     64 
     65 /*********************************************************************//**
     66  * @brief		Prepare sector(s) for write operation
     67  *
     68  * @param[in] start_sec	          The number of start sector
     69  * @param[in] end_sec	          The number of end sector
     70  *
     71  * @return 	CMD_SUCCESS/BUSY/INVALID_SECTOR.
     72  *
     73  **********************************************************************/
     74 IAP_STATUS_CODE PrepareSector(uint32_t start_sec, uint32_t end_sec)
     75 {
     76     IAP_COMMAND_Type command;
     77     command.cmd    = IAP_PREPARE;                    // Prepare Sector for Write
     78     command.param[0] = start_sec;                    // Start Sector
     79     command.param[1] = end_sec;                      // End Sector
     80     IAP_Call (&command.cmd, &command.status);        // Call IAP Command
     81     return (IAP_STATUS_CODE)command.status;
     82 }
     83 
     84 /*********************************************************************//**
     85  * @brief		 Copy RAM to Flash
     86  *
     87  * @param[in] dest	          destination buffer (in Flash memory).
     88  * @param[in] source	   source buffer (in RAM).
     89  * @param[in] size	          the write size.
     90  *
     91  * @return 	CMD_SUCCESS.
     92  *                  SRC_ADDR_ERROR/DST_ADDR_ERROR
     93  *                  SRC_ADDR_NOT_MAPPED/DST_ADDR_NOT_MAPPED
     94  *                  COUNT_ERROR/SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION
     95  *                  BUSY
     96  *
     97  **********************************************************************/
     98 IAP_STATUS_CODE CopyRAM2Flash(uint8_t * dest, uint8_t* source, IAP_WRITE_SIZE size)
     99 {
    100     uint32_t sec;
    101     IAP_STATUS_CODE status;
    102     IAP_COMMAND_Type command;
    103 
    104 	// Prepare sectors
    105     sec = GetSecNum((uint32_t)dest);
    106    	status = PrepareSector(sec, sec);
    107 	if(status != CMD_SUCCESS)
    108         return status;
    109    
    110 	// write
    111 	command.cmd    = IAP_COPY_RAM2FLASH;             // Copy RAM to Flash
    112     command.param[0] = (uint32_t)dest;                 // Destination Flash Address
    113     command.param[1] = (uint32_t)source;               // Source RAM Address
    114     command.param[2] =  size;                          // Number of bytes
    115     command.param[3] =  SystemCoreClock / 1000;         // CCLK in kHz
    116     IAP_Call (&command.cmd, &command.status);              // Call IAP Command
    117 	  
    118     return (IAP_STATUS_CODE)command.status;             // Finished without Errors	  
    119 }
    120 
    121 /*********************************************************************//**
    122  * @brief		 Erase sector(s)
    123  *
    124  * @param[in] start_sec	   The number of start sector
    125  * @param[in] end_sec	   The number of end sector
    126  *
    127  * @return 	CMD_SUCCESS.
    128  *                  INVALID_SECTOR
    129  *                  SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION
    130  *                  BUSY
    131  *
    132  **********************************************************************/
    133 IAP_STATUS_CODE EraseSector(uint32_t start_sec, uint32_t end_sec)
    134 {
    135     IAP_COMMAND_Type command;
    136     IAP_STATUS_CODE status;
    137 
    138 	// Prepare sectors
    139    	status = PrepareSector(start_sec, end_sec);
    140 	if(status != CMD_SUCCESS)
    141         return status;
    142 
    143 	// Erase sectors
    144     command.cmd    = IAP_ERASE;                    // Prepare Sector for Write
    145     command.param[0] = start_sec;                  // Start Sector
    146     command.param[1] = end_sec;                    // End Sector
    147     command.param[2] =  SystemCoreClock / 1000;         // CCLK in kHz
    148     IAP_Call (&command.cmd, &command.status);      // Call IAP Command
    149     return (IAP_STATUS_CODE)command.status;  
    150 }
    151 
    152 /*********************************************************************//**
    153  * @brief		  Blank check sector(s)
    154  *
    155  * @param[in] start_sec	   The number of start sector
    156  * @param[in] end_sec	   The number of end sector
    157  * @param[out] first_nblank_loc  The offset of the first non-blank word
    158   * @param[out] first_nblank_val  The value of the first non-blank word
    159  *
    160  * @return 	CMD_SUCCESS.
    161  *                  INVALID_SECTOR
    162  *                  SECTOR_NOT_BLANK
    163  *                  BUSY
    164  *
    165  **********************************************************************/
    166 IAP_STATUS_CODE BlankCheckSector(uint32_t start_sec, uint32_t end_sec,
    167                                  uint32_t *first_nblank_loc, 
    168 								 uint32_t *first_nblank_val)
    169 {
    170     IAP_COMMAND_Type command;
    171 	
    172     command.cmd    = IAP_BLANK_CHECK;                // Prepare Sector for Write
    173     command.param[0] = start_sec;                    // Start Sector
    174     command.param[1] = end_sec;                      // End Sector
    175     IAP_Call (&command.cmd, &command.status);        // Call IAP Command
    176 
    177 	if(command.status == SECTOR_NOT_BLANK)
    178 	{
    179 	  // Update out value
    180 	  if(first_nblank_loc != NULL)
    181 	      *first_nblank_loc =  command.result[0];
    182 	  if(first_nblank_val != NULL)
    183 	      *first_nblank_val =  command.result[1];
    184     }
    185 
    186     return (IAP_STATUS_CODE)command.status;
    187 }
    188 
    189 /*********************************************************************//**
    190  * @brief		   Read part identification number
    191  *
    192  * @param[out] partID  Part ID
    193  *
    194  * @return 	CMD_SUCCESS
    195  *
    196  **********************************************************************/
    197 IAP_STATUS_CODE ReadPartID(uint32_t *partID)
    198 {
    199    IAP_COMMAND_Type command;
    200    command.cmd = IAP_READ_PART_ID;
    201    IAP_Call (&command.cmd, &command.status);        // Call IAP Command
    202 
    203    if(command.status == CMD_SUCCESS)
    204    {
    205       if(partID != NULL)
    206 	     *partID = command.result[0];
    207    }
    208 
    209    return (IAP_STATUS_CODE)command.status;
    210 }
    211 
    212 /*********************************************************************//**
    213  * @brief		   Read boot code version. The version is interpreted as <major>.<minor>.
    214  *
    215  * @param[out] major  The major
    216  * @param[out] minor  The minor
    217  *
    218  * @return 	CMD_SUCCESS
    219  *
    220  **********************************************************************/
    221 IAP_STATUS_CODE ReadBootCodeVer(uint8_t *major, uint8_t* minor)
    222 {
    223    IAP_COMMAND_Type command;
    224    command.cmd = IAP_READ_BOOT_VER;
    225    IAP_Call (&command.cmd, &command.status);        // Call IAP Command
    226 
    227    if(command.status == CMD_SUCCESS)
    228    {
    229       if(major != NULL)
    230 	     *major = (command.result[0] >> 8) & 0xFF;
    231       if(minor != NULL)
    232 	     *minor = (command.result[0]) & 0xFF;
    233    }
    234 
    235    return (IAP_STATUS_CODE)command.status;
    236 }
    237 
    238 /*********************************************************************//**
    239  * @brief		   Read Device serial number.
    240  *
    241  * @param[out] uid   Serial number.
    242  *
    243  * @return 	CMD_SUCCESS
    244  *
    245  **********************************************************************/
    246 IAP_STATUS_CODE ReadDeviceSerialNum(uint32_t *uid)
    247 {
    248    IAP_COMMAND_Type command;
    249    command.cmd = IAP_READ_SERIAL_NUMBER;
    250    IAP_Call (&command.cmd, &command.status);        // Call IAP Command
    251 
    252    if(command.status == CMD_SUCCESS)
    253    {
    254       if(uid != NULL)
    255 	  {
    256 	    uint32_t i = 0;
    257 		for(i = 0; i < 4; i++)
    258 	       uid[i] =  command.result[i];
    259 	  }
    260    }
    261 
    262    return (IAP_STATUS_CODE)command.status;
    263 }
    264 
    265 /*********************************************************************//**
    266  * @brief		   compare the memory contents at two locations.
    267  *
    268  * @param[in] addr1   The address of the 1st buffer (in RAM/Flash).
    269  * @param[in] addr2   The address of the 2nd buffer (in RAM/Flash).
    270  * @param[in] size      Number of bytes to be compared; should be a multiple of 4.
    271  *
    272  * @return 	CMD_SUCCESS
    273  *                  COMPARE_ERROR
    274  *                  COUNT_ERROR (Byte count is not a multiple of 4)
    275  *                  ADDR_ERROR
    276  *                  ADDR_NOT_MAPPED
    277  *
    278  **********************************************************************/
    279 IAP_STATUS_CODE Compare(uint8_t *addr1, uint8_t *addr2, uint32_t size)
    280 {
    281    IAP_COMMAND_Type command;
    282    command.cmd = IAP_COMPARE;
    283    command.param[0] = (uint32_t)addr1;
    284    command.param[1] = (uint32_t)addr2;
    285    command.param[2] = size;
    286    IAP_Call (&command.cmd, &command.status);        // Call IAP Command
    287 
    288    return (IAP_STATUS_CODE)command.status;
    289 }
    290 
    291 /*********************************************************************//**
    292  * @brief		   Re-invoke ISP.
    293  *
    294  * @param[in] None.
    295  *
    296  * @return 	None.
    297  *
    298  **********************************************************************/
    299 void InvokeISP(void)
    300 {
    301    IAP_COMMAND_Type command;
    302    command.cmd = IAP_REINVOKE_ISP;
    303    IAP_Call (&command.cmd, &command.status);        // Call IAP Command
    304 }
    305 
    306 /**
    307  * @}
    308  */
    309  
    310