RAS

Fork of IAP by Tedd OKANO

Committer:
pascalreygner
Date:
Fri Aug 24 16:38:19 2018 +0000
Revision:
11:69e39050fccf
Parent:
10:59f7e32ae397
Child:
12:91ac1391a13b
essai

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 2:17f3464672c1 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 2:17f3464672c1 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 2:17f3464672c1 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 4:cee1a2a734c9 25 * revision 3.0 09-Jan-2015 LPC812 and LPC824 support added
okano 4:cee1a2a734c9 26 * revision 3.1 13-Jan-2015 LPC1114 support added
okano 4:cee1a2a734c9 27 * revision 3.1.1 16-Jan-2015 Target MCU name changed for better compatibility across the platforms
okano 8:1d79b2bb1131 28 * revision 3.1.2 10-Mar-2015 merged with pull requests. reinvoke_isp() added and modified read_serial() to return a pointer.
okano 8:1d79b2bb1131 29 * revision 3.1.3 16-Aug-2018 "write_page" function added for LPC81X/LPC82X
okano 0:ada7fb504504 30 */
okano 0:ada7fb504504 31
okano 0:ada7fb504504 32 #include "mbed.h"
okano 0:ada7fb504504 33 #include "IAP.h"
okano 0:ada7fb504504 34
okano 0:ada7fb504504 35 #define USER_FLASH_AREA_START_STR( x ) STR( x )
okano 0:ada7fb504504 36 #define STR( x ) #x
pascalreygner 11:69e39050fccf 37 #define MEM_SIZE 256
okano 0:ada7fb504504 38
okano 0:ada7fb504504 39 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 40
okano 0:ada7fb504504 41 /*
okano 0:ada7fb504504 42 * Reserve of flash area is explained by Igor. Please refer next URL
okano 0:ada7fb504504 43 * http://mbed.org/users/okano/notebook/iap-in-application-programming-internal-flash-eras/?page=1#comment-271
okano 0:ada7fb504504 44 */
okano 2:17f3464672c1 45
okano 0:ada7fb504504 46 //unsigned char user_area[ size ] __attribute__((section(".ARM.__at_0x78000"), zero_init));
okano 0:ada7fb504504 47
okano 0:ada7fb504504 48 /*
okano 0:ada7fb504504 49 * IAP command codes
okano 0:ada7fb504504 50 * Table 589. "IAP Command Summary", Chapter 8. "IAP commands", usermanual
okano 0:ada7fb504504 51 */
okano 0:ada7fb504504 52
okano 2:17f3464672c1 53 enum command_code {
okano 2:17f3464672c1 54 IAPCommand_Prepare_sector_for_write_operation = 50,
okano 2:17f3464672c1 55 IAPCommand_Copy_RAM_to_Flash,
okano 2:17f3464672c1 56 IAPCommand_Erase_sector,
okano 2:17f3464672c1 57 IAPCommand_Blank_check_sector,
okano 2:17f3464672c1 58 IAPCommand_Read_part_ID,
okano 2:17f3464672c1 59 IAPCommand_Read_Boot_Code_version,
okano 2:17f3464672c1 60 IAPCommand_Compare,
okano 2:17f3464672c1 61 IAPCommand_Reinvoke_ISP,
okano 2:17f3464672c1 62 IAPCommand_Read_device_serial_number,
okano 4:cee1a2a734c9 63 #if defined(TARGET_LPC11UXX)
okano 2:17f3464672c1 64 IAPCommand_EEPROM_Write = 61,
okano 2:17f3464672c1 65 IAPCommand_EEPROM_Read,
okano 4:cee1a2a734c9 66 #elif defined(TARGET_LPC81X) || defined(TARGET_LPC82X)
okano 2:17f3464672c1 67 IAPCommand_Erase_page = 59,
okano 1:ff906ad52cf9 68 #endif
okano 2:17f3464672c1 69 };
okano 0:ada7fb504504 70
jaerts 5:7484398d50ea 71 int IAP::reinvoke_isp( void ) {
jaerts 5:7484398d50ea 72 __disable_irq();
jaerts 5:7484398d50ea 73
jaerts 5:7484398d50ea 74 IAP_command[ 0 ] = IAPCommand_Reinvoke_ISP;
jaerts 5:7484398d50ea 75
jaerts 5:7484398d50ea 76 iap_entry( IAP_command, IAP_result );
jaerts 5:7484398d50ea 77
jaerts 5:7484398d50ea 78 return ( (int)IAP_result[ 0 ] );
jaerts 5:7484398d50ea 79 }
jaerts 5:7484398d50ea 80
okano 0:ada7fb504504 81 /** Read part identification number
okano 0:ada7fb504504 82 *
okano 0:ada7fb504504 83 * @return device ID
okano 0:ada7fb504504 84 * @see read_serial()
okano 0:ada7fb504504 85 */
okano 2:17f3464672c1 86 int IAP::read_ID( void )
okano 2:17f3464672c1 87 {
okano 2:17f3464672c1 88 IAP_command[ 0 ] = IAPCommand_Read_part_ID;
okano 0:ada7fb504504 89
okano 0:ada7fb504504 90 iap_entry( IAP_command, IAP_result );
okano 2:17f3464672c1 91
okano 0:ada7fb504504 92 // return ( (int)IAP_result[ 0 ] );
okano 0:ada7fb504504 93 return ( (int)IAP_result[ 1 ] ); // to return the number itself (this command always returns CMD_SUCCESS)
okano 0:ada7fb504504 94 }
okano 0:ada7fb504504 95
sam_grove 6:f794a51897b8 96 int *IAP::read_serial( void ) {
okano 2:17f3464672c1 97 IAP_command[ 0 ] = IAPCommand_Read_device_serial_number;
okano 0:ada7fb504504 98
okano 2:17f3464672c1 99 iap_entry( IAP_command, IAP_result );
okano 0:ada7fb504504 100
okano 0:ada7fb504504 101 // return ( (int)IAP_result[ 0 ] );
sam_grove 6:f794a51897b8 102 return ( (int *)&IAP_result[ 1 ] ); // to return the number itself (this command always returns CMD_SUCCESS)
okano 0:ada7fb504504 103 }
okano 0:ada7fb504504 104
okano 2:17f3464672c1 105 int IAP::blank_check( int start, int end )
okano 2:17f3464672c1 106 {
okano 0:ada7fb504504 107 IAP_command[ 0 ] = IAPCommand_Blank_check_sector;
okano 0:ada7fb504504 108 IAP_command[ 1 ] = (unsigned int)start; // Start Sector Number
okano 0:ada7fb504504 109 IAP_command[ 2 ] = (unsigned int)end; // End Sector Number (should be greater than or equal to start sector number)
okano 0:ada7fb504504 110
okano 0:ada7fb504504 111 iap_entry( IAP_command, IAP_result );
okano 0:ada7fb504504 112
okano 0:ada7fb504504 113 return ( (int)IAP_result[ 0 ] );
okano 0:ada7fb504504 114 }
okano 0:ada7fb504504 115
okano 2:17f3464672c1 116 int IAP::erase( int start, int end )
okano 2:17f3464672c1 117 {
okano 0:ada7fb504504 118 IAP_command[ 0 ] = IAPCommand_Erase_sector;
okano 0:ada7fb504504 119 IAP_command[ 1 ] = (unsigned int)start; // Start Sector Number
okano 0:ada7fb504504 120 IAP_command[ 2 ] = (unsigned int)end; // End Sector Number (should be greater than or equal to start sector number)
okano 0:ada7fb504504 121 IAP_command[ 3 ] = cclk_kHz; // CPU Clock Frequency (CCLK) in kHz
okano 0:ada7fb504504 122
okano 0:ada7fb504504 123 iap_entry( IAP_command, IAP_result );
okano 0:ada7fb504504 124
okano 0:ada7fb504504 125 return ( (int)IAP_result[ 0 ] );
okano 0:ada7fb504504 126 }
okano 0:ada7fb504504 127
okano 2:17f3464672c1 128 int IAP::prepare( int start, int end )
okano 2:17f3464672c1 129 {
okano 0:ada7fb504504 130 IAP_command[ 0 ] = IAPCommand_Prepare_sector_for_write_operation;
okano 0:ada7fb504504 131 IAP_command[ 1 ] = (unsigned int)start; // Start Sector Number
okano 0:ada7fb504504 132 IAP_command[ 2 ] = (unsigned int)end; // End Sector Number (should be greater than or equal to start sector number).
okano 2:17f3464672c1 133
okano 0:ada7fb504504 134 iap_entry( IAP_command, IAP_result );
okano 2:17f3464672c1 135
okano 0:ada7fb504504 136 return ( (int)IAP_result[ 0 ] );
okano 0:ada7fb504504 137 }
okano 0:ada7fb504504 138
okano 2:17f3464672c1 139 int IAP::write( char *source_addr, char *target_addr, int size )
okano 2:17f3464672c1 140 {
okano 0:ada7fb504504 141 IAP_command[ 0 ] = IAPCommand_Copy_RAM_to_Flash;
okano 0:ada7fb504504 142 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 143 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 144 IAP_command[ 3 ] = size; // Number of bytes to be written. Should be 256 | 512 | 1024 | 4096.
okano 0:ada7fb504504 145 IAP_command[ 4 ] = cclk_kHz; // CPU Clock Frequency (CCLK) in kHz.
okano 0:ada7fb504504 146
okano 0:ada7fb504504 147 iap_entry( IAP_command, IAP_result );
okano 0:ada7fb504504 148
okano 0:ada7fb504504 149 return ( (int)IAP_result[ 0 ] );
okano 0:ada7fb504504 150 }
okano 0:ada7fb504504 151
okano 2:17f3464672c1 152 int IAP::compare( char *source_addr, char *target_addr, int size )
okano 2:17f3464672c1 153 {
okano 0:ada7fb504504 154 IAP_command[ 0 ] = IAPCommand_Compare;
okano 0:ada7fb504504 155 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 156 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 157 IAP_command[ 3 ] = size; // Number of bytes to be compared; should be a multiple of 4.
okano 0:ada7fb504504 158
okano 0:ada7fb504504 159 iap_entry( IAP_command, IAP_result );
okano 0:ada7fb504504 160
okano 0:ada7fb504504 161 return ( (int)IAP_result[ 0 ] );
okano 0:ada7fb504504 162 }
okano 0:ada7fb504504 163
okano 2:17f3464672c1 164 int IAP::read_BootVer(void)
okano 2:17f3464672c1 165 {
okano 0:ada7fb504504 166 IAP_command[0] = IAPCommand_Read_Boot_Code_version;
okano 0:ada7fb504504 167 IAP_result[1] = 0; // not sure if in high or low bits.
okano 0:ada7fb504504 168 iap_entry(IAP_command, IAP_result);
okano 0:ada7fb504504 169 return ((int)IAP_result[1]);
okano 0:ada7fb504504 170 }
okano 0:ada7fb504504 171
okano 0:ada7fb504504 172 char * IAP::reserved_flash_area_start( void )
okano 0:ada7fb504504 173 {
okano 0:ada7fb504504 174 return ( (char *)USER_FLASH_AREA_START );
okano 0:ada7fb504504 175 }
okano 0:ada7fb504504 176
okano 0:ada7fb504504 177 int IAP::reserved_flash_area_size( void )
okano 0:ada7fb504504 178 {
okano 0:ada7fb504504 179 return ( USER_FLASH_AREA_SIZE );
okano 0:ada7fb504504 180 }
okano 0:ada7fb504504 181
pascalreygner 11:69e39050fccf 182 // ************ Ajout PR 22/8/2018 ***********************************
pascalreygner 11:69e39050fccf 183 void IAP::eraseFlashSector(int numSecteur)
pascalreygner 11:69e39050fccf 184 {
pascalreygner 11:69e39050fccf 185 prepare( numSecteur, numSecteur );
pascalreygner 11:69e39050fccf 186 erase( numSecteur, numSecteur );
pascalreygner 11:69e39050fccf 187 }
pascalreygner 11:69e39050fccf 188
pascalreygner 11:69e39050fccf 189 int IAP::writeFlashAd(char *data,int numSecteur,int numBlock)
pascalreygner 11:69e39050fccf 190 {
pascalreygner 11:69e39050fccf 191 prepare(numSecteur, numSecteur );
pascalreygner 11:69e39050fccf 192 int r = write( data, sector_start_adress[ numSecteur]+MEM_SIZE*numBlock, MEM_SIZE );
pascalreygner 11:69e39050fccf 193 return(r);
pascalreygner 11:69e39050fccf 194 }
pascalreygner 11:69e39050fccf 195
pascalreygner 11:69e39050fccf 196 void IAP::readFlashAd(char *data,int numSecteur,int numBlock)
pascalreygner 11:69e39050fccf 197 {
pascalreygner 11:69e39050fccf 198 memcpy( data, sector_start_adress[ numSecteur]+MEM_SIZE*numBlock, MEM_SIZE );
pascalreygner 11:69e39050fccf 199 }
pascalreygner 11:69e39050fccf 200 #define FLASH_NBBLOCK 128 // nb blocks dans un secteur
pascalreygner 11:69e39050fccf 201
pascalreygner 11:69e39050fccf 202 void IAP::copyFlashSector(int numSecteurSrc,int numSecteurDest)
pascalreygner 11:69e39050fccf 203 {
pascalreygner 11:69e39050fccf 204 char data[MEM_SIZE];
pascalreygner 11:69e39050fccf 205 eraseFlashSector(numSecteurDest);
pascalreygner 11:69e39050fccf 206 for (int numBlock =0; numBlock<FLASH_NBBLOCK; numBlock++) {
pascalreygner 11:69e39050fccf 207 readFlashAd(data, numSecteurSrc,numBlock);
pascalreygner 11:69e39050fccf 208 writeFlashAd(data, numSecteurDest,numBlock);
pascalreygner 11:69e39050fccf 209 }
pascalreygner 11:69e39050fccf 210 }
pascalreygner 11:69e39050fccf 211 // ************ Fin Ajout PR 22/8/2018 ***********************************
pascalreygner 11:69e39050fccf 212
okano 4:cee1a2a734c9 213 #if defined(TARGET_LPC11UXX)
okano 2:17f3464672c1 214
okano 2:17f3464672c1 215 int IAP::write_eeprom( char *source_addr, char *target_addr, int size )
okano 2:17f3464672c1 216 {
okano 1:ff906ad52cf9 217 IAP_command[ 0 ] = IAPCommand_EEPROM_Write;
okano 1:ff906ad52cf9 218 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 219 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 220 IAP_command[ 3 ] = size; // Number of bytes to be written. Should be 256 | 512 | 1024 | 4096.
okano 1:ff906ad52cf9 221 IAP_command[ 4 ] = cclk_kHz; // CPU Clock Frequency (CCLK) in kHz.
okano 2:17f3464672c1 222
okano 1:ff906ad52cf9 223 iap_entry( IAP_command, IAP_result );
okano 2:17f3464672c1 224
okano 1:ff906ad52cf9 225 return ( (int)IAP_result[ 0 ] );
okano 1:ff906ad52cf9 226 }
okano 2:17f3464672c1 227
okano 2:17f3464672c1 228 int IAP::read_eeprom( char *source_addr, char *target_addr, int size )
okano 2:17f3464672c1 229 {
okano 1:ff906ad52cf9 230 IAP_command[ 0 ] = IAPCommand_EEPROM_Read;
okano 1:ff906ad52cf9 231 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 232 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 233 IAP_command[ 3 ] = size; // Number of bytes to be written. Should be 256 | 512 | 1024 | 4096.
okano 1:ff906ad52cf9 234 IAP_command[ 4 ] = cclk_kHz; // CPU Clock Frequency (CCLK) in kHz.
okano 2:17f3464672c1 235
okano 1:ff906ad52cf9 236 iap_entry( IAP_command, IAP_result );
okano 2:17f3464672c1 237
okano 1:ff906ad52cf9 238 return ( (int)IAP_result[ 0 ] );
okano 1:ff906ad52cf9 239 }
okano 2:17f3464672c1 240
okano 4:cee1a2a734c9 241 #elif defined(TARGET_LPC81X) || defined(TARGET_LPC82X)
okano 2:17f3464672c1 242
okano 2:17f3464672c1 243 int IAP::erase_page( int start, int end )
okano 2:17f3464672c1 244 {
okano 2:17f3464672c1 245 IAP_command[ 0 ] = IAPCommand_Erase_page;
okano 2:17f3464672c1 246 IAP_command[ 1 ] = (unsigned int)start; // Start Sector Number
okano 2:17f3464672c1 247 IAP_command[ 2 ] = (unsigned int)end; // End Sector Number (should be greater than or equal to start sector number)
okano 2:17f3464672c1 248 IAP_command[ 3 ] = cclk_kHz; // CPU Clock Frequency (CCLK) in kHz
okano 2:17f3464672c1 249
okano 2:17f3464672c1 250 iap_entry( IAP_command, IAP_result );
okano 2:17f3464672c1 251
okano 2:17f3464672c1 252 return ( (int)IAP_result[ 0 ] );
okano 2:17f3464672c1 253 }
okano 2:17f3464672c1 254
okano 10:59f7e32ae397 255 #pragma diag_suppress 1293 // suppressing warning of "assignment in condition"
okano 10:59f7e32ae397 256
okano 8:1d79b2bb1131 257 int IAP::write_page( char *source_addr, int target_page )
okano 8:1d79b2bb1131 258 {
okano 9:26095608ac1a 259 int r;
okano 9:26095608ac1a 260
okano 9:26095608ac1a 261 if ( r = prepare( target_page / (LPC8XX_SCTR_SIZE / LPC8XX_PAGE_SIZE), target_page / (LPC8XX_SCTR_SIZE / LPC8XX_PAGE_SIZE) ) )
okano 9:26095608ac1a 262 return ( r );
okano 9:26095608ac1a 263
okano 8:1d79b2bb1131 264 return ( write( source_addr, (char *)(target_page * LPC8XX_PAGE_SIZE), LPC8XX_PAGE_SIZE ) );
okano 8:1d79b2bb1131 265 }
okano 8:1d79b2bb1131 266
okano 1:ff906ad52cf9 267 #endif