1 /*
2 * Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 /***********************************************************************************************************************
8 * Includes
9 **********************************************************************************************************************/
10 #include "r_spi_b.h"
11 #include "r_spi_b_cfg.h"
12
13 /***********************************************************************************************************************
14 * Macro definitions
15 **********************************************************************************************************************/
16
17 /** "SPI" in ASCII, used to determine if channel is open. */
18 #define SPI_B_OPEN (0x52535049ULL)
19
20 /** SPI base register access macro. */
21 #define SPI_B_REG(channel) ((R_SPI_B0_Type *) ((uint32_t) R_SPI_B0 + \
22 ((uint32_t) R_SPI_B1 - (uint32_t) R_SPI_B0) * \
23 (channel)))
24
25 #define SPI_B_DTC_MAX_TRANSFER (0x10000)
26
27 #define SPI_B_DTC_RX_TRANSFER_SETTINGS ((TRANSFER_MODE_NORMAL << TRANSFER_SETTINGS_MODE_BITS) | \
28 (TRANSFER_SIZE_1_BYTE << TRANSFER_SETTINGS_SIZE_BITS) | \
29 (TRANSFER_ADDR_MODE_FIXED << TRANSFER_SETTINGS_SRC_ADDR_BITS) | \
30 (TRANSFER_IRQ_END << TRANSFER_SETTINGS_IRQ_BITS) | \
31 (TRANSFER_ADDR_MODE_INCREMENTED << TRANSFER_SETTINGS_DEST_ADDR_BITS))
32
33 #define SPI_B_DTC_TX_TRANSFER_SETTINGS ((TRANSFER_MODE_NORMAL << TRANSFER_SETTINGS_MODE_BITS) | \
34 (TRANSFER_SIZE_1_BYTE << TRANSFER_SETTINGS_SIZE_BITS) | \
35 (TRANSFER_ADDR_MODE_INCREMENTED << TRANSFER_SETTINGS_SRC_ADDR_BITS) | \
36 (TRANSFER_IRQ_END << TRANSFER_SETTINGS_IRQ_BITS) | \
37 (TRANSFER_ADDR_MODE_FIXED << TRANSFER_SETTINGS_DEST_ADDR_BITS))
38
39 #define SPI_B_CLK_N_DIV_MULTIPLIER (512U) ///< Maximum divider for N=0
40 #define SPI_B_CLK_MAX_DIV (4096U) ///< Maximum SPI CLK divider
41 #define SPI_B_CLK_MIN_DIV (2U) ///< Minimum SPI CLK divider
42
43 #define SPI_B_PRV_SPSRC_ALL_CLEAR (0xFD800000U) ///< Clear all status flags
44
45 /***********************************************************************************************************************
46 * Typedef definitions
47 **********************************************************************************************************************/
48 #if defined(__ARMCC_VERSION) || defined(__ICCARM__)
49 typedef void (BSP_CMSE_NONSECURE_CALL * spi_prv_ns_callback)(spi_callback_args_t * p_args);
50 #elif defined(__GNUC__)
51 typedef BSP_CMSE_NONSECURE_CALL void (*volatile spi_prv_ns_callback)(spi_callback_args_t * p_args);
52 #endif
53
54 /***********************************************************************************************************************
55 * Private function declarations
56 **********************************************************************************************************************/
57 static fsp_err_t r_spi_b_transfer_config(spi_cfg_t const * const p_cfg);
58 static void r_spi_b_hw_config(spi_b_instance_ctrl_t * p_ctrl);
59 static void r_spi_b_nvic_config(spi_b_instance_ctrl_t * p_ctrl);
60
61 static void r_spi_b_bit_width_config(spi_b_instance_ctrl_t * p_ctrl);
62 static void r_spi_b_start_transfer(spi_b_instance_ctrl_t * p_ctrl);
63 static fsp_err_t r_spi_b_write_read_common(spi_ctrl_t * const p_api_ctrl,
64 void const * p_src,
65 void * p_dest,
66 uint32_t const length,
67 spi_bit_width_t const bit_width);
68
69 static void r_spi_b_receive(spi_b_instance_ctrl_t * p_ctrl);
70 static void r_spi_b_transmit(spi_b_instance_ctrl_t * p_ctrl);
71 static void r_spi_b_call_callback(spi_b_instance_ctrl_t * p_ctrl, spi_event_t event);
72
73 /***********************************************************************************************************************
74 * ISR prototypes
75 **********************************************************************************************************************/
76 void spi_b_rxi_isr(void);
77 void spi_b_txi_isr(void);
78 void spi_b_tei_isr(void);
79 void spi_b_eri_isr(void);
80
81 /***********************************************************************************************************************
82 * Private global variables
83 **********************************************************************************************************************/
84
85 /***********************************************************************************************************************
86 * Global variables
87 **********************************************************************************************************************/
88
89 /* SPI implementation of SPI interface. */
90 const spi_api_t g_spi_on_spi_b =
91 {
92 .open = R_SPI_B_Open,
93 .read = R_SPI_B_Read,
94 .write = R_SPI_B_Write,
95 .writeRead = R_SPI_B_WriteRead,
96 .close = R_SPI_B_Close,
97 .callbackSet = R_SPI_B_CallbackSet
98 };
99
100 /*******************************************************************************************************************//**
101 * @addtogroup SPI_B
102 * @{
103 **********************************************************************************************************************/
104
105 /***********************************************************************************************************************
106 * Functions
107 **********************************************************************************************************************/
108
109 /*******************************************************************************************************************//**
110 * This functions initializes a channel for SPI communication mode. Implements @ref spi_api_t::open.
111 *
112 * This function performs the following tasks:
113 * - Performs parameter checking and processes error conditions.
114 * - Configures the peripheral registers according to the configuration.
115 * - Initialize the control structure for use in other @ref SPI_API functions.
116 *
117 * @retval FSP_SUCCESS Channel initialized successfully.
118 * @retval FSP_ERR_ALREADY_OPEN Instance was already initialized.
119 * @retval FSP_ERR_ASSERTION An invalid argument was given in the configuration structure.
120 * @retval FSP_ERR_UNSUPPORTED A requested setting is not possible on this device with the current build
121 * configuration.
122 * @retval FSP_ERR_IP_CHANNEL_NOT_PRESENT The channel number is invalid.
123 * @return See @ref RENESAS_ERROR_CODES or functions called by this function for other possible return codes. This
124 * function calls: @ref transfer_api_t::open
125 * @note This function is reentrant.
126 **********************************************************************************************************************/
R_SPI_B_Open(spi_ctrl_t * p_api_ctrl,spi_cfg_t const * const p_cfg)127 fsp_err_t R_SPI_B_Open (spi_ctrl_t * p_api_ctrl, spi_cfg_t const * const p_cfg)
128 {
129 fsp_err_t err = FSP_SUCCESS;
130
131 spi_b_instance_ctrl_t * p_ctrl = (spi_b_instance_ctrl_t *) p_api_ctrl;
132
133 #if SPI_B_CFG_PARAM_CHECKING_ENABLE
134 FSP_ASSERT(NULL != p_ctrl);
135 FSP_ERROR_RETURN(SPI_B_OPEN != p_ctrl->open, FSP_ERR_ALREADY_OPEN);
136 FSP_ASSERT(NULL != p_cfg);
137 FSP_ASSERT(NULL != p_cfg->p_callback);
138 FSP_ASSERT(NULL != p_cfg->p_extend);
139 FSP_ERROR_RETURN(BSP_FEATURE_SPI_MAX_CHANNEL > p_cfg->channel, FSP_ERR_IP_CHANNEL_NOT_PRESENT);
140 FSP_ASSERT(p_cfg->rxi_irq >= 0);
141 FSP_ASSERT(p_cfg->txi_irq >= 0);
142 FSP_ASSERT(p_cfg->tei_irq >= 0);
143 FSP_ASSERT(p_cfg->eri_irq >= 0);
144
145 #if SPI_B_TRANSMIT_FROM_RXI_ISR == 1
146 spi_b_extended_cfg_t * p_extend = (spi_b_extended_cfg_t *) p_cfg->p_extend;
147
148 /* Half Duplex - Transmit Only mode is not supported when transmit interrupt is handled in the RXI ISR. */
149 FSP_ERROR_RETURN(p_extend->spi_comm != SPI_B_COMMUNICATION_TRANSMIT_ONLY, FSP_ERR_UNSUPPORTED);
150
151 /* When the TXI Interrupt is handled in the RXI ISR, a TX DTC instance must be present if there is a
152 * RX DTC instance present otherwise the TXI Interrupts will not be processed. */
153 if (p_cfg->p_transfer_rx)
154 {
155 FSP_ERROR_RETURN(0 != p_cfg->p_transfer_tx, FSP_ERR_UNSUPPORTED);
156 }
157 #endif
158 #endif
159
160 /* Configure transfers if they are provided in p_cfg. */
161 err = r_spi_b_transfer_config(p_cfg);
162 FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
163
164 /* Get the register address of the channel. */
165 p_ctrl->p_cfg = p_cfg;
166 p_ctrl->p_callback = p_cfg->p_callback;
167 p_ctrl->p_context = p_cfg->p_context;
168 p_ctrl->p_callback_memory = NULL;
169
170 p_ctrl->p_regs = SPI_B_REG(p_ctrl->p_cfg->channel);
171
172 /* Configure hardware registers according to the r_spi_api configuration structure. */
173 r_spi_b_hw_config(p_ctrl);
174
175 /* Enable interrupts in NVIC. */
176 r_spi_b_nvic_config(p_ctrl);
177
178 p_ctrl->open = SPI_B_OPEN;
179
180 return err;
181 }
182
183 /*******************************************************************************************************************//**
184 * This function receives data from a SPI device. Implements @ref spi_api_t::read.
185 *
186 * The function performs the following tasks:
187 * - Performs parameter checking and processes error conditions.
188 * - Sets up the instance to complete a SPI read operation.
189 *
190 * @retval FSP_SUCCESS Read operation successfully completed.
191 * @retval FSP_ERR_ASSERTION NULL pointer to control or destination parameters or transfer length is zero.
192 * @retval FSP_ERR_NOT_OPEN The channel has not been opened. Open channel first.
193 * @retval FSP_ERR_IN_USE A transfer is already in progress.
194 **********************************************************************************************************************/
R_SPI_B_Read(spi_ctrl_t * const p_api_ctrl,void * p_dest,uint32_t const length,spi_bit_width_t const bit_width)195 fsp_err_t R_SPI_B_Read (spi_ctrl_t * const p_api_ctrl,
196 void * p_dest,
197 uint32_t const length,
198 spi_bit_width_t const bit_width)
199 {
200 return r_spi_b_write_read_common(p_api_ctrl, NULL, p_dest, length, bit_width);
201 }
202
203 /*******************************************************************************************************************//**
204 * This function transmits data to a SPI device using the TX Only Communications Operation Mode.
205 * Implements @ref spi_api_t::write.
206 *
207 * The function performs the following tasks:
208 * - Performs parameter checking and processes error conditions.
209 * - Sets up the instance to complete a SPI write operation.
210 *
211 * @retval FSP_SUCCESS Write operation successfully completed.
212 * @retval FSP_ERR_ASSERTION NULL pointer to control or source parameters or transfer length is zero.
213 * @retval FSP_ERR_NOT_OPEN The channel has not been opened. Open the channel first.
214 * @retval FSP_ERR_IN_USE A transfer is already in progress.
215 **********************************************************************************************************************/
R_SPI_B_Write(spi_ctrl_t * const p_api_ctrl,void const * p_src,uint32_t const length,spi_bit_width_t const bit_width)216 fsp_err_t R_SPI_B_Write (spi_ctrl_t * const p_api_ctrl,
217 void const * p_src,
218 uint32_t const length,
219 spi_bit_width_t const bit_width)
220 {
221 return r_spi_b_write_read_common(p_api_ctrl, p_src, NULL, length, bit_width);
222 }
223
224 /*******************************************************************************************************************//**
225 * This function simultaneously transmits and receive data. Implements @ref spi_api_t::writeRead.
226 *
227 * The function performs the following tasks:
228 * - Performs parameter checking and processes error conditions.
229 * - Sets up the instance to complete a SPI writeRead operation.
230 *
231 * @retval FSP_SUCCESS Write operation successfully completed.
232 * @retval FSP_ERR_ASSERTION NULL pointer to control, source or destination parameters or
233 * transfer length is zero.
234 * @retval FSP_ERR_NOT_OPEN The channel has not been opened. Open the channel first.
235 * @retval FSP_ERR_IN_USE A transfer is already in progress.
236 *********************************************************************************************************************/
R_SPI_B_WriteRead(spi_ctrl_t * const p_api_ctrl,void const * p_src,void * p_dest,uint32_t const length,spi_bit_width_t const bit_width)237 fsp_err_t R_SPI_B_WriteRead (spi_ctrl_t * const p_api_ctrl,
238 void const * p_src,
239 void * p_dest,
240 uint32_t const length,
241 spi_bit_width_t const bit_width)
242 {
243 #if SPI_B_CFG_PARAM_CHECKING_ENABLE
244 FSP_ASSERT(p_src != NULL);
245 FSP_ASSERT(p_dest != NULL);
246 #endif
247
248 return r_spi_b_write_read_common(p_api_ctrl, p_src, p_dest, length, bit_width);
249 }
250
251 /*******************************************************************************************************************//**
252 * Updates the user callback and has option of providing memory for callback structure.
253 * Implements spi_api_t::callbackSet
254 *
255 * @retval FSP_SUCCESS Callback updated successfully.
256 * @retval FSP_ERR_ASSERTION A required pointer is NULL.
257 * @retval FSP_ERR_NOT_OPEN The control block has not been opened.
258 * @retval FSP_ERR_NO_CALLBACK_MEMORY p_callback is non-secure and p_callback_memory is either secure or NULL.
259 **********************************************************************************************************************/
R_SPI_B_CallbackSet(spi_ctrl_t * const p_api_ctrl,void (* p_callback)(spi_callback_args_t *),void const * const p_context,spi_callback_args_t * const p_callback_memory)260 fsp_err_t R_SPI_B_CallbackSet (spi_ctrl_t * const p_api_ctrl,
261 void ( * p_callback)(spi_callback_args_t *),
262 void const * const p_context,
263 spi_callback_args_t * const p_callback_memory)
264 {
265 spi_b_instance_ctrl_t * p_ctrl = (spi_b_instance_ctrl_t *) p_api_ctrl;
266
267 #if (SPI_B_CFG_PARAM_CHECKING_ENABLE)
268 FSP_ASSERT(p_ctrl);
269 FSP_ASSERT(p_callback);
270 FSP_ERROR_RETURN(SPI_B_OPEN == p_ctrl->open, FSP_ERR_NOT_OPEN);
271 #endif
272
273 #if BSP_TZ_SECURE_BUILD
274
275 /* Get security state of p_callback */
276 bool callback_is_secure =
277 (NULL == cmse_check_address_range((void *) p_callback, sizeof(void *), CMSE_AU_NONSECURE));
278
279 #if SPI_B_CFG_PARAM_CHECKING_ENABLE
280
281 /* In secure projects, p_callback_memory must be provided in non-secure space if p_callback is non-secure */
282 spi_callback_args_t * const p_callback_memory_checked = cmse_check_pointed_object(p_callback_memory,
283 CMSE_AU_NONSECURE);
284 FSP_ERROR_RETURN(callback_is_secure || (NULL != p_callback_memory_checked), FSP_ERR_NO_CALLBACK_MEMORY);
285 #endif
286 #endif
287
288 /* Store callback and context */
289 #if BSP_TZ_SECURE_BUILD
290 p_ctrl->p_callback = callback_is_secure ? p_callback :
291 (void (*)(spi_callback_args_t *))cmse_nsfptr_create(p_callback);
292 #else
293 p_ctrl->p_callback = p_callback;
294 #endif
295 p_ctrl->p_context = p_context;
296 p_ctrl->p_callback_memory = p_callback_memory;
297
298 return FSP_SUCCESS;
299 }
300
301 /*******************************************************************************************************************//**
302 * This function manages the closing of a channel by the following task. Implements @ref spi_api_t::close.
303 *
304 * Disables SPI operations by disabling the SPI bus.
305 * - Disables the SPI peripheral.
306 * - Disables all the associated interrupts.
307 * - Update control structure so it will not work with @ref SPI_API functions.
308 *
309 * @retval FSP_SUCCESS Channel successfully closed.
310 * @retval FSP_ERR_ASSERTION A required pointer argument is NULL.
311 * @retval FSP_ERR_NOT_OPEN The channel has not been opened. Open the channel first.
312 **********************************************************************************************************************/
R_SPI_B_Close(spi_ctrl_t * const p_api_ctrl)313 fsp_err_t R_SPI_B_Close (spi_ctrl_t * const p_api_ctrl)
314 {
315 spi_b_instance_ctrl_t * p_ctrl = (spi_b_instance_ctrl_t *) p_api_ctrl;
316
317 #if SPI_B_CFG_PARAM_CHECKING_ENABLE
318 FSP_ASSERT(NULL != p_ctrl);
319 FSP_ERROR_RETURN(SPI_B_OPEN == p_ctrl->open, FSP_ERR_NOT_OPEN);
320 #endif
321
322 p_ctrl->open = 0;
323
324 #if SPI_B_DTC_SUPPORT_ENABLE == 1
325 if (NULL != p_ctrl->p_cfg->p_transfer_rx)
326 {
327 p_ctrl->p_cfg->p_transfer_rx->p_api->close(p_ctrl->p_cfg->p_transfer_rx->p_ctrl);
328 }
329
330 if (NULL != p_ctrl->p_cfg->p_transfer_tx)
331 {
332 p_ctrl->p_cfg->p_transfer_tx->p_api->close(p_ctrl->p_cfg->p_transfer_tx->p_ctrl);
333 }
334 #endif
335
336 /* Disable interrupts in NVIC. */
337 R_BSP_IrqDisable(p_ctrl->p_cfg->txi_irq);
338 R_BSP_IrqDisable(p_ctrl->p_cfg->rxi_irq);
339 R_BSP_IrqDisable(p_ctrl->p_cfg->tei_irq);
340 R_BSP_IrqDisable(p_ctrl->p_cfg->eri_irq);
341
342 /* Disable the SPI Transfer. */
343 p_ctrl->p_regs->SPCR_b.SPE = 0U;
344
345 /* Clear the status register. */
346 p_ctrl->p_regs->SPSRC = SPI_B_PRV_SPSRC_ALL_CLEAR;
347
348 return FSP_SUCCESS;
349 }
350
351 /*******************************************************************************************************************//**
352 * Calculates the SPBR register value and the BRDV bits for a desired bitrate.
353 * If the desired bitrate is faster than the maximum bitrate, than the bitrate is set to the
354 * maximum bitrate. If the desired bitrate is slower than the minimum bitrate, than an error is returned.
355 *
356 * @param[in] bitrate Desired bitrate
357 * @param[in] clock_source SPI communication clock source to be used
358 * @param[out] spck_div Memory location to store bitrate register settings.
359 *
360 * @retval FSP_SUCCESS Valid spbr and brdv values were calculated
361 * @retval FSP_ERR_UNSUPPORTED Bitrate is not achievable
362 **********************************************************************************************************************/
R_SPI_B_CalculateBitrate(uint32_t bitrate,spi_b_clock_source_t clock_source,rspck_div_setting_t * spck_div)363 fsp_err_t R_SPI_B_CalculateBitrate (uint32_t bitrate, spi_b_clock_source_t clock_source, rspck_div_setting_t * spck_div)
364 {
365 /* desired_divider = Smallest integer greater than or equal to TCLK / bitrate. */
366 uint32_t desired_divider;
367 if (SPI_B_CLOCK_SOURCE_PCLK == clock_source)
368 {
369 desired_divider = R_FSP_SystemClockHzGet(BSP_FEATURE_SPI_CLK);
370 }
371 else
372 {
373 #if BSP_FEATURE_BSP_HAS_SCISPI_CLOCK
374 desired_divider = R_FSP_SciSpiClockHzGet();
375 #elif BSP_FEATURE_BSP_HAS_SPI_CLOCK
376 desired_divider = R_FSP_SpiClockHzGet();
377 #endif
378 }
379
380 desired_divider = (desired_divider + bitrate - 1) / bitrate;
381
382 /* Can't achieve bitrate slower than desired. */
383 if (desired_divider > SPI_B_CLK_MAX_DIV)
384 {
385 return FSP_ERR_UNSUPPORTED;
386 }
387
388 if (desired_divider < SPI_B_CLK_MIN_DIV)
389 {
390 /* Configure max bitrate (TCLK / 2) */
391 spck_div->brdv = 0;
392 spck_div->spbr = 0;
393
394 return FSP_SUCCESS;
395 }
396
397 /*
398 * Possible TCLK dividers for values of N:
399 * N = 0; div = [2,4,6,..,512]
400 * N = 1; div = [4,8,12,..,1024]
401 * N = 2; div = [8,16,32,..,2048]
402 * N = 3; div = [16,32,64,..,4096]
403 */
404 uint8_t i;
405 for (i = 0; i < 4; i++)
406 {
407 /* Select smallest value for N possible. */
408
409 /* div <= 512; N = 0
410 * 512 < div <= 1024; N=1
411 * ...
412 */
413 if (desired_divider <= (SPI_B_CLK_N_DIV_MULTIPLIER << i))
414 {
415 break;
416 }
417 }
418
419 spck_div->brdv = i & 0x03U;
420
421 /*
422 * desired_divider = 2 * (spbr + 1) * 2^i.
423 *
424 * With desired_divider and i known, solve for spbr.
425 *
426 * spbr = TCLK_DIV / (2 * 2^i) - 1
427 */
428 uint32_t spbr_divisor = (2U * (1U << i));
429
430 /* spbr = (Smallest integer greater than or equal to TCLK_DIV / (2 * 2^i)) - 1. */
431 spck_div->spbr = (uint8_t) (((desired_divider + spbr_divisor - 1U) / spbr_divisor) - 1U) & UINT8_MAX;
432
433 return FSP_SUCCESS;
434 }
435
436 /*******************************************************************************************************************//**
437 * @} (end addtogroup SPI_B)
438 **********************************************************************************************************************/
439
440 /*******************************************************************************************************************//**
441 * Private Functions
442 **********************************************************************************************************************/
443
444 /*******************************************************************************************************************//**
445 * Configure the given transfer instances for receiving and transmitting data without CPU intervention.
446 *
447 * @param p_cfg Configuration structure with references to receive and transmit transfer instances.
448 *
449 * @retval FSP_SUCCESS The given transfer instances were configured successfully.
450 * @return See @ref RENESAS_ERROR_CODES for other possible return codes. This function internally
451 * calls @ref transfer_api_t::open.
452 **********************************************************************************************************************/
r_spi_b_transfer_config(spi_cfg_t const * const p_cfg)453 static fsp_err_t r_spi_b_transfer_config (spi_cfg_t const * const p_cfg)
454 {
455 fsp_err_t err = FSP_SUCCESS;
456
457 #if SPI_B_DTC_SUPPORT_ENABLE == 1
458 const transfer_instance_t * p_transfer_tx = p_cfg->p_transfer_tx;
459 void * p_spdr = (void *) &(SPI_B_REG(p_cfg->channel)->SPDR);
460 if (p_transfer_tx)
461 {
462 p_transfer_tx->p_cfg->p_info->transfer_settings_word = SPI_B_DTC_TX_TRANSFER_SETTINGS;
463 p_transfer_tx->p_cfg->p_info->p_dest = p_spdr;
464
465 err = p_transfer_tx->p_api->open(p_transfer_tx->p_ctrl, p_transfer_tx->p_cfg);
466 FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
467 }
468
469 const transfer_instance_t * p_transfer_rx = p_cfg->p_transfer_rx;
470 if (p_transfer_rx)
471 {
472 p_transfer_rx->p_cfg->p_info->transfer_settings_word = SPI_B_DTC_RX_TRANSFER_SETTINGS;
473 p_transfer_rx->p_cfg->p_info->p_src = p_spdr;
474
475 err = p_transfer_rx->p_api->open(p_transfer_rx->p_ctrl, p_transfer_rx->p_cfg);
476
477 if ((FSP_SUCCESS != err) && p_transfer_tx)
478 {
479 p_transfer_tx->p_api->close(p_transfer_tx->p_ctrl);
480 }
481 }
482
483 #else
484 FSP_PARAMETER_NOT_USED(p_cfg);
485 #endif
486
487 return err;
488 }
489
490 /*******************************************************************************************************************//**
491 * Hardware configuration for settings given by the configuration structure.
492 *
493 * @param[in] p_ctrl pointer to control structure.
494 **********************************************************************************************************************/
r_spi_b_hw_config(spi_b_instance_ctrl_t * p_ctrl)495 static void r_spi_b_hw_config (spi_b_instance_ctrl_t * p_ctrl)
496 {
497 uint32_t spcr = 0;
498 uint32_t spcr2 = 0;
499 uint32_t spcr3 = 0;
500 uint32_t spdecr = 0;
501 uint32_t spcmd0 = 0;
502 uint32_t spdcr = 0;
503
504 #if SPI_B_TRANSMIT_FROM_RXI_ISR
505 if (p_ctrl->p_cfg->p_transfer_tx)
506 #endif
507 {
508 /* Transmit Buffer Empty IRQ must be enabled for DTC even if TRANSMIT_FROM_RXI is enabled. */
509 spcr |= R_SPI_B0_SPCR_SPTIE_Msk;
510 }
511
512 /* Enable Error interrupt. */
513 spcr |= R_SPI_B0_SPCR_SPEIE_Msk;
514
515 /* Enable Communication End interrupt. */
516 spcr |= R_SPI_B0_SPCR_CENDIE_Msk;
517
518 /* Configure Master Mode setting. */
519 spcr |= (uint32_t) (SPI_MODE_MASTER == p_ctrl->p_cfg->operating_mode) << R_SPI_B0_SPCR_MSTR_Pos;
520
521 /* Enable SCK Auto Stop setting in order to prevent RX Overflow in Master Mode */
522 spcr |= (uint32_t) (SPI_MODE_MASTER == p_ctrl->p_cfg->operating_mode) << R_SPI_B0_SPCR_SCKASE_Pos;
523
524 /* Configure CPHA setting. */
525 spcmd0 |= (uint32_t) p_ctrl->p_cfg->clk_phase << R_SPI_B0_SPCMD0_CPHA_Pos;
526
527 /* Configure CPOL setting. */
528 spcmd0 |= (uint32_t) p_ctrl->p_cfg->clk_polarity << R_SPI_B0_SPCMD0_CPOL_Pos;
529
530 /* Configure Bit Order (MSB,LSB) */
531 spcmd0 |= (uint32_t) p_ctrl->p_cfg->bit_order << R_SPI_B0_SPCMD0_LSBF_Pos;
532
533 spi_b_extended_cfg_t * p_extend = ((spi_b_extended_cfg_t *) p_ctrl->p_cfg->p_extend);
534
535 /* Set clock source */
536 spcr |= (uint32_t) (p_extend->clock_source << R_SPI_B0_SPCR_BPEN_Pos);
537
538 if (SPI_B_SSL_MODE_SPI == p_extend->spi_clksyn)
539 {
540 /* Configure SSL Level Keep Setting. */
541 spcmd0 |= (uint32_t) (!p_ctrl->p_cfg->operating_mode << R_SPI_B0_SPCMD0_SSLKP_Pos);
542 }
543 else
544 {
545 /* Configure 3-Wire Mode Setting. */
546 spcr |= R_SPI_B0_SPCR_SPMS_Msk;
547 }
548
549 if (SPI_B_COMMUNICATION_FULL_DUPLEX == p_extend->spi_comm)
550 {
551 /* Enable Receive Buffer Full interrupt. */
552 spcr |= R_SPI_B0_SPCR_SPRIE_Msk;
553 }
554
555 /* Set TX Only or Full Duplex */
556 spcr |= (uint32_t) (p_extend->spi_comm << R_SPI_B0_SPCR_TXMD_Pos);
557
558 /* Configure SSLn polarity setting. */
559 spcr3 &= ~0x0FU;
560 spcr3 |= (uint32_t) p_extend->ssl_polarity << p_extend->ssl_select;
561
562 /* Configure bitrate */
563 spcr3 |= ((uint32_t) p_extend->spck_div.spbr) << R_SPI_B0_SPCR3_SPBR_Pos;
564
565 /* Configure SSLn setting. (SSL0, SSL1, SSL2, SSL3)*/
566 spcmd0 &= ~R_SPI_B0_SPCMD0_SSLA_Msk;
567 spcmd0 |= (uint32_t) p_extend->ssl_select << R_SPI_B0_SPCMD0_SSLA_Pos;
568
569 if (SPI_B_MOSI_IDLE_VALUE_FIXING_DISABLE != p_extend->mosi_idle)
570 {
571 /* Enable MOSI value fixing */
572 spcr2 |= R_SPI_B0_SPCR2_MOIFE_Msk;
573
574 if (SPI_B_MOSI_IDLE_VALUE_FIXING_HIGH == p_extend->mosi_idle)
575 {
576 spcr2 |= R_SPI_B0_SPCR2_MOIFV_Msk;
577 }
578 }
579
580 if (SPI_B_PARITY_MODE_DISABLE != p_extend->parity)
581 {
582 /* Enable Parity Mode. */
583 spcr |= R_SPI_B0_SPCR_SPPE_Msk;
584
585 if (SPI_B_PARITY_MODE_ODD == p_extend->parity)
586 {
587 /* Configure ODD Parity Setting. */
588 spcr |= R_SPI_B0_SPCR_SPOE_Msk;
589 }
590 }
591
592 /* Configure byte swapping for 16/32-Bit mode. */
593 spdcr |= p_extend->byte_swap;
594
595 /* Configure the Bit Rate Division Setting */
596 spcmd0 |= (uint32_t) p_extend->spck_div.brdv << R_SPI_B0_SPCMD0_BRDV_Pos;
597
598 /* Enable all delay settings. */
599 if (SPI_MODE_MASTER == p_ctrl->p_cfg->operating_mode)
600 {
601 /* Note that disabling delay settings is same as setting delay to 1. */
602 spcmd0 |= (uint32_t) R_SPI_B0_SPCMD0_SPNDEN_Msk | R_SPI_B0_SPCMD0_SLNDEN_Msk | R_SPI_B0_SPCMD0_SCKDEN_Msk;
603
604 spdecr = (uint32_t) ((p_extend->spck_delay << R_SPI_B0_SPDECR_SCKDL_Pos) |
605 (p_extend->ssl_negation_delay << R_SPI_B0_SPDECR_SLNDL_Pos) |
606 (p_extend->next_access_delay << R_SPI_B0_SPDECR_SPNDL_Pos));
607 }
608
609 /* Enable the SPI module. */
610 R_BSP_MODULE_START(FSP_IP_SPI, p_ctrl->p_cfg->channel);
611
612 /* Clear the status register. */
613 p_ctrl->p_regs->SPSRC = SPI_B_PRV_SPSRC_ALL_CLEAR;
614
615 /* Write registers */
616 p_ctrl->p_regs->SPCR3 = spcr3;
617 p_ctrl->p_regs->SPDECR = spdecr;
618 p_ctrl->p_regs->SPCR2 = spcr2;
619 p_ctrl->p_regs->SPCMD0 = spcmd0;
620 p_ctrl->p_regs->SPDCR = spdcr;
621
622 /* Set all SPCR bits except MSTR */
623 p_ctrl->p_regs->SPCR = spcr & ~R_SPI_B0_SPCR_MSTR_Msk;
624
625 /* Read back SPCR to ensure 1 TCLK has passed
626 * (see Figure 30.64 Note 1 in the RA6T2 User's Manual (R01UH0951EJ0100)) */
627 p_ctrl->p_regs->SPCR;
628
629 /* Include MSTR bit */
630 p_ctrl->p_regs->SPCR = spcr;
631 }
632
633 /*******************************************************************************************************************//**
634 * Enable Receive Buffer Full, Transmit Buffer Empty, and Error Interrupts in the NVIC.
635 *
636 * @param[in] p_ctrl pointer to control structure.
637 **********************************************************************************************************************/
r_spi_b_nvic_config(spi_b_instance_ctrl_t * p_ctrl)638 static void r_spi_b_nvic_config (spi_b_instance_ctrl_t * p_ctrl)
639 {
640 R_BSP_IrqCfgEnable(p_ctrl->p_cfg->txi_irq, p_ctrl->p_cfg->txi_ipl, p_ctrl);
641 R_BSP_IrqCfgEnable(p_ctrl->p_cfg->rxi_irq, p_ctrl->p_cfg->rxi_ipl, p_ctrl);
642 R_BSP_IrqCfgEnable(p_ctrl->p_cfg->eri_irq, p_ctrl->p_cfg->eri_ipl, p_ctrl);
643
644 R_BSP_IrqCfg(p_ctrl->p_cfg->tei_irq, p_ctrl->p_cfg->tei_ipl, p_ctrl);
645
646 /* Note tei_irq is not enabled until the last data frame is transfered. */
647 }
648
649 /*******************************************************************************************************************//**
650 * Setup the bit width configuration for a transfer.
651 *
652 * @param[in] p_ctrl pointer to control structure.
653 **********************************************************************************************************************/
r_spi_b_bit_width_config(spi_b_instance_ctrl_t * p_ctrl)654 static void r_spi_b_bit_width_config (spi_b_instance_ctrl_t * p_ctrl)
655 {
656 uint32_t spcmd0 = p_ctrl->p_regs->SPCMD0;
657
658 /* Configure data length based on the selected bit width . */
659 spcmd0 &= ~R_SPI_B0_SPCMD0_SPB_Msk;
660 spcmd0 |= (uint32_t) (p_ctrl->bit_width) << R_SPI_B0_SPCMD0_SPB_Pos;
661
662 p_ctrl->p_regs->SPCMD0 = spcmd0;
663 }
664
665 /*******************************************************************************************************************//**
666 * Initiates a SPI transfer by setting the SPE bit in SPCR.
667 *
668 * @param[in] p_ctrl pointer to control structure.
669 *
670 * Note: When not using the DTC to transmit, this function pre-loads the SPI shift-register and shift-register-buffer
671 * instead of waiting for the transmit buffer empty interrupt. This is required when transmitting from the
672 * Receive Buffer Full interrupt, but it does not interfere with transmitting when using the transmit buffer empty
673 * interrupt.
674 **********************************************************************************************************************/
r_spi_b_start_transfer(spi_b_instance_ctrl_t * p_ctrl)675 static void r_spi_b_start_transfer (spi_b_instance_ctrl_t * p_ctrl)
676 {
677 /* Clear FIFOs */
678 p_ctrl->p_regs->SPFCR = 1;
679
680 #if SPI_B_TRANSMIT_FROM_RXI_ISR == 1
681 if (!p_ctrl->p_cfg->p_transfer_tx)
682 {
683 /* Handle the first two transmit empty events here because transmit interrupt may not be enabled. */
684
685 /* Critical section required so that the txi interrupt can be handled here instead of in the ISR. */
686 FSP_CRITICAL_SECTION_DEFINE;
687 FSP_CRITICAL_SECTION_ENTER;
688
689 /* Enable the SPI Transfer. */
690 p_ctrl->p_regs->SPCR_b.SPE = 1;
691
692 /* Must call transmit to kick off transfer when transmitting from rxi ISR. */
693 r_spi_b_transmit(p_ctrl); ///< First data immediately copied into the SPI shift register.
694
695 /* Second transmit significantly improves slave mode performance. */
696 r_spi_b_transmit(p_ctrl); ///< Second data copied into the SPI transmit buffer.
697
698 /* Must clear the txi IRQ status (The interrupt was handled here). */
699 R_BSP_IrqEnable(p_ctrl->p_cfg->txi_irq);
700
701 FSP_CRITICAL_SECTION_EXIT;
702 }
703 else
704 {
705 /* Enable the SPI Transfer. */
706 p_ctrl->p_regs->SPCR_b.SPE = 1;
707 }
708
709 #else
710
711 /* Enable the SPI Transfer. */
712 p_ctrl->p_regs->SPCR_b.SPE = 1;
713 #endif
714 }
715
716 /*******************************************************************************************************************//**
717 * Configures the driver state and initiates a SPI transfer for all modes of operation.
718 *
719 * @param[in] p_api_ctrl pointer to control structure.
720 * @param p_src Buffer to transmit data from.
721 * @param p_dest Buffer to store received data in.
722 * @param[in] length Number of transfers
723 * @param[in] bit_width Data frame size (8-Bit, 16-Bit, 32-Bit)
724 *
725 * @retval FSP_SUCCESS Transfer was started successfully.
726 * @retval FSP_ERR_ASSERTION An argument is invalid.
727 * @retval FSP_ERR_NOT_OPEN The instance has not been initialized.
728 * @retval FSP_ERR_IN_USE A transfer is already in progress.
729 * @return See @ref RENESAS_ERROR_CODES for other possible return codes. This function internally
730 * calls @ref transfer_api_t::reconfigure.
731 **********************************************************************************************************************/
r_spi_b_write_read_common(spi_ctrl_t * const p_api_ctrl,void const * p_src,void * p_dest,uint32_t const length,spi_bit_width_t const bit_width)732 static fsp_err_t r_spi_b_write_read_common (spi_ctrl_t * const p_api_ctrl,
733 void const * p_src,
734 void * p_dest,
735 uint32_t const length,
736 spi_bit_width_t const bit_width)
737 {
738 spi_b_instance_ctrl_t * p_ctrl = (spi_b_instance_ctrl_t *) p_api_ctrl;
739
740 #if SPI_B_CFG_PARAM_CHECKING_ENABLE
741 FSP_ASSERT(NULL != p_ctrl);
742 FSP_ERROR_RETURN(SPI_B_OPEN == p_ctrl->open, FSP_ERR_NOT_OPEN);
743 FSP_ASSERT(p_src || p_dest);
744 FSP_ASSERT(0 != length);
745 if (p_ctrl->p_cfg->p_transfer_tx || p_ctrl->p_cfg->p_transfer_rx)
746 {
747 FSP_ASSERT(length <= SPI_B_DTC_MAX_TRANSFER);
748 }
749 #endif
750
751 /* Check to ensure SPE is cleared after the last transmission.
752 * (see RA6T2 User's Manual (R01UH0951EJ0100) Figure 30.64 "Transmission flow in master mode") */
753 FSP_ERROR_RETURN(0 == p_ctrl->p_regs->SPPSR, FSP_ERR_IN_USE);
754
755 p_ctrl->p_tx_data = p_src;
756 p_ctrl->p_rx_data = p_dest;
757 p_ctrl->tx_count = 0;
758 p_ctrl->rx_count = 0;
759 p_ctrl->count = length;
760 p_ctrl->bit_width = bit_width;
761
762 #if SPI_B_DTC_SUPPORT_ENABLE == 1
763
764 /* Determine DTC transfer size */
765 transfer_size_t size;
766 if (p_ctrl->bit_width > SPI_BIT_WIDTH_16_BITS) /* Bit Widths of 17-32 bits */
767 {
768 size = TRANSFER_SIZE_4_BYTE;
769 }
770 else if (p_ctrl->bit_width > SPI_BIT_WIDTH_8_BITS) /* Bit Widths of 9-16 bits*/
771 {
772 size = TRANSFER_SIZE_2_BYTE;
773 }
774 else /* Bit Widths of 4-8 bits */
775 {
776 size = TRANSFER_SIZE_1_BYTE;
777 }
778
779 if (p_ctrl->p_cfg->p_transfer_rx)
780 {
781 /* When the rxi interrupt is called, all transfers will be finished. */
782 p_ctrl->rx_count = length;
783
784 transfer_instance_t * p_transfer_rx = (transfer_instance_t *) p_ctrl->p_cfg->p_transfer_rx;
785 transfer_info_t * p_info = p_transfer_rx->p_cfg->p_info;
786
787 /* Configure the receive DMA instance. */
788 p_info->transfer_settings_word_b.size = size;
789 p_info->length = (uint16_t) length;
790 p_info->transfer_settings_word_b.dest_addr_mode = TRANSFER_ADDR_MODE_INCREMENTED;
791 p_info->p_dest = p_dest;
792
793 if (NULL == p_dest)
794 {
795 static uint32_t dummy_rx;
796 p_info->transfer_settings_word_b.dest_addr_mode = TRANSFER_ADDR_MODE_FIXED;
797 p_info->p_dest = &dummy_rx;
798 }
799
800 fsp_err_t err = p_transfer_rx->p_api->reconfigure(p_transfer_rx->p_ctrl, p_info);
801 FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
802 }
803
804 if (p_ctrl->p_cfg->p_transfer_tx)
805 {
806 /* When the txi interrupt is called, all transfers will be finished. */
807 p_ctrl->tx_count = length;
808
809 transfer_instance_t * p_transfer_tx = (transfer_instance_t *) p_ctrl->p_cfg->p_transfer_tx;
810 transfer_info_t * p_info = p_transfer_tx->p_cfg->p_info;
811
812 /* Configure the transmit DMA instance. */
813 p_info->transfer_settings_word_b.size = size;
814 p_info->length = (uint16_t) length;
815 p_info->transfer_settings_word_b.src_addr_mode = TRANSFER_ADDR_MODE_INCREMENTED;
816 p_info->p_src = p_src;
817
818 if (NULL == p_src)
819 {
820 static uint32_t dummy_tx = 0;
821 p_info->transfer_settings_word_b.src_addr_mode = TRANSFER_ADDR_MODE_FIXED;
822 p_info->p_src = &dummy_tx;
823 }
824
825 fsp_err_t err = p_transfer_tx->p_api->reconfigure(p_transfer_tx->p_ctrl, p_info);
826 FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
827 }
828 #endif
829
830 r_spi_b_bit_width_config(p_ctrl);
831 r_spi_b_start_transfer(p_ctrl);
832
833 return FSP_SUCCESS;
834 }
835
836 /*******************************************************************************************************************//**
837 * Copy configured bit width from the SPI data register to the current rx data location.
838 * If the receive buffer is NULL, just read the SPI data register.
839 * If the total transfer length has already been received than do nothing.
840 *
841 * @param[in] p_ctrl pointer to control structure.
842 **********************************************************************************************************************/
r_spi_b_receive(spi_b_instance_ctrl_t * p_ctrl)843 static void r_spi_b_receive (spi_b_instance_ctrl_t * p_ctrl)
844 {
845 uint32_t rx_count = p_ctrl->rx_count;
846 if (rx_count == p_ctrl->count)
847 {
848 return;
849 }
850
851 if (0 == p_ctrl->p_rx_data)
852 {
853 /* Read the received data but do nothing with it. */
854 p_ctrl->p_regs->SPDR;
855 }
856 else
857 {
858 if (p_ctrl->bit_width > SPI_BIT_WIDTH_16_BITS) /* Bit Widths of 17-32 bits */
859 {
860 ((uint32_t *) (p_ctrl->p_rx_data))[rx_count] = p_ctrl->p_regs->SPDR;
861 }
862 else if (p_ctrl->bit_width > SPI_BIT_WIDTH_8_BITS) /* Bit Widths of 9-16 bits*/
863 {
864 ((uint16_t *) (p_ctrl->p_rx_data))[rx_count] = (uint16_t) p_ctrl->p_regs->SPDR;
865 }
866 else /* Bit Widths of 4-8 bits */
867 {
868 ((uint8_t *) (p_ctrl->p_rx_data))[rx_count] = (uint8_t) p_ctrl->p_regs->SPDR;
869 }
870 }
871
872 /* Clear Receive Full flag */
873 p_ctrl->p_regs->SPSRC = R_SPI_B0_SPSRC_SPRFC_Msk;
874
875 p_ctrl->rx_count = rx_count + 1;
876 }
877
878 /*******************************************************************************************************************//**
879 * Copy configured bit width from the current tx data location into the SPI data register.
880 * If the transmit buffer is NULL, than write zero to the SPI data register.
881 * If the total transfer length has already been transmitted than do nothing.
882 *
883 * @param[in] p_ctrl pointer to control structure.
884 **********************************************************************************************************************/
r_spi_b_transmit(spi_b_instance_ctrl_t * p_ctrl)885 static void r_spi_b_transmit (spi_b_instance_ctrl_t * p_ctrl)
886 {
887 uint32_t tx_count = p_ctrl->tx_count;
888 if (tx_count == p_ctrl->count)
889 {
890 return;
891 }
892
893 if (0 == p_ctrl->p_tx_data)
894 {
895 /* Transmit zero if no tx buffer present. */
896 p_ctrl->p_regs->SPDR = 0;
897 }
898 else
899 {
900 if (p_ctrl->bit_width > SPI_BIT_WIDTH_16_BITS) /* Bit Widths of 17-32 bits */
901 {
902 p_ctrl->p_regs->SPDR = ((uint32_t *) p_ctrl->p_tx_data)[tx_count];
903 }
904 else if (p_ctrl->bit_width > SPI_BIT_WIDTH_8_BITS) /* Bit Widths of 9-16 bits*/
905 {
906 p_ctrl->p_regs->SPDR = ((uint16_t *) p_ctrl->p_tx_data)[tx_count];
907 }
908 else /* Bit Widths of 4-8 bits */
909 {
910 p_ctrl->p_regs->SPDR = ((uint8_t *) p_ctrl->p_tx_data)[tx_count];
911 }
912 }
913
914 /* Clear Transmit Empty flag */
915 p_ctrl->p_regs->SPSRC = R_SPI_B0_SPSRC_SPTEFC_Msk;
916
917 p_ctrl->tx_count = tx_count + 1;
918 }
919
920 /*******************************************************************************************************************//**
921 * Calls user callback.
922 *
923 * @param[in] p_ctrl Pointer to SPI instance control block
924 * @param[in] event Event code
925 **********************************************************************************************************************/
r_spi_b_call_callback(spi_b_instance_ctrl_t * p_ctrl,spi_event_t event)926 static void r_spi_b_call_callback (spi_b_instance_ctrl_t * p_ctrl, spi_event_t event)
927 {
928 spi_callback_args_t args;
929
930 /* Store callback arguments in memory provided by user if available. This allows callback arguments to be
931 * stored in non-secure memory so they can be accessed by a non-secure callback function. */
932 spi_callback_args_t * p_args = p_ctrl->p_callback_memory;
933 if (NULL == p_args)
934 {
935 /* Store on stack */
936 p_args = &args;
937 }
938 else
939 {
940 /* Save current arguments on the stack in case this is a nested interrupt. */
941 args = *p_args;
942 }
943
944 p_args->channel = p_ctrl->p_cfg->channel;
945 p_args->event = event;
946 p_args->p_context = p_ctrl->p_context;
947
948 #if BSP_TZ_SECURE_BUILD
949
950 /* p_callback can point to a secure function or a non-secure function. */
951 if (!cmse_is_nsfptr(p_ctrl->p_callback))
952 {
953 /* If p_callback is secure, then the project does not need to change security state. */
954 p_ctrl->p_callback(p_args);
955 }
956 else
957 {
958 /* If p_callback is Non-secure, then the project must change to Non-secure state in order to call the callback. */
959 spi_prv_ns_callback p_callback = (spi_prv_ns_callback) (p_ctrl->p_callback);
960 p_callback(p_args);
961 }
962
963 #else
964
965 /* If the project is not Trustzone Secure, then it will never need to change security state in order to call the callback. */
966 p_ctrl->p_callback(p_args);
967 #endif
968 if (NULL != p_ctrl->p_callback_memory)
969 {
970 /* Restore callback memory in case this is a nested interrupt. */
971 *p_ctrl->p_callback_memory = args;
972 }
973 }
974
975 /*******************************************************************************************************************//**
976 * ISR called when data is loaded into SPI data register from the shift register.
977 **********************************************************************************************************************/
spi_b_rxi_isr(void)978 void spi_b_rxi_isr (void)
979 {
980 /* Save context if RTOS is used */
981 FSP_CONTEXT_SAVE
982
983 IRQn_Type irq = R_FSP_CurrentIrqGet();
984 R_BSP_IrqStatusClear(irq);
985
986 spi_b_instance_ctrl_t * p_ctrl = (spi_b_instance_ctrl_t *) R_FSP_IsrContextGet(irq);
987
988 r_spi_b_receive(p_ctrl);
989
990 #if SPI_B_TRANSMIT_FROM_RXI_ISR == 1
991
992 /* It is a little faster to handle the transmit buffer empty event in the receive buffer full ISR.
993 * Note that this is only possible when the instance is not using a transfer instance to receive data. */
994 r_spi_b_transmit(p_ctrl);
995 #endif
996
997 if (p_ctrl->rx_count == p_ctrl->count)
998 {
999 /* If the transmit and receive ISRs are too slow to keep up at high bitrates,
1000 * the hardware will generate an interrupt before all of the transfers are completed.
1001 * By enabling the transfer end ISR here, all of the transfers are guaranteed to be completed. */
1002 R_BSP_IrqEnableNoClear(p_ctrl->p_cfg->tei_irq);
1003 }
1004
1005 /* Restore context if RTOS is used */
1006 FSP_CONTEXT_RESTORE
1007 }
1008
1009 /*******************************************************************************************************************//**
1010 * ISR called when data is copied from the SPI data register into the SPI shift register.
1011 **********************************************************************************************************************/
spi_b_txi_isr(void)1012 void spi_b_txi_isr (void)
1013 {
1014 /* Save context if RTOS is used */
1015 FSP_CONTEXT_SAVE
1016
1017 IRQn_Type irq = R_FSP_CurrentIrqGet();
1018 R_BSP_IrqStatusClear(irq);
1019
1020 #if SPI_B_TRANSMIT_FROM_RXI_ISR == 0
1021 spi_b_instance_ctrl_t * p_ctrl = (spi_b_instance_ctrl_t *) R_FSP_IsrContextGet(irq);
1022
1023 spi_b_extended_cfg_t * p_extend = ((spi_b_extended_cfg_t *) p_ctrl->p_cfg->p_extend);
1024
1025 if (SPI_B_COMMUNICATION_TRANSMIT_ONLY == p_extend->spi_comm)
1026 {
1027 /* Only enable the transfer end ISR if there are no receive buffer full interrupts expected to be handled
1028 * after this interrupt. */
1029 if (p_ctrl->tx_count == p_ctrl->count - 1)
1030 {
1031 /* If the transmit and receive ISRs are too slow to keep up at high bitrates,
1032 * the hardware will generate an interrupt before all of the transfers are completed.
1033 * By enabling the transfer end ISR here, all of the transfers are guaranteed to be completed. */
1034 R_BSP_IrqEnable(p_ctrl->p_cfg->tei_irq);
1035 }
1036 else if (p_ctrl->p_cfg->p_transfer_tx)
1037 {
1038 /* If DMA is used to transmit data, enable the interrupt after all the data has been transfered, but do not
1039 * clear the IRQ Pending Bit. */
1040 R_BSP_IrqEnableNoClear(p_ctrl->p_cfg->tei_irq);
1041 }
1042 else
1043 {
1044 }
1045 }
1046
1047 /* Transmit happens after checking if the last transfer has been written to the transmit buffer in order
1048 * to ensure that the end interrupt is not enabled while there is data still in the transmit buffer. */
1049 r_spi_b_transmit(p_ctrl);
1050 #endif
1051
1052 /* Restore context if RTOS is used */
1053 FSP_CONTEXT_RESTORE
1054 }
1055
1056 /*******************************************************************************************************************//**
1057 * ISR called when the SPI peripheral transitions from the transferring state to the IDLE state.
1058 **********************************************************************************************************************/
spi_b_tei_isr(void)1059 void spi_b_tei_isr (void)
1060 {
1061 /* Save context if RTOS is used */
1062 FSP_CONTEXT_SAVE
1063
1064 IRQn_Type irq = R_FSP_CurrentIrqGet();
1065 R_BSP_IrqStatusClear(irq);
1066
1067 spi_b_instance_ctrl_t * p_ctrl = (spi_b_instance_ctrl_t *) R_FSP_IsrContextGet(irq);
1068
1069 if ((0 == p_ctrl->p_regs->SPSR_b.IDLNF) || (SPI_MODE_SLAVE == p_ctrl->p_cfg->operating_mode))
1070 {
1071 R_BSP_IrqDisable(irq);
1072
1073 /* Writing 0 to SPE generatates a TXI IRQ. Disable the TXI IRQ.
1074 * (See Section 38.2.1 SPI Control Register in the RA6T2 manual R01UH0886EJ0100). */
1075 R_BSP_IrqDisable(p_ctrl->p_cfg->txi_irq);
1076
1077 /* Disable the SPI Transfer. */
1078 p_ctrl->p_regs->SPCR_b.SPE = 0;
1079
1080 /* Re-enable the TXI IRQ and clear the pending IRQ. */
1081 R_BSP_IrqEnable(p_ctrl->p_cfg->txi_irq);
1082
1083 /* Signal that a transfer has completed. */
1084 r_spi_b_call_callback(p_ctrl, SPI_EVENT_TRANSFER_COMPLETE);
1085 }
1086
1087 /* Restore context if RTOS is used */
1088 FSP_CONTEXT_RESTORE
1089 }
1090
1091 /*******************************************************************************************************************//**
1092 * ISR called in the event that an error occurs (Ex: RX_OVERFLOW).
1093 **********************************************************************************************************************/
spi_b_eri_isr(void)1094 void spi_b_eri_isr (void)
1095 {
1096 /* Save context if RTOS is used */
1097 FSP_CONTEXT_SAVE
1098
1099 IRQn_Type irq = R_FSP_CurrentIrqGet();
1100 spi_b_instance_ctrl_t * p_ctrl = (spi_b_instance_ctrl_t *) R_FSP_IsrContextGet(irq);
1101
1102 /* Writing 0 to SPE generatates a TXI IRQ. Disable the TXI IRQ.
1103 * (See Section 38.2.1 SPI Control Register in the RA6T2 manual R01UH0886EJ0100). */
1104 R_BSP_IrqDisable(p_ctrl->p_cfg->txi_irq);
1105
1106 /* Disable the SPI Transfer. */
1107 p_ctrl->p_regs->SPCR_b.SPE = 0;
1108
1109 /* Re-enable the TXI IRQ and clear the pending IRQ. */
1110 R_BSP_IrqEnable(p_ctrl->p_cfg->txi_irq);
1111
1112 /* Read the status register. */
1113 uint32_t status = p_ctrl->p_regs->SPSR;
1114
1115 /* Clear the status register. */
1116 p_ctrl->p_regs->SPSRC = SPI_B_PRV_SPSRC_ALL_CLEAR;
1117
1118 /* Check if the error is a Parity Error. */
1119 if (R_SPI_B0_SPSR_PERF_Msk & status)
1120 {
1121 r_spi_b_call_callback(p_ctrl, SPI_EVENT_ERR_PARITY);
1122 }
1123
1124 /* Check if the error is a Receive Buffer Overflow Error. */
1125 if (R_SPI_B0_SPSR_OVRF_Msk & status)
1126 {
1127 r_spi_b_call_callback(p_ctrl, SPI_EVENT_ERR_READ_OVERFLOW);
1128 }
1129
1130 /* Check if the error is a Mode Fault Error. */
1131 if (R_SPI_B0_SPSR_MODF_Msk & status)
1132 {
1133 /* Check if the error is a Transmit Buffer Underflow Error. */
1134 if (R_SPI_B0_SPSR_UDRF_Msk & status)
1135 {
1136 r_spi_b_call_callback(p_ctrl, SPI_EVENT_ERR_MODE_UNDERRUN);
1137 }
1138 }
1139
1140 R_BSP_IrqStatusClear(irq);
1141
1142 /* Restore context if RTOS is used */
1143 FSP_CONTEXT_RESTORE
1144 }
1145
1146 /* End of file R_SPI. */
1147