stm32f2_4_flash.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. /*
  2. * Copyright (C) 2012, 2013 Uwe Bonnes
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the copyright holders nor the names of
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  24. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  25. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  26. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  27. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. *
  30. * For additional information see http://www.ethernut.de/
  31. *
  32. */
  33. #include <stdint.h>
  34. #include <string.h>
  35. #include <cfg/arch.h>
  36. #include <cfg/memory.h>
  37. #include <cfg/eeprom.h>
  38. #include <sys/nutdebug.h>
  39. #include <sys/heap.h>
  40. #include <dev/iap_flash.h>
  41. #if !defined(MCU_STM32F2) && !defined(MCU_STM32F4)
  42. #warning "STM32 family has no F2/F4 compatible FLASH"
  43. #endif
  44. #define FLASH_SECTOR_SIZE (1 << 17)
  45. #define FLASH_PSIZE_8 0
  46. #define FLASH_PSIZE_16 FLASH_CR_PSIZE_0
  47. #define FLASH_PSIZE_32 FLASH_CR_PSIZE_1
  48. #define FLASH_PSIZE_64 (FLASH_CR_PSIZE_0 | FLASH_CR_PSIZE_1)
  49. #define FLASH_PSIZE_MASK (FLASH_PSIZE_64)
  50. #define ERASED_PATTERN_32 0xffffffff
  51. #define FLASH_SIZE_REG 0x1fff7A22
  52. #define FLASH_CR_SNB_MASK (FLASH_CR_SNB_0 | FLASH_CR_SNB_1 | FLASH_CR_SNB_2 |\
  53. FLASH_CR_SNB_3)
  54. /* If no other value is given, use 32-bit access*/
  55. #if (FLASH_PE_PARALLELISM == 8)
  56. #define FLASH_PSIZE FLASH_PSIZE_8
  57. #define FLASH_TYPE_CAST (volatile uint8_t *)
  58. #define FLASH_LEN_MASK 0
  59. #elif (FLASH_PE_PARALLELISM == 16)
  60. #define FLASH_PSIZE FLASH_PSIZE_16
  61. #define FLASH_TYPE_CAST (volatile uint16_t *)
  62. #define FLASH_LEN_MASK 1
  63. #else
  64. #if (FLASH_PE_PARALLELISM == 64)
  65. #define FLASH_TYPE_CAST (volatile uint64_t *)
  66. #define FLASH_PSIZE FLASH_PSIZE_64
  67. #define FLASH_LEN_MASK 7
  68. #else
  69. #define FLASH_TYPE_CAST (volatile uint32_t *)
  70. #define FLASH_PSIZE FLASH_PSIZE_32
  71. #define FLASH_LEN_MASK 3
  72. #endif
  73. #endif
  74. #define FLASH_KEY1 0x45670123L
  75. #define FLASH_KEY2 0xCDEF89ABL
  76. #define FLASH_OPTKEY1 0x08192A3B
  77. #define FLASH_OPTKEY2 0x4C5D6E7F
  78. /*! \brief Size of the configuration area.
  79. *
  80. * During write operations a buffer with this size is allocated
  81. * from heap and may cause memory problems with large sectors.
  82. * Thus, this value may be less than the size of the configuration
  83. * sector, in which case the rest of the sector is unused.
  84. *
  85. * Currently only 1 sector can be used for system configurations.
  86. */
  87. #ifndef FLASH_CONF_SIZE
  88. #define FLASH_CONF_SIZE 256
  89. #elif ((FLASH_CONF_SIZE != 256) && (FLASH_CONF_SIZE != 512) && \
  90. (FLASH_CONF_SIZE != 1024) && (FLASH_CONF_SIZE != 2048) && \
  91. (FLASH_CONF_SIZE != 4096) && (FLASH_CONF_SIZE != 8192))
  92. #error FLASH_CONF_SIZE has to be either 256 (default), 512, 1024, 2048,\
  93. 4096 or 8192
  94. #endif
  95. /*!
  96. *\brief Bitmask of sectors either empty or active erased when first touched
  97. */
  98. static uint32_t sectorlist = 0;
  99. static const uint8_t sector2size[] = {
  100. 0x04, 0x04, 0x04, 0x04, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
  101. };
  102. void FlashUntouch(void)
  103. {
  104. sectorlist = 0;
  105. }
  106. /*!
  107. * \brief Unlocks the FLASH Program Erase Controller.
  108. * \retval 0 on success, FLASH_LOCKED else.
  109. */
  110. static FLASH_Status FLASH_Unlock( void )
  111. {
  112. FLASH->KEYR = FLASH_KEY1;
  113. FLASH->KEYR = FLASH_KEY2;
  114. return (FLASH->CR & FLASH_CR_LOCK)?FLASH_LOCKED:FLASH_COMPLETE;
  115. }
  116. /*!
  117. *\brief Calculate sector number and sector length form address
  118. * \param Addr Address
  119. *
  120. * \return Sector Number
  121. */
  122. static uint32_t FlashAddr2Sector(void* Addr)
  123. {
  124. uint32_t sector;
  125. uint32_t addr = (uint32_t) Addr;
  126. if (addr < (FLASH_BASE + 0x10000))
  127. sector = (addr - FLASH_BASE)/0x4000;
  128. else if (addr < (FLASH_BASE + 0x20000))
  129. sector = 4;
  130. #if defined(MCU_STM32F42X)
  131. else if (FLASH->OPTCR & FLASH_OPTCR_DB1M) {
  132. if (addr < (FLASH_BASE + 0x80000))
  133. sector = ((addr - FLASH_BASE)/0x20000) + 4;
  134. else if (addr < (FLASH_BASE + 0x90000))
  135. sector = ((addr - FLASH_BASE - 0x80000)/0x4000) + 12;
  136. else if (addr < (FLASH_BASE + 0xA0000))
  137. sector = 16;
  138. else
  139. sector = ((addr - FLASH_BASE - 0x80000)/0x20000) + 16;
  140. }
  141. else { /* Dual bank mapping of 1 MiB device F42x/F43x */
  142. if (addr < (FLASH_BASE + 0x100000))
  143. sector = ((addr - FLASH_BASE)/0x20000) + 4;
  144. else if (addr < (FLASH_BASE + 0x110000))
  145. sector = ((addr - FLASH_BASE - 0x100000)/0x4000) + 12;
  146. else if (addr < (FLASH_BASE + 0x120000))
  147. sector = 16;
  148. else
  149. sector = ((addr - FLASH_BASE - 0x100000)/0x20000) + 16;
  150. }
  151. #else /* STM32F2xx has only one bank*/
  152. else
  153. sector = ((addr - FLASH_BASE)/0x20000) + 4;
  154. #endif
  155. return sector;
  156. }
  157. /*!
  158. * \brief Waits for a Flash operation to complete or a TIMEOUT to occur.
  159. * \param Timeout: FLASH progamming Timeout in Microseconds
  160. *
  161. * \retval FLASH Status: FLASH_COMPLETE or appropriate error.
  162. */
  163. static FLASH_Status FLASH_GetStatus(void)
  164. {
  165. FLASH_Status rs = FLASH_COMPLETE;
  166. /* Decode the Flash Status
  167. * Check BSY last, so maybe it has completed meanwhile*/
  168. if (FLASH->SR & (FLASH_SR_PGSERR | FLASH_SR_PGPERR | FLASH_SR_PGAERR))
  169. rs = FLASH_ERROR_PG;
  170. else if (FLASH->SR & FLASH_SR_WRPERR)
  171. rs = FLASH_ERROR_WRP;
  172. else if (FLASH->SR & FLASH_SR_BSY)
  173. rs = FLASH_BUSY;
  174. /* Return the Flash Status */
  175. return rs;
  176. }
  177. /*!
  178. * \brief Waits for a Flash operation to complete
  179. *
  180. * \retval FLASH Status: FLASH_COMPLETE or appropriate error.
  181. * Every flash access stalls while FLASH erase/program is running
  182. * The erase/program process however will finish at some point
  183. * and may indicate failure then
  184. */
  185. static FLASH_Status FlashWaitReady(void)
  186. {
  187. FLASH_Status status;
  188. do
  189. status = FLASH_GetStatus();
  190. while(status == FLASH_BUSY);
  191. /* Return the operation status */
  192. return status;
  193. }
  194. /*!
  195. * \brief Erase specified FLASH sector.
  196. *
  197. * \param sector Sector to erase.
  198. *
  199. * \return FLASH Status: FLASH_COMPLETE or appropriate error.
  200. */
  201. static FLASH_Status FlashEraseSector(uint32_t sector)
  202. {
  203. const uint8_t sector2start[] = {
  204. 0x00, 0x01, 0x02, 0x03, 0x04, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38};
  205. uint32_t flash_cr = FLASH_CR_SER;
  206. FLASH_Status rs = FLASH_COMPLETE;
  207. int i;
  208. uint32_t *addr;
  209. int size;
  210. uint32_t offset = 0;
  211. #if defined(MCU_STM32F42X)
  212. /* On STM32F42x/F43x with 1 MiByte, a dual bank option is available.
  213. * When mapped, sectors 7..11 and 19.. 23 are not used and sector 12
  214. * starts at offset 0x80000 instead of 0x100000. */
  215. if (sector > 11) {
  216. if (FLASH->OPTCR & FLASH_OPTCR_DB1M)
  217. offset = 0x80000;
  218. else
  219. offset = 0x100000;
  220. flash_cr |= FLASH_CR_SNB_4;
  221. sector = sector - 12;
  222. }
  223. #endif
  224. addr = (uint32_t *)(FLASH_BASE + offset + (sector2start[sector] << 14));
  225. /* Size in 4-byte words */
  226. size = sector2size[sector] << 10;
  227. /* Check if sector is already erased */
  228. for(i = 0; i < size ; i++)
  229. if (addr[i] != ERASED_PATTERN_32)
  230. break;
  231. if (i >= size)
  232. goto erase_done;
  233. /* Wait for last operation to be completed */
  234. rs = FlashWaitReady();
  235. flash_cr |= sector * FLASH_CR_SNB_0;
  236. if(rs == FLASH_COMPLETE) {
  237. /* if the previous operation is completed, proceed to erase the page */
  238. FLASH->CR = flash_cr;
  239. FLASH->CR = flash_cr | FLASH_CR_STRT;
  240. /* Wait for last operation to be completed */
  241. rs = FlashWaitReady();
  242. FLASH->CR = 0;
  243. }
  244. erase_done:
  245. if(rs != FLASH_COMPLETE)
  246. sectorlist &= ~(1 << sector);
  247. else
  248. sectorlist |= (1 << sector);
  249. /* Return the Erase Status */
  250. return rs;
  251. }
  252. /*!
  253. * \brief Program any data to FLASH.
  254. *
  255. * This function writes data from source address to FLASH.
  256. * It handles erasing and assembling of data automatically.
  257. * On F2/F4 We need to handle sectors with up to 128 kByte,
  258. * so we can't keep a copy.
  259. *
  260. * Lets do some heuristic for F2/F4: We keep count of the sectors
  261. * we have touched.
  262. * If we touch a sector for the first time, we look if the sector is
  263. * clean and if not we erase the sector. Further access to this sector
  264. * doesn't erase until reset.
  265. * Attention: It is the users responsibility to not write multiple times
  266. * to the same range.
  267. *
  268. * \param dst Pointer to address anywhere in FLASH.
  269. * \param src Pointer to source data. With SRC == NULL, the region
  270. * is checked for write protection
  271. * \param len Number of bytes to be written/checked.
  272. * \param mode Erase mode (Always, on first access to block, never).
  273. *
  274. * \return FLASH Status: FLASH_COMPLETE or appropriate error.
  275. */
  276. static FLASH_Status FlashWrite( void* dst, void* src, size_t len,
  277. FLASH_ERASE_MODE mode)
  278. {
  279. FLASH_Status rs = FLASH_COMPLETE;
  280. uint32_t sector_start, sector_end;
  281. int i;
  282. uint32_t optcr = FLASH->OPTCR;
  283. void *wptr = dst;
  284. void *rptr = src;
  285. uint32_t length = len;
  286. uint16_t flash_size = *(uint16_t*)FLASH_SIZE_REG;
  287. uint32_t flash_end_addr = FLASH_BASE + (flash_size << 10);
  288. uint32_t last_sector_nr = -1;
  289. /* we need to run with at least 1 MHz for flashing*/
  290. NUTASSERT((SysTick->LOAD +1)/NUT_TICK_FREQ > 1000);
  291. if (len == 0)
  292. return FLASH_COMPLETE;
  293. /* Check top boundary */
  294. if ((((uint32_t)dst+len) > flash_end_addr) || ((uint32_t)dst < FLASH_BASE))
  295. {
  296. return FLASH_BOUNDARY;
  297. }
  298. /* Check for write protected sectors */
  299. sector_start = FlashAddr2Sector(dst);
  300. sector_end = FlashAddr2Sector(dst+len);
  301. for (i = sector_start; i < sector_end; i++)
  302. if (i < 12) {
  303. /* Skip not available sectors on 1 MiBB dual boot devices*/
  304. #if defined(STM32F2X)
  305. if ((optcr & FLASH_OPTCR_DB1M) && (i > 6))
  306. continue;
  307. #endif
  308. if ((optcr & (1 << (i +_BI32(FLASH_OPTCR_nWRP_0)))) == 0)
  309. return FLASH_ERROR_WRP;
  310. }
  311. #if defined(STM32F2X)
  312. else {
  313. int j = i - 12;
  314. uint32_t optcr1 = FLASH->OPTCR1;
  315. if ((optcr1 & (1 << (j +_BI32(FLASH_OPTCR1_nWRP_0)))) == 0)
  316. return FLASH_ERROR_WRP;
  317. }
  318. #endif
  319. if (src == NULL)
  320. /* Only a check for write protection was requested */
  321. return FLASH_COMPLETE;
  322. /* Unlock related banks */
  323. rs = FLASH_Unlock();
  324. if (rs != FLASH_COMPLETE)
  325. {
  326. /* Unlocking failed for any reason */
  327. return FLASH_LOCKED;
  328. }
  329. while( (length) && (rs==FLASH_COMPLETE))
  330. {
  331. uint32_t sector_nr = FlashAddr2Sector(wptr);
  332. uint32_t sector_length = sector2size[sector_nr % 12] << 12;
  333. uint32_t current_length = length;
  334. if (((uint32_t)wptr & (sector_length -1)) + length > sector_length)
  335. current_length = sector_length -
  336. ((uint32_t)wptr & (sector_length -1));
  337. length -= current_length;
  338. /* Check if sector needs erase */
  339. if (((mode == FLASH_ERASE_ALWAYS) && (sector_nr != last_sector_nr)) ||
  340. ((mode == FLASH_ERASE_FIRST_TOUCH) &&
  341. (sectorlist & (1 << sector_nr)) == 0))
  342. {
  343. rs = FlashEraseSector(sector_nr);
  344. if (rs != FLASH_COMPLETE)
  345. goto done;
  346. last_sector_nr = sector_nr;
  347. }
  348. /* Program the sector */
  349. rs = FlashWaitReady();
  350. if (rs != FLASH_COMPLETE)
  351. goto done;
  352. else
  353. {
  354. /* Size written must correspond the size announced! */
  355. /* Enable Programming Mode */
  356. FLASH->CR = FLASH_CR_PG | FLASH_PSIZE_8;
  357. /* Write data to page */
  358. /* First, align to 2/4/8 Byte boundary */
  359. /* Run loop control before waiting for command to finish*/
  360. while(current_length && ((uint32_t)wptr & FLASH_LEN_MASK))
  361. {
  362. rs = FlashWaitReady();
  363. *(volatile uint8_t*)wptr++ = *(volatile uint8_t*)rptr++;
  364. current_length--;
  365. }
  366. /* Write Bulk of data in requested width*/
  367. rs = FlashWaitReady();
  368. FLASH->CR = FLASH_CR_PG | FLASH_PSIZE_32 ;
  369. while((current_length > FLASH_LEN_MASK) && (rs == FLASH_COMPLETE))
  370. {
  371. rs = FlashWaitReady();
  372. * FLASH_TYPE_CAST wptr = * FLASH_TYPE_CAST rptr ;
  373. current_length -= (FLASH_LEN_MASK +1);
  374. wptr += (FLASH_LEN_MASK +1);
  375. rptr += (FLASH_LEN_MASK +1);
  376. }
  377. rs = FlashWaitReady();
  378. FLASH->CR = FLASH_CR_PG | FLASH_PSIZE_8;
  379. while ((current_length > 0) && (rs == FLASH_COMPLETE))
  380. {
  381. rs = FlashWaitReady();
  382. *(volatile uint8_t*)wptr++ = *(volatile uint8_t*)rptr++;
  383. current_length --;
  384. }
  385. rs = FlashWaitReady();
  386. FLASH->CR = 0;
  387. if(rs != FLASH_COMPLETE)
  388. goto done;
  389. }
  390. }
  391. /* Check the written data */
  392. wptr = dst;
  393. rptr = src;
  394. length = len;
  395. /* Align flash access to 4 Byte Boundary*/
  396. while (length && ((uint32_t)wptr & FLASH_LEN_MASK)) {
  397. if(*(volatile uint8_t*)wptr++ != *(uint8_t*)rptr++)
  398. goto cmp_err;
  399. length--;
  400. }
  401. /* Now compare 32-bit at a time*/
  402. while (length > 3) {
  403. if(*(volatile uint32_t*)wptr != *(uint32_t*)rptr)
  404. goto cmp_err;
  405. length -= 4;
  406. wptr += +4;
  407. rptr += +4;
  408. }
  409. while (length) {
  410. if((*(volatile uint8_t*)wptr++) != *(uint8_t*)rptr++)
  411. goto cmp_err;
  412. length--;
  413. }
  414. goto done;
  415. cmp_err:
  416. rs = FLASH_COMPARE;
  417. done:
  418. /* Lock the FLASH again */
  419. FLASH->CR = FLASH_CR_LOCK;
  420. return rs;
  421. }
  422. /*!
  423. * \brief Get Upper limit of Flash.
  424. *
  425. * This function writes data from source address to FLASH. Write to
  426. * configuration area, if configured, is denied.
  427. *
  428. * \param NONE
  429. * \return Last Flash Address.
  430. */
  431. uint32_t IapFlashEnd(void)
  432. {
  433. uint32_t area_end = FLASH_BASE + (((*(uint16_t*)FLASH_SIZE_REG)<<10)) - 1;
  434. #if defined(NUT_CONFIG_STM32_IAP)
  435. area_end -= FLASH_SECTOR_SIZE;
  436. #endif
  437. return area_end;
  438. }
  439. /*!
  440. * \brief Program any data to FLASH.
  441. *
  442. * This function writes data from source address to FLASH.
  443. * It handles erasing and assembling of data automatically.
  444. * On F2/F4 We need to handle sectors with up to 128 kByte,
  445. * so we can't keep a copy. If a configuration sector is used,
  446. * this sector is not allowed for writing.
  447. *
  448. * \param dst Pointer to address anywhere in FLASH.
  449. * \param src Pointer to source data. With SRC == NULL, the region
  450. * is checked for write protection
  451. * \param len Number of bytes to be written/checked.
  452. * \param mode Erase mode (Always, on first access to block, never).
  453. *
  454. * \return FLASH Status: FLASH_COMPLETE or appropriate error.
  455. */
  456. FLASH_Status IapFlashWrite( void* dst, void* src, size_t len,
  457. FLASH_ERASE_MODE mode)
  458. {
  459. uint16_t flash_size = *(uint16_t*)FLASH_SIZE_REG;
  460. uint32_t flash_end_addr = FLASH_BASE + (flash_size << 10);
  461. #if defined(NUT_CONFIG_STM32_IAP)
  462. flash_end_addr -= FLASH_SECTOR_SIZE;
  463. #endif
  464. if ((uint32_t)dst + len > flash_end_addr)
  465. return FLASH_BOUNDARY;
  466. else
  467. return FlashWrite( dst, src, len, mode);
  468. }
  469. /*!
  470. * \brief Nut/OS specific handling for parameters in FLASH.
  471. *
  472. * This function enables to read system specific parameters
  473. * from processors FLASH. The sectors used for storage are
  474. * configureable via nutconf.
  475. * As the upper sectors of the F2/4 are 128 kByte big, we
  476. * use a rolling scheme to write a FLASH_CONF_SIZE
  477. * configuration page. The upper 32-bit word in a configuration
  478. * page is used to indicated the present used configuration page.
  479. * The first page with this value erases is considered the page
  480. * in use.
  481. *
  482. * \param pos Offset of parameter(s) in configured page(s).
  483. * \param data Pointer where to copy data from flash to.
  484. * \param len Number of bytes to be copied.
  485. *
  486. * \return FLASH_Status: FLASH_COMPLETE or appropriate error.
  487. */
  488. FLASH_Status Stm32FlashParamRead(uint32_t pos, void *data, size_t len)
  489. {
  490. uint8_t conf_page = 0;
  491. uint16_t flash_size = *(uint16_t*)FLASH_SIZE_REG;
  492. uint32_t flash_conf_sector =
  493. FLASH_BASE + (flash_size << 10) - FLASH_SECTOR_SIZE;
  494. uint32_t marker = *(uint32_t*)
  495. (flash_conf_sector +((conf_page + 1) * FLASH_CONF_SIZE)
  496. - sizeof(ERASED_PATTERN_32));
  497. if (len == 0)
  498. return FLASH_COMPLETE;
  499. /* Check boundaries */
  500. if (pos + len + sizeof(ERASED_PATTERN_32) > FLASH_CONF_SIZE)
  501. {
  502. return FLASH_CONF_OVERFLOW;
  503. }
  504. /* Find configuration page in CONF_SECTOR*/
  505. while ((marker != ERASED_PATTERN_32) &&
  506. (conf_page < ((FLASH_SECTOR_SIZE/FLASH_CONF_SIZE) - 1 ))) {
  507. conf_page++;
  508. marker = *(uint32_t*)
  509. (flash_conf_sector + ((conf_page + 1) * FLASH_CONF_SIZE)
  510. - sizeof(ERASED_PATTERN_32));
  511. }
  512. if (marker != ERASED_PATTERN_32)
  513. /* no page sizes unit in CONF_SECTOR has a valid mark */
  514. return FLASH_ERR_CONF_LAYOUT;
  515. memcpy( data, (uint8_t *)((uint8_t*)flash_conf_sector +
  516. conf_page * FLASH_CONF_SIZE + pos), len);
  517. /* Return success or fault code */
  518. return FLASH_COMPLETE;
  519. }
  520. /*!
  521. * \brief Nut/OS specific handling for parameters in FLASH.
  522. *
  523. * This function enables to store system specific parameters
  524. * in processors FLASH. The sectors used for storage are
  525. * configurable via nutconf.
  526. *
  527. * FIXME: As the F2/F4 last sector is quite much bigger than
  528. * a FLASH_CONF_SIZE we can handle, implement some rolling scheme
  529. * E.g. the last word == 0xffffffff in the first FLASH_CONF_SIZE
  530. * unit starting at FLASH_CONF_SECTOR marks a valid CONF_PAGE. When
  531. * writing a new sector, we set the MARK of the last CONF_SECTOR to
  532. * 0. If CONF_SECTOR wraps the sectorsize, we start all over.
  533. *
  534. * \param pos Offset of parameter(s) in configured page(s).
  535. * \param data Pointer to source data.
  536. * \param len Number of bytes to be written.
  537. *
  538. * \return FLASH_Status: FLASH_COMPLETE or appropriate error.
  539. */
  540. FLASH_Status Stm32FlashParamWrite(unsigned int pos, void *data,
  541. size_t len)
  542. {
  543. FLASH_Status rs = 0;
  544. uint8_t *buffer;
  545. uint8_t conf_page = 0, *mem;
  546. uint16_t flash_size = *(uint16_t*)FLASH_SIZE_REG;
  547. void* flash_conf_sector = (void*)FLASH_BASE +
  548. (flash_size << 10) - FLASH_SECTOR_SIZE;
  549. uint32_t marker = *(uint32_t*)
  550. (flash_conf_sector + ((conf_page +1) * FLASH_CONF_SIZE)
  551. - sizeof(ERASED_PATTERN_32));
  552. int i;
  553. FLASH_ERASE_MODE mode;
  554. if (len == 0)
  555. return FLASH_COMPLETE;
  556. /* Check top boundaries */
  557. if (pos + len + sizeof(ERASED_PATTERN_32) > FLASH_CONF_SIZE)
  558. {
  559. return FLASH_CONF_OVERFLOW;
  560. }
  561. /* Find configuration page in CONF_SECTOR*/
  562. while ((marker != ERASED_PATTERN_32) &&
  563. conf_page < ((FLASH_SECTOR_SIZE/FLASH_CONF_SIZE) -1)) {
  564. conf_page++;
  565. marker = *(uint32_t*)
  566. (flash_conf_sector + ((conf_page + 1)* FLASH_CONF_SIZE)
  567. - sizeof(ERASED_PATTERN_32));
  568. }
  569. if (marker != ERASED_PATTERN_32) {
  570. /* no page sizes unit in CONF_SECTOR has a valid mark
  571. * Erase Sector and write provided data to position at first sector */
  572. rs = FlashWrite(flash_conf_sector + pos, data, len, FLASH_ERASE_ALWAYS);
  573. /* Return success or fault code */
  574. return rs;
  575. }
  576. /* Check if target area is erased.
  577. * It seems no C standard function provides this functionality!
  578. */
  579. mem = (uint8_t*) (flash_conf_sector + conf_page * FLASH_CONF_SIZE + pos);
  580. for (i = 0; i < len; i++) {
  581. if (mem[i] != 0xff)
  582. break;
  583. }
  584. if (i >= len) {
  585. /* Needed area is erased, simply write the data to the requested area*/
  586. rs = FlashWrite( flash_conf_sector + conf_page * FLASH_CONF_SIZE + pos,
  587. data, len, FLASH_ERASE_NEVER);
  588. return rs;
  589. }
  590. /* Check if content needs no update. */
  591. if (memcmp(flash_conf_sector + conf_page * FLASH_CONF_SIZE + pos,
  592. data, len) == 0)
  593. return FLASH_COMPLETE;
  594. /* Save configuration page in RAM and write updated data to next
  595. * configuration page, eventually erasing the sector wrapping to the
  596. * first page
  597. */
  598. buffer = NutHeapAlloc(FLASH_CONF_SIZE);
  599. if (buffer == NULL)
  600. {
  601. /* Not enough memory */
  602. return FLASH_OUT_OF_MEMORY;
  603. }
  604. /* Get the content of the whole config page*/
  605. memcpy( buffer, flash_conf_sector + conf_page * FLASH_CONF_SIZE ,
  606. FLASH_CONF_SIZE);
  607. /* Overwrite new data region*/
  608. memcpy (buffer + pos, data, len);
  609. conf_page++;
  610. mode = FLASH_ERASE_NEVER;
  611. if (conf_page < FLASH_SECTOR_SIZE/FLASH_CONF_SIZE) {
  612. uint32_t indicator = ~ERASED_PATTERN_32;
  613. rs = FlashWrite( flash_conf_sector + conf_page * FLASH_CONF_SIZE -
  614. sizeof(indicator), &indicator, sizeof(indicator),
  615. FLASH_ERASE_NEVER);
  616. }
  617. else {
  618. /* All pages used, mark the sector as not yet erases to force erase*/
  619. sectorlist &= ~(1<<FlashAddr2Sector(flash_conf_sector));
  620. conf_page = 0;
  621. mode = FLASH_ERASE_ALWAYS;
  622. }
  623. rs = FlashWrite( flash_conf_sector + conf_page * FLASH_CONF_SIZE , buffer,
  624. FLASH_CONF_SIZE, mode);
  625. NutHeapFree(buffer);
  626. /* Return success or fault code */
  627. return rs;
  628. }
  629. /*!
  630. * \brief Try to protect/unprotect the requested flash region.
  631. *
  632. * \param dst Pointer to address anywhere in FLASH.
  633. * \param len Length of region in bytes.
  634. * \param ena 0 disables write protection anything else write-protects.
  635. *
  636. * \return FLASH_Status: FLASH_COMPLETE or appropriate error.
  637. */
  638. FLASH_Status IapFlashWriteProtect(void *dst, size_t len, int ena)
  639. {
  640. uint32_t sector_start, sector_end;
  641. int i;
  642. uint32_t optcr;
  643. FLASH_Status rs = FLASH_COMPLETE;
  644. uint16_t flash_size = *(uint16_t*)FLASH_SIZE_REG;
  645. uint32_t flash_end_addr = FLASH_BASE + (flash_size << 10);
  646. #if defined(NUT_CONFIG_STM32_IAP)
  647. flash_end_addr -= FLASH_SECTOR_SIZE;
  648. #endif
  649. /* Check boundaries */
  650. if ((((uint32_t)dst+len) > flash_end_addr) || ((uint32_t)dst < FLASH_BASE))
  651. {
  652. return FLASH_BOUNDARY;
  653. }
  654. if (len == 0)
  655. return FLASH_COMPLETE;
  656. /* Wait for last operation to be completed */
  657. rs = FlashWaitReady();
  658. if(rs != FLASH_COMPLETE)
  659. return rs;
  660. FLASH->OPTKEYR = FLASH_OPTKEY1;
  661. FLASH->OPTKEYR = FLASH_OPTKEY2;
  662. optcr = FLASH->OPTCR;
  663. if (optcr & FLASH_OPTCR_OPTLOCK)
  664. return FLASH_ERROR_PG;
  665. sector_start = FlashAddr2Sector(dst);
  666. sector_end = FlashAddr2Sector(dst + len -1);
  667. for (i = sector_start; i <= sector_end; i++) {
  668. if (i < 12) {
  669. #if defined(STM32F2X)
  670. /* Skip not available sectors on 1 MiBB dual boot devices*/
  671. if ((FLASH->OPTCR & FLASH_OPTCR_DB1M) && i > 6)
  672. continue;
  673. #endif
  674. if (ena)
  675. optcr &= ~(1 << (i + _BI32(FLASH_OPTCR_nWRP_0)));
  676. else
  677. optcr |= (1 << (i + _BI32(FLASH_OPTCR_nWRP_0)));
  678. }
  679. #if defined(STM32F2X)
  680. else {
  681. int j = i - 12;
  682. uint32_t optcr1 = FLASH->OPTCR1;
  683. if ((FLASH->OPTCR & FLASH_OPTCR_DB1M) && j > 6)
  684. continue;
  685. if (ena)
  686. optcr1 &= ~(1 << (j + _BI32(FLASH_OPTCR1_nWRP_0)));
  687. else
  688. optcr1 |= (1 << (j + _BI32(FLASH_OPTCR1_nWRP_0)));
  689. FLASH->OPTCR1 = optcr1;
  690. }
  691. #else
  692. }
  693. #endif
  694. FLASH->OPTCR = optcr;
  695. FLASH->OPTCR = optcr |FLASH_OPTCR_OPTSTRT;
  696. /* Wait for last operation to be completed */
  697. rs = FlashWaitReady();
  698. FLASH->OPTCR |= FLASH_OPTCR_OPTLOCK;
  699. return rs;
  700. }