IAP class library for LPC1768 and LPC11U24

Fork of IAP by Tedd OKANO

Committer:
jaerts
Date:
Tue Oct 22 17:23:53 2013 +0000
Revision:
2:7484398d50ea
Parent:
1:ff906ad52cf9
Implement reinvoke isp function

Who changed what in which revision?

UserRevisionLine numberNew contents of line
okano 0:ada7fb504504 1 /** IAP : internal Flash memory access library
okano 0:ada7fb504504 2 *
okano 0:ada7fb504504 3 * The internal Flash memory access is described in the LPC1768 and LPC11U24 usermanual.
okano 0:ada7fb504504 4 * http://www.nxp.com/documents/user_manual/UM10360.pdf
okano 0:ada7fb504504 5 * http://www.nxp.com/documents/user_manual/UM10462.pdf
okano 0:ada7fb504504 6 *
okano 0:ada7fb504504 7 * LPC1768 --
okano 0:ada7fb504504 8 * Chapter 2: "LPC17xx Memory map"
okano 0:ada7fb504504 9 * Chapter 32: "LPC17xx Flash memory interface and programming"
okano 0:ada7fb504504 10 * refering Rev. 01 - 4 January 2010
okano 0:ada7fb504504 11 *
okano 0:ada7fb504504 12 * LPC11U24 --
okano 0:ada7fb504504 13 * Chapter 2: "LPC11Uxx Memory mapping"
okano 0:ada7fb504504 14 * Chapter 20: "LPC11Uxx Flash programming firmware"
okano 0:ada7fb504504 15 * refering Rev. 03 - 16 July 2012
okano 0:ada7fb504504 16 *
okano 0:ada7fb504504 17 * Released under the MIT License: http://mbed.org/license/mit
okano 0:ada7fb504504 18 *
okano 0:ada7fb504504 19 * revision 1.0 09-Mar-2010 1st release
okano 0:ada7fb504504 20 * revision 1.1 12-Mar-2010 chaged: to make possible to reserve flash area for user
okano 0:ada7fb504504 21 * it can be set by USER_FLASH_AREA_START and USER_FLASH_AREA_SIZE in IAP.h
okano 1:ff906ad52cf9 22 * revision 2.0 26-Nov-2012 LPC11U24 code added
okano 1:ff906ad52cf9 23 * revision 2.1 26-Nov-2012 EEPROM access code imported from Suga koubou san's (http://mbed.org/users/okini3939/) library
okano 1:ff906ad52cf9 24 * http://mbed.org/users/okini3939/code/M0_EEPROM_test/
okano 0:ada7fb504504 25 */
okano 0:ada7fb504504 26
okano 0:ada7fb504504 27 #include "mbed.h"
okano 0:ada7fb504504 28 #include "IAP.h"
okano 0:ada7fb504504 29
okano 0:ada7fb504504 30 #define USER_FLASH_AREA_START_STR( x ) STR( x )
okano 0:ada7fb504504 31 #define STR( x ) #x
okano 0:ada7fb504504 32
okano 0:ada7fb504504 33 unsigned char user_area[ USER_FLASH_AREA_SIZE ] __attribute__((section( ".ARM.__at_" USER_FLASH_AREA_START_STR( USER_FLASH_AREA_START ) ), zero_init));
okano 0:ada7fb504504 34
okano 0:ada7fb504504 35
okano 0:ada7fb504504 36 /*
okano 0:ada7fb504504 37 * Reserve of flash area is explained by Igor. Please refer next URL
okano 0:ada7fb504504 38 * http://mbed.org/users/okano/notebook/iap-in-application-programming-internal-flash-eras/?page=1#comment-271
okano 0:ada7fb504504 39 */
okano 0:ada7fb504504 40
okano 0:ada7fb504504 41 //unsigned char user_area[ size ] __attribute__((section(".ARM.__at_0x78000"), zero_init));
okano 0:ada7fb504504 42
okano 0:ada7fb504504 43 /*
okano 0:ada7fb504504 44 * IAP command codes
okano 0:ada7fb504504 45 * Table 589. "IAP Command Summary", Chapter 8. "IAP commands", usermanual
okano 0:ada7fb504504 46 */
okano 0:ada7fb504504 47
okano 0:ada7fb504504 48 enum command_code
okano 0:ada7fb504504 49 {
okano 0:ada7fb504504 50 IAPCommand_Prepare_sector_for_write_operation = 50,
okano 0:ada7fb504504 51 IAPCommand_Copy_RAM_to_Flash,
okano 0:ada7fb504504 52 IAPCommand_Erase_sector,
okano 0:ada7fb504504 53 IAPCommand_Blank_check_sector,
okano 0:ada7fb504504 54 IAPCommand_Read_part_ID,
okano 0:ada7fb504504 55 IAPCommand_Read_Boot_Code_version,
okano 0:ada7fb504504 56 IAPCommand_Compare,
okano 0:ada7fb504504 57 IAPCommand_Reinvoke_ISP,
okano 1:ff906ad52cf9 58 IAPCommand_Read_device_serial_number,
okano 1:ff906ad52cf9 59 #if defined(TARGET_LPC11U24)
okano 1:ff906ad52cf9 60 IAPCommand_EEPROM_Write = 61,
okano 1:ff906ad52cf9 61 IAPCommand_EEPROM_Read,
okano 1:ff906ad52cf9 62 #endif
okano 0:ada7fb504504 63 };
okano 0:ada7fb504504 64
okano 0:ada7fb504504 65
jaerts 2:7484398d50ea 66 /** Reinvoke ISP
jaerts 2:7484398d50ea 67 *
jaerts 2:7484398d50ea 68 * @return error code
jaerts 2:7484398d50ea 69 */
jaerts 2:7484398d50ea 70
jaerts 2:7484398d50ea 71 int IAP::reinvoke_isp( void ) {
jaerts 2:7484398d50ea 72 __disable_irq();
jaerts 2:7484398d50ea 73
jaerts 2:7484398d50ea 74 IAP_command[ 0 ] = IAPCommand_Reinvoke_ISP;
jaerts 2:7484398d50ea 75
jaerts 2:7484398d50ea 76 iap_entry( IAP_command, IAP_result );
jaerts 2:7484398d50ea 77
jaerts 2:7484398d50ea 78 return ( (int)IAP_result[ 0 ] );
jaerts 2:7484398d50ea 79 }
jaerts 2:7484398d50ea 80
jaerts 2:7484398d50ea 81
okano 0:ada7fb504504 82 /** Read part identification number
okano 0:ada7fb504504 83 *
okano 0:ada7fb504504 84 * @return device ID
okano 0:ada7fb504504 85 * @see read_serial()
okano 0:ada7fb504504 86 */
okano 0:ada7fb504504 87
okano 0:ada7fb504504 88 int IAP::read_ID( void ) {
okano 0:ada7fb504504 89 IAP_command[ 0 ] = IAPCommand_Read_part_ID;
okano 0:ada7fb504504 90
okano 0:ada7fb504504 91 iap_entry( IAP_command, IAP_result );
okano 0:ada7fb504504 92
okano 0:ada7fb504504 93 // return ( (int)IAP_result[ 0 ] );
okano 0:ada7fb504504 94 return ( (int)IAP_result[ 1 ] ); // to return the number itself (this command always returns CMD_SUCCESS)
okano 0:ada7fb504504 95 }
okano 0:ada7fb504504 96
okano 0:ada7fb504504 97
okano 0:ada7fb504504 98 /** Read device serial number
okano 0:ada7fb504504 99 *
okano 0:ada7fb504504 100 * @return device serial number
okano 0:ada7fb504504 101 * @see read_ID()
okano 0:ada7fb504504 102 */
okano 0:ada7fb504504 103
okano 0:ada7fb504504 104 int IAP::read_serial( void ) {
okano 0:ada7fb504504 105 IAP_command[ 0 ] = IAPCommand_Read_device_serial_number;
okano 0:ada7fb504504 106
okano 0:ada7fb504504 107 iap_entry( IAP_command, IAP_result );
okano 0:ada7fb504504 108
okano 0:ada7fb504504 109 // return ( (int)IAP_result[ 0 ] );
okano 0:ada7fb504504 110 return ( (int)IAP_result[ 1 ] ); // to return the number itself (this command always returns CMD_SUCCESS)
okano 0:ada7fb504504 111 }
okano 0:ada7fb504504 112
okano 0:ada7fb504504 113
okano 0:ada7fb504504 114 /** Blank check sector(s)
okano 0:ada7fb504504 115 *
okano 0:ada7fb504504 116 * @param start a Start Sector Number
okano 0:ada7fb504504 117 * @param end an End Sector Number (should be greater than or equal to start sector number).
okano 0:ada7fb504504 118 * @return error code: CMD_SUCCESS | BUSY | SECTOR_NOT_BLANK | INVALID_SECTOR
okano 0:ada7fb504504 119 */
okano 0:ada7fb504504 120
okano 0:ada7fb504504 121 int IAP::blank_check( int start, int end ) {
okano 0:ada7fb504504 122 IAP_command[ 0 ] = IAPCommand_Blank_check_sector;
okano 0:ada7fb504504 123 IAP_command[ 1 ] = (unsigned int)start; // Start Sector Number
okano 0:ada7fb504504 124 IAP_command[ 2 ] = (unsigned int)end; // End Sector Number (should be greater than or equal to start sector number)
okano 0:ada7fb504504 125
okano 0:ada7fb504504 126 iap_entry( IAP_command, IAP_result );
okano 0:ada7fb504504 127
okano 0:ada7fb504504 128 return ( (int)IAP_result[ 0 ] );
okano 0:ada7fb504504 129 }
okano 0:ada7fb504504 130
okano 0:ada7fb504504 131
okano 0:ada7fb504504 132 /** Erase Sector(s)
okano 0:ada7fb504504 133 *
okano 0:ada7fb504504 134 * @param start a Start Sector Number
okano 0:ada7fb504504 135 * @param end an End Sector Number (should be greater than or equal to start sector number).
okano 0:ada7fb504504 136 * @return error code: CMD_SUCCESS | BUSY | SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION | INVALID_SECTOR
okano 0:ada7fb504504 137 */
okano 0:ada7fb504504 138
okano 0:ada7fb504504 139 int IAP::erase( int start, int end ) {
okano 0:ada7fb504504 140 IAP_command[ 0 ] = IAPCommand_Erase_sector;
okano 0:ada7fb504504 141 IAP_command[ 1 ] = (unsigned int)start; // Start Sector Number
okano 0:ada7fb504504 142 IAP_command[ 2 ] = (unsigned int)end; // End Sector Number (should be greater than or equal to start sector number)
okano 0:ada7fb504504 143 IAP_command[ 3 ] = cclk_kHz; // CPU Clock Frequency (CCLK) in kHz
okano 0:ada7fb504504 144
okano 0:ada7fb504504 145 iap_entry( IAP_command, IAP_result );
okano 0:ada7fb504504 146
okano 0:ada7fb504504 147 return ( (int)IAP_result[ 0 ] );
okano 0:ada7fb504504 148 }
okano 0:ada7fb504504 149
okano 0:ada7fb504504 150
okano 0:ada7fb504504 151 /** Prepare sector(s) for write operation
okano 0:ada7fb504504 152 *
okano 0:ada7fb504504 153 * @param start a Start Sector Number
okano 0:ada7fb504504 154 * @param end an End Sector Number (should be greater than or equal to start sector number).
okano 0:ada7fb504504 155 * @return error code: CMD_SUCCESS | BUSY | INVALID_SECTOR
okano 0:ada7fb504504 156 */
okano 0:ada7fb504504 157
okano 0:ada7fb504504 158 int IAP::prepare( int start, int end ) {
okano 0:ada7fb504504 159 IAP_command[ 0 ] = IAPCommand_Prepare_sector_for_write_operation;
okano 0:ada7fb504504 160 IAP_command[ 1 ] = (unsigned int)start; // Start Sector Number
okano 0:ada7fb504504 161 IAP_command[ 2 ] = (unsigned int)end; // End Sector Number (should be greater than or equal to start sector number).
okano 0:ada7fb504504 162
okano 0:ada7fb504504 163 iap_entry( IAP_command, IAP_result );
okano 0:ada7fb504504 164
okano 0:ada7fb504504 165 return ( (int)IAP_result[ 0 ] );
okano 0:ada7fb504504 166 }
okano 0:ada7fb504504 167
okano 0:ada7fb504504 168
okano 0:ada7fb504504 169 /** Copy RAM to Flash
okano 0:ada7fb504504 170 *
okano 0:ada7fb504504 171 * @param source_addr Source RAM address from which data bytes are to be read. This address should be a word boundary.
okano 0:ada7fb504504 172 * @param target_addr Destination flash address where data bytes are to be written. This address should be a 256 byte boundary.
okano 0:ada7fb504504 173 * @param size Number of bytes to be written. Should be 256 | 512 | 1024 | 4096.
okano 0:ada7fb504504 174 * @return error code: CMD_SUCCESS | SRC_ADDR_ERROR (Address not a word boundary) | DST_ADDR_ERROR (Address not on correct boundary) | SRC_ADDR_NOT_MAPPED | DST_ADDR_NOT_MAPPED | COUNT_ERROR (Byte count is not 256 | 512 | 1024 | 4096) | SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION | BUSY
okano 0:ada7fb504504 175 */
okano 0:ada7fb504504 176
okano 0:ada7fb504504 177 int IAP::write( char *source_addr, char *target_addr, int size ) {
okano 0:ada7fb504504 178 IAP_command[ 0 ] = IAPCommand_Copy_RAM_to_Flash;
okano 0:ada7fb504504 179 IAP_command[ 1 ] = (unsigned int)target_addr; // Destination flash address where data bytes are to be written. This address should be a 256 byte boundary.
okano 0:ada7fb504504 180 IAP_command[ 2 ] = (unsigned int)source_addr; // Source RAM address from which data bytes are to be read. This address should be a word boundary.
okano 0:ada7fb504504 181 IAP_command[ 3 ] = size; // Number of bytes to be written. Should be 256 | 512 | 1024 | 4096.
okano 0:ada7fb504504 182 IAP_command[ 4 ] = cclk_kHz; // CPU Clock Frequency (CCLK) in kHz.
okano 0:ada7fb504504 183
okano 0:ada7fb504504 184 iap_entry( IAP_command, IAP_result );
okano 0:ada7fb504504 185
okano 0:ada7fb504504 186 return ( (int)IAP_result[ 0 ] );
okano 0:ada7fb504504 187 }
okano 0:ada7fb504504 188
okano 0:ada7fb504504 189
okano 0:ada7fb504504 190 /** Compare <address1> <address2> <no of bytes>
okano 0:ada7fb504504 191 *
okano 0:ada7fb504504 192 * @param source_addr Starting flash or RAM address of data bytes to be compared. This address should be a word boundary.
okano 0:ada7fb504504 193 * @param target_addr Starting flash or RAM address of data bytes to be compared. This address should be a word boundary.
okano 0:ada7fb504504 194 * @param size Number of bytes to be compared; should be a multiple of 4.
okano 0:ada7fb504504 195 * @return error code: CMD_SUCCESS | COMPARE_ERROR | COUNT_ERROR (Byte count is not a multiple of 4) | ADDR_ERROR | ADDR_NOT_MAPPED
okano 0:ada7fb504504 196 */
okano 0:ada7fb504504 197
okano 0:ada7fb504504 198 int IAP::compare( char *source_addr, char *target_addr, int size ) {
okano 0:ada7fb504504 199 IAP_command[ 0 ] = IAPCommand_Compare;
okano 0:ada7fb504504 200 IAP_command[ 1 ] = (unsigned int)target_addr; // Starting flash or RAM address of data bytes to be compared. This address should be a word boundary.
okano 0:ada7fb504504 201 IAP_command[ 2 ] = (unsigned int)source_addr; // Starting flash or RAM address of data bytes to be compared. This address should be a word boundary.
okano 0:ada7fb504504 202 IAP_command[ 3 ] = size; // Number of bytes to be compared; should be a multiple of 4.
okano 0:ada7fb504504 203
okano 0:ada7fb504504 204 iap_entry( IAP_command, IAP_result );
okano 0:ada7fb504504 205
okano 0:ada7fb504504 206 return ( (int)IAP_result[ 0 ] );
okano 0:ada7fb504504 207 }
okano 0:ada7fb504504 208
okano 0:ada7fb504504 209 /** Compare <address1> <address2> <no of bytes>
okano 0:ada7fb504504 210 *
okano 0:ada7fb504504 211 * @param source_addr Starting flash or RAM address of data bytes to be compared. This address should be a word boundary.
okano 0:ada7fb504504 212 * @param target_addr Starting flash or RAM address of data bytes to be compared. This address should be a word boundary.
okano 0:ada7fb504504 213 * @param size Number of bytes to be compared; should be a multiple of 4.
okano 0:ada7fb504504 214 * @return error code: CMD_SUCCESS | COMPARE_ERROR | COUNT_ERROR (Byte count is not a multiple of 4) | ADDR_ERROR | ADDR_NOT_MAPPED
okano 0:ada7fb504504 215 */
okano 0:ada7fb504504 216
okano 0:ada7fb504504 217 int IAP::read_BootVer(void) {
okano 0:ada7fb504504 218 IAP_command[0] = IAPCommand_Read_Boot_Code_version;
okano 0:ada7fb504504 219 IAP_result[1] = 0; // not sure if in high or low bits.
okano 0:ada7fb504504 220 iap_entry(IAP_command, IAP_result);
okano 0:ada7fb504504 221 return ((int)IAP_result[1]);
okano 0:ada7fb504504 222 }
okano 0:ada7fb504504 223
okano 0:ada7fb504504 224 /** Get user reserved flash start address
okano 0:ada7fb504504 225 *
okano 0:ada7fb504504 226 * @return start address of user reserved flash memory
okano 0:ada7fb504504 227 * @see reserved_flash_area_size()
okano 0:ada7fb504504 228 */
okano 0:ada7fb504504 229
okano 0:ada7fb504504 230 char * IAP::reserved_flash_area_start( void )
okano 0:ada7fb504504 231 {
okano 0:ada7fb504504 232 return ( (char *)USER_FLASH_AREA_START );
okano 0:ada7fb504504 233 }
okano 0:ada7fb504504 234
okano 0:ada7fb504504 235
okano 0:ada7fb504504 236 /** Get user reserved flash size
okano 0:ada7fb504504 237 *
okano 0:ada7fb504504 238 * @return size of user reserved flash memory
okano 0:ada7fb504504 239 * @see reserved_flash_area_start()
okano 0:ada7fb504504 240 */
okano 0:ada7fb504504 241
okano 0:ada7fb504504 242 int IAP::reserved_flash_area_size( void )
okano 0:ada7fb504504 243 {
okano 0:ada7fb504504 244 return ( USER_FLASH_AREA_SIZE );
okano 0:ada7fb504504 245 }
okano 0:ada7fb504504 246
okano 1:ff906ad52cf9 247 #if defined(TARGET_LPC11U24)
okano 1:ff906ad52cf9 248 /** Copy RAM to EEPROM (LPC11U24)
okano 1:ff906ad52cf9 249 *
okano 1:ff906ad52cf9 250 * @param source_addr Source RAM address from which data bytes are to be read.
okano 1:ff906ad52cf9 251 * @param target_addr Destination EEPROM address where data bytes are to be written.
okano 1:ff906ad52cf9 252 * @param size Number of bytes to be written.
okano 1:ff906ad52cf9 253 * @return error code: CMD_SUCCESS | SRC_ADDR_NOT_MAPPED | DST_ADDR_NOT_MAPPED
okano 1:ff906ad52cf9 254 * Remark: The top 64 bytes of the EEPROM memory are reserved and cannot be written to.
okano 1:ff906ad52cf9 255 */
okano 1:ff906ad52cf9 256 int IAP::write_eeprom( char *source_addr, char *target_addr, int size ) {
okano 1:ff906ad52cf9 257 IAP_command[ 0 ] = IAPCommand_EEPROM_Write;
okano 1:ff906ad52cf9 258 IAP_command[ 1 ] = (unsigned int)target_addr; // Destination EEPROM address where data bytes are to be written. This address should be a 256 byte boundary.
okano 1:ff906ad52cf9 259 IAP_command[ 2 ] = (unsigned int)source_addr; // Source RAM address from which data bytes are to be read. This address should be a word boundary.
okano 1:ff906ad52cf9 260 IAP_command[ 3 ] = size; // Number of bytes to be written. Should be 256 | 512 | 1024 | 4096.
okano 1:ff906ad52cf9 261 IAP_command[ 4 ] = cclk_kHz; // CPU Clock Frequency (CCLK) in kHz.
okano 1:ff906ad52cf9 262
okano 1:ff906ad52cf9 263 iap_entry( IAP_command, IAP_result );
okano 1:ff906ad52cf9 264
okano 1:ff906ad52cf9 265 return ( (int)IAP_result[ 0 ] );
okano 1:ff906ad52cf9 266 }
okano 1:ff906ad52cf9 267
okano 1:ff906ad52cf9 268 /** Copy EEPROM to RAM (LPC11U24)
okano 1:ff906ad52cf9 269 *
okano 1:ff906ad52cf9 270 * @param source_addr Source EEPROM address from which data bytes are to be read.
okano 1:ff906ad52cf9 271 * @param target_addr Destination RAM address where data bytes are to be written.
okano 1:ff906ad52cf9 272 * @param size Number of bytes to be written.
okano 1:ff906ad52cf9 273 * @return error code: CMD_SUCCESS | SRC_ADDR_NOT_MAPPED | DST_ADDR_NOT_MAPPED
okano 1:ff906ad52cf9 274 * Remark: The top 64 bytes of the EEPROM memory are reserved and cannot be written to.
okano 1:ff906ad52cf9 275 */
okano 1:ff906ad52cf9 276 int IAP::read_eeprom( char *source_addr, char *target_addr, int size ) {
okano 1:ff906ad52cf9 277 IAP_command[ 0 ] = IAPCommand_EEPROM_Read;
okano 1:ff906ad52cf9 278 IAP_command[ 1 ] = (unsigned int)source_addr; // Source EEPROM address from which data bytes are to be read. This address should be a word boundary.
okano 1:ff906ad52cf9 279 IAP_command[ 2 ] = (unsigned int)target_addr; // Destination RAM address where data bytes are to be written. This address should be a 256 byte boundary.
okano 1:ff906ad52cf9 280 IAP_command[ 3 ] = size; // Number of bytes to be written. Should be 256 | 512 | 1024 | 4096.
okano 1:ff906ad52cf9 281 IAP_command[ 4 ] = cclk_kHz; // CPU Clock Frequency (CCLK) in kHz.
okano 1:ff906ad52cf9 282
okano 1:ff906ad52cf9 283 iap_entry( IAP_command, IAP_result );
okano 1:ff906ad52cf9 284
okano 1:ff906ad52cf9 285 return ( (int)IAP_result[ 0 ] );
okano 1:ff906ad52cf9 286 }
okano 1:ff906ad52cf9 287 #endif