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:
Sat Apr 30 03:32:33 2016 +0000
Revision:
12:fd6a08b46228
add STM32L0

Who changed what in which revision?

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