| if (stat) FTFL_FSTAT = stat; | if (stat) FTFL_FSTAT = stat; | ||||
| // FlexRAM is configured as traditional RAM | // FlexRAM is configured as traditional RAM | ||||
| // We need to reconfigure for EEPROM usage | // We need to reconfigure for EEPROM usage | ||||
| kinetis_hsrun_disable(); | |||||
| FTFL_FCCOB0 = 0x80; // PGMPART = Program Partition Command | FTFL_FCCOB0 = 0x80; // PGMPART = Program Partition Command | ||||
| FTFL_FCCOB3 = 0; | FTFL_FCCOB3 = 0; | ||||
| FTFL_FCCOB4 = EEESPLIT | EEESIZE; | FTFL_FCCOB4 = EEESPLIT | EEESIZE; | ||||
| // do_flash_cmd() must execute from RAM. Luckily the C syntax is simple... | // 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); | (*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&FTFL_FSTAT); | ||||
| __enable_irq(); | __enable_irq(); | ||||
| kinetis_hsrun_enable(); | |||||
| status = FTFL_FSTAT; | status = FTFL_FSTAT; | ||||
| if (status & 0x70) { | if (status & 0x70) { | ||||
| FTFL_FSTAT = (status & 0x70); | FTFL_FSTAT = (status & 0x70); | ||||
| } | } | ||||
| } | } | ||||
| #if F_CPU > 120000000 && defined(__MK66FX1M0__) | |||||
| static volatile uint16_t c_intrestore = 0; | |||||
| void c_enable_irq( void ); | |||||
| void c_disable_irq( void ); | |||||
| static __inline__ uint32_t __get_primask(void) \ | |||||
| { uint32_t primask = 0; \ | |||||
| __asm__ volatile ("MRS %[result], PRIMASK\n\t":[result]"=r"(primask)::); \ | |||||
| return primask; } // returns 0 if interrupts enabled, 1 if disabled | |||||
| void c_enable_irq( void ){ | |||||
| if ( c_intrestore ) { | |||||
| c_intrestore =0; | |||||
| __enable_irq( ); | |||||
| } | |||||
| } | |||||
| void c_disable_irq( void ){ | |||||
| if ( !__get_primask() ) { // Returns 0 if they are enabled, or non-zero if disabled | |||||
| __disable_irq( ); | |||||
| c_intrestore = 1; | |||||
| } | |||||
| } | |||||
| static volatile uint8_t restore_hsrun = 0; | |||||
| static void hsrun_off(void) | |||||
| { | |||||
| if (SMC_PMSTAT == SMC_PMSTAT_HSRUN) { | |||||
| c_disable_irq( ); // Turn off interrupts for the DURATION !!!! | |||||
| SMC_PMCTRL = SMC_PMCTRL_RUNM(0); // exit HSRUN mode | |||||
| while (SMC_PMSTAT == SMC_PMSTAT_HSRUN) delayMicroseconds(2); // wait for !HSRUN | |||||
| delayMicroseconds(100); | |||||
| restore_hsrun = 1; | |||||
| } | |||||
| } | |||||
| static void hsrun_on(void) | |||||
| { | |||||
| if (restore_hsrun) { | |||||
| SMC_PMCTRL = SMC_PMCTRL_RUNM(3); // enter HSRUN mode | |||||
| while (SMC_PMSTAT != SMC_PMSTAT_HSRUN) delayMicroseconds(2);; // wait for HSRUN | |||||
| restore_hsrun = 0; | |||||
| c_enable_irq( ); // Restore interrupts only when HSRUN restored } | |||||
| } | |||||
| } | |||||
| #else | |||||
| #define hsrun_off() | |||||
| #define hsrun_on() | |||||
| #endif | |||||
| void eeprom_write_byte(uint8_t *addr, uint8_t value) | void eeprom_write_byte(uint8_t *addr, uint8_t value) | ||||
| { | { | ||||
| uint32_t offset = (uint32_t)addr; | uint32_t offset = (uint32_t)addr; | ||||
| if (offset >= EEPROM_SIZE) return; | if (offset >= EEPROM_SIZE) return; | ||||
| if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); | if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); | ||||
| hsrun_off(); | |||||
| if (FlexRAM[offset] != value) { | if (FlexRAM[offset] != value) { | ||||
| kinetis_hsrun_disable(); | |||||
| uint8_t stat = FTFL_FSTAT & 0x70; | uint8_t stat = FTFL_FSTAT & 0x70; | ||||
| if (stat) FTFL_FSTAT = stat; | if (stat) FTFL_FSTAT = stat; | ||||
| FlexRAM[offset] = value; | FlexRAM[offset] = value; | ||||
| flexram_wait(); | flexram_wait(); | ||||
| kinetis_hsrun_enable(); | |||||
| } | } | ||||
| hsrun_on(); | |||||
| } | } | ||||
| void eeprom_write_word(uint16_t *addr, uint16_t value) | void eeprom_write_word(uint16_t *addr, uint16_t value) | ||||
| if (offset >= EEPROM_SIZE-1) return; | if (offset >= EEPROM_SIZE-1) return; | ||||
| if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); | if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); | ||||
| hsrun_off(); | |||||
| #ifdef HANDLE_UNALIGNED_WRITES | #ifdef HANDLE_UNALIGNED_WRITES | ||||
| if ((offset & 1) == 0) { | if ((offset & 1) == 0) { | ||||
| #endif | #endif | ||||
| if (*(uint16_t *)(&FlexRAM[offset]) != value) { | if (*(uint16_t *)(&FlexRAM[offset]) != value) { | ||||
| kinetis_hsrun_disable(); | |||||
| uint8_t stat = FTFL_FSTAT & 0x70; | uint8_t stat = FTFL_FSTAT & 0x70; | ||||
| if (stat) FTFL_FSTAT = stat; | if (stat) FTFL_FSTAT = stat; | ||||
| *(uint16_t *)(&FlexRAM[offset]) = value; | *(uint16_t *)(&FlexRAM[offset]) = value; | ||||
| flexram_wait(); | flexram_wait(); | ||||
| kinetis_hsrun_enable(); | |||||
| } | } | ||||
| #ifdef HANDLE_UNALIGNED_WRITES | #ifdef HANDLE_UNALIGNED_WRITES | ||||
| } else { | } else { | ||||
| if (FlexRAM[offset] != value) { | if (FlexRAM[offset] != value) { | ||||
| kinetis_hsrun_disable(); | |||||
| uint8_t stat = FTFL_FSTAT & 0x70; | uint8_t stat = FTFL_FSTAT & 0x70; | ||||
| if (stat) FTFL_FSTAT = stat; | if (stat) FTFL_FSTAT = stat; | ||||
| FlexRAM[offset] = value; | FlexRAM[offset] = value; | ||||
| flexram_wait(); | flexram_wait(); | ||||
| kinetis_hsrun_enable(); | |||||
| } | } | ||||
| if (FlexRAM[offset + 1] != (value >> 8)) { | if (FlexRAM[offset + 1] != (value >> 8)) { | ||||
| kinetis_hsrun_disable(); | |||||
| uint8_t stat = FTFL_FSTAT & 0x70; | uint8_t stat = FTFL_FSTAT & 0x70; | ||||
| if (stat) FTFL_FSTAT = stat; | if (stat) FTFL_FSTAT = stat; | ||||
| FlexRAM[offset + 1] = value >> 8; | FlexRAM[offset + 1] = value >> 8; | ||||
| flexram_wait(); | flexram_wait(); | ||||
| kinetis_hsrun_enable(); | |||||
| } | } | ||||
| } | } | ||||
| #endif | #endif | ||||
| hsrun_on(); | |||||
| } | } | ||||
| void eeprom_write_dword(uint32_t *addr, uint32_t value) | void eeprom_write_dword(uint32_t *addr, uint32_t value) | ||||
| if (offset >= EEPROM_SIZE-3) return; | if (offset >= EEPROM_SIZE-3) return; | ||||
| if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); | if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); | ||||
| hsrun_off(); | |||||
| #ifdef HANDLE_UNALIGNED_WRITES | #ifdef HANDLE_UNALIGNED_WRITES | ||||
| switch (offset & 3) { | switch (offset & 3) { | ||||
| case 0: | case 0: | ||||
| #endif | #endif | ||||
| if (*(uint32_t *)(&FlexRAM[offset]) != value) { | if (*(uint32_t *)(&FlexRAM[offset]) != value) { | ||||
| kinetis_hsrun_disable(); | |||||
| uint8_t stat = FTFL_FSTAT & 0x70; | uint8_t stat = FTFL_FSTAT & 0x70; | ||||
| if (stat) FTFL_FSTAT = stat; | if (stat) FTFL_FSTAT = stat; | ||||
| *(uint32_t *)(&FlexRAM[offset]) = value; | *(uint32_t *)(&FlexRAM[offset]) = value; | ||||
| flexram_wait(); | flexram_wait(); | ||||
| kinetis_hsrun_enable(); | |||||
| } | } | ||||
| hsrun_on(); | |||||
| return; | return; | ||||
| #ifdef HANDLE_UNALIGNED_WRITES | #ifdef HANDLE_UNALIGNED_WRITES | ||||
| case 2: | case 2: | ||||
| if (*(uint16_t *)(&FlexRAM[offset]) != value) { | if (*(uint16_t *)(&FlexRAM[offset]) != value) { | ||||
| kinetis_hsrun_disable(); | |||||
| uint8_t stat = FTFL_FSTAT & 0x70; | uint8_t stat = FTFL_FSTAT & 0x70; | ||||
| if (stat) FTFL_FSTAT = stat; | if (stat) FTFL_FSTAT = stat; | ||||
| *(uint16_t *)(&FlexRAM[offset]) = value; | *(uint16_t *)(&FlexRAM[offset]) = value; | ||||
| flexram_wait(); | flexram_wait(); | ||||
| kinetis_hsrun_enable(); | |||||
| } | } | ||||
| if (*(uint16_t *)(&FlexRAM[offset + 2]) != (value >> 16)) { | if (*(uint16_t *)(&FlexRAM[offset + 2]) != (value >> 16)) { | ||||
| kinetis_hsrun_disable(); | |||||
| uint8_t stat = FTFL_FSTAT & 0x70; | uint8_t stat = FTFL_FSTAT & 0x70; | ||||
| if (stat) FTFL_FSTAT = stat; | if (stat) FTFL_FSTAT = stat; | ||||
| *(uint16_t *)(&FlexRAM[offset + 2]) = value >> 16; | *(uint16_t *)(&FlexRAM[offset + 2]) = value >> 16; | ||||
| flexram_wait(); | flexram_wait(); | ||||
| kinetis_hsrun_enable(); | |||||
| } | } | ||||
| hsrun_on(); | |||||
| return; | return; | ||||
| default: | default: | ||||
| if (FlexRAM[offset] != value) { | if (FlexRAM[offset] != value) { | ||||
| kinetis_hsrun_disable(); | |||||
| uint8_t stat = FTFL_FSTAT & 0x70; | uint8_t stat = FTFL_FSTAT & 0x70; | ||||
| if (stat) FTFL_FSTAT = stat; | if (stat) FTFL_FSTAT = stat; | ||||
| FlexRAM[offset] = value; | FlexRAM[offset] = value; | ||||
| flexram_wait(); | flexram_wait(); | ||||
| kinetis_hsrun_enable(); | |||||
| } | } | ||||
| if (*(uint16_t *)(&FlexRAM[offset + 1]) != (value >> 8)) { | if (*(uint16_t *)(&FlexRAM[offset + 1]) != (value >> 8)) { | ||||
| kinetis_hsrun_disable(); | |||||
| uint8_t stat = FTFL_FSTAT & 0x70; | uint8_t stat = FTFL_FSTAT & 0x70; | ||||
| if (stat) FTFL_FSTAT = stat; | if (stat) FTFL_FSTAT = stat; | ||||
| *(uint16_t *)(&FlexRAM[offset + 1]) = value >> 8; | *(uint16_t *)(&FlexRAM[offset + 1]) = value >> 8; | ||||
| flexram_wait(); | flexram_wait(); | ||||
| kinetis_hsrun_enable(); | |||||
| } | } | ||||
| if (FlexRAM[offset + 3] != (value >> 24)) { | if (FlexRAM[offset + 3] != (value >> 24)) { | ||||
| kinetis_hsrun_disable(); | |||||
| uint8_t stat = FTFL_FSTAT & 0x70; | uint8_t stat = FTFL_FSTAT & 0x70; | ||||
| if (stat) FTFL_FSTAT = stat; | if (stat) FTFL_FSTAT = stat; | ||||
| FlexRAM[offset + 3] = value >> 24; | FlexRAM[offset + 3] = value >> 24; | ||||
| flexram_wait(); | flexram_wait(); | ||||
| kinetis_hsrun_enable(); | |||||
| } | } | ||||
| } | } | ||||
| #endif | #endif | ||||
| hsrun_on(); | |||||
| } | } | ||||
| void eeprom_write_block(const void *buf, void *addr, uint32_t len) | void eeprom_write_block(const void *buf, void *addr, uint32_t len) | ||||
| if (offset >= EEPROM_SIZE) return; | if (offset >= EEPROM_SIZE) return; | ||||
| if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); | if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); | ||||
| hsrun_off(); | |||||
| if (len >= EEPROM_SIZE) len = EEPROM_SIZE; | if (len >= EEPROM_SIZE) len = EEPROM_SIZE; | ||||
| if (offset + len >= EEPROM_SIZE) len = EEPROM_SIZE - offset; | if (offset + len >= EEPROM_SIZE) len = EEPROM_SIZE - offset; | ||||
| while (len > 0) { | while (len > 0) { | ||||
| val32 |= (*src++ << 16); | val32 |= (*src++ << 16); | ||||
| val32 |= (*src++ << 24); | val32 |= (*src++ << 24); | ||||
| if (*(uint32_t *)(&FlexRAM[offset]) != val32) { | if (*(uint32_t *)(&FlexRAM[offset]) != val32) { | ||||
| kinetis_hsrun_disable(); | |||||
| uint8_t stat = FTFL_FSTAT & 0x70; | uint8_t stat = FTFL_FSTAT & 0x70; | ||||
| if (stat) FTFL_FSTAT = stat; | if (stat) FTFL_FSTAT = stat; | ||||
| *(uint32_t *)(&FlexRAM[offset]) = val32; | *(uint32_t *)(&FlexRAM[offset]) = val32; | ||||
| flexram_wait(); | flexram_wait(); | ||||
| kinetis_hsrun_enable(); | |||||
| } | } | ||||
| offset += 4; | offset += 4; | ||||
| len -= 4; | len -= 4; | ||||
| val16 = *src++; | val16 = *src++; | ||||
| val16 |= (*src++ << 8); | val16 |= (*src++ << 8); | ||||
| if (*(uint16_t *)(&FlexRAM[offset]) != val16) { | if (*(uint16_t *)(&FlexRAM[offset]) != val16) { | ||||
| kinetis_hsrun_disable(); | |||||
| uint8_t stat = FTFL_FSTAT & 0x70; | uint8_t stat = FTFL_FSTAT & 0x70; | ||||
| if (stat) FTFL_FSTAT = stat; | if (stat) FTFL_FSTAT = stat; | ||||
| *(uint16_t *)(&FlexRAM[offset]) = val16; | *(uint16_t *)(&FlexRAM[offset]) = val16; | ||||
| flexram_wait(); | flexram_wait(); | ||||
| kinetis_hsrun_enable(); | |||||
| } | } | ||||
| offset += 2; | offset += 2; | ||||
| len -= 2; | len -= 2; | ||||
| // write 8 bits | // write 8 bits | ||||
| uint8_t val8 = *src++; | uint8_t val8 = *src++; | ||||
| if (FlexRAM[offset] != val8) { | if (FlexRAM[offset] != val8) { | ||||
| kinetis_hsrun_disable(); | |||||
| uint8_t stat = FTFL_FSTAT & 0x70; | uint8_t stat = FTFL_FSTAT & 0x70; | ||||
| if (stat) FTFL_FSTAT = stat; | if (stat) FTFL_FSTAT = stat; | ||||
| FlexRAM[offset] = val8; | FlexRAM[offset] = val8; | ||||
| flexram_wait(); | flexram_wait(); | ||||
| kinetis_hsrun_enable(); | |||||
| } | } | ||||
| offset++; | offset++; | ||||
| len--; | len--; | ||||
| } | } | ||||
| } | } | ||||
| hsrun_on(); | |||||
| } | } | ||||
| /* | /* |