stm32f1_3_flash.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749
  1. /*
  2. * Copyright (C) 2010 by Ulrich Prinz (uprinz2@netscape.net)
  3. * Copyright (C) 2010 by Rittal GmbH & Co. KG. All rights reserved.
  4. * Copyright (C) 2012, 2013 Uwe Bonnes
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the copyright holders nor the names of
  16. * contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  23. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  24. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  25. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  26. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  27. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  28. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  29. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. *
  32. * For additional information see http://www.ethernut.de/
  33. *
  34. */
  35. #include <stdint.h>
  36. #include <string.h>
  37. #include <cfg/arch.h>
  38. #include <cfg/memory.h>
  39. #include <cfg/eeprom.h>
  40. #include <sys/nutdebug.h>
  41. #include <sys/heap.h>
  42. #include <dev/iap_flash.h>
  43. #if defined(MCU_STM32F0) || defined(MCU_STM32F1) || defined(MCU_STM32F3)
  44. #include <arch/cm3/stm/stm32xxxx.h>
  45. #else
  46. #warning "STM32 family has no F1/F3 compatible FLASH"
  47. #endif
  48. #if defined (STM32F030) || defined (STM32F031) || defined (STM32F051)
  49. #define FLASH_PAGE_SIZE 1024
  50. static uint32_t pagelist[2] = {0, 0};
  51. #elif defined (STM32F072)
  52. static uint32_t pagelist[2] = {0, 0};
  53. #define FLASH_PAGE_SIZE 2048
  54. #elif defined (STM32F10X_LD) || defined (STM32F10X_LD_VL)
  55. #define FLASH_PAGE_SIZE 1024
  56. static uint32_t pagelist[1] = {0};
  57. #elif defined (STM32F10X_MD) || defined(STM32F10X_MD_VL)
  58. #define FLASH_PAGE_SIZE 1024
  59. static uint32_t pagelist[4] = {0, 0, 0, 0};
  60. #elif defined (STM32F10X_HD) || defined (STM32F10X_HD_VL) ||\
  61. defined (STM32F10X_CL) /* || defined(STM32F3) */
  62. #define FLASH_PAGE_SIZE 2048
  63. static uint32_t pagelist[8] = {0,0,0,0,0,0,0,0};
  64. #elif defined(STM32F10X_XL)
  65. #define FLASH_PAGE_SIZE 2048
  66. static uint32_t pagelist[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  67. #elif defined(MCU_STM32F3)
  68. #define FLASH_PAGE_SIZE 2048
  69. static uint32_t pagelist[4] = {0,0,0,0};
  70. #else
  71. #warning Unknown STM32 Type
  72. #endif
  73. #define ERASED_PATTERN_16 0xffff
  74. #ifndef FLASH_CONF_SIZE
  75. #define FLASH_CONF_SIZE FLASH_PAGE_SIZE
  76. #elif ((FLASH_CONF_SIZE != 256) && (FLASH_CONF_SIZE != 512) && \
  77. (FLASH_CONF_SIZE != 1024) && (FLASH_CONF_SIZE != 2048) && \
  78. (FLASH_CONF_SIZE != 4096) && (FLASH_CONF_SIZE != 8192))
  79. #error FLASH_CONF_SIZE has to be either FLASH_PAGE_SIZE (default), 256, 512, 1024, 2048, 4096 or 8192
  80. #endif
  81. #if !defined(RDP_KEY)
  82. #define RDP_KEY 0x00aa;
  83. #endif
  84. #if !defined(FLASH_KEY1)
  85. #define FLASH_KEY1 0x45670123L
  86. #endif
  87. #if !defined(FLASH_KEY2)
  88. #define FLASH_KEY2 0xCDEF89ABL
  89. #endif
  90. #if !defined(FLASH_OPTKEY1)
  91. #define FLASH_OPTKEY1 0x08192A3B
  92. #endif
  93. #if !defined(FLASH_OPTKEY2)
  94. #define FLASH_OPTKEY2 0x4C5D6E7F
  95. #endif
  96. #if !defined(FLASH_SR_WRPRTERR) && defined(FLASH_SR_WRPERR)
  97. #define FLASH_SR_WRPRTERR FLASH_SR_WRPERR
  98. #endif
  99. void FlashUntouch(void)
  100. {
  101. int i;
  102. for (i = 0; i< sizeof(pagelist); i++)
  103. pagelist[1] = 0;
  104. }
  105. static uint32_t FlashEnd(void)
  106. {
  107. uint16_t size;
  108. #if defined(MCU_STM32F3)
  109. size = *(__I uint16_t *) 0x1FFFF7CC;
  110. #else
  111. size = *(__I uint16_t *) 0x1FFFF7E0;
  112. #endif
  113. return FLASH_BASE - 1 + size * 1024;
  114. }
  115. /*!
  116. * \brief Returns the FLASH Status.
  117. *
  118. * \retval FLASH Status: FLASH_COMPLETE or appropriate error.
  119. */
  120. static FLASH_Status FLASH_GetStatus(void)
  121. {
  122. FLASH_Status rs = FLASH_COMPLETE;
  123. /* Decode the Flash Status */
  124. if (FLASH->SR & FLASH_SR_WRPRTERR)
  125. rs = FLASH_ERROR_WRP;
  126. else if (FLASH->SR & FLASH_SR_PGERR) {
  127. rs = FLASH_ERROR_PG;
  128. FLASH->CR = 0; /* Reset STRT */
  129. }
  130. else if (FLASH->SR & FLASH_SR_BSY)
  131. rs = FLASH_BUSY;
  132. FLASH->SR = FLASH_SR_EOP | FLASH_SR_WRPRTERR | FLASH_SR_PGERR;
  133. #if defined(STM32F10X_XL)
  134. /* Decode the Flash Status */
  135. if (FLASH->SR2 & FLASH_SR_WRPRTERR)
  136. rs |= FLASH_ERROR_WRP;
  137. else if (FLASH->SR2 & FLASH_SR_PGERR)
  138. rs |= FLASH_ERROR_PG;
  139. else if (FLASH->SR2 & FLASH_SR_BSY)
  140. rs |= FLASH_BUSY;
  141. #endif /* STM32F10X_XL */
  142. /* Return the Flash Status */
  143. return rs;
  144. }
  145. /*!
  146. * \brief Waits for a Flash operation to complete
  147. *
  148. * \retval FLASH Status: FLASH_COMPLETE or appropriate error.
  149. * Every flash access stalls while FLASH erase/program is running
  150. * The erase/program process however will finish at some point
  151. * and may indicate failure then
  152. */
  153. static FLASH_Status FlashWaitReady(void)
  154. {
  155. FLASH_Status status;
  156. do
  157. status = FLASH_GetStatus();
  158. while(status == FLASH_BUSY);
  159. /* Return the operation status */
  160. return status;
  161. }
  162. /*!
  163. * \brief Erase FLASH Page at specified address.
  164. *
  165. * This routine is called by Stm32FlashWritePage to erase
  166. * before programming.
  167. *
  168. * \param page Page to erase.
  169. *
  170. * \return FLASH Status.
  171. *
  172. * Even for page erase, AR takes the memory address while
  173. * rm0316 ands pm0075 tell about the page as argument
  174. */
  175. static FLASH_Status FlashErasePage(uint32_t mem)
  176. {
  177. FLASH_Status rs = FLASH_COMPLETE;
  178. uint32_t current_page = ((uint32_t)mem - FLASH_BASE)/FLASH_PAGE_SIZE;
  179. uint32_t *addr = (uint32_t *)(current_page * FLASH_PAGE_SIZE);
  180. int i;
  181. for(i = 0; i < FLASH_PAGE_SIZE >> 2; i++)
  182. if (addr[i] != ((ERASED_PATTERN_16 << 16) | ERASED_PATTERN_16))
  183. break;
  184. if (i >= (FLASH_PAGE_SIZE >> 2))
  185. goto erase_done;
  186. /* Wait for last operation to be completed */
  187. rs = FlashWaitReady();
  188. if(rs == FLASH_COMPLETE) {
  189. #if defined(STM32F10X_XL)
  190. if ((current_page / FLASH_PAGE_SIZE) >255) {
  191. FLASH->CR2 = FLASH_CR_PER;
  192. FLASH->AR2 = mem;
  193. FLASH->CR2 = FLASH_CR_PER | FLASH_CR_STRT;
  194. rs = FlashWaitReady();
  195. FLASH->CR2 = 0;
  196. goto erase_done;
  197. }
  198. #endif
  199. /* if the previous operation is completed, proceed to erase the page */
  200. FLASH->CR = FLASH_CR_PER;
  201. FLASH->AR = mem;
  202. FLASH->CR = FLASH_CR_PER | FLASH_CR_STRT;
  203. rs = FlashWaitReady();
  204. FLASH->CR = 0;
  205. }
  206. erase_done:
  207. if (rs != FLASH_COMPLETE)
  208. pagelist[current_page/32] &= ~(1 <<(current_page%32));
  209. else
  210. pagelist[current_page/32] |= (1 <<(current_page%32));
  211. /* Return the Erase Status */
  212. return rs;
  213. }
  214. /*!
  215. * \brief Program any data to FLASH.
  216. *
  217. * This function writes data from source address to FLASH.
  218. *
  219. * \param dst Pointer to address anywhere in FLASH. Must be word
  220. * aligned
  221. * \param src Pointer to source data. With SRC == NULL, the region
  222. * is checked for write protection
  223. * \param len Number of bytes to be written/checked. Must be even.
  224. *
  225. * \return FLASH Status: FLASH_COMPLETE or appropriate error.
  226. */
  227. static FLASH_Status FlashWrite( void* dst, void* src, size_t len,
  228. FLASH_ERASE_MODE mode)
  229. {
  230. FLASH_Status rs = FLASH_COMPLETE;
  231. uint32_t wrpr = FLASH->WRPR; /* Old write protection state */
  232. uint32_t page_start, page_end;
  233. int i;
  234. void *wptr = dst;
  235. void *rptr = src;
  236. uint32_t length = len;
  237. if (len == 0)
  238. return FLASH_COMPLETE;
  239. /* Check boundaries */
  240. if ((((uint32_t)dst + len - 1) > FlashEnd()) || ((uint32_t)dst < FLASH_BASE)) {
  241. return FLASH_BOUNDARY;
  242. }
  243. /* Check for write protected sectors */
  244. page_start = ((uint32_t)dst - FLASH_BASE)/FLASH_PAGE_SIZE;
  245. page_end = (((uint32_t)dst + len -1) - FLASH_BASE)/FLASH_PAGE_SIZE;
  246. /* Write protection happens in 4 kiByte unites. The uppermost bit in
  247. FLASH->WRPR handles all remaining units*/
  248. #if FLASH_PAGE_SIZE == 1024
  249. for (i = page_start>>2; i <= page_end>>2; i++)
  250. #else
  251. for (i = page_start>>1; i <= page_end>>1; i++)
  252. #endif
  253. if (((i < 31) && ((wrpr & (1<<i)) == 0)) || ((i >= 31) && (wrpr & 0x80000000) == 0))
  254. return FLASH_ERROR_WRP;
  255. if (src == NULL)
  256. /* Only a check for write protection was requested */
  257. return FLASH_COMPLETE;
  258. /* Unlock related banks*/
  259. if (((uint32_t)dst - FLASH_BASE)/FLASH_PAGE_SIZE <256) {
  260. FLASH->KEYR = FLASH_KEY1;
  261. FLASH->KEYR = FLASH_KEY2;
  262. rs = FLASH->CR & FLASH_CR_LOCK;
  263. }
  264. #if defined(STM32F10X_XL)
  265. if (((uint32_t)dst + len - FLASH_BASE)/FLASH_PAGE_SIZE > 255) {
  266. FLASH->KEYR2 = FLASH_KEY1;
  267. FLASH->KEYR2 = FLASH_KEY2;
  268. rs |= FLASH->SR2;
  269. }
  270. #endif
  271. if (rs != FLASH_COMPLETE)
  272. return FLASH_LOCKED;
  273. while (length && (rs == FLASH_COMPLETE))
  274. {
  275. uint32_t current_page = ((uint32_t)wptr - FLASH_BASE)/FLASH_PAGE_SIZE;
  276. uint32_t current_length = length;
  277. uint32_t offset_in_page = (uint32_t)wptr % FLASH_PAGE_SIZE;
  278. int prepend = 0, append = 0;
  279. uint16_t prepend_data = 0, append_data = 0;
  280. if (length > FLASH_PAGE_SIZE)
  281. current_length = FLASH_PAGE_SIZE;
  282. length -= current_length;
  283. prepend = (offset_in_page & 1);
  284. if (prepend) {
  285. uint8_t saved_data = *(uint8_t*)wptr;
  286. if (saved_data != (ERASED_PATTERN_16 & 0xff))
  287. return FLASH_ERR_ALIGNMENT;
  288. prepend_data = (*(uint8_t*)( rptr)<< 8) | (*(uint8_t *)wptr);
  289. }
  290. else {
  291. append = (current_length &1);
  292. if(append) {
  293. uint8_t saved_data = *(uint8_t*)( wptr + current_length );
  294. if (saved_data != (ERASED_PATTERN_16 & 0xff))
  295. return FLASH_ERR_ALIGNMENT;
  296. append_data = *(uint8_t*)( rptr + current_length -1) | (saved_data << 8);
  297. }
  298. }
  299. /* Check if page needs erase*/
  300. if ((mode == FLASH_ERASE_ALWAYS) ||
  301. ((mode == FLASH_ERASE_FIRST_TOUCH) &&
  302. (((pagelist[current_page/32] & (1 <<(current_page%32))) == 0)))) {
  303. if (i < (FLASH_PAGE_SIZE>>1)) {
  304. rs = FlashErasePage((uint32_t)wptr);
  305. if (rs != FLASH_COMPLETE)
  306. /* Erase failed for any reason */
  307. goto done;
  308. }
  309. }
  310. /* Program the sector */
  311. rs = FlashWaitReady();
  312. if (rs != FLASH_COMPLETE)
  313. goto done;
  314. if (((uint32_t)wptr -FLASH_BASE)/FLASH_PAGE_SIZE <256)
  315. FLASH->CR = FLASH_CR_PG;
  316. #if defined(STM32F10X_XL)
  317. else
  318. FLASH->CR2 = FLASH_CR_PG;
  319. #endif
  320. if (prepend) {
  321. if(prepend_data != ERASED_PATTERN_16)
  322. *(volatile uint16_t*)((uint32_t)wptr & ~1) = prepend_data;
  323. current_length -= 1;
  324. wptr += 1;
  325. rptr += 1;
  326. }
  327. while (current_length > 1 && (rs == FLASH_COMPLETE)) {
  328. rs = FlashWaitReady();
  329. if(*(volatile uint16_t*)rptr != ERASED_PATTERN_16)
  330. *(volatile uint16_t*)wptr = *(volatile uint16_t*)rptr;
  331. current_length -=2;
  332. wptr += 2;
  333. rptr += 2;
  334. }
  335. if (append) {
  336. if(append_data != ERASED_PATTERN_16)
  337. *(volatile uint16_t*)(wptr) = append_data;
  338. current_length -= 1;
  339. wptr += 1;
  340. rptr += 1;
  341. }
  342. rs = FlashWaitReady();
  343. FLASH->CR = 0;
  344. if(rs != FLASH_COMPLETE)
  345. goto done;
  346. }
  347. rs = FlashWaitReady();
  348. /* Check the written data */
  349. wptr = dst;
  350. rptr = src;
  351. length = len;
  352. /* Align flash access to 4 Byte Boundary*/
  353. while (length && ((uint32_t)wptr & 3)) {
  354. if(*(volatile uint8_t*)wptr++ != *(uint8_t*)rptr++)
  355. goto cmp_err;
  356. length--;
  357. }
  358. /* Now compare word at a time*/
  359. while (length > 3) {
  360. if(*(volatile uint32_t*)wptr != *(uint32_t*)rptr)
  361. goto cmp_err;
  362. length -= 4;
  363. wptr += +4;
  364. rptr += +4;
  365. }
  366. /* Compare the rest */
  367. while (length) {
  368. if((*(volatile uint8_t*)wptr++) != *(uint8_t*)rptr++)
  369. goto cmp_err;
  370. length--;
  371. }
  372. goto done;
  373. cmp_err:
  374. rs = FLASH_COMPARE;
  375. done:
  376. /* Lock the FLASH again */
  377. FLASH->CR = FLASH_CR_LOCK;
  378. #if defined(STM32F10X_XL)
  379. FLASH->CR2 = FLASH_CR_LOCK;
  380. #endif
  381. return rs;
  382. }
  383. /*!
  384. * \brief Program any data to FLASH.
  385. *
  386. * This function writes data from source address to FLASH. Write to
  387. * configuration area, if configured, is denied.
  388. *
  389. * \param dst Pointer to address anywhere in FLASH. Must be word
  390. * aligned
  391. * \param src Pointer to source data. With SRC == NULL, the region
  392. * is checked for write protection
  393. * \param len Number of bytes to be written/checked. Must be even.
  394. *
  395. * \return FLASH Status: FLASH_COMPLETE or appropriate error.
  396. */
  397. FLASH_Status IapFlashWrite( void* dst, void* src, size_t len,
  398. FLASH_ERASE_MODE mode)
  399. {
  400. uint32_t iap_flash_end = FlashEnd();
  401. #if defined(NUT_CONFIG_STM32_IAP) && FLASH_CONF_SIZE > FLASH_PAGE_SIZE
  402. iap_flash_end -= FLASH_CONF_SIZE ;
  403. #elif defined(NUT_CONFIG_STM32_IAP)
  404. iap_flash_end -= FLASH_PAGE_SIZE ;
  405. #endif
  406. if (len == 0)
  407. return FLASH_COMPLETE;
  408. /* Check top boundary */
  409. if ((((uint32_t)dst + len - 1) > iap_flash_end ) || ((uint32_t)dst < FLASH_BASE))
  410. {
  411. return FLASH_BOUNDARY;
  412. }
  413. return FlashWrite(dst, src, len, mode);
  414. }
  415. /*!
  416. * \brief Get Upper limit of Flash.
  417. *
  418. * This function writes data from source address to FLASH. Write to
  419. * configuration area, if configured, is denied.
  420. *
  421. * \param NONE
  422. * \return Last Flash Address.
  423. */
  424. uint32_t IapFlashEnd(void)
  425. {
  426. #if defined(NUT_CONFIG_STM32_IAP) && FLASH_CONF_SIZE > FLASH_PAGE_SIZE
  427. return FlashEnd() - FLASH_CONF_SIZE;
  428. #elif defined(NUT_CONFIG_STM32_IAP)
  429. return FlashEnd() - FLASH_PAGE_SIZE;
  430. #else
  431. return FlashEnd();
  432. #endif
  433. }
  434. /*!
  435. * \brief Try to protect/unprotect the requested flash region.
  436. *
  437. * \param dst Pointer to address anywhere in FLASH.
  438. * \param len Length of region in bytes.
  439. * \param ena 0 disables write protection anything else write-protects.
  440. *
  441. * \return FLASH_Status: FLASH_COMPLETE or appropriate error.
  442. */
  443. FLASH_Status IapFlashWriteProtect(void *dst, size_t len, int ena)
  444. {
  445. uint32_t page_start, page_end;
  446. int i;
  447. FLASH_Status rs = FLASH_COMPLETE;
  448. uint32_t wrpr = FLASH->WRPR; /* Old write protection state */
  449. __IO uint16_t *WRP = &OB->WRP0;
  450. uint32_t iap_flash_end = FlashEnd();
  451. if (len == 0)
  452. return FLASH_COMPLETE;
  453. /* Check boundaries */
  454. if ((((uint32_t)dst+len) > iap_flash_end ) || ((uint32_t)dst < FLASH_BASE))
  455. {
  456. return FLASH_BOUNDARY;
  457. }
  458. /* Wait for last operation to be completed */
  459. rs = FlashWaitReady();
  460. if(rs != FLASH_COMPLETE)
  461. return rs;
  462. /* erase option bytes */
  463. /* set OPTWRE by wrinting key*/
  464. FLASH->OPTKEYR = FLASH_KEY1;
  465. FLASH->OPTKEYR = FLASH_KEY2;
  466. FLASH->CR = FLASH_CR_OPTER;
  467. FLASH->CR = FLASH_CR_OPTER | FLASH_CR_STRT;
  468. rs = FlashWaitReady();
  469. if(rs != FLASH_COMPLETE)
  470. return rs;
  471. FLASH->CR = FLASH_CR_OPTPG;
  472. OB->RDP = RDP_KEY;
  473. page_start = ((uint32_t)dst - FLASH_BASE)/FLASH_PAGE_SIZE;
  474. page_end = (((uint32_t)dst + len -1) - FLASH_BASE)/FLASH_PAGE_SIZE;
  475. rs = FlashWaitReady();
  476. #if FLASH_PAGE_SIZE == 1024
  477. for (i = page_start>>2; i <= page_end>>2; i++)
  478. #else
  479. for (i = page_start>>1; i <= page_end>>1; i++)
  480. #endif
  481. {
  482. if (i < 31) {
  483. if (ena)
  484. wrpr &= ~(1<<(i));
  485. else
  486. wrpr |= (1<<(i));
  487. }
  488. /* If one high page is write protected, protect all high pages*/
  489. else if (ena) wrpr &= ~0x80000000;
  490. }
  491. #if defined (STM32F10X_LD) || defined (STM32F10X_LD_VL)
  492. for(i = 0; i < 1 && rs == FLASH_COMPLETE; i++)
  493. #else
  494. for(i = 0; i < 4 && rs == FLASH_COMPLETE; i++)
  495. #endif
  496. {
  497. uint8_t val = (wrpr>>(8*i) && 0xff);
  498. uint16_t pval = ~val<<8 |val;
  499. if (val == 0xff)
  500. continue;
  501. rs = FlashWaitReady();
  502. if(rs != FLASH_COMPLETE)
  503. break;
  504. *WRP++ = pval;
  505. }
  506. rs = FlashWaitReady();
  507. FLASH->CR = 0;
  508. return rs;
  509. }
  510. /*!
  511. * \brief Nut/OS specific handling for parameters in FLASH.
  512. *
  513. * This function enables to read system specific parameters
  514. * from processors FLASH. The sectors used for storage are
  515. * configureable via nutconf.
  516. *
  517. * If multiple FLASH_CONF_SIZE fit into the FLASH_PAGE_SIZE,
  518. * implement a rolling scheme. The first FLASH_CONF_SIZE unit
  519. * in FLASH_PAGE_SIZE with with the uppermost word erased is
  520. * considered valid.
  521. *
  522. * \param pos Offset of parameter(s) in configured page(s).
  523. * \param data Pointer where to copy data from flash to.
  524. * \param len Number of bytes to be copied.
  525. *
  526. * \return FLASH_Status: FLASH_COMPLETE or appropriate error.
  527. */
  528. FLASH_Status Stm32FlashParamRead(uint32_t pos, void *data, size_t len)
  529. {
  530. uint32_t flash_conf_sector = FlashEnd() & ~(FLASH_PAGE_SIZE - 1);
  531. if (FLASH_CONF_SIZE > FLASH_PAGE_SIZE)
  532. return FLASH_ERR_CONF_LAYOUT;
  533. #if defined(FLASH_CONF_SIZE) && (FLASH_CONF_SIZE << 1) <= FLASH_PAGE_SIZE
  534. uint8_t conf_page = 0;
  535. uint16_t marker = *(uint16_t*) (flash_conf_sector + ((conf_page + 1) * FLASH_CONF_SIZE) - sizeof(ERASED_PATTERN_16));
  536. if (len == 0)
  537. return FLASH_COMPLETE;
  538. /* Check boundaries */
  539. if (pos + len + sizeof(ERASED_PATTERN_16) > FLASH_CONF_SIZE)
  540. {
  541. return FLASH_CONF_OVERFLOW;
  542. }
  543. /* Find configuration page in CONF_SECTOR*/
  544. while ((marker != ERASED_PATTERN_16) && (conf_page < ((FLASH_PAGE_SIZE/FLASH_CONF_SIZE) - 1 ))) {
  545. conf_page++;
  546. marker = *(uint32_t*)(flash_conf_sector + ((conf_page + 1)* FLASH_CONF_SIZE) - sizeof(ERASED_PATTERN_16));
  547. }
  548. if (marker != ERASED_PATTERN_16)
  549. /* no page sizes unit in CONF_SECTOR has a valid mark */
  550. return FLASH_ERR_CONF_LAYOUT;
  551. memcpy( data, (uint8_t *)((uint8_t*)flash_conf_sector + conf_page * FLASH_CONF_SIZE + pos), len);
  552. #else
  553. if (len == 0)
  554. return FLASH_COMPLETE;
  555. /* Check boundaries */
  556. if (pos + len > FLASH_PAGE_SIZE)
  557. {
  558. return FLASH_CONF_OVERFLOW;
  559. }
  560. memcpy( data, (uint8_t *)((uint8_t*)flash_conf_sector + pos), len);
  561. #endif
  562. /* Return success or fault code */
  563. return FLASH_COMPLETE;
  564. }
  565. /*!
  566. * \brief Nut/OS specific handling for parameters in FLASH.
  567. *
  568. * This function enables to store system specific parameters
  569. * in processors FLASH. The sectors used for storage are
  570. * configurable via nutconf.
  571. *
  572. * If multiple FLASH_CONF_SIZE fit into FLASH_PAGE_SIZE,
  573. * implement a rolling scheme. The first FLASH_CONF_SIZE unit
  574. * in FLASH_PAGE_SIZE with with the uppermost word erased is
  575. * considered valid.
  576. *
  577. * \param pos Offset of parameter(s) in configured page(s).
  578. * \param data Pointer to source data.
  579. * \param len Number of bytes to be written.
  580. *
  581. * \return FLASH_Status: FLASH_COMPLETE or appropriate error.
  582. */
  583. FLASH_Status Stm32FlashParamWrite(unsigned int pos, void *data,
  584. size_t len)
  585. {
  586. FLASH_Status rs = 0;
  587. uint8_t *buffer;
  588. void* flash_conf_sector = (void*)(FlashEnd() & ~(FLASH_PAGE_SIZE - 1));
  589. int i;
  590. uint8_t *mem, *src;
  591. if(FLASH_CONF_SIZE > FLASH_PAGE_SIZE)
  592. return FLASH_ERR_CONF_LAYOUT;
  593. #if defined(FLASH_CONF_SIZE) && (FLASH_CONF_SIZE << 1) <= FLASH_PAGE_SIZE
  594. uint8_t conf_page = 0;
  595. uint16_t marker = *(uint16_t*) (flash_conf_sector + ((conf_page +1) * FLASH_CONF_SIZE) - sizeof(ERASED_PATTERN_16));
  596. FLASH_ERASE_MODE mode;
  597. if (len == 0)
  598. return FLASH_COMPLETE;
  599. /* Check top boundaries */
  600. if (pos + len + sizeof(ERASED_PATTERN_16) > FLASH_CONF_SIZE)
  601. {
  602. return FLASH_BOUNDARY;
  603. }
  604. /* Find configuration page in CONF_SECTOR*/
  605. while ((marker != ERASED_PATTERN_16) && conf_page < ((FLASH_PAGE_SIZE/FLASH_CONF_SIZE) -1)) {
  606. conf_page++;
  607. marker = *(uint16_t*)(flash_conf_sector + ((conf_page + 1)* FLASH_CONF_SIZE) - sizeof(ERASED_PATTERN_16));
  608. }
  609. if (marker != ERASED_PATTERN_16) {
  610. /* no page sizes unit in CONF_SECTOR has a valid mark
  611. * Erase Sector and write provided data to position at first sector */
  612. rs = FlashWrite( flash_conf_sector + pos, data, len, FLASH_ERASE_ALWAYS);
  613. /* Return success or fault code */
  614. return rs;
  615. }
  616. /* Check if target area is erased.
  617. * It seems no C standard function provides this functionality!
  618. */
  619. mem = (uint8_t*) (flash_conf_sector + conf_page * FLASH_CONF_SIZE + pos);
  620. src = (uint8_t*) data;
  621. for (i = 0; i < len; i++) {
  622. if ((mem[i] != 0xff) && (mem[i] != src[i]))
  623. break;
  624. }
  625. if (i >= len) {
  626. /* Needed area is erased, simply write the data to the requested area*/
  627. rs = FlashWrite( flash_conf_sector + conf_page * FLASH_CONF_SIZE + pos, data, len, FLASH_ERASE_NEVER);
  628. return rs;
  629. }
  630. /* Check if content needs no update. */
  631. if (memcmp(flash_conf_sector + conf_page * FLASH_CONF_SIZE + pos, data, len) == 0)
  632. return FLASH_COMPLETE;
  633. /* Save configuration page in RAM and write updated data to next configuration page,
  634. * eventually erasing the sector wrapping to the first page
  635. */
  636. buffer = NutHeapAlloc(FLASH_CONF_SIZE);
  637. if (buffer == NULL)
  638. {
  639. /* Not enough memory */
  640. return FLASH_OUT_OF_MEMORY;
  641. }
  642. /* Get the content of the whole config page*/
  643. memcpy( buffer, flash_conf_sector + conf_page * FLASH_CONF_SIZE , FLASH_CONF_SIZE);
  644. /* Overwrite new data region*/
  645. memcpy (buffer + pos, data, len);
  646. conf_page++;
  647. mode = FLASH_ERASE_NEVER;
  648. if (conf_page < FLASH_PAGE_SIZE/FLASH_CONF_SIZE) {
  649. uint16_t indicator = (uint16_t)~ERASED_PATTERN_16;
  650. rs = FlashWrite( flash_conf_sector + conf_page * FLASH_CONF_SIZE - sizeof(indicator),
  651. &indicator, sizeof(indicator), FLASH_ERASE_NEVER);
  652. }
  653. else {
  654. /* All pages used, mark the sector as not yet erases to force erase*/
  655. FlashUntouch();
  656. conf_page = 0;
  657. mode = FLASH_ERASE_ALWAYS;
  658. }
  659. rs = FlashWrite( flash_conf_sector + conf_page * FLASH_CONF_SIZE , buffer, FLASH_CONF_SIZE, mode);
  660. #else
  661. /* Check top boundaries */
  662. if (pos + len > FLASH_PAGE_SIZE)
  663. {
  664. return FLASH_BOUNDARY;
  665. }
  666. /* Check if target area is erased.
  667. * It seems no C standard function provides this functionality!
  668. */
  669. mem = (uint8_t*) (flash_conf_sector + pos);
  670. src = (uint8_t*) data;
  671. for (i = 0; i < len; i++) {
  672. if ((mem[i] != 0xff) && (mem[i] != src[i]))
  673. break;
  674. }
  675. if (i >= len) {
  676. /* Needed area is erased, simply write the data to the requested area*/
  677. rs = FlashWrite( flash_conf_sector + pos, data, len, FLASH_ERASE_NEVER);
  678. return rs;
  679. }
  680. buffer = NutHeapAlloc(FLASH_CONF_SIZE);
  681. if (buffer == NULL)
  682. {
  683. /* Not enough memory */
  684. return FLASH_OUT_OF_MEMORY;
  685. }
  686. /* Get the content of the whole config page*/
  687. memcpy( buffer, flash_conf_sector , FLASH_PAGE_SIZE);
  688. /* Overwrite new data region*/
  689. memcpy (buffer + pos, data, len);
  690. rs = FlashWrite( flash_conf_sector, buffer, FLASH_PAGE_SIZE, FLASH_ERASE_ALWAYS);
  691. #endif
  692. NutHeapFree(buffer);
  693. /* Return success or fault code */
  694. return rs;
  695. }