L14-Click 1.0
STM32WLE5CC LoRaWAN Sensor Platform
Loading...
Searching...
No Matches
flash_at25.c
Go to the documentation of this file.
1#include "flash_at25.h"
2#include "main.h"
3#include <string.h>
4
5// Commands
6#define CMD_READ_ID 0x9F
7#define CMD_READ_DATA 0x03
8#define CMD_FAST_READ 0x0B // Fast read command for optimized reads
9#define CMD_PAGE_PROG 0x02
10#define CMD_WRITE_ENABLE 0x06
11#define CMD_WRITE_DISABLE 0x04
12#define CMD_READ_STATUS 0x05
13#define CMD_PAGE_ERASE 0x81
14
15// Status Register Bits
16#define SR_WIP 0x01 // Write In Progress
17#define SR_WEL 0x02 // Write Enable Latch
18
19// Timeouts for wait operations (in iterations)
20#define FLASH_TIMEOUT 10000
21
22
23
24// internal buffer for erasing of page before write
25static uint8_t _buffer256[256] = {};
26
27static void flash_Select(const flash_at25CS_t *s)
28{
29 HAL_GPIO_WritePin(s->CSPort, s->CSPin, GPIO_PIN_RESET);
30}
31
32static void flash_Unselect(const flash_at25CS_t *s)
33{
34 HAL_GPIO_WritePin(s->CSPort, s->CSPin, GPIO_PIN_SET);
35}
36
37/**
38 * @brief Helper function to wait for flash ready with timeout protection
39 * Optimized for frequent operations with proper timeout and CS handling
40 * @param s Pointer to flash configuration structure
41 * @retval HAL_OK if ready, HAL_TIMEOUT if timeout, HAL_ERROR on communication error
42 */
43static HAL_StatusTypeDef flashNew_WaitReadyWithTimeout(const flash_at25CS_t *s)
44{
45 HAL_StatusTypeDef ret;
46 uint32_t timeout = FLASH_TIMEOUT;
47 uint8_t status;
48
49 do
50 {
51 uint8_t cmd = CMD_READ_STATUS;
52
53 flash_Select(s);
54 if ((ret = HAL_SPI_Transmit(s->Spi, &cmd, 1, HAL_MAX_DELAY)) != HAL_OK)
55 break;
56 if ((ret = HAL_SPI_Receive(s->Spi, &status, 1, HAL_MAX_DELAY)) != HAL_OK)
57 break;
59 } while ((status & SR_WIP) && timeout--); // repeat, until write is progress, Check WIP (Write In Progress) bit
61 return ret;
62}
63
64/**
65 * @brief Helper function to enable write with verification
66 * Ensures write enable latch is properly set
67 * @param s Pointer to flash configuration structure
68 * @retval HAL_OK if write enabled, HAL_ERROR otherwise
69 */
70static HAL_StatusTypeDef flashNew_WriteEnableVerified(const flash_at25CS_t *s)
71{
72 HAL_StatusTypeDef ret = HAL_ERROR;
73 uint8_t cmd = CMD_WRITE_ENABLE;
74 uint8_t status;
75
76 do
77 {
78 // Send write enable command
79 flash_Select(s);
80 if ((ret = HAL_SPI_Transmit(s->Spi, &cmd, 1, HAL_MAX_DELAY)) != HAL_OK)
81 break;
83
84 // Verify WEL bit is set in status register
85 flash_Select(s);
86 cmd = CMD_READ_STATUS;
87 if ((ret = HAL_SPI_Transmit(s->Spi, &cmd, 1, HAL_MAX_DELAY)) != HAL_OK)
88 break;
89 if ((ret = HAL_SPI_Receive(s->Spi, &status, 1, HAL_MAX_DELAY)) != HAL_OK)
90 break;
92 } while (ret == HAL_OK && !(status & SR_WEL));
94 return ret;
95}
96
97//////// public /////////////
98HAL_StatusTypeDef flash_at25_Init(flash_at25CS_t *s)
99{
100 uint8_t cmd = CMD_READ_ID;
101 uint8_t id[3];
102 HAL_StatusTypeDef ret;
103
104 // Read device ID with proper verification
105 s->Is = 0;
106 s->Size = 0;
107 flash_Select(s);
108 do
109 {
110 ret = HAL_SPI_Transmit(s->Spi, &cmd, 1, 100);
111 if (ret != HAL_OK)
112 break;
113 ret = HAL_SPI_Receive(s->Spi, id, 3, 100);
114 if (ret != HAL_OK)
115 break;
116
117 // Verify manufacturer ID (0x1F for Atmel/Microchip)
118 if (id[0] != AT25_MANUFACTURER_ID)
119 {
120 ret = HAL_ERROR;
121 break;
122 }
123 // Verify device family and density for AT25EU0041A
124 // id[1] = device family, id[2] = density code
125 // For AT25EU0041A: family should be 0x84 and density 0x10 (4Mbit)
126 s->Is = 1;
127 s->Size = AT25_MEMSIZE; // 4Mbit = 512KB = 524288 bytes
128 } while (0);
130 return ret;
131}
132
133int8_t flash_at25_Is(flash_at25CS_t *s, int8_t tryInit)
134{
135 if (!s->Is && tryInit)
137 return s->Is;
138}
139
140HAL_StatusTypeDef flash_at25_Read(const flash_at25CS_t *s, uint32_t addr, void *buffer, uint16_t size)
141{
142 HAL_StatusTypeDef ret = HAL_ERROR;
143
144 // Validate inputs
145 if (s->Is > 0 && buffer != NULL && size > 0 && addr + size <= s->Size)
146 {
147 uint8_t cmd[5];
148
149 // Use fast read command for better performance
150 // Fast read requires: CMD + 3 address bytes + 1 dummy byte + data
151 cmd[0] = CMD_FAST_READ;
152 cmd[1] = (addr >> 16) & 0xFF;
153 cmd[2] = (addr >> 8) & 0xFF;
154 cmd[3] = addr & 0xFF;
155 cmd[4] = 0xFF; // Dummy byte required for fast read
156
157 do
158 {
159 // Wait for any pending operations to complete
160 if ((ret = flashNew_WaitReadyWithTimeout(s)) != HAL_OK)
161 break;
162 flash_Select(s); // because flashNew_WaitReadyWithTimeout
163 if ((ret = HAL_SPI_Transmit(s->Spi, cmd, 5, HAL_MAX_DELAY)) != HAL_OK)
164 break;
165 ret = HAL_SPI_Receive(s->Spi, buffer, size, HAL_MAX_DELAY);
166 if (ret != HAL_OK)
167 break;
168 } while (0);
170 }
171 return ret;
172}
173
174/**
175 * @brief write data to 256 bounder with erase of page
176 */
177static HAL_StatusTypeDef flash_WritePage(const flash_at25CS_t *s, uint32_t addr, const uint8_t *data, uint16_t size)
178{
179 HAL_StatusTypeDef status = HAL_ERROR;
180
181 if (s->Is > 0)
182 {
183 if (size > sizeof(_buffer256))
184 {
185 writeLog("flash_WritePage incorrect length:%d", (int)size);
187 }
188 do
189 {
190 uint32_t pageAddr = addr >> 8; // /256
191 uint8_t cmd[4];
192
193 pageAddr <<= 8; // 256 the erase Page to 256 bounde`r
194 if ((status = flash_at25_Read(s, pageAddr, _buffer256, sizeof(_buffer256))) != HAL_OK) // backup Page
195 break;
196 cmd[0] = CMD_PAGE_ERASE; // Page Erase Command
197 cmd[1] = (pageAddr >> 16) & 0xFF; // page 256
198 cmd[2] = (pageAddr >> 8) & 0xFF;
199 cmd[3] = pageAddr & 0xFF;
200 if ((status = flashNew_WriteEnableVerified(s)) != HAL_OK)
201 break;
202 flash_Select(s);
203 if ((status = HAL_SPI_Transmit(s->Spi, cmd, 4, HAL_MAX_DELAY)) != HAL_OK)
204 break;
206
207 cmd[0] = CMD_PAGE_PROG; // write on same position
208 memcpy(_buffer256 + (addr - pageAddr), data, size); // copy new data only
209 // Wait for flash to be ready
210 if ((status = flashNew_WaitReadyWithTimeout(s)) != HAL_OK)
211 break;
212 // Enable write operations with verification
213 if ((status = flashNew_WriteEnableVerified(s)) != HAL_OK)
214 break;
215 flash_Select(s);
216 if ((status = HAL_SPI_Transmit(s->Spi, cmd, 4, HAL_MAX_DELAY)) != HAL_OK)
217 break;
218 if ((status = HAL_SPI_Transmit(s->Spi, _buffer256, sizeof(_buffer256), HAL_MAX_DELAY)) != HAL_OK) // whole buffer
219 break;
221 // Final wait to ensure last write completes
223 }while(0);
225 }
226 return status;
227}
228
229HAL_StatusTypeDef flash_at25_Write(const flash_at25CS_t *s, uint32_t addr, const void *data, uint16_t size)
230{
231 HAL_StatusTypeDef ret = HAL_ERROR;
232 uint32_t pAddr = addr;
233 uint32_t bytesLeft = size;
234 const uint8_t *pBuffer = data;
235
236 while (bytesLeft > 0)
237 {
238 // Calculate how many bytes can be written in the current page
239 uint32_t pageOffset = pAddr % 256;
240 uint32_t maxWrite = 256 - pageOffset;
241 uint32_t currentWriteLen = (bytesLeft < maxWrite) ? bytesLeft : maxWrite;
242
243 ret = flash_WritePage(s, pAddr, pBuffer, currentWriteLen);
244 if (ret != HAL_OK)
245 break;
246
247 pAddr += currentWriteLen;
248 pBuffer += currentWriteLen;
249 bytesLeft -= currentWriteLen;
250 }
251
252 // memory check
253#ifdef xxxDEBUG
254 uint8_t sectorBuffer[512] = {};
255 ret = flash_at25_Read(s, addr, sectorBuffer, size);
256 if (ret != HAL_OK)
257 {
258 writeLog("flashNew_Write: read check failed:%d", (int) ret);
260 }
261 if (memcmp(sectorBuffer, data, size) != 0)
262 {
263 writeLog("flashNew_Write: compare failed!");
265 }
266#endif
267 return ret;
268}
int8_t flash_at25_Is(flash_at25CS_t *s, int8_t tryInit)
check if flash chip is present or not
Definition flash_at25.c:133
#define CMD_PAGE_ERASE
Definition flash_at25.c:13
#define CMD_PAGE_PROG
Definition flash_at25.c:9
HAL_StatusTypeDef flash_at25_Read(const flash_at25CS_t *s, uint32_t addr, void *buffer, uint16_t size)
Fast read from flash memory Uses fast read command (0x0B) for improved performance in frequent read o...
Definition flash_at25.c:140
HAL_StatusTypeDef flash_at25_Write(const flash_at25CS_t *s, uint32_t addr, const void *data, uint16_t size)
Write to flash memory with sector preservation Handles page-aligned writes efficiently with proper ve...
Definition flash_at25.c:229
HAL_StatusTypeDef flash_at25_Init(flash_at25CS_t *s)
Initialization for AT25EU0041A flash chip Performs proper device identification and verification Suit...
Definition flash_at25.c:98
#define CMD_FAST_READ
Definition flash_at25.c:8
#define CMD_WRITE_ENABLE
Definition flash_at25.c:10
static HAL_StatusTypeDef flash_WritePage(const flash_at25CS_t *s, uint32_t addr, const uint8_t *data, uint16_t size)
write data to 256 bounder with erase of page
Definition flash_at25.c:177
static void flash_Select(const flash_at25CS_t *s)
Definition flash_at25.c:27
#define CMD_READ_STATUS
Definition flash_at25.c:12
static void flash_Unselect(const flash_at25CS_t *s)
Definition flash_at25.c:32
#define FLASH_TIMEOUT
Definition flash_at25.c:20
#define SR_WEL
Definition flash_at25.c:17
#define SR_WIP
Definition flash_at25.c:16
static HAL_StatusTypeDef flashNew_WriteEnableVerified(const flash_at25CS_t *s)
Helper function to enable write with verification Ensures write enable latch is properly set.
Definition flash_at25.c:70
#define CMD_READ_ID
Definition flash_at25.c:6
static HAL_StatusTypeDef flashNew_WaitReadyWithTimeout(const flash_at25CS_t *s)
Helper function to wait for flash ready with timeout protection Optimized for frequent operations wit...
Definition flash_at25.c:43
static uint8_t _buffer256[256]
Definition flash_at25.c:25
#define AT25_MEMSIZE
Definition flash_at25.h:24
#define AT25_MANUFACTURER_ID
Definition flash_at25.h:23
: Header for main.c file. This file contains the common defines of the application.
void Error_Handler(void)
Default error handler called by HAL on unrecoverable errors. Disables interrupts and enters an infini...
Definition main.c:505
void writeLog(const char *format,...)
Format and send a log message over UART (printf-style). Available only when WRITELOG is defined; comp...
Definition main.c:97
Configuration and state descriptor for one AT25EU0041A flash chip. Pass a pointer to this struct to e...
Definition flash_at25.h:34
uint16_t CSPin
Definition flash_at25.h:37
SPI_HandleTypeDef * Spi
Definition flash_at25.h:35
GPIO_TypeDef * CSPort
Definition flash_at25.h:36
uint32_t Size
Definition flash_at25.h:39