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 uint8_t waitForWakeup = 0;
104 uint32_t timeout = 2000; // Max safety timeout
105 uint32_t start_tick = HAL_GetTick();
106
107 // Read device ID with proper verification
108 s->Is = 0;
109 s->Size = 0;
110 Power3v3_On();
111
112 do
113 {
114 waitForWakeup = 0;
115 flash_Select(s);
116 do
117 {
118 ret = HAL_SPI_Transmit(s->Spi, &cmd, 1, 100);
119 if (ret != HAL_OK)
120 break;
121 ret = HAL_SPI_Receive(s->Spi, id, 3, 100);
122 if (ret != HAL_OK)
123 break;
124
125 // Verify manufacturer ID (0x1F for Atmel/Microchip)
126 if (id[0] != AT25_MANUFACTURER_ID)
127 {
128 ret = HAL_ERROR;
129 waitForWakeup = 1; // the chip is ready, but looks like not woke up yet
130 break;
131 }
132 // Verify device family and density for AT25EU0041A
133 // id[1] = device family, id[2] = density code
134 // For AT25EU0041A: family should be 0x84 and density 0x10 (4Mbit)
135 s->Is = 1;
136 s->Size = AT25_MEMSIZE; // 4Mbit = 512KB = 524288 bytes
137 } while (0);
139 } while (waitForWakeup && HAL_GetTick() - start_tick < timeout);
140
141 Power3v3_Off();
142 return ret;
143}
144
145int8_t flash_at25_Is(flash_at25CS_t *s, int8_t tryInit)
146{
147 if (!s->Is && tryInit)
149 return s->Is;
150}
151
152HAL_StatusTypeDef flash_at25_Read(const flash_at25CS_t *s, uint32_t addr, void *buffer, uint16_t size)
153{
154 HAL_StatusTypeDef ret = HAL_ERROR;
155
156 // Validate inputs
157 if (s->Is > 0 && buffer != NULL && size > 0 && addr + size <= s->Size)
158 {
159 uint8_t cmd[5];
160
161 // Use fast read command for better performance
162 // Fast read requires: CMD + 3 address bytes + 1 dummy byte + data
163 cmd[0] = CMD_FAST_READ;
164 cmd[1] = (addr >> 16) & 0xFF;
165 cmd[2] = (addr >> 8) & 0xFF;
166 cmd[3] = addr & 0xFF;
167 cmd[4] = 0xFF; // Dummy byte required for fast read
168
169 Power3v3_On();
170 do
171 {
172 // Wait for any pending operations to complete
173 if ((ret = flashNew_WaitReadyWithTimeout(s)) != HAL_OK)
174 break;
175 flash_Select(s); // because flashNew_WaitReadyWithTimeout
176 if ((ret = HAL_SPI_Transmit(s->Spi, cmd, 5, HAL_MAX_DELAY)) != HAL_OK)
177 break;
178 ret = HAL_SPI_Receive(s->Spi, buffer, size, HAL_MAX_DELAY);
179 if (ret != HAL_OK)
180 break;
181 } while (0);
183 Power3v3_Off();
184 }
185 return ret;
186}
187
188/**
189 * @brief write data to 256 bounder with erase of page
190 */
191static HAL_StatusTypeDef flash_WritePage(const flash_at25CS_t *s, uint32_t addr, const uint8_t *data, uint16_t size)
192{
193 HAL_StatusTypeDef status = HAL_ERROR;
194
195 if (s->Is > 0)
196 {
197 if (size > sizeof(_buffer256))
198 {
199 writeLog("flash_WritePage incorrect length:%d", (int)size);
201 }
202 do
203 {
204 uint32_t pageAddr = addr >> 8; // /256
205 uint8_t cmd[4];
206
207 pageAddr <<= 8; // 256 the erase Page to 256 bounde`r
208 if ((status = flash_at25_Read(s, pageAddr, _buffer256, sizeof(_buffer256))) != HAL_OK) // backup Page
209 break;
210 cmd[0] = CMD_PAGE_ERASE; // Page Erase Command
211 cmd[1] = (pageAddr >> 16) & 0xFF; // page 256
212 cmd[2] = (pageAddr >> 8) & 0xFF;
213 cmd[3] = pageAddr & 0xFF;
214 if ((status = flashNew_WriteEnableVerified(s)) != HAL_OK)
215 break;
216 flash_Select(s);
217 if ((status = HAL_SPI_Transmit(s->Spi, cmd, 4, HAL_MAX_DELAY)) != HAL_OK)
218 break;
220
221 cmd[0] = CMD_PAGE_PROG; // write on same position
222 memcpy(_buffer256 + (addr - pageAddr), data, size); // copy new data only
223 // Wait for flash to be ready
224 if ((status = flashNew_WaitReadyWithTimeout(s)) != HAL_OK)
225 break;
226 // Enable write operations with verification
227 if ((status = flashNew_WriteEnableVerified(s)) != HAL_OK)
228 break;
229 flash_Select(s);
230 if ((status = HAL_SPI_Transmit(s->Spi, cmd, 4, HAL_MAX_DELAY)) != HAL_OK)
231 break;
232 if ((status = HAL_SPI_Transmit(s->Spi, _buffer256, sizeof(_buffer256), HAL_MAX_DELAY)) != HAL_OK) // whole buffer
233 break;
235 // Final wait to ensure last write completes
237 }while(0);
239 }
240 return status;
241}
242
243HAL_StatusTypeDef flash_at25_Write(const flash_at25CS_t *s, uint32_t addr, const void *data, uint16_t size)
244{
245 HAL_StatusTypeDef ret = HAL_ERROR;
246 uint32_t pAddr = addr;
247 uint32_t bytesLeft = size;
248 const uint8_t *pBuffer = data;
249
250 Power3v3_On();
251 while (bytesLeft > 0)
252 {
253 // Calculate how many bytes can be written in the current page
254 uint32_t pageOffset = pAddr % 256;
255 uint32_t maxWrite = 256 - pageOffset;
256 uint32_t currentWriteLen = (bytesLeft < maxWrite) ? bytesLeft : maxWrite;
257
258 ret = flash_WritePage(s, pAddr, pBuffer, currentWriteLen);
259 if (ret != HAL_OK)
260 break;
261
262 pAddr += currentWriteLen;
263 pBuffer += currentWriteLen;
264 bytesLeft -= currentWriteLen;
265 }
266 Power3v3_Off();
267
268 // memory check
269#ifdef xxxDEBUG
270 uint8_t sectorBuffer[512] = {};
271 ret = flash_at25_Read(s, addr, sectorBuffer, size);
272 if (ret != HAL_OK)
273 {
274 writeLog("flashNew_Write: read check failed:%d", (int) ret);
276 }
277 if (memcmp(sectorBuffer, data, size) != 0)
278 {
279 writeLog("flashNew_Write: compare failed!");
281 }
282#endif
283 return ret;
284}
int8_t flash_at25_Is(flash_at25CS_t *s, int8_t tryInit)
check if flash chip is present or not
Definition flash_at25.c:145
#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:152
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:243
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:191
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)
This function is executed in case of error occurrence.
Definition main.c:589
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:105
void Power3v3_On()
Cumulative turn the all peripheries to ON state - pull-up the _3V3_Enb_Pin pin.
Definition main.c:250
void Power3v3_Off()
Cumulative turn the all peripheries to OFF state - pull-down the _3V3_Enb_Pin pin.
Definition main.c:262
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
uint32_t HAL_GetTick(void)
Definition sys_app.c:337