1 /***************************************************************************//**
2 * \file cy_scb_spi.c
3 * \version 3.10
4 *
5 * Provides SPI API implementation of the SCB driver.
6 *
7 ********************************************************************************
8 * \copyright
9 * Copyright 2016-2021 Cypress Semiconductor Corporation
10 * SPDX-License-Identifier: Apache-2.0
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *******************************************************************************/
24
25 #include "cy_device.h"
26
27 #if (defined (CY_IP_MXSCB) || defined (CY_IP_MXS22SCB))
28
29 #include "cy_scb_spi.h"
30
31 #if defined(__cplusplus)
32 extern "C" {
33 #endif
34
35 /* Static functions */
36 static void HandleTransmit(CySCB_Type *base, cy_stc_scb_spi_context_t *context);
37 static void HandleReceive (CySCB_Type *base, cy_stc_scb_spi_context_t *context);
38 static void DiscardArrayNoCheck(CySCB_Type const *base, uint32_t size);
39
40 /*******************************************************************************
41 * Function Name: Cy_SCB_SPI_Init
42 ****************************************************************************//**
43 *
44 * Initializes the SCB for SPI operation.
45 *
46 * \param base
47 * The pointer to the SPI SCB instance.
48 *
49 * \param config
50 * The pointer to the configuration structure \ref cy_stc_scb_spi_config_t.
51 *
52 * \param context
53 * The pointer to the context structure \ref cy_stc_scb_spi_context_t allocated
54 * by the user. The structure is used during the SPI operation for internal
55 * configuration and data retention. The user must not modify anything
56 * in this structure.
57 * If only SPI \ref group_scb_spi_ll will be used pass NULL as pointer to
58 * context.
59 *
60 * \return
61 * \ref cy_en_scb_spi_status_t
62 *
63 * \note
64 * If SCB is already enabled, ensure that the SCB block is disabled
65 * \ref Cy_SCB_SPI_Disable before calling this function.
66 *
67 *******************************************************************************/
Cy_SCB_SPI_Init(CySCB_Type * base,cy_stc_scb_spi_config_t const * config,cy_stc_scb_spi_context_t * context)68 cy_en_scb_spi_status_t Cy_SCB_SPI_Init(CySCB_Type *base, cy_stc_scb_spi_config_t const *config, cy_stc_scb_spi_context_t *context)
69 {
70 /* Input parameters verification */
71 if ((NULL == base) || (NULL == config))
72 {
73 return CY_SCB_SPI_BAD_PARAM;
74 }
75 #if((defined CY_IP_MXSCB_VERSION && (CY_IP_MXSCB_VERSION>=2)) || defined (CY_IP_MXS22SCB))
76 uint32_t memWidth_type = CY_SCB_MEM_WIDTH_BYTE;
77 #endif /* CY_IP_MXSCB_VERSION */
78 CY_ASSERT_L3(CY_SCB_SPI_IS_MODE_VALID (config->spiMode));
79 CY_ASSERT_L3(CY_SCB_SPI_IS_SUB_MODE_VALID (config->subMode));
80 CY_ASSERT_L3(CY_SCB_SPI_IS_SCLK_MODE_VALID(config->sclkMode));
81
82 CY_ASSERT_L2(CY_SCB_SPI_IS_OVERSAMPLE_VALID (config->oversample, config->spiMode));
83 CY_ASSERT_L2(CY_SCB_SPI_IS_SS_POLARITY_VALID(config->ssPolarity));
84 CY_ASSERT_L2(CY_SCB_SPI_IS_DATA_WIDTH_VALID (config->rxDataWidth));
85 CY_ASSERT_L2(CY_SCB_SPI_IS_DATA_WIDTH_VALID (config->txDataWidth));
86 CY_ASSERT_L2(CY_SCB_SPI_IS_BOTH_DATA_WIDTH_VALID(config->subMode, config->rxDataWidth, config->txDataWidth));
87
88 CY_ASSERT_L2(CY_SCB_IS_INTR_VALID(config->rxFifoIntEnableMask, CY_SCB_SPI_RX_INTR_MASK));
89 CY_ASSERT_L2(CY_SCB_IS_INTR_VALID(config->txFifoIntEnableMask, CY_SCB_SPI_TX_INTR_MASK));
90 CY_ASSERT_L2(CY_SCB_IS_INTR_VALID(config->masterSlaveIntEnableMask, CY_SCB_SPI_MASTER_SLAVE_INTR_MASK));
91
92 uint32_t locSclkMode = CY_SCB_SPI_GetSclkMode(config->subMode, config->sclkMode);
93 #if((defined (CY_IP_MXSCB_VERSION) && (CY_IP_MXSCB_VERSION>=2)) || defined (CY_IP_MXS22SCB))
94 uint32_t memWidth = config->rxDataWidth <= config->txDataWidth ? config->txDataWidth : config->rxDataWidth ;
95
96 if(memWidth <= CY_SCB_BYTE_WIDTH)
97 {
98 memWidth_type = CY_SCB_MEM_WIDTH_BYTE;
99 }
100 else if(memWidth <= CY_SCB_HALF_WORD_WIDTH)
101 {
102 memWidth_type = CY_SCB_MEM_WIDTH_HALFWORD;
103 }
104 else
105 {
106 memWidth_type = CY_SCB_MEM_WIDTH_WORD;
107 }
108 #elif((defined (CY_IP_MXSCB_VERSION) && CY_IP_MXSCB_VERSION==1))
109 bool byteMode = (config->rxDataWidth <= CY_SCB_BYTE_WIDTH) && (config->txDataWidth <= CY_SCB_BYTE_WIDTH);
110 #endif /* CY_IP_MXSCB_VERSION */
111 /* Configure an SPI interface */
112 SCB_CTRL(base) =_BOOL2FLD(SCB_CTRL_EC_AM_MODE, config->enableWakeFromSleep) |
113 _VAL2FLD(SCB_CTRL_OVS, (config->oversample - 1UL)) |
114 _VAL2FLD(SCB_CTRL_MODE, CY_SCB_CTRL_MODE_SPI);
115 #if((defined (CY_IP_MXSCB_VERSION) && (CY_IP_MXSCB_VERSION>=2)) || defined (CY_IP_MXS22SCB))
116 Cy_SCB_SetMemWidth(base, memWidth_type);
117 #elif((defined (CY_IP_MXSCB_VERSION) && CY_IP_MXSCB_VERSION==1))
118 SCB_CTRL(base) |=_BOOL2FLD(SCB_CTRL_BYTE_MODE, byteMode);
119 #endif /* CY_IP_MXSCB_VERSION */
120
121 /* Configure SCB_CTRL.BYTE_MODE then verify levels */
122 CY_ASSERT_L2(CY_SCB_IS_TRIGGER_LEVEL_VALID(base, config->rxFifoTriggerLevel));
123 CY_ASSERT_L2(CY_SCB_IS_TRIGGER_LEVEL_VALID(base, config->txFifoTriggerLevel));
124
125 SCB_SPI_CTRL(base) = _BOOL2FLD(SCB_SPI_CTRL_SSEL_CONTINUOUS, (!config->enableTransferSeperation)) |
126 _BOOL2FLD(SCB_SPI_CTRL_SELECT_PRECEDE, (CY_SCB_SPI_TI_PRECEDES == config->subMode)) |
127 _BOOL2FLD(SCB_SPI_CTRL_LATE_MISO_SAMPLE, config->enableMisoLateSample) |
128 _BOOL2FLD(SCB_SPI_CTRL_SCLK_CONTINUOUS, config->enableFreeRunSclk) |
129 _BOOL2FLD(SCB_SPI_CTRL_MASTER_MODE, (CY_SCB_SPI_MASTER == config->spiMode)) |
130 _VAL2FLD(CY_SCB_SPI_CTRL_CLK_MODE, locSclkMode) |
131 _VAL2FLD(CY_SCB_SPI_CTRL_SSEL_POLARITY, config->ssPolarity) |
132 _VAL2FLD(SCB_SPI_CTRL_MODE, (uint32_t) config->subMode);
133 #if((defined (CY_IP_MXSCB_VERSION) && (CY_IP_MXSCB_VERSION>=2)) || defined (CY_IP_MXS22SCB))
134 if(config->subMode == CY_SCB_SPI_MOTOROLA)
135 {
136 SCB_SPI_CTRL(base) &= ~SCB_SPI_CTRL_SSEL_SETUP_DEL_Msk;
137 SCB_SPI_CTRL(base) |= _VAL2FLD(SCB_SPI_CTRL_SSEL_SETUP_DEL, config->ssSetupDelay);
138
139 SCB_SPI_CTRL(base) &= ~SCB_SPI_CTRL_SSEL_HOLD_DEL_Msk;
140 SCB_SPI_CTRL(base) |= _VAL2FLD(SCB_SPI_CTRL_SSEL_HOLD_DEL, config->ssHoldDelay);
141
142 SCB_SPI_CTRL(base) &= ~SCB_SPI_CTRL_SSEL_INTER_FRAME_DEL_Msk;
143 SCB_SPI_CTRL(base) |= _VAL2FLD(SCB_SPI_CTRL_SSEL_INTER_FRAME_DEL, config->ssInterFrameDelay);
144 }
145 #endif /* CY_IP_MXSCB_VERSION */
146
147 /* Configure the RX direction */
148 SCB_RX_CTRL(base) = _BOOL2FLD(SCB_RX_CTRL_MSB_FIRST, config->enableMsbFirst) |
149 _BOOL2FLD(SCB_RX_CTRL_MEDIAN, config->enableInputFilter) |
150 _VAL2FLD(SCB_RX_CTRL_DATA_WIDTH, (config->rxDataWidth - 1UL));
151
152 SCB_RX_FIFO_CTRL(base) = _VAL2FLD(SCB_RX_FIFO_CTRL_TRIGGER_LEVEL, config->rxFifoTriggerLevel);
153
154 /* Configure the TX direction */
155 SCB_TX_CTRL(base) = _BOOL2FLD(SCB_TX_CTRL_MSB_FIRST, config->enableMsbFirst) |
156 _VAL2FLD(SCB_TX_CTRL_DATA_WIDTH, (config->txDataWidth - 1UL));
157 #if((defined (CY_IP_MXSCB_VERSION) && (CY_IP_MXSCB_VERSION>=2)) || defined (CY_IP_MXS22SCB))
158 if(config->subMode == CY_SCB_SPI_MOTOROLA)
159 {
160 /* Configure the TX direction */
161 SCB_SPI_TX_CTRL(base) = _VAL2FLD(CY_SCB_SPI_TX_CTRL_SET_PARITY, (uint32_t) config->parity);
162 }
163 #endif /* CY_IP_MXSCB_VERSION */
164
165 SCB_TX_FIFO_CTRL(base) = _VAL2FLD(SCB_TX_FIFO_CTRL_TRIGGER_LEVEL, config->txFifoTriggerLevel);
166 #if((defined (CY_IP_MXSCB_VERSION) && (CY_IP_MXSCB_VERSION>=2)) || defined (CY_IP_MXS22SCB))
167 if(config->subMode == CY_SCB_SPI_MOTOROLA)
168 {
169 /* Configure the RX direction */
170 SCB_SPI_RX_CTRL(base) = _BOOL2FLD(SCB_SPI_RX_CTRL_DROP_ON_PARITY_ERROR, config->dropOnParityError) |
171 _VAL2FLD(CY_SCB_SPI_RX_CTRL_SET_PARITY, (uint32_t) config->parity);
172 }
173 #endif /* CY_IP_MXSCB_VERSION */
174
175 /* Set up interrupt sources */
176 SCB_INTR_RX_MASK(base) = (config->rxFifoIntEnableMask & CY_SCB_SPI_RX_INTR_MASK);
177 SCB_INTR_TX_MASK(base) = (config->txFifoIntEnableMask & CY_SCB_SPI_TX_INTR_MASK);
178 SCB_INTR_M_MASK(base) = (config->masterSlaveIntEnableMask & CY_SCB_SPI_MASTER_DONE);
179 SCB_INTR_S_MASK(base) = (config->masterSlaveIntEnableMask & CY_SCB_SPI_SLAVE_ERR);
180 SCB_INTR_SPI_EC_MASK(base) = 0UL;
181
182 /* Initialize the context */
183 if (NULL != context)
184 {
185 context->status = 0UL;
186
187 context->txBufIdx = 0UL;
188 context->rxBufIdx = 0UL;
189
190 context->cbEvents = NULL;
191
192 #if !defined(NDEBUG)
193 /* Put an initialization key into the initKey variable to verify
194 * context initialization in the transfer API.
195 */
196 context->initKey = CY_SCB_SPI_INIT_KEY;
197 #endif /* !(NDEBUG) */
198 }
199
200 return CY_SCB_SPI_SUCCESS;
201 }
202
203
204 /*******************************************************************************
205 * Function Name: Cy_SCB_SPI_DeInit
206 ****************************************************************************//**
207 *
208 * De-initializes the SCB block; returns the register values to default.
209 *
210 * \param base
211 * The pointer to the SPI SCB instance.
212 *
213 * \note
214 * Ensure that the SCB block is disabled \ref Cy_SCB_SPI_Disable
215 * before calling this function.
216 *
217 *******************************************************************************/
Cy_SCB_SPI_DeInit(CySCB_Type * base)218 void Cy_SCB_SPI_DeInit(CySCB_Type *base)
219 {
220 /* SPI interface */
221 SCB_CTRL(base) = CY_SCB_CTRL_DEF_VAL;
222 SCB_SPI_CTRL(base) = CY_SCB_SPI_CTRL_DEF_VAL;
223
224 /* RX direction */
225 #if((defined (CY_IP_MXSCB_VERSION) && (CY_IP_MXSCB_VERSION>=2)) || defined (CY_IP_MXS22SCB))
226 SCB_SPI_RX_CTRL(base) = 0UL;
227 #endif /* CY_IP_MXSCB_VERSION */
228 SCB_RX_CTRL(base) = CY_SCB_RX_CTRL_DEF_VAL;
229 SCB_RX_FIFO_CTRL(base) = 0UL;
230
231 /* TX direction */
232 #if((defined (CY_IP_MXSCB_VERSION) && (CY_IP_MXSCB_VERSION>=2)) || defined (CY_IP_MXS22SCB))
233 SCB_SPI_TX_CTRL(base) = 0UL;
234 #endif /* CY_IP_MXSCB_VERSION */
235 SCB_TX_CTRL(base) = CY_SCB_TX_CTRL_DEF_VAL;
236 SCB_TX_FIFO_CTRL(base) = 0UL;
237
238 /* Disable all interrupt sources */
239 SCB_INTR_SPI_EC_MASK(base) = 0UL;
240 SCB_INTR_I2C_EC_MASK(base) = 0UL;
241 SCB_INTR_RX_MASK(base) = 0UL;
242 SCB_INTR_TX_MASK(base) = 0UL;
243 SCB_INTR_M_MASK(base) = 0UL;
244 SCB_INTR_S_MASK(base) = 0UL;
245 }
246
247
248 /*******************************************************************************
249 * Function Name: Cy_SCB_SPI_Disable
250 ****************************************************************************//**
251 *
252 * Disables the SCB block, clears context statuses, and disables
253 * TX and RX interrupt sources.
254 * Note that after the block is disabled, the TX and RX FIFOs and
255 * hardware statuses are cleared. Also, the hardware stops driving the output
256 * and ignores the input. Refer to section \ref group_scb_spi_lp for more
257 * information about SPI pins when SCB disabled.
258 *
259 * \param base
260 * The pointer to the SPI SCB instance.
261 *
262 * \param context
263 * The pointer to the context structure \ref cy_stc_scb_spi_context_t allocated
264 * by the user. The structure is used during the SPI operation for internal
265 * configuration and data retention. The user must not modify anything
266 * in this structure.
267 * If only SPI functions that do not require context will be used to pass NULL
268 * as pointer to context.
269 *
270 * \note
271 * Calling this function when the SPI is busy (master preforms data transfer or
272 * slave communicates with the master) may cause transfer corruption because the
273 * hardware stops driving the outputs and ignores the inputs.
274 * Ensure that the SPI is not busy before calling this function.
275 *
276 *******************************************************************************/
Cy_SCB_SPI_Disable(CySCB_Type * base,cy_stc_scb_spi_context_t * context)277 void Cy_SCB_SPI_Disable(CySCB_Type *base, cy_stc_scb_spi_context_t *context)
278 {
279 SCB_CTRL(base) &= (uint32_t) ~SCB_CTRL_ENABLED_Msk;
280
281 if (NULL != context)
282 {
283 context->status = 0UL;
284
285 context->rxBufIdx = 0UL;
286 context->txBufIdx = 0UL;
287 }
288
289 /* Disable RX and TX interrupt sources for the slave because
290 * RX overflow and TX underflow are kept enabled after the 1st call of
291 * Cy_SCB_SPI_Transfer().
292 */
293 if (!_FLD2BOOL(SCB_SPI_CTRL_MASTER_MODE, SCB_SPI_CTRL(base)))
294 {
295 Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
296 Cy_SCB_SetTxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
297 }
298 }
299
300
301 /*******************************************************************************
302 * Function Name: Cy_SCB_SPI_DeepSleepCallback
303 ****************************************************************************//**
304 *
305 * This function handles the transition of the SCB SPI into and out of
306 * Deep Sleep mode. It prevents the device from entering Deep Sleep mode
307 * if the SPI slave or master is actively communicating, or there is any data
308 * in the TX or RX FIFOs.
309 * The following behavior of the SPI SCB depends on whether the SCB block is
310 * wakeup-capable or not:
311 * * <b>Wakeup-capable</b>: any transfer intended to the slave wakes up
312 * the device from Deep Sleep mode. The slave responds with 0xFF to the
313 * transfer and incoming data is ignored.
314 * If the transfer occurs before the device enters Deep Sleep mode, the device
315 * will not enter Deep Sleep mode and incoming data is stored in the RX FIFO.
316 * The SCB clock is disabled before entering Deep Sleep and enabled after the
317 * device exits Deep Sleep mode. The SCB clock disabling may lead to
318 * corrupted data in the RX FIFO. Clear the RX FIFO after this callback is
319 * executed.
320 * Note that for proper SPI operation after Deep Sleep the source of
321 * hf_clk[0] must be stable, this includes the FLL/PLL. The SysClk callback
322 * ensures that hf_clk[0] gets stable and it must be called before
323 * \ref Cy_SCB_SPI_DeepSleepCallback.
324 * Only the SPI slave can be configured to be a wakeup source from Deep Sleep
325 * mode.
326 * * <b>Not wakeup-capable</b>: the SPI is disabled. It is enabled when
327 * the device fails to enter Deep Sleep mode or it is awakened from Deep Sleep
328 * mode. While the SPI is disabled, it stops driving the outputs and ignores
329 * the inputs. Any incoming data is ignored.
330 * Refer to section \ref group_scb_spi_lp for more information about SPI pins
331 * when SCB disabled.
332 *
333 * This function must be called during execution of \ref Cy_SysPm_CpuEnterDeepSleep.
334 * To do it, register this function as a callback before calling
335 * \ref Cy_SysPm_CpuEnterDeepSleep : specify \ref CY_SYSPM_DEEPSLEEP as the callback
336 * type and call \ref Cy_SysPm_RegisterCallback.
337 *
338 * \param callbackParams
339 * The pointer to the callback parameters structure
340 * \ref cy_stc_syspm_callback_params_t.
341 *
342 * \param mode
343 * Callback mode, see \ref cy_en_syspm_callback_mode_t
344 *
345 * \return
346 * \ref cy_en_syspm_status_t
347 *
348 * \note
349 * Only applicable for <b>rev-08 of the CY8CKIT-062-BLE</b>.
350 * For proper operation, when the SPI slave is configured to be a wakeup source
351 * from Deep Sleep mode, this function must be copied and modified by the user.
352 * The SPI clock disable code must be inserted in the \ref CY_SYSPM_BEFORE_TRANSITION
353 * and clock enable code in the \ref CY_SYSPM_AFTER_TRANSITION mode processing.
354 *
355 *******************************************************************************/
Cy_SCB_SPI_DeepSleepCallback(cy_stc_syspm_callback_params_t * callbackParams,cy_en_syspm_callback_mode_t mode)356 cy_en_syspm_status_t Cy_SCB_SPI_DeepSleepCallback(cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode)
357 {
358 CySCB_Type *locBase = (CySCB_Type *) callbackParams->base;
359 cy_stc_scb_spi_context_t *locContext = (cy_stc_scb_spi_context_t *) callbackParams->context;
360
361 cy_en_syspm_status_t retStatus = CY_SYSPM_FAIL;
362
363 switch(mode)
364 {
365 case CY_SYSPM_CHECK_READY:
366 {
367 /* Check whether the High-level API is not busy executing the transfer
368 * operation.
369 */
370 if (0UL == (CY_SCB_SPI_TRANSFER_ACTIVE & Cy_SCB_SPI_GetTransferStatus(locBase, locContext)))
371 {
372 /* If the SPI bus is not busy, all data elements are transferred
373 * on the bus from the TX FIFO and shifter and the RX FIFOs are
374 * empty - the SPI is ready to enter Deep Sleep mode.
375 */
376 if (!Cy_SCB_SPI_IsBusBusy(locBase))
377 {
378 if (Cy_SCB_SPI_IsTxComplete(locBase))
379 {
380 if (0UL == Cy_SCB_SPI_GetNumInRxFifo(locBase))
381 {
382 if (_FLD2BOOL(SCB_CTRL_EC_AM_MODE, SCB_CTRL(locBase)))
383 {
384 /* The SCB is wakeup-capable: clear the SPI
385 * wakeup interrupt source because it triggers
386 * during Active mode communication and make
387 * sure that a new transfer is not started after
388 * clearing.
389 */
390 Cy_SCB_ClearSpiInterrupt(locBase, CY_SCB_SPI_INTR_WAKEUP);
391
392 if (!Cy_SCB_SPI_IsBusBusy(locBase))
393 {
394 retStatus = CY_SYSPM_SUCCESS;
395 }
396 }
397 else
398 {
399 /* The SCB is NOT wakeup-capable: disable the
400 * SPI. The master and slave stop driving the
401 * bus until the SPI is enabled. This happens
402 * when the device fails to enter Deep Sleep
403 * mode or it is awakened from Deep Sleep mode.
404 */
405 Cy_SCB_SPI_Disable(locBase, locContext);
406
407 retStatus = CY_SYSPM_SUCCESS;
408 }
409 }
410 }
411 }
412 }
413 }
414 break;
415
416 case CY_SYSPM_CHECK_FAIL:
417 {
418 /* The other driver is not ready for Deep Sleep mode. Restore
419 * Active mode configuration.
420 */
421
422 if (!_FLD2BOOL(SCB_CTRL_EC_AM_MODE, SCB_CTRL(locBase)))
423 {
424 /* The SCB is NOT wakeup-capable: enable the SPI to operate */
425 Cy_SCB_SPI_Enable(locBase);
426 }
427
428 retStatus = CY_SYSPM_SUCCESS;
429 }
430 break;
431
432 case CY_SYSPM_BEFORE_TRANSITION:
433 {
434 /* This code executes inside the critical section and enabling the
435 * active interrupt source makes the interrupt pending in the NVIC.
436 * However, the interrupt processing is delayed until the code exits
437 * the critical section. The pending interrupt force WFI instruction
438 * does nothing and the device remains in Active mode.
439 */
440
441 if (_FLD2BOOL(SCB_CTRL_EC_AM_MODE, SCB_CTRL(locBase)))
442 {
443 /* The SCB is wakeup-capable: enable the SPI wakeup interrupt
444 * source. If any transaction happens, the wakeup interrupt
445 * becomes pending and prevents entering Deep Sleep mode.
446 */
447 Cy_SCB_SetSpiInterruptMask(locBase, CY_SCB_I2C_INTR_WAKEUP);
448
449 /* Disable SCB clock */
450 SCB_I2C_CFG(locBase) &= (uint32_t) ~CY_SCB_I2C_CFG_CLK_ENABLE_Msk;
451
452 /* IMPORTANT (replace line above for the CY8CKIT-062 rev-08):
453 * for proper entering Deep Sleep mode the SPI clock must be disabled.
454 * This code must be inserted by the user because the driver
455 * does not have access to the clock.
456 */
457 }
458
459 retStatus = CY_SYSPM_SUCCESS;
460 }
461 break;
462
463 case CY_SYSPM_AFTER_TRANSITION:
464 {
465 if (_FLD2BOOL(SCB_CTRL_EC_AM_MODE, SCB_CTRL(locBase)))
466 {
467 /* Enable SCB clock */
468 SCB_I2C_CFG(locBase) |= CY_SCB_I2C_CFG_CLK_ENABLE_Msk;
469
470 /* IMPORTANT (replace line above for the CY8CKIT-062 rev-08):
471 * for proper exiting Deep Sleep mode, the SPI clock must be enabled.
472 * This code must be inserted by the user because the driver
473 * does not have access to the clock.
474 */
475
476 /* The SCB is wakeup-capable: disable the SPI wakeup interrupt
477 * source
478 */
479 Cy_SCB_SetSpiInterruptMask(locBase, CY_SCB_CLEAR_ALL_INTR_SRC);
480 }
481 else
482 {
483 /* The SCB is NOT wakeup-capable: enable the SPI to operate */
484 Cy_SCB_SPI_Enable(locBase);
485 }
486
487 retStatus = CY_SYSPM_SUCCESS;
488 }
489 break;
490
491 default:
492 /* Unknown state */
493 break;
494 }
495
496 return (retStatus);
497 }
498
499
500 /*******************************************************************************
501 * Function Name: Cy_SCB_SPI_HibernateCallback
502 ****************************************************************************//**
503 *
504 * This function handles the transition of the SCB SPI into Hibernate mode.
505 * It prevents the device from entering Hibernate mode if the SPI slave or
506 * master is actively communicating, or there is any data in the TX or RX FIFOs.
507 * If the SPI is ready to enter Hibernate mode, it is disabled. If the device
508 * failed to enter Hibernate mode, the SPI is re-enabled. While the SPI is
509 * disabled, it stops driving the outputs and ignores the inputs. Any incoming
510 * data is ignored. Refer to section \ref group_scb_spi_lp for more information
511 * about SPI pins when SCB disabled.
512 *
513 * This function must be called during execution of \ref Cy_SysPm_SystemEnterHibernate.
514 * To do it, register this function as a callback before calling
515 * \ref Cy_SysPm_SystemEnterHibernate : specify \ref CY_SYSPM_HIBERNATE as the callback
516 * type and call \ref Cy_SysPm_RegisterCallback.
517 *
518 * \param callbackParams
519 * The pointer to the callback parameters structure
520 * \ref cy_stc_syspm_callback_params_t.
521 *
522 * \param mode
523 * Callback mode, see \ref cy_en_syspm_callback_mode_t
524 *
525 * \return
526 * \ref cy_en_syspm_status_t
527 *
528 *******************************************************************************/
Cy_SCB_SPI_HibernateCallback(cy_stc_syspm_callback_params_t * callbackParams,cy_en_syspm_callback_mode_t mode)529 cy_en_syspm_status_t Cy_SCB_SPI_HibernateCallback(cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode)
530 {
531 CySCB_Type *locBase = (CySCB_Type *) callbackParams->base;
532 cy_stc_scb_spi_context_t *locContext = (cy_stc_scb_spi_context_t *) callbackParams->context;
533
534 cy_en_syspm_status_t retStatus = CY_SYSPM_FAIL;
535
536 switch(mode)
537 {
538 case CY_SYSPM_CHECK_READY:
539 {
540 /* Check whether the High-level API is not busy executing the transfer
541 * operation.
542 */
543 if (0UL == (CY_SCB_SPI_TRANSFER_ACTIVE & Cy_SCB_SPI_GetTransferStatus(locBase, locContext)))
544 {
545 /* If the SPI bus is not busy, all data elements are transferred
546 * on the bus from the TX FIFO and shifter and the RX FIFOs are
547 * empty - the SPI is ready to enter Hibernate mode.
548 */
549 if (!Cy_SCB_SPI_IsBusBusy(locBase))
550 {
551 if (Cy_SCB_SPI_IsTxComplete(locBase))
552 {
553 if (0UL == Cy_SCB_SPI_GetNumInRxFifo(locBase))
554 {
555 /* Disable the SPI. The master or slave stops
556 * driving the bus until the SPI is enabled.
557 * This happens if the device failed to enter
558 * Hibernate mode.
559 */
560 Cy_SCB_SPI_Disable(locBase, locContext);
561
562 retStatus = CY_SYSPM_SUCCESS;
563 }
564 }
565 }
566 }
567 }
568 break;
569
570 case CY_SYSPM_CHECK_FAIL:
571 {
572 /* The other driver is not ready for Hibernate mode. Restore Active
573 * mode configuration.
574 */
575
576 /* Enable the SPI to operate */
577 Cy_SCB_SPI_Enable(locBase);
578
579 retStatus = CY_SYSPM_SUCCESS;
580 }
581 break;
582
583 case CY_SYSPM_BEFORE_TRANSITION:
584 case CY_SYSPM_AFTER_TRANSITION:
585 {
586 /* The SCB is not capable of waking up from Hibernate mode:
587 * do nothing.
588 */
589 retStatus = CY_SYSPM_SUCCESS;
590 }
591 break;
592
593 default:
594 /* Unknown state */
595 break;
596 }
597
598 return (retStatus);
599 }
600
601
602 /************************* High-Level Functions ********************************
603 * The following functions are considered high-level. They provide the layer of
604 * intelligence to the SCB. These functions require interrupts.
605 * Low-level and high-level functions must not be mixed because low-level API
606 * can adversely affect the operation of high-level functions.
607 *******************************************************************************/
608
609
610 /*******************************************************************************
611 * Function Name: Cy_SCB_SPI_Transfer
612 ****************************************************************************//**
613 *
614 * This function starts an SPI transfer operation.
615 * It configures transmit and receive buffers for an SPI transfer.
616 * If the data that will be received is not important, pass NULL as rxBuffer.
617 * If the data that will be transmitted is not important, pass NULL as txBuffer
618 * and then the \ref CY_SCB_SPI_DEFAULT_TX is sent out as each data element.
619 * Note that passing NULL as rxBuffer and txBuffer are considered invalid cases.
620 *
621 * After the function configures TX and RX interrupt sources, it returns and
622 * \ref Cy_SCB_SPI_Interrupt manages further data transfer.
623 *
624 * * In the master mode, the transfer operation starts after calling this
625 * function
626 * * In the slave mode, the transfer registers and will start when
627 * the master request arrives.
628 *
629 * When the transfer operation is completed (requested number of data elements
630 * sent and received), the \ref CY_SCB_SPI_TRANSFER_ACTIVE status is cleared
631 * and the \ref CY_SCB_SPI_TRANSFER_CMPLT_EVENT event is generated.
632 *
633 * \param base
634 * The pointer to the SPI SCB instance.
635 *
636 * \param txBuffer
637 * The pointer of the buffer with data to transmit.
638 * The element size is defined by the data type that depends on the configured
639 * TX data width.
640 *
641 * \param rxBuffer
642 * The pointer to the buffer to store received data.
643 * The element size is defined by the data type that depends on the configured
644 * RX data width.
645 *
646 * \param size
647 * The number of data elements to transmit and receive.
648 *
649 * \param context
650 * The pointer to the context structure \ref cy_stc_scb_spi_context_t allocated
651 * by the user. The structure is used during the SPI operation for internal
652 * configuration and data retention. The user must not modify anything
653 * in this structure.
654 *
655 * \return
656 * \ref cy_en_scb_spi_status_t
657 *
658 * \note
659 * * The buffers must not be modified and must stay allocated until the end of the
660 * transfer.
661 * * This function overrides all RX and TX FIFO interrupt sources and changes
662 * the RX and TX FIFO level.
663 *
664 *******************************************************************************/
Cy_SCB_SPI_Transfer(CySCB_Type * base,void * txBuffer,void * rxBuffer,uint32_t size,cy_stc_scb_spi_context_t * context)665 cy_en_scb_spi_status_t Cy_SCB_SPI_Transfer(CySCB_Type *base, void *txBuffer, void *rxBuffer, uint32_t size,
666 cy_stc_scb_spi_context_t *context)
667 {
668 CY_ASSERT_L1(NULL != context);
669 #if !defined(NDEBUG)
670 CY_ASSERT_L1(CY_SCB_SPI_INIT_KEY == context->initKey);
671 #endif
672 CY_ASSERT_L1(CY_SCB_SPI_IS_BUFFER_VALID(txBuffer, rxBuffer, size));
673
674 cy_en_scb_spi_status_t retStatus = CY_SCB_SPI_TRANSFER_BUSY;
675
676 /* Check whether there are no active transfer requests */
677 if (0UL == (CY_SCB_SPI_TRANSFER_ACTIVE & context->status))
678 {
679 uint32_t fifoSize = Cy_SCB_GetFifoSize(base);
680
681 /* Set up the context */
682 context->status = CY_SCB_SPI_TRANSFER_ACTIVE;
683
684 context->txBuf = txBuffer;
685 context->txBufSize = size;
686 context->txBufIdx = 0UL;
687
688 context->rxBuf = rxBuffer;
689 context->rxBufSize = size;
690 context->rxBufIdx = 0UL;
691
692 /* Set the TX interrupt when half of FIFO was transmitted */
693 Cy_SCB_SetTxFifoLevel(base, fifoSize / 2UL);
694
695 if (_FLD2BOOL(SCB_SPI_CTRL_MASTER_MODE, SCB_SPI_CTRL(base)))
696 {
697 /* Trigger an RX interrupt:
698 * - If the transfer size is equal to or less than FIFO, trigger at the end of the transfer.
699 * - If the transfer size is greater than FIFO, trigger 1 byte earlier than the TX interrupt.
700 */
701 Cy_SCB_SetRxFifoLevel(base, (size > fifoSize) ? ((fifoSize / 2UL) - 2UL) : (size - 1UL));
702
703 Cy_SCB_SetMasterInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
704
705 /* Enable interrupt sources to perform a transfer */
706 Cy_SCB_SetRxInterruptMask(base, CY_SCB_RX_INTR_LEVEL);
707 Cy_SCB_SetTxInterruptMask(base, CY_SCB_TX_INTR_LEVEL);
708 }
709 else
710 {
711 /* Trigger an RX interrupt:
712 * - If the transfer size is equal to or less than half of FIFO, trigger ??at the end of the transfer.
713 * - If the transfer size is greater than half of FIFO, trigger 1 byte earlier than a TX interrupt.
714 */
715 Cy_SCB_SetRxFifoLevel(base, (size > (fifoSize / 2UL)) ? ((fifoSize / 2UL) - 2UL) : (size - 1UL));
716
717 Cy_SCB_SetSlaveInterruptMask(base, CY_SCB_SLAVE_INTR_SPI_BUS_ERROR);
718
719 /* Enable interrupt sources to perform a transfer */
720 Cy_SCB_SetRxInterruptMask(base, CY_SCB_RX_INTR_LEVEL | CY_SCB_RX_INTR_OVERFLOW);
721 Cy_SCB_SetTxInterruptMask(base, CY_SCB_TX_INTR_LEVEL | CY_SCB_TX_INTR_UNDERFLOW);
722 }
723
724 retStatus = CY_SCB_SPI_SUCCESS;
725 }
726
727 return (retStatus);
728 }
729
730
731 /*******************************************************************************
732 * Function Name: Cy_SCB_SPI_AbortTransfer
733 ****************************************************************************//**
734 *
735 * Aborts the current SPI transfer.
736 * It disables the TX and RX interrupt sources, clears the TX
737 * and RX FIFOs and the status.
738 *
739 * \param base
740 * The pointer to the SPI SCB instance.
741 *
742 * \param context
743 * The pointer to the context structure \ref cy_stc_scb_spi_context_t allocated
744 * by the user. The structure is used during the SPI operation for internal
745 * configuration and data retention. The user must not modify anything
746 * in this structure.
747 *
748 * \note
749 * If slave aborts transfer and the master is still transferring data,
750 * that data will be placed in the RX FIFO, and the TX underflow will be set.
751 * To drop data received into the RX FIFO, RX FIFO must be cleared when
752 * the transfer is complete. Otherwise, received data will be kept and
753 * copied to the buffer when \ref Cy_SCB_SPI_Transfer is called.
754 *
755 * \sideeffect
756 * The transmit FIFO clear operation also clears the shift register, so that
757 * the shifter can be cleared in the middle of a data element transfer,
758 * corrupting it. The data element corruption means that all bits that have
759 * not been transmitted are transmitted as "ones" on the bus.
760 *
761 *******************************************************************************/
Cy_SCB_SPI_AbortTransfer(CySCB_Type * base,cy_stc_scb_spi_context_t * context)762 void Cy_SCB_SPI_AbortTransfer(CySCB_Type *base, cy_stc_scb_spi_context_t *context)
763 {
764 /* Disable interrupt sources */
765 Cy_SCB_SetSlaveInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
766
767 if (_FLD2BOOL(SCB_SPI_CTRL_MASTER_MODE, SCB_SPI_CTRL(base)))
768 {
769 Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
770 Cy_SCB_SetTxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
771 }
772 else
773 {
774 Cy_SCB_SetRxInterruptMask(base, CY_SCB_RX_INTR_OVERFLOW);
775 Cy_SCB_SetTxInterruptMask(base, CY_SCB_TX_INTR_UNDERFLOW);
776 }
777
778 /* Clear FIFOs */
779 Cy_SCB_SPI_ClearTxFifo(base);
780 Cy_SCB_SPI_ClearRxFifo(base);
781
782 /* Clear the status to allow a new transfer */
783 context->status = 0UL;
784 }
785
786
787 /*******************************************************************************
788 * Function Name: Cy_SCB_SPI_GetNumTransfered
789 ****************************************************************************//**
790 *
791 * Returns the number of data elements transferred since the last call to \ref
792 * Cy_SCB_SPI_Transfer.
793 *
794 * \param base
795 * The pointer to the SPI SCB instance.
796 *
797 * \param context
798 * The pointer to the context structure \ref cy_stc_scb_spi_context_t allocated
799 * by the user. The structure is used during the SPI operation for internal
800 * configuration and data retention. The user must not modify anything
801 * in this structure.
802 *
803 * \return
804 * The number of data elements transferred.
805 *
806 *******************************************************************************/
Cy_SCB_SPI_GetNumTransfered(CySCB_Type const * base,cy_stc_scb_spi_context_t const * context)807 uint32_t Cy_SCB_SPI_GetNumTransfered(CySCB_Type const *base, cy_stc_scb_spi_context_t const *context)
808 {
809 /* Suppress a compiler warning about unused variables */
810 (void) base;
811
812 return (context->rxBufIdx);
813 }
814
815
816 /*******************************************************************************
817 * Function Name: Cy_SCB_SPI_GetTransferStatus
818 ****************************************************************************//**
819 *
820 * Returns the status of the transfer operation started by
821 * \ref Cy_SCB_SPI_Transfer.
822 * This status is a bit mask and the value returned may have a multiple-bit set.
823 *
824 * \param base
825 * The pointer to the SPI SCB instance.
826 *
827 * \param context
828 * The pointer to the context structure \ref cy_stc_scb_spi_context_t allocated
829 * by the user. The structure is used during the SPI operation for internal
830 * configuration and data retention. The user must not modify anything
831 * in this structure.
832 *
833 * \return
834 * \ref group_scb_spi_macros_xfer_status.
835 *
836 * \note
837 * The status is cleared by calling \ref Cy_SCB_SPI_Transfer or
838 * \ref Cy_SCB_SPI_AbortTransfer.
839 *
840 *******************************************************************************/
Cy_SCB_SPI_GetTransferStatus(CySCB_Type const * base,cy_stc_scb_spi_context_t const * context)841 uint32_t Cy_SCB_SPI_GetTransferStatus(CySCB_Type const *base, cy_stc_scb_spi_context_t const *context)
842 {
843 /* Suppress a compiler warning about unused variables */
844 (void) base;
845
846 return (context->status);
847 }
848
849
850 /*******************************************************************************
851 * Function Name: Cy_SCB_SPI_Interrupt
852 ****************************************************************************//**
853 *
854 * This is the interrupt function for the SCB configured in the SPI mode.
855 * This function must be called inside the user-defined interrupt service
856 * routine for \ref Cy_SCB_SPI_Transfer to work.
857 *
858 * \param base
859 * The pointer to the SPI SCB instance.
860 *
861 * \param context
862 * The pointer to the context structure \ref cy_stc_scb_spi_context_t allocated
863 * by the user. The structure is used during the SPI operation for internal
864 * configuration and data retention. The user must not modify anything
865 * in this structure.
866 *
867 *******************************************************************************/
Cy_SCB_SPI_Interrupt(CySCB_Type * base,cy_stc_scb_spi_context_t * context)868 void Cy_SCB_SPI_Interrupt(CySCB_Type *base, cy_stc_scb_spi_context_t *context)
869 {
870 bool locXferErr = false;
871
872 /* Wake up on the slave select condition */
873 if (0UL != (CY_SCB_SPI_INTR_WAKEUP & Cy_SCB_GetSpiInterruptStatusMasked(base)))
874 {
875 Cy_SCB_ClearSpiInterrupt(base, CY_SCB_SPI_INTR_WAKEUP);
876 }
877
878 /* The slave error condition */
879 if (0UL != (CY_SCB_SLAVE_INTR_SPI_BUS_ERROR & Cy_SCB_GetSlaveInterruptStatusMasked(base)))
880 {
881 locXferErr = true;
882 context->status |= CY_SCB_SPI_SLAVE_TRANSFER_ERR;
883
884 Cy_SCB_ClearSlaveInterrupt(base, CY_SCB_SLAVE_INTR_SPI_BUS_ERROR);
885 }
886
887 /* The RX overflow error condition */
888 if (0UL != (CY_SCB_RX_INTR_OVERFLOW & Cy_SCB_GetRxInterruptStatusMasked(base)))
889 {
890 locXferErr = true;
891 context->status |= CY_SCB_SPI_TRANSFER_OVERFLOW;
892
893 Cy_SCB_ClearRxInterrupt(base, CY_SCB_RX_INTR_OVERFLOW);
894 }
895
896 /* The TX underflow error condition or slave complete data transfer */
897 if (0UL != (CY_SCB_TX_INTR_UNDERFLOW & Cy_SCB_GetTxInterruptStatusMasked(base)))
898 {
899 locXferErr = true;
900 context->status |= CY_SCB_SPI_TRANSFER_UNDERFLOW;
901
902 Cy_SCB_ClearTxInterrupt(base, CY_SCB_TX_INTR_UNDERFLOW);
903 }
904
905 /* Report an error, use a callback */
906 if (locXferErr)
907 {
908 if (NULL != context->cbEvents)
909 {
910 context->cbEvents(CY_SCB_SPI_TRANSFER_ERR_EVENT);
911 }
912 }
913
914 /* RX direction */
915 if (0UL != (CY_SCB_RX_INTR_LEVEL & Cy_SCB_GetRxInterruptStatusMasked(base)))
916 {
917 HandleReceive(base, context);
918
919 Cy_SCB_ClearRxInterrupt(base, CY_SCB_RX_INTR_LEVEL);
920 }
921
922 /* TX direction */
923 if (0UL != (CY_SCB_TX_INTR_LEVEL & Cy_SCB_GetTxInterruptStatusMasked(base)))
924 {
925 HandleTransmit(base, context);
926
927 Cy_SCB_ClearTxInterrupt(base, CY_SCB_TX_INTR_LEVEL);
928 }
929
930 /* The transfer is complete: all data is loaded in the TX FIFO
931 * and all data is read from the RX FIFO
932 */
933 if ((0UL != (context->status & CY_SCB_SPI_TRANSFER_ACTIVE)) &&
934 (0UL == context->rxBufSize) && (0UL == context->txBufSize))
935 {
936 /* The transfer is complete */
937 context->status &= (uint32_t) ~CY_SCB_SPI_TRANSFER_ACTIVE;
938
939 if (NULL != context->cbEvents)
940 {
941 context->cbEvents(CY_SCB_SPI_TRANSFER_CMPLT_EVENT);
942 }
943 }
944 }
945
946
947 /*******************************************************************************
948 * Function Name: HandleReceive
949 ****************************************************************************//**
950 *
951 * Reads data from RX FIFO into the buffer provided by \ref Cy_SCB_SPI_Transfer.
952 *
953 * \param base
954 * The pointer to the SPI SCB instance.
955 *
956 * \param context
957 * The pointer to the context structure \ref cy_stc_scb_spi_context_t allocated
958 * by the user. The structure is used during the SPI operation for internal
959 * configuration and data retention. The user must not modify anything
960 * in this structure.
961 *
962 *******************************************************************************/
HandleReceive(CySCB_Type * base,cy_stc_scb_spi_context_t * context)963 static void HandleReceive(CySCB_Type *base, cy_stc_scb_spi_context_t *context)
964 {
965 /* Get data in RX FIFO */
966 uint32_t numToCopy = Cy_SCB_GetNumInRxFifo(base);
967 #if((defined (CY_IP_MXSCB_VERSION) && (CY_IP_MXSCB_VERSION>=2)) || defined (CY_IP_MXS22SCB))
968 uint32_t mem_width;
969 #endif /* CY_IP_MXSCB_VERSION */
970
971 /* Adjust the number to read */
972 if (numToCopy > context->rxBufSize)
973 {
974 numToCopy = context->rxBufSize;
975 }
976
977 /* Move the buffer */
978 context->rxBufIdx += numToCopy;
979 context->rxBufSize -= numToCopy;
980
981 /* Read data from RX FIFO */
982 if (NULL != context->rxBuf)
983 {
984 uint8_t *buf = (uint8_t *) context->rxBuf;
985
986 Cy_SCB_ReadArrayNoCheck(base, context->rxBuf, numToCopy);
987
988 #if((defined (CY_IP_MXSCB_VERSION) && (CY_IP_MXSCB_VERSION>=2)) || defined (CY_IP_MXS22SCB))
989 mem_width = _FLD2VAL(SCB_CTRL_MEM_WIDTH, SCB_CTRL(base));
990 buf = &buf[((1UL << mem_width) * numToCopy)];
991 #elif((defined (CY_IP_MXSCB_VERSION) && CY_IP_MXSCB_VERSION==1))
992 buf = &buf[(Cy_SCB_IsRxDataWidthByte(base) ? (numToCopy) : (2UL * numToCopy))];
993 #endif /* CY_IP_MXSCB_VERSION */
994 context->rxBuf = (void *) buf;
995 }
996 else
997 {
998 /* Discard read data. */
999 DiscardArrayNoCheck(base, numToCopy);
1000 }
1001
1002 if (0UL == context->rxBufSize)
1003 {
1004 /* Disable the RX level interrupt */
1005 Cy_SCB_SetRxInterruptMask(base, (Cy_SCB_GetRxInterruptMask(base) & (uint32_t) ~CY_SCB_RX_INTR_LEVEL));
1006 }
1007 else
1008 {
1009 uint32_t level = (_FLD2BOOL(SCB_SPI_CTRL_MASTER_MODE, SCB_SPI_CTRL(base))) ?
1010 Cy_SCB_GetFifoSize(base) : (Cy_SCB_GetFifoSize(base) / 2UL);
1011
1012 if (context->rxBufSize < level)
1013 {
1014 Cy_SCB_SetRxFifoLevel(base, (context->rxBufSize - 1UL));
1015 }
1016 }
1017 }
1018
1019
1020 /*******************************************************************************
1021 * Function Name: HandleTransmit
1022 ****************************************************************************//**
1023 *
1024 * Loads TX FIFO with data provided by \ref Cy_SCB_SPI_Transfer.
1025 *
1026 * \param base
1027 * The pointer to the SPI SCB instance.
1028 *
1029 * \param context
1030 * The pointer to the context structure \ref cy_stc_scb_spi_context_t allocated
1031 * by the user. The structure is used during the SPI operation for internal
1032 * configuration and data retention. The user must not modify anything
1033 * in this structure.
1034 *
1035 *******************************************************************************/
HandleTransmit(CySCB_Type * base,cy_stc_scb_spi_context_t * context)1036 static void HandleTransmit(CySCB_Type *base, cy_stc_scb_spi_context_t *context)
1037 {
1038 uint32_t numToCopy;
1039 uint32_t fifoSize = Cy_SCB_GetFifoSize(base);
1040 #if((defined (CY_IP_MXSCB_VERSION) && (CY_IP_MXSCB_VERSION>=2)) || defined (CY_IP_MXS22SCB))
1041 uint32_t mem_width;
1042 #endif /* CY_IP_MXSCB_VERSION */
1043
1044 numToCopy = fifoSize - Cy_SCB_GetNumInTxFifo(base);
1045
1046 /* Adjust the number to load */
1047 if (numToCopy > context->txBufSize)
1048 {
1049 numToCopy = context->txBufSize;
1050 }
1051
1052 /* Move the buffer */
1053 context->txBufIdx += numToCopy;
1054 context->txBufSize -= numToCopy;
1055
1056 /* Load TX FIFO with data */
1057 if (NULL != context->txBuf)
1058 {
1059 uint8_t *buf = (uint8_t *) context->txBuf;
1060
1061 Cy_SCB_WriteArrayNoCheck(base, context->txBuf, numToCopy);
1062
1063 #if((defined (CY_IP_MXSCB_VERSION) && (CY_IP_MXSCB_VERSION>=2)) || defined (CY_IP_MXS22SCB))
1064 mem_width = _FLD2VAL(SCB_CTRL_MEM_WIDTH, SCB_CTRL(base));
1065 buf = &buf[((1UL << mem_width) * numToCopy)];
1066 #elif((defined (CY_IP_MXSCB_VERSION) && CY_IP_MXSCB_VERSION==1))
1067 buf = &buf[(Cy_SCB_IsTxDataWidthByte(base) ? (numToCopy) : (2UL * numToCopy))];
1068 #endif /* CY_IP_MXSCB_VERSION */
1069 context->txBuf = (void *) buf;
1070 }
1071 else
1072 {
1073 Cy_SCB_WriteDefaultArrayNoCheck(base, CY_SCB_SPI_DEFAULT_TX, numToCopy);
1074 }
1075
1076 if (0UL == context->txBufSize)
1077 {
1078 /* Data is transferred into TX FIFO */
1079 context->status |= CY_SCB_SPI_TRANSFER_IN_FIFO;
1080
1081 /* Disable the TX level interrupt */
1082 Cy_SCB_SetTxInterruptMask(base, (Cy_SCB_GetTxInterruptMask(base) & (uint32_t) ~CY_SCB_TX_INTR_LEVEL));
1083
1084 if (NULL != context->cbEvents)
1085 {
1086 context->cbEvents(CY_SCB_SPI_TRANSFER_IN_FIFO_EVENT);
1087 }
1088 }
1089 }
1090
1091
1092 /*******************************************************************************
1093 * Function Name: DiscardArrayNoCheck
1094 ****************************************************************************//**
1095 *
1096 * Reads the number of data elements from the SPI RX FIFO. The read data is
1097 * discarded. Before calling this function, make sure that RX FIFO has
1098 * enough data elements to read.
1099 *
1100 * \param base
1101 * The pointer to the SPI SCB instance.
1102 *
1103 * \param size
1104 * The number of data elements to read.
1105 *
1106 *******************************************************************************/
DiscardArrayNoCheck(CySCB_Type const * base,uint32_t size)1107 static void DiscardArrayNoCheck(CySCB_Type const *base, uint32_t size)
1108 {
1109 while (size > 0UL)
1110 {
1111 (void) Cy_SCB_SPI_Read(base);
1112 --size;
1113 }
1114 }
1115
1116 #if defined(__cplusplus)
1117 }
1118 #endif
1119
1120 #endif /* (defined (CY_IP_MXSCB) || defined (CY_IP_MXS22SCB)) */
1121
1122 /* [] END OF FILE */
1123