1 /*
2 * Copyright 2018, 2020 NXP
3 * All rights reserved.
4 *
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 /*! *********************************************************************************
10 *************************************************************************************
11 * Include
12 *************************************************************************************
13 ********************************************************************************** */
14 #include "fsl_common.h"
15 #include "fsl_adapter_spi.h"
16 #include "fsl_adapter_eeprom.h"
17 /*! *********************************************************************************
18 *************************************************************************************
19 * Private macros
20 *************************************************************************************
21 ********************************************************************************** */
22 #if (!defined(GCOV_DO_COVERAGE) || (GCOV_DO_COVERAGE == 0))
23 #define EEPROM_STATIC static
24 #define EEPROM_PUBLIC
25 #else
26 #define EEPROM_STATIC __WEAK
27 #define EEPROM_PUBLIC __WEAK
28 #endif
29
30 #define EEPROM_RDSR 0x05U
31 #define EEPROM_READ 0x03U
32 #define EEPROM_WRITE 0x02U
33 #define EEPROM_WR_ENABLE 0x06U
34
35 #define EEPROM_BUSY_FLAG_MASK 0x01U
36 #define EEPROM_WRITE_ENABLED 0x02U
37
38 #define EEPROM_PAGE_SIZE (256U)
39 #define EEPROM_BLOCK_SIZE (8U * EEPROM_PAGE_SIZE)
40 #define EEPROM_PAGE_MASK (EEPROM_PAGE_SIZE - 1U)
41
42 /* adress mask */
43 #define ADDRESS_MASK 0x000000FFUL
44 /******************************************************************************
45 *******************************************************************************
46 * Private Prototypes
47 *******************************************************************************
48 ******************************************************************************/
49 typedef struct _eeprom_state
50 {
51 uint8_t eepromEraseBitmap[32];
52 HAL_SPI_MASTER_HANDLE_DEFINE(spiHandle); /*!< spi handle*/
53 eeprom_type_t eeType; /*!< eeprom type*/
54 } eeprom_state_t;
55
56 EEPROM_STATIC eeprom_state_t s_eeState;
57 /*! *********************************************************************************
58 *************************************************************************************
59 * Private Memory Declarations
60 *************************************************************************************
61 ********************************************************************************** */
62
63 /*! *********************************************************************************
64 *************************************************************************************
65 * Private Memory function
66 *************************************************************************************
67 ********************************************************************************** */
68
EEPROM_SetSpiTransferValue(hal_spi_transfer_t * transferValue,uint8_t * txData,uint8_t * rxData,size_t dataSize,uint32_t flags)69 EEPROM_STATIC void EEPROM_SetSpiTransferValue(hal_spi_transfer_t *transferValue,
70 uint8_t *txData,
71 uint8_t *rxData,
72 size_t dataSize,
73 uint32_t flags)
74 {
75 transferValue->txData = txData;
76 transferValue->rxData = rxData;
77 transferValue->dataSize = dataSize;
78 transferValue->flags = flags;
79 }
80
EEPROM_ReadStatusReq(void)81 EEPROM_STATIC uint8_t EEPROM_ReadStatusReq(void)
82 {
83 uint8_t cmd = EEPROM_RDSR;
84 hal_spi_transfer_t xfer;
85 uint8_t data[1] = {0U};
86
87 EEPROM_SetSpiTransferValue(&xfer, &cmd, NULL, sizeof(cmd),
88 (SPI_FIFOWR_RXIGNORE(1)|SPI_FIFOWR_EOF(1)));
89 (void)HAL_SpiMasterTransferBlocking(s_eeState.spiHandle, &xfer);
90
91 EEPROM_SetSpiTransferValue(&xfer, NULL, data, 1,
92 (SPI_FIFOWR_TXIGNORE(1)|SPI_FIFOWR_EOF(1)|SPI_FIFOWR_EOT(1)));
93 (void)HAL_SpiMasterTransferBlocking(s_eeState.spiHandle, &xfer);
94
95 return *((uint8_t *)((void *)data));
96 }
97
EEPROM_isBusy(void)98 EEPROM_STATIC uint8_t EEPROM_isBusy(void)
99 {
100 return ((EEPROM_ReadStatusReq() & EEPROM_BUSY_FLAG_MASK) == 0U) ? 0U : 1U;
101 }
102
EEPROM_WaitForReady(bool isInfinite)103 EEPROM_STATIC eeprom_status_t EEPROM_WaitForReady(bool isInfinite)
104 {
105 volatile uint16_t wait = 0x400; /* near 50 ms @ 50 us/cycle */
106
107 while ((bool)EEPROM_isBusy())
108 {
109 if (!isInfinite)
110 {
111 if (0U != wait)
112 {
113 wait--;
114 }
115 else
116 {
117 break;
118 }
119 }
120 }
121
122 if (0U != wait)
123 {
124 return kStatus_EeSuccess;
125 }
126 return kStatus_EeError;
127 }
128
EEPROM_PrepareForWrite()129 EEPROM_STATIC eeprom_status_t EEPROM_PrepareForWrite()
130 {
131 uint8_t cmd = EEPROM_WR_ENABLE;
132 hal_spi_transfer_t xfer;
133 uint8_t status = EEPROM_ReadStatusReq();
134
135 if ((status & EEPROM_WRITE_ENABLED) == 0U)
136 {
137 EEPROM_SetSpiTransferValue(&xfer, &cmd, NULL, sizeof(cmd),
138 (SPI_FIFOWR_RXIGNORE(1)|SPI_FIFOWR_EOF(1)|SPI_FIFOWR_EOT(1)));
139 (void)HAL_SpiMasterTransferBlocking(s_eeState.spiHandle, &xfer);
140 }
141 return kStatus_EeSuccess;
142 }
143
EEPROM_Command(uint8_t opCode,uint32_t addre)144 EEPROM_STATIC eeprom_status_t EEPROM_Command(uint8_t opCode, uint32_t addre)
145 {
146 uint8_t cmd[4];
147 hal_spi_transfer_t xfer;
148
149 cmd[0] = opCode;
150 cmd[1] = (uint8_t)((addre >> 16) & ADDRESS_MASK);
151 cmd[2] = (uint8_t)((addre >> 8) & ADDRESS_MASK);
152 cmd[3] = (uint8_t)((addre >> 0) & ADDRESS_MASK);
153
154 EEPROM_SetSpiTransferValue(&xfer, (uint8_t *)cmd, NULL, sizeof(cmd), SPI_FIFOWR_RXIGNORE(1));
155 return (eeprom_status_t)HAL_SpiMasterTransferBlocking(s_eeState.spiHandle, &xfer);
156 }
157
158 /*!*********************************************************************************
159 *************************************************************************************
160 * Public Functions
161 *************************************************************************************
162 ********************************************************************************** */
163
EEPROM_Init(eeprom_config_t * eepromConfig)164 eeprom_status_t EEPROM_Init(eeprom_config_t *eepromConfig)
165 {
166 static uint8_t initialized = 0U;
167
168 hal_spi_master_config_t spiMasterConfig = {
169 .srcClock_Hz = eepromConfig->spiSrcClock_Hz,
170 .baudRate_Bps = 9600U,
171 .enableMaster = true,
172 .polarity = kHAL_SpiClockPolarityActiveHigh,
173 .phase = kHAL_SpiClockPhaseFirstEdge,
174 .direction = kHAL_SpiMsbFirst,
175 .instance = eepromConfig->spiInstance,
176 };
177
178 uint32_t i;
179
180 /* Mark Flash as Unerased */
181 for (i = 0; i < sizeof(s_eeState.eepromEraseBitmap) / sizeof(s_eeState.eepromEraseBitmap[0]); i++)
182 {
183 s_eeState.eepromEraseBitmap[i] = 0;
184 }
185
186 if (0U == initialized)
187 {
188 s_eeState.eeType = eepromConfig->eeType;
189
190 (void)HAL_SpiMasterInit((hal_spi_master_handle_t)s_eeState.spiHandle, (void *)&spiMasterConfig);
191
192 initialized = 1;
193 }
194
195 return kStatus_EeSuccess;
196 }
197
EEPROM_WritePage(uint32_t noOfBytes,uint32_t addre,uint8_t * Outbuf)198 static eeprom_status_t EEPROM_WritePage(uint32_t noOfBytes, uint32_t addre, uint8_t *Outbuf)
199 {
200 hal_spi_transfer_t xfer;
201
202 if (0U == noOfBytes)
203 {
204 return kStatus_EeSuccess;
205 }
206
207 (void)EEPROM_WaitForReady(true);
208
209 (void)EEPROM_PrepareForWrite();
210
211 (void)EEPROM_WaitForReady(true);
212
213 if (kStatus_EeSuccess != EEPROM_Command(EEPROM_WRITE, addre))
214 {
215 return kStatus_EeError;
216 }
217 EEPROM_SetSpiTransferValue(&xfer, Outbuf, NULL, noOfBytes, SPI_FIFOWR_EOT(1));
218 if (kStatus_HAL_SpiSuccess != HAL_SpiMasterTransferBlocking(s_eeState.spiHandle, &xfer))
219 {
220 return kStatus_EeError;
221 }
222
223 return kStatus_EeSuccess;
224 }
225 /*****************************************************************************
226 * EEPROM_WriteData
227 *
228 * Writes a data buffer into EEPROM, at a given address
229 *
230 *****************************************************************************/
EEPROM_WriteData(uint32_t noOfBytes,uint32_t addr2eeprom,uint8_t * Outbuf)231 eeprom_status_t EEPROM_WriteData(uint32_t noOfBytes, uint32_t addr2eeprom, uint8_t *Outbuf)
232 {
233 eeprom_status_t retval;
234
235 while ((addr2eeprom & EEPROM_PAGE_MASK) + noOfBytes > EEPROM_PAGE_MASK)
236 {
237 uint32_t bytes = EEPROM_PAGE_SIZE - (addr2eeprom & EEPROM_PAGE_MASK);
238
239 retval = EEPROM_WritePage(bytes, addr2eeprom, Outbuf);
240 noOfBytes -= bytes;
241 addr2eeprom += bytes;
242
243 for (uint32_t j = 0; j < bytes; j++)
244 {
245 Outbuf++; /*Outbuf += bytes;*/
246 }
247
248 if (kStatus_EeSuccess != retval)
249 {
250 return retval;
251 }
252 }
253 retval = EEPROM_WritePage(noOfBytes, addr2eeprom, Outbuf);
254
255 return retval;
256 }
257
258 /*****************************************************************************
259 * EEPROM_ReadData
260 *
261 * Reads a data buffer from EEPROM, from a given address
262 *
263 *****************************************************************************/
EEPROM_ReadData(uint16_t noOfBytes,uint32_t addr2eeprom,uint8_t * inbuf)264 eeprom_status_t EEPROM_ReadData(uint16_t noOfBytes, uint32_t addr2eeprom, uint8_t *inbuf)
265 {
266 hal_spi_transfer_t xfer;
267 (void)EEPROM_WaitForReady(true);
268
269 if (kStatus_EeSuccess != EEPROM_Command(EEPROM_READ, addr2eeprom))
270 {
271 return kStatus_EeError;
272 }
273 EEPROM_SetSpiTransferValue(&xfer, NULL, inbuf, noOfBytes, SPI_FIFOWR_EOT(1));
274 if (kStatus_HAL_SpiSuccess != HAL_SpiMasterTransferBlocking(s_eeState.spiHandle, &xfer))
275 {
276 return kStatus_EeError;
277 }
278
279 return kStatus_EeSuccess;
280 }
281