IAP compatible.

Fork of IAP by Tedd OKANO

Import programSTM32_IAP_internal_flash_write

STM32_IAP demo.

Import programSTM32_IAP_test

STM32_IAP test

Committer:
va009039
Date:
Sun Apr 10 11:32:54 2016 +0000
Revision:
8:8af7acf9dbf3
Child:
9:7e19f12b81b4
first commit

Who changed what in which revision?

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