浏览代码

Add EEPROM emulation on Teensy-LC

teensy4-core
PaulStoffregen 10 年前
父节点
当前提交
86e6235e91
共有 3 个文件被更改,包括 213 次插入7 次删除
  1. +196
    -3
      teensy3/eeprom.c
  2. +9
    -1
      teensy3/kinetis.h
  3. +8
    -3
      teensy3/mk20dx128.c

+ 196
- 3
teensy3/eeprom.c 查看文件

@@ -32,6 +32,9 @@
#include <stdint.h>
//#include "HardwareSerial.h"


#if defined(KINETISK)

// 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,
@@ -279,9 +282,6 @@ void eeprom_write_block(const void *buf, void *addr, uint32_t len)
}
}




/*
void do_flash_cmd(volatile uint8_t *fstat)
{
@@ -297,3 +297,196 @@ void do_flash_cmd(volatile uint8_t *fstat)
e: 4770 bx lr
*/

#elif defined(KINETISL)

#define EEPROM_SIZE 128

#define FLASH_BEGIN (uint16_t *)63488
#define FLASH_END (uint16_t *)65536
static uint16_t flashend = 0;

void eeprom_initialize(void)
{
const uint16_t *p = FLASH_BEGIN;

do {
if (*p++ == 0xFFFF) {
flashend = (uint32_t)(p - 2);
return;
}
} while (p < FLASH_END);
flashend = (uint32_t)(FLASH_END - 1);
}

uint8_t eeprom_read_byte(const uint8_t *addr)
{
uint32_t offset = (uint32_t)addr;
const uint16_t *p = FLASH_BEGIN;
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 *)&FTFL_FCCOB3 = 0x06000000 | (addr & 0x00FFFFFC);
*(uint32_t *)&FTFL_FCCOB7 = data;
__disable_irq();
(*((void (*)(volatile uint8_t *))((uint32_t)code | 1)))(&FTFL_FSTAT);
__enable_irq();
stat = FTFL_FSTAT & 0x70;
if (stat) {
FTFL_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 < FLASH_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;
}
for (p = FLASH_BEGIN; p < FLASH_END; p++) {
val = *p;
if ((val & 255) < EEPROM_SIZE) {
buf[val & 255] = val >> 8;
}
}
buf[offset] = data;
for (flashaddr=(uint32_t)FLASH_BEGIN; flashaddr < (uint32_t)FLASH_END; flashaddr += 1024) {
*(uint32_t *)&FTFL_FCCOB3 = 0x09000000 | flashaddr;
__disable_irq();
(*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&FTFL_FSTAT);
__enable_irq();
val = FTFL_FSTAT & 0x70;
if (val) FTFL_FSTAT = val;
MCM_PLACR |= MCM_PLACR_CFCC;
}
flashaddr=(uint32_t)FLASH_BEGIN;
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++);
}
}


#endif // KINETISL

+ 9
- 1
teensy3/kinetis.h 查看文件

@@ -616,7 +616,15 @@ enum IRQ_NUMBER_t {
#elif defined(KINETISL)
#define MCM_PLASC (*(volatile uint16_t *)0xF0003008) // Crossbar Switch (AXBS) Slave Configuration
#define MCM_PLAMC (*(volatile uint16_t *)0xF000300A) // Crossbar Switch (AXBS) Master Configuration
#define MCM_PLACR (*(volatile uint32_t *)0xF000300C) // Platform Control Register
#define MCM_PLACR (*(volatile uint32_t *)0xF000300C) // Platform Control Register
#define MCM_PLACR_ESFC ((uint32_t)0x00010000) // Enable Stalling Flash Controller
#define MCM_PLACR_DFCS ((uint32_t)0x00008000) // Disable Flash Controller Speculation
#define MCM_PLACR_EFDS ((uint32_t)0x00004000) // Enable Flash Data Speculation
#define MCM_PLACR_DFCC ((uint32_t)0x00002000) // Disable Flash Controller Cache
#define MCM_PLACR_DFCIC ((uint32_t)0x00001000) // Disable Flash Controller Instruction Caching
#define MCM_PLACR_DFCDA ((uint32_t)0x00000800) // Disable Flash Controller Data Caching
#define MCM_PLACR_CFCC ((uint32_t)0x00000400) // Clear Flash Controller Cache
#define MCM_PLACR_ARB ((uint32_t)0x00000200) // Arbitration select
#define MCM_CPO (*(volatile uint32_t *)0xF0003040) // Compute Operation Control Register
#endif


+ 8
- 3
teensy3/mk20dx128.c 查看文件

@@ -29,8 +29,8 @@
*/

#include "kinetis.h"
//#include "core_pins.h" // testing only
//#include "ser_print.h" // testing only
#include "core_pins.h" // testing only
#include "ser_print.h" // testing only

extern unsigned long _stext;
extern unsigned long _etext;
@@ -54,7 +54,12 @@ void fault_isr(void)
{
#if 0
uint32_t addr;
digitalWriteFast(15, HIGH);

SIM_SCGC4 |= 0x00000400;
UART0_BDH = 0;
UART0_BDL = 26; // 115200 at 48 MHz
UART0_C2 = UART_C2_TE;
PORTB_PCR17 = PORT_PCR_MUX(3);
ser_print("\nfault: \n??: ");
asm("ldr %0, [sp, #52]" : "=r" (addr) ::);
ser_print_hex32(addr);

正在加载...
取消
保存