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(
70 hal_spi_transfer_t *transferValue, uint8_t *txData, uint8_t *rxData, size_t dataSize, uint32_t flags)
71 {
72 transferValue->txData = txData;
73 transferValue->rxData = rxData;
74 transferValue->dataSize = dataSize;
75 transferValue->flags = flags;
76 }
77
EEPROM_ReadStatusReq(void)78 EEPROM_STATIC uint8_t EEPROM_ReadStatusReq(void)
79 {
80 uint8_t cmd = EEPROM_RDSR;
81 hal_spi_transfer_t xfer;
82 uint8_t data[1] = {0U};
83
84 EEPROM_SetSpiTransferValue(&xfer, &cmd, NULL, sizeof(cmd), (SPI_FIFOWR_RXIGNORE(1) | SPI_FIFOWR_EOF(1)));
85 (void)HAL_SpiMasterTransferBlocking(s_eeState.spiHandle, &xfer);
86
87 EEPROM_SetSpiTransferValue(&xfer, NULL, data, 1, (SPI_FIFOWR_TXIGNORE(1) | SPI_FIFOWR_EOF(1) | SPI_FIFOWR_EOT(1)));
88 (void)HAL_SpiMasterTransferBlocking(s_eeState.spiHandle, &xfer);
89
90 return *((uint8_t *)((void *)data));
91 }
92
EEPROM_isBusy(void)93 EEPROM_STATIC uint8_t EEPROM_isBusy(void)
94 {
95 return ((EEPROM_ReadStatusReq() & EEPROM_BUSY_FLAG_MASK) == 0U) ? 0U : 1U;
96 }
97
EEPROM_WaitForReady(bool isInfinite)98 EEPROM_STATIC eeprom_status_t EEPROM_WaitForReady(bool isInfinite)
99 {
100 volatile uint16_t wait = 0x400; /* near 50 ms @ 50 us/cycle */
101
102 while ((bool)EEPROM_isBusy())
103 {
104 if (!isInfinite)
105 {
106 if (0U != wait)
107 {
108 wait--;
109 }
110 else
111 {
112 break;
113 }
114 }
115 }
116
117 if (0U != wait)
118 {
119 return kStatus_EeSuccess;
120 }
121 return kStatus_EeError;
122 }
123
EEPROM_PrepareForWrite()124 EEPROM_STATIC eeprom_status_t EEPROM_PrepareForWrite()
125 {
126 uint8_t cmd = EEPROM_WR_ENABLE;
127 hal_spi_transfer_t xfer;
128 uint8_t status = EEPROM_ReadStatusReq();
129
130 if ((status & EEPROM_WRITE_ENABLED) == 0U)
131 {
132 EEPROM_SetSpiTransferValue(&xfer, &cmd, NULL, sizeof(cmd),
133 (SPI_FIFOWR_RXIGNORE(1) | SPI_FIFOWR_EOF(1) | SPI_FIFOWR_EOT(1)));
134 (void)HAL_SpiMasterTransferBlocking(s_eeState.spiHandle, &xfer);
135 }
136 return kStatus_EeSuccess;
137 }
138
EEPROM_Command(uint8_t opCode,uint32_t addre)139 EEPROM_STATIC eeprom_status_t EEPROM_Command(uint8_t opCode, uint32_t addre)
140 {
141 uint8_t cmd[4];
142 hal_spi_transfer_t xfer;
143
144 cmd[0] = opCode;
145 cmd[1] = (uint8_t)((addre >> 16) & ADDRESS_MASK);
146 cmd[2] = (uint8_t)((addre >> 8) & ADDRESS_MASK);
147 cmd[3] = (uint8_t)((addre >> 0) & ADDRESS_MASK);
148
149 EEPROM_SetSpiTransferValue(&xfer, (uint8_t *)cmd, NULL, sizeof(cmd), SPI_FIFOWR_RXIGNORE(1));
150 return (eeprom_status_t)HAL_SpiMasterTransferBlocking(s_eeState.spiHandle, &xfer);
151 }
152
153 /*!*********************************************************************************
154 *************************************************************************************
155 * Public Functions
156 *************************************************************************************
157 ********************************************************************************** */
158
EEPROM_Init(eeprom_config_t * eepromConfig)159 eeprom_status_t EEPROM_Init(eeprom_config_t *eepromConfig)
160 {
161 static uint8_t initialized = 0U;
162
163 hal_spi_master_config_t spiMasterConfig = {
164 .srcClock_Hz = eepromConfig->spiSrcClock_Hz,
165 .baudRate_Bps = 9600U,
166 .enableMaster = true,
167 .polarity = kHAL_SpiClockPolarityActiveHigh,
168 .phase = kHAL_SpiClockPhaseFirstEdge,
169 .direction = kHAL_SpiMsbFirst,
170 .instance = eepromConfig->spiInstance,
171 };
172
173 uint32_t i;
174
175 /* Mark Flash as Unerased */
176 for (i = 0; i < sizeof(s_eeState.eepromEraseBitmap) / sizeof(s_eeState.eepromEraseBitmap[0]); i++)
177 {
178 s_eeState.eepromEraseBitmap[i] = 0;
179 }
180
181 if (0U == initialized)
182 {
183 s_eeState.eeType = eepromConfig->eeType;
184
185 (void)HAL_SpiMasterInit((hal_spi_master_handle_t)s_eeState.spiHandle, (void *)&spiMasterConfig);
186
187 initialized = 1;
188 }
189
190 return kStatus_EeSuccess;
191 }
192
EEPROM_WritePage(uint32_t noOfBytes,uint32_t addre,uint8_t * Outbuf)193 static eeprom_status_t EEPROM_WritePage(uint32_t noOfBytes, uint32_t addre, uint8_t *Outbuf)
194 {
195 hal_spi_transfer_t xfer;
196
197 if (0U == noOfBytes)
198 {
199 return kStatus_EeSuccess;
200 }
201
202 (void)EEPROM_WaitForReady(true);
203
204 (void)EEPROM_PrepareForWrite();
205
206 (void)EEPROM_WaitForReady(true);
207
208 if (kStatus_EeSuccess != EEPROM_Command(EEPROM_WRITE, addre))
209 {
210 return kStatus_EeError;
211 }
212 EEPROM_SetSpiTransferValue(&xfer, Outbuf, NULL, noOfBytes, SPI_FIFOWR_EOT(1));
213 if (kStatus_HAL_SpiSuccess != HAL_SpiMasterTransferBlocking(s_eeState.spiHandle, &xfer))
214 {
215 return kStatus_EeError;
216 }
217
218 return kStatus_EeSuccess;
219 }
220 /*****************************************************************************
221 * EEPROM_WriteData
222 *
223 * Writes a data buffer into EEPROM, at a given address
224 *
225 *****************************************************************************/
EEPROM_WriteData(uint32_t noOfBytes,uint32_t addr2eeprom,uint8_t * Outbuf)226 eeprom_status_t EEPROM_WriteData(uint32_t noOfBytes, uint32_t addr2eeprom, uint8_t *Outbuf)
227 {
228 eeprom_status_t retval;
229
230 while ((addr2eeprom & EEPROM_PAGE_MASK) + noOfBytes > EEPROM_PAGE_MASK)
231 {
232 uint32_t bytes = EEPROM_PAGE_SIZE - (addr2eeprom & EEPROM_PAGE_MASK);
233
234 retval = EEPROM_WritePage(bytes, addr2eeprom, Outbuf);
235 noOfBytes -= bytes;
236 addr2eeprom += bytes;
237
238 for (uint32_t j = 0; j < bytes; j++)
239 {
240 Outbuf++; /*Outbuf += bytes;*/
241 }
242
243 if (kStatus_EeSuccess != retval)
244 {
245 return retval;
246 }
247 }
248 retval = EEPROM_WritePage(noOfBytes, addr2eeprom, Outbuf);
249
250 return retval;
251 }
252
253 /*****************************************************************************
254 * EEPROM_ReadData
255 *
256 * Reads a data buffer from EEPROM, from a given address
257 *
258 *****************************************************************************/
EEPROM_ReadData(uint16_t noOfBytes,uint32_t addr2eeprom,uint8_t * inbuf)259 eeprom_status_t EEPROM_ReadData(uint16_t noOfBytes, uint32_t addr2eeprom, uint8_t *inbuf)
260 {
261 hal_spi_transfer_t xfer;
262 (void)EEPROM_WaitForReady(true);
263
264 if (kStatus_EeSuccess != EEPROM_Command(EEPROM_READ, addr2eeprom))
265 {
266 return kStatus_EeError;
267 }
268 EEPROM_SetSpiTransferValue(&xfer, NULL, inbuf, noOfBytes, SPI_FIFOWR_EOT(1));
269 if (kStatus_HAL_SpiSuccess != HAL_SpiMasterTransferBlocking(s_eeState.spiHandle, &xfer))
270 {
271 return kStatus_EeError;
272 }
273
274 return kStatus_EeSuccess;
275 }
276