STM32_IAP demo.

Dependencies:   STM32_IAP mbed

Fork of IAP_internal_flash_write by Tedd OKANO

FLASH_wrtie_test EEPROM_write_test

Committer:
okano
Date:
Fri Mar 12 10:24:57 2010 +0000
Revision:
0:b802bd2f4cc9

        

Who changed what in which revision?

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