Teensy 4.1 core updated for C++20
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

606 líneas
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 defined(__MK20DX128__) || defined(__MK20DX256__)
  34. #define EEPROM_MAX 2048
  35. #define EEPARTITION 0x03 // all 32K dataflash for EEPROM, none for Data
  36. #define EEESPLIT 0x30 // must be 0x30 on these chips
  37. #elif defined(__MK64FX512__)
  38. #define EEPROM_MAX 4096
  39. #define EEPARTITION 0x05 // all 128K dataflash for EEPROM
  40. #define EEESPLIT 0x10 // best endurance: 0x00 = first 12%, 0x10 = first 25%, 0x30 = all equal
  41. #elif defined(__MK66FX1M0__)
  42. #define EEPROM_MAX 4096
  43. #define EEPARTITION 0x05 // 128K dataflash for EEPROM, 128K for Data
  44. #define EEESPLIT 0x10 // best endurance: 0x00 = first 12%, 0x10 = first 25%, 0x30 = all equal
  45. #elif defined(__MKL26Z64__)
  46. #define EEPROM_MAX 255
  47. #endif
  48. #if E2END > (EEPROM_MAX-1)
  49. #error "E2END is set larger than the maximum possible EEPROM size"
  50. #endif
  51. #if defined(KINETISK)
  52. // The EEPROM is really RAM with a hardware-based backup system to
  53. // flash memory. Selecting a smaller size EEPROM allows more wear
  54. // leveling, for higher write endurance. If you edit this file,
  55. // set this to the smallest size your application can use. Also,
  56. // due to Freescale's implementation, writing 16 or 32 bit words
  57. // (aligned to 2 or 4 byte boundaries) has twice the endurance
  58. // compared to writing 8 bit bytes.
  59. //
  60. #if E2END < 32
  61. #define EEPROM_SIZE 32
  62. #define EEESIZE 0x09
  63. #elif E2END < 64
  64. #define EEPROM_SIZE 64
  65. #define EEESIZE 0x08
  66. #elif E2END < 128
  67. #define EEPROM_SIZE 128
  68. #define EEESIZE 0x07
  69. #elif E2END < 256
  70. #define EEPROM_SIZE 256
  71. #define EEESIZE 0x06
  72. #elif E2END < 512
  73. #define EEPROM_SIZE 512
  74. #define EEESIZE 0x05
  75. #elif E2END < 1024
  76. #define EEPROM_SIZE 1024
  77. #define EEESIZE 0x04
  78. #elif E2END < 2048
  79. #define EEPROM_SIZE 2048
  80. #define EEESIZE 0x03
  81. #elif E2END < 4096
  82. #define EEPROM_SIZE 4096
  83. #define EEESIZE 0x02
  84. #endif
  85. // Writing unaligned 16 or 32 bit data is handled automatically when
  86. // this is defined, but at a cost of extra code size. Without this,
  87. // any unaligned write will cause a hard fault exception! If you're
  88. // absolutely sure all 16 and 32 bit writes will be aligned, you can
  89. // remove the extra unnecessary code.
  90. //
  91. #define HANDLE_UNALIGNED_WRITES
  92. void eeprom_initialize(void)
  93. {
  94. uint32_t count=0;
  95. uint16_t do_flash_cmd[] = {
  96. 0xf06f, 0x037f, 0x7003, 0x7803,
  97. 0xf013, 0x0f80, 0xd0fb, 0x4770};
  98. uint8_t status;
  99. if (FTFL_FCNFG & FTFL_FCNFG_RAMRDY) {
  100. uint8_t stat = FTFL_FSTAT & 0x70;
  101. if (stat) FTFL_FSTAT = stat;
  102. // FlexRAM is configured as traditional RAM
  103. // We need to reconfigure for EEPROM usage
  104. FTFL_FCCOB0 = 0x80; // PGMPART = Program Partition Command
  105. FTFL_FCCOB3 = 0;
  106. FTFL_FCCOB4 = EEESPLIT | EEESIZE;
  107. FTFL_FCCOB5 = EEPARTITION;
  108. __disable_irq();
  109. // do_flash_cmd() must execute from RAM. Luckily the C syntax is simple...
  110. (*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&FTFL_FSTAT);
  111. __enable_irq();
  112. status = FTFL_FSTAT;
  113. if (status & 0x70) {
  114. FTFL_FSTAT = (status & 0x70);
  115. return; // error
  116. }
  117. }
  118. // wait for eeprom to become ready (is this really necessary?)
  119. while (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) {
  120. if (++count > 200000) break;
  121. }
  122. }
  123. #define FlexRAM ((volatile uint8_t *)0x14000000)
  124. uint8_t eeprom_read_byte(const uint8_t *addr)
  125. {
  126. uint32_t offset = (uint32_t)addr;
  127. if (offset >= EEPROM_SIZE) return 0;
  128. if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  129. return FlexRAM[offset];
  130. }
  131. uint16_t eeprom_read_word(const uint16_t *addr)
  132. {
  133. uint32_t offset = (uint32_t)addr;
  134. if (offset >= EEPROM_SIZE-1) return 0;
  135. if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  136. return *(uint16_t *)(&FlexRAM[offset]);
  137. }
  138. uint32_t eeprom_read_dword(const uint32_t *addr)
  139. {
  140. uint32_t offset = (uint32_t)addr;
  141. if (offset >= EEPROM_SIZE-3) return 0;
  142. if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  143. return *(uint32_t *)(&FlexRAM[offset]);
  144. }
  145. void eeprom_read_block(void *buf, const void *addr, uint32_t len)
  146. {
  147. uint32_t offset = (uint32_t)addr;
  148. uint8_t *dest = (uint8_t *)buf;
  149. uint32_t end = offset + len;
  150. if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  151. if (end > EEPROM_SIZE) end = EEPROM_SIZE;
  152. while (offset < end) {
  153. *dest++ = FlexRAM[offset++];
  154. }
  155. }
  156. int eeprom_is_ready(void)
  157. {
  158. return (FTFL_FCNFG & FTFL_FCNFG_EEERDY) ? 1 : 0;
  159. }
  160. static void flexram_wait(void)
  161. {
  162. while (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) {
  163. // TODO: timeout
  164. }
  165. }
  166. #if F_CPU > 120000000 && defined(__MK66FX1M0__)
  167. static volatile uint16_t c_intrestore = 0;
  168. void c_enable_irq( void );
  169. void c_disable_irq( void );
  170. static __inline__ uint32_t __get_primask(void) \
  171. { uint32_t primask = 0; \
  172. __asm__ volatile ("MRS %[result], PRIMASK\n\t":[result]"=r"(primask)::); \
  173. return primask; } // returns 0 if interrupts enabled, 1 if disabled
  174. void c_enable_irq( void ){
  175. if ( c_intrestore ) {
  176. c_intrestore =0;
  177. __enable_irq( );
  178. }
  179. }
  180. void c_disable_irq( void ){
  181. if ( !__get_primask() ) { // Returns 0 if they are enabled, or non-zero if disabled
  182. c_intrestore = 1;
  183. __disable_irq( );
  184. }
  185. }
  186. static volatile uint8_t restore_hsrun = 0;
  187. static void hsrun_off(void)
  188. {
  189. if (SMC_PMSTAT == SMC_PMSTAT_HSRUN) {
  190. c_disable_irq( ); // Turn off interrupts for the DURATION !!!!
  191. SMC_PMCTRL = SMC_PMCTRL_RUNM(0); // exit HSRUN mode
  192. while (SMC_PMSTAT == SMC_PMSTAT_HSRUN) ; // wait for !HSRUN
  193. restore_hsrun = 1;
  194. }
  195. }
  196. static void hsrun_on(void)
  197. {
  198. if (restore_hsrun) {
  199. SMC_PMCTRL = SMC_PMCTRL_RUNM(3); // enter HSRUN mode
  200. while (SMC_PMSTAT != SMC_PMSTAT_HSRUN); // wait for HSRUN
  201. restore_hsrun = 0;
  202. c_enable_irq( ); // Restore interrupts only when HSRUN restored }
  203. }
  204. }
  205. #else
  206. #define hsrun_off()
  207. #define hsrun_on()
  208. #endif
  209. void eeprom_write_byte(uint8_t *addr, uint8_t value)
  210. {
  211. uint32_t offset = (uint32_t)addr;
  212. if (offset >= EEPROM_SIZE) return;
  213. hsrun_off();
  214. if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  215. if (FlexRAM[offset] != value) {
  216. uint8_t stat = FTFL_FSTAT & 0x70;
  217. if (stat) FTFL_FSTAT = stat;
  218. FlexRAM[offset] = value;
  219. flexram_wait();
  220. }
  221. hsrun_on();
  222. }
  223. void eeprom_write_word(uint16_t *addr, uint16_t value)
  224. {
  225. uint32_t offset = (uint32_t)addr;
  226. if (offset >= EEPROM_SIZE-1) return;
  227. hsrun_off();
  228. if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  229. #ifdef HANDLE_UNALIGNED_WRITES
  230. if ((offset & 1) == 0) {
  231. #endif
  232. if (*(uint16_t *)(&FlexRAM[offset]) != value) {
  233. uint8_t stat = FTFL_FSTAT & 0x70;
  234. if (stat) FTFL_FSTAT = stat;
  235. *(uint16_t *)(&FlexRAM[offset]) = value;
  236. flexram_wait();
  237. }
  238. #ifdef HANDLE_UNALIGNED_WRITES
  239. } else {
  240. if (FlexRAM[offset] != value) {
  241. uint8_t stat = FTFL_FSTAT & 0x70;
  242. if (stat) FTFL_FSTAT = stat;
  243. FlexRAM[offset] = value;
  244. flexram_wait();
  245. }
  246. if (FlexRAM[offset + 1] != (value >> 8)) {
  247. uint8_t stat = FTFL_FSTAT & 0x70;
  248. if (stat) FTFL_FSTAT = stat;
  249. FlexRAM[offset + 1] = value >> 8;
  250. flexram_wait();
  251. }
  252. }
  253. #endif
  254. hsrun_on();
  255. }
  256. void eeprom_write_dword(uint32_t *addr, uint32_t value)
  257. {
  258. uint32_t offset = (uint32_t)addr;
  259. if (offset >= EEPROM_SIZE-3) return;
  260. hsrun_off();
  261. if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  262. #ifdef HANDLE_UNALIGNED_WRITES
  263. switch (offset & 3) {
  264. case 0:
  265. #endif
  266. if (*(uint32_t *)(&FlexRAM[offset]) != value) {
  267. uint8_t stat = FTFL_FSTAT & 0x70;
  268. if (stat) FTFL_FSTAT = stat;
  269. *(uint32_t *)(&FlexRAM[offset]) = value;
  270. flexram_wait();
  271. }
  272. hsrun_on();
  273. return;
  274. #ifdef HANDLE_UNALIGNED_WRITES
  275. case 2:
  276. if (*(uint16_t *)(&FlexRAM[offset]) != value) {
  277. uint8_t stat = FTFL_FSTAT & 0x70;
  278. if (stat) FTFL_FSTAT = stat;
  279. *(uint16_t *)(&FlexRAM[offset]) = value;
  280. flexram_wait();
  281. }
  282. if (*(uint16_t *)(&FlexRAM[offset + 2]) != (value >> 16)) {
  283. uint8_t stat = FTFL_FSTAT & 0x70;
  284. if (stat) FTFL_FSTAT = stat;
  285. *(uint16_t *)(&FlexRAM[offset + 2]) = value >> 16;
  286. flexram_wait();
  287. }
  288. hsrun_on();
  289. return;
  290. default:
  291. if (FlexRAM[offset] != value) {
  292. uint8_t stat = FTFL_FSTAT & 0x70;
  293. if (stat) FTFL_FSTAT = stat;
  294. FlexRAM[offset] = value;
  295. flexram_wait();
  296. }
  297. if (*(uint16_t *)(&FlexRAM[offset + 1]) != (value >> 8)) {
  298. uint8_t stat = FTFL_FSTAT & 0x70;
  299. if (stat) FTFL_FSTAT = stat;
  300. *(uint16_t *)(&FlexRAM[offset + 1]) = value >> 8;
  301. flexram_wait();
  302. }
  303. if (FlexRAM[offset + 3] != (value >> 24)) {
  304. uint8_t stat = FTFL_FSTAT & 0x70;
  305. if (stat) FTFL_FSTAT = stat;
  306. FlexRAM[offset + 3] = value >> 24;
  307. flexram_wait();
  308. }
  309. }
  310. #endif
  311. hsrun_on();
  312. }
  313. void eeprom_write_block(const void *buf, void *addr, uint32_t len)
  314. {
  315. uint32_t offset = (uint32_t)addr;
  316. const uint8_t *src = (const uint8_t *)buf;
  317. if (offset >= EEPROM_SIZE) return;
  318. hsrun_off();
  319. if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  320. if (len >= EEPROM_SIZE) len = EEPROM_SIZE;
  321. if (offset + len >= EEPROM_SIZE) len = EEPROM_SIZE - offset;
  322. while (len > 0) {
  323. uint32_t lsb = offset & 3;
  324. if (lsb == 0 && len >= 4) {
  325. // write aligned 32 bits
  326. uint32_t val32;
  327. val32 = *src++;
  328. val32 |= (*src++ << 8);
  329. val32 |= (*src++ << 16);
  330. val32 |= (*src++ << 24);
  331. if (*(uint32_t *)(&FlexRAM[offset]) != val32) {
  332. uint8_t stat = FTFL_FSTAT & 0x70;
  333. if (stat) FTFL_FSTAT = stat;
  334. *(uint32_t *)(&FlexRAM[offset]) = val32;
  335. flexram_wait();
  336. }
  337. offset += 4;
  338. len -= 4;
  339. } else if ((lsb == 0 || lsb == 2) && len >= 2) {
  340. // write aligned 16 bits
  341. uint16_t val16;
  342. val16 = *src++;
  343. val16 |= (*src++ << 8);
  344. if (*(uint16_t *)(&FlexRAM[offset]) != val16) {
  345. uint8_t stat = FTFL_FSTAT & 0x70;
  346. if (stat) FTFL_FSTAT = stat;
  347. *(uint16_t *)(&FlexRAM[offset]) = val16;
  348. flexram_wait();
  349. }
  350. offset += 2;
  351. len -= 2;
  352. } else {
  353. // write 8 bits
  354. uint8_t val8 = *src++;
  355. if (FlexRAM[offset] != val8) {
  356. uint8_t stat = FTFL_FSTAT & 0x70;
  357. if (stat) FTFL_FSTAT = stat;
  358. FlexRAM[offset] = val8;
  359. flexram_wait();
  360. }
  361. offset++;
  362. len--;
  363. }
  364. }
  365. hsrun_on();
  366. }
  367. /*
  368. void do_flash_cmd(volatile uint8_t *fstat)
  369. {
  370. *fstat = 0x80;
  371. while ((*fstat & 0x80) == 0) ; // wait
  372. }
  373. 00000000 <do_flash_cmd>:
  374. 0: f06f 037f mvn.w r3, #127 ; 0x7f
  375. 4: 7003 strb r3, [r0, #0]
  376. 6: 7803 ldrb r3, [r0, #0]
  377. 8: f013 0f80 tst.w r3, #128 ; 0x80
  378. c: d0fb beq.n 6 <do_flash_cmd+0x6>
  379. e: 4770 bx lr
  380. */
  381. #elif defined(KINETISL)
  382. #define EEPROM_SIZE (E2END+1)
  383. #define FLASH_BEGIN (uint16_t *)63488
  384. #define FLASH_END (uint16_t *)65536
  385. static uint16_t flashend = 0;
  386. void eeprom_initialize(void)
  387. {
  388. const uint16_t *p = FLASH_BEGIN;
  389. do {
  390. if (*p++ == 0xFFFF) {
  391. flashend = (uint32_t)(p - 2);
  392. return;
  393. }
  394. } while (p < FLASH_END);
  395. flashend = (uint32_t)(FLASH_END - 1);
  396. }
  397. uint8_t eeprom_read_byte(const uint8_t *addr)
  398. {
  399. uint32_t offset = (uint32_t)addr;
  400. const uint16_t *p = FLASH_BEGIN;
  401. const uint16_t *end = (const uint16_t *)((uint32_t)flashend);
  402. uint16_t val;
  403. uint8_t data=0xFF;
  404. if (!end) {
  405. eeprom_initialize();
  406. end = (const uint16_t *)((uint32_t)flashend);
  407. }
  408. if (offset < EEPROM_SIZE) {
  409. while (p <= end) {
  410. val = *p++;
  411. if ((val & 255) == offset) data = val >> 8;
  412. }
  413. }
  414. return data;
  415. }
  416. static void flash_write(const uint16_t *code, uint32_t addr, uint32_t data)
  417. {
  418. // with great power comes great responsibility....
  419. uint32_t stat;
  420. *(uint32_t *)&FTFL_FCCOB3 = 0x06000000 | (addr & 0x00FFFFFC);
  421. *(uint32_t *)&FTFL_FCCOB7 = data;
  422. __disable_irq();
  423. (*((void (*)(volatile uint8_t *))((uint32_t)code | 1)))(&FTFL_FSTAT);
  424. __enable_irq();
  425. stat = FTFL_FSTAT & 0x70;
  426. if (stat) {
  427. FTFL_FSTAT = stat;
  428. }
  429. MCM_PLACR |= MCM_PLACR_CFCC;
  430. }
  431. void eeprom_write_byte(uint8_t *addr, uint8_t data)
  432. {
  433. uint32_t offset = (uint32_t)addr;
  434. const uint16_t *p, *end = (const uint16_t *)((uint32_t)flashend);
  435. uint32_t i, val, flashaddr;
  436. uint16_t do_flash_cmd[] = {
  437. 0x2380, 0x7003, 0x7803, 0xb25b, 0x2b00, 0xdafb, 0x4770};
  438. uint8_t buf[EEPROM_SIZE];
  439. if (offset >= EEPROM_SIZE) return;
  440. if (!end) {
  441. eeprom_initialize();
  442. end = (const uint16_t *)((uint32_t)flashend);
  443. }
  444. if (++end < FLASH_END) {
  445. val = (data << 8) | offset;
  446. flashaddr = (uint32_t)end;
  447. flashend = flashaddr;
  448. if ((flashaddr & 2) == 0) {
  449. val |= 0xFFFF0000;
  450. } else {
  451. val <<= 16;
  452. val |= 0x0000FFFF;
  453. }
  454. flash_write(do_flash_cmd, flashaddr, val);
  455. } else {
  456. for (i=0; i < EEPROM_SIZE; i++) {
  457. buf[i] = 0xFF;
  458. }
  459. for (p = FLASH_BEGIN; p < FLASH_END; p++) {
  460. val = *p;
  461. if ((val & 255) < EEPROM_SIZE) {
  462. buf[val & 255] = val >> 8;
  463. }
  464. }
  465. buf[offset] = data;
  466. for (flashaddr=(uint32_t)FLASH_BEGIN; flashaddr < (uint32_t)FLASH_END; flashaddr += 1024) {
  467. *(uint32_t *)&FTFL_FCCOB3 = 0x09000000 | flashaddr;
  468. __disable_irq();
  469. (*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&FTFL_FSTAT);
  470. __enable_irq();
  471. val = FTFL_FSTAT & 0x70;
  472. if (val) FTFL_FSTAT = val;
  473. MCM_PLACR |= MCM_PLACR_CFCC;
  474. }
  475. flashaddr=(uint32_t)FLASH_BEGIN;
  476. for (i=0; i < EEPROM_SIZE; i++) {
  477. if (buf[i] == 0xFF) continue;
  478. if ((flashaddr & 2) == 0) {
  479. val = (buf[i] << 8) | i;
  480. } else {
  481. val = val | (buf[i] << 24) | (i << 16);
  482. flash_write(do_flash_cmd, flashaddr, val);
  483. }
  484. flashaddr += 2;
  485. }
  486. flashend = flashaddr;
  487. if ((flashaddr & 2)) {
  488. val |= 0xFFFF0000;
  489. flash_write(do_flash_cmd, flashaddr, val);
  490. }
  491. }
  492. }
  493. /*
  494. void do_flash_cmd(volatile uint8_t *fstat)
  495. {
  496. *fstat = 0x80;
  497. while ((*fstat & 0x80) == 0) ; // wait
  498. }
  499. 00000000 <do_flash_cmd>:
  500. 0: 2380 movs r3, #128 ; 0x80
  501. 2: 7003 strb r3, [r0, #0]
  502. 4: 7803 ldrb r3, [r0, #0]
  503. 6: b25b sxtb r3, r3
  504. 8: 2b00 cmp r3, #0
  505. a: dafb bge.n 4 <do_flash_cmd+0x4>
  506. c: 4770 bx lr
  507. */
  508. uint16_t eeprom_read_word(const uint16_t *addr)
  509. {
  510. const uint8_t *p = (const uint8_t *)addr;
  511. return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8);
  512. }
  513. uint32_t eeprom_read_dword(const uint32_t *addr)
  514. {
  515. const uint8_t *p = (const uint8_t *)addr;
  516. return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8)
  517. | (eeprom_read_byte(p+2) << 16) | (eeprom_read_byte(p+3) << 24);
  518. }
  519. void eeprom_read_block(void *buf, const void *addr, uint32_t len)
  520. {
  521. const uint8_t *p = (const uint8_t *)addr;
  522. uint8_t *dest = (uint8_t *)buf;
  523. while (len--) {
  524. *dest++ = eeprom_read_byte(p++);
  525. }
  526. }
  527. int eeprom_is_ready(void)
  528. {
  529. return 1;
  530. }
  531. void eeprom_write_word(uint16_t *addr, uint16_t value)
  532. {
  533. uint8_t *p = (uint8_t *)addr;
  534. eeprom_write_byte(p++, value);
  535. eeprom_write_byte(p, value >> 8);
  536. }
  537. void eeprom_write_dword(uint32_t *addr, uint32_t value)
  538. {
  539. uint8_t *p = (uint8_t *)addr;
  540. eeprom_write_byte(p++, value);
  541. eeprom_write_byte(p++, value >> 8);
  542. eeprom_write_byte(p++, value >> 16);
  543. eeprom_write_byte(p, value >> 24);
  544. }
  545. void eeprom_write_block(const void *buf, void *addr, uint32_t len)
  546. {
  547. uint8_t *p = (uint8_t *)addr;
  548. const uint8_t *src = (const uint8_t *)buf;
  549. while (len--) {
  550. eeprom_write_byte(p++, *src++);
  551. }
  552. }
  553. #endif // KINETISL