1 /***************************************************************************//**
2 * \file cy_smif_memslot.c
3 * \version 2.100
4 *
5 * \brief
6 * This file provides the source code for the memory-level APIs of the SMIF driver.
7 *
8 * Note:
9 *
10 ********************************************************************************
11 * \copyright
12 * Copyright 2016-2022 Cypress Semiconductor Corporation
13 * SPDX-License-Identifier: Apache-2.0
14 *
15 * Licensed under the Apache License, Version 2.0 (the "License");
16 * you may not use this file except in compliance with the License.
17 * You may obtain a copy of the License at
18 *
19 * http://www.apache.org/licenses/LICENSE-2.0
20 *
21 * Unless required by applicable law or agreed to in writing, software
22 * distributed under the License is distributed on an "AS IS" BASIS,
23 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24 * See the License for the specific language governing permissions and
25 * limitations under the License.
26 *******************************************************************************/
27
28 #include "cy_device.h"
29
30 #if defined (CY_IP_MXSMIF) && (CY_IP_MXSMIF_VERSION <= 5)
31
32 #include "cy_smif_memslot.h"
33 #include "cy_gpio.h"
34
35 #if defined(__cplusplus)
36 extern "C" {
37 #endif
38
39 /** \cond INTERNAL */
40 /***************************************
41 * Internal Constants
42 ***************************************/
43 #define SMIF_MAX_RX_COUNT (65536UL)
44 #define ONE_MILLI_IN_MICRO (1000UL)
45 #define TIMEOUT_SLICE_MAX (1000000UL) /* The maximum timeout slice (microseconds)
46 * while polling the memory */
47 #define TIMEOUT_SLICE_DIV (4U) /* The division factor to use for slicing the timeout
48 * while polling the memory
49 */
50 /** \endcond */
51
52 /*******************************************************************************
53 * Function Name: Cy_SMIF_MemInit
54 ****************************************************************************//**
55 *
56 * This function initializes the slots of the memory device in the SMIF
57 * configuration.
58 * This function must be called when a memory device is required to be used
59 * in memory-mapped (XIP) mode. This function can also be called instead of
60 * calling \ref Cy_SMIF_MemSfdpDetect when SFDP auto-discovery is enabled.
61 * Note that this function performs SFDP on all the external memories whereas
62 * \ref Cy_SMIF_MemSfdpDetect performs it only on one memory that is specified
63 * through the arguments. This function configures the SMIF device slot registers
64 * with the configuration from \ref cy_stc_smif_mem_config_t structure which is
65 * a member of the \ref cy_stc_smif_block_config_t structure. If SFDP discovery
66 * is enabled in the configuration structure through autoDetectSfdp field,
67 * this function calls \ref Cy_SMIF_MemSfdpDetect function for each memory,
68 * fills the structures with the discovered parameters, and configures the
69 * SMIF device slot registers accordingly. \ref Cy_SMIF_Init must have been
70 * called prior to calling this function.
71 * The \ref cy_stc_smif_context_t context structure returned from \ref Cy_SMIF_Init
72 * is passed as a parameter to this function.
73 *
74 * \note 4-byte addressing mode is set when the memory device supports
75 * 3- or 4-byte addressing mode.
76 *
77 * \param base
78 * The address of the slave-slot device register to initialize.
79 *
80 * \param blockConfig
81 * The configuration structure array that configures the SMIF memory device to be
82 * mapped into the PSoC memory map. \ref cy_stc_smif_mem_config_t
83 *
84 * \param context
85 * This is the pointer to the context structure \ref cy_stc_smif_context_t
86 * allocated by the user. The structure is used during the SMIF
87 * operation for internal configuration and data retention. The user must not
88 * modify anything in this structure.
89 *
90 * \return The memory slot initialization status.
91 * - \ref CY_SMIF_SUCCESS
92 * - \ref CY_SMIF_BAD_PARAM
93 * - \ref CY_SMIF_SFDP_SS0_FAILED
94 * - \ref CY_SMIF_SFDP_SS1_FAILED
95 * - \ref CY_SMIF_SFDP_SS2_FAILED
96 * - \ref CY_SMIF_SFDP_SS3_FAILED
97 *
98 *******************************************************************************/
Cy_SMIF_MemInit(SMIF_Type * base,cy_stc_smif_block_config_t const * blockConfig,cy_stc_smif_context_t * context)99 cy_en_smif_status_t Cy_SMIF_MemInit(SMIF_Type *base,
100 cy_stc_smif_block_config_t const * blockConfig,
101 cy_stc_smif_context_t *context)
102 {
103 SMIF_DEVICE_Type volatile * device;
104 cy_stc_smif_mem_config_t const * memCfg;
105 uint32_t result = (uint32_t)CY_SMIF_BAD_PARAM;
106 uint32_t sfdpRes =(uint32_t)CY_SMIF_SUCCESS;
107 uint32_t idx;
108
109 if ((NULL != base) && (NULL != blockConfig) && (NULL != blockConfig->memConfig)
110 && (NULL != context) && (0U != blockConfig->memCount))
111 {
112 uint32_t size = blockConfig->memCount;
113 cy_stc_smif_mem_config_t** extMemCfg = blockConfig->memConfig;
114
115 result = (uint32_t)CY_SMIF_SUCCESS;
116 for(idx = 0UL; idx < size; idx++)
117 {
118 memCfg = extMemCfg[idx];
119 if (NULL != memCfg)
120 {
121 /* Check smif memory slot configuration */
122 CY_ASSERT_L3(CY_SMIF_SLAVE_SEL_VALID(memCfg->slaveSelect));
123 CY_ASSERT_L3(CY_SMIF_DATA_SEL_VALID(memCfg->dataSelect));
124
125 #if (CY_IP_MXSMIF_VERSION >= 2)
126 context->flags = memCfg->flags;
127 #endif /* (CY_IP_MXSMIF_VERSION>=2) */
128
129 /* Before SFDP Enumeration, configure SMIF dedicated Clock and RWDS lines */
130 #if (CY_IP_MXSMIF_VERSION >= 5)
131 SMIF_CLK_HSIOM(base) = ((uint32_t)(HSIOM_SEL_ACT_15)) | (((uint32_t)HSIOM_SEL_ACT_15) << 8U);
132 SMIF_RWDS_HSIOM(base) = (uint32_t)HSIOM_SEL_ACT_15;
133 SMIF_CLK_DRIVEMODE(base) = CY_GPIO_DM_STRONG | (CY_GPIO_DM_STRONG << 4U);
134 SMIF_RWDS_DRIVEMODE(base) = CY_GPIO_DM_PULLDOWN;
135
136 /* DRIVE Strength kept as full for initial bring up.
137 In case of power consumption impact we have to optimize this setting */
138 SMIF_CLK_DRIVE_STRENGTH(base) = ((CY_GPIO_DRIVE_FULL) | (CY_GPIO_DRIVE_FULL << 8U));
139 SMIF_RWDS_DRIVE_STRENGTH(base) = CY_GPIO_DRIVE_FULL;
140 #endif
141
142 /* SPI(deviceCfg) and Hyperbus(hbdeviceCfg) are mutually exclusive and if both are initialized, priority would be for SPI(deviceCfg) */
143 if(memCfg->deviceCfg != NULL)
144 {
145 device = Cy_SMIF_GetDeviceBySlot(base, memCfg->slaveSelect);
146 if (NULL != device)
147 {
148 /* The slave-slot initialization of the device control register.
149 * Cy_SMIF_MemSfdpDetect() must work */
150 SMIF_DEVICE_CTL(device) = _CLR_SET_FLD32U(SMIF_DEVICE_CTL(device),
151 SMIF_DEVICE_CTL_DATA_SEL,
152 (uint32_t)memCfg->dataSelect);
153
154 uint32_t sfdpRet = (uint32_t)CY_SMIF_SUCCESS;
155 if (0U != (memCfg->flags & CY_SMIF_FLAG_DETECT_SFDP))
156 {
157 sfdpRet = (uint32_t)Cy_SMIF_MemSfdpDetect(base,
158 memCfg->deviceCfg,
159 memCfg->slaveSelect,
160 memCfg->dataSelect,
161 context);
162 if((uint32_t)CY_SMIF_SUCCESS != sfdpRet)
163 {
164 sfdpRes |= ((uint32_t)CY_SMIF_SFDP_FAIL << idx);
165 }
166 }
167 /* Check the size of the smif memory slot address */
168 CY_ASSERT_L2(MEM_ADDR_SIZE_VALID(memCfg->deviceCfg->numOfAddrBytes));
169
170 /* Check if SMIF XIP is already enabled, then do not overwrite XIP registers */
171 if (((uint32_t)CY_SMIF_SUCCESS == sfdpRet) &&
172 (0U != (memCfg->flags & CY_SMIF_FLAG_MEMORY_MAPPED)) &&
173 (_FLD2VAL(SMIF_CTL_XIP_MODE, SMIF_CTL(base)) != 1U))
174 {
175 /* Check valid parameters for XIP */
176 CY_ASSERT_L3(MEM_ADDR_VALID( memCfg->baseAddress, memCfg->memMappedSize));
177 CY_ASSERT_L3(MEM_MAPPED_SIZE_VALID( memCfg->memMappedSize));
178
179 XipRegInit(device, memCfg);
180
181 #if(CY_IP_MXSMIF_VERSION>=2)
182 context->preXIPDataRate = memCfg->deviceCfg->readCmd->dataRate;
183 #endif /* CY_IP_MXSMIF_VERSION */
184 #if (CY_IP_MXSMIF_VERSION >= 4)
185 if (context->preXIPDataRate == CY_SMIF_DDR)
186 {
187 SMIF_DEVICE_RX_CAPTURE_CONFIG(device) |= _VAL2FLD(SMIF_CORE_DEVICE_RX_CAPTURE_CONFIG_DDR_PIPELINE_POS_DAT, 1U) |
188 _VAL2FLD(SMIF_CORE_DEVICE_RX_CAPTURE_CONFIG_DDR_SWAP_BYTES, 1U);
189 }
190 /* DDR_PIPELINE_POS_DAT should be SET for RX Capture mode xSPI */
191 if (_FLD2VAL(SMIF_CORE_CTL2_RX_CAPTURE_MODE, (SMIF_CTL2(base))) == (uint32_t)CY_SMIF_SEL_XSPI_HYPERBUS_WITH_DQS)
192 {
193 SMIF_DEVICE_RX_CAPTURE_CONFIG(device) |= _VAL2FLD(SMIF_CORE_DEVICE_RX_CAPTURE_CONFIG_DDR_PIPELINE_POS_DAT, 1U);
194 }
195 #endif
196
197 /* The device control register initialization */
198 SMIF_DEVICE_CTL(device) = _VAL2FLD(SMIF_DEVICE_CTL_WR_EN, ((bool)(memCfg->flags & CY_SMIF_FLAG_WRITE_ENABLE))? 1U : 0U) |
199 _VAL2FLD(SMIF_DEVICE_CTL_CRYPTO_EN, ((bool)(memCfg->flags & CY_SMIF_FLAG_CRYPTO_ENABLE))? 1U : 0U) |
200 _VAL2FLD(SMIF_DEVICE_CTL_DATA_SEL, (uint32_t)memCfg->dataSelect) |
201 #if(CY_IP_MXSMIF_VERSION>=2)
202 _VAL2FLD(SMIF_DEVICE_CTL_MERGE_EN, ((bool)(memCfg->flags & CY_SMIF_FLAG_MERGE_ENABLE))? 1U : 0U) |
203 _VAL2FLD(SMIF_DEVICE_CTL_MERGE_TIMEOUT, (uint32_t)memCfg->mergeTimeout) |
204 #endif /* CY_IP_MXSMIF_VERSION */
205 SMIF_DEVICE_CTL_ENABLED_Msk;
206 }
207 }
208 else
209 {
210 result = (uint32_t)CY_SMIF_BAD_PARAM;
211 break;
212 }
213 }
214 #if (CY_IP_MXSMIF_VERSION>=2) && defined (SMIF_HYPERBUS_DEVICE_SUPPORT)
215 else if(memCfg->hbdeviceCfg != NULL)
216 {
217 result = (uint32_t)Cy_SMIF_HyperBus_InitDevice(base, memCfg, context);
218 }
219 #endif /* (CY_IP_MXSMIF_VERSION>=2) && defined (SMIF_HYPERBUS_DEVICE_SUPPORT) */
220 else
221 {
222 result = (uint32_t)CY_SMIF_BAD_PARAM;
223 break;
224 }
225 }
226 }
227 }
228 if((uint32_t)CY_SMIF_SUCCESS != sfdpRes)
229 {
230 result = (((uint32_t)CY_SMIF_ID) | ((uint32_t)CY_PDL_STATUS_ERROR) | sfdpRes);
231 }
232 return (cy_en_smif_status_t) result;
233 }
234
235 /*******************************************************************************
236 * Function Name: Cy_SMIF_MemDeInit
237 ****************************************************************************//**
238 *
239 * This function de-initializes all slave slots of the memory device to their default
240 * values.
241 *
242 * \param base
243 * Holds the base address of the SMIF block registers.
244 *
245 *******************************************************************************/
Cy_SMIF_MemDeInit(SMIF_Type * base)246 void Cy_SMIF_MemDeInit(SMIF_Type *base)
247 {
248 /* Configure the SMIF device slots to the default values. The default value is 0 */
249 uint32_t deviceIndex;
250
251 #if (CY_IP_MXSMIF_VERSION >= 5)
252 SMIF_CLK_HSIOM(base) = (uint32_t)HSIOM_SEL_GPIO;
253 SMIF_RWDS_HSIOM(base) = (uint32_t)HSIOM_SEL_GPIO;
254 SMIF_CLK_DRIVEMODE(base) = CY_GPIO_DM_ANALOG | (CY_GPIO_DM_ANALOG << 8U);
255 SMIF_RWDS_DRIVEMODE(base) = CY_GPIO_DM_ANALOG;
256 #endif
257
258 for(deviceIndex = 0UL; deviceIndex < (uint32_t)SMIF_DEVICE_NR; deviceIndex++)
259 {
260 SMIF_DEVICE_IDX_CTL(base, deviceIndex) = 0U;
261 SMIF_DEVICE_IDX_ADDR(base, deviceIndex) = 0U;
262 SMIF_DEVICE_IDX_MASK(base, deviceIndex) = 0U;
263 SMIF_DEVICE_IDX_ADDR_CTL(base, deviceIndex) = 0U;
264 SMIF_DEVICE_IDX_RD_CMD_CTL(base, deviceIndex) = 0U;
265 SMIF_DEVICE_IDX_RD_ADDR_CTL(base, deviceIndex) = 0U;
266 SMIF_DEVICE_IDX_RD_MODE_CTL(base, deviceIndex) = 0U;
267 SMIF_DEVICE_IDX_RD_DUMMY_CTL(base, deviceIndex) = 0U;
268 SMIF_DEVICE_IDX_RD_DATA_CTL(base, deviceIndex) = 0U;
269 SMIF_DEVICE_IDX_WR_CMD_CTL(base, deviceIndex) = 0U;
270 SMIF_DEVICE_IDX_WR_ADDR_CTL(base, deviceIndex) = 0U;
271 SMIF_DEVICE_IDX_WR_MODE_CTL(base, deviceIndex) = 0U;
272 SMIF_DEVICE_IDX_WR_DUMMY_CTL(base, deviceIndex) = 0U;
273 SMIF_DEVICE_IDX_WR_DATA_CTL(base, deviceIndex) = 0U;
274 }
275 }
276
277
278 /*******************************************************************************
279 * Function Name: Cy_SMIF_MemCmdWriteEnable
280 ****************************************************************************//**
281 *
282 * This function sends the Write Enable command to the memory device.
283 *
284 * \note This function uses the low-level Cy_SMIF_TransmitCommand() API.
285 * The Cy_SMIF_TransmitCommand() API works in a blocking mode. In the dual quad mode,
286 * this API is called for each memory.
287 *
288 * \param base
289 * Holds the base address of the SMIF block registers.
290 *
291 * \param memDevice
292 * The device to which the command is sent.
293 *
294 * \param context
295 * This is the pointer to the context structure \ref cy_stc_smif_context_t
296 * allocated by the user. The structure is used during the SMIF
297 * operation for internal configuration and data retention. The user must not
298 * modify anything in this structure.
299 *
300 * \return A status of the command transmission.
301 * - \ref CY_SMIF_SUCCESS
302 * - \ref CY_SMIF_EXCEED_TIMEOUT
303 * - \ref CY_SMIF_CMD_NOT_FOUND
304 *
305 *******************************************************************************/
Cy_SMIF_MemCmdWriteEnable(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,cy_stc_smif_context_t const * context)306 cy_en_smif_status_t Cy_SMIF_MemCmdWriteEnable(SMIF_Type *base,
307 cy_stc_smif_mem_config_t const *memDevice,
308 cy_stc_smif_context_t const *context)
309 {
310 /* The memory Write Enable */
311 cy_stc_smif_mem_cmd_t* writeEn = memDevice->deviceCfg->writeEnCmd;
312
313 cy_en_smif_status_t result = CY_SMIF_CMD_NOT_FOUND;
314
315 if(NULL != writeEn)
316 {
317 #if (CY_IP_MXSMIF_VERSION>=2)
318 result = Cy_SMIF_TransmitCommand_Ext( base,
319 (uint16_t)(writeEn->command | writeEn->command << 8),
320 (writeEn->cmdWidth == CY_SMIF_WIDTH_OCTAL) ? true : false,
321 writeEn->cmdWidth,
322 writeEn->cmdRate,
323 NULL,
324 0,
325 CY_SMIF_WIDTH_NA,
326 writeEn->addrRate,
327 memDevice->slaveSelect,
328 CY_SMIF_TX_LAST_BYTE,
329 context);
330 #else
331 result = Cy_SMIF_TransmitCommand( base, (uint8_t) writeEn->command,
332 writeEn->cmdWidth,
333 NULL,
334 CY_SMIF_CMD_WITHOUT_PARAM,
335 CY_SMIF_WIDTH_NA,
336 memDevice->slaveSelect,
337 CY_SMIF_TX_LAST_BYTE,
338 context);
339 #endif
340 }
341
342 return result;
343 }
344
345
346 /*******************************************************************************
347 * Function Name: Cy_SMIF_MemCmdWriteDisable
348 ****************************************************************************//**
349 *
350 * This function sends a Write Disable command to the memory device.
351 *
352 * \note This function uses the low-level Cy_SMIF_TransmitCommand() API.
353 * Cy_SMIF_TransmitCommand() API works in a blocking mode. In the dual quad mode
354 * this API should be called for each memory.
355 *
356 * \param base
357 * Holds the base address of the SMIF block registers.
358 *
359 * \param memDevice
360 * The device to which the command is sent.
361 *
362 * \param context
363 * This is the pointer to the context structure \ref cy_stc_smif_context_t
364 * allocated by the user. The structure is used during the SMIF
365 * operation for internal configuration and data retention. The user must not
366 * modify anything in this structure.
367 *
368 * \return A status of the command transmission.
369 * - \ref CY_SMIF_SUCCESS
370 * - \ref CY_SMIF_EXCEED_TIMEOUT
371 * - \ref CY_SMIF_CMD_NOT_FOUND
372 *
373 *******************************************************************************/
Cy_SMIF_MemCmdWriteDisable(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,cy_stc_smif_context_t const * context)374 cy_en_smif_status_t Cy_SMIF_MemCmdWriteDisable(SMIF_Type *base,
375 cy_stc_smif_mem_config_t const *memDevice,
376 cy_stc_smif_context_t const *context)
377 {
378 cy_stc_smif_mem_cmd_t* writeDis = memDevice->deviceCfg->writeDisCmd;
379
380 cy_en_smif_status_t result = CY_SMIF_CMD_NOT_FOUND;
381
382 if(NULL != writeDis)
383 {
384 #if (CY_IP_MXSMIF_VERSION>=2)
385 result = Cy_SMIF_TransmitCommand_Ext( base,
386 (uint16_t)(writeDis->command | writeDis->command << 8),
387 (writeDis->cmdWidth == CY_SMIF_WIDTH_OCTAL) ? true : false,
388 writeDis->cmdWidth,
389 writeDis->cmdRate,
390 NULL,
391 0,
392 CY_SMIF_WIDTH_NA,
393 writeDis->addrRate,
394 memDevice->slaveSelect,
395 CY_SMIF_TX_LAST_BYTE,
396 context);
397 #else
398 /* The memory write disable */
399 result = Cy_SMIF_TransmitCommand( base, (uint8_t)writeDis->command,
400 writeDis->cmdWidth,
401 NULL,
402 CY_SMIF_CMD_WITHOUT_PARAM,
403 CY_SMIF_WIDTH_NA,
404 memDevice->slaveSelect,
405 CY_SMIF_TX_LAST_BYTE,
406 context);
407 #endif
408 }
409
410 return result;
411 }
412
413
414 /*******************************************************************************
415 * Function Name: Cy_SMIF_MemIsBusy
416 ****************************************************************************//**
417 *
418 * This function checks if the status of the memory device is busy.
419 * This is done by reading the status register and the corresponding bit
420 * (stsRegBusyMask). This function is a blocking function until the status
421 * register from the memory is read.
422 *
423 * \note In the dual quad mode, this API is called for each memory.
424 *
425 * \param base
426 * Holds the base address of the SMIF block registers.
427 *
428 * \param memDevice
429 * The device to which the command is sent.
430 *
431 * \param context
432 * This is the pointer to the context structure \ref cy_stc_smif_context_t
433 * allocated by the user. The structure is used during the SMIF
434 * operation for internal configuration and data retention. The user must not
435 * modify anything in this structure.
436 *
437 * \return A status of the memory device.
438 * - True - The device is busy or a timeout occurs.
439 * - False - The device is not busy.
440 *
441 * \note Check \ref group_smif_usage_rules for any usage restriction
442 *
443 *******************************************************************************/
Cy_SMIF_MemIsBusy(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,cy_stc_smif_context_t const * context)444 bool Cy_SMIF_MemIsBusy(SMIF_Type *base, cy_stc_smif_mem_config_t const *memDevice,
445 cy_stc_smif_context_t const *context)
446 {
447 uint16_t status = 1U;
448 cy_en_smif_status_t readStsResult = CY_SMIF_CMD_NOT_FOUND;
449 cy_stc_smif_mem_device_cfg_t* device = memDevice->deviceCfg;
450
451 if(NULL != device->readStsRegWipCmd)
452 {
453 #if (CY_IP_MXSMIF_VERSION>=2)
454 if (device->readStsRegWipCmd->cmdWidth == CY_SMIF_WIDTH_OCTAL)
455 {
456 uint8_t addr_param[4] = {0};
457 /* Read the memory status register */
458 readStsResult = Cy_SMIF_TransmitCommand_Ext( base,
459 (uint16_t)(device->readStsRegWipCmd->command | (device->readStsRegWipCmd->command << 8)),
460 true,
461 device->readStsRegWipCmd->cmdWidth,
462 device->readStsRegWipCmd->cmdRate,
463 addr_param, sizeof(addr_param),
464 device->readStsRegWipCmd->addrWidth,
465 device->readStsRegWipCmd->addrRate,
466 memDevice->slaveSelect,
467 CY_SMIF_TX_NOT_LAST_BYTE,
468 context);
469
470 if ((CY_SMIF_SUCCESS == readStsResult) && (device->readStsRegWipCmd->dummyCycles > 0U))
471 {
472 readStsResult = Cy_SMIF_SendDummyCycles_Ext(base,
473 device->readStsRegWipCmd->addrWidth,
474 device->readStsRegWipCmd->addrRate,
475 device->readStsRegWipCmd->dummyCycles);
476 }
477 if (CY_SMIF_SUCCESS == readStsResult)
478 {
479 readStsResult = Cy_SMIF_ReceiveDataBlocking_Ext( base, (uint8_t *)&status,
480 (device->readStsRegWipCmd->cmdRate == CY_SMIF_DDR) ? 2U : 1U,
481 device->readStsRegWipCmd->cmdWidth,
482 device->readStsRegWipCmd->cmdRate,
483 context);
484 }
485
486 }
487 else
488 {
489 #endif
490 readStsResult = Cy_SMIF_MemCmdReadStatus(base, memDevice, (uint8_t *)&status,
491 (uint8_t)device->readStsRegWipCmd->command,
492 context);
493 #if (CY_IP_MXSMIF_VERSION>=2)
494 }
495 #endif
496 }
497
498 if (CY_SMIF_SUCCESS == readStsResult)
499 {
500 /* Masked not busy bits in returned status */
501 status &= (uint8_t)device->stsRegBusyMask;
502 }
503
504 return (0U != status);
505 }
506
507
508 /*******************************************************************************
509 * Function Name: Cy_SMIF_MemQuadEnable
510 ****************************************************************************//**
511 *
512 * This function enables the memory device for the quad mode of operation.
513 * This command must be executed before sending quad SPI commands to the
514 * memory device.
515 *
516 * \note In the dual quad mode, this API is called for each memory.
517 *
518 * \param base
519 * Holds the base address of the SMIF block registers.
520 *
521 * \param memDevice
522 * The device to which the command is sent.
523 *
524 * \param context
525 * This is the pointer to the context structure \ref cy_stc_smif_context_t
526 * allocated by the user. The structure is used during the SMIF
527 * operation for internal configuration and data retention. The user must not
528 * modify anything in this structure.
529 *
530 * \return A status of the command.
531 * - \ref CY_SMIF_SUCCESS
532 * - \ref CY_SMIF_NO_QE_BIT
533 * - \ref CY_SMIF_CMD_FIFO_FULL
534 * - \ref CY_SMIF_BAD_PARAM
535 * - \ref CY_SMIF_CMD_NOT_FOUND
536 *
537 * \note Check \ref group_smif_usage_rules for any usage restriction
538 *
539 *******************************************************************************/
Cy_SMIF_MemQuadEnable(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,cy_stc_smif_context_t const * context)540 cy_en_smif_status_t Cy_SMIF_MemQuadEnable(SMIF_Type *base,
541 cy_stc_smif_mem_config_t const *memDevice,
542 cy_stc_smif_context_t const *context)
543 {
544 cy_en_smif_status_t result= CY_SMIF_CMD_NOT_FOUND;
545 uint8_t statusReg[CY_SMIF_QE_BIT_STATUS_REG2_T1] = {0U};
546 cy_stc_smif_mem_device_cfg_t* device = memDevice->deviceCfg;
547
548 /* Check that command exists */
549 if((NULL != device->readStsRegQeCmd) &&
550 (NULL != device->writeStsRegQeCmd) &&
551 (NULL != device->readStsRegWipCmd))
552 {
553 uint8_t readQeCmd = (uint8_t)device->readStsRegQeCmd->command;
554 uint8_t writeQeCmd = (uint8_t)device->writeStsRegQeCmd->command;
555 uint8_t readWipCmd = (uint8_t)device->readStsRegWipCmd->command;
556
557 result = Cy_SMIF_MemCmdReadStatus(base, memDevice, &statusReg[0U],
558 readQeCmd, context);
559 if (CY_SMIF_SUCCESS == result)
560 {
561 uint32_t qeMask = device->stsRegQuadEnableMask;
562
563 switch(qeMask)
564 {
565 case CY_SMIF_SFDP_QE_BIT_6_OF_SR_1:
566 statusReg[0U] |= (uint8_t)qeMask;
567 result = Cy_SMIF_MemCmdWriteStatus(base, memDevice,
568 &statusReg[0U], writeQeCmd, context);
569 break;
570 case CY_SMIF_SFDP_QE_BIT_1_OF_SR_2:
571 /* Read status register 1 with the assumption that WIP is always in
572 * status register 1 */
573 result = Cy_SMIF_MemCmdReadStatus(base, memDevice,
574 &statusReg[0U], readWipCmd, context);
575 if (CY_SMIF_SUCCESS == result)
576 {
577 result = Cy_SMIF_MemCmdReadStatus(base, memDevice,
578 &statusReg[1U], readQeCmd, context);
579 if (CY_SMIF_SUCCESS == result)
580 {
581 statusReg[1U] |= (uint8_t)qeMask;
582
583 if (writeQeCmd == CY_SMIF_WRITE_STATUS_REG2_T2_CMD)
584 {
585 result = Cy_SMIF_MemCmdWriteStatus(base, memDevice,
586 &statusReg[1U], writeQeCmd, context);
587 }
588 else
589 {
590 result = Cy_SMIF_MemCmdWriteStatus(base, memDevice,
591 statusReg, writeQeCmd, context);
592 }
593 }
594 }
595 break;
596 case CY_SMIF_SFDP_QE_BIT_7_OF_SR_2:
597 result = Cy_SMIF_MemCmdReadStatus(base, memDevice,
598 &statusReg[1U], readQeCmd, context);
599 if (CY_SMIF_SUCCESS == result)
600 {
601 statusReg[1U] |= (uint8_t)qeMask;
602 result = Cy_SMIF_MemCmdWriteStatus(base, memDevice,
603 &statusReg[1U], writeQeCmd, context);
604 }
605 break;
606 default:
607 result = CY_SMIF_NO_QE_BIT;
608 break;
609 }
610 }
611 }
612 return(result);
613 }
614 #if (CY_IP_MXSMIF_VERSION>=2) || defined (CY_DOXYGEN)
615 /*******************************************************************************
616 * Function Name: Cy_SMIF_MemOctalEnable
617 ****************************************************************************//**
618 *
619 * This function enables the memory device for the octal mode of operation.
620 * This command must be executed before sending octal SPI commands to the
621 * memory device.
622 *
623 * \param base
624 * Holds the base address of the SMIF block registers.
625 *
626 * \param memDevice
627 * The device to which the command is sent.
628 *
629 * \param dataRate
630 * Specifies the data rate to enable (SDR/DDR).
631 *
632 * \param context
633 * This is the pointer to the context structure \ref cy_stc_smif_context_t
634 * allocated by the user. The structure is used during the SMIF
635 * operation for internal configuration and data retention. The user must not
636 * modify anything in this structure.
637 *
638 * \return A status of the command.
639 * - \ref CY_SMIF_SUCCESS
640 * - \ref CY_SMIF_NO_OE_BIT
641 * - \ref CY_SMIF_CMD_FIFO_FULL
642 * - \ref CY_SMIF_BAD_PARAM
643 * - \ref CY_SMIF_CMD_NOT_FOUND
644 *
645 * \note Check \ref group_smif_usage_rules for any usage restriction
646 *
647 * \snippet smif/snippet/main.c snippet_Cy_SMIF_MemOctalEnable
648 *******************************************************************************/
Cy_SMIF_MemOctalEnable(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,cy_en_smif_data_rate_t dataRate,cy_stc_smif_context_t const * context)649 cy_en_smif_status_t Cy_SMIF_MemOctalEnable(SMIF_Type *base,
650 cy_stc_smif_mem_config_t const *memDevice,
651 cy_en_smif_data_rate_t dataRate,
652 cy_stc_smif_context_t const *context)
653 {
654 cy_en_smif_status_t result= CY_SMIF_CMD_NOT_FOUND;
655 cy_stc_smif_mem_device_cfg_t* device = memDevice->deviceCfg;
656
657 if (dataRate == CY_SMIF_DDR)
658 {
659 cy_stc_smif_octal_ddr_en_seq_t* oDDREnSeq = device->octalDDREnableSeq;
660
661 /* Send Command Sequence 1 */
662 if ((oDDREnSeq != NULL) && (oDDREnSeq->cmdSeq1Len > 0U))
663 {
664 result = Cy_SMIF_TransmitCommand( base, oDDREnSeq->cmdSeq1[0], CY_SMIF_WIDTH_SINGLE,
665 (uint8_t const *)&oDDREnSeq->cmdSeq1[1U],
666 ((uint32_t)oDDREnSeq->cmdSeq1Len - 1U), CY_SMIF_WIDTH_SINGLE,
667 memDevice->slaveSelect, CY_SMIF_TX_LAST_BYTE, context);
668 }
669 /* Send Command Sequence 2 */
670 if ((oDDREnSeq != NULL) && (oDDREnSeq->cmdSeq2Len > 0U))
671 {
672 result = Cy_SMIF_TransmitCommand( base, oDDREnSeq->cmdSeq2[0], CY_SMIF_WIDTH_SINGLE,
673 (uint8_t const *)&oDDREnSeq->cmdSeq2[1U],
674 ((uint32_t)oDDREnSeq->cmdSeq2Len - 1U), CY_SMIF_WIDTH_SINGLE,
675 memDevice->slaveSelect, CY_SMIF_TX_LAST_BYTE, context);
676 }
677 }
678 else
679 {
680 /* Check that command exists */
681 if((NULL != device->readStsRegOeCmd) &&
682 (NULL != device->writeStsRegOeCmd))
683 {
684 uint8_t readOeCmd = (uint8_t)device->readStsRegOeCmd->command;
685 uint8_t writeOeCmd = (uint8_t)device->writeStsRegOeCmd->command;
686 uint8_t writeEnCmd = (uint8_t)device->writeEnCmd->command;
687 uint8_t octalEnableAddr[CY_SMIF_SFDP_ADDRESS_LENGTH + 1u] = {0U};
688
689 ValueToByteArray(device->octalEnableRegAddr, octalEnableAddr, 0u, CY_SMIF_SFDP_ADDRESS_LENGTH);
690
691 if (device->octalEnableRegAddr != CY_SMIF_NO_COMMAND_OR_MODE)
692 {
693 result = ReadAnyReg(base, memDevice->slaveSelect, &octalEnableAddr[CY_SMIF_SFDP_ADDRESS_LENGTH],
694 readOeCmd, 0, octalEnableAddr,
695 CY_SMIF_SFDP_ADDRESS_LENGTH, context);
696
697 if (CY_SMIF_SUCCESS == result)
698 {
699 uint32_t oeMask = device->stsRegOctalEnableMask;
700
701 octalEnableAddr[CY_SMIF_SFDP_ADDRESS_LENGTH] |= (uint8_t)oeMask;
702
703 /* The Write Enable */
704 result = Cy_SMIF_TransmitCommand(base, writeEnCmd,
705 CY_SMIF_WIDTH_SINGLE, NULL, 0U, CY_SMIF_WIDTH_SINGLE,
706 memDevice->slaveSelect, CY_SMIF_TX_LAST_BYTE, context);
707
708 /* The Write Status */
709 if (CY_SMIF_SUCCESS == result)
710 {
711 result = Cy_SMIF_TransmitCommand( base, writeOeCmd, CY_SMIF_WIDTH_SINGLE,
712 (uint8_t const *)octalEnableAddr, sizeof(octalEnableAddr), CY_SMIF_WIDTH_SINGLE,
713 memDevice->slaveSelect, CY_SMIF_TX_LAST_BYTE, context);
714 }
715 }
716 }
717 else
718 {
719 uint8_t statusReg = 0;
720 result = Cy_SMIF_MemCmdReadStatus(base, memDevice, &statusReg,
721 readOeCmd, context);
722 if (CY_SMIF_SUCCESS == result)
723 {
724 uint32_t oeMask = device->stsRegOctalEnableMask;
725
726 statusReg |= (uint8_t)oeMask;
727 result = Cy_SMIF_MemCmdWriteStatus(base, memDevice,
728 &statusReg, writeOeCmd, context);
729 }
730 }
731 }
732 }
733 return (result);
734 }
735 #endif
736
737 /*******************************************************************************
738 * Function Name: Cy_SMIF_MemCmdReadStatus
739 ****************************************************************************//**
740 *
741 * This function reads the status register. This function is a blocking function,
742 * it will block the execution flow until the status register is read.
743 *
744 * \note This function uses the low-level Cy_SMIF_TransmitCommand() API.
745 * the Cy_SMIF_TransmitCommand() API works in a blocking mode. In the dual quad mode,
746 * this API is called for each memory.
747 *
748 * \param base
749 * Holds the base address of the SMIF block registers.
750 *
751 * \param memDevice
752 * The device to which the command is sent.
753 *
754 * \param status
755 * The status register value returned by the external memory.
756 *
757 * \param command
758 * The command required to read the status/configuration register.
759 *
760 * \param context
761 * This is the pointer to the context structure \ref cy_stc_smif_context_t
762 * allocated by the user. The structure is used during the SMIF
763 * operation for internal configuration and data retention. The user must not
764 * modify anything in this structure.
765 *
766 * \return A status of the command reception.
767 * - \ref CY_SMIF_SUCCESS
768 * - \ref CY_SMIF_CMD_FIFO_FULL
769 * - \ref CY_SMIF_EXCEED_TIMEOUT
770 * - \ref CY_SMIF_CMD_NOT_FOUND
771 *
772 * \note Check \ref group_smif_usage_rules for any usage restriction
773 *
774 *******************************************************************************/
Cy_SMIF_MemCmdReadStatus(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,uint8_t * status,uint8_t command,cy_stc_smif_context_t const * context)775 cy_en_smif_status_t Cy_SMIF_MemCmdReadStatus(SMIF_Type *base,
776 cy_stc_smif_mem_config_t const *memDevice,
777 uint8_t *status,
778 uint8_t command,
779 cy_stc_smif_context_t const *context)
780 {
781 cy_en_smif_status_t result = CY_SMIF_CMD_NOT_FOUND;
782
783 /* Read the memory status register */
784 result = Cy_SMIF_TransmitCommand( base, command, CY_SMIF_WIDTH_SINGLE,
785 NULL, CY_SMIF_CMD_WITHOUT_PARAM,
786 CY_SMIF_WIDTH_NA, memDevice->slaveSelect,
787 CY_SMIF_TX_NOT_LAST_BYTE, context);
788
789 if (CY_SMIF_SUCCESS == result)
790 {
791 result = Cy_SMIF_ReceiveDataBlocking( base, status,
792 CY_SMIF_READ_ONE_BYTE, CY_SMIF_WIDTH_SINGLE, context);
793 }
794
795 return(result);
796 }
797
798
799 /*******************************************************************************
800 * Function Name: Cy_SMIF_MemCmdWriteStatus
801 ****************************************************************************//**
802 *
803 * This function writes the status register. This is a blocking function, it will
804 * block the execution flow until the command transmission is completed.
805 *
806 * \note This function uses the low-level Cy_SMIF_TransmitCommand() API.
807 * The Cy_SMIF_TransmitCommand() API works in a blocking mode. In the dual quad mode,
808 * this API is called for each memory.
809 *
810 * \param base
811 * Holds the base address of the SMIF block registers.
812 *
813 * \param memDevice
814 * The device to which the command is sent.
815 *
816 * \param status
817 * The status to write into the status register.
818 *
819 * \param command
820 * The command to write into the status/configuration register.
821 *
822 * \param context
823 * This is the pointer to the context structure \ref cy_stc_smif_context_t
824 * allocated by the user. The structure is used during the SMIF
825 * operation for internal configuration and data retention. The user must not
826 * modify anything in this structure.
827 *
828 * \return A status of the command transmission.
829 * - \ref CY_SMIF_SUCCESS
830 * - \ref CY_SMIF_EXCEED_TIMEOUT
831 * - \ref CY_SMIF_CMD_NOT_FOUND
832 *
833 *******************************************************************************/
Cy_SMIF_MemCmdWriteStatus(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,void const * status,uint8_t command,cy_stc_smif_context_t const * context)834 cy_en_smif_status_t Cy_SMIF_MemCmdWriteStatus(SMIF_Type *base,
835 cy_stc_smif_mem_config_t const *memDevice,
836 void const *status,
837 uint8_t command,
838 cy_stc_smif_context_t const *context)
839 {
840 cy_en_smif_status_t result;
841
842 /* The Write Enable */
843 result = Cy_SMIF_MemCmdWriteEnable(base, memDevice, context);
844
845 /* The Write Status */
846 if (CY_SMIF_SUCCESS == result)
847 {
848 uint32_t size;
849 uint32_t qeMask = memDevice->deviceCfg->stsRegQuadEnableMask;
850
851 size = ( (CY_SMIF_SFDP_QE_BIT_1_OF_SR_2 == qeMask) && (memDevice->deviceCfg->writeStsRegQeCmd->command == CY_SMIF_WRITE_STATUS_REG1_CMD)) ?
852 CY_SMIF_WRITE_TWO_BYTES:CY_SMIF_WRITE_ONE_BYTE;
853 result = Cy_SMIF_TransmitCommand( base, command, CY_SMIF_WIDTH_SINGLE,
854 (uint8_t const *)status, size, CY_SMIF_WIDTH_SINGLE,
855 memDevice->slaveSelect, CY_SMIF_TX_LAST_BYTE, context);
856 }
857
858 return(result);
859 }
860 /*******************************************************************************
861 * Function Name: Cy_SMIF_MemCmdChipErase
862 ****************************************************************************//**
863 *
864 * This function performs a chip erase of the external memory. The Write Enable
865 * command is called before this API.
866 *
867 * \note This function uses the low-level Cy_SMIF_TransmitCommand() API.
868 * Cy_SMIF_TransmitCommand() API works in a blocking mode. In the dual quad mode,
869 * this API is called for each memory.
870 *
871 * \param base
872 * Holds the base address of the SMIF block registers.
873 *
874 * \param memDevice
875 * The device to which the command is sent
876 *
877 * \param context
878 * This is the pointer to the context structure \ref cy_stc_smif_context_t
879 * allocated by the user. The structure is used during the SMIF
880 * operation for internal configuration and data retention. The user must not
881 * modify anything in this structure.
882 *
883 * \return A status of the command transmission.
884 * - \ref CY_SMIF_SUCCESS
885 * - \ref CY_SMIF_EXCEED_TIMEOUT
886 * - \ref CY_SMIF_CMD_NOT_FOUND
887 *
888 *******************************************************************************/
Cy_SMIF_MemCmdChipErase(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,cy_stc_smif_context_t const * context)889 cy_en_smif_status_t Cy_SMIF_MemCmdChipErase(SMIF_Type *base,
890 cy_stc_smif_mem_config_t const *memDevice,
891 cy_stc_smif_context_t const *context)
892 {
893 cy_en_smif_status_t result= CY_SMIF_CMD_NOT_FOUND;
894
895 cy_stc_smif_mem_cmd_t *cmdErase = memDevice->deviceCfg->chipEraseCmd;
896 if(NULL != cmdErase)
897 {
898 result = Cy_SMIF_TransmitCommand( base, (uint8_t)cmdErase->command,
899 cmdErase->cmdWidth, NULL,
900 CY_SMIF_CMD_WITHOUT_PARAM, CY_SMIF_WIDTH_NA,
901 memDevice->slaveSelect, CY_SMIF_TX_LAST_BYTE, context);
902 }
903
904 return(result);
905 }
906
907
908 /*******************************************************************************
909 * Function Name: Cy_SMIF_MemCmdSectorErase
910 ****************************************************************************//**
911 *
912 * This function performs a block Erase of the external memory. The Write Enable
913 * command is called before this API.
914 *
915 * \note This function uses the low-level Cy_SMIF_TransmitCommand() API.
916 * The Cy_SMIF_TransmitCommand() API works in a blocking mode. In the dual quad mode,
917 * this API is called for each memory.
918 *
919 * \param base
920 * Holds the base address of the SMIF block registers.
921 *
922 * \param memDevice
923 * The device to which the command is sent.
924 *
925 * \param sectorAddr
926 * The sector address to erase.
927 *
928 * \param context
929 * This is the pointer to the context structure \ref cy_stc_smif_context_t
930 * allocated by the user. The structure is used during the SMIF
931 * operation for internal configuration and data retention. The user must not
932 * modify anything in this structure.
933 *
934 * \return A status of the command transmission.
935 * - \ref CY_SMIF_SUCCESS
936 * - \ref CY_SMIF_BAD_PARAM
937 * - \ref CY_SMIF_EXCEED_TIMEOUT
938 * - \ref CY_SMIF_CMD_NOT_FOUND
939 *
940 *******************************************************************************/
Cy_SMIF_MemCmdSectorErase(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,uint8_t const * sectorAddr,cy_stc_smif_context_t const * context)941 cy_en_smif_status_t Cy_SMIF_MemCmdSectorErase(SMIF_Type *base,
942 cy_stc_smif_mem_config_t const *memDevice,
943 uint8_t const *sectorAddr,
944 cy_stc_smif_context_t const *context)
945 {
946 cy_en_smif_status_t result = CY_SMIF_BAD_PARAM;
947
948 CY_ASSERT_L1(NULL != memDevice);
949
950 if (NULL != sectorAddr)
951 {
952 cy_stc_smif_mem_device_cfg_t *device = memDevice->deviceCfg;
953 cy_stc_smif_mem_cmd_t *cmdErase = device->eraseCmd;
954 cy_stc_smif_hybrid_region_info_t* hybrInfo = NULL;
955
956 result = Cy_SMIF_MemLocateHybridRegion(memDevice, &hybrInfo,
957 ByteArrayToValue(sectorAddr, device->numOfAddrBytes));
958
959 if ((NULL != cmdErase) && (CY_SMIF_WIDTH_NA != cmdErase->cmdWidth) && (result != CY_SMIF_BAD_PARAM))
960 {
961 uint16_t eraseCommand = (uint16_t)((result == CY_SMIF_SUCCESS) ? (hybrInfo->eraseCmd) : (cmdErase->command));
962 #if (CY_IP_MXSMIF_VERSION>=2)
963 if (device->eraseCmd->cmdWidth != CY_SMIF_WIDTH_OCTAL)
964 {
965 #endif
966 result = Cy_SMIF_TransmitCommand( base, (uint8_t)eraseCommand,
967 cmdErase->cmdWidth, sectorAddr, device->numOfAddrBytes,
968 cmdErase->cmdWidth, memDevice->slaveSelect,
969 CY_SMIF_TX_LAST_BYTE, context);
970
971 #if (CY_IP_MXSMIF_VERSION>=2)
972 }
973 else
974 {
975 result = Cy_SMIF_TransmitCommand_Ext( base, (eraseCommand | ((uint16_t)eraseCommand << 8)),
976 true,cmdErase->cmdWidth, cmdErase->cmdRate, sectorAddr, device->numOfAddrBytes,
977 cmdErase->cmdWidth, cmdErase->addrRate, memDevice->slaveSelect,
978 CY_SMIF_TX_LAST_BYTE, context);
979
980 }
981 #endif
982 }
983 else
984 {
985 result = CY_SMIF_CMD_NOT_FOUND;
986 }
987 }
988 return(result);
989 }
990
991
992 /*******************************************************************************
993 * Function Name: Cy_SMIF_MemCmdProgram
994 ****************************************************************************//**
995 *
996 * This function performs the Program operation.
997 *
998 * \note This function uses the Cy_SMIF_TransmitCommand() API.
999 * The Cy_SMIF_TransmitCommand() API works in the blocking mode. In the dual quad mode,
1000 * this API works with both types of memory simultaneously.
1001 *
1002 * \param base
1003 * Holds the base address of the SMIF block registers.
1004 *
1005 * \param memDevice
1006 * The device to which the command is sent.
1007 *
1008 * \param addr
1009 * The address to program.
1010 *
1011 * \param writeBuff
1012 * The pointer to the data to program. If this pointer is a NULL, then the
1013 * function does not enable the interrupt. This use case is typically used when
1014 * the FIFO is handled outside the interrupt and is managed in either a
1015 * polling-based code or a DMA. The user would handle the FIFO management
1016 * in a DMA or a polling-based code.
1017 * If the user provides a NULL pointer in this function and does not handle
1018 * the FIFO transaction, this could either stall or timeout the operation
1019 * \ref Cy_SMIF_TransmitData().
1020 *
1021 * \param size
1022 * The size of data to program. The user must ensure that the data size
1023 * does not exceed the page size.
1024 *
1025 * \param cmdCompleteCb
1026 * The callback function to call after the transfer completion. NULL interpreted
1027 * as no callback.
1028 *
1029 * \param context
1030 * This is the pointer to the context structure \ref cy_stc_smif_context_t
1031 * allocated by the user. The structure is used during the SMIF
1032 * operation for internal configuration and data retention. The user must not
1033 * modify anything in this structure.
1034 *
1035 * \return A status of a transmission.
1036 * - \ref CY_SMIF_SUCCESS
1037 * - \ref CY_SMIF_CMD_FIFO_FULL
1038 * - \ref CY_SMIF_BAD_PARAM
1039 * - \ref CY_SMIF_EXCEED_TIMEOUT
1040 * - \ref CY_SMIF_CMD_NOT_FOUND
1041 *
1042 *******************************************************************************/
Cy_SMIF_MemCmdProgram(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,uint8_t const * addr,uint8_t const * writeBuff,uint32_t size,cy_smif_event_cb_t cmdCompleteCb,cy_stc_smif_context_t * context)1043 cy_en_smif_status_t Cy_SMIF_MemCmdProgram(SMIF_Type *base,
1044 cy_stc_smif_mem_config_t const *memDevice,
1045 uint8_t const *addr,
1046 uint8_t const *writeBuff,
1047 uint32_t size,
1048 cy_smif_event_cb_t cmdCompleteCb,
1049 cy_stc_smif_context_t *context)
1050 {
1051 cy_en_smif_status_t result = CY_SMIF_SUCCESS;
1052 cy_en_smif_slave_select_t slaveSelected;
1053
1054 cy_stc_smif_mem_device_cfg_t *device = memDevice->deviceCfg;
1055 cy_stc_smif_mem_cmd_t *cmdProg = device->programCmd;
1056
1057 if(NULL == cmdProg)
1058 {
1059 result = CY_SMIF_CMD_NOT_FOUND;
1060 }
1061 else if ((NULL == addr) || (size > device->programSize))
1062 {
1063 result = CY_SMIF_BAD_PARAM;
1064 }
1065 else
1066 {
1067 slaveSelected = (0U == memDevice->dualQuadSlots)? memDevice->slaveSelect :
1068 (cy_en_smif_slave_select_t)memDevice->dualQuadSlots;
1069
1070 #if (CY_IP_MXSMIF_VERSION>=2)
1071 if(cmdProg->cmdWidth == CY_SMIF_WIDTH_OCTAL)
1072 {
1073 /* The page program command */
1074 result = Cy_SMIF_TransmitCommand_Ext( base, (uint16_t)(cmdProg->command | cmdProg->command << 8),
1075 true,
1076 cmdProg->cmdWidth, cmdProg->cmdRate,
1077 addr, device->numOfAddrBytes,
1078 cmdProg->addrWidth, cmdProg->addrRate, slaveSelected, CY_SMIF_TX_NOT_LAST_BYTE,
1079 context);
1080
1081 if((CY_SMIF_SUCCESS == result) && (CY_SMIF_NO_COMMAND_OR_MODE != cmdProg->mode))
1082 {
1083 result = Cy_SMIF_TransmitCommand(base, (uint8_t)cmdProg->mode,
1084 cmdProg->modeWidth, NULL,
1085 CY_SMIF_CMD_WITHOUT_PARAM, CY_SMIF_WIDTH_NA,
1086 (cy_en_smif_slave_select_t)slaveSelected,
1087 CY_SMIF_TX_NOT_LAST_BYTE, context);
1088 }
1089
1090 if((CY_SMIF_SUCCESS == result) && (cmdProg->dummyCycles > 0U))
1091 {
1092 result = Cy_SMIF_SendDummyCycles_Ext(base, CY_SMIF_WIDTH_OCTAL, cmdProg->addrRate, cmdProg->dummyCycles);
1093 }
1094
1095 if(CY_SMIF_SUCCESS == result)
1096 {
1097 result = Cy_SMIF_TransmitData_Ext( base, writeBuff, size,
1098 cmdProg->dataWidth, cmdProg->dataRate, cmdCompleteCb, context);
1099 }
1100
1101 }
1102 else
1103 {
1104 #endif
1105 /* The page program command */
1106 result = Cy_SMIF_TransmitCommand( base, (uint8_t)cmdProg->command,
1107 cmdProg->cmdWidth, addr, device->numOfAddrBytes,
1108 cmdProg->addrWidth, slaveSelected, CY_SMIF_TX_NOT_LAST_BYTE,
1109 context);
1110
1111 if((CY_SMIF_SUCCESS == result) && (CY_SMIF_NO_COMMAND_OR_MODE != cmdProg->mode))
1112 {
1113 result = Cy_SMIF_TransmitCommand(base, (uint8_t)cmdProg->mode,
1114 cmdProg->modeWidth, NULL,
1115 CY_SMIF_CMD_WITHOUT_PARAM, CY_SMIF_WIDTH_NA,
1116 (cy_en_smif_slave_select_t)slaveSelected,
1117 CY_SMIF_TX_NOT_LAST_BYTE, context);
1118 }
1119
1120 if((CY_SMIF_SUCCESS == result) && (cmdProg->dummyCycles > 0U))
1121 {
1122 result = Cy_SMIF_SendDummyCycles(base, cmdProg->dummyCycles);
1123 }
1124
1125 if(CY_SMIF_SUCCESS == result)
1126 {
1127 result = Cy_SMIF_TransmitData( base, writeBuff, size,
1128 cmdProg->dataWidth, cmdCompleteCb, context);
1129 }
1130 #if (CY_IP_MXSMIF_VERSION>=2)
1131 }
1132 #endif
1133 }
1134
1135 return(result);
1136 }
1137
1138
1139 /*******************************************************************************
1140 * Function Name: Cy_SMIF_MemCmdRead
1141 ****************************************************************************//**
1142 *
1143 * This function performs the Read operation.
1144 *
1145 * \note This function uses the Cy_SMIF_TransmitCommand() API.
1146 * The Cy_SMIF_TransmitCommand() API works in the blocking mode. In the dual quad mode,
1147 * this API works with both types of memory simultaneously.
1148 *
1149 * \param base
1150 * Holds the base address of the SMIF block registers.
1151 *
1152 * \param memDevice
1153 * The device to which the command is sent.
1154 *
1155 * \param addr
1156 * The address to read.
1157 *
1158 * \param readBuff
1159 * The pointer to the variable where the read data is stored. If this pointer is
1160 * a NULL, then the function does not enable the interrupt. This use case is
1161 * typically used when the FIFO is handled outside the interrupt and is managed
1162 * in either a polling-based code or a DMA. The user would handle the FIFO
1163 * management in a DMA or a polling-based code.
1164 * If the user provides a NULL pointer in this function and does not handle
1165 * the FIFO transaction, this could either stall or timeout the operation
1166 * \ref Cy_SMIF_TransmitData().
1167 *
1168 * \param size
1169 * The size of data to read.
1170 *
1171 * \param cmdCompleteCb
1172 * The callback function to call after the transfer completion. NULL interpreted
1173 * as no callback.
1174 *
1175 * \param context
1176 * This is the pointer to the context structure \ref cy_stc_smif_context_t
1177 * allocated by the user. The structure is used during the SMIF
1178 * operation for internal configuration and data retention. The user must not
1179 * modify anything in this structure.
1180 *
1181 * \return A status of the transmission.
1182 * - \ref CY_SMIF_SUCCESS
1183 * - \ref CY_SMIF_CMD_FIFO_FULL
1184 * - \ref CY_SMIF_BAD_PARAM
1185 * - \ref CY_SMIF_EXCEED_TIMEOUT
1186 * - \ref CY_SMIF_CMD_NOT_FOUND
1187 *
1188 * \note Check \ref group_smif_usage_rules for any usage restriction
1189 *
1190 *******************************************************************************/
Cy_SMIF_MemCmdRead(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,uint8_t const * addr,uint8_t * readBuff,uint32_t size,cy_smif_event_cb_t cmdCompleteCb,cy_stc_smif_context_t * context)1191 cy_en_smif_status_t Cy_SMIF_MemCmdRead(SMIF_Type *base,
1192 cy_stc_smif_mem_config_t const *memDevice,
1193 uint8_t const *addr,
1194 uint8_t* readBuff,
1195 uint32_t size,
1196 cy_smif_event_cb_t cmdCompleteCb,
1197 cy_stc_smif_context_t *context)
1198 {
1199 cy_en_smif_status_t result = CY_SMIF_BAD_PARAM;
1200 cy_en_smif_slave_select_t slaveSelected;
1201 cy_stc_smif_mem_device_cfg_t *device = memDevice->deviceCfg;
1202 cy_stc_smif_mem_cmd_t *cmdRead = device->readCmd;
1203
1204 if(NULL == cmdRead)
1205 {
1206 result = CY_SMIF_CMD_NOT_FOUND;
1207 }
1208 else if(NULL == addr)
1209 {
1210 result = CY_SMIF_BAD_PARAM;
1211 }
1212 else
1213 {
1214 slaveSelected = (0U == memDevice->dualQuadSlots)? memDevice->slaveSelect :
1215 (cy_en_smif_slave_select_t)memDevice->dualQuadSlots;
1216
1217 result = Cy_SMIF_TransmitCommand( base, (uint8_t)cmdRead->command,
1218 cmdRead->cmdWidth, addr, device->numOfAddrBytes,
1219 cmdRead->addrWidth, slaveSelected, CY_SMIF_TX_NOT_LAST_BYTE,
1220 context);
1221
1222 if((CY_SMIF_SUCCESS == result) && (CY_SMIF_NO_COMMAND_OR_MODE != cmdRead->mode))
1223 {
1224 result = Cy_SMIF_TransmitCommand(base, (uint8_t)cmdRead->mode,
1225 cmdRead->modeWidth, NULL,
1226 CY_SMIF_CMD_WITHOUT_PARAM, CY_SMIF_WIDTH_NA,
1227 (cy_en_smif_slave_select_t)slaveSelected,
1228 CY_SMIF_TX_NOT_LAST_BYTE, context);
1229 }
1230
1231 if((CY_SMIF_SUCCESS == result) && (0U < cmdRead->dummyCycles))
1232 {
1233 result = Cy_SMIF_SendDummyCycles(base, cmdRead->dummyCycles);
1234 }
1235
1236 if(CY_SMIF_SUCCESS == result)
1237 {
1238 result = Cy_SMIF_ReceiveData(base, readBuff, size,
1239 cmdRead->dataWidth, cmdCompleteCb, context);
1240 }
1241 }
1242
1243 return(result);
1244 }
1245
1246
1247 /*******************************************************************************
1248 * Function Name: Cy_SMIF_MemLocateHybridRegion
1249 ****************************************************************************//**
1250 *
1251 * This function locates the region structure by the address which belongs to it.
1252 *
1253 * \note This function is valid for the memories with hybrid sectors.
1254 *
1255 * \param memDevice
1256 * The memory device configuration.
1257 *
1258 * \param regionInfo
1259 * Places a hybrid region configuration structure that contains the region
1260 * specific parameters. See \ref cy_stc_smif_hybrid_region_info_t for
1261 * reference.
1262 *
1263 * \param address
1264 * The address for which a region is searched.
1265 *
1266 * \return A status of the region location.
1267 * - \ref CY_SMIF_SUCCESS
1268 * - \ref CY_SMIF_NOT_HYBRID_MEM
1269 * - \ref CY_SMIF_BAD_PARAM
1270 *
1271 * \funcusage
1272 * \snippet smif/snippet/main.c snippet_Cy_SMIF_MemLocateHybridRegion
1273 *
1274 *******************************************************************************/
Cy_SMIF_MemLocateHybridRegion(cy_stc_smif_mem_config_t const * memDevice,cy_stc_smif_hybrid_region_info_t ** regionInfo,uint32_t address)1275 cy_en_smif_status_t Cy_SMIF_MemLocateHybridRegion(cy_stc_smif_mem_config_t const *memDevice,
1276 cy_stc_smif_hybrid_region_info_t** regionInfo,
1277 uint32_t address)
1278 {
1279 cy_en_smif_status_t result = CY_SMIF_BAD_PARAM;
1280 cy_stc_smif_hybrid_region_info_t* currInfo = NULL;
1281 CY_ASSERT_L1(NULL != memDevice);
1282 cy_stc_smif_mem_device_cfg_t *device = memDevice->deviceCfg;
1283
1284 /* Check if the address exceeds the memory size */
1285 if(address < device->memSize)
1286 {
1287 result = CY_SMIF_NOT_HYBRID_MEM;
1288 /* Check if the memory is hybrid */
1289 if(NULL != device->hybridRegionInfo)
1290 {
1291 uint32_t idx;
1292 uint32_t regionStartAddr;
1293 uint32_t regionEndAddr;
1294 for(idx = 0UL; idx < device->hybridRegionCount; idx++)
1295 {
1296 currInfo = device->hybridRegionInfo[idx];
1297 regionStartAddr = currInfo->regionAddress;
1298 regionEndAddr = regionStartAddr + (currInfo->sectorsCount * currInfo->eraseSize);
1299 if ((address >= regionStartAddr) && (address < regionEndAddr))
1300 {
1301 *regionInfo = currInfo;
1302 result = CY_SMIF_SUCCESS;
1303 break;
1304 }
1305 }
1306 }
1307 }
1308
1309 return result;
1310 }
1311
1312 /*******************************************************************************
1313 * Function Name: Cy_SMIF_SetReadyPollingDelay
1314 ****************************************************************************//**
1315 *
1316 * This function sets the polling delay in micro seconds to check memory device availability.
1317 * By default polling delay is set to 0.
1318 *
1319 * \param pollTimeoutUs
1320 * Specifies the polling timeout value in micro seconds.
1321 *
1322 * \param context
1323 * This is the pointer to the context structure \ref cy_stc_smif_context_t
1324 * allocated by the user. The structure is used during the SMIF
1325 * operation for internal configuration and data retention. The user must not
1326 * modify anything in this structure.
1327 *
1328 *
1329 *******************************************************************************/
Cy_SMIF_SetReadyPollingDelay(uint16_t pollTimeoutUs,cy_stc_smif_context_t * context)1330 void Cy_SMIF_SetReadyPollingDelay(uint16_t pollTimeoutUs,
1331 cy_stc_smif_context_t *context)
1332 {
1333 CY_ASSERT_L1(NULL != context);
1334
1335 context->memReadyPollDelay = pollTimeoutUs;
1336 }
1337
1338 /*******************************************************************************
1339 * Function Name: Cy_SMIF_MemIsReady
1340 ****************************************************************************//**
1341 *
1342 * Polls the memory device to check whether it is ready to accept new commands or
1343 * not until either it is ready or the retries have exceeded the limit.
1344 * This is a blocking function, it will block the execution flow until
1345 * the command transmission is completed.
1346 *
1347 * \param base
1348 * Holds the base address of the SMIF block registers.
1349 *
1350 * \param memConfig
1351 * The memory device configuration.
1352 *
1353 * \param timeoutUs
1354 * The timeout value in microseconds to apply while polling the memory.
1355 *
1356 * \param context
1357 * This is the pointer to the context structure \ref cy_stc_smif_context_t
1358 * allocated by the user. The structure is used during the SMIF
1359 * operation for internal configuration and data retention. The user must not
1360 * modify anything in this structure.
1361 *
1362 * \return The status of the operation.
1363 * \ref CY_SMIF_SUCCESS - Memory is ready to accept new commands.
1364 * \ref CY_SMIF_EXCEED_TIMEOUT - Memory is busy.
1365 *
1366 * \funcusage
1367 * \snippet smif/snippet/main.c snippet_Cy_SMIF_MemIsReady
1368 *
1369 *******************************************************************************/
Cy_SMIF_MemIsReady(SMIF_Type * base,cy_stc_smif_mem_config_t const * memConfig,uint32_t timeoutUs,cy_stc_smif_context_t const * context)1370 cy_en_smif_status_t Cy_SMIF_MemIsReady(SMIF_Type *base, cy_stc_smif_mem_config_t const *memConfig,
1371 uint32_t timeoutUs, cy_stc_smif_context_t const *context)
1372 {
1373 bool isBusy = Cy_SMIF_Memslot_IsBusy(base, (cy_stc_smif_mem_config_t* )memConfig, context);
1374
1375 CY_ASSERT_L1(NULL != context);
1376
1377 if (context->memReadyPollDelay > 0U)
1378 {
1379 if (isBusy)
1380 {
1381 uint16_t pollingDelay = (timeoutUs > context->memReadyPollDelay) ? context->memReadyPollDelay : (uint16_t)timeoutUs;
1382 do
1383 {
1384 /* Avoid using weak function if XIP is enabled */
1385 if (_FLD2VAL(SMIF_CTL_XIP_MODE, SMIF_CTL(base)) != 0U)
1386 {
1387 Cy_SysLib_DelayUs(pollingDelay);
1388 }
1389 else
1390 {
1391 Cy_SysLib_Rtos_DelayUs(pollingDelay);
1392 }
1393 isBusy = Cy_SMIF_Memslot_IsBusy(base, (cy_stc_smif_mem_config_t* )memConfig, context);
1394 timeoutUs = (timeoutUs > pollingDelay) ? (timeoutUs - pollingDelay) : 0UL;
1395 } while(isBusy && (timeoutUs > 0UL));
1396 }
1397 }
1398 else
1399 {
1400 if(isBusy)
1401 {
1402 uint32_t delayMs = 0UL;
1403 uint32_t timeoutSlice = 0UL;
1404 uint16_t delayUs = 0U;
1405
1406 /* Calculate the slice of time to split the timeoutUs delay into TIMEOUT_SLICE_DIV times */
1407 timeoutSlice = timeoutUs / TIMEOUT_SLICE_DIV;
1408
1409 /* Reduce the slice if needed to avoid too big idle period between checking the busy state */
1410 if (timeoutSlice > TIMEOUT_SLICE_MAX)
1411 {
1412 timeoutSlice = TIMEOUT_SLICE_MAX;
1413 }
1414 if(timeoutSlice == 0UL)
1415 {
1416 timeoutSlice = 1UL;
1417 }
1418
1419 do
1420 {
1421 delayMs = timeoutSlice / 1000UL;
1422 delayUs = (uint16_t) (timeoutSlice % 1000UL);
1423
1424 /* Avoid using weak function if XIP is enabled */
1425 if (_FLD2VAL(SMIF_CTL_XIP_MODE, SMIF_CTL(base)) != 0U)
1426 {
1427 Cy_SysLib_Delay(delayMs);
1428 Cy_SysLib_DelayUs(delayUs);
1429 }
1430 else
1431 {
1432 Cy_SysLib_Rtos_Delay(delayMs);
1433 Cy_SysLib_Rtos_DelayUs(delayUs);
1434 }
1435
1436 isBusy = Cy_SMIF_Memslot_IsBusy(base, (cy_stc_smif_mem_config_t* )memConfig, context);
1437
1438 timeoutUs = (timeoutUs > timeoutSlice) ? (timeoutUs - timeoutSlice) : 0UL;
1439
1440 } while(isBusy && (timeoutUs > 0UL));
1441 }
1442 }
1443
1444 return (isBusy ? CY_SMIF_EXCEED_TIMEOUT : CY_SMIF_SUCCESS);
1445 }
1446
1447
1448 /*******************************************************************************
1449 * Function Name: Cy_SMIF_MemIsQuadEnabled
1450 ****************************************************************************//**
1451 *
1452 * Checks whether the QE (Quad Enable) bit is set or not in the configuration
1453 * register of the memory.
1454 * This is a blocking function, it will block the execution flow until
1455 * the command transmission is completed.
1456 *
1457 * \param base
1458 * Holds the base address of the SMIF block registers.
1459 *
1460 * \param memConfig
1461 * The memory device configuration.
1462 *
1463 * \param isQuadEnabled
1464 * This parameter is updated to indicate whether quad mode is enabled (true) or
1465 * not (false). The value is valid only when the function returns
1466 * CY_SMIF_SUCCESS.
1467 *
1468 * \param context
1469 * This is the pointer to the context structure \ref cy_stc_smif_context_t
1470 * allocated by the user. The structure is used during the SMIF
1471 * operation for internal configuration and data retention. The user must not
1472 * modify anything in this structure.
1473 *
1474 * \return The status of the operation. See \ref cy_en_smif_status_t.
1475 *
1476 * \funcusage
1477 * \snippet smif/snippet/main.c snippet_Cy_SMIF_MemIsQuadEnabled
1478 *
1479 *******************************************************************************/
Cy_SMIF_MemIsQuadEnabled(SMIF_Type * base,cy_stc_smif_mem_config_t const * memConfig,bool * isQuadEnabled,cy_stc_smif_context_t const * context)1480 cy_en_smif_status_t Cy_SMIF_MemIsQuadEnabled(SMIF_Type *base, cy_stc_smif_mem_config_t const *memConfig,
1481 bool *isQuadEnabled, cy_stc_smif_context_t const *context)
1482 {
1483 cy_en_smif_status_t status;
1484 uint8_t readStatus = 0U;
1485 CY_ASSERT_L1(NULL != memConfig);
1486 uint32_t statusCmd = memConfig->deviceCfg->readStsRegQeCmd->command;
1487 uint8_t maskQE = (uint8_t) memConfig->deviceCfg->stsRegQuadEnableMask;
1488
1489 status = Cy_SMIF_MemCmdReadStatus(base, memConfig, &readStatus, (uint8_t)statusCmd, context);
1490
1491 *isQuadEnabled = false;
1492 if(CY_SMIF_SUCCESS == status)
1493 {
1494 /* Check whether quad mode is already enabled or not */
1495 *isQuadEnabled = (maskQE == (readStatus & maskQE));
1496 }
1497
1498 return status;
1499 }
1500
1501
1502 /*******************************************************************************
1503 * Function Name: Cy_SMIF_MemEnableQuadMode
1504 ****************************************************************************//**
1505 *
1506 * Sets the QE (QUAD Enable) bit in the external memory
1507 * configuration register to enable quad SPI mode.
1508 * This is a blocking function, it will block the execution flow until
1509 * the command transmission is completed.
1510 *
1511 * \param base
1512 * Holds the base address of the SMIF block registers.
1513 *
1514 * \param memConfig
1515 * The memory device configuration.
1516 *
1517 * \param timeoutUs
1518 * The timeout value in microseconds to apply while polling the memory.
1519 *
1520 * \param context
1521 * This is the pointer to the context structure \ref cy_stc_smif_context_t
1522 * allocated by the user. The structure is used during the SMIF
1523 * operation for internal configuration and data retention. The user must not
1524 * modify anything in this structure.
1525 *
1526 * \return The status of the operation. See \ref cy_en_smif_status_t.
1527 *
1528 * \funcusage
1529 * See \ref Cy_SMIF_MemIsQuadEnabled usage.
1530 *
1531 *******************************************************************************/
Cy_SMIF_MemEnableQuadMode(SMIF_Type * base,cy_stc_smif_mem_config_t const * memConfig,uint32_t timeoutUs,cy_stc_smif_context_t const * context)1532 cy_en_smif_status_t Cy_SMIF_MemEnableQuadMode(SMIF_Type *base, cy_stc_smif_mem_config_t const *memConfig,
1533 uint32_t timeoutUs, cy_stc_smif_context_t const *context)
1534 {
1535 cy_en_smif_status_t status;
1536
1537 CY_ASSERT_L1(NULL != memConfig);
1538
1539 /* Send Write Enable to the external memory */
1540 status = Cy_SMIF_MemCmdWriteEnable(base, (cy_stc_smif_mem_config_t* )memConfig, context);
1541
1542 if(CY_SMIF_SUCCESS == status)
1543 {
1544 status = Cy_SMIF_MemQuadEnable(base, (cy_stc_smif_mem_config_t* )memConfig, context);
1545
1546 if(CY_SMIF_SUCCESS == status)
1547 {
1548 /* Poll the memory for the completion of the operation */
1549 status = Cy_SMIF_MemIsReady(base, memConfig, timeoutUs, context);
1550 }
1551 }
1552
1553 return status;
1554 }
1555
1556 /*******************************************************************************
1557 * Function Name: Cy_SMIF_MemRead
1558 ****************************************************************************//**
1559 *
1560 * Reads data from the external memory and blocks until the read
1561 * transfer is complete or a timeout occurs.
1562 * This is a blocking function, it will block the execution flow until
1563 * the command transmission is completed.
1564 *
1565 * \param base
1566 * Holds the base address of the SMIF block registers.
1567 *
1568 * \param memConfig
1569 * The memory device configuration.
1570 *
1571 * \param address
1572 * The address to read data from.
1573 *
1574 * \param rxBuffer
1575 * The buffer for storing the read data. In case of Octal DDR, address must be an even address.
1576 *
1577 * \param length
1578 * The size of data to read.
1579 *
1580 * \param context
1581 * This is the pointer to the context structure \ref cy_stc_smif_context_t
1582 * allocated by the user. The structure is used during the SMIF
1583 * operation for internal configuration and data retention. The user must not
1584 * modify anything in this structure.
1585 *
1586 * \return The status of the operation. See \ref cy_en_smif_status_t.
1587 *
1588 * \funcusage
1589 * \snippet smif/snippet/main.c snippet_Cy_SMIF_MemRead
1590 *
1591 *******************************************************************************/
Cy_SMIF_MemRead(SMIF_Type * base,cy_stc_smif_mem_config_t const * memConfig,uint32_t address,uint8_t rxBuffer[],uint32_t length,cy_stc_smif_context_t const * context)1592 cy_en_smif_status_t Cy_SMIF_MemRead(SMIF_Type *base, cy_stc_smif_mem_config_t const *memConfig,
1593 uint32_t address, uint8_t rxBuffer[],
1594 uint32_t length, cy_stc_smif_context_t const *context)
1595 {
1596 cy_en_smif_status_t status = CY_SMIF_BAD_PARAM;
1597 uint32_t chunk = 0UL;
1598 uint8_t addrArray[CY_SMIF_FOUR_BYTES_ADDR] = {0U};
1599 cy_stc_smif_mem_cmd_t *cmdRead;
1600
1601 CY_ASSERT_L1(NULL != memConfig);
1602 CY_ASSERT_L1(NULL != rxBuffer);
1603
1604 cmdRead = memConfig->deviceCfg->readCmd;
1605
1606 if((address + length) <= memConfig->deviceCfg->memSize) /* Check if the address exceeds the memory size */
1607 {
1608 uint32_t interruptState = 0;
1609
1610 /* If XIP is enabled, disable interrupts to avoid task switching to XIP location */
1611 if (_FLD2VAL(SMIF_CTL_XIP_MODE, SMIF_CTL(base)) != 0U)
1612 {
1613 interruptState = Cy_SysLib_EnterCriticalSection();
1614 }
1615
1616 /* SMIF can read only up to 65536 bytes in one go. Split the larger read into multiple chunks */
1617 while (length > 0UL)
1618 {
1619 /* Get the number of bytes which can be read during one operation */
1620 chunk = (length > SMIF_MAX_RX_COUNT) ? (SMIF_MAX_RX_COUNT) : length;
1621 ValueToByteArray(address, &addrArray[0], 0UL,
1622 memConfig->deviceCfg->numOfAddrBytes);
1623
1624 #if (CY_IP_MXSMIF_VERSION>=2)
1625 status = Cy_SMIF_TransmitCommand_Ext(base,
1626 (uint16_t)(cmdRead->command | cmdRead->commandH << 8),
1627 ((bool)cmdRead->commandH),
1628 cmdRead->cmdWidth,
1629 cmdRead->cmdRate,
1630 (const uint8_t *)addrArray,
1631 memConfig->deviceCfg->numOfAddrBytes,
1632 cmdRead->addrWidth,
1633 cmdRead->addrRate,
1634 memConfig->slaveSelect,
1635 CY_SMIF_TX_NOT_LAST_BYTE,
1636 context);
1637
1638 if((CY_SMIF_SUCCESS == status) && (CY_SMIF_NO_COMMAND_OR_MODE != cmdRead->mode))
1639 {
1640 status = Cy_SMIF_TransmitCommand_Ext(base,
1641 (uint16_t)cmdRead->mode,
1642 false,
1643 cmdRead->modeWidth,
1644 cmdRead->modeRate,
1645 NULL,
1646 CY_SMIF_CMD_WITHOUT_PARAM,
1647 CY_SMIF_WIDTH_NA,
1648 cmdRead->modeRate,
1649 memConfig->slaveSelect,
1650 CY_SMIF_TX_NOT_LAST_BYTE,
1651 context);
1652 }
1653
1654 if((CY_SMIF_SUCCESS == status) && (0U < cmdRead->dummyCycles))
1655 {
1656 #if ((CY_IP_MXSMIF_VERSION==2) || (CY_IP_MXSMIF_VERSION==3))
1657 uint32_t ifRxSel = _FLD2VAL(SMIF_CTL_CLOCK_IF_RX_SEL, SMIF_CTL(base));
1658
1659 if(ifRxSel == (uint32_t)CY_SMIF_SEL_SPHB_RWDS_CLK || ifRxSel == (uint32_t)CY_SMIF_SEL_INVERTED_SPHB_RWDS_CLK)
1660 {
1661 status = Cy_SMIF_SendDummyCycles_With_RWDS(base, true, (cmdRead->dummyCyclesPresence == CY_SMIF_PRESENT_2BYTE), cmdRead->dummyCycles);
1662 }
1663 else
1664 #endif
1665 #if (CY_IP_MXSMIF_VERSION >= 4)
1666 if (_FLD2VAL(SMIF_CORE_CTL2_RX_CAPTURE_MODE, (SMIF_CTL2(base))) == (uint32_t)CY_SMIF_SEL_XSPI_HYPERBUS_WITH_DQS)
1667 {
1668 status = Cy_SMIF_SendDummyCycles_With_RWDS(base, true, (cmdRead->dummyCyclesPresence == CY_SMIF_PRESENT_2BYTE), cmdRead->dummyCycles);
1669 }
1670 else
1671 #endif
1672 {
1673 status = Cy_SMIF_SendDummyCycles_Ext(base, cmdRead->dataWidth, cmdRead->dataRate, cmdRead->dummyCycles);
1674 }
1675 }
1676
1677 if(CY_SMIF_SUCCESS == status)
1678 {
1679 status = Cy_SMIF_ReceiveDataBlocking_Ext(base,
1680 rxBuffer,
1681 chunk,
1682 cmdRead->dataWidth,
1683 cmdRead->dataRate,
1684 context);
1685 }
1686 #else
1687 status = Cy_SMIF_TransmitCommand(base,
1688 (uint8_t)cmdRead->command,
1689 cmdRead->cmdWidth,
1690 (const uint8_t *)addrArray,
1691 memConfig->deviceCfg->numOfAddrBytes,
1692 cmdRead->addrWidth,
1693 memConfig->slaveSelect,
1694 CY_SMIF_TX_NOT_LAST_BYTE,
1695 context);
1696
1697 if((CY_SMIF_SUCCESS == status) && (CY_SMIF_NO_COMMAND_OR_MODE != cmdRead->mode))
1698 {
1699 status = Cy_SMIF_TransmitCommand(base,
1700 (uint8_t)cmdRead->mode,
1701 cmdRead->modeWidth,
1702 NULL,
1703 CY_SMIF_CMD_WITHOUT_PARAM,
1704 CY_SMIF_WIDTH_NA,
1705 memConfig->slaveSelect,
1706 CY_SMIF_TX_NOT_LAST_BYTE,
1707 context);
1708 }
1709
1710 if((CY_SMIF_SUCCESS == status) && (0U < cmdRead->dummyCycles))
1711 {
1712 status = Cy_SMIF_SendDummyCycles(base, cmdRead->dummyCycles);
1713 }
1714
1715 if(CY_SMIF_SUCCESS == status)
1716 {
1717 status = Cy_SMIF_ReceiveDataBlocking(base,
1718 rxBuffer,
1719 chunk,
1720 cmdRead->dataWidth,
1721 context);
1722 }
1723 #endif /* CY_IP_MXSMIF_VERSION */
1724
1725 if(CY_SMIF_SUCCESS != status)
1726 {
1727 break;
1728 }
1729
1730 /* Recalculate the next rxBuffer offset */
1731 length -= chunk;
1732 address += chunk;
1733 rxBuffer = (uint8_t *)rxBuffer + chunk;
1734 }
1735 /* Restore interrupts */
1736 if (_FLD2VAL(SMIF_CTL_XIP_MODE, SMIF_CTL(base)) != 0U)
1737 {
1738 Cy_SysLib_ExitCriticalSection(interruptState);
1739 }
1740 }
1741
1742 return status;
1743 }
1744
1745
1746 /*******************************************************************************
1747 * Function Name: Cy_SMIF_MemWrite
1748 ****************************************************************************//**
1749 *
1750 * This function writes data to the external memory.
1751 * This is a blocking function, it will block the execution flow until
1752 * the command transmission is completed.
1753 *
1754 * \param base
1755 * Holds the base address of the SMIF block registers.
1756 *
1757 * \param memConfig
1758 * The memory device configuration.
1759 *
1760 * \param address
1761 * The address to write data at. In case of Octal DDR, address must be an even address.
1762 *
1763 * \param txBuffer
1764 * The buffer holding the data to write in the external memory.
1765 *
1766 * \param length
1767 * The size of data to write.
1768 *
1769 * \param context
1770 * This is the pointer to the context structure \ref cy_stc_smif_context_t
1771 * allocated by the user. The structure is used during the SMIF
1772 * operation for internal configuration and data retention. The user must not
1773 * modify anything in this structure.
1774 *
1775 * \return The status of the operation. See \ref cy_en_smif_status_t.
1776 *
1777 * \funcusage
1778 * \snippet smif/snippet/main.c snippet_Cy_SMIF_MemWrite
1779 *
1780 *******************************************************************************/
Cy_SMIF_MemWrite(SMIF_Type * base,cy_stc_smif_mem_config_t const * memConfig,uint32_t address,uint8_t const txBuffer[],uint32_t length,cy_stc_smif_context_t const * context)1781 cy_en_smif_status_t Cy_SMIF_MemWrite(SMIF_Type *base, cy_stc_smif_mem_config_t const *memConfig,
1782 uint32_t address, uint8_t const txBuffer[],
1783 uint32_t length, cy_stc_smif_context_t const *context)
1784 {
1785 cy_en_smif_status_t status = CY_SMIF_BAD_PARAM;
1786 uint32_t offset = 0UL;
1787 uint32_t chunk = 0UL;
1788 uint32_t pageSize;
1789 uint8_t addrArray[CY_SMIF_FOUR_BYTES_ADDR] = {0U};
1790 cy_stc_smif_mem_cmd_t *cmdProgram;
1791
1792 CY_ASSERT_L1(NULL != memConfig);
1793 CY_ASSERT_L1(NULL != txBuffer);
1794
1795 pageSize = memConfig->deviceCfg->programSize; /* Get the page size */
1796 cmdProgram = memConfig->deviceCfg->programCmd; /* Get the program command */
1797
1798 if((address + length) <= memConfig->deviceCfg->memSize) /* Check if the address exceeds the memory size */
1799 {
1800 uint32_t interruptState = 0;
1801
1802 /* If XIP is enabled, disable interrupts to avoid task switching to XIP location */
1803 if (_FLD2VAL(SMIF_CTL_XIP_MODE, SMIF_CTL(base)) != 0U)
1804 {
1805 interruptState = Cy_SysLib_EnterCriticalSection();
1806 }
1807 /* SMIF can read only up to 65536 bytes in one go. Split the larger read into multiple chunks */
1808 while (length > 0UL)
1809 {
1810 /* Get the number of bytes which can be written during one operation */
1811 offset = address % pageSize;
1812 chunk = ((offset + length) < pageSize) ? length : (pageSize - offset);
1813
1814 /* The Write Enable bit may be cleared by the memory after every successful
1815 * operation of write or erase operations. Therefore, must be set for
1816 * every loop.
1817 */
1818 status = Cy_SMIF_MemCmdWriteEnable(base, memConfig, context);
1819
1820 if(CY_SMIF_SUCCESS == status)
1821 {
1822 ValueToByteArray(address, &addrArray[0], 0UL,
1823 memConfig->deviceCfg->numOfAddrBytes);
1824 #if (CY_IP_MXSMIF_VERSION>=2)
1825 status = Cy_SMIF_TransmitCommand_Ext(base,
1826 (uint16_t)(cmdProgram->command | cmdProgram->commandH << 8),
1827 (bool)cmdProgram->commandH,
1828 cmdProgram->cmdWidth, cmdProgram->cmdRate,
1829 (const uint8_t *)addrArray, memConfig->deviceCfg->numOfAddrBytes,
1830 cmdProgram->addrWidth, cmdProgram->addrRate,
1831 memConfig->slaveSelect, CY_SMIF_TX_NOT_LAST_BYTE, context);
1832
1833 if((CY_SMIF_SUCCESS == status) && (CY_SMIF_NO_COMMAND_OR_MODE != cmdProgram->mode))
1834 {
1835 status = Cy_SMIF_TransmitCommand_Ext(base,
1836 (uint16_t)cmdProgram->mode, false,
1837 cmdProgram->modeWidth, cmdProgram->modeRate,
1838 NULL, CY_SMIF_CMD_WITHOUT_PARAM, CY_SMIF_WIDTH_NA,
1839 cmdProgram->modeRate, memConfig->slaveSelect,
1840 CY_SMIF_TX_NOT_LAST_BYTE, context);
1841 }
1842
1843 if((CY_SMIF_SUCCESS == status) && (cmdProgram->dummyCycles > 0U))
1844 {
1845 #if ((CY_IP_MXSMIF_VERSION==2) || (CY_IP_MXSMIF_VERSION==3))
1846 uint32_t ifRxSel = _FLD2VAL(SMIF_CTL_CLOCK_IF_RX_SEL, SMIF_CTL(base));
1847
1848 if(ifRxSel == (uint32_t)CY_SMIF_SEL_SPHB_RWDS_CLK || ifRxSel == (uint32_t)CY_SMIF_SEL_INVERTED_SPHB_RWDS_CLK)
1849 {
1850 status = Cy_SMIF_SendDummyCycles_With_RWDS(base, false, (cmdProgram->dummyCyclesPresence == CY_SMIF_PRESENT_2BYTE), cmdProgram->dummyCycles);
1851 }
1852 else
1853 #endif
1854 #if (CY_IP_MXSMIF_VERSION >= 4)
1855 if (_FLD2VAL(SMIF_CORE_CTL2_RX_CAPTURE_MODE, (SMIF_CTL2(base))) == (uint32_t)CY_SMIF_SEL_XSPI_HYPERBUS_WITH_DQS)
1856 {
1857 status = Cy_SMIF_SendDummyCycles_With_RWDS(base, false, (cmdProgram->dummyCyclesPresence == CY_SMIF_PRESENT_2BYTE), cmdProgram->dummyCycles);
1858 }
1859 else
1860 #endif
1861 {
1862 status = Cy_SMIF_SendDummyCycles_Ext(base, cmdProgram->dataWidth, cmdProgram->dataRate, cmdProgram->dummyCycles);
1863 }
1864 }
1865
1866 if(CY_SMIF_SUCCESS == status)
1867 {
1868 status = Cy_SMIF_TransmitDataBlocking_Ext(base,
1869 (uint8_t *)txBuffer, chunk,
1870 cmdProgram->dataWidth, cmdProgram->dataRate, context);
1871 }
1872 #else
1873 status = Cy_SMIF_TransmitCommand(base,
1874 (uint8_t)cmdProgram->command,
1875 cmdProgram->cmdWidth,
1876 (const uint8_t *)addrArray,
1877 memConfig->deviceCfg->numOfAddrBytes,
1878 cmdProgram->addrWidth,
1879 memConfig->slaveSelect,
1880 CY_SMIF_TX_NOT_LAST_BYTE,
1881 context);
1882
1883 if((CY_SMIF_SUCCESS == status) && (CY_SMIF_NO_COMMAND_OR_MODE != cmdProgram->mode))
1884 {
1885 status = Cy_SMIF_TransmitCommand(base,
1886 (uint8_t)cmdProgram->mode,
1887 cmdProgram->modeWidth,
1888 NULL,
1889 CY_SMIF_CMD_WITHOUT_PARAM,
1890 CY_SMIF_WIDTH_NA,
1891 memConfig->slaveSelect,
1892 CY_SMIF_TX_NOT_LAST_BYTE,
1893 context);
1894 }
1895
1896 if((CY_SMIF_SUCCESS == status) && (cmdProgram->dummyCycles > 0U))
1897 {
1898 status = Cy_SMIF_SendDummyCycles(base, cmdProgram->dummyCycles);
1899 }
1900
1901 if(CY_SMIF_SUCCESS == status)
1902 {
1903 status = Cy_SMIF_TransmitDataBlocking(base,
1904 (uint8_t *)txBuffer,
1905 chunk,
1906 cmdProgram->dataWidth,
1907 context);
1908 }
1909 #endif /* CY_IP_MXSMIF_VERSION */
1910 if ((CY_SMIF_SUCCESS == status) && (NULL != memConfig->deviceCfg->readStsRegWipCmd))
1911 {
1912 /* Check if the memory has completed the write operation. ProgramTime is in microseconds */
1913 status = Cy_SMIF_MemIsReady(base, memConfig, memConfig->deviceCfg->programTime, context);
1914 }
1915 }
1916
1917 if(CY_SMIF_SUCCESS != status)
1918 {
1919 break;
1920 }
1921
1922 /* Recalculate the next rxBuffer offset */
1923 txBuffer = (uint8_t *)txBuffer + chunk;
1924 address += chunk;
1925 length -= chunk;
1926 }
1927 /* Restore interrupts */
1928 if (_FLD2VAL(SMIF_CTL_XIP_MODE, SMIF_CTL(base)) != 0U)
1929 {
1930 Cy_SysLib_ExitCriticalSection(interruptState);
1931 }
1932 }
1933
1934 return status;
1935 }
1936
1937
1938 /*******************************************************************************
1939 * Function Name: Cy_SMIF_MemEraseSector
1940 ****************************************************************************//**
1941 *
1942 * Erases a block/sector of the external memory.
1943 * This is a blocking function, it will block the execution flow until
1944 * the command transmission is completed.
1945 *
1946 * \param base
1947 * Holds the base address of the SMIF block registers.
1948 *
1949 * \param memConfig
1950 * The memory device configuration.
1951 *
1952 * \param address
1953 * The address of the block to be erased. The address will be aligned to
1954 * the start address of the sector in which address is located.
1955 *
1956 * \param length
1957 * The length of data to erase. The length will be aligned to the sector
1958 * boundary where end address is located. If length exceeds memory size
1959 * API returns \ref CY_SMIF_BAD_PARAM without performing erase operation.
1960 *
1961 * \param context
1962 * This is the pointer to the context structure \ref cy_stc_smif_context_t
1963 * allocated by the user. The structure is used during the SMIF
1964 * operation for internal configuration and data retention. The user must not
1965 * modify anything in this structure.
1966 *
1967 * \return The status of the operation. See \ref cy_en_smif_status_t.
1968 *
1969 * \note Memories like hybrid have sectors of different sizes. \n
1970 * Check the address and length parameters before calling this function.
1971 *
1972 * \funcusage
1973 * \snippet smif/snippet/main.c snippet_Cy_SMIF_MemEraseSector
1974 *
1975 *******************************************************************************/
Cy_SMIF_MemEraseSector(SMIF_Type * base,cy_stc_smif_mem_config_t const * memConfig,uint32_t address,uint32_t length,cy_stc_smif_context_t const * context)1976 cy_en_smif_status_t Cy_SMIF_MemEraseSector(SMIF_Type *base, cy_stc_smif_mem_config_t const *memConfig,
1977 uint32_t address, uint32_t length,
1978 cy_stc_smif_context_t const *context)
1979 {
1980 cy_en_smif_status_t status = CY_SMIF_SUCCESS;
1981 uint32_t endAddress = address + length - 1UL;
1982 uint32_t hybridRegionEnd = 0UL;
1983 uint32_t hybridRegionStart = 0UL;
1984 uint8_t addrArray[CY_SMIF_FOUR_BYTES_ADDR] = {0U};
1985 cy_stc_smif_hybrid_region_info_t* hybrInfo = NULL;
1986 CY_ASSERT_L1(NULL != memConfig);
1987 cy_stc_smif_mem_device_cfg_t *device = memConfig->deviceCfg;
1988 uint32_t eraseSectorSize = device->eraseSize;
1989 uint32_t maxEraseTime = device->eraseTime;
1990
1991 /* Check if the address exceeds the memory size */
1992 if (endAddress < device->memSize)
1993 {
1994 /* Align start address and end address to corresponding sector boundary */
1995 cy_stc_smif_hybrid_region_info_t* regionInfo = NULL;
1996
1997 /* Check if it is a hybrid memory */
1998 status = Cy_SMIF_MemLocateHybridRegion(memConfig, ®ionInfo, address);
1999
2000 if ((CY_SMIF_SUCCESS == status) && (regionInfo != NULL)) /* Hybrid */
2001 {
2002 uint32_t offsetInRegion = address - regionInfo->regionAddress;
2003 uint32_t sectorOffsetInRegion = offsetInRegion / regionInfo->eraseSize;
2004
2005 /* Align start address */
2006 address = regionInfo->regionAddress + (sectorOffsetInRegion * regionInfo->eraseSize);
2007
2008 /* Last hybrid region in desired block */
2009 status = Cy_SMIF_MemLocateHybridRegion(memConfig, ®ionInfo, endAddress);
2010 if (CY_SMIF_SUCCESS == status)
2011 {
2012 offsetInRegion = endAddress - regionInfo->regionAddress + 1UL;
2013 sectorOffsetInRegion = offsetInRegion / regionInfo->eraseSize;
2014 if (0UL != offsetInRegion % regionInfo->eraseSize)
2015 {
2016 sectorOffsetInRegion++;
2017 }
2018 /* Align end address */
2019 endAddress = regionInfo->regionAddress + (sectorOffsetInRegion * regionInfo->eraseSize) - 1UL;
2020
2021 /* Update length according the aligned start address and end address */
2022 length = endAddress - address + 1UL;
2023 }
2024 }
2025 else /* Not hybrid (unified) sectors layout */
2026 {
2027 /* If start address is somewhere at the middle of erase page, align it to the page start */
2028 if (0UL != (address % eraseSectorSize))
2029 {
2030 address = eraseSectorSize * (address / eraseSectorSize);
2031 }
2032
2033 /* If end address is somewhere at the middle of erase page, align it to the page end */
2034 if (0UL != ((endAddress + 1UL) % eraseSectorSize))
2035 {
2036 endAddress = (((endAddress + eraseSectorSize - 1UL) / eraseSectorSize) * eraseSectorSize) - 1UL;
2037 }
2038 /* Update length according the aligned start address and end address */
2039 length = endAddress - address + 1UL;
2040
2041 status = CY_SMIF_SUCCESS;
2042 }
2043
2044 /* Check if the address exceeds the memory size */
2045 if (endAddress < device->memSize)
2046 {
2047 uint32_t interruptState = 0UL;
2048
2049 /* If XIP is enabled, disable interrupts to avoid task switching to a code running in
2050 * XIP when erase operation is ongoing */
2051 if (_FLD2VAL(SMIF_CTL_XIP_MODE, SMIF_CTL(base)) != 0U)
2052 {
2053 interruptState = Cy_SysLib_EnterCriticalSection();
2054 }
2055
2056 while(length > 0UL)
2057 {
2058 /* In case of hybrid memory - update erase size and time for current region */
2059 status = Cy_SMIF_MemLocateHybridRegion(memConfig, &hybrInfo, address);
2060 if (CY_SMIF_SUCCESS == status)
2061 {
2062 maxEraseTime = hybrInfo->eraseTime;
2063 eraseSectorSize = hybrInfo->eraseSize;
2064 hybridRegionStart = hybrInfo->regionAddress;
2065 hybridRegionEnd = (hybrInfo->sectorsCount * eraseSectorSize) + hybridRegionStart - 1UL;
2066 if(endAddress < hybridRegionEnd)
2067 {
2068 hybridRegionEnd = endAddress;
2069 }
2070 }
2071 else
2072 {
2073 hybridRegionEnd = endAddress;
2074 }
2075
2076 while (address < hybridRegionEnd)
2077 {
2078 /* The Write Enable bit may be cleared by the memory after every successful
2079 * operation of write/erase operations. Therefore, it must be set for
2080 * every loop.
2081 */
2082 status = Cy_SMIF_MemCmdWriteEnable(base, memConfig, context);
2083 if(CY_SMIF_SUCCESS == status)
2084 {
2085 ValueToByteArray(address, &addrArray[0], 0UL, device->numOfAddrBytes);
2086
2087 /* Send the command to erase one sector */
2088 status = Cy_SMIF_MemCmdSectorErase(base, (cy_stc_smif_mem_config_t* )memConfig,
2089 (const uint8_t *)addrArray, context);
2090 if(CY_SMIF_SUCCESS == status)
2091 {
2092 /* Wait until the erase operation is completed or a timeout occurs.
2093 * Note: eraseTime is in milliseconds */
2094 status = Cy_SMIF_MemIsReady(base, memConfig, (maxEraseTime * ONE_MILLI_IN_MICRO), context);
2095
2096 /* Recalculate the next sector address offset */
2097 if(length > eraseSectorSize)
2098 {
2099 address += eraseSectorSize;
2100 length -= eraseSectorSize;
2101 }
2102 else
2103 {
2104 length = 0;
2105 break;
2106 }
2107 }
2108 }
2109
2110 if(CY_SMIF_SUCCESS != status)
2111 {
2112 break;
2113 }
2114 }
2115 }
2116
2117 /* Restore interrupts */
2118 if (_FLD2VAL(SMIF_CTL_XIP_MODE, SMIF_CTL(base)) != 0U)
2119 {
2120 Cy_SysLib_ExitCriticalSection(interruptState);
2121 }
2122 }
2123 else
2124 {
2125 /* Aligned end address exceeds memory size */
2126 status = CY_SMIF_BAD_PARAM;
2127 }
2128 }
2129 else
2130 {
2131 /* end address exceeds memory size */
2132 status = CY_SMIF_BAD_PARAM;
2133 }
2134
2135 return status;
2136 }
2137
2138
2139 /*******************************************************************************
2140 * Function Name: Cy_SMIF_MemEraseChip
2141 ****************************************************************************//**
2142 *
2143 * Erases the entire chip of the external memory.
2144 * This is a blocking function, it will block the execution flow until
2145 * the command transmission is completed.
2146 *
2147 * \param base
2148 * Holds the base address of the SMIF block registers.
2149 *
2150 * \param memConfig
2151 * The memory device configuration.
2152 *
2153 * \param context
2154 * This is the pointer to the context structure \ref cy_stc_smif_context_t
2155 * allocated by the user. The structure is used during the SMIF
2156 * operation for internal configuration and data retention. The user must not
2157 * modify anything in this structure.
2158 *
2159 * \return The status of the operation. See \ref cy_en_smif_status_t.
2160 *
2161 * \funcusage
2162 * \snippet smif/snippet/main.c snippet_Cy_SMIF_MemEraseChip
2163 *
2164 *******************************************************************************/
Cy_SMIF_MemEraseChip(SMIF_Type * base,cy_stc_smif_mem_config_t const * memConfig,cy_stc_smif_context_t const * context)2165 cy_en_smif_status_t Cy_SMIF_MemEraseChip(SMIF_Type *base, cy_stc_smif_mem_config_t const *memConfig,
2166 cy_stc_smif_context_t const *context)
2167 {
2168 cy_en_smif_status_t status;
2169
2170 CY_ASSERT_L1(NULL != memConfig);
2171
2172 /* The Write Enable bit may be cleared by the memory after every successful
2173 * operation of write/erase operations. Therefore, it must be set for
2174 * every loop
2175 */
2176 status = Cy_SMIF_MemCmdWriteEnable(base, memConfig, context);
2177
2178 if(CY_SMIF_SUCCESS == status)
2179 {
2180 /* Send the command to erase the entire chip */
2181 status = Cy_SMIF_MemCmdChipErase(base, memConfig, context);
2182
2183 if(CY_SMIF_SUCCESS == status)
2184 {
2185 /* Wait until the erase operation is completed or a timeout occurs. chipEraseTime is in milliseconds */
2186 status = Cy_SMIF_MemIsReady(base, memConfig,
2187 (memConfig->deviceCfg->chipEraseTime * ONE_MILLI_IN_MICRO), context);
2188 }
2189 }
2190
2191 return status;
2192 }
2193
2194 /*******************************************************************************
2195 * Function Name: Cy_SMIF_MemCmdPowerDown
2196 ****************************************************************************//**
2197 *
2198 * This function sends a Power-down command to the selected memory device in
2199 * Single SPI mode. Please note that, once \ref Cy_SMIF_MemCmdPowerDown is issued, external
2200 * memory will not respond to any other command except \ref Cy_SMIF_MemCmdReleasePowerDown.
2201 *
2202 * \note This function uses the low-level Cy_SMIF_TransmitCommand() API.
2203 * Cy_SMIF_TransmitCommand() API works in a blocking mode. In the dual quad mode
2204 * this API should be called for each memory.
2205 *
2206 * \param base
2207 * Holds the base address of the SMIF block registers.
2208 *
2209 * \param memDevice
2210 * The device to which the command is sent.
2211 *
2212 * \param context
2213 * This is the pointer to the context structure \ref cy_stc_smif_context_t
2214 * allocated by the user. The structure is used during the SMIF
2215 * operation for internal configuration and data retention. The user must not
2216 * modify anything in this structure.
2217 *
2218 * \return A status of the command transmission.
2219 * - \ref CY_SMIF_SUCCESS
2220 * - \ref CY_SMIF_EXCEED_TIMEOUT
2221 *
2222 * \snippet smif/snippet/main.c SMIF_API: PowerDown
2223 *******************************************************************************/
Cy_SMIF_MemCmdPowerDown(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,cy_stc_smif_context_t const * context)2224 cy_en_smif_status_t Cy_SMIF_MemCmdPowerDown(SMIF_Type *base,
2225 cy_stc_smif_mem_config_t const *memDevice,
2226 cy_stc_smif_context_t const *context)
2227 {
2228
2229 cy_en_smif_status_t result;
2230
2231 /* The memory Power-down command */
2232 result = Cy_SMIF_TransmitCommand( base, CY_SMIF_POWER_DOWN_CMD,
2233 CY_SMIF_WIDTH_SINGLE,
2234 NULL,
2235 CY_SMIF_CMD_WITHOUT_PARAM,
2236 CY_SMIF_WIDTH_NA,
2237 memDevice->slaveSelect,
2238 CY_SMIF_TX_LAST_BYTE,
2239 context);
2240
2241 return result;
2242 }
2243 /*******************************************************************************
2244 * Function Name: Cy_SMIF_MemCmdReleasePowerDown
2245 ****************************************************************************//**
2246 *
2247 * This function sends a Release Power-down command to the selected memory device
2248 * in Single SPI mode.
2249 *
2250 * \note This function uses the low-level Cy_SMIF_TransmitCommand() API.
2251 * Cy_SMIF_TransmitCommand() API works in a blocking mode. In the dual quad mode
2252 * this API should be called for each memory.
2253 *
2254 * \param base
2255 * Holds the base address of the SMIF block registers.
2256 *
2257 * \param memDevice
2258 * The device to which the command is sent.
2259 *
2260 * \param context
2261 * This is the pointer to the context structure \ref cy_stc_smif_context_t
2262 * allocated by the user. The structure is used during the SMIF
2263 * operation for internal configuration and data retention. The user must not
2264 * modify anything in this structure.
2265 *
2266 * \return A status of the command transmission.
2267 * - \ref CY_SMIF_SUCCESS
2268 * - \ref CY_SMIF_EXCEED_TIMEOUT
2269 *
2270 * \snippet smif/snippet/main.c SMIF_API: PowerDown
2271 *******************************************************************************/
Cy_SMIF_MemCmdReleasePowerDown(SMIF_Type * base,cy_stc_smif_mem_config_t const * memDevice,cy_stc_smif_context_t const * context)2272 cy_en_smif_status_t Cy_SMIF_MemCmdReleasePowerDown(SMIF_Type *base,
2273 cy_stc_smif_mem_config_t const *memDevice,
2274 cy_stc_smif_context_t const *context)
2275 {
2276
2277 cy_en_smif_status_t result;
2278
2279 /* The memory Release Power-down command */
2280 result = Cy_SMIF_TransmitCommand( base, CY_SMIF_RELEASE_POWER_DOWN_CMD,
2281 CY_SMIF_WIDTH_SINGLE,
2282 NULL,
2283 CY_SMIF_CMD_WITHOUT_PARAM,
2284 CY_SMIF_WIDTH_NA,
2285 memDevice->slaveSelect,
2286 CY_SMIF_TX_LAST_BYTE,
2287 context);
2288
2289 return result;
2290 }
2291
2292 #if defined(__cplusplus)
2293 }
2294 #endif
2295
2296 #endif /* CY_IP_MXSMIF */
2297
2298 /* [] END OF FILE */
2299