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