Teensy 4.1 core updated for C++20
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

611 lines
16KB

  1. /* Teensyduino Core Library
  2. * http://www.pjrc.com/teensy/
  3. * Copyright (c) 2016 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. FTFL_FCCOB0 = 0x80; // PGMPART = Program Partition Command
  108. FTFL_FCCOB3 = 0;
  109. FTFL_FCCOB4 = EEESPLIT | EEESIZE;
  110. FTFL_FCCOB5 = EEPARTITION;
  111. __disable_irq();
  112. // do_flash_cmd() must execute from RAM. Luckily the C syntax is simple...
  113. (*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&FTFL_FSTAT);
  114. __enable_irq();
  115. status = FTFL_FSTAT;
  116. if (status & 0x70) {
  117. FTFL_FSTAT = (status & 0x70);
  118. return; // error
  119. }
  120. }
  121. // wait for eeprom to become ready (is this really necessary?)
  122. while (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) {
  123. if (++count > 200000) break;
  124. }
  125. }
  126. #define FlexRAM ((volatile uint8_t *)0x14000000)
  127. uint8_t eeprom_read_byte(const uint8_t *addr)
  128. {
  129. uint32_t offset = (uint32_t)addr;
  130. if (offset >= EEPROM_SIZE) return 0;
  131. if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  132. return FlexRAM[offset];
  133. }
  134. uint16_t eeprom_read_word(const uint16_t *addr)
  135. {
  136. uint32_t offset = (uint32_t)addr;
  137. if (offset >= EEPROM_SIZE-1) return 0;
  138. if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  139. return *(uint16_t *)(&FlexRAM[offset]);
  140. }
  141. uint32_t eeprom_read_dword(const uint32_t *addr)
  142. {
  143. uint32_t offset = (uint32_t)addr;
  144. if (offset >= EEPROM_SIZE-3) return 0;
  145. if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  146. return *(uint32_t *)(&FlexRAM[offset]);
  147. }
  148. void eeprom_read_block(void *buf, const void *addr, uint32_t len)
  149. {
  150. uint32_t offset = (uint32_t)addr;
  151. uint8_t *dest = (uint8_t *)buf;
  152. uint32_t end = offset + len;
  153. if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  154. if (end > EEPROM_SIZE) end = EEPROM_SIZE;
  155. while (offset < end) {
  156. *dest++ = FlexRAM[offset++];
  157. }
  158. }
  159. int eeprom_is_ready(void)
  160. {
  161. return (FTFL_FCNFG & FTFL_FCNFG_EEERDY) ? 1 : 0;
  162. }
  163. static void flexram_wait(void)
  164. {
  165. while (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) {
  166. // TODO: timeout
  167. }
  168. }
  169. #if F_CPU > 120000000 && defined(__MK66FX1M0__)
  170. static volatile uint16_t c_intrestore = 0;
  171. void c_enable_irq( void );
  172. void c_disable_irq( void );
  173. static __inline__ uint32_t __get_primask(void) \
  174. { uint32_t primask = 0; \
  175. __asm__ volatile ("MRS %[result], PRIMASK\n\t":[result]"=r"(primask)::); \
  176. return primask; } // returns 0 if interrupts enabled, 1 if disabled
  177. void c_enable_irq( void ){
  178. if ( c_intrestore ) {
  179. c_intrestore =0;
  180. __enable_irq( );
  181. }
  182. }
  183. void c_disable_irq( void ){
  184. if ( !__get_primask() ) { // Returns 0 if they are enabled, or non-zero if disabled
  185. c_intrestore = 1;
  186. __disable_irq( );
  187. }
  188. }
  189. static volatile uint8_t restore_hsrun = 0;
  190. static void hsrun_off(void)
  191. {
  192. if (SMC_PMSTAT == SMC_PMSTAT_HSRUN) {
  193. c_disable_irq( ); // Turn off interrupts for the DURATION !!!!
  194. SMC_PMCTRL = SMC_PMCTRL_RUNM(0); // exit HSRUN mode
  195. while (SMC_PMSTAT == SMC_PMSTAT_HSRUN) delayMicroseconds(2); // wait for !HSRUN
  196. delayMicroseconds(100);
  197. restore_hsrun = 1;
  198. }
  199. }
  200. static void hsrun_on(void)
  201. {
  202. if (restore_hsrun) {
  203. SMC_PMCTRL = SMC_PMCTRL_RUNM(3); // enter HSRUN mode
  204. while (SMC_PMSTAT != SMC_PMSTAT_HSRUN) delayMicroseconds(2);; // wait for HSRUN
  205. restore_hsrun = 0;
  206. c_enable_irq( ); // Restore interrupts only when HSRUN restored }
  207. }
  208. }
  209. #else
  210. #define hsrun_off()
  211. #define hsrun_on()
  212. #endif
  213. void eeprom_write_byte(uint8_t *addr, uint8_t value)
  214. {
  215. uint32_t offset = (uint32_t)addr;
  216. if (offset >= EEPROM_SIZE) return;
  217. if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  218. hsrun_off();
  219. if (FlexRAM[offset] != value) {
  220. uint8_t stat = FTFL_FSTAT & 0x70;
  221. if (stat) FTFL_FSTAT = stat;
  222. FlexRAM[offset] = value;
  223. flexram_wait();
  224. }
  225. hsrun_on();
  226. }
  227. void eeprom_write_word(uint16_t *addr, uint16_t value)
  228. {
  229. uint32_t offset = (uint32_t)addr;
  230. if (offset >= EEPROM_SIZE-1) return;
  231. if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  232. hsrun_off();
  233. #ifdef HANDLE_UNALIGNED_WRITES
  234. if ((offset & 1) == 0) {
  235. #endif
  236. if (*(uint16_t *)(&FlexRAM[offset]) != value) {
  237. uint8_t stat = FTFL_FSTAT & 0x70;
  238. if (stat) FTFL_FSTAT = stat;
  239. *(uint16_t *)(&FlexRAM[offset]) = value;
  240. flexram_wait();
  241. }
  242. #ifdef HANDLE_UNALIGNED_WRITES
  243. } else {
  244. if (FlexRAM[offset] != value) {
  245. uint8_t stat = FTFL_FSTAT & 0x70;
  246. if (stat) FTFL_FSTAT = stat;
  247. FlexRAM[offset] = value;
  248. flexram_wait();
  249. }
  250. if (FlexRAM[offset + 1] != (value >> 8)) {
  251. uint8_t stat = FTFL_FSTAT & 0x70;
  252. if (stat) FTFL_FSTAT = stat;
  253. FlexRAM[offset + 1] = value >> 8;
  254. flexram_wait();
  255. }
  256. }
  257. #endif
  258. hsrun_on();
  259. }
  260. void eeprom_write_dword(uint32_t *addr, uint32_t value)
  261. {
  262. uint32_t offset = (uint32_t)addr;
  263. if (offset >= EEPROM_SIZE-3) return;
  264. if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  265. hsrun_off();
  266. #ifdef HANDLE_UNALIGNED_WRITES
  267. switch (offset & 3) {
  268. case 0:
  269. #endif
  270. if (*(uint32_t *)(&FlexRAM[offset]) != value) {
  271. uint8_t stat = FTFL_FSTAT & 0x70;
  272. if (stat) FTFL_FSTAT = stat;
  273. *(uint32_t *)(&FlexRAM[offset]) = value;
  274. flexram_wait();
  275. }
  276. hsrun_on();
  277. return;
  278. #ifdef HANDLE_UNALIGNED_WRITES
  279. case 2:
  280. if (*(uint16_t *)(&FlexRAM[offset]) != value) {
  281. uint8_t stat = FTFL_FSTAT & 0x70;
  282. if (stat) FTFL_FSTAT = stat;
  283. *(uint16_t *)(&FlexRAM[offset]) = value;
  284. flexram_wait();
  285. }
  286. if (*(uint16_t *)(&FlexRAM[offset + 2]) != (value >> 16)) {
  287. uint8_t stat = FTFL_FSTAT & 0x70;
  288. if (stat) FTFL_FSTAT = stat;
  289. *(uint16_t *)(&FlexRAM[offset + 2]) = value >> 16;
  290. flexram_wait();
  291. }
  292. hsrun_on();
  293. return;
  294. default:
  295. if (FlexRAM[offset] != value) {
  296. uint8_t stat = FTFL_FSTAT & 0x70;
  297. if (stat) FTFL_FSTAT = stat;
  298. FlexRAM[offset] = value;
  299. flexram_wait();
  300. }
  301. if (*(uint16_t *)(&FlexRAM[offset + 1]) != (value >> 8)) {
  302. uint8_t stat = FTFL_FSTAT & 0x70;
  303. if (stat) FTFL_FSTAT = stat;
  304. *(uint16_t *)(&FlexRAM[offset + 1]) = value >> 8;
  305. flexram_wait();
  306. }
  307. if (FlexRAM[offset + 3] != (value >> 24)) {
  308. uint8_t stat = FTFL_FSTAT & 0x70;
  309. if (stat) FTFL_FSTAT = stat;
  310. FlexRAM[offset + 3] = value >> 24;
  311. flexram_wait();
  312. }
  313. }
  314. #endif
  315. hsrun_on();
  316. }
  317. void eeprom_write_block(const void *buf, void *addr, uint32_t len)
  318. {
  319. uint32_t offset = (uint32_t)addr;
  320. const uint8_t *src = (const uint8_t *)buf;
  321. if (offset >= EEPROM_SIZE) return;
  322. if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  323. hsrun_off();
  324. if (len >= EEPROM_SIZE) len = EEPROM_SIZE;
  325. if (offset + len >= EEPROM_SIZE) len = EEPROM_SIZE - offset;
  326. while (len > 0) {
  327. uint32_t lsb = offset & 3;
  328. if (lsb == 0 && len >= 4) {
  329. // write aligned 32 bits
  330. uint32_t val32;
  331. val32 = *src++;
  332. val32 |= (*src++ << 8);
  333. val32 |= (*src++ << 16);
  334. val32 |= (*src++ << 24);
  335. if (*(uint32_t *)(&FlexRAM[offset]) != val32) {
  336. uint8_t stat = FTFL_FSTAT & 0x70;
  337. if (stat) FTFL_FSTAT = stat;
  338. *(uint32_t *)(&FlexRAM[offset]) = val32;
  339. flexram_wait();
  340. }
  341. offset += 4;
  342. len -= 4;
  343. } else if ((lsb == 0 || lsb == 2) && len >= 2) {
  344. // write aligned 16 bits
  345. uint16_t val16;
  346. val16 = *src++;
  347. val16 |= (*src++ << 8);
  348. if (*(uint16_t *)(&FlexRAM[offset]) != val16) {
  349. uint8_t stat = FTFL_FSTAT & 0x70;
  350. if (stat) FTFL_FSTAT = stat;
  351. *(uint16_t *)(&FlexRAM[offset]) = val16;
  352. flexram_wait();
  353. }
  354. offset += 2;
  355. len -= 2;
  356. } else {
  357. // write 8 bits
  358. uint8_t val8 = *src++;
  359. if (FlexRAM[offset] != val8) {
  360. uint8_t stat = FTFL_FSTAT & 0x70;
  361. if (stat) FTFL_FSTAT = stat;
  362. FlexRAM[offset] = val8;
  363. flexram_wait();
  364. }
  365. offset++;
  366. len--;
  367. }
  368. }
  369. hsrun_on();
  370. }
  371. /*
  372. void do_flash_cmd(volatile uint8_t *fstat)
  373. {
  374. *fstat = 0x80;
  375. while ((*fstat & 0x80) == 0) ; // wait
  376. }
  377. 00000000 <do_flash_cmd>:
  378. 0: f06f 037f mvn.w r3, #127 ; 0x7f
  379. 4: 7003 strb r3, [r0, #0]
  380. 6: 7803 ldrb r3, [r0, #0]
  381. 8: f013 0f80 tst.w r3, #128 ; 0x80
  382. c: d0fb beq.n 6 <do_flash_cmd+0x6>
  383. e: 4770 bx lr
  384. */
  385. #elif defined(KINETISL)
  386. #define EEPROM_SIZE (E2END+1)
  387. #define FLASH_BEGIN (uint16_t *)63488
  388. #define FLASH_END (uint16_t *)65536
  389. static uint16_t flashend = 0;
  390. void eeprom_initialize(void)
  391. {
  392. const uint16_t *p = FLASH_BEGIN;
  393. do {
  394. if (*p++ == 0xFFFF) {
  395. flashend = (uint32_t)(p - 2);
  396. return;
  397. }
  398. } while (p < FLASH_END);
  399. flashend = (uint32_t)(FLASH_END - 1);
  400. }
  401. uint8_t eeprom_read_byte(const uint8_t *addr)
  402. {
  403. uint32_t offset = (uint32_t)addr;
  404. const uint16_t *p = FLASH_BEGIN;
  405. const uint16_t *end = (const uint16_t *)((uint32_t)flashend);
  406. uint16_t val;
  407. uint8_t data=0xFF;
  408. if (!end) {
  409. eeprom_initialize();
  410. end = (const uint16_t *)((uint32_t)flashend);
  411. }
  412. if (offset < EEPROM_SIZE) {
  413. while (p <= end) {
  414. val = *p++;
  415. if ((val & 255) == offset) data = val >> 8;
  416. }
  417. }
  418. return data;
  419. }
  420. static void flash_write(const uint16_t *code, uint32_t addr, uint32_t data)
  421. {
  422. // with great power comes great responsibility....
  423. uint32_t stat;
  424. *(uint32_t *)&FTFL_FCCOB3 = 0x06000000 | (addr & 0x00FFFFFC);
  425. *(uint32_t *)&FTFL_FCCOB7 = data;
  426. __disable_irq();
  427. (*((void (*)(volatile uint8_t *))((uint32_t)code | 1)))(&FTFL_FSTAT);
  428. __enable_irq();
  429. stat = FTFL_FSTAT & 0x70;
  430. if (stat) {
  431. FTFL_FSTAT = stat;
  432. }
  433. MCM_PLACR |= MCM_PLACR_CFCC;
  434. }
  435. void eeprom_write_byte(uint8_t *addr, uint8_t data)
  436. {
  437. uint32_t offset = (uint32_t)addr;
  438. const uint16_t *p, *end = (const uint16_t *)((uint32_t)flashend);
  439. uint32_t i, val, flashaddr;
  440. uint16_t do_flash_cmd[] = {
  441. 0x2380, 0x7003, 0x7803, 0xb25b, 0x2b00, 0xdafb, 0x4770};
  442. uint8_t buf[EEPROM_SIZE];
  443. if (offset >= EEPROM_SIZE) return;
  444. if (!end) {
  445. eeprom_initialize();
  446. end = (const uint16_t *)((uint32_t)flashend);
  447. }
  448. if (++end < FLASH_END) {
  449. val = (data << 8) | offset;
  450. flashaddr = (uint32_t)end;
  451. flashend = flashaddr;
  452. if ((flashaddr & 2) == 0) {
  453. val |= 0xFFFF0000;
  454. } else {
  455. val <<= 16;
  456. val |= 0x0000FFFF;
  457. }
  458. flash_write(do_flash_cmd, flashaddr, val);
  459. } else {
  460. for (i=0; i < EEPROM_SIZE; i++) {
  461. buf[i] = 0xFF;
  462. }
  463. for (p = FLASH_BEGIN; p < FLASH_END; p++) {
  464. val = *p;
  465. if ((val & 255) < EEPROM_SIZE) {
  466. buf[val & 255] = val >> 8;
  467. }
  468. }
  469. buf[offset] = data;
  470. for (flashaddr=(uint32_t)FLASH_BEGIN; flashaddr < (uint32_t)FLASH_END; flashaddr += 1024) {
  471. *(uint32_t *)&FTFL_FCCOB3 = 0x09000000 | flashaddr;
  472. __disable_irq();
  473. (*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&FTFL_FSTAT);
  474. __enable_irq();
  475. val = FTFL_FSTAT & 0x70;
  476. if (val) FTFL_FSTAT = val;
  477. MCM_PLACR |= MCM_PLACR_CFCC;
  478. }
  479. flashaddr=(uint32_t)FLASH_BEGIN;
  480. for (i=0; i < EEPROM_SIZE; i++) {
  481. if (buf[i] == 0xFF) continue;
  482. if ((flashaddr & 2) == 0) {
  483. val = (buf[i] << 8) | i;
  484. } else {
  485. val = val | (buf[i] << 24) | (i << 16);
  486. flash_write(do_flash_cmd, flashaddr, val);
  487. }
  488. flashaddr += 2;
  489. }
  490. flashend = flashaddr;
  491. if ((flashaddr & 2)) {
  492. val |= 0xFFFF0000;
  493. flash_write(do_flash_cmd, flashaddr, val);
  494. }
  495. }
  496. }
  497. /*
  498. void do_flash_cmd(volatile uint8_t *fstat)
  499. {
  500. *fstat = 0x80;
  501. while ((*fstat & 0x80) == 0) ; // wait
  502. }
  503. 00000000 <do_flash_cmd>:
  504. 0: 2380 movs r3, #128 ; 0x80
  505. 2: 7003 strb r3, [r0, #0]
  506. 4: 7803 ldrb r3, [r0, #0]
  507. 6: b25b sxtb r3, r3
  508. 8: 2b00 cmp r3, #0
  509. a: dafb bge.n 4 <do_flash_cmd+0x4>
  510. c: 4770 bx lr
  511. */
  512. uint16_t eeprom_read_word(const uint16_t *addr)
  513. {
  514. const uint8_t *p = (const uint8_t *)addr;
  515. return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8);
  516. }
  517. uint32_t eeprom_read_dword(const uint32_t *addr)
  518. {
  519. const uint8_t *p = (const uint8_t *)addr;
  520. return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8)
  521. | (eeprom_read_byte(p+2) << 16) | (eeprom_read_byte(p+3) << 24);
  522. }
  523. void eeprom_read_block(void *buf, const void *addr, uint32_t len)
  524. {
  525. const uint8_t *p = (const uint8_t *)addr;
  526. uint8_t *dest = (uint8_t *)buf;
  527. while (len--) {
  528. *dest++ = eeprom_read_byte(p++);
  529. }
  530. }
  531. int eeprom_is_ready(void)
  532. {
  533. return 1;
  534. }
  535. void eeprom_write_word(uint16_t *addr, uint16_t value)
  536. {
  537. uint8_t *p = (uint8_t *)addr;
  538. eeprom_write_byte(p++, value);
  539. eeprom_write_byte(p, value >> 8);
  540. }
  541. void eeprom_write_dword(uint32_t *addr, uint32_t value)
  542. {
  543. uint8_t *p = (uint8_t *)addr;
  544. eeprom_write_byte(p++, value);
  545. eeprom_write_byte(p++, value >> 8);
  546. eeprom_write_byte(p++, value >> 16);
  547. eeprom_write_byte(p, value >> 24);
  548. }
  549. void eeprom_write_block(const void *buf, void *addr, uint32_t len)
  550. {
  551. uint8_t *p = (uint8_t *)addr;
  552. const uint8_t *src = (const uint8_t *)buf;
  553. while (len--) {
  554. eeprom_write_byte(p++, *src++);
  555. }
  556. }
  557. #endif // KINETISL