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