ChibiOS/HAL  6.1.0
hal_jesd216_flash.c
Go to the documentation of this file.
1 /*
2  ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
3 
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 */
16 
17 /**
18  * @file hal_jesd216_flash.c
19  * @brief JESD216 compliant flash driver class code.
20  *
21  * @addtogroup HAL_JESD216_FLASH
22  * @{
23  */
24 
25 #include "hal.h"
26 
27 #include "hal_jesd216_flash.h"
28 
29 /*===========================================================================*/
30 /* Driver local definitions. */
31 /*===========================================================================*/
32 
33 /*===========================================================================*/
34 /* Driver exported variables. */
35 /*===========================================================================*/
36 
37 /*===========================================================================*/
38 /* Driver local variables and types. */
39 /*===========================================================================*/
40 
41 /*===========================================================================*/
42 /* Driver local functions. */
43 /*===========================================================================*/
44 
45 /*===========================================================================*/
46 /* Driver exported functions. */
47 /*===========================================================================*/
48 
49 void jesd216_start(BUSDriver *busp, const BUSConfig *config) {
50 
51 #if JESD216_BUS_MODE == JESD216_BUS_MODE_SPI
52  spiStart(busp, config);
53 #else
54  qspiStart(busp, config);
55 #endif
56 }
57 
58 void jesd216_stop(BUSDriver *busp) {
59 
60 #if JESD216_BUS_MODE == JESD216_BUS_MODE_SPI
61  spiStop(busp);
62 #else
63  qspiStop(busp);
64 #endif
65 }
66 
67 void jesd216_cmd(BUSDriver *busp, uint32_t cmd) {
68 #if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
69  qspi_command_t mode;
70 
71  mode.cfg = QSPI_CFG_CMD(cmd) |
72 #if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
73  QSPI_CFG_CMD_MODE_ONE_LINE;
74 #elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
75  QSPI_CFG_CMD_MODE_TWO_LINES;
76 #else
77  QSPI_CFG_CMD_MODE_FOUR_LINES;
78 #endif
79  mode.addr = 0U;
80  mode.alt = 0U;
81  qspiCommand(busp, &mode);
82 #else
83  uint8_t buf[1];
84 
85  spiSelect(busp);
86  buf[0] = cmd;
87  spiSend(busp, 1, buf);
88  spiUnselect(busp);
89 #endif
90 }
91 
92 void jesd216_cmd_receive(BUSDriver *busp,
93  uint32_t cmd,
94  size_t n,
95  uint8_t *p) {
96 #if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
97  qspi_command_t mode;
98 
99  mode.cfg = QSPI_CFG_CMD(cmd) |
100 #if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
101  QSPI_CFG_CMD_MODE_ONE_LINE |
102  QSPI_CFG_DATA_MODE_ONE_LINE;
103 #elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
104  QSPI_CFG_CMD_MODE_TWO_LINES |
105  QSPI_CFG_DATA_MODE_TWO_LINES;
106 #else
107  QSPI_CFG_CMD_MODE_FOUR_LINES |
108  QSPI_CFG_DATA_MODE_FOUR_LINES;
109 
110 #endif
111  mode.addr = 0U;
112  mode.alt = 0U;
113  qspiReceive(busp, &mode, n, p);
114 #else
115  uint8_t buf[1];
116 
117  spiSelect(busp);
118  buf[0] = cmd;
119  spiSend(busp, 1, buf);
120  spiReceive(busp, n, p);
121  spiUnselect(busp);
122 #endif
123 }
124 
125 void jesd216_cmd_send(BUSDriver *busp,
126  uint32_t cmd,
127  size_t n,
128  const uint8_t *p) {
129 #if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
130  qspi_command_t mode;
131 
132  mode.cfg = QSPI_CFG_CMD(cmd) |
133 #if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
134  QSPI_CFG_CMD_MODE_ONE_LINE |
135  QSPI_CFG_DATA_MODE_ONE_LINE;
136 #elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
137  QSPI_CFG_CMD_MODE_TWO_LINES |
138  QSPI_CFG_DATA_MODE_TWO_LINES;
139 #else
140  QSPI_CFG_CMD_MODE_FOUR_LINES |
141  QSPI_CFG_DATA_MODE_FOUR_LINES;
142 
143 #endif
144  mode.addr = 0U;
145  mode.alt = 0U;
146  qspiSend(busp, &mode, n, p);
147 #else
148  uint8_t buf[1];
149 
150  spiSelect(busp);
151  buf[0] = cmd;
152  spiSend(busp, 1, buf);
153  spiSend(busp, n, p);
154  spiUnselect(busp);
155 #endif
156 }
157 
158 void jesd216_cmd_addr(BUSDriver *busp,
159  uint32_t cmd,
160  flash_offset_t offset) {
161 #if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
162  qspi_command_t mode;
163 
164  mode.cfg = QSPI_CFG_CMD(cmd) |
165 #if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
166  QSPI_CFG_CMD_MODE_ONE_LINE |
167  QSPI_CFG_ADDR_MODE_ONE_LINE |
168  QSPI_CFG_ADDR_SIZE_24;
169 #elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
170  QSPI_CFG_CMD_MODE_TWO_LINES |
171  QSPI_CFG_ADDR_MODE_TWO_LINES |
172  QSPI_CFG_ADDR_SIZE_24;
173 #else
174  QSPI_CFG_CMD_MODE_FOUR_LINES |
175  QSPI_CFG_ADDR_MODE_FOUR_LINES |
176  QSPI_CFG_ADDR_SIZE_24;
177 
178 #endif
179  mode.addr = offset;
180  mode.alt = 0U;
181  qspiCommand(busp, &mode);
182 #else
183  uint8_t buf[4];
184 
185  spiSelect(busp);
186  buf[0] = cmd;
187  buf[1] = (uint8_t)(offset >> 16);
188  buf[2] = (uint8_t)(offset >> 8);
189  buf[3] = (uint8_t)(offset >> 0);
190  spiSend(busp, 4, buf);
191  spiUnselect(busp);
192 #endif
193 }
194 
195 void jesd216_cmd_addr_send(BUSDriver *busp,
196  uint32_t cmd,
197  flash_offset_t offset,
198  size_t n,
199  const uint8_t *p) {
200 #if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
201  qspi_command_t mode;
202 
203  mode.cfg = QSPI_CFG_CMD(cmd & 0xFFU) |
204 #if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
205  QSPI_CFG_CMD_MODE_ONE_LINE |
206  QSPI_CFG_ADDR_MODE_ONE_LINE |
207  QSPI_CFG_DATA_MODE_ONE_LINE;
208 #elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
209  QSPI_CFG_CMD_MODE_TWO_LINES |
210  QSPI_CFG_ADDR_MODE_TWO_LINES |
211  QSPI_CFG_DATA_MODE_TWO_LINES;
212 #else
213  QSPI_CFG_CMD_MODE_FOUR_LINES |
214  QSPI_CFG_ADDR_MODE_FOUR_LINES |
215  QSPI_CFG_DATA_MODE_FOUR_LINES;
216 #endif
217 
218  /* Handling 32 bits addressing.*/
219  if ((cmd & JESD216_CMD_EXTENDED_ADDRESSING) == 0) {
220  mode .cfg |= QSPI_CFG_ADDR_SIZE_24;
221  }
222  else {
223  mode .cfg |= QSPI_CFG_ADDR_SIZE_32;
224  }
225 
226  mode.addr = offset;
227  mode.alt = 0U;
228  qspiSend(busp, &mode, n, p);
229 #else
230  uint8_t buf[4];
231 
232  spiSelect(busp);
233  buf[0] = cmd;
234  buf[1] = (uint8_t)(offset >> 16);
235  buf[2] = (uint8_t)(offset >> 8);
236  buf[3] = (uint8_t)(offset >> 0);
237  spiSend(busp, 4, buf);
238  spiSend(busp, n, p);
239  spiUnselect(busp);
240 #endif
241 }
242 
243 void jesd216_cmd_addr_receive(BUSDriver *busp,
244  uint32_t cmd,
245  flash_offset_t offset,
246  size_t n,
247  uint8_t *p) {
248 #if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
249  qspi_command_t mode;
250 
251  mode.cfg = QSPI_CFG_CMD(cmd & 0xFFU) |
252 #if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
253  QSPI_CFG_CMD_MODE_ONE_LINE |
254  QSPI_CFG_ADDR_MODE_ONE_LINE |
255  QSPI_CFG_DATA_MODE_ONE_LINE;
256 #elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
257  QSPI_CFG_CMD_MODE_TWO_LINES |
258  QSPI_CFG_ADDR_MODE_TWO_LINES |
259  QSPI_CFG_ADDR_SIZE_24 |
260  QSPI_CFG_DATA_MODE_TWO_LINES;
261 #else
262  QSPI_CFG_CMD_MODE_FOUR_LINES |
263  QSPI_CFG_ADDR_MODE_FOUR_LINES |
264  QSPI_CFG_DATA_MODE_FOUR_LINES;
265 #endif
266 
267  /* Handling 32 bits addressing.*/
268  if ((cmd & JESD216_CMD_EXTENDED_ADDRESSING) == 0) {
269  mode .cfg |= QSPI_CFG_ADDR_SIZE_24;
270  }
271  else {
272  mode .cfg |= QSPI_CFG_ADDR_SIZE_32;
273  }
274 
275  mode.addr = offset;
276  mode.alt = 0U;
277  qspiReceive(busp, &mode, n, p);
278 #else
279  uint8_t buf[4];
280 
281  spiSelect(busp);
282  buf[0] = cmd;
283  buf[1] = (uint8_t)(offset >> 16);
284  buf[2] = (uint8_t)(offset >> 8);
285  buf[3] = (uint8_t)(offset >> 0);
286  spiSend(busp, 4, buf);
287  spiReceive(busp, n, p);
288  spiUnselect(busp);
289 #endif
290 }
291 
292 #if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) || defined(__DOXYGEN__)
293 void jesd216_cmd_addr_dummy_receive(BUSDriver *busp,
294  uint32_t cmd,
295  flash_offset_t offset,
296  uint8_t dummy,
297  size_t n,
298  uint8_t *p) {
299  qspi_command_t mode;
300 
301  mode.cfg = QSPI_CFG_CMD(cmd & 0xFFU) |
302 #if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
303  QSPI_CFG_CMD_MODE_ONE_LINE |
304  QSPI_CFG_ADDR_MODE_ONE_LINE |
305  QSPI_CFG_DUMMY_CYCLES(dummy) |
306  QSPI_CFG_DATA_MODE_ONE_LINE;
307 #elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
308  QSPI_CFG_CMD_MODE_TWO_LINES |
309  QSPI_CFG_ADDR_MODE_TWO_LINES |
310  QSPI_CFG_DUMMY_CYCLES(dummy) |
311  QSPI_CFG_DATA_MODE_TWO_LINES;
312 #else
313  QSPI_CFG_CMD_MODE_FOUR_LINES |
314  QSPI_CFG_ADDR_MODE_FOUR_LINES |
315  QSPI_CFG_DUMMY_CYCLES(dummy) |
316  QSPI_CFG_DATA_MODE_FOUR_LINES;
317 #endif
318 
319  /* Handling 32 bits addressing.*/
320  if ((cmd & JESD216_CMD_EXTENDED_ADDRESSING) == 0) {
321  mode .cfg |= QSPI_CFG_ADDR_SIZE_24;
322  }
323  else {
324  mode .cfg |= QSPI_CFG_ADDR_SIZE_32;
325  }
326 
327  mode.addr = offset;
328  mode.alt = 0U;
329  qspiReceive(busp, &mode, n, p);
330 }
331 #endif /* JESD216_BUS_MODE != JESD216_BUS_MODE_SPI */
332 
333 #if ((JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) && \
334  (JESD216_SHARED_BUS == TRUE)) || defined(__DOXYGEN__)
335 void jesd216_bus_acquire(BUSDriver *busp, const BUSConfig *config) {
336 
337  (void)config;
338 
339  qspiAcquireBus(busp);
340  if (busp->config != config) {
341  qspiStart(busp, config);
342  }
343 }
344 
345 void jesd216_bus_release(BUSDriver *busp) {
346 
347  qspiReleaseBus(busp);
348 }
349 #elif (JESD216_BUS_MODE == JESD216_BUS_MODE_SPI) && \
350  (JESD216_SHARED_BUS == TRUE)
351 void jesd216_bus_acquire(BUSDriver *busp, const BUSConfig *config) {
352 
353  spiAcquireBus(busp);
354  if (busp->config != config) {
355  spiStart(busp, config);
356  }
357 }
358 
359 void jesd216_bus_release(BUSDriver *busp) {
360 
361  spiReleaseBus(busp);
362 }
363 #else
364 #define jesd216_bus_acquire(busp)
365 #define jesd216_bus_release(busp)
366 #endif
367 
368 /** @} */
void spiUnselect(SPIDriver *spip)
Deasserts the slave select signal.
Definition: hal_spi.c:152
void spiSelect(SPIDriver *spip)
Asserts the slave select signal and prepares for transfers.
Definition: hal_spi.c:134
void spiReceive(SPIDriver *spip, size_t n, void *rxbuf)
Receives data from the SPI bus.
Definition: hal_spi.c:416
void spiStart(SPIDriver *spip, const SPIConfig *config)
Configures and activates the SPI peripheral.
Definition: hal_spi.c:91
void qspiReleaseBus(QSPIDriver *qspip)
Releases exclusive access to the QSPI bus.
Definition: hal_qspi.c:382
HAL subsystem header.
void spiReleaseBus(SPIDriver *spip)
Releases exclusive access to the SPI bus.
Definition: hal_spi.c:459
JESD216 compliant flash driver class header.
void spiAcquireBus(SPIDriver *spip)
Gains exclusive access to the SPI bus.
Definition: hal_spi.c:443
void qspiStart(QSPIDriver *qspip, const QSPIConfig *config)
Configures and activates the QSPI peripheral.
Definition: hal_qspi.c:91
void qspiReceive(QSPIDriver *qspip, const qspi_command_t *cmdp, size_t n, uint8_t *rxbuf)
Sends a command then receives data over the QSPI bus.
Definition: hal_qspi.c:281
void qspiSend(QSPIDriver *qspip, const qspi_command_t *cmdp, size_t n, const uint8_t *txbuf)
Sends a command with data over the QSPI bus.
Definition: hal_qspi.c:249
uint32_t flash_offset_t
Type of a flash offset.
Definition: hal_flash.h:83
void qspiAcquireBus(QSPIDriver *qspip)
Gains exclusive access to the QSPI bus.
Definition: hal_qspi.c:366
void qspiCommand(QSPIDriver *qspip, const qspi_command_t *cmdp)
Sends a command without data phase.
Definition: hal_qspi.c:219
void spiSend(SPIDriver *spip, size_t n, const void *txbuf)
Sends data over the SPI bus.
Definition: hal_spi.c:386
void qspiStop(QSPIDriver *qspip)
Deactivates the QSPI peripheral.
Definition: hal_qspi.c:116
void spiStop(SPIDriver *spip)
Deactivates the SPI peripheral.
Definition: hal_spi.c:111
Type of a QSPI command descriptor.
Definition: hal_qspi.h:125