diff options
author | Joel Challis <git@zvecr.com> | 2021-11-19 18:41:02 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-19 10:41:02 -0800 |
commit | 2728603fe6d73e805a539d337fd01051c46ca806 (patch) | |
tree | 5c83ffc7efa112da870bd5d8502a9d91d4792f35 /tmk_core/common/chibios/eeprom_teensy.c | |
parent | 43b9e23bae12916d5161f03700c9bfe46737324b (diff) |
Move tmk_core/common/<plat> (#13918)
Diffstat (limited to 'tmk_core/common/chibios/eeprom_teensy.c')
-rw-r--r-- | tmk_core/common/chibios/eeprom_teensy.c | 795 |
1 files changed, 0 insertions, 795 deletions
diff --git a/tmk_core/common/chibios/eeprom_teensy.c b/tmk_core/common/chibios/eeprom_teensy.c deleted file mode 100644 index 97da6f9e14..0000000000 --- a/tmk_core/common/chibios/eeprom_teensy.c +++ /dev/null @@ -1,795 +0,0 @@ -#include <ch.h> -#include <hal.h> - -#include "eeconfig.h" - -/*************************************/ -/* Hardware backend */ -/* */ -/* Code from PJRC/Teensyduino */ -/*************************************/ - -/* Teensyduino Core Library - * http://www.pjrc.com/teensy/ - * Copyright (c) 2013 PJRC.COM, LLC. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * 1. The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * 2. If the Software is incorporated into a build system that allows - * selection among a list of target devices, then similar target - * devices manufactured by PJRC.COM must be included in the list of - * target devices and selectable in the same manner. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#define SMC_PMSTAT_RUN ((uint8_t)0x01) -#define SMC_PMSTAT_HSRUN ((uint8_t)0x80) - -#define F_CPU KINETIS_SYSCLK_FREQUENCY - -static inline int kinetis_hsrun_disable(void) { -#if defined(MK66F18) - if (SMC->PMSTAT == SMC_PMSTAT_HSRUN) { -// First, reduce the CPU clock speed, but do not change -// the peripheral speed (F_BUS). Serial1 & Serial2 baud -// rates will be impacted, but most other peripherals -// will continue functioning at the same speed. -# if F_CPU == 256000000 && F_BUS == 64000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 3, 1, 7); // TODO: TEST -# elif F_CPU == 256000000 && F_BUS == 128000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7); // TODO: TEST -# elif F_CPU == 240000000 && F_BUS == 60000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 3, 1, 7); // ok -# elif F_CPU == 240000000 && F_BUS == 80000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8); // ok -# elif F_CPU == 240000000 && F_BUS == 120000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7); // ok -# elif F_CPU == 216000000 && F_BUS == 54000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 3, 1, 7); // ok -# elif F_CPU == 216000000 && F_BUS == 72000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8); // ok -# elif F_CPU == 216000000 && F_BUS == 108000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7); // ok -# elif F_CPU == 192000000 && F_BUS == 48000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 3, 1, 7); // ok -# elif F_CPU == 192000000 && F_BUS == 64000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8); // ok -# elif F_CPU == 192000000 && F_BUS == 96000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7); // ok -# elif F_CPU == 180000000 && F_BUS == 60000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8); // ok -# elif F_CPU == 180000000 && F_BUS == 90000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7); // ok -# elif F_CPU == 168000000 && F_BUS == 56000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 5); // ok -# elif F_CPU == 144000000 && F_BUS == 48000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 5); // ok -# elif F_CPU == 144000000 && F_BUS == 72000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 5); // ok -# elif F_CPU == 120000000 && F_BUS == 60000000 - SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(KINETIS_CLKDIV1_OUTDIV1 - 1) | SIM_CLKDIV1_OUTDIV2(KINETIS_CLKDIV1_OUTDIV2 - 1) | -# if defined(MK66F18) - SIM_CLKDIV1_OUTDIV3(KINETIS_CLKDIV1_OUTDIV3 - 1) | -# endif - SIM_CLKDIV1_OUTDIV4(KINETIS_CLKDIV1_OUTDIV4 - 1); -# else - return 0; -# endif - // Then turn off HSRUN mode - SMC->PMCTRL = SMC_PMCTRL_RUNM_SET(0); - while (SMC->PMSTAT == SMC_PMSTAT_HSRUN) - ; // wait - return 1; - } -#endif - return 0; -} - -static inline int kinetis_hsrun_enable(void) { -#if defined(MK66F18) - if (SMC->PMSTAT == SMC_PMSTAT_RUN) { - // Turn HSRUN mode on - SMC->PMCTRL = SMC_PMCTRL_RUNM_SET(3); - while (SMC->PMSTAT != SMC_PMSTAT_HSRUN) { - ; - } // wait -// Then configure clock for full speed -# if F_CPU == 256000000 && F_BUS == 64000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 7); -# elif F_CPU == 256000000 && F_BUS == 128000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 7); -# elif F_CPU == 240000000 && F_BUS == 60000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 7); -# elif F_CPU == 240000000 && F_BUS == 80000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 7); -# elif F_CPU == 240000000 && F_BUS == 120000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 7); -# elif F_CPU == 216000000 && F_BUS == 54000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 7); -# elif F_CPU == 216000000 && F_BUS == 72000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 7); -# elif F_CPU == 216000000 && F_BUS == 108000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 7); -# elif F_CPU == 192000000 && F_BUS == 48000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 6); -# elif F_CPU == 192000000 && F_BUS == 64000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 6); -# elif F_CPU == 192000000 && F_BUS == 96000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 6); -# elif F_CPU == 180000000 && F_BUS == 60000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 6); -# elif F_CPU == 180000000 && F_BUS == 90000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 6); -# elif F_CPU == 168000000 && F_BUS == 56000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 5); -# elif F_CPU == 144000000 && F_BUS == 48000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 4); -# elif F_CPU == 144000000 && F_BUS == 72000000 - SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 4); -# elif F_CPU == 120000000 && F_BUS == 60000000 - SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(KINETIS_CLKDIV1_OUTDIV1 - 1) | SIM_CLKDIV1_OUTDIV2(KINETIS_CLKDIV1_OUTDIV2 - 1) | -# if defined(MK66F18) - SIM_CLKDIV1_OUTDIV3(KINETIS_CLKDIV1_OUTDIV3 - 1) | -# endif - SIM_CLKDIV1_OUTDIV4(KINETIS_CLKDIV1_OUTDIV4 - 1); -# else - return 0; -# endif - return 1; - } -#endif - return 0; -} - -#if defined(K20x) || defined(MK66F18) /* chip selection */ -/* Teensy 3.0, 3.1, 3.2; mchck; infinity keyboard */ - -// The EEPROM is really RAM with a hardware-based backup system to -// flash memory. Selecting a smaller size EEPROM allows more wear -// leveling, for higher write endurance. If you edit this file, -// set this to the smallest size your application can use. Also, -// due to Freescale's implementation, writing 16 or 32 bit words -// (aligned to 2 or 4 byte boundaries) has twice the endurance -// compared to writing 8 bit bytes. -// -# ifndef EEPROM_SIZE -# define EEPROM_SIZE 32 -# endif - -/* - ^^^ Here be dragons: - NXP AppNote AN4282 section 3.1 states that partitioning must only be done once. - Once EEPROM partitioning is done, the size is locked to this initial configuration. - Attempts to modify the EEPROM_SIZE setting may brick your board. -*/ - -// Writing unaligned 16 or 32 bit data is handled automatically when -// this is defined, but at a cost of extra code size. Without this, -// any unaligned write will cause a hard fault exception! If you're -// absolutely sure all 16 and 32 bit writes will be aligned, you can -// remove the extra unnecessary code. -// -# define HANDLE_UNALIGNED_WRITES - -# if defined(K20x) -# define EEPROM_MAX 2048 -# define EEPARTITION 0x03 // all 32K dataflash for EEPROM, none for Data -# define EEESPLIT 0x30 // must be 0x30 on these chips -# elif defined(MK66F18) -# define EEPROM_MAX 4096 -# define EEPARTITION 0x05 // 128K dataflash for EEPROM, 128K for Data -# define EEESPLIT 0x10 // best endurance: 0x00 = first 12%, 0x10 = first 25%, 0x30 = all equal -# endif - -// Minimum EEPROM Endurance -// ------------------------ -# if (EEPROM_SIZE == 4096) -# define EEESIZE 0x02 -# elif (EEPROM_SIZE == 2048) // 35000 writes/byte or 70000 writes/word -# define EEESIZE 0x03 -# elif (EEPROM_SIZE == 1024) // 75000 writes/byte or 150000 writes/word -# define EEESIZE 0x04 -# elif (EEPROM_SIZE == 512) // 155000 writes/byte or 310000 writes/word -# define EEESIZE 0x05 -# elif (EEPROM_SIZE == 256) // 315000 writes/byte or 630000 writes/word -# define EEESIZE 0x06 -# elif (EEPROM_SIZE == 128) // 635000 writes/byte or 1270000 writes/word -# define EEESIZE 0x07 -# elif (EEPROM_SIZE == 64) // 1275000 writes/byte or 2550000 writes/word -# define EEESIZE 0x08 -# elif (EEPROM_SIZE == 32) // 2555000 writes/byte or 5110000 writes/word -# define EEESIZE 0x09 -# endif - -/** \brief eeprom initialization - * - * FIXME: needs doc - */ -void eeprom_initialize(void) { - uint32_t count = 0; - uint16_t do_flash_cmd[] = {0xf06f, 0x037f, 0x7003, 0x7803, 0xf013, 0x0f80, 0xd0fb, 0x4770}; - uint8_t status; - - if (FTFL->FCNFG & FTFL_FCNFG_RAMRDY) { - uint8_t stat = FTFL->FSTAT & 0x70; - if (stat) FTFL->FSTAT = stat; - - // FlexRAM is configured as traditional RAM - // We need to reconfigure for EEPROM usage - kinetis_hsrun_disable(); - FTFL->FCCOB0 = 0x80; // PGMPART = Program Partition Command - FTFL->FCCOB3 = 0; - FTFL->FCCOB4 = EEESPLIT | EEESIZE; - FTFL->FCCOB5 = EEPARTITION; - __disable_irq(); - // do_flash_cmd() must execute from RAM. Luckily the C syntax is simple... - (*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&(FTFL->FSTAT)); - __enable_irq(); - kinetis_hsrun_enable(); - status = FTFL->FSTAT; - if (status & (FTFL_FSTAT_RDCOLERR | FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL)) { - FTFL->FSTAT = (status & (FTFL_FSTAT_RDCOLERR | FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL)); - return; // error - } - } - // wait for eeprom to become ready (is this really necessary?) - while (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) { - if (++count > 200000) break; - } -} - -# define FlexRAM ((volatile uint8_t *)0x14000000) - -/** \brief eeprom read byte - * - * FIXME: needs doc - */ -uint8_t eeprom_read_byte(const uint8_t *addr) { - uint32_t offset = (uint32_t)addr; - if (offset >= EEPROM_SIZE) return 0; - if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); - return FlexRAM[offset]; -} - -/** \brief eeprom read word - * - * FIXME: needs doc - */ -uint16_t eeprom_read_word(const uint16_t *addr) { - uint32_t offset = (uint32_t)addr; - if (offset >= EEPROM_SIZE - 1) return 0; - if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); - return *(uint16_t *)(&FlexRAM[offset]); -} - -/** \brief eeprom read dword - * - * FIXME: needs doc - */ -uint32_t eeprom_read_dword(const uint32_t *addr) { - uint32_t offset = (uint32_t)addr; - if (offset >= EEPROM_SIZE - 3) return 0; - if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); - return *(uint32_t *)(&FlexRAM[offset]); -} - -/** \brief eeprom read block - * - * FIXME: needs doc - */ -void eeprom_read_block(void *buf, const void *addr, uint32_t len) { - uint32_t offset = (uint32_t)addr; - uint8_t *dest = (uint8_t *)buf; - uint32_t end = offset + len; - - if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); - if (end > EEPROM_SIZE) end = EEPROM_SIZE; - while (offset < end) { - *dest++ = FlexRAM[offset++]; - } -} - -/** \brief eeprom is ready - * - * FIXME: needs doc - */ -int eeprom_is_ready(void) { return (FTFL->FCNFG & FTFL_FCNFG_EEERDY) ? 1 : 0; } - -/** \brief flexram wait - * - * FIXME: needs doc - */ -static void flexram_wait(void) { - while (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) { - // TODO: timeout - } -} - -/** \brief eeprom_write_byte - * - * FIXME: needs doc - */ -void eeprom_write_byte(uint8_t *addr, uint8_t value) { - uint32_t offset = (uint32_t)addr; - - if (offset >= EEPROM_SIZE) return; - if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); - if (FlexRAM[offset] != value) { - kinetis_hsrun_disable(); - uint8_t stat = FTFL->FSTAT & 0x70; - if (stat) FTFL->FSTAT = stat; - FlexRAM[offset] = value; - flexram_wait(); - kinetis_hsrun_enable(); - } -} - -/** \brief eeprom write word - * - * FIXME: needs doc - */ -void eeprom_write_word(uint16_t *addr, uint16_t value) { - uint32_t offset = (uint32_t)addr; - - if (offset >= EEPROM_SIZE - 1) return; - if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); -# ifdef HANDLE_UNALIGNED_WRITES - if ((offset & 1) == 0) { -# endif - if (*(uint16_t *)(&FlexRAM[offset]) != value) { - kinetis_hsrun_disable(); - uint8_t stat = FTFL->FSTAT & 0x70; - if (stat) FTFL->FSTAT = stat; - *(uint16_t *)(&FlexRAM[offset]) = value; - flexram_wait(); - kinetis_hsrun_enable(); - } -# ifdef HANDLE_UNALIGNED_WRITES - } else { - if (FlexRAM[offset] != value) { - kinetis_hsrun_disable(); - uint8_t stat = FTFL->FSTAT & 0x70; - if (stat) FTFL->FSTAT = stat; - FlexRAM[offset] = value; - flexram_wait(); - kinetis_hsrun_enable(); - } - if (FlexRAM[offset + 1] != (value >> 8)) { - kinetis_hsrun_disable(); - uint8_t stat = FTFL->FSTAT & 0x70; - if (stat) FTFL->FSTAT = stat; - FlexRAM[offset + 1] = value >> 8; - flexram_wait(); - kinetis_hsrun_enable(); - } - } -# endif -} - -/** \brief eeprom write dword - * - * FIXME: needs doc - */ -void eeprom_write_dword(uint32_t *addr, uint32_t value) { - uint32_t offset = (uint32_t)addr; - - if (offset >= EEPROM_SIZE - 3) return; - if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); -# ifdef HANDLE_UNALIGNED_WRITES - switch (offset & 3) { - case 0: -# endif - if (*(uint32_t *)(&FlexRAM[offset]) != value) { - kinetis_hsrun_disable(); - uint8_t stat = FTFL->FSTAT & 0x70; - if (stat) FTFL->FSTAT = stat; - *(uint32_t *)(&FlexRAM[offset]) = value; - flexram_wait(); - kinetis_hsrun_enable(); - } - return; -# ifdef HANDLE_UNALIGNED_WRITES - case 2: - if (*(uint16_t *)(&FlexRAM[offset]) != value) { - kinetis_hsrun_disable(); - uint8_t stat = FTFL->FSTAT & 0x70; - if (stat) FTFL->FSTAT = stat; - *(uint16_t *)(&FlexRAM[offset]) = value; - flexram_wait(); - kinetis_hsrun_enable(); - } - if (*(uint16_t *)(&FlexRAM[offset + 2]) != (value >> 16)) { - kinetis_hsrun_disable(); - uint8_t stat = FTFL->FSTAT & 0x70; - if (stat) FTFL->FSTAT = stat; - *(uint16_t *)(&FlexRAM[offset + 2]) = value >> 16; - flexram_wait(); - kinetis_hsrun_enable(); - } - return; - default: - if (FlexRAM[offset] != value) { - kinetis_hsrun_disable(); - uint8_t stat = FTFL->FSTAT & 0x70; - if (stat) FTFL->FSTAT = stat; - FlexRAM[offset] = value; - flexram_wait(); - kinetis_hsrun_enable(); - } - if (*(uint16_t *)(&FlexRAM[offset + 1]) != (value >> 8)) { - kinetis_hsrun_disable(); - uint8_t stat = FTFL->FSTAT & 0x70; - if (stat) FTFL->FSTAT = stat; - *(uint16_t *)(&FlexRAM[offset + 1]) = value >> 8; - flexram_wait(); - kinetis_hsrun_enable(); - } - if (FlexRAM[offset + 3] != (value >> 24)) { - kinetis_hsrun_disable(); - uint8_t stat = FTFL->FSTAT & 0x70; - if (stat) FTFL->FSTAT = stat; - FlexRAM[offset + 3] = value >> 24; - flexram_wait(); - kinetis_hsrun_enable(); - } - } -# endif -} - -/** \brief eeprom write block - * - * FIXME: needs doc - */ -void eeprom_write_block(const void *buf, void *addr, uint32_t len) { - uint32_t offset = (uint32_t)addr; - const uint8_t *src = (const uint8_t *)buf; - - if (offset >= EEPROM_SIZE) return; - if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); - if (len >= EEPROM_SIZE) len = EEPROM_SIZE; - if (offset + len >= EEPROM_SIZE) len = EEPROM_SIZE - offset; - kinetis_hsrun_disable(); - while (len > 0) { - uint32_t lsb = offset & 3; - if (lsb == 0 && len >= 4) { - // write aligned 32 bits - uint32_t val32; - val32 = *src++; - val32 |= (*src++ << 8); - val32 |= (*src++ << 16); - val32 |= (*src++ << 24); - if (*(uint32_t *)(&FlexRAM[offset]) != val32) { - uint8_t stat = FTFL->FSTAT & 0x70; - if (stat) FTFL->FSTAT = stat; - *(uint32_t *)(&FlexRAM[offset]) = val32; - flexram_wait(); - } - offset += 4; - len -= 4; - } else if ((lsb == 0 || lsb == 2) && len >= 2) { - // write aligned 16 bits - uint16_t val16; - val16 = *src++; - val16 |= (*src++ << 8); - if (*(uint16_t *)(&FlexRAM[offset]) != val16) { - uint8_t stat = FTFL->FSTAT & 0x70; - if (stat) FTFL->FSTAT = stat; - *(uint16_t *)(&FlexRAM[offset]) = val16; - flexram_wait(); - } - offset += 2; - len -= 2; - } else { - // write 8 bits - uint8_t val8 = *src++; - if (FlexRAM[offset] != val8) { - uint8_t stat = FTFL->FSTAT & 0x70; - if (stat) FTFL->FSTAT = stat; - FlexRAM[offset] = val8; - flexram_wait(); - } - offset++; - len--; - } - } - kinetis_hsrun_enable(); -} - -/* -void do_flash_cmd(volatile uint8_t *fstat) -{ - *fstat = 0x80; - while ((*fstat & 0x80) == 0) ; // wait -} -00000000 <do_flash_cmd>: - 0: f06f 037f mvn.w r3, #127 ; 0x7f - 4: 7003 strb r3, [r0, #0] - 6: 7803 ldrb r3, [r0, #0] - 8: f013 0f80 tst.w r3, #128 ; 0x80 - c: d0fb beq.n 6 <do_flash_cmd+0x6> - e: 4770 bx lr -*/ - -#elif defined(KL2x) /* chip selection */ -/* Teensy LC (emulated) */ - -# define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0)) - -extern uint32_t __eeprom_workarea_start__; -extern uint32_t __eeprom_workarea_end__; - -# define EEPROM_SIZE 128 - -static uint32_t flashend = 0; - -void eeprom_initialize(void) { - const uint16_t *p = (uint16_t *)SYMVAL(__eeprom_workarea_start__); - - do { - if (*p++ == 0xFFFF) { - flashend = (uint32_t)(p - 2); - return; - } - } while (p < (uint16_t *)SYMVAL(__eeprom_workarea_end__)); - flashend = (uint32_t)(p - 1); -} - -uint8_t eeprom_read_byte(const uint8_t *addr) { - uint32_t offset = (uint32_t)addr; - const uint16_t *p = (uint16_t *)SYMVAL(__eeprom_workarea_start__); - const uint16_t *end = (const uint16_t *)((uint32_t)flashend); - uint16_t val; - uint8_t data = 0xFF; - - if (!end) { - eeprom_initialize(); - end = (const uint16_t *)((uint32_t)flashend); - } - if (offset < EEPROM_SIZE) { - while (p <= end) { - val = *p++; - if ((val & 255) == offset) data = val >> 8; - } - } - return data; -} - -static void flash_write(const uint16_t *code, uint32_t addr, uint32_t data) { - // with great power comes great responsibility.... - uint32_t stat; - *(uint32_t *)&(FTFA->FCCOB3) = 0x06000000 | (addr & 0x00FFFFFC); - *(uint32_t *)&(FTFA->FCCOB7) = data; - __disable_irq(); - (*((void (*)(volatile uint8_t *))((uint32_t)code | 1)))(&(FTFA->FSTAT)); - __enable_irq(); - stat = FTFA->FSTAT & (FTFA_FSTAT_RDCOLERR | FTFA_FSTAT_ACCERR | FTFA_FSTAT_FPVIOL); - if (stat) { - FTFA->FSTAT = stat; - } - MCM->PLACR |= MCM_PLACR_CFCC; -} - -void eeprom_write_byte(uint8_t *addr, uint8_t data) { - uint32_t offset = (uint32_t)addr; - const uint16_t *p, *end = (const uint16_t *)((uint32_t)flashend); - uint32_t i, val, flashaddr; - uint16_t do_flash_cmd[] = {0x2380, 0x7003, 0x7803, 0xb25b, 0x2b00, 0xdafb, 0x4770}; - uint8_t buf[EEPROM_SIZE]; - - if (offset >= EEPROM_SIZE) return; - if (!end) { - eeprom_initialize(); - end = (const uint16_t *)((uint32_t)flashend); - } - if (++end < (uint16_t *)SYMVAL(__eeprom_workarea_end__)) { - val = (data << 8) | offset; - flashaddr = (uint32_t)end; - flashend = flashaddr; - if ((flashaddr & 2) == 0) { - val |= 0xFFFF0000; - } else { - val <<= 16; - val |= 0x0000FFFF; - } - flash_write(do_flash_cmd, flashaddr, val); - } else { - for (i = 0; i < EEPROM_SIZE; i++) { - buf[i] = 0xFF; - } - val = 0; - for (p = (uint16_t *)SYMVAL(__eeprom_workarea_start__); p < (uint16_t *)SYMVAL(__eeprom_workarea_end__); p++) { - val = *p; - if ((val & 255) < EEPROM_SIZE) { - buf[val & 255] = val >> 8; - } - } - buf[offset] = data; - for (flashaddr = (uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_start__); flashaddr < (uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_end__); flashaddr += 1024) { - *(uint32_t *)&(FTFA->FCCOB3) = 0x09000000 | flashaddr; - __disable_irq(); - (*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&(FTFA->FSTAT)); - __enable_irq(); - val = FTFA->FSTAT & (FTFA_FSTAT_RDCOLERR | FTFA_FSTAT_ACCERR | FTFA_FSTAT_FPVIOL); - ; - if (val) FTFA->FSTAT = val; - MCM->PLACR |= MCM_PLACR_CFCC; - } - flashaddr = (uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_start__); - for (i = 0; i < EEPROM_SIZE; i++) { - if (buf[i] == 0xFF) continue; - if ((flashaddr & 2) == 0) { - val = (buf[i] << 8) | i; - } else { - val = val | (buf[i] << 24) | (i << 16); - flash_write(do_flash_cmd, flashaddr, val); - } - flashaddr += 2; - } - flashend = flashaddr; - if ((flashaddr & 2)) { - val |= 0xFFFF0000; - flash_write(do_flash_cmd, flashaddr, val); - } - } -} - -/* -void do_flash_cmd(volatile uint8_t *fstat) -{ - *fstat = 0x80; - while ((*fstat & 0x80) == 0) ; // wait -} -00000000 <do_flash_cmd>: - 0: 2380 movs r3, #128 ; 0x80 - 2: 7003 strb r3, [r0, #0] - 4: 7803 ldrb r3, [r0, #0] - 6: b25b sxtb r3, r3 - 8: 2b00 cmp r3, #0 - a: dafb bge.n 4 <do_flash_cmd+0x4> - c: 4770 bx lr -*/ - -uint16_t eeprom_read_word(const uint16_t *addr) { - const uint8_t *p = (const uint8_t *)addr; - return eeprom_read_byte(p) | (eeprom_read_byte(p + 1) << 8); -} - -uint32_t eeprom_read_dword(const uint32_t *addr) { - const uint8_t *p = (const uint8_t *)addr; - return eeprom_read_byte(p) | (eeprom_read_byte(p + 1) << 8) | (eeprom_read_byte(p + 2) << 16) | (eeprom_read_byte(p + 3) << 24); -} - -void eeprom_read_block(void *buf, const void *addr, uint32_t len) { - const uint8_t *p = (const uint8_t *)addr; - uint8_t * dest = (uint8_t *)buf; - while (len--) { - *dest++ = eeprom_read_byte(p++); - } -} - -int eeprom_is_ready(void) { return 1; } - -void eeprom_write_word(uint16_t *addr, uint16_t value) { - uint8_t *p = (uint8_t *)addr; - eeprom_write_byte(p++, value); - eeprom_write_byte(p, value >> 8); -} - -void eeprom_write_dword(uint32_t *addr, uint32_t value) { - uint8_t *p = (uint8_t *)addr; - eeprom_write_byte(p++, value); - eeprom_write_byte(p++, value >> 8); - eeprom_write_byte(p++, value >> 16); - eeprom_write_byte(p, value >> 24); -} - -void eeprom_write_block(const void *buf, void *addr, uint32_t len) { - uint8_t * p = (uint8_t *)addr; - const uint8_t *src = (const uint8_t *)buf; - while (len--) { - eeprom_write_byte(p++, *src++); - } -} - -#else -// No EEPROM supported, so emulate it - -# ifndef EEPROM_SIZE -# include "eeconfig.h" -# define EEPROM_SIZE (((EECONFIG_SIZE + 3) / 4) * 4) // based off eeconfig's current usage, aligned to 4-byte sizes, to deal with LTO -# endif -__attribute__((aligned(4))) static uint8_t buffer[EEPROM_SIZE]; - -uint8_t eeprom_read_byte(const uint8_t *addr) { - uint32_t offset = (uint32_t)addr; - return buffer[offset]; -} - -void eeprom_write_byte(uint8_t *addr, uint8_t value) { - uint32_t offset = (uint32_t)addr; - buffer[offset] = value; -} - -uint16_t eeprom_read_word(const uint16_t *addr) { - const uint8_t *p = (const uint8_t *)addr; - return eeprom_read_byte(p) | (eeprom_read_byte(p + 1) << 8); -} - -uint32_t eeprom_read_dword(const uint32_t *addr) { - const uint8_t *p = (const uint8_t *)addr; - return eeprom_read_byte(p) | (eeprom_read_byte(p + 1) << 8) | (eeprom_read_byte(p + 2) << 16) | (eeprom_read_byte(p + 3) << 24); -} - -void eeprom_read_block(void *buf, const void *addr, size_t len) { - const uint8_t *p = (const uint8_t *)addr; - uint8_t * dest = (uint8_t *)buf; - while (len--) { - *dest++ = eeprom_read_byte(p++); - } -} - -void eeprom_write_word(uint16_t *addr, uint16_t value) { - uint8_t *p = (uint8_t *)addr; - eeprom_write_byte(p++, value); - eeprom_write_byte(p, value >> 8); -} - -void eeprom_write_dword(uint32_t *addr, uint32_t value) { - uint8_t *p = (uint8_t *)addr; - eeprom_write_byte(p++, value); - eeprom_write_byte(p++, value >> 8); - eeprom_write_byte(p++, value >> 16); - eeprom_write_byte(p, value >> 24); -} - -void eeprom_write_block(const void *buf, void *addr, size_t len) { - uint8_t * p = (uint8_t *)addr; - const uint8_t *src = (const uint8_t *)buf; - while (len--) { - eeprom_write_byte(p++, *src++); - } -} - -#endif /* chip selection */ -// The update functions just calls write for now, but could probably be optimized - -void eeprom_update_byte(uint8_t *addr, uint8_t value) { eeprom_write_byte(addr, value); } - -void eeprom_update_word(uint16_t *addr, uint16_t value) { - uint8_t *p = (uint8_t *)addr; - eeprom_write_byte(p++, value); - eeprom_write_byte(p, value >> 8); -} - -void eeprom_update_dword(uint32_t *addr, uint32_t value) { - uint8_t *p = (uint8_t *)addr; - eeprom_write_byte(p++, value); - eeprom_write_byte(p++, value >> 8); - eeprom_write_byte(p++, value >> 16); - eeprom_write_byte(p, value >> 24); -} - -void eeprom_update_block(const void *buf, void *addr, size_t len) { - uint8_t * p = (uint8_t *)addr; - const uint8_t *src = (const uint8_t *)buf; - while (len--) { - eeprom_write_byte(p++, *src++); - } -} |