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