1 /***********************************************************************************************//**
2 * \file cy_serial_flash_qspi.h
3 *
4 * \brief
5 * Provides APIs for interacting with an external flash connected to the SPI or
6 * QSPI interface. Read is implemented as both blocking and non-blocking whereas
7 * write, and erase are implemented as blocking functions.
8 *
9 ***************************************************************************************************
10 * \copyright
11 * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or
12 * an affiliate of Cypress Semiconductor Corporation
13 *
14 * SPDX-License-Identifier: Apache-2.0
15 *
16 * Licensed under the Apache License, Version 2.0 (the "License");
17 * you may not use this file except in compliance with the License.
18 * You may obtain a copy of the License at
19 *
20 * http://www.apache.org/licenses/LICENSE-2.0
21 *
22 * Unless required by applicable law or agreed to in writing, software
23 * distributed under the License is distributed on an "AS IS" BASIS,
24 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25 * See the License for the specific language governing permissions and
26 * limitations under the License.
27 **************************************************************************************************/
28
29 /**
30 * \addtogroup group_board_libs Serial Flash
31 * \ingroup group_lib
32 * \{
33 *
34 * \section section_resource_usage DMA Resource Usage
35 * This library uses fixed DMA (Datawire or DW) resources and supports DMA only
36 * for the following devices. DMA is not supported for other devices and the
37 * functions \ref cy_serial_flash_qspi_read_async() and
38 * \ref cy_serial_flash_qspi_abort_read() will return
39 * \ref CY_RSLT_SERIAL_FLASH_ERR_UNSUPPORTED error and
40 * \ref cy_serial_flash_qspi_set_dma_interrupt_priority() will simply return
41 * doing nothing.
42 * * CY8C6xx4, CY8C6xx5, CY8C6xx8, CY8C6xxA, CYB06xx5, CYB06xxA, CYS06xxA: <b>DW1, Channel 23</b>
43 * * CY8C6xx6, CY8C6xx7, CYB06xx7: <b>DW1, Channel 15</b>
44 */
45
46 #pragma once
47
48 #include <stddef.h>
49 #include "cy_result.h"
50 #include "cy_pdl.h"
51 #include "cyhal.h"
52
53 #ifdef CY_IP_MXSMIF
54
55 #if defined(__cplusplus)
56 extern "C" {
57 #endif
58
59 /** The function or operation is not supported on the target or the memory */
60 #define CY_RSLT_SERIAL_FLASH_ERR_UNSUPPORTED \
61 (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_BOARD_LIB_SERIAL_FLASH, 1))
62
63 /** Parameters passed to a function are invalid */
64 #define CY_RSLT_SERIAL_FLASH_ERR_BAD_PARAM \
65 (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_BOARD_LIB_SERIAL_FLASH, 2))
66
67 /** A previously initiated read operation is not yet complete */
68 #define CY_RSLT_SERIAL_FLASH_ERR_READ_BUSY \
69 (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_BOARD_LIB_SERIAL_FLASH, 3))
70
71 /** A DMA error occurred during read transfer */
72 #define CY_RSLT_SERIAL_FLASH_ERR_DMA \
73 (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_BOARD_LIB_SERIAL_FLASH, 4))
74
75 /** Read abort failed. QSPI block is busy. */
76 #define CY_RSLT_SERIAL_FLASH_ERR_QSPI_BUSY \
77 (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_BOARD_LIB_SERIAL_FLASH, 5))
78
79 #ifdef DOXYGEN
80 /** Enables thread-safety for use with multi-threaded RTOS environment. */
81 #define CY_SERIAL_FLASH_QSPI_THREAD_SAFE
82 #endif /* #ifdef DOXYGEN */
83
84 /**
85 * Callback pointer to use with \ref cy_serial_flash_qspi_read_async().
86 * \param operation_status Status of the read operation
87 * \param callback_arg Pointer to be passed back to the callback function
88 */
89 typedef void (* cy_serial_flash_qspi_read_complete_callback_t)(cy_rslt_t operation_status,
90 void* callback_arg);
91
92 /**
93 * \brief Initializes the serial flash memory. This function accepts up to 8
94 * I/Os. Number of I/Os depend on the type of memory interface. Pass NC when an
95 * I/O is unused.
96 * Single SPI - (io0, io1) or (io2, io3) or (io4, io5) or (io6, io7)
97 * Dual SPI - (io0, io1) or (io2, io3) or (io4, io5) or (io6, io7)
98 * Quad SPI - (io0, io1, io2, io3) or (io4, io5, io6, io7)
99 * Octal SPI - All 8 I/Os are used.
100 * \param mem_config Memory configuration to be used for initializing
101 * \param io0 Data/IO pin 0 connected to the memory, Pass NC when unused.
102 * \param io1 Data/IO pin 1 connected to the memory, Pass NC when unused.
103 * \param io2 Data/IO pin 2 connected to the memory, Pass NC when unused.
104 * \param io3 Data/IO pin 3 connected to the memory, Pass NC when unused.
105 * \param io4 Data/IO pin 4 connected to the memory, Pass NC when unused.
106 * \param io5 Data/IO pin 5 connected to the memory, Pass NC when unused.
107 * \param io6 Data/IO pin 6 connected to the memory, Pass NC when unused.
108 * \param io7 Data/IO pin 7 connected to the memory, Pass NC when unused.
109 * \param sclk Clock pin connected to the memory
110 * \param ssel Slave select pin connected to the memory
111 * \param hz Clock frequency to be used with the memory.
112 * \returns CY_RSLT_SUCCESS if the initialization was successful, an error code
113 * otherwise.
114 */
115 cy_rslt_t cy_serial_flash_qspi_init(
116 const cy_stc_smif_mem_config_t* mem_config,
117 cyhal_gpio_t io0,
118 cyhal_gpio_t io1,
119 cyhal_gpio_t io2,
120 cyhal_gpio_t io3,
121 cyhal_gpio_t io4,
122 cyhal_gpio_t io5,
123 cyhal_gpio_t io6,
124 cyhal_gpio_t io7,
125 cyhal_gpio_t sclk,
126 cyhal_gpio_t ssel,
127 uint32_t hz);
128
129 /**
130 * \brief De-initializes the serial flash memory.
131 * Before calling this function, ensure that an ongoing asynchronous read
132 * operation is either completed or successfully aborted.
133 * Async read is started by calling \ref cy_serial_flash_qspi_read_async() and
134 * aborted by calling \ref cy_serial_flash_qspi_abort_read().
135 */
136 void cy_serial_flash_qspi_deinit(void);
137
138 /**
139 * \brief Returns the size of the serial flash memory in bytes.
140 * \returns Memory size in bytes.
141 */
142 size_t cy_serial_flash_qspi_get_size(void);
143
144 /**
145 * \brief Returns the size of the erase sector to which the given address
146 * belongs. Address is used only for a memory with hybrid sector size.
147 * \param addr Address that belongs to the sector for which size is returned.
148 * \returns Erase sector size in bytes.
149 */
150 size_t cy_serial_flash_qspi_get_erase_size(uint32_t addr);
151
152 /**
153 * \brief Returns the page size for programming of the sector to which the given
154 * address belongs. Address is used only for a memory with hybrid sector size.
155 * \param addr Address that belongs to the sector for which size is returned.
156 * \returns Page size in bytes.
157 */
158 size_t cy_serial_flash_qspi_get_prog_size(uint32_t addr);
159
160 /**
161 * \brief Utility function to calculate the starting address of an erase sector
162 * to which the given address belongs.
163 * \param addr Address in the sector for which the starting address is returned.
164 * \returns Starting address of the sector
165 */
cy_serial_flash_get_sector_start_address(uint32_t addr)166 __STATIC_INLINE uint32_t cy_serial_flash_get_sector_start_address(uint32_t addr)
167 {
168 return (addr & ~(cy_serial_flash_qspi_get_erase_size(addr) - 1));
169 }
170
171
172 /**
173 * \brief Reads data from the serial flash memory. This is a blocking
174 * function. Returns error if (addr + length) exceeds the flash size.
175 * \param addr Starting address to read from
176 * \param length Number of data bytes to read
177 * \param buf Pointer to the buffer to store the data read from the memory
178 * \returns CY_RSLT_SUCCESS if the read was successful, an error code otherwise.
179 */
180 cy_rslt_t cy_serial_flash_qspi_read(uint32_t addr, size_t length, uint8_t* buf);
181
182 /**
183 * \brief Reads data from the serial flash memory. This is a non-blocking
184 * function. Returns error if (addr + length) exceeds the flash size.
185 * Uses fixed DMA (DW) instance and channel for transferring the data from
186 * QSPI RX FIFO to the user-provided buffer.
187 * \param addr Starting address to read from
188 * \param length Number of data bytes to read
189 * \param buf Pointer to the buffer to store the data read from the memory
190 * \param callback Pointer to the callback function to be called after the read
191 * operation is complete. Callback is invoked from the DMA ISR.
192 * \param callback_arg Pointer to the argument to be passed to the callback
193 * function
194 * \returns CY_RSLT_SUCCESS if the read was successful, an error code otherwise.
195 */
196 cy_rslt_t cy_serial_flash_qspi_read_async(uint32_t addr, size_t length, uint8_t* buf,
197 cy_serial_flash_qspi_read_complete_callback_t callback,
198 void* callback_arg);
199
200 /**
201 * \brief Aborts an ongoing asynchronous read initiated by calling
202 * \ref cy_serial_flash_qspi_read_async().
203 *
204 * \returns CY_RSLT_SUCCESS if the abort was successful, an error code
205 * if the QSPI block is still busy after a timeout.
206 */
207 cy_rslt_t cy_serial_flash_qspi_abort_read(void);
208
209 /**
210 * \brief Writes the data to the serial flash memory. The program area
211 * must have been erased prior to calling this API using
212 * \ref cy_serial_flash_qspi_erase() This is a blocking function. Returns error if
213 * (addr + length) exceeds the flash size.
214 * \param addr Starting address to write to
215 * \param length Number of bytes to write
216 * \param buf Pointer to the buffer storing the data to be written
217 * \returns CY_RSLT_SUCCESS if the write was successful, an error code
218 * otherwise.
219 */
220 cy_rslt_t cy_serial_flash_qspi_write(uint32_t addr, size_t length, const uint8_t* buf);
221
222 /**
223 * \brief Erases the serial flash memory, uses chip erase command when
224 * addr = 0 and length = flash_size otherwise uses sector erase command. This is
225 * a blocking function. Returns error if addr or (addr + length) is not aligned
226 * to the sector size or if (addr + length) exceeds the flash size.
227 * For memories with hybrid sectors, returns error if the end address
228 * (=addr + length) is not aligned to the size of the sector in which the end
229 * address is located.
230 * Call \ref cy_serial_flash_qspi_get_size() to get the flash size and
231 * call \ref cy_serial_flash_qspi_get_erase_size() to get the size of an erase
232 * sector.
233 *
234 * \param addr Starting address to begin erasing
235 * \param length Number of bytes to erase
236 * \returns CY_RSLT_SUCCESS if the erase was successful, an error code
237 * otherwise.
238 */
239 cy_rslt_t cy_serial_flash_qspi_erase(uint32_t addr, size_t length);
240
241 /**
242 * \brief Enables Execute-in-Place (memory mapped) mode on the MCU. This
243 * function does not send any command to the serial flash. This may not be
244 * supported on all the targets in which case
245 * CY_RSLT_SERIAL_FLASH_ERR_UNSUPPORTED is returned.
246 * \param enable true: XIP mode is set, false: normal mode is set
247 * \returns CY_RSLT_SUCCESS if the operation was successful.
248 * CY_RSLT_SERIAL_FLASH_ERR_UNSUPPORTED if the target does not
249 * support XIP.
250 */
251 cy_rslt_t cy_serial_flash_qspi_enable_xip(bool enable);
252
253 /**
254 * \brief Changes QSPI interrupt priority
255 * \param priority interrupt priority to be set
256 */
257 void cy_serial_flash_qspi_set_interrupt_priority(uint8_t priority);
258
259 /**
260 * \brief Changes the DMA interrupt priority
261 * \param priority interrupt priority to be set
262 */
263 void cy_serial_flash_qspi_set_dma_interrupt_priority(uint8_t priority);
264
265
266 #if defined(__cplusplus)
267 }
268 #endif
269
270 #endif // CY_IP_MXSMIF
271
272 /** \} group_board_libs */
273