flashc.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973
  1. /**
  2. * \file
  3. *
  4. * \brief FLASHC driver for AVR32 UC3.
  5. *
  6. * Copyright (c) 2009-2018 Microchip Technology Inc. and its subsidiaries.
  7. *
  8. * \asf_license_start
  9. *
  10. * \page License
  11. *
  12. * Subject to your compliance with these terms, you may use Microchip
  13. * software and any derivatives exclusively with Microchip products.
  14. * It is your responsibility to comply with third party license terms applicable
  15. * to your use of third party software (including open source software) that
  16. * may accompany Microchip software.
  17. *
  18. * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
  19. * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
  20. * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
  21. * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
  22. * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
  23. * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
  24. * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
  25. * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
  26. * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
  27. * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
  28. * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
  29. *
  30. * \asf_license_stop
  31. *
  32. */
  33. /*
  34. * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
  35. */
  36. #include <avr32/io.h>
  37. #include <stddef.h>
  38. #include "compiler.h"
  39. #include "flashc.h"
  40. /*! \name FLASHC Writable Bit-Field Registers
  41. */
  42. //! @{
  43. typedef union {
  44. unsigned long fcr;
  45. avr32_flashc_fcr_t FCR;
  46. } u_avr32_flashc_fcr_t;
  47. typedef union {
  48. unsigned long fcmd;
  49. avr32_flashc_fcmd_t FCMD;
  50. } u_avr32_flashc_fcmd_t;
  51. //! @}
  52. /*! \name Flash Properties
  53. */
  54. //! @{
  55. unsigned int flashc_get_flash_size(void)
  56. {
  57. #if (AVR32_FLASHC_H_VERSION >= 300)
  58. const uint16_t FLASH_SIZE[] = {
  59. 4,
  60. 8,
  61. 16,
  62. 32,
  63. 48,
  64. 64,
  65. 96,
  66. 128,
  67. 192,
  68. 256,
  69. 384,
  70. 512,
  71. 768,
  72. 1024,
  73. 2048,
  74. };
  75. return ((unsigned int)FLASH_SIZE[(AVR32_FLASHC.pr & AVR32_FLASHC_PR_FSZ_MASK)
  76. >> AVR32_FLASHC_PR_FSZ_OFFSET])<<10;
  77. #else // in older flashc version, FSZ is located in FSR register
  78. const uint16_t FLASH_SIZE[] = {
  79. 32,
  80. 64,
  81. 128,
  82. 256,
  83. 384,
  84. 512,
  85. 768,
  86. 1024,
  87. };
  88. return ((unsigned int)FLASH_SIZE[(AVR32_FLASHC.fsr & AVR32_FLASHC_FSR_FSZ_MASK)
  89. >> AVR32_FLASHC_FSR_FSZ_OFFSET]) << 10;
  90. #endif
  91. }
  92. unsigned int flashc_get_page_count(void)
  93. {
  94. return flashc_get_flash_size() / AVR32_FLASHC_PAGE_SIZE;
  95. }
  96. unsigned int flashc_get_page_count_per_region(void)
  97. {
  98. return flashc_get_page_count() / AVR32_FLASHC_REGIONS;
  99. }
  100. unsigned int flashc_get_page_region(int page_number)
  101. {
  102. return ((page_number >= 0) ? page_number
  103. : flashc_get_page_number()) / flashc_get_page_count_per_region();
  104. }
  105. unsigned int flashc_get_region_first_page_number(unsigned int region)
  106. {
  107. return region * flashc_get_page_count_per_region();
  108. }
  109. //! @}
  110. /*! \name FLASHC Control
  111. */
  112. //! @{
  113. unsigned int flashc_get_wait_state(void)
  114. {
  115. return (AVR32_FLASHC.fcr & AVR32_FLASHC_FCR_FWS_MASK) >> AVR32_FLASHC_FCR_FWS_OFFSET;
  116. }
  117. void flashc_set_wait_state(unsigned int wait_state)
  118. {
  119. u_avr32_flashc_fcr_t u_avr32_flashc_fcr = {AVR32_FLASHC.fcr};
  120. u_avr32_flashc_fcr.FCR.fws = wait_state;
  121. AVR32_FLASHC.fcr = u_avr32_flashc_fcr.fcr;
  122. }
  123. void flashc_set_bus_freq(unsigned int cpu_f_hz)
  124. {
  125. if (cpu_f_hz >= AVR32_FLASHC_FWS_0_MAX_FREQ) {
  126. // Set 1 WS.
  127. flashc_set_wait_state(1);
  128. } else {
  129. // Set 0 WS.
  130. flashc_set_wait_state(0);
  131. }
  132. }
  133. bool flashc_is_ready_int_enabled(void)
  134. {
  135. return ((AVR32_FLASHC.fcr & AVR32_FLASHC_FCR_FRDY_MASK) != 0);
  136. }
  137. void flashc_enable_ready_int(bool enable)
  138. {
  139. u_avr32_flashc_fcr_t u_avr32_flashc_fcr = {AVR32_FLASHC.fcr};
  140. u_avr32_flashc_fcr.FCR.frdy = (enable != false);
  141. AVR32_FLASHC.fcr = u_avr32_flashc_fcr.fcr;
  142. }
  143. bool flashc_is_lock_error_int_enabled(void)
  144. {
  145. return ((AVR32_FLASHC.fcr & AVR32_FLASHC_FCR_LOCKE_MASK) != 0);
  146. }
  147. void flashc_enable_lock_error_int(bool enable)
  148. {
  149. u_avr32_flashc_fcr_t u_avr32_flashc_fcr = {AVR32_FLASHC.fcr};
  150. u_avr32_flashc_fcr.FCR.locke = (enable != false);
  151. AVR32_FLASHC.fcr = u_avr32_flashc_fcr.fcr;
  152. }
  153. bool flashc_is_prog_error_int_enabled(void)
  154. {
  155. return ((AVR32_FLASHC.fcr & AVR32_FLASHC_FCR_PROGE_MASK) != 0);
  156. }
  157. void flashc_enable_prog_error_int(bool enable)
  158. {
  159. u_avr32_flashc_fcr_t u_avr32_flashc_fcr = {AVR32_FLASHC.fcr};
  160. u_avr32_flashc_fcr.FCR.proge = (enable != false);
  161. AVR32_FLASHC.fcr = u_avr32_flashc_fcr.fcr;
  162. }
  163. //! @}
  164. /*! \name FLASHC Status
  165. */
  166. //! @{
  167. bool flashc_is_ready(void)
  168. {
  169. return ((AVR32_FLASHC.fsr & AVR32_FLASHC_FSR_FRDY_MASK) != 0);
  170. }
  171. void flashc_default_wait_until_ready(void)
  172. {
  173. while (!flashc_is_ready());
  174. }
  175. void (*volatile flashc_wait_until_ready)(void) = flashc_default_wait_until_ready;
  176. /*! \brief Gets the error status of the FLASHC.
  177. *
  178. * \return The error status of the FLASHC built up from
  179. * \c AVR32_FLASHC_FSR_LOCKE_MASK and \c AVR32_FLASHC_FSR_PROGE_MASK.
  180. *
  181. * \warning This hardware error status is cleared by all functions reading the
  182. * Flash Status Register (FSR). This function is therefore not part of
  183. * the driver's API which instead presents \ref flashc_is_lock_error
  184. * and \ref flashc_is_programming_error.
  185. */
  186. static unsigned int flashc_get_error_status(void)
  187. {
  188. return AVR32_FLASHC.fsr & (AVR32_FLASHC_FSR_LOCKE_MASK |
  189. AVR32_FLASHC_FSR_PROGE_MASK);
  190. }
  191. //! Sticky error status of the FLASHC.
  192. //! This variable is updated by functions that issue FLASHC commands. It
  193. //! contains the cumulated FLASHC error status of all the FLASHC commands issued
  194. //! by a function.
  195. static unsigned int flashc_error_status = 0;
  196. bool flashc_is_lock_error(void)
  197. {
  198. return ((flashc_error_status & AVR32_FLASHC_FSR_LOCKE_MASK) != 0);
  199. }
  200. bool flashc_is_programming_error(void)
  201. {
  202. return ((flashc_error_status & AVR32_FLASHC_FSR_PROGE_MASK) != 0);
  203. }
  204. //! @}
  205. /*! \name FLASHC Command Control
  206. */
  207. //! @{
  208. unsigned int flashc_get_command(void)
  209. {
  210. return (AVR32_FLASHC.fcmd & AVR32_FLASHC_FCMD_CMD_MASK) >> AVR32_FLASHC_FCMD_CMD_OFFSET;
  211. }
  212. unsigned int flashc_get_page_number(void)
  213. {
  214. return (AVR32_FLASHC.fcmd & AVR32_FLASHC_FCMD_PAGEN_MASK) >> AVR32_FLASHC_FCMD_PAGEN_OFFSET;
  215. }
  216. void flashc_issue_command(unsigned int command, int page_number)
  217. {
  218. u_avr32_flashc_fcmd_t u_avr32_flashc_fcmd;
  219. flashc_wait_until_ready();
  220. u_avr32_flashc_fcmd.fcmd = AVR32_FLASHC.fcmd;
  221. u_avr32_flashc_fcmd.FCMD.cmd = command;
  222. if (page_number >= 0) {
  223. u_avr32_flashc_fcmd.FCMD.pagen = page_number;
  224. }
  225. u_avr32_flashc_fcmd.FCMD.key = AVR32_FLASHC_FCMD_KEY_KEY;
  226. AVR32_FLASHC.fcmd = u_avr32_flashc_fcmd.fcmd;
  227. flashc_error_status = flashc_get_error_status();
  228. flashc_wait_until_ready();
  229. }
  230. //! @}
  231. /*! \name FLASHC Global Commands
  232. */
  233. //! @{
  234. void flashc_no_operation(void)
  235. {
  236. flashc_issue_command(AVR32_FLASHC_FCMD_CMD_NOP, -1);
  237. }
  238. void flashc_erase_all(void)
  239. {
  240. flashc_issue_command(AVR32_FLASHC_FCMD_CMD_EA, -1);
  241. }
  242. //! @}
  243. /*! \name FLASHC Protection Mechanisms
  244. */
  245. //! @{
  246. bool flashc_is_security_bit_active(void)
  247. {
  248. return ((AVR32_FLASHC.fsr & AVR32_FLASHC_FSR_SECURITY_MASK) != 0);
  249. }
  250. void flashc_activate_security_bit(void)
  251. {
  252. flashc_issue_command(AVR32_FLASHC_FCMD_CMD_SSB, -1);
  253. }
  254. unsigned int flashc_get_bootloader_protected_size(void)
  255. {
  256. unsigned int bootprot = (1 << AVR32_FLASHC_FGPFRLO_BOOTPROT_SIZE) - 1 -
  257. flashc_read_gp_fuse_bitfield(AVR32_FLASHC_FGPFRLO_BOOTPROT_OFFSET,
  258. AVR32_FLASHC_FGPFRLO_BOOTPROT_SIZE);
  259. return (bootprot) ? AVR32_FLASHC_PAGE_SIZE << bootprot : 0;
  260. }
  261. unsigned int flashc_set_bootloader_protected_size(unsigned int bootprot_size)
  262. {
  263. flashc_set_gp_fuse_bitfield(AVR32_FLASHC_FGPFRLO_BOOTPROT_OFFSET,
  264. AVR32_FLASHC_FGPFRLO_BOOTPROT_SIZE,
  265. (1 << AVR32_FLASHC_FGPFRLO_BOOTPROT_SIZE) - 1 -
  266. ((bootprot_size) ?
  267. 32 - clz((((min(max(bootprot_size, AVR32_FLASHC_PAGE_SIZE << 1),
  268. AVR32_FLASHC_PAGE_SIZE <<
  269. ((1 << AVR32_FLASHC_FGPFRLO_BOOTPROT_SIZE) - 1)) +
  270. AVR32_FLASHC_PAGE_SIZE - 1) /
  271. AVR32_FLASHC_PAGE_SIZE) << 1) - 1) - 1 :
  272. 0));
  273. return flashc_get_bootloader_protected_size();
  274. }
  275. bool flashc_is_external_privileged_fetch_locked(void)
  276. {
  277. return (!flashc_read_gp_fuse_bit(AVR32_FLASHC_FGPFRLO_EPFL_OFFSET));
  278. }
  279. void flashc_lock_external_privileged_fetch(bool lock)
  280. {
  281. flashc_set_gp_fuse_bit(AVR32_FLASHC_FGPFRLO_EPFL_OFFSET, !lock);
  282. }
  283. bool flashc_is_page_region_locked(int page_number)
  284. {
  285. return flashc_is_region_locked(flashc_get_page_region(page_number));
  286. }
  287. bool flashc_is_region_locked(unsigned int region)
  288. {
  289. return ((AVR32_FLASHC.fsr & AVR32_FLASHC_FSR_LOCK0_MASK << (region & (AVR32_FLASHC_REGIONS - 1))) != 0);
  290. }
  291. void flashc_lock_page_region(int page_number, bool lock)
  292. {
  293. flashc_issue_command((lock) ? AVR32_FLASHC_FCMD_CMD_LP : AVR32_FLASHC_FCMD_CMD_UP, page_number);
  294. }
  295. void flashc_lock_region(unsigned int region, bool lock)
  296. {
  297. flashc_lock_page_region(flashc_get_region_first_page_number(region), lock);
  298. }
  299. void flashc_lock_all_regions(bool lock)
  300. {
  301. unsigned int error_status = 0;
  302. unsigned int region = AVR32_FLASHC_REGIONS;
  303. while (region) {
  304. flashc_lock_region(--region, lock);
  305. error_status |= flashc_error_status;
  306. }
  307. flashc_error_status = error_status;
  308. }
  309. //! @}
  310. /*! \name Access to General-Purpose Fuses
  311. */
  312. //! @{
  313. bool flashc_read_gp_fuse_bit(unsigned int gp_fuse_bit)
  314. {
  315. return ((flashc_read_all_gp_fuses() & 1ULL << (gp_fuse_bit & 0x3F)) != 0);
  316. }
  317. uint64_t flashc_read_gp_fuse_bitfield(unsigned int pos, unsigned int width)
  318. {
  319. return flashc_read_all_gp_fuses() >> (pos & 0x3F) & ((1ULL << min(width, 64)) - 1);
  320. }
  321. uint8_t flashc_read_gp_fuse_byte(unsigned int gp_fuse_byte)
  322. {
  323. return flashc_read_all_gp_fuses() >> ((gp_fuse_byte & 0x07) << 3);
  324. }
  325. uint64_t flashc_read_all_gp_fuses(void)
  326. {
  327. return AVR32_FLASHC.fgpfrlo | (uint64_t)AVR32_FLASHC.fgpfrhi << 32;
  328. }
  329. bool flashc_erase_gp_fuse_bit(unsigned int gp_fuse_bit, bool check)
  330. {
  331. flashc_issue_command(AVR32_FLASHC_FCMD_CMD_EGPB, gp_fuse_bit & 0x3F);
  332. return (check) ? flashc_read_gp_fuse_bit(gp_fuse_bit) : true;
  333. }
  334. bool flashc_erase_gp_fuse_bitfield(unsigned int pos, unsigned int width, bool check)
  335. {
  336. unsigned int error_status = 0;
  337. unsigned int gp_fuse_bit;
  338. pos &= 0x3F;
  339. width = min(width, 64);
  340. for (gp_fuse_bit = pos; gp_fuse_bit < pos + width; gp_fuse_bit++) {
  341. flashc_erase_gp_fuse_bit(gp_fuse_bit, false);
  342. error_status |= flashc_error_status;
  343. }
  344. flashc_error_status = error_status;
  345. return (check) ? (flashc_read_gp_fuse_bitfield(pos, width) == (1ULL << width) - 1) : true;
  346. }
  347. bool flashc_erase_gp_fuse_byte(unsigned int gp_fuse_byte, bool check)
  348. {
  349. unsigned int error_status;
  350. unsigned int current_gp_fuse_byte;
  351. uint64_t value = flashc_read_all_gp_fuses();
  352. flashc_erase_all_gp_fuses(false);
  353. error_status = flashc_error_status;
  354. for (current_gp_fuse_byte = 0; current_gp_fuse_byte < 8; current_gp_fuse_byte++, value >>= 8) {
  355. if (current_gp_fuse_byte != gp_fuse_byte) {
  356. flashc_write_gp_fuse_byte(current_gp_fuse_byte, value);
  357. error_status |= flashc_error_status;
  358. }
  359. }
  360. flashc_error_status = error_status;
  361. return (check) ? (flashc_read_gp_fuse_byte(gp_fuse_byte) == 0xFF) : true;
  362. }
  363. bool flashc_erase_all_gp_fuses(bool check)
  364. {
  365. flashc_issue_command(AVR32_FLASHC_FCMD_CMD_EAGPF, -1);
  366. return (check) ? (flashc_read_all_gp_fuses() == 0xFFFFFFFFFFFFFFFFULL) : true;
  367. }
  368. void flashc_write_gp_fuse_bit(unsigned int gp_fuse_bit, bool value)
  369. {
  370. if (!value) {
  371. flashc_issue_command(AVR32_FLASHC_FCMD_CMD_WGPB, gp_fuse_bit & 0x3F);
  372. }
  373. }
  374. void flashc_write_gp_fuse_bitfield(unsigned int pos, unsigned int width, uint64_t value)
  375. {
  376. unsigned int error_status = 0;
  377. unsigned int gp_fuse_bit;
  378. pos &= 0x3F;
  379. width = min(width, 64);
  380. for (gp_fuse_bit = pos; gp_fuse_bit < pos + width; gp_fuse_bit++, value >>= 1) {
  381. flashc_write_gp_fuse_bit(gp_fuse_bit, value & 0x01);
  382. error_status |= flashc_error_status;
  383. }
  384. flashc_error_status = error_status;
  385. }
  386. void flashc_write_gp_fuse_byte(unsigned int gp_fuse_byte, uint8_t value)
  387. {
  388. flashc_issue_command(AVR32_FLASHC_FCMD_CMD_PGPFB, (gp_fuse_byte & 0x07) | value << 3);
  389. }
  390. void flashc_write_all_gp_fuses(uint64_t value)
  391. {
  392. unsigned int error_status = 0;
  393. unsigned int gp_fuse_byte;
  394. for (gp_fuse_byte = 0; gp_fuse_byte < 8; gp_fuse_byte++, value >>= 8) {
  395. flashc_write_gp_fuse_byte(gp_fuse_byte, value);
  396. error_status |= flashc_error_status;
  397. }
  398. flashc_error_status = error_status;
  399. }
  400. void flashc_set_gp_fuse_bit(unsigned int gp_fuse_bit, bool value)
  401. {
  402. if (value) {
  403. flashc_erase_gp_fuse_bit(gp_fuse_bit, false);
  404. } else {
  405. flashc_write_gp_fuse_bit(gp_fuse_bit, false);
  406. }
  407. }
  408. void flashc_set_gp_fuse_bitfield(unsigned int pos, unsigned int width, uint64_t value)
  409. {
  410. unsigned int error_status = 0;
  411. unsigned int gp_fuse_bit;
  412. pos &= 0x3F;
  413. width = min(width, 64);
  414. for (gp_fuse_bit = pos; gp_fuse_bit < pos + width; gp_fuse_bit++, value >>= 1) {
  415. flashc_set_gp_fuse_bit(gp_fuse_bit, value & 0x01);
  416. error_status |= flashc_error_status;
  417. }
  418. flashc_error_status = error_status;
  419. }
  420. void flashc_set_gp_fuse_byte(unsigned int gp_fuse_byte, uint8_t value)
  421. {
  422. unsigned int error_status;
  423. switch (value) {
  424. case 0xFF:
  425. flashc_erase_gp_fuse_byte(gp_fuse_byte, false);
  426. break;
  427. case 0x00:
  428. flashc_write_gp_fuse_byte(gp_fuse_byte, 0x00);
  429. break;
  430. default:
  431. flashc_erase_gp_fuse_byte(gp_fuse_byte, false);
  432. error_status = flashc_error_status;
  433. flashc_write_gp_fuse_byte(gp_fuse_byte, value);
  434. flashc_error_status |= error_status;
  435. break;
  436. }
  437. }
  438. void flashc_set_all_gp_fuses(uint64_t value)
  439. {
  440. unsigned int error_status;
  441. switch (value) {
  442. case 0xFFFFFFFFFFFFFFFFULL:
  443. flashc_erase_all_gp_fuses(false);
  444. break;
  445. case 0x0000000000000000ULL:
  446. flashc_write_all_gp_fuses(0x0000000000000000ULL);
  447. break;
  448. default:
  449. flashc_erase_all_gp_fuses(false);
  450. error_status = flashc_error_status;
  451. flashc_write_all_gp_fuses(value);
  452. flashc_error_status |= error_status;
  453. break;
  454. }
  455. }
  456. //! @}
  457. /*! \name Access to Flash Pages
  458. */
  459. //! @{
  460. void flashc_clear_page_buffer(void)
  461. {
  462. flashc_issue_command(AVR32_FLASHC_FCMD_CMD_CPB, -1);
  463. }
  464. bool flashc_is_page_erased(void)
  465. {
  466. return ((AVR32_FLASHC.fsr & AVR32_FLASHC_FSR_QPRR_MASK) != 0);
  467. }
  468. bool flashc_quick_page_read(int page_number)
  469. {
  470. flashc_issue_command(AVR32_FLASHC_FCMD_CMD_QPR, page_number);
  471. return flashc_is_page_erased();
  472. }
  473. bool flashc_erase_page(int page_number, bool check)
  474. {
  475. bool page_erased = true;
  476. flashc_issue_command(AVR32_FLASHC_FCMD_CMD_EP, page_number);
  477. if (check) {
  478. unsigned int error_status = flashc_error_status;
  479. page_erased = flashc_quick_page_read(-1);
  480. flashc_error_status |= error_status;
  481. }
  482. return page_erased;
  483. }
  484. bool flashc_erase_all_pages(bool check)
  485. {
  486. bool all_pages_erased = true;
  487. unsigned int error_status = 0;
  488. unsigned int page_number = flashc_get_page_count();
  489. while (page_number) {
  490. all_pages_erased &= flashc_erase_page(--page_number, check);
  491. error_status |= flashc_error_status;
  492. }
  493. flashc_error_status = error_status;
  494. return all_pages_erased;
  495. }
  496. void flashc_write_page(int page_number)
  497. {
  498. flashc_issue_command(AVR32_FLASHC_FCMD_CMD_WP, page_number);
  499. }
  500. bool flashc_quick_user_page_read(void)
  501. {
  502. flashc_issue_command(AVR32_FLASHC_FCMD_CMD_QPRUP, -1);
  503. return flashc_is_page_erased();
  504. }
  505. bool flashc_erase_user_page(bool check)
  506. {
  507. flashc_issue_command(AVR32_FLASHC_FCMD_CMD_EUP, -1);
  508. return (check) ? flashc_quick_user_page_read() : true;
  509. }
  510. void flashc_write_user_page(void)
  511. {
  512. flashc_issue_command(AVR32_FLASHC_FCMD_CMD_WUP, -1);
  513. }
  514. volatile void *flashc_memset8(volatile void *dst, uint8_t src, size_t nbytes, bool erase)
  515. {
  516. return flashc_memset16(dst, src | (uint16_t)src << 8, nbytes, erase);
  517. }
  518. volatile void *flashc_memset16(volatile void *dst, uint16_t src, size_t nbytes, bool erase)
  519. {
  520. return flashc_memset32(dst, src | (uint32_t)src << 16, nbytes, erase);
  521. }
  522. volatile void *flashc_memset32(volatile void *dst, uint32_t src, size_t nbytes, bool erase)
  523. {
  524. return flashc_memset64(dst, src | (uint64_t)src << 32, nbytes, erase);
  525. }
  526. volatile void *flashc_memset64(volatile void *dst, uint64_t src, size_t nbytes, bool erase)
  527. {
  528. // Use aggregated pointers to have several alignments available for a same address.
  529. UnionCVPtr flash_array_end;
  530. UnionVPtr dest;
  531. Union64 source = {0};
  532. StructCVPtr dest_end;
  533. UnionCVPtr flash_page_source_end;
  534. bool incomplete_flash_page_end;
  535. Union64 flash_dword;
  536. UnionVPtr tmp;
  537. unsigned int error_status = 0;
  538. unsigned int i;
  539. // Reformat arguments.
  540. flash_array_end.u8ptr = AVR32_FLASH + flashc_get_flash_size();
  541. dest.u8ptr = dst;
  542. for (i = (Get_align((uint32_t)dest.u8ptr, sizeof(uint64_t)) - 1) & (sizeof(uint64_t) - 1);
  543. src; i = (i - 1) & (sizeof(uint64_t) - 1)) {
  544. source.u8[i] = src;
  545. src >>= 8;
  546. }
  547. dest_end.u8ptr = dest.u8ptr + nbytes;
  548. // If destination is outside flash, go to next flash page if any.
  549. if (dest.u8ptr < AVR32_FLASH) {
  550. dest.u8ptr = AVR32_FLASH;
  551. } else if (flash_array_end.u8ptr <= dest.u8ptr && dest.u8ptr < AVR32_FLASHC_USER_PAGE) {
  552. dest.u8ptr = AVR32_FLASHC_USER_PAGE;
  553. }
  554. // If end of destination is outside flash, move it to the end of the previous flash page if any.
  555. if (dest_end.u8ptr > AVR32_FLASHC_USER_PAGE + AVR32_FLASHC_USER_PAGE_SIZE) {
  556. dest_end.u8ptr = AVR32_FLASHC_USER_PAGE + AVR32_FLASHC_USER_PAGE_SIZE;
  557. } else if (AVR32_FLASHC_USER_PAGE >= dest_end.u8ptr && dest_end.u8ptr > flash_array_end.u8ptr) {
  558. dest_end.u8ptr = flash_array_end.u8ptr;
  559. }
  560. // Align each end of destination pointer with its natural boundary.
  561. dest_end.u16ptr = (uint16_t *)Align_down((uint32_t)dest_end.u8ptr, sizeof(uint16_t));
  562. dest_end.u32ptr = (uint32_t *)Align_down((uint32_t)dest_end.u16ptr, sizeof(uint32_t));
  563. dest_end.u64ptr = (uint64_t *)Align_down((uint32_t)dest_end.u32ptr, sizeof(uint64_t));
  564. // While end of destination is not reached...
  565. while (dest.u8ptr < dest_end.u8ptr) {
  566. // Clear the page buffer in order to prepare data for a flash page write.
  567. flashc_clear_page_buffer();
  568. error_status |= flashc_error_status;
  569. // Determine where the source data will end in the current flash page.
  570. flash_page_source_end.u64ptr =
  571. (uint64_t *)min((uint32_t)dest_end.u64ptr,
  572. Align_down((uint32_t)dest.u8ptr, AVR32_FLASHC_PAGE_SIZE) + AVR32_FLASHC_PAGE_SIZE);
  573. // Determine if the current destination page has an incomplete end.
  574. incomplete_flash_page_end = (Align_down((uint32_t)dest.u8ptr, AVR32_FLASHC_PAGE_SIZE) >=
  575. Align_down((uint32_t)dest_end.u8ptr, AVR32_FLASHC_PAGE_SIZE));
  576. // Use a flash double-word buffer to manage unaligned accesses.
  577. flash_dword.u64 = source.u64;
  578. // If destination does not point to the beginning of the current flash page...
  579. if (!Test_align((uint32_t)dest.u8ptr, AVR32_FLASHC_PAGE_SIZE)) {
  580. // Fill the beginning of the page buffer with the current flash page data.
  581. // This is required by the hardware, even if page erase is not requested,
  582. // in order to be able to write successfully to erased parts of flash
  583. // pages that have already been written to.
  584. for (tmp.u8ptr = (uint8_t *)Align_down((uint32_t)dest.u8ptr, AVR32_FLASHC_PAGE_SIZE);
  585. tmp.u64ptr < (uint64_t *)Align_down((uint32_t)dest.u8ptr, sizeof(uint64_t));
  586. tmp.u64ptr++) {
  587. *tmp.u64ptr = *tmp.u64ptr;
  588. }
  589. // If destination is not 64-bit aligned...
  590. if (!Test_align((uint32_t)dest.u8ptr, sizeof(uint64_t))) {
  591. // Fill the beginning of the flash double-word buffer with the current
  592. // flash page data.
  593. // This is required by the hardware, even if page erase is not
  594. // requested, in order to be able to write successfully to erased parts
  595. // of flash pages that have already been written to.
  596. for (i = 0; i < Get_align((uint32_t)dest.u8ptr, sizeof(uint64_t)); i++) {
  597. flash_dword.u8[i] = *tmp.u8ptr++;
  598. }
  599. // Align the destination pointer with its 64-bit boundary.
  600. dest.u64ptr = (uint64_t *)Align_down((uint32_t)dest.u8ptr, sizeof(uint64_t));
  601. // If the current destination double-word is not the last one...
  602. if (dest.u64ptr < dest_end.u64ptr) {
  603. // Write the flash double-word buffer to the page buffer and reinitialize it.
  604. *dest.u64ptr++ = flash_dword.u64;
  605. flash_dword.u64 = source.u64;
  606. }
  607. }
  608. }
  609. // Write the source data to the page buffer with 64-bit alignment.
  610. for (i = flash_page_source_end.u64ptr - dest.u64ptr; i; i--) {
  611. *dest.u64ptr++ = source.u64;
  612. }
  613. // If the current destination page has an incomplete end...
  614. if (incomplete_flash_page_end) {
  615. // This is required by the hardware, even if page erase is not requested,
  616. // in order to be able to write successfully to erased parts of flash
  617. // pages that have already been written to.
  618. {
  619. tmp.u8ptr = (volatile uint8_t *)dest_end.u8ptr;
  620. // If end of destination is not 64-bit aligned...
  621. if (!Test_align((uint32_t)dest_end.u8ptr, sizeof(uint64_t))) {
  622. // Fill the end of the flash double-word buffer with the current flash page data.
  623. for (i = Get_align((uint32_t)dest_end.u8ptr, sizeof(uint64_t)); i < sizeof(uint64_t); i++)
  624. flash_dword.u8[i] = *tmp.u8ptr++;
  625. // Write the flash double-word buffer to the page buffer.
  626. *dest.u64ptr++ = flash_dword.u64;
  627. }
  628. // Fill the end of the page buffer with the current flash page data.
  629. for (; !Test_align((uint32_t)tmp.u64ptr, AVR32_FLASHC_PAGE_SIZE); tmp.u64ptr++) {
  630. *tmp.u64ptr = *tmp.u64ptr;
  631. }
  632. }
  633. }
  634. // If the current flash page is in the flash array...
  635. if (dest.u8ptr <= AVR32_FLASHC_USER_PAGE) {
  636. // Erase the current page if requested and write it from the page buffer.
  637. if (erase) {
  638. flashc_erase_page(-1, false);
  639. error_status |= flashc_error_status;
  640. }
  641. flashc_write_page(-1);
  642. error_status |= flashc_error_status;
  643. // If the end of the flash array is reached, go to the User page.
  644. if (dest.u8ptr >= flash_array_end.u8ptr) {
  645. dest.u8ptr = AVR32_FLASHC_USER_PAGE;
  646. }
  647. } else {
  648. // Erase the User page if requested and write it from the page buffer.
  649. if (erase) {
  650. flashc_erase_user_page(false);
  651. error_status |= flashc_error_status;
  652. }
  653. flashc_write_user_page();
  654. error_status |= flashc_error_status;
  655. }
  656. }
  657. // Update the FLASHC error status.
  658. flashc_error_status = error_status;
  659. // Return the initial destination pointer as the standard memset function does.
  660. return dst;
  661. }
  662. volatile void *flashc_memcpy(volatile void *dst, const void *src, size_t nbytes, bool erase)
  663. {
  664. uint16_t page_pos;
  665. Union64 flash_dword;
  666. uint8_t i;
  667. bool b_user_page;
  668. unsigned int error_status = 0;
  669. uint8_t* flash_add;
  670. uint8_t* dest_add=(uint8_t*)dst;
  671. const uint8_t* src_buf=(const uint8_t*)src;
  672. // Copy area must be in flash array or flash user page
  673. Assert( (((uint8_t *)dst >= AVR32_FLASH)
  674. && (((uint8_t *)dst + nbytes) <= (AVR32_FLASH + flashc_get_flash_size())))
  675. || (((uint8_t *)dst >= AVR32_FLASHC_USER_PAGE)
  676. && (((uint8_t *)dst + nbytes) <= (AVR32_FLASHC_USER_PAGE + AVR32_FLASHC_USER_PAGE_SIZE))) );
  677. b_user_page = (volatile uint8_t *)dst >= AVR32_FLASHC_USER_PAGE;
  678. flash_add = (uint8_t*)((uint32_t)dest_add - ((uint32_t)dest_add % AVR32_FLASHC_PAGE_SIZE));
  679. while (nbytes) {
  680. // Clear the page buffer in order to prepare data for a flash page write.
  681. flashc_clear_page_buffer();
  682. error_status |= flashc_error_status;
  683. // Loop in the page
  684. for (page_pos=0; page_pos<AVR32_FLASHC_PAGE_SIZE; page_pos+=sizeof(uint64_t) ) {
  685. // Read the flash double-word buffer
  686. flash_dword.u64 = *(volatile uint64_t*)flash_add;
  687. // Update double-word if necessary
  688. for (i = 0; i < sizeof(uint64_t); i++) {
  689. if (nbytes && (flash_add == dest_add)) {
  690. // Update page with data source
  691. flash_dword.u8[i] = *src_buf++;
  692. dest_add++;
  693. nbytes--;
  694. }
  695. flash_add++;
  696. }
  697. // Write the flash double-word buffer to the page buffer.
  698. *(volatile uint64_t*)((uint32_t)flash_add - sizeof(uint64_t))= flash_dword.u64;
  699. }
  700. // Erase the current page if requested and write it from the page buffer.
  701. if (erase) {
  702. (b_user_page)? flashc_erase_user_page(false) : flashc_erase_page(-1, false);
  703. error_status |= flashc_error_status;
  704. }
  705. // Write the page
  706. (b_user_page)? flashc_write_user_page() : flashc_write_page(-1);
  707. error_status |= flashc_error_status;
  708. }
  709. // Update the FLASHC error status.
  710. flashc_error_status = error_status;
  711. // Return the initial destination pointer as the standard memcpy function does.
  712. return dst;
  713. }
  714. #if UC3C
  715. void flashc_set_flash_waitstate_and_readmode(unsigned long cpu_f_hz)
  716. {
  717. //! Device-specific data
  718. #undef AVR32_FLASHC_FWS_0_MAX_FREQ
  719. #undef AVR32_FLASHC_FWS_1_MAX_FREQ
  720. #undef AVR32_FLASHC_HSEN_FWS_0_MAX_FREQ
  721. #undef AVR32_FLASHC_HSEN_FWS_1_MAX_FREQ
  722. #define AVR32_FLASHC_FWS_0_MAX_FREQ 33000000
  723. #define AVR32_FLASHC_FWS_1_MAX_FREQ 66000000
  724. #define AVR32_FLASHC_HSEN_FWS_0_MAX_FREQ 33000000
  725. #define AVR32_FLASHC_HSEN_FWS_1_MAX_FREQ 72000000
  726. // These defines are missing from or wrong in the toolchain header files uc3cxxx.h
  727. // Put a Bugzilla
  728. if (cpu_f_hz > AVR32_FLASHC_HSEN_FWS_0_MAX_FREQ) { // > 33MHz
  729. // Set a wait-state
  730. flashc_set_wait_state(1);
  731. if (cpu_f_hz <= AVR32_FLASHC_FWS_1_MAX_FREQ) { // <= 66MHz and >33Mhz
  732. // Disable the high-speed read mode.
  733. flashc_issue_command(AVR32_FLASHC_FCMD_CMD_HSDIS, -1);
  734. } else { // > 66Mhz
  735. // Enable the high-speed read mode.
  736. flashc_issue_command(AVR32_FLASHC_FCMD_CMD_HSEN, -1);
  737. }
  738. } else { // <= 33 MHz
  739. // Disable wait-state
  740. flashc_set_wait_state(0);
  741. // Disable the high-speed read mode.
  742. flashc_issue_command(AVR32_FLASHC_FCMD_CMD_HSDIS, -1);
  743. }
  744. }
  745. #endif // UC3C device-specific implementation
  746. //! @}