IAP support library, used to provide non-volatile storage on the C027 board.

This small library provides IAP provides support for read/write to FLASh on the LPC1768 platform. The code here is taken from:

http://developer.mbed.org/users/okano/code/IAP/

All rights remain with Tedd OKANO, etc.

Committer:
RobMeades
Date:
Fri May 22 11:41:02 2015 +0000
Revision:
0:c258b7b02be5
Initial commit of IAP support (for non-volatile storate) to mbed cloud.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
RobMeades 0:c258b7b02be5 1 /** IAP provides support for read/write to FLASh on the LPC1768 platform. The code here is taken from:
RobMeades 0:c258b7b02be5 2 *
RobMeades 0:c258b7b02be5 3 * http://developer.mbed.org/users/okano/code/IAP/
RobMeades 0:c258b7b02be5 4 *
RobMeades 0:c258b7b02be5 5 * All rights remain with Tedd OKANO, etc.
RobMeades 0:c258b7b02be5 6 */
RobMeades 0:c258b7b02be5 7
RobMeades 0:c258b7b02be5 8 /** IAP : internal Flash memory access library
RobMeades 0:c258b7b02be5 9 *
RobMeades 0:c258b7b02be5 10 * The internal Flash memory access is described in the LPC1768 and LPC11U24 usermanual.
RobMeades 0:c258b7b02be5 11 * http://www.nxp.com/documents/user_manual/UM10360.pdf
RobMeades 0:c258b7b02be5 12 * http://www.nxp.com/documents/user_manual/UM10462.pdf
RobMeades 0:c258b7b02be5 13 *
RobMeades 0:c258b7b02be5 14 * LPC1768 --
RobMeades 0:c258b7b02be5 15 * Chapter 2: "LPC17xx Memory map"
RobMeades 0:c258b7b02be5 16 * Chapter 32: "LPC17xx Flash memory interface and programming"
RobMeades 0:c258b7b02be5 17 * refering Rev. 01 - 4 January 2010
RobMeades 0:c258b7b02be5 18 *
RobMeades 0:c258b7b02be5 19 * LPC11U24 --
RobMeades 0:c258b7b02be5 20 * Chapter 2: "LPC11Uxx Memory mapping"
RobMeades 0:c258b7b02be5 21 * Chapter 20: "LPC11Uxx Flash programming firmware"
RobMeades 0:c258b7b02be5 22 * refering Rev. 03 - 16 July 2012
RobMeades 0:c258b7b02be5 23 *
RobMeades 0:c258b7b02be5 24 * Released under the MIT License: http://mbed.org/license/mit
RobMeades 0:c258b7b02be5 25 *
RobMeades 0:c258b7b02be5 26 * revision 1.0 09-Mar-2010 1st release
RobMeades 0:c258b7b02be5 27 * revision 1.1 12-Mar-2010 chaged: to make possible to reserve flash area for user
RobMeades 0:c258b7b02be5 28 * it can be set by USER_FLASH_AREA_START and USER_FLASH_AREA_SIZE in IAP.h
RobMeades 0:c258b7b02be5 29 * revision 2.0 26-Nov-2012 LPC11U24 code added
RobMeades 0:c258b7b02be5 30 * revision 2.1 26-Nov-2012 EEPROM access code imported from Suga koubou san's (http://mbed.org/users/okini3939/) library
RobMeades 0:c258b7b02be5 31 * http://mbed.org/users/okini3939/code/M0_EEPROM_test/
RobMeades 0:c258b7b02be5 32 * revision 3.0 09-Jan-2015 LPC812 and LPC824 support added
RobMeades 0:c258b7b02be5 33 * revision 3.1 13-Jan-2015 LPC1114 support added
RobMeades 0:c258b7b02be5 34 * revision 3.1.1 16-Jan-2015 Target MCU name changed for better compatibility across the platforms
RobMeades 0:c258b7b02be5 35 */
RobMeades 0:c258b7b02be5 36
RobMeades 0:c258b7b02be5 37 #include "mbed.h"
RobMeades 0:c258b7b02be5 38 #include "IapApi.h"
RobMeades 0:c258b7b02be5 39
RobMeades 0:c258b7b02be5 40 #define USER_FLASH_AREA_START_STR( x ) STR( x )
RobMeades 0:c258b7b02be5 41 #define STR( x ) #x
RobMeades 0:c258b7b02be5 42
RobMeades 0:c258b7b02be5 43 /*
RobMeades 0:c258b7b02be5 44 * Reserve of flash area is explained by Igor. Please refer next URL
RobMeades 0:c258b7b02be5 45 * http://mbed.org/users/okano/notebook/iap-in-application-programming-internal-flash-eras/?page=1#comment-271
RobMeades 0:c258b7b02be5 46 */
RobMeades 0:c258b7b02be5 47
RobMeades 0:c258b7b02be5 48 //unsigned char user_area[ size ] __attribute__((section(".ARM.__at_0x78000"), zero_init));
RobMeades 0:c258b7b02be5 49
RobMeades 0:c258b7b02be5 50 /*
RobMeades 0:c258b7b02be5 51 * IAP command codes
RobMeades 0:c258b7b02be5 52 * Table 589. "IAP Command Summary", Chapter 8. "IAP commands", usermanual
RobMeades 0:c258b7b02be5 53 */
RobMeades 0:c258b7b02be5 54
RobMeades 0:c258b7b02be5 55 enum command_code {
RobMeades 0:c258b7b02be5 56 IAPCommand_Prepare_sector_for_write_operation = 50,
RobMeades 0:c258b7b02be5 57 IAPCommand_Copy_RAM_to_Flash,
RobMeades 0:c258b7b02be5 58 IAPCommand_Erase_sector,
RobMeades 0:c258b7b02be5 59 IAPCommand_Blank_check_sector,
RobMeades 0:c258b7b02be5 60 IAPCommand_Read_part_ID,
RobMeades 0:c258b7b02be5 61 IAPCommand_Read_Boot_Code_version,
RobMeades 0:c258b7b02be5 62 IAPCommand_Compare,
RobMeades 0:c258b7b02be5 63 IAPCommand_Reinvoke_ISP,
RobMeades 0:c258b7b02be5 64 IAPCommand_Read_device_serial_number,
RobMeades 0:c258b7b02be5 65 #if defined(TARGET_LPC11UXX)
RobMeades 0:c258b7b02be5 66 IAPCommand_EEPROM_Write = 61,
RobMeades 0:c258b7b02be5 67 IAPCommand_EEPROM_Read,
RobMeades 0:c258b7b02be5 68 #elif defined(TARGET_LPC81X) || defined(TARGET_LPC82X)
RobMeades 0:c258b7b02be5 69 IAPCommand_Erase_page = 59,
RobMeades 0:c258b7b02be5 70 #endif
RobMeades 0:c258b7b02be5 71 };
RobMeades 0:c258b7b02be5 72
RobMeades 0:c258b7b02be5 73 int IAP::read_ID( void )
RobMeades 0:c258b7b02be5 74 {
RobMeades 0:c258b7b02be5 75 IAP_command[ 0 ] = IAPCommand_Read_part_ID;
RobMeades 0:c258b7b02be5 76
RobMeades 0:c258b7b02be5 77 iap_entry( IAP_command, IAP_result );
RobMeades 0:c258b7b02be5 78
RobMeades 0:c258b7b02be5 79 // return ( (int)IAP_result[ 0 ] );
RobMeades 0:c258b7b02be5 80 return ( (int)IAP_result[ 1 ] ); // to return the number itself (this command always returns CMD_SUCCESS)
RobMeades 0:c258b7b02be5 81 }
RobMeades 0:c258b7b02be5 82
RobMeades 0:c258b7b02be5 83 int IAP::read_serial( void )
RobMeades 0:c258b7b02be5 84 {
RobMeades 0:c258b7b02be5 85 IAP_command[ 0 ] = IAPCommand_Read_device_serial_number;
RobMeades 0:c258b7b02be5 86
RobMeades 0:c258b7b02be5 87 iap_entry( IAP_command, IAP_result );
RobMeades 0:c258b7b02be5 88
RobMeades 0:c258b7b02be5 89 // return ( (int)IAP_result[ 0 ] );
RobMeades 0:c258b7b02be5 90 return ( (int)IAP_result[ 1 ] ); // to return the number itself (this command always returns CMD_SUCCESS)
RobMeades 0:c258b7b02be5 91 }
RobMeades 0:c258b7b02be5 92
RobMeades 0:c258b7b02be5 93 int IAP::blank_check( int start, int end )
RobMeades 0:c258b7b02be5 94 {
RobMeades 0:c258b7b02be5 95 IAP_command[ 0 ] = IAPCommand_Blank_check_sector;
RobMeades 0:c258b7b02be5 96 IAP_command[ 1 ] = (unsigned int)start; // Start Sector Number
RobMeades 0:c258b7b02be5 97 IAP_command[ 2 ] = (unsigned int)end; // End Sector Number (should be greater than or equal to start sector number)
RobMeades 0:c258b7b02be5 98
RobMeades 0:c258b7b02be5 99 iap_entry( IAP_command, IAP_result );
RobMeades 0:c258b7b02be5 100
RobMeades 0:c258b7b02be5 101 return ( (int)IAP_result[ 0 ] );
RobMeades 0:c258b7b02be5 102 }
RobMeades 0:c258b7b02be5 103
RobMeades 0:c258b7b02be5 104 int IAP::erase( int start, int end )
RobMeades 0:c258b7b02be5 105 {
RobMeades 0:c258b7b02be5 106 IAP_command[ 0 ] = IAPCommand_Erase_sector;
RobMeades 0:c258b7b02be5 107 IAP_command[ 1 ] = (unsigned int)start; // Start Sector Number
RobMeades 0:c258b7b02be5 108 IAP_command[ 2 ] = (unsigned int)end; // End Sector Number (should be greater than or equal to start sector number)
RobMeades 0:c258b7b02be5 109 IAP_command[ 3 ] = cclk_kHz; // CPU Clock Frequency (CCLK) in kHz
RobMeades 0:c258b7b02be5 110
RobMeades 0:c258b7b02be5 111 iap_entry( IAP_command, IAP_result );
RobMeades 0:c258b7b02be5 112
RobMeades 0:c258b7b02be5 113 return ( (int)IAP_result[ 0 ] );
RobMeades 0:c258b7b02be5 114 }
RobMeades 0:c258b7b02be5 115
RobMeades 0:c258b7b02be5 116 int IAP::prepare( int start, int end )
RobMeades 0:c258b7b02be5 117 {
RobMeades 0:c258b7b02be5 118 IAP_command[ 0 ] = IAPCommand_Prepare_sector_for_write_operation;
RobMeades 0:c258b7b02be5 119 IAP_command[ 1 ] = (unsigned int)start; // Start Sector Number
RobMeades 0:c258b7b02be5 120 IAP_command[ 2 ] = (unsigned int)end; // End Sector Number (should be greater than or equal to start sector number).
RobMeades 0:c258b7b02be5 121
RobMeades 0:c258b7b02be5 122 iap_entry( IAP_command, IAP_result );
RobMeades 0:c258b7b02be5 123
RobMeades 0:c258b7b02be5 124 return ( (int)IAP_result[ 0 ] );
RobMeades 0:c258b7b02be5 125 }
RobMeades 0:c258b7b02be5 126
RobMeades 0:c258b7b02be5 127 int IAP::write( char *source_addr, char *target_addr, int size )
RobMeades 0:c258b7b02be5 128 {
RobMeades 0:c258b7b02be5 129 IAP_command[ 0 ] = IAPCommand_Copy_RAM_to_Flash;
RobMeades 0:c258b7b02be5 130 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.
RobMeades 0:c258b7b02be5 131 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.
RobMeades 0:c258b7b02be5 132 IAP_command[ 3 ] = size; // Number of bytes to be written. Should be 256 | 512 | 1024 | 4096.
RobMeades 0:c258b7b02be5 133 IAP_command[ 4 ] = cclk_kHz; // CPU Clock Frequency (CCLK) in kHz.
RobMeades 0:c258b7b02be5 134
RobMeades 0:c258b7b02be5 135 iap_entry( IAP_command, IAP_result );
RobMeades 0:c258b7b02be5 136
RobMeades 0:c258b7b02be5 137 return ( (int)IAP_result[ 0 ] );
RobMeades 0:c258b7b02be5 138 }
RobMeades 0:c258b7b02be5 139
RobMeades 0:c258b7b02be5 140 int IAP::compare( char *source_addr, char *target_addr, int size )
RobMeades 0:c258b7b02be5 141 {
RobMeades 0:c258b7b02be5 142 IAP_command[ 0 ] = IAPCommand_Compare;
RobMeades 0:c258b7b02be5 143 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.
RobMeades 0:c258b7b02be5 144 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.
RobMeades 0:c258b7b02be5 145 IAP_command[ 3 ] = size; // Number of bytes to be compared; should be a multiple of 4.
RobMeades 0:c258b7b02be5 146
RobMeades 0:c258b7b02be5 147 iap_entry( IAP_command, IAP_result );
RobMeades 0:c258b7b02be5 148
RobMeades 0:c258b7b02be5 149 return ( (int)IAP_result[ 0 ] );
RobMeades 0:c258b7b02be5 150 }
RobMeades 0:c258b7b02be5 151
RobMeades 0:c258b7b02be5 152 int IAP::read_BootVer(void)
RobMeades 0:c258b7b02be5 153 {
RobMeades 0:c258b7b02be5 154 IAP_command[0] = IAPCommand_Read_Boot_Code_version;
RobMeades 0:c258b7b02be5 155 IAP_result[1] = 0; // not sure if in high or low bits.
RobMeades 0:c258b7b02be5 156 iap_entry(IAP_command, IAP_result);
RobMeades 0:c258b7b02be5 157 return ((int)IAP_result[1]);
RobMeades 0:c258b7b02be5 158 }
RobMeades 0:c258b7b02be5 159
RobMeades 0:c258b7b02be5 160 char * IAP::reserved_flash_area_start( void )
RobMeades 0:c258b7b02be5 161 {
RobMeades 0:c258b7b02be5 162 return ( (char *)USER_FLASH_AREA_START );
RobMeades 0:c258b7b02be5 163 }
RobMeades 0:c258b7b02be5 164
RobMeades 0:c258b7b02be5 165 int IAP::reserved_flash_area_size( void )
RobMeades 0:c258b7b02be5 166 {
RobMeades 0:c258b7b02be5 167 return ( USER_FLASH_AREA_SIZE );
RobMeades 0:c258b7b02be5 168 }
RobMeades 0:c258b7b02be5 169
RobMeades 0:c258b7b02be5 170 #if defined(TARGET_LPC11UXX)
RobMeades 0:c258b7b02be5 171
RobMeades 0:c258b7b02be5 172 int IAP::write_eeprom( char *source_addr, char *target_addr, int size )
RobMeades 0:c258b7b02be5 173 {
RobMeades 0:c258b7b02be5 174 IAP_command[ 0 ] = IAPCommand_EEPROM_Write;
RobMeades 0:c258b7b02be5 175 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.
RobMeades 0:c258b7b02be5 176 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.
RobMeades 0:c258b7b02be5 177 IAP_command[ 3 ] = size; // Number of bytes to be written. Should be 256 | 512 | 1024 | 4096.
RobMeades 0:c258b7b02be5 178 IAP_command[ 4 ] = cclk_kHz; // CPU Clock Frequency (CCLK) in kHz.
RobMeades 0:c258b7b02be5 179
RobMeades 0:c258b7b02be5 180 iap_entry( IAP_command, IAP_result );
RobMeades 0:c258b7b02be5 181
RobMeades 0:c258b7b02be5 182 return ( (int)IAP_result[ 0 ] );
RobMeades 0:c258b7b02be5 183 }
RobMeades 0:c258b7b02be5 184
RobMeades 0:c258b7b02be5 185 int IAP::read_eeprom( char *source_addr, char *target_addr, int size )
RobMeades 0:c258b7b02be5 186 {
RobMeades 0:c258b7b02be5 187 IAP_command[ 0 ] = IAPCommand_EEPROM_Read;
RobMeades 0:c258b7b02be5 188 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.
RobMeades 0:c258b7b02be5 189 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.
RobMeades 0:c258b7b02be5 190 IAP_command[ 3 ] = size; // Number of bytes to be written. Should be 256 | 512 | 1024 | 4096.
RobMeades 0:c258b7b02be5 191 IAP_command[ 4 ] = cclk_kHz; // CPU Clock Frequency (CCLK) in kHz.
RobMeades 0:c258b7b02be5 192
RobMeades 0:c258b7b02be5 193 iap_entry( IAP_command, IAP_result );
RobMeades 0:c258b7b02be5 194
RobMeades 0:c258b7b02be5 195 return ( (int)IAP_result[ 0 ] );
RobMeades 0:c258b7b02be5 196 }
RobMeades 0:c258b7b02be5 197
RobMeades 0:c258b7b02be5 198 #elif defined(TARGET_LPC81X) || defined(TARGET_LPC82X)
RobMeades 0:c258b7b02be5 199
RobMeades 0:c258b7b02be5 200 int IAP::erase_page( int start, int end )
RobMeades 0:c258b7b02be5 201 {
RobMeades 0:c258b7b02be5 202 IAP_command[ 0 ] = IAPCommand_Erase_page;
RobMeades 0:c258b7b02be5 203 IAP_command[ 1 ] = (unsigned int)start; // Start Sector Number
RobMeades 0:c258b7b02be5 204 IAP_command[ 2 ] = (unsigned int)end; // End Sector Number (should be greater than or equal to start sector number)
RobMeades 0:c258b7b02be5 205 IAP_command[ 3 ] = cclk_kHz; // CPU Clock Frequency (CCLK) in kHz
RobMeades 0:c258b7b02be5 206
RobMeades 0:c258b7b02be5 207 iap_entry( IAP_command, IAP_result );
RobMeades 0:c258b7b02be5 208
RobMeades 0:c258b7b02be5 209 return ( (int)IAP_result[ 0 ] );
RobMeades 0:c258b7b02be5 210 }
RobMeades 0:c258b7b02be5 211
RobMeades 0:c258b7b02be5 212 #endif