IAP compatible.
Fork of IAP by
Embed:
(wiki syntax)
Show/hide line numbers
IAP_STM32F0.cpp
00001 #if defined(TARGET_STM32F0)||defined(TARGET_STM32F1) 00002 /** IAP : internal Flash memory access library 00003 * 00004 * The internal Flash memory access is described in the LPC1768 and LPC11U24 usermanual. 00005 * http://www.nxp.com/documents/user_manual/UM10360.pdf 00006 * http://www.nxp.com/documents/user_manual/UM10462.pdf 00007 * 00008 * LPC1768 -- 00009 * Chapter 2: "LPC17xx Memory map" 00010 * Chapter 32: "LPC17xx Flash memory interface and programming" 00011 * refering Rev. 01 - 4 January 2010 00012 * 00013 * LPC11U24 -- 00014 * Chapter 2: "LPC11Uxx Memory mapping" 00015 * Chapter 20: "LPC11Uxx Flash programming firmware" 00016 * refering Rev. 03 - 16 July 2012 00017 * 00018 * Released under the MIT License: http://mbed.org/license/mit 00019 * 00020 * revision 1.0 09-Mar-2010 1st release 00021 * revision 1.1 12-Mar-2010 chaged: to make possible to reserve flash area for user 00022 * it can be set by USER_FLASH_AREA_START and USER_FLASH_AREA_SIZE in IAP.h 00023 * revision 2.0 26-Nov-2012 LPC11U24 code added 00024 * revision 2.1 26-Nov-2012 EEPROM access code imported from Suga koubou san's (http://mbed.org/users/okini3939/) library 00025 * http://mbed.org/users/okini3939/code/M0_EEPROM_test/ 00026 * revision 3.0 09-Jan-2015 LPC812 and LPC824 support added 00027 * revision 3.1 13-Jan-2015 LPC1114 support added 00028 * revision 3.1.1 16-Jan-2015 Target MCU name changed for better compatibility across the platforms 00029 */ 00030 00031 #include "mbed.h" 00032 #include "IAP.h" 00033 00034 #define USER_FLASH_AREA_START_STR( x ) STR( x ) 00035 #define STR( x ) #x 00036 00037 //unsigned char user_area[ USER_FLASH_AREA_SIZE ] __attribute__((section( ".ARM.__at_" USER_FLASH_AREA_START_STR( USER_FLASH_AREA_START ) ), zero_init)); 00038 00039 /* 00040 * Reserve of flash area is explained by Igor. Please refer next URL 00041 * http://mbed.org/users/okano/notebook/iap-in-application-programming-internal-flash-eras/?page=1#comment-271 00042 */ 00043 00044 //unsigned char user_area[ size ] __attribute__((section(".ARM.__at_0x78000"), zero_init)); 00045 00046 /* 00047 * IAP command codes 00048 * Table 589. "IAP Command Summary", Chapter 8. "IAP commands", usermanual 00049 */ 00050 00051 enum command_code { 00052 IAPCommand_Prepare_sector_for_write_operation = 50, 00053 IAPCommand_Copy_RAM_to_Flash, 00054 IAPCommand_Erase_sector, 00055 IAPCommand_Blank_check_sector, 00056 IAPCommand_Read_part_ID, 00057 IAPCommand_Read_Boot_Code_version, 00058 IAPCommand_Compare, 00059 IAPCommand_Reinvoke_ISP, 00060 IAPCommand_Read_device_serial_number, 00061 #if defined(TARGET_LPC11UXX) 00062 IAPCommand_EEPROM_Write = 61, 00063 IAPCommand_EEPROM_Read, 00064 #elif defined(TARGET_LPC81X) || defined(TARGET_LPC82X) 00065 IAPCommand_Erase_page = 59, 00066 #endif 00067 }; 00068 00069 int IAP::reinvoke_isp( void ) { 00070 return INVALID_COMMAND; 00071 } 00072 00073 /** Read part identification number 00074 * 00075 * @return device ID 00076 * @see read_serial() 00077 */ 00078 int IAP::read_ID( void ) 00079 { 00080 IAP_result[1] = HAL_GetDEVID(); 00081 return ( (int)IAP_result[ 1 ] ); // to return the number itself (this command always returns CMD_SUCCESS) 00082 } 00083 00084 #if defined(TARGET_STM32F0) 00085 int *IAP::read_serial( void ) { 00086 memcpy(&IAP_result[1], (void*)0x1ffff7ac, sizeof(uint32_t) * 3); 00087 IAP_result[4] = 0; 00088 return ( (int *)&IAP_result[ 1 ] ); // to return the number itself (this command always returns CMD_SUCCESS) 00089 } 00090 00091 #elif defined(TARGET_STM32F1) 00092 int *IAP::read_serial( void ) { 00093 memset(&IAP_result[1], 0x00, sizeof(uint32_t) * 4); 00094 return ( (int *)&IAP_result[ 1 ] ); // to return the number itself (this command always returns CMD_SUCCESS) 00095 } 00096 00097 #endif 00098 00099 int IAP::blank_check( int start, int end ) 00100 { 00101 if (!IS_FLASH_NB_PAGES(FLASH_BASE, start) || !IS_FLASH_NB_PAGES(FLASH_BASE, end)) { 00102 return INVALID_SECTOR; 00103 } 00104 uint8_t* p = reinterpret_cast<uint8_t*>(FLASH_BASE + start * FLASH_PAGE_SIZE); 00105 uint8_t* e = p + (end - start + 1) * FLASH_PAGE_SIZE; 00106 while(p < e) { 00107 if (*p++ != 0x00) { 00108 return SECTOR_NOT_BLANK; 00109 } 00110 } 00111 return CMD_SUCCESS; 00112 } 00113 00114 struct FLASH_Unlock { 00115 FLASH_Unlock() { HAL_FLASH_Unlock(); } 00116 ~FLASH_Unlock() { HAL_FLASH_Lock(); } 00117 }; 00118 00119 int IAP::erase( int start, int end ) 00120 { 00121 if (!IS_FLASH_NB_PAGES(FLASH_BASE, start) || !IS_FLASH_NB_PAGES(FLASH_BASE, end)) { 00122 return INVALID_SECTOR; 00123 } 00124 FLASH_EraseInitTypeDef Erase; 00125 Erase.TypeErase = FLASH_TYPEERASE_PAGES; 00126 Erase.PageAddress = start * FLASH_PAGE_SIZE; 00127 Erase.NbPages = end - start + 1; 00128 uint32_t PageError = 0; 00129 FLASH_Unlock unlock; 00130 HAL_StatusTypeDef status = HAL_FLASHEx_Erase(&Erase, &PageError); 00131 return status == HAL_OK ? CMD_SUCCESS : INVALID_COMMAND; 00132 } 00133 00134 int IAP::prepare( int start, int end ) 00135 { 00136 if (!IS_FLASH_NB_PAGES(FLASH_BASE, start) || !IS_FLASH_NB_PAGES(FLASH_BASE, end)) { 00137 return INVALID_SECTOR; 00138 } 00139 return CMD_SUCCESS; 00140 } 00141 00142 int IAP::write( char *source_addr, char *target_addr, int size ) 00143 { 00144 if (!IS_FLASH_PROGRAM_ADDRESS((uint32_t)target_addr) || !IS_FLASH_PROGRAM_ADDRESS((uint32_t)target_addr + size - 1)) { 00145 return DST_ADDR_NOT_MAPPED; 00146 } 00147 uint32_t data; 00148 FLASH_Unlock unlock; 00149 for(int n = 0; n < size; n += sizeof(data)) { 00150 memcpy(&data, source_addr + n, sizeof(data)); 00151 if (HAL_OK != HAL_FLASH_Program(TYPEPROGRAM_WORD, (uint32_t)target_addr + n, data)) { 00152 return INVALID_COMMAND; 00153 } 00154 } 00155 return CMD_SUCCESS; 00156 } 00157 00158 int IAP::compare( char *source_addr, char *target_addr, int size ) 00159 { 00160 return memcmp(source_addr, target_addr, size) == 0 ? CMD_SUCCESS : COMPARE_ERROR; 00161 } 00162 00163 int IAP::read_BootVer(void) 00164 { 00165 // TODO 00166 return 0; 00167 } 00168 00169 char * IAP::reserved_flash_area_start( void ) 00170 { 00171 // TODO 00172 return NULL; 00173 } 00174 00175 int IAP::reserved_flash_area_size( void ) 00176 { 00177 // TODO 00178 return 0; 00179 } 00180 00181 #if defined(TARGET_LPC11UXX) 00182 00183 int IAP::write_eeprom( char *source_addr, char *target_addr, int size ) 00184 { 00185 IAP_command[ 0 ] = IAPCommand_EEPROM_Write; 00186 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. 00187 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. 00188 IAP_command[ 3 ] = size; // Number of bytes to be written. Should be 256 | 512 | 1024 | 4096. 00189 IAP_command[ 4 ] = cclk_kHz; // CPU Clock Frequency (CCLK) in kHz. 00190 00191 iap_entry( IAP_command, IAP_result ); 00192 00193 return ( (int)IAP_result[ 0 ] ); 00194 } 00195 00196 int IAP::read_eeprom( char *source_addr, char *target_addr, int size ) 00197 { 00198 IAP_command[ 0 ] = IAPCommand_EEPROM_Read; 00199 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. 00200 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. 00201 IAP_command[ 3 ] = size; // Number of bytes to be written. Should be 256 | 512 | 1024 | 4096. 00202 IAP_command[ 4 ] = cclk_kHz; // CPU Clock Frequency (CCLK) in kHz. 00203 00204 iap_entry( IAP_command, IAP_result ); 00205 00206 return ( (int)IAP_result[ 0 ] ); 00207 } 00208 00209 #elif defined(TARGET_LPC81X) || defined(TARGET_LPC82X) 00210 00211 int IAP::erase_page( int start, int end ) 00212 { 00213 IAP_command[ 0 ] = IAPCommand_Erase_page; 00214 IAP_command[ 1 ] = (unsigned int)start; // Start Sector Number 00215 IAP_command[ 2 ] = (unsigned int)end; // End Sector Number (should be greater than or equal to start sector number) 00216 IAP_command[ 3 ] = cclk_kHz; // CPU Clock Frequency (CCLK) in kHz 00217 00218 iap_entry( IAP_command, IAP_result ); 00219 00220 return ( (int)IAP_result[ 0 ] ); 00221 } 00222 00223 #endif 00224 00225 #endif // TARGET_STM32F0, TARGET_STM32F1
Generated on Mon Jul 18 2022 02:45:22 by 1.7.2