Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

581 lines
15KB

  1. /* Teensyduino Core Library
  2. * http://www.pjrc.com/teensy/
  3. * Copyright (c) 2017 PJRC.COM, LLC.
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining
  6. * a copy of this software and associated documentation files (the
  7. * "Software"), to deal in the Software without restriction, including
  8. * without limitation the rights to use, copy, modify, merge, publish,
  9. * distribute, sublicense, and/or sell copies of the Software, and to
  10. * permit persons to whom the Software is furnished to do so, subject to
  11. * the following conditions:
  12. *
  13. * 1. The above copyright notice and this permission notice shall be
  14. * included in all copies or substantial portions of the Software.
  15. *
  16. * 2. If the Software is incorporated into a build system that allows
  17. * selection among a list of target devices, then similar target
  18. * devices manufactured by PJRC.COM must be included in the list of
  19. * target devices and selectable in the same manner.
  20. *
  21. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  22. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  24. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  25. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  26. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  27. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  28. * SOFTWARE.
  29. */
  30. #include "kinetis.h"
  31. #include <avr/eeprom.h>
  32. //#include "HardwareSerial.h"
  33. #if F_CPU > 120000000 && defined(__MK66FX1M0__)
  34. #include "core_pins.h" // delayMicroseconds()
  35. #endif
  36. #if defined(__MK20DX128__) || defined(__MK20DX256__)
  37. #define EEPROM_MAX 2048
  38. #define EEPARTITION 0x03 // all 32K dataflash for EEPROM, none for Data
  39. #define EEESPLIT 0x30 // must be 0x30 on these chips
  40. #elif defined(__MK64FX512__)
  41. #define EEPROM_MAX 4096
  42. #define EEPARTITION 0x05 // all 128K dataflash for EEPROM
  43. #define EEESPLIT 0x10 // best endurance: 0x00 = first 12%, 0x10 = first 25%, 0x30 = all equal
  44. #elif defined(__MK66FX1M0__)
  45. #define EEPROM_MAX 4096
  46. #define EEPARTITION 0x05 // 128K dataflash for EEPROM, 128K for Data
  47. #define EEESPLIT 0x10 // best endurance: 0x00 = first 12%, 0x10 = first 25%, 0x30 = all equal
  48. #elif defined(__MKL26Z64__)
  49. #define EEPROM_MAX 255
  50. #endif
  51. #if E2END > (EEPROM_MAX-1)
  52. #error "E2END is set larger than the maximum possible EEPROM size"
  53. #endif
  54. #if defined(KINETISK)
  55. // The EEPROM is really RAM with a hardware-based backup system to
  56. // flash memory. Selecting a smaller size EEPROM allows more wear
  57. // leveling, for higher write endurance. If you edit this file,
  58. // set this to the smallest size your application can use. Also,
  59. // due to Freescale's implementation, writing 16 or 32 bit words
  60. // (aligned to 2 or 4 byte boundaries) has twice the endurance
  61. // compared to writing 8 bit bytes.
  62. //
  63. #if E2END < 32
  64. #define EEPROM_SIZE 32
  65. #define EEESIZE 0x09
  66. #elif E2END < 64
  67. #define EEPROM_SIZE 64
  68. #define EEESIZE 0x08
  69. #elif E2END < 128
  70. #define EEPROM_SIZE 128
  71. #define EEESIZE 0x07
  72. #elif E2END < 256
  73. #define EEPROM_SIZE 256
  74. #define EEESIZE 0x06
  75. #elif E2END < 512
  76. #define EEPROM_SIZE 512
  77. #define EEESIZE 0x05
  78. #elif E2END < 1024
  79. #define EEPROM_SIZE 1024
  80. #define EEESIZE 0x04
  81. #elif E2END < 2048
  82. #define EEPROM_SIZE 2048
  83. #define EEESIZE 0x03
  84. #elif E2END < 4096
  85. #define EEPROM_SIZE 4096
  86. #define EEESIZE 0x02
  87. #endif
  88. // Writing unaligned 16 or 32 bit data is handled automatically when
  89. // this is defined, but at a cost of extra code size. Without this,
  90. // any unaligned write will cause a hard fault exception! If you're
  91. // absolutely sure all 16 and 32 bit writes will be aligned, you can
  92. // remove the extra unnecessary code.
  93. //
  94. #define HANDLE_UNALIGNED_WRITES
  95. void eeprom_initialize(void)
  96. {
  97. uint32_t count=0;
  98. uint16_t do_flash_cmd[] = {
  99. 0xf06f, 0x037f, 0x7003, 0x7803,
  100. 0xf013, 0x0f80, 0xd0fb, 0x4770};
  101. uint8_t status;
  102. if (FTFL_FCNFG & FTFL_FCNFG_RAMRDY) {
  103. uint8_t stat = FTFL_FSTAT & 0x70;
  104. if (stat) FTFL_FSTAT = stat;
  105. // FlexRAM is configured as traditional RAM
  106. // We need to reconfigure for EEPROM usage
  107. kinetis_hsrun_disable();
  108. FTFL_FCCOB0 = 0x80; // PGMPART = Program Partition Command
  109. FTFL_FCCOB3 = 0;
  110. FTFL_FCCOB4 = EEESPLIT | EEESIZE;
  111. FTFL_FCCOB5 = EEPARTITION;
  112. __disable_irq();
  113. // do_flash_cmd() must execute from RAM. Luckily the C syntax is simple...
  114. (*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&FTFL_FSTAT);
  115. __enable_irq();
  116. kinetis_hsrun_enable();
  117. status = FTFL_FSTAT;
  118. if (status & 0x70) {
  119. FTFL_FSTAT = (status & 0x70);
  120. return; // error
  121. }
  122. }
  123. // wait for eeprom to become ready (is this really necessary?)
  124. while (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) {
  125. if (++count > 200000) break;
  126. }
  127. }
  128. #define FlexRAM ((volatile uint8_t *)0x14000000)
  129. uint8_t eeprom_read_byte(const uint8_t *addr)
  130. {
  131. uint32_t offset = (uint32_t)addr;
  132. if (offset >= EEPROM_SIZE) return 0;
  133. if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  134. return FlexRAM[offset];
  135. }
  136. uint16_t eeprom_read_word(const uint16_t *addr)
  137. {
  138. uint32_t offset = (uint32_t)addr;
  139. if (offset >= EEPROM_SIZE-1) return 0;
  140. if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  141. return *(uint16_t *)(&FlexRAM[offset]);
  142. }
  143. uint32_t eeprom_read_dword(const uint32_t *addr)
  144. {
  145. uint32_t offset = (uint32_t)addr;
  146. if (offset >= EEPROM_SIZE-3) return 0;
  147. if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  148. return *(uint32_t *)(&FlexRAM[offset]);
  149. }
  150. void eeprom_read_block(void *buf, const void *addr, uint32_t len)
  151. {
  152. uint32_t offset = (uint32_t)addr;
  153. uint8_t *dest = (uint8_t *)buf;
  154. uint32_t end = offset + len;
  155. if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  156. if (end > EEPROM_SIZE) end = EEPROM_SIZE;
  157. while (offset < end) {
  158. *dest++ = FlexRAM[offset++];
  159. }
  160. }
  161. int eeprom_is_ready(void)
  162. {
  163. return (FTFL_FCNFG & FTFL_FCNFG_EEERDY) ? 1 : 0;
  164. }
  165. static void flexram_wait(void)
  166. {
  167. while (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) {
  168. // TODO: timeout
  169. }
  170. }
  171. void eeprom_write_byte(uint8_t *addr, uint8_t value)
  172. {
  173. uint32_t offset = (uint32_t)addr;
  174. if (offset >= EEPROM_SIZE) return;
  175. if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  176. if (FlexRAM[offset] != value) {
  177. kinetis_hsrun_disable();
  178. uint8_t stat = FTFL_FSTAT & 0x70;
  179. if (stat) FTFL_FSTAT = stat;
  180. FlexRAM[offset] = value;
  181. flexram_wait();
  182. kinetis_hsrun_enable();
  183. }
  184. }
  185. void eeprom_write_word(uint16_t *addr, uint16_t value)
  186. {
  187. uint32_t offset = (uint32_t)addr;
  188. if (offset >= EEPROM_SIZE-1) return;
  189. if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  190. #ifdef HANDLE_UNALIGNED_WRITES
  191. if ((offset & 1) == 0) {
  192. #endif
  193. if (*(uint16_t *)(&FlexRAM[offset]) != value) {
  194. kinetis_hsrun_disable();
  195. uint8_t stat = FTFL_FSTAT & 0x70;
  196. if (stat) FTFL_FSTAT = stat;
  197. *(uint16_t *)(&FlexRAM[offset]) = value;
  198. flexram_wait();
  199. kinetis_hsrun_enable();
  200. }
  201. #ifdef HANDLE_UNALIGNED_WRITES
  202. } else {
  203. if (FlexRAM[offset] != value) {
  204. kinetis_hsrun_disable();
  205. uint8_t stat = FTFL_FSTAT & 0x70;
  206. if (stat) FTFL_FSTAT = stat;
  207. FlexRAM[offset] = value;
  208. flexram_wait();
  209. kinetis_hsrun_enable();
  210. }
  211. if (FlexRAM[offset + 1] != (value >> 8)) {
  212. kinetis_hsrun_disable();
  213. uint8_t stat = FTFL_FSTAT & 0x70;
  214. if (stat) FTFL_FSTAT = stat;
  215. FlexRAM[offset + 1] = value >> 8;
  216. flexram_wait();
  217. kinetis_hsrun_enable();
  218. }
  219. }
  220. #endif
  221. }
  222. void eeprom_write_dword(uint32_t *addr, uint32_t value)
  223. {
  224. uint32_t offset = (uint32_t)addr;
  225. if (offset >= EEPROM_SIZE-3) return;
  226. if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  227. #ifdef HANDLE_UNALIGNED_WRITES
  228. switch (offset & 3) {
  229. case 0:
  230. #endif
  231. if (*(uint32_t *)(&FlexRAM[offset]) != value) {
  232. kinetis_hsrun_disable();
  233. uint8_t stat = FTFL_FSTAT & 0x70;
  234. if (stat) FTFL_FSTAT = stat;
  235. *(uint32_t *)(&FlexRAM[offset]) = value;
  236. flexram_wait();
  237. kinetis_hsrun_enable();
  238. }
  239. return;
  240. #ifdef HANDLE_UNALIGNED_WRITES
  241. case 2:
  242. if (*(uint16_t *)(&FlexRAM[offset]) != value) {
  243. kinetis_hsrun_disable();
  244. uint8_t stat = FTFL_FSTAT & 0x70;
  245. if (stat) FTFL_FSTAT = stat;
  246. *(uint16_t *)(&FlexRAM[offset]) = value;
  247. flexram_wait();
  248. kinetis_hsrun_enable();
  249. }
  250. if (*(uint16_t *)(&FlexRAM[offset + 2]) != (value >> 16)) {
  251. kinetis_hsrun_disable();
  252. uint8_t stat = FTFL_FSTAT & 0x70;
  253. if (stat) FTFL_FSTAT = stat;
  254. *(uint16_t *)(&FlexRAM[offset + 2]) = value >> 16;
  255. flexram_wait();
  256. kinetis_hsrun_enable();
  257. }
  258. return;
  259. default:
  260. if (FlexRAM[offset] != value) {
  261. kinetis_hsrun_disable();
  262. uint8_t stat = FTFL_FSTAT & 0x70;
  263. if (stat) FTFL_FSTAT = stat;
  264. FlexRAM[offset] = value;
  265. flexram_wait();
  266. kinetis_hsrun_enable();
  267. }
  268. if (*(uint16_t *)(&FlexRAM[offset + 1]) != (value >> 8)) {
  269. kinetis_hsrun_disable();
  270. uint8_t stat = FTFL_FSTAT & 0x70;
  271. if (stat) FTFL_FSTAT = stat;
  272. *(uint16_t *)(&FlexRAM[offset + 1]) = value >> 8;
  273. flexram_wait();
  274. kinetis_hsrun_enable();
  275. }
  276. if (FlexRAM[offset + 3] != (value >> 24)) {
  277. kinetis_hsrun_disable();
  278. uint8_t stat = FTFL_FSTAT & 0x70;
  279. if (stat) FTFL_FSTAT = stat;
  280. FlexRAM[offset + 3] = value >> 24;
  281. flexram_wait();
  282. kinetis_hsrun_enable();
  283. }
  284. }
  285. #endif
  286. }
  287. void eeprom_write_block(const void *buf, void *addr, uint32_t len)
  288. {
  289. uint32_t offset = (uint32_t)addr;
  290. const uint8_t *src = (const uint8_t *)buf;
  291. if (offset >= EEPROM_SIZE) return;
  292. if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  293. if (len >= EEPROM_SIZE) len = EEPROM_SIZE;
  294. if (offset + len >= EEPROM_SIZE) len = EEPROM_SIZE - offset;
  295. while (len > 0) {
  296. uint32_t lsb = offset & 3;
  297. if (lsb == 0 && len >= 4) {
  298. // write aligned 32 bits
  299. uint32_t val32;
  300. val32 = *src++;
  301. val32 |= (*src++ << 8);
  302. val32 |= (*src++ << 16);
  303. val32 |= (*src++ << 24);
  304. if (*(uint32_t *)(&FlexRAM[offset]) != val32) {
  305. kinetis_hsrun_disable();
  306. uint8_t stat = FTFL_FSTAT & 0x70;
  307. if (stat) FTFL_FSTAT = stat;
  308. *(uint32_t *)(&FlexRAM[offset]) = val32;
  309. flexram_wait();
  310. kinetis_hsrun_enable();
  311. }
  312. offset += 4;
  313. len -= 4;
  314. } else if ((lsb == 0 || lsb == 2) && len >= 2) {
  315. // write aligned 16 bits
  316. uint16_t val16;
  317. val16 = *src++;
  318. val16 |= (*src++ << 8);
  319. if (*(uint16_t *)(&FlexRAM[offset]) != val16) {
  320. kinetis_hsrun_disable();
  321. uint8_t stat = FTFL_FSTAT & 0x70;
  322. if (stat) FTFL_FSTAT = stat;
  323. *(uint16_t *)(&FlexRAM[offset]) = val16;
  324. flexram_wait();
  325. kinetis_hsrun_enable();
  326. }
  327. offset += 2;
  328. len -= 2;
  329. } else {
  330. // write 8 bits
  331. uint8_t val8 = *src++;
  332. if (FlexRAM[offset] != val8) {
  333. kinetis_hsrun_disable();
  334. uint8_t stat = FTFL_FSTAT & 0x70;
  335. if (stat) FTFL_FSTAT = stat;
  336. FlexRAM[offset] = val8;
  337. flexram_wait();
  338. kinetis_hsrun_enable();
  339. }
  340. offset++;
  341. len--;
  342. }
  343. }
  344. }
  345. /*
  346. void do_flash_cmd(volatile uint8_t *fstat)
  347. {
  348. *fstat = 0x80;
  349. while ((*fstat & 0x80) == 0) ; // wait
  350. }
  351. 00000000 <do_flash_cmd>:
  352. 0: f06f 037f mvn.w r3, #127 ; 0x7f
  353. 4: 7003 strb r3, [r0, #0]
  354. 6: 7803 ldrb r3, [r0, #0]
  355. 8: f013 0f80 tst.w r3, #128 ; 0x80
  356. c: d0fb beq.n 6 <do_flash_cmd+0x6>
  357. e: 4770 bx lr
  358. */
  359. #elif defined(KINETISL)
  360. #define EEPROM_SIZE (E2END+1)
  361. #define FLASH_BEGIN (uint16_t *)63488
  362. #define FLASH_END (uint16_t *)65536
  363. static uint16_t flashend = 0;
  364. void eeprom_initialize(void)
  365. {
  366. const uint16_t *p = FLASH_BEGIN;
  367. do {
  368. if (*p++ == 0xFFFF) {
  369. flashend = (uint32_t)(p - 2);
  370. return;
  371. }
  372. } while (p < FLASH_END);
  373. flashend = (uint32_t)(FLASH_END - 1);
  374. }
  375. uint8_t eeprom_read_byte(const uint8_t *addr)
  376. {
  377. uint32_t offset = (uint32_t)addr;
  378. const uint16_t *p = FLASH_BEGIN;
  379. const uint16_t *end = (const uint16_t *)((uint32_t)flashend);
  380. uint16_t val;
  381. uint8_t data=0xFF;
  382. if (!end) {
  383. eeprom_initialize();
  384. end = (const uint16_t *)((uint32_t)flashend);
  385. }
  386. if (offset < EEPROM_SIZE) {
  387. while (p <= end) {
  388. val = *p++;
  389. if ((val & 255) == offset) data = val >> 8;
  390. }
  391. }
  392. return data;
  393. }
  394. static void flash_write(const uint16_t *code, uint32_t addr, uint32_t data)
  395. {
  396. // with great power comes great responsibility....
  397. uint32_t stat;
  398. *(uint32_t *)&FTFL_FCCOB3 = 0x06000000 | (addr & 0x00FFFFFC);
  399. *(uint32_t *)&FTFL_FCCOB7 = data;
  400. __disable_irq();
  401. (*((void (*)(volatile uint8_t *))((uint32_t)code | 1)))(&FTFL_FSTAT);
  402. __enable_irq();
  403. stat = FTFL_FSTAT & 0x70;
  404. if (stat) {
  405. FTFL_FSTAT = stat;
  406. }
  407. MCM_PLACR |= MCM_PLACR_CFCC;
  408. }
  409. void eeprom_write_byte(uint8_t *addr, uint8_t data)
  410. {
  411. uint32_t offset = (uint32_t)addr;
  412. const uint16_t *p, *end = (const uint16_t *)((uint32_t)flashend);
  413. uint32_t i, val, flashaddr;
  414. uint16_t do_flash_cmd[] = {
  415. 0x2380, 0x7003, 0x7803, 0xb25b, 0x2b00, 0xdafb, 0x4770};
  416. uint8_t buf[EEPROM_SIZE];
  417. if (offset >= EEPROM_SIZE) return;
  418. if (!end) {
  419. eeprom_initialize();
  420. end = (const uint16_t *)((uint32_t)flashend);
  421. }
  422. if (++end < FLASH_END) {
  423. val = (data << 8) | offset;
  424. flashaddr = (uint32_t)end;
  425. flashend = flashaddr;
  426. if ((flashaddr & 2) == 0) {
  427. val |= 0xFFFF0000;
  428. } else {
  429. val <<= 16;
  430. val |= 0x0000FFFF;
  431. }
  432. flash_write(do_flash_cmd, flashaddr, val);
  433. } else {
  434. for (i=0; i < EEPROM_SIZE; i++) {
  435. buf[i] = 0xFF;
  436. }
  437. for (p = FLASH_BEGIN; p < FLASH_END; p++) {
  438. val = *p;
  439. if ((val & 255) < EEPROM_SIZE) {
  440. buf[val & 255] = val >> 8;
  441. }
  442. }
  443. buf[offset] = data;
  444. for (flashaddr=(uint32_t)FLASH_BEGIN; flashaddr < (uint32_t)FLASH_END; flashaddr += 1024) {
  445. *(uint32_t *)&FTFL_FCCOB3 = 0x09000000 | flashaddr;
  446. __disable_irq();
  447. (*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&FTFL_FSTAT);
  448. __enable_irq();
  449. val = FTFL_FSTAT & 0x70;
  450. if (val) FTFL_FSTAT = val;
  451. MCM_PLACR |= MCM_PLACR_CFCC;
  452. }
  453. flashaddr=(uint32_t)FLASH_BEGIN;
  454. for (i=0; i < EEPROM_SIZE; i++) {
  455. if (buf[i] == 0xFF) continue;
  456. if ((flashaddr & 2) == 0) {
  457. val = (buf[i] << 8) | i;
  458. } else {
  459. val = val | (buf[i] << 24) | (i << 16);
  460. flash_write(do_flash_cmd, flashaddr, val);
  461. }
  462. flashaddr += 2;
  463. }
  464. flashend = flashaddr;
  465. if ((flashaddr & 2)) {
  466. val |= 0xFFFF0000;
  467. flash_write(do_flash_cmd, flashaddr, val);
  468. }
  469. }
  470. }
  471. /*
  472. void do_flash_cmd(volatile uint8_t *fstat)
  473. {
  474. *fstat = 0x80;
  475. while ((*fstat & 0x80) == 0) ; // wait
  476. }
  477. 00000000 <do_flash_cmd>:
  478. 0: 2380 movs r3, #128 ; 0x80
  479. 2: 7003 strb r3, [r0, #0]
  480. 4: 7803 ldrb r3, [r0, #0]
  481. 6: b25b sxtb r3, r3
  482. 8: 2b00 cmp r3, #0
  483. a: dafb bge.n 4 <do_flash_cmd+0x4>
  484. c: 4770 bx lr
  485. */
  486. uint16_t eeprom_read_word(const uint16_t *addr)
  487. {
  488. const uint8_t *p = (const uint8_t *)addr;
  489. return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8);
  490. }
  491. uint32_t eeprom_read_dword(const uint32_t *addr)
  492. {
  493. const uint8_t *p = (const uint8_t *)addr;
  494. return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8)
  495. | (eeprom_read_byte(p+2) << 16) | (eeprom_read_byte(p+3) << 24);
  496. }
  497. void eeprom_read_block(void *buf, const void *addr, uint32_t len)
  498. {
  499. const uint8_t *p = (const uint8_t *)addr;
  500. uint8_t *dest = (uint8_t *)buf;
  501. while (len--) {
  502. *dest++ = eeprom_read_byte(p++);
  503. }
  504. }
  505. int eeprom_is_ready(void)
  506. {
  507. return 1;
  508. }
  509. void eeprom_write_word(uint16_t *addr, uint16_t value)
  510. {
  511. uint8_t *p = (uint8_t *)addr;
  512. eeprom_write_byte(p++, value);
  513. eeprom_write_byte(p, value >> 8);
  514. }
  515. void eeprom_write_dword(uint32_t *addr, uint32_t value)
  516. {
  517. uint8_t *p = (uint8_t *)addr;
  518. eeprom_write_byte(p++, value);
  519. eeprom_write_byte(p++, value >> 8);
  520. eeprom_write_byte(p++, value >> 16);
  521. eeprom_write_byte(p, value >> 24);
  522. }
  523. void eeprom_write_block(const void *buf, void *addr, uint32_t len)
  524. {
  525. uint8_t *p = (uint8_t *)addr;
  526. const uint8_t *src = (const uint8_t *)buf;
  527. while (len--) {
  528. eeprom_write_byte(p++, *src++);
  529. }
  530. }
  531. #endif // KINETISL