REDAC HybridController
Firmware for LUCIDAC/REDAC Teensy
Loading...
Searching...
No Matches
eeprom.cpp
Go to the documentation of this file.
1/* Teensyduino Core Library
2 * http://www.pjrc.com/teensy/
3 * Copyright (c) 2019 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
31// To configure the EEPROM size, edit E2END in avr/eeprom.h.
32//
33// Generally you should avoid editing this code, unless you really
34// know what you're doing.
35
36#include "imxrt.h"
37#include <avr/eeprom.h>
38#include <string.h>
39#include <avr/pgmspace.h>
40
41#include "debug/printf.h"
42
43#if defined(ARDUINO_TEENSY40)
44#define FLASH_BASEADDR 0x601F0000
45#define FLASH_SECTORS 15
46#elif defined(ARDUINO_TEENSY41)
47#define FLASH_BASEADDR 0x607C0000
48#define FLASH_SECTORS 63
49#elif defined(ARDUINO_TEENSY_MICROMOD)
50#define FLASH_BASEADDR 0x60FC0000
51#define FLASH_SECTORS 63
52#endif
53
54
55#if E2END > (255*FLASH_SECTORS-1)
56#error "E2END is set larger than the maximum possible EEPROM size"
57#endif
58
59// Conversation about how this code works & what the upper limits are
60// https://forum.pjrc.com/threads/57377?p=214566&viewfull=1#post214566
61
62// To be called from LittleFS_Program, any other use at your own risk!
63void flash_write(void *addr, const void *data, uint32_t len);
64void flash_erase_sector(void *addr);
65void flash_erase_32K_block(void *addr);
66void flash_erase_64K_block(void *addr);
67
68#define LUT0(opcode, pads, operand) (FLEXSPI_LUT_INSTRUCTION((opcode), (pads), (operand)))
69#define LUT1(opcode, pads, operand) (FLEXSPI_LUT_INSTRUCTION((opcode), (pads), (operand)) << 16)
70#define CMD_SDR FLEXSPI_LUT_OPCODE_CMD_SDR
71#define ADDR_SDR FLEXSPI_LUT_OPCODE_RADDR_SDR
72#define READ_SDR FLEXSPI_LUT_OPCODE_READ_SDR
73#define WRITE_SDR FLEXSPI_LUT_OPCODE_WRITE_SDR
74#define PINS1 FLEXSPI_LUT_NUM_PADS_1
75#define PINS4 FLEXSPI_LUT_NUM_PADS_4
76
77FASTRUN
78static void flash_wait()
79{
80 FLEXSPI_LUT60 = LUT0(CMD_SDR, PINS1, 0x05) | LUT1(READ_SDR, PINS1, 1); // 05 = read status
81 FLEXSPI_LUT61 = 0;
82 uint8_t status;
83 do {
84 FLEXSPI_IPRXFCR = FLEXSPI_IPRXFCR_CLRIPRXF; // clear rx fifo
85 FLEXSPI_IPCR0 = 0;
86 FLEXSPI_IPCR1 = FLEXSPI_IPCR1_ISEQID(15) | FLEXSPI_IPCR1_IDATSZ(1);
87 FLEXSPI_IPCMD = FLEXSPI_IPCMD_TRG;
88 while (!(FLEXSPI_INTR & FLEXSPI_INTR_IPCMDDONE)) {;}
89 FLEXSPI_INTR = FLEXSPI_INTR_IPCMDDONE;
90 asm("":::"memory");
91 status = *(uint8_t *)&FLEXSPI_RFDR0;
92 } while (status & 1);
93 FLEXSPI_MCR0 |= FLEXSPI_MCR0_SWRESET; // purge stale data from FlexSPI's AHB FIFO
94 while (FLEXSPI_MCR0 & FLEXSPI_MCR0_SWRESET) ; // wait
95}
96
97// write bytes into flash memory (which is already erased to 0xFF)
98FASTRUN
99void flash_write(void *addr, const void *data, uint32_t len)
100{
101 FLEXSPI_LUTKEY = FLEXSPI_LUTKEY_VALUE;
102 FLEXSPI_LUTCR = FLEXSPI_LUTCR_UNLOCK;
103 FLEXSPI_IPCR0 = 0;
104 FLEXSPI_LUT60 = LUT0(CMD_SDR, PINS1, 0x06); // 06 = write enable
105 FLEXSPI_LUT61 = 0;
106 FLEXSPI_LUT62 = 0;
107 FLEXSPI_LUT63 = 0;
108 FLEXSPI_IPCR1 = FLEXSPI_IPCR1_ISEQID(15);
109 FLEXSPI_IPCMD = FLEXSPI_IPCMD_TRG;
110 arm_dcache_delete(addr, len); // purge old data from ARM's cache
111 while (!(FLEXSPI_INTR & FLEXSPI_INTR_IPCMDDONE)) ; // wait
112 FLEXSPI_INTR = FLEXSPI_INTR_IPCMDDONE;
113 FLEXSPI_LUT60 = LUT0(CMD_SDR, PINS1, 0x32) | LUT1(ADDR_SDR, PINS1, 24); // 32 = quad write
114 FLEXSPI_LUT61 = LUT0(WRITE_SDR, PINS4, 1);
115 FLEXSPI_IPTXFCR = FLEXSPI_IPTXFCR_CLRIPTXF; // clear tx fifo
116 FLEXSPI_IPCR0 = (uint32_t)addr & 0x00FFFFFF;
117 FLEXSPI_IPCR1 = FLEXSPI_IPCR1_ISEQID(15) | FLEXSPI_IPCR1_IDATSZ(len);
118 FLEXSPI_IPCMD = FLEXSPI_IPCMD_TRG;
119 const uint8_t *src = (const uint8_t *)data;
120 uint32_t n;
121 while (!((n = FLEXSPI_INTR) & FLEXSPI_INTR_IPCMDDONE)) {
122 if (n & FLEXSPI_INTR_IPTXWE) {
123 uint32_t wrlen = len;
124 if (wrlen > 8) wrlen = 8;
125 if (wrlen > 0) {
126 memcpy((void *)&FLEXSPI_TFDR0, src, wrlen);
127 src += wrlen;
128 len -= wrlen;
129 }
130 FLEXSPI_INTR = FLEXSPI_INTR_IPTXWE;
131 }
132 }
133 FLEXSPI_INTR = FLEXSPI_INTR_IPCMDDONE | FLEXSPI_INTR_IPTXWE;
134 flash_wait();
135}
136
137// erase a 4K sector
138FASTRUN
139void flash_erase_sector(void *addr)
140{
141 FLEXSPI_LUTKEY = FLEXSPI_LUTKEY_VALUE;
142 FLEXSPI_LUTCR = FLEXSPI_LUTCR_UNLOCK;
143 FLEXSPI_LUT60 = LUT0(CMD_SDR, PINS1, 0x06); // 06 = write enable
144 FLEXSPI_LUT61 = 0;
145 FLEXSPI_LUT62 = 0;
146 FLEXSPI_LUT63 = 0;
147 FLEXSPI_IPCR0 = 0;
148 FLEXSPI_IPCR1 = FLEXSPI_IPCR1_ISEQID(15);
149 FLEXSPI_IPCMD = FLEXSPI_IPCMD_TRG;
150 arm_dcache_delete((void *)((uint32_t)addr & 0xFFFFF000), 4096); // purge data from cache
151 while (!(FLEXSPI_INTR & FLEXSPI_INTR_IPCMDDONE)) ; // wait
152 FLEXSPI_INTR = FLEXSPI_INTR_IPCMDDONE;
153 FLEXSPI_LUT60 = LUT0(CMD_SDR, PINS1, 0x20) | LUT1(ADDR_SDR, PINS1, 24); // 20 = sector erase
154 FLEXSPI_IPCR0 = (uint32_t)addr & 0x00FFF000;
155 FLEXSPI_IPCR1 = FLEXSPI_IPCR1_ISEQID(15);
156 FLEXSPI_IPCMD = FLEXSPI_IPCMD_TRG;
157 while (!(FLEXSPI_INTR & FLEXSPI_INTR_IPCMDDONE)) ; // wait
158 FLEXSPI_INTR = FLEXSPI_INTR_IPCMDDONE;
159 flash_wait();
160}
161
162FASTRUN
163void flash_erase_32K_block(void *addr)
164{
165 FLEXSPI_LUTKEY = FLEXSPI_LUTKEY_VALUE;
166 FLEXSPI_LUTCR = FLEXSPI_LUTCR_UNLOCK;
167 FLEXSPI_LUT60 = LUT0(CMD_SDR, PINS1, 0x06); // 06 = write enable
168 FLEXSPI_LUT61 = 0;
169 FLEXSPI_LUT62 = 0;
170 FLEXSPI_LUT63 = 0;
171 FLEXSPI_IPCR0 = 0;
172 FLEXSPI_IPCR1 = FLEXSPI_IPCR1_ISEQID(15);
173 FLEXSPI_IPCMD = FLEXSPI_IPCMD_TRG;
174 arm_dcache_delete((void *)((uint32_t)addr & 0xFFFF8000), 32768); // purge data from cache
175 while (!(FLEXSPI_INTR & FLEXSPI_INTR_IPCMDDONE)) ; // wait
176 FLEXSPI_INTR = FLEXSPI_INTR_IPCMDDONE;
177 FLEXSPI_LUT60 = LUT0(CMD_SDR, PINS1, 0x52) | LUT1(ADDR_SDR, PINS1, 24); // 52 = 32K erase
178 FLEXSPI_IPCR0 = (uint32_t)addr & 0x00FF8000;
179 FLEXSPI_IPCR1 = FLEXSPI_IPCR1_ISEQID(15);
180 FLEXSPI_IPCMD = FLEXSPI_IPCMD_TRG;
181 while (!(FLEXSPI_INTR & FLEXSPI_INTR_IPCMDDONE)) ; // wait
182 FLEXSPI_INTR = FLEXSPI_INTR_IPCMDDONE;
183 flash_wait();
184}
185
186FASTRUN
187void flash_erase_64K_block(void *addr)
188{
189 FLEXSPI_LUTKEY = FLEXSPI_LUTKEY_VALUE;
190 FLEXSPI_LUTCR = FLEXSPI_LUTCR_UNLOCK;
191 FLEXSPI_LUT60 = LUT0(CMD_SDR, PINS1, 0x06); // 06 = write enable
192 FLEXSPI_LUT61 = 0;
193 FLEXSPI_LUT62 = 0;
194 FLEXSPI_LUT63 = 0;
195 FLEXSPI_IPCR0 = 0;
196 FLEXSPI_IPCR1 = FLEXSPI_IPCR1_ISEQID(15);
197 FLEXSPI_IPCMD = FLEXSPI_IPCMD_TRG;
198 arm_dcache_delete((void *)((uint32_t)addr & 0xFFFF0000), 65536); // purge data from cache
199 while (!(FLEXSPI_INTR & FLEXSPI_INTR_IPCMDDONE)) ; // wait
200 FLEXSPI_INTR = FLEXSPI_INTR_IPCMDDONE;
201 FLEXSPI_LUT60 = LUT0(CMD_SDR, PINS1, 0xD8) | LUT1(ADDR_SDR, PINS1, 24); // D8 = 64K erase
202 FLEXSPI_IPCR0 = (uint32_t)addr & 0x00FF0000;
203 FLEXSPI_IPCR1 = FLEXSPI_IPCR1_ISEQID(15);
204 FLEXSPI_IPCMD = FLEXSPI_IPCMD_TRG;
205 while (!(FLEXSPI_INTR & FLEXSPI_INTR_IPCMDDONE)) ; // wait
206 FLEXSPI_INTR = FLEXSPI_INTR_IPCMDDONE;
207 flash_wait();
208}
UnitResult status
Definition daq.h:21
#define PINS4
Definition eeprom.cpp:75
#define ADDR_SDR
Definition eeprom.cpp:71
void flash_write(void *addr, const void *data, uint32_t len)
Definition eeprom.cpp:99
#define WRITE_SDR
Definition eeprom.cpp:73
void flash_erase_64K_block(void *addr)
Definition eeprom.cpp:187
static FASTRUN void flash_wait()
Definition eeprom.cpp:78
#define READ_SDR
Definition eeprom.cpp:72
#define LUT1(opcode, pads, operand)
Definition eeprom.cpp:69
void flash_erase_32K_block(void *addr)
Definition eeprom.cpp:163
#define PINS1
Definition eeprom.cpp:74
void flash_erase_sector(void *addr)
Definition eeprom.cpp:139
#define LUT0(opcode, pads, operand)
Definition eeprom.cpp:68
#define CMD_SDR
Definition eeprom.cpp:70