dynamic load and run users binary file. self write the flash memory.

Dependencies:   mbed

Committer:
okini3939
Date:
Tue Dec 27 17:02:56 2011 +0000
Revision:
3:5cf31386b95d
Parent:
1:fbb938b95cef

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
okini3939 0:f8cf4fdf6ab4 1 /** IAP : internal Flash memory access library
okini3939 0:f8cf4fdf6ab4 2 *
okini3939 0:f8cf4fdf6ab4 3 * The internal Flash memory access is described in the LPC1768 usermanual.
okini3939 0:f8cf4fdf6ab4 4 * http://www.nxp.com/documents/user_manual/UM10360.pdf
okini3939 0:f8cf4fdf6ab4 5 *
okini3939 0:f8cf4fdf6ab4 6 * Chapter 2: "LPC17xx Memory map"
okini3939 0:f8cf4fdf6ab4 7 * Chapter 32: "LPC17xx Flash memory interface and programming"
okini3939 0:f8cf4fdf6ab4 8 * refering Rev. 01 - 4 January 2010
okini3939 0:f8cf4fdf6ab4 9 *
okini3939 0:f8cf4fdf6ab4 10 * Released under the MIT License: http://mbed.org/license/mit
okini3939 0:f8cf4fdf6ab4 11 *
okini3939 0:f8cf4fdf6ab4 12 * revision 1.0 09-Mar-2010 1st release
okini3939 0:f8cf4fdf6ab4 13 * revision 1.1 12-Mar-2010 chaged: to make possible to reserve flash area for user
okini3939 0:f8cf4fdf6ab4 14 * it can be set by USER_FLASH_AREA_START and USER_FLASH_AREA_SIZE in IAP.h
okini3939 0:f8cf4fdf6ab4 15 *
okini3939 1:fbb938b95cef 16 * by Tedd OKANO http://mbed.org/users/okano/notebook/iap-in-application-programming-internal-flash-eras/
okini3939 0:f8cf4fdf6ab4 17 */
okini3939 0:f8cf4fdf6ab4 18
okini3939 0:f8cf4fdf6ab4 19 #include "mbed.h"
okini3939 0:f8cf4fdf6ab4 20 #include "IAP.h"
okini3939 0:f8cf4fdf6ab4 21
okini3939 0:f8cf4fdf6ab4 22 #define USER_FLASH_AREA_START_STR( x ) STR( x )
okini3939 0:f8cf4fdf6ab4 23 #define STR( x ) #x
okini3939 0:f8cf4fdf6ab4 24
okini3939 0:f8cf4fdf6ab4 25 unsigned char user_area[ USER_FLASH_AREA_SIZE ] __attribute__((section( ".ARM.__at_" USER_FLASH_AREA_START_STR( USER_FLASH_AREA_START ) ), zero_init));
okini3939 0:f8cf4fdf6ab4 26
okini3939 0:f8cf4fdf6ab4 27
okini3939 0:f8cf4fdf6ab4 28 /*
okini3939 0:f8cf4fdf6ab4 29 * Reserve of flash area is explained by Igor. Please refer next URL
okini3939 0:f8cf4fdf6ab4 30 * http://mbed.org/users/okano/notebook/iap-in-application-programming-internal-flash-eras/?page=1#comment-271
okini3939 0:f8cf4fdf6ab4 31 */
okini3939 0:f8cf4fdf6ab4 32
okini3939 0:f8cf4fdf6ab4 33 //unsigned char user_area[ size ] __attribute__((section(".ARM.__at_0x78000"), zero_init));
okini3939 0:f8cf4fdf6ab4 34
okini3939 0:f8cf4fdf6ab4 35 /*
okini3939 0:f8cf4fdf6ab4 36 * IAP command codes
okini3939 0:f8cf4fdf6ab4 37 * Table 589. "IAP Command Summary", Chapter 8. "IAP commands", usermanual
okini3939 0:f8cf4fdf6ab4 38 */
okini3939 0:f8cf4fdf6ab4 39
okini3939 0:f8cf4fdf6ab4 40 enum command_code
okini3939 0:f8cf4fdf6ab4 41 {
okini3939 0:f8cf4fdf6ab4 42 IAPCommand_Prepare_sector_for_write_operation = 50,
okini3939 0:f8cf4fdf6ab4 43 IAPCommand_Copy_RAM_to_Flash,
okini3939 0:f8cf4fdf6ab4 44 IAPCommand_Erase_sector,
okini3939 0:f8cf4fdf6ab4 45 IAPCommand_Blank_check_sector,
okini3939 0:f8cf4fdf6ab4 46 IAPCommand_Read_part_ID,
okini3939 0:f8cf4fdf6ab4 47 IAPCommand_Read_Boot_Code_version,
okini3939 0:f8cf4fdf6ab4 48 IAPCommand_Compare,
okini3939 0:f8cf4fdf6ab4 49 IAPCommand_Reinvoke_ISP,
okini3939 0:f8cf4fdf6ab4 50 IAPCommand_Read_device_serial_number
okini3939 0:f8cf4fdf6ab4 51 };
okini3939 0:f8cf4fdf6ab4 52
okini3939 0:f8cf4fdf6ab4 53
okini3939 0:f8cf4fdf6ab4 54 /** Read part identification number
okini3939 0:f8cf4fdf6ab4 55 *
okini3939 0:f8cf4fdf6ab4 56 * @return device ID
okini3939 0:f8cf4fdf6ab4 57 * @see read_serial()
okini3939 0:f8cf4fdf6ab4 58 */
okini3939 0:f8cf4fdf6ab4 59
okini3939 0:f8cf4fdf6ab4 60 int IAP::read_ID( void ) {
okini3939 0:f8cf4fdf6ab4 61 IAP_command[ 0 ] = IAPCommand_Read_part_ID;
okini3939 0:f8cf4fdf6ab4 62
okini3939 0:f8cf4fdf6ab4 63 iap_entry( IAP_command, IAP_result );
okini3939 0:f8cf4fdf6ab4 64
okini3939 0:f8cf4fdf6ab4 65 // return ( (int)IAP_result[ 0 ] );
okini3939 0:f8cf4fdf6ab4 66 return ( (int)IAP_result[ 1 ] ); // to return the number itself (this command always returns CMD_SUCCESS)
okini3939 0:f8cf4fdf6ab4 67 }
okini3939 0:f8cf4fdf6ab4 68
okini3939 0:f8cf4fdf6ab4 69
okini3939 0:f8cf4fdf6ab4 70 /** Read device serial number
okini3939 0:f8cf4fdf6ab4 71 *
okini3939 0:f8cf4fdf6ab4 72 * @return device serial number
okini3939 0:f8cf4fdf6ab4 73 * @see read_ID()
okini3939 0:f8cf4fdf6ab4 74 */
okini3939 0:f8cf4fdf6ab4 75
okini3939 0:f8cf4fdf6ab4 76 int IAP::read_serial( void ) {
okini3939 0:f8cf4fdf6ab4 77 IAP_command[ 0 ] = IAPCommand_Read_device_serial_number;
okini3939 0:f8cf4fdf6ab4 78
okini3939 0:f8cf4fdf6ab4 79 iap_entry( IAP_command, IAP_result );
okini3939 0:f8cf4fdf6ab4 80
okini3939 0:f8cf4fdf6ab4 81 // return ( (int)IAP_result[ 0 ] );
okini3939 0:f8cf4fdf6ab4 82 return ( (int)IAP_result[ 1 ] ); // to return the number itself (this command always returns CMD_SUCCESS)
okini3939 0:f8cf4fdf6ab4 83 }
okini3939 0:f8cf4fdf6ab4 84
okini3939 0:f8cf4fdf6ab4 85
okini3939 0:f8cf4fdf6ab4 86 /** Blank check sector(s)
okini3939 0:f8cf4fdf6ab4 87 *
okini3939 0:f8cf4fdf6ab4 88 * @param start a Start Sector Number
okini3939 0:f8cf4fdf6ab4 89 * @param end an End Sector Number (should be greater than or equal to start sector number).
okini3939 0:f8cf4fdf6ab4 90 * @return error code: CMD_SUCCESS | BUSY | SECTOR_NOT_BLANK | INVALID_SECTOR
okini3939 0:f8cf4fdf6ab4 91 */
okini3939 0:f8cf4fdf6ab4 92
okini3939 0:f8cf4fdf6ab4 93 int IAP::blank_check( int start, int end ) {
okini3939 0:f8cf4fdf6ab4 94 IAP_command[ 0 ] = IAPCommand_Blank_check_sector;
okini3939 0:f8cf4fdf6ab4 95 IAP_command[ 1 ] = (unsigned int)start; // Start Sector Number
okini3939 0:f8cf4fdf6ab4 96 IAP_command[ 2 ] = (unsigned int)end; // End Sector Number (should be greater than or equal to start sector number)
okini3939 0:f8cf4fdf6ab4 97
okini3939 0:f8cf4fdf6ab4 98 iap_entry( IAP_command, IAP_result );
okini3939 0:f8cf4fdf6ab4 99
okini3939 0:f8cf4fdf6ab4 100 return ( (int)IAP_result[ 0 ] );
okini3939 0:f8cf4fdf6ab4 101 }
okini3939 0:f8cf4fdf6ab4 102
okini3939 0:f8cf4fdf6ab4 103
okini3939 0:f8cf4fdf6ab4 104 /** Erase Sector(s)
okini3939 0:f8cf4fdf6ab4 105 *
okini3939 0:f8cf4fdf6ab4 106 * @param start a Start Sector Number
okini3939 0:f8cf4fdf6ab4 107 * @param end an End Sector Number (should be greater than or equal to start sector number).
okini3939 0:f8cf4fdf6ab4 108 * @return error code: CMD_SUCCESS | BUSY | SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION | INVALID_SECTOR
okini3939 0:f8cf4fdf6ab4 109 */
okini3939 0:f8cf4fdf6ab4 110
okini3939 0:f8cf4fdf6ab4 111 int IAP::erase( int start, int end ) {
okini3939 0:f8cf4fdf6ab4 112 IAP_command[ 0 ] = IAPCommand_Erase_sector;
okini3939 0:f8cf4fdf6ab4 113 IAP_command[ 1 ] = (unsigned int)start; // Start Sector Number
okini3939 0:f8cf4fdf6ab4 114 IAP_command[ 2 ] = (unsigned int)end; // End Sector Number (should be greater than or equal to start sector number)
okini3939 0:f8cf4fdf6ab4 115 IAP_command[ 3 ] = cclk_kHz; // CPU Clock Frequency (CCLK) in kHz
okini3939 0:f8cf4fdf6ab4 116
okini3939 0:f8cf4fdf6ab4 117 iap_entry( IAP_command, IAP_result );
okini3939 0:f8cf4fdf6ab4 118
okini3939 0:f8cf4fdf6ab4 119 return ( (int)IAP_result[ 0 ] );
okini3939 0:f8cf4fdf6ab4 120 }
okini3939 0:f8cf4fdf6ab4 121
okini3939 0:f8cf4fdf6ab4 122
okini3939 0:f8cf4fdf6ab4 123 /** Prepare sector(s) for write operation
okini3939 0:f8cf4fdf6ab4 124 *
okini3939 0:f8cf4fdf6ab4 125 * @param start a Start Sector Number
okini3939 0:f8cf4fdf6ab4 126 * @param end an End Sector Number (should be greater than or equal to start sector number).
okini3939 0:f8cf4fdf6ab4 127 * @return error code: CMD_SUCCESS | BUSY | INVALID_SECTOR
okini3939 0:f8cf4fdf6ab4 128 */
okini3939 0:f8cf4fdf6ab4 129
okini3939 0:f8cf4fdf6ab4 130 int IAP::prepare( int start, int end ) {
okini3939 0:f8cf4fdf6ab4 131 IAP_command[ 0 ] = IAPCommand_Prepare_sector_for_write_operation;
okini3939 0:f8cf4fdf6ab4 132 IAP_command[ 1 ] = (unsigned int)start; // Start Sector Number
okini3939 0:f8cf4fdf6ab4 133 IAP_command[ 2 ] = (unsigned int)end; // End Sector Number (should be greater than or equal to start sector number).
okini3939 0:f8cf4fdf6ab4 134
okini3939 0:f8cf4fdf6ab4 135 iap_entry( IAP_command, IAP_result );
okini3939 0:f8cf4fdf6ab4 136
okini3939 0:f8cf4fdf6ab4 137 return ( (int)IAP_result[ 0 ] );
okini3939 0:f8cf4fdf6ab4 138 }
okini3939 0:f8cf4fdf6ab4 139
okini3939 0:f8cf4fdf6ab4 140
okini3939 0:f8cf4fdf6ab4 141 /** Copy RAM to Flash
okini3939 0:f8cf4fdf6ab4 142 *
okini3939 0:f8cf4fdf6ab4 143 * @param source_addr Source RAM address from which data bytes are to be read. This address should be a word boundary.
okini3939 0:f8cf4fdf6ab4 144 * @param target_addr Destination flash address where data bytes are to be written. This address should be a 256 byte boundary.
okini3939 0:f8cf4fdf6ab4 145 * @param size Number of bytes to be written. Should be 256 | 512 | 1024 | 4096.
okini3939 0:f8cf4fdf6ab4 146 * @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
okini3939 0:f8cf4fdf6ab4 147 */
okini3939 0:f8cf4fdf6ab4 148
okini3939 0:f8cf4fdf6ab4 149 int IAP::write( char *source_addr, char *target_addr, int size ) {
okini3939 0:f8cf4fdf6ab4 150 IAP_command[ 0 ] = IAPCommand_Copy_RAM_to_Flash;
okini3939 0:f8cf4fdf6ab4 151 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.
okini3939 0:f8cf4fdf6ab4 152 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.
okini3939 0:f8cf4fdf6ab4 153 IAP_command[ 3 ] = size; // Number of bytes to be written. Should be 256 | 512 | 1024 | 4096.
okini3939 0:f8cf4fdf6ab4 154 IAP_command[ 4 ] = cclk_kHz; // CPU Clock Frequency (CCLK) in kHz.
okini3939 0:f8cf4fdf6ab4 155
okini3939 0:f8cf4fdf6ab4 156 iap_entry( IAP_command, IAP_result );
okini3939 0:f8cf4fdf6ab4 157
okini3939 0:f8cf4fdf6ab4 158 return ( (int)IAP_result[ 0 ] );
okini3939 0:f8cf4fdf6ab4 159 }
okini3939 0:f8cf4fdf6ab4 160
okini3939 0:f8cf4fdf6ab4 161
okini3939 0:f8cf4fdf6ab4 162 /** Compare <address1> <address2> <no of bytes>
okini3939 0:f8cf4fdf6ab4 163 *
okini3939 0:f8cf4fdf6ab4 164 * @param source_addr Starting flash or RAM address of data bytes to be compared. This address should be a word boundary.
okini3939 0:f8cf4fdf6ab4 165 * @param target_addr Starting flash or RAM address of data bytes to be compared. This address should be a word boundary.
okini3939 0:f8cf4fdf6ab4 166 * @param size Number of bytes to be compared; should be a multiple of 4.
okini3939 0:f8cf4fdf6ab4 167 * @return error code: CMD_SUCCESS | COMPARE_ERROR | COUNT_ERROR (Byte count is not a multiple of 4) | ADDR_ERROR | ADDR_NOT_MAPPED
okini3939 0:f8cf4fdf6ab4 168 */
okini3939 0:f8cf4fdf6ab4 169
okini3939 0:f8cf4fdf6ab4 170 int IAP::compare( char *source_addr, char *target_addr, int size ) {
okini3939 0:f8cf4fdf6ab4 171 IAP_command[ 0 ] = IAPCommand_Compare;
okini3939 0:f8cf4fdf6ab4 172 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.
okini3939 0:f8cf4fdf6ab4 173 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.
okini3939 0:f8cf4fdf6ab4 174 IAP_command[ 3 ] = size; // Number of bytes to be compared; should be a multiple of 4.
okini3939 0:f8cf4fdf6ab4 175
okini3939 0:f8cf4fdf6ab4 176 iap_entry( IAP_command, IAP_result );
okini3939 0:f8cf4fdf6ab4 177
okini3939 0:f8cf4fdf6ab4 178 return ( (int)IAP_result[ 0 ] );
okini3939 0:f8cf4fdf6ab4 179 }
okini3939 0:f8cf4fdf6ab4 180
okini3939 0:f8cf4fdf6ab4 181
okini3939 0:f8cf4fdf6ab4 182 /** Get user reserved flash start address
okini3939 0:f8cf4fdf6ab4 183 *
okini3939 0:f8cf4fdf6ab4 184 * @return start address of user reserved flash memory
okini3939 0:f8cf4fdf6ab4 185 * @see reserved_flash_area_size()
okini3939 0:f8cf4fdf6ab4 186 */
okini3939 0:f8cf4fdf6ab4 187
okini3939 0:f8cf4fdf6ab4 188 char * IAP::reserved_flash_area_start( void )
okini3939 0:f8cf4fdf6ab4 189 {
okini3939 0:f8cf4fdf6ab4 190 return ( (char *)USER_FLASH_AREA_START );
okini3939 0:f8cf4fdf6ab4 191 }
okini3939 0:f8cf4fdf6ab4 192
okini3939 0:f8cf4fdf6ab4 193
okini3939 0:f8cf4fdf6ab4 194 /** Get user reserved flash size
okini3939 0:f8cf4fdf6ab4 195 *
okini3939 0:f8cf4fdf6ab4 196 * @return size of user reserved flash memory
okini3939 0:f8cf4fdf6ab4 197 * @see reserved_flash_area_start()
okini3939 0:f8cf4fdf6ab4 198 */
okini3939 0:f8cf4fdf6ab4 199
okini3939 0:f8cf4fdf6ab4 200 int IAP::reserved_flash_area_size( void )
okini3939 0:f8cf4fdf6ab4 201 {
okini3939 0:f8cf4fdf6ab4 202 return ( USER_FLASH_AREA_SIZE );
okini3939 0:f8cf4fdf6ab4 203 }
okini3939 0:f8cf4fdf6ab4 204