7bc3eef8cc262e12b0f823ba4c92cf97ca3dc1fa
- Author
- Nick Brassel <nick@tzarc.org>
- Committer
- GitHub <noreply@github.com>
- Date
Message
Diff
This diff is truncated to protect this page.
1diff --git a/builddefs/common_features.mk b/builddefs/common_features.mk
2index 68f9a1dd08a8f03ad311768d49af0f9afef81aa3..498614dd2641f47c65492275e115e14aff2e2d91 100644
3--- a/builddefs/common_features.mk
4+++ b/builddefs/common_features.mk
5@@ -282,18 +282,17 @@ ifneq ($(strip $(WEAR_LEVELING_DRIVER)),none)
6 endif
7 endif
8
9-VALID_FLASH_DRIVER_TYPES := spi
10+VALID_FLASH_DRIVER_TYPES := spi custom
11 FLASH_DRIVER ?= none
12 ifneq ($(strip $(FLASH_DRIVER)), none)
13 ifeq ($(filter $(FLASH_DRIVER),$(VALID_FLASH_DRIVER_TYPES)),)
14 $(call CATASTROPHIC_ERROR,Invalid FLASH_DRIVER,FLASH_DRIVER="$(FLASH_DRIVER)" is not a valid flash driver)
15 else
16- OPT_DEFS += -DFLASH_ENABLE
17+ OPT_DEFS += -DFLASH_ENABLE -DFLASH_DRIVER -DFLASH_DRIVER_$(strip $(shell echo $(FLASH_DRIVER) | tr '[:lower:]' '[:upper:]'))
18+ COMMON_VPATH += $(DRIVER_PATH)/flash
19 ifeq ($(strip $(FLASH_DRIVER)),spi)
20- SPI_DRIVER_REQUIRED = yes
21- OPT_DEFS += -DFLASH_DRIVER -DFLASH_SPI
22- COMMON_VPATH += $(DRIVER_PATH)/flash
23 SRC += flash_spi.c
24+ SPI_DRIVER_REQUIRED = yes
25 endif
26 endif
27 endif
28diff --git a/drivers/flash/flash.h b/drivers/flash/flash.h
29new file mode 100644
30index 0000000000000000000000000000000000000000..4d6247513987c748994361c3b95c971e25d70f06
31--- /dev/null
32+++ b/drivers/flash/flash.h
33@@ -0,0 +1,126 @@
34+// Copyright 2024 Nick Brassel (@tzarc)
35+// SPDX-License-Identifier: GPL-2.0-or-later
36+#pragma once
37+
38+#ifdef __cplusplus
39+extern "C" {
40+#endif
41+
42+#include <stdint.h>
43+#include <stdlib.h>
44+#include <stdbool.h>
45+
46+/**
47+ * @brief The status of a flash operation.
48+ */
49+enum {
50+ FLASH_STATUS_SUCCESS = 0, //< The operation completed successfully.
51+ FLASH_STATUS_ERROR = -1, //< An error occurred during the operation.
52+ FLASH_STATUS_TIMEOUT = -2, //< The operation timed out.
53+ FLASH_STATUS_BAD_ADDRESS = -3, //< The address is out of bounds.
54+ FLASH_STATUS_BUSY = -4, //< The flash is busy.
55+};
56+
57+/**
58+ * @brief The status of a flash operation.
59+ */
60+typedef int16_t flash_status_t;
61+
62+/**
63+ * @brief Initializes the flash driver.
64+ *
65+ * This function initializes the flash driver and prepares it for use.
66+ * It should be called before any other flash-related functions are used.
67+ */
68+void flash_init(void);
69+
70+/**
71+ * @brief Checks if the flash is busy.
72+ *
73+ * This function checks if the flash is currently busy with an operation.
74+ *
75+ * @return FLASH_STATUS_SUCCESS if the flash is not busy, FLASH_STATUS_BUSY if the flash is busy, or FLASH_STATUS_ERROR if an error occurred.
76+ */
77+flash_status_t flash_is_busy(void);
78+
79+/**
80+ * @brief Initiates a chip erase operation.
81+ *
82+ * This function does not wait for the flash to become ready.
83+ *
84+ * @return FLASH_STATUS_SUCCESS if the erase command was successfully sent, FLASH_STATUS_TIMEOUT if the flash is busy, or FLASH_STATUS_ERROR if an error occurred.
85+ */
86+flash_status_t flash_begin_erase_chip(void);
87+
88+/**
89+ * @brief Waits for the chip erase operation to complete.
90+ *
91+ * This function waits for the chip erase operation to complete.
92+ *
93+ * @return FLASH_STATUS_SUCCESS if the chip erase operation completed successfully, FLASH_STATUS_TIMEOUT if the flash was still busy, or FLASH_STATUS_ERROR if an error occurred.
94+ */
95+flash_status_t flash_wait_erase_chip(void);
96+
97+/**
98+ * @brief Erases the entire flash memory chip.
99+ *
100+ * This function initiates an erase operation to erase the entire flash memory chip.
101+ * It waits for the operation to complete.
102+ *
103+ * @return FLASH_STATUS_SUCCESS if the erase was successfully executed, FLASH_STATUS_TIMEOUT if the flash is busy, or FLASH_STATUS_ERROR if an error occurred.
104+ */
105+flash_status_t flash_erase_chip(void);
106+
107+/**
108+ * @brief Erases a block of flash memory.
109+ *
110+ * This function initiates an erase operation to erase a block of flash memory.
111+ * It waits for the operation to complete.
112+ *
113+ * @param addr The address of the block to erase.
114+ *
115+ * @return FLASH_STATUS_SUCCESS if the erase was successfully executed, FLASH_STATUS_TIMEOUT if the flash is busy, or FLASH_STATUS_ERROR if an error occurred.
116+ */
117+flash_status_t flash_erase_block(uint32_t addr);
118+
119+/**
120+ * @brief Erases a sector of flash memory.
121+ *
122+ * This function initiates an erase operation to erase a sector of flash memory.
123+ * It waits for the operation to complete.
124+ *
125+ * @param addr The address of the sector to erase.
126+ *
127+ * @return FLASH_STATUS_SUCCESS if the erase was successfully executed, FLASH_STATUS_TIMEOUT if the flash is busy, or FLASH_STATUS_ERROR if an error occurred.
128+ */
129+flash_status_t flash_erase_sector(uint32_t addr);
130+
131+/**
132+ * @brief Reads a range of flash memory.
133diff --git a/drivers/flash/flash_spi.c b/drivers/flash/flash_spi.c
134index 0c0eb8a99e5bb58e0aad072d5dc82c444c9e51e6..7226773ff41236337375db75ade22b60a363b04e 100644
135--- a/drivers/flash/flash_spi.c
136+++ b/drivers/flash/flash_spi.c
137@@ -1,22 +1,10 @@
138-/*
139-Copyright (C) 2021 Westberry Technology (ChangZhou) Corp., Ltd
140-
141-This program is free software: you can redistribute it and/or modify
142-it under the terms of the GNU General Public License as published by
143-the Free Software Foundation, either version 2 of the License, or
144-(at your option) any later version.
145-
146-This program is distributed in the hope that it will be useful,
147-but WITHOUT ANY WARRANTY; without even the implied warranty of
148-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
149-GNU General Public License for more details.
150-
151-You should have received a copy of the GNU General Public License
152-along with this program. If not, see <http://www.gnu.org/licenses/>.
153-*/
154+// Copyright 2021 Westberry Technology (ChangZhou) Corp., Ltd
155+// Copyright 2024 Nick Brassel (@tzarc)
156+// SPDX-License-Identifier: GPL-2.0-or-later
157
158 #include <string.h>
159
160+#include "flash.h"
161 #include "util.h"
162 #include "wait.h"
163 #include "debug.h"
164@@ -69,33 +57,43 @@ static bool spi_flash_start(void) {
165 return spi_start(EXTERNAL_FLASH_SPI_SLAVE_SELECT_PIN, EXTERNAL_FLASH_SPI_LSBFIRST, EXTERNAL_FLASH_SPI_MODE, EXTERNAL_FLASH_SPI_CLOCK_DIVISOR);
166 }
167
168-static flash_status_t spi_flash_wait_while_busy(void) {
169- uint32_t deadline = timer_read32() + EXTERNAL_FLASH_SPI_TIMEOUT;
170+static flash_status_t spi_flash_wait_while_busy_multiplier(int multiplier) {
171 flash_status_t response = FLASH_STATUS_SUCCESS;
172- uint8_t retval;
173-
174+ uint32_t deadline = timer_read32() + ((EXTERNAL_FLASH_SPI_TIMEOUT)*multiplier);
175 do {
176- bool res = spi_flash_start();
177- if (!res) {
178- dprint("Failed to start SPI! [spi flash wait while busy]\n");
179- return FLASH_STATUS_ERROR;
180- }
181-
182- spi_write(FLASH_CMD_RDSR);
183-
184- retval = (uint8_t)spi_read();
185-
186- spi_stop();
187-
188 if (timer_read32() >= deadline) {
189 response = FLASH_STATUS_TIMEOUT;
190 break;
191 }
192- } while (retval & FLASH_FLAG_WIP);
193
194+ response = flash_is_busy();
195+ } while (response == FLASH_STATUS_BUSY);
196 return response;
197 }
198
199+static flash_status_t spi_flash_wait_while_busy(void) {
200+ return spi_flash_wait_while_busy_multiplier(1);
201+}
202+
203+flash_status_t flash_is_busy(void) {
204+ bool res = spi_flash_start();
205+ if (!res) {
206+ dprint("Failed to start SPI! [spi flash wait while busy]\n");
207+ return FLASH_STATUS_ERROR;
208+ }
209+
210+ spi_write(FLASH_CMD_RDSR);
211+ spi_status_t status = spi_read();
212+ spi_stop();
213+
214+ if (status < 0) {
215+ return status;
216+ }
217+
218+ uint8_t sr = (uint8_t)status;
219+ return (sr & FLASH_FLAG_WIP) ? FLASH_STATUS_BUSY : FLASH_STATUS_SUCCESS;
220+}
221+
222 static flash_status_t spi_flash_write_enable(void) {
223 bool res = spi_flash_start();
224 if (!res) {
225@@ -104,7 +102,6 @@ static flash_status_t spi_flash_write_enable(void) {
226 }
227
228 spi_write(FLASH_CMD_WREN);
229-
230 spi_stop();
231
232 return FLASH_STATUS_SUCCESS;
233@@ -118,7 +115,6 @@ static flash_status_t spi_flash_write_disable(void) {
234 }
235
236 spi_write(FLASH_CMD_WRDI);
237diff --git a/drivers/flash/flash_spi.h b/drivers/flash/flash_spi.h
238index 87460fc210ee6aec69a1c0200be9a0a373e1671d..7a979daf0f70fb1b1282daeba493b7fdd2e9c31d 100644
239--- a/drivers/flash/flash_spi.h
240+++ b/drivers/flash/flash_spi.h
241@@ -17,6 +17,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
242
243 #pragma once
244
245+#include "flash.h"
246+
247 /* All the following default configurations are based on MX25L4006E Nor FLASH. */
248
249 /*
250@@ -105,32 +107,3 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
251 The page count of the FLASH, calculated by total FLASH size and page size.
252 */
253 #define EXTERNAL_FLASH_PAGE_COUNT ((EXTERNAL_FLASH_SIZE) / (EXTERNAL_FLASH_PAGE_SIZE))
254-
255-typedef int16_t flash_status_t;
256-
257-#define FLASH_STATUS_SUCCESS (0)
258-#define FLASH_STATUS_ERROR (-1)
259-#define FLASH_STATUS_TIMEOUT (-2)
260-#define FLASH_STATUS_BAD_ADDRESS (-3)
261-
262-#ifdef __cplusplus
263-extern "C" {
264-#endif
265-
266-#include <stdint.h>
267-
268-void flash_init(void);
269-
270-flash_status_t flash_erase_chip(void);
271-
272-flash_status_t flash_erase_block(uint32_t addr);
273-
274-flash_status_t flash_erase_sector(uint32_t addr);
275-
276-flash_status_t flash_read_block(uint32_t addr, void *buf, size_t len);
277-
278-flash_status_t flash_write_block(uint32_t addr, const void *buf, size_t len);
279-
280-#ifdef __cplusplus
281-}
282-#endif
283diff --git a/drivers/wear_leveling/wear_leveling_flash_spi.c b/drivers/wear_leveling/wear_leveling_flash_spi.c
284index 6191f8bf09582a246753ca2c23707cdcb53643d9..304aed1641fb56dbdc0ba4ef2dd80a5306e94daf 100644
285--- a/drivers/wear_leveling/wear_leveling_flash_spi.c
286+++ b/drivers/wear_leveling/wear_leveling_flash_spi.c
287@@ -58,7 +58,7 @@ bool backing_store_read(uint32_t address, backing_store_int_t *value) {
288 bool backing_store_read_bulk(uint32_t address, backing_store_int_t *values, size_t item_count) {
289 bs_dprintf("Read ");
290 uint32_t offset = (WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_OFFSET) * (EXTERNAL_FLASH_BLOCK_SIZE) + address;
291- flash_status_t status = flash_read_block(offset, values, sizeof(backing_store_int_t) * item_count);
292+ flash_status_t status = flash_read_range(offset, values, sizeof(backing_store_int_t) * item_count);
293 if (status == FLASH_STATUS_SUCCESS) {
294 for (size_t i = 0; i < item_count; ++i) {
295 values[i] = ~values[i];
296@@ -88,7 +88,7 @@ bool backing_store_write_bulk(uint32_t address, backing_store_int_t *values, siz
297 }
298
299 // Write out the block
300- if (flash_write_block(offset, temp, sizeof(backing_store_int_t) * this_loop) != FLASH_STATUS_SUCCESS) {
301+ if (flash_write_range(offset, temp, sizeof(backing_store_int_t) * this_loop) != FLASH_STATUS_SUCCESS) {
302 return false;
303 }
304