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.h"
11 #include "r_spi_cfg.h"
12 
13 /***********************************************************************************************************************
14  * Macro definitions
15  **********************************************************************************************************************/
16 
17 /** "SPI" in ASCII, used to determine if channel is open. */
18 #define SPI_OPEN                        (0x52535049ULL)
19 
20 /** SPI base register access macro.  */
21 #define SPI_REG(channel)    ((R_SPI0_Type *) ((uint32_t) R_SPI0 +                       \
22                                               ((uint32_t) R_SPI1 - (uint32_t) R_SPI0) * \
23                                               (channel)))
24 
25 #define SPI_DTC_RX_TRANSFER_SETTINGS    ((TRANSFER_MODE_NORMAL << TRANSFER_SETTINGS_MODE_BITS) |         \
26                                          (TRANSFER_SIZE_1_BYTE << TRANSFER_SETTINGS_SIZE_BITS) |         \
27                                          (TRANSFER_ADDR_MODE_FIXED << TRANSFER_SETTINGS_SRC_ADDR_BITS) | \
28                                          (TRANSFER_IRQ_END << TRANSFER_SETTINGS_IRQ_BITS) |              \
29                                          (TRANSFER_ADDR_MODE_INCREMENTED << TRANSFER_SETTINGS_DEST_ADDR_BITS))
30 
31 #define SPI_DTC_TX_TRANSFER_SETTINGS    ((TRANSFER_MODE_NORMAL << TRANSFER_SETTINGS_MODE_BITS) |               \
32                                          (TRANSFER_SIZE_1_BYTE << TRANSFER_SETTINGS_SIZE_BITS) |               \
33                                          (TRANSFER_ADDR_MODE_INCREMENTED << TRANSFER_SETTINGS_SRC_ADDR_BITS) | \
34                                          (TRANSFER_IRQ_END << TRANSFER_SETTINGS_IRQ_BITS) |                    \
35                                          (TRANSFER_ADDR_MODE_FIXED << TRANSFER_SETTINGS_DEST_ADDR_BITS))
36 
37 #define SPI_CLK_N_DIV_MULTIPLIER        (512U)                              ///< Maximum divider for N=0
38 #define SPI_CLK_MAX_DIV                 (4096U)                             ///< Maximum SPI CLK divider
39 #define SPI_CLK_MIN_DIV                 (2U)                                ///< Minimum SPI CLK divider
40 
41 /* SPCMD0 Bit Field Definitions */
42 #define R_SPI0_SPCMD0_CPHA_Pos          (0U)                                ///< Clock Phase setting offset
43 #define R_SPI0_SPCMD0_CPHA_Msk          (1U << R_SPI0_SPCMD0_CPHA_Pos)      ///< Clock Phase setting mask
44 #define R_SPI0_SPCMD0_CPOL_Pos          (1U)                                ///< Clock Polarity setting offset
45 #define R_SPI0_SPCMD0_CPOL_Msk          (1U << R_SPI0_SPCMD0_CPOL_Pos)      ///< Clock Polarity setting mask
46 #define R_SPI0_SPCMD0_BRDV_Pos          (2U)                                ///< Bitrate division setting offset
47 #define R_SPI0_SPCMD0_BRDV_Msk          (0x0003U << R_SPI0_SPCMD0_BRDV_Pos) ///< Bitrate division setting mask
48 #define R_SPI0_SPCMD0_SSLA_Pos          (4U)                                ///< SSL Signal selection setting offset
49 #define R_SPI0_SPCMD0_SSLA_Msk          (0x0007U << R_SPI0_SPCMD0_SSLA_Pos) ///< SSL Signal selection setting mask
50 #define R_SPI0_SPCMD0_SSLKP_Pos         (7U)                                ///< SSL Level Keep setting offset
51 #define R_SPI0_SPCMD0_SSLKP_Msk         (1U << R_SPI0_SPCMD0_SSLKP_Pos)     ///< SSL Level Keep setting mask
52 #define R_SPI0_SPCMD0_SPB_Pos           (8U)                                ///< Bit Width setting offset
53 #define R_SPI0_SPCMD0_SPB_Msk           (0x000FU << R_SPI0_SPCMD0_SPB_Pos)  ///< Bit Width setting mask
54 #define R_SPI0_SPCMD0_LSBF_Pos          (12U)                               ///< LSB/MSB setting offset
55 #define R_SPI0_SPCMD0_LSBF_Msk          (1U << R_SPI0_SPCMD0_LSBF_Pos)      ///< LSB/MSB setting mask
56 #define R_SPI0_SPCMD0_SPNDEN_Pos        (13)                                ///< SPI Next-Access Delay Enable setting offset
57 #define R_SPI0_SPCMD0_SPNDEN_Msk        (1U << R_SPI0_SPCMD0_SPNDEN_Pos)    ///< SPI Next-Access Delay Enable setting mask
58 #define R_SPI0_SPCMD0_SLNDEN_Pos        (14)                                ///< SSL Negation Delay Setting Enable setting offset
59 #define R_SPI0_SPCMD0_SLNDEN_Msk        (1U << R_SPI0_SPCMD0_SLNDEN_Pos)    ///< SSL Negation Delay Setting Enable setting mask
60 #define R_SPI0_SPCMD0_SCKDEN_Pos        (15)                                ///< RSPCK Delay Setting Enable setting offset
61 #define R_SPI0_SPCMD0_SCKDEN_Msk        (1U << R_SPI0_SPCMD0_SCKDEN_Pos)    ///< RSPCK Delay Setting Enable setting mask
62 
63 /***********************************************************************************************************************
64  * Typedef definitions
65  **********************************************************************************************************************/
66 #if defined(__ARMCC_VERSION) || defined(__ICCARM__)
67 typedef void (BSP_CMSE_NONSECURE_CALL * spi_prv_ns_callback)(spi_callback_args_t * p_args);
68 #elif defined(__GNUC__)
69 typedef BSP_CMSE_NONSECURE_CALL void (*volatile spi_prv_ns_callback)(spi_callback_args_t * p_args);
70 #endif
71 
72 /***********************************************************************************************************************
73  * Private function declarations
74  **********************************************************************************************************************/
75 static fsp_err_t r_spi_transfer_config(spi_cfg_t const * const p_cfg);
76 static void      r_spi_hw_config(spi_instance_ctrl_t * p_ctrl);
77 static void      r_spi_nvic_config(spi_instance_ctrl_t * p_ctrl);
78 
79 static void      r_spi_bit_width_config(spi_instance_ctrl_t * p_ctrl);
80 static void      r_spi_start_transfer(spi_instance_ctrl_t * p_ctrl);
81 static fsp_err_t r_spi_write_read_common(spi_ctrl_t * const    p_api_ctrl,
82                                          void const          * p_src,
83                                          void                * p_dest,
84                                          uint32_t const        length,
85                                          spi_bit_width_t const bit_width);
86 
87 static void r_spi_receive(spi_instance_ctrl_t * p_ctrl);
88 static void r_spi_transmit(spi_instance_ctrl_t * p_ctrl);
89 static void r_spi_call_callback(spi_instance_ctrl_t * p_ctrl, spi_event_t event);
90 
91 /***********************************************************************************************************************
92  * ISR prototypes
93  **********************************************************************************************************************/
94 void spi_rxi_isr(void);
95 void spi_txi_isr(void);
96 void spi_tei_isr(void);
97 void spi_eri_isr(void);
98 
99 void spi_rx_dmac_callback(spi_instance_ctrl_t const * const p_ctrl);
100 void spi_tx_dmac_callback(spi_instance_ctrl_t const * const p_ctrl);
101 
102 /***********************************************************************************************************************
103  * Private global variables
104  **********************************************************************************************************************/
105 
106 /***********************************************************************************************************************
107  * Global variables
108  **********************************************************************************************************************/
109 
110 /* SPI implementation of SPI interface. */
111 const spi_api_t g_spi_on_spi =
112 {
113     .open        = R_SPI_Open,
114     .read        = R_SPI_Read,
115     .write       = R_SPI_Write,
116     .writeRead   = R_SPI_WriteRead,
117     .close       = R_SPI_Close,
118     .callbackSet = R_SPI_CallbackSet
119 };
120 
121 /*******************************************************************************************************************//**
122  * @addtogroup SPI
123  * @{
124  **********************************************************************************************************************/
125 
126 /***********************************************************************************************************************
127  * Functions
128  **********************************************************************************************************************/
129 
130 /*******************************************************************************************************************//**
131  * This functions initializes a channel for SPI communication mode. Implements @ref spi_api_t::open.
132  *
133  * This function performs the following tasks:
134  * - Performs parameter checking and processes error conditions.
135  * - Configures the pperipheral registers acording to the configuration.
136  * - Initialize the control structure for use in other @ref SPI_API functions.
137  *
138  * @retval     FSP_SUCCESS                     Channel initialized successfully.
139  * @retval     FSP_ERR_ALREADY_OPEN            Instance was already initialized.
140  * @retval     FSP_ERR_ASSERTION               An invalid argument was given in the configuration structure.
141  * @retval     FSP_ERR_UNSUPPORTED             A requested setting is not possible on this device with the current build
142  *                                             configuration.
143  * @retval     FSP_ERR_IP_CHANNEL_NOT_PRESENT  The channel number is invalid.
144  * @return     See @ref RENESAS_ERROR_CODES or functions called by this function for other possible return codes. This
145  *             function calls: @ref transfer_api_t::open
146  * @note       This function is reentrant.
147  **********************************************************************************************************************/
R_SPI_Open(spi_ctrl_t * p_api_ctrl,spi_cfg_t const * const p_cfg)148 fsp_err_t R_SPI_Open (spi_ctrl_t * p_api_ctrl, spi_cfg_t const * const p_cfg)
149 {
150     fsp_err_t err = FSP_SUCCESS;
151 
152     spi_instance_ctrl_t * p_ctrl = (spi_instance_ctrl_t *) p_api_ctrl;
153 
154 #if SPI_CFG_PARAM_CHECKING_ENABLE
155     FSP_ASSERT(NULL != p_ctrl);
156     FSP_ERROR_RETURN(SPI_OPEN != p_ctrl->open, FSP_ERR_ALREADY_OPEN);
157     FSP_ASSERT(NULL != p_cfg);
158     FSP_ASSERT(NULL != p_cfg->p_callback);
159     FSP_ASSERT(NULL != p_cfg->p_extend);
160     FSP_ERROR_RETURN(BSP_FEATURE_SPI_MAX_CHANNEL > p_cfg->channel, FSP_ERR_IP_CHANNEL_NOT_PRESENT);
161     FSP_ASSERT(p_cfg->tei_irq >= 0);
162     FSP_ASSERT(p_cfg->eri_irq >= 0);
163 
164     /* CPHA=0 is not supported in slave mode because of hardware limitations. Reference section 38.3.10.2(3) "Slave
165      * mode operation" in the RA6M3 manual R01UH0886EJ0100. */
166     if (SPI_MODE_SLAVE == p_cfg->operating_mode)
167     {
168         FSP_ERROR_RETURN(SPI_CLK_PHASE_EDGE_EVEN == p_cfg->clk_phase, FSP_ERR_UNSUPPORTED);
169     }
170 
171  #if BSP_FEATURE_SPI_HAS_SSL_LEVEL_KEEP == 0 || SPI_TRANSMIT_FROM_RXI_ISR == 1
172     spi_extended_cfg_t * p_extend = (spi_extended_cfg_t *) p_cfg->p_extend;
173  #endif
174  #if SPI_TRANSMIT_FROM_RXI_ISR == 1
175 
176     /* Half Duplex - Transmit Only mode is not supported when transmit interrupt is handled in the RXI ISR. */
177     FSP_ERROR_RETURN(p_extend->spi_comm != SPI_COMMUNICATION_TRANSMIT_ONLY, FSP_ERR_UNSUPPORTED);
178 
179     /* When the TXI Interrupt is handled in the RXI ISR, a TX DTC instance must be present if there is a
180      * RX DTC instance present otherwise the TXI Interrupts will not be processed. */
181     if (p_cfg->p_transfer_rx)
182     {
183         FSP_ERROR_RETURN(0 != p_cfg->p_transfer_tx, FSP_ERR_UNSUPPORTED);
184     }
185  #endif
186 
187  #if BSP_FEATURE_SPI_HAS_SSL_LEVEL_KEEP == 0
188     if ((SPI_MODE_MASTER == p_cfg->operating_mode))
189     {
190         /* 4-Wire Mode is not supported in master mode on devices without SSL_LEVEL_KEEP */
191         FSP_ERROR_RETURN(SPI_SSL_MODE_SPI != p_extend->spi_clksyn, FSP_ERR_UNSUPPORTED);
192     }
193  #endif
194 #endif
195 
196     /* Configure transfers if they are provided in p_cfg. */
197     err = r_spi_transfer_config(p_cfg);
198     FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
199 
200     /* Get the register address of the channel. */
201     p_ctrl->p_cfg             = p_cfg;
202     p_ctrl->p_callback        = p_cfg->p_callback;
203     p_ctrl->p_context         = p_cfg->p_context;
204     p_ctrl->p_callback_memory = NULL;
205 
206     p_ctrl->p_regs = SPI_REG(p_ctrl->p_cfg->channel);
207 
208     /* Configure hardware registers according to the r_spi_api configuration structure. */
209     r_spi_hw_config(p_ctrl);
210 
211     /* Enable interrupts in NVIC. */
212     r_spi_nvic_config(p_ctrl);
213 
214     p_ctrl->open = SPI_OPEN;
215 
216     return err;
217 }
218 
219 /*******************************************************************************************************************//**
220  * This function receives data from a SPI device. Implements @ref spi_api_t::read.
221  *
222  * The function performs the following tasks:
223  * - Performs parameter checking and processes error conditions.
224  * - Sets up the instance to complete a SPI read operation.
225  *
226  * @retval  FSP_SUCCESS                   Read operation successfully completed.
227  * @retval  FSP_ERR_ASSERTION             NULL pointer to control or destination parameters or transfer length is zero.
228  * @retval  FSP_ERR_NOT_OPEN              The channel has not been opened. Open channel first.
229  * @retval  FSP_ERR_IN_USE                A transfer is already in progress.
230  **********************************************************************************************************************/
R_SPI_Read(spi_ctrl_t * const p_api_ctrl,void * p_dest,uint32_t const length,spi_bit_width_t const bit_width)231 fsp_err_t R_SPI_Read (spi_ctrl_t * const    p_api_ctrl,
232                       void                * p_dest,
233                       uint32_t const        length,
234                       spi_bit_width_t const bit_width)
235 {
236     return r_spi_write_read_common(p_api_ctrl, NULL, p_dest, length, bit_width);
237 }
238 
239 /*******************************************************************************************************************//**
240  * This function transmits data to a SPI device using the TX Only Communications Operation Mode.
241  * Implements @ref spi_api_t::write.
242  *
243  * The function performs the following tasks:
244  * - Performs parameter checking and processes error conditions.
245  * - Sets up the instance to complete a SPI write operation.
246  *
247  * @retval  FSP_SUCCESS                     Write operation successfully completed.
248  * @retval  FSP_ERR_ASSERTION               NULL pointer to control or source parameters or transfer length is zero.
249  * @retval  FSP_ERR_NOT_OPEN                The channel has not been opened. Open the channel first.
250  * @retval  FSP_ERR_IN_USE                  A transfer is already in progress.
251  **********************************************************************************************************************/
R_SPI_Write(spi_ctrl_t * const p_api_ctrl,void const * p_src,uint32_t const length,spi_bit_width_t const bit_width)252 fsp_err_t R_SPI_Write (spi_ctrl_t * const    p_api_ctrl,
253                        void const          * p_src,
254                        uint32_t const        length,
255                        spi_bit_width_t const bit_width)
256 {
257     return r_spi_write_read_common(p_api_ctrl, p_src, NULL, length, bit_width);
258 }
259 
260 /*******************************************************************************************************************//**
261  * This function simultaneously transmits and receive data. Implements @ref spi_api_t::writeRead.
262  *
263  * The function performs the following tasks:
264  * - Performs parameter checking and processes error conditions.
265  * - Sets up the instance to complete a SPI writeRead operation.
266  *
267  * @retval  FSP_SUCCESS                   Write operation successfully completed.
268  * @retval  FSP_ERR_ASSERTION             NULL pointer to control, source or destination parameters or
269  *                                        transfer length is zero.
270  * @retval  FSP_ERR_NOT_OPEN              The channel has not been opened. Open the channel first.
271  * @retval  FSP_ERR_IN_USE                A transfer is already in progress.
272  *********************************************************************************************************************/
R_SPI_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)273 fsp_err_t R_SPI_WriteRead (spi_ctrl_t * const    p_api_ctrl,
274                            void const          * p_src,
275                            void                * p_dest,
276                            uint32_t const        length,
277                            spi_bit_width_t const bit_width)
278 {
279 #if SPI_CFG_PARAM_CHECKING_ENABLE
280     FSP_ASSERT(p_src != NULL);
281     FSP_ASSERT(p_dest != NULL);
282 #endif
283 
284     return r_spi_write_read_common(p_api_ctrl, p_src, p_dest, length, bit_width);
285 }
286 
287 /*******************************************************************************************************************//**
288  * Updates the user callback and has option of providing memory for callback structure.
289  * Implements spi_api_t::callbackSet
290  *
291  * @retval  FSP_SUCCESS                  Callback updated successfully.
292  * @retval  FSP_ERR_ASSERTION            A required pointer is NULL.
293  * @retval  FSP_ERR_NOT_OPEN             The control block has not been opened.
294  * @retval  FSP_ERR_NO_CALLBACK_MEMORY   p_callback is non-secure and p_callback_memory is either secure or NULL.
295  **********************************************************************************************************************/
R_SPI_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)296 fsp_err_t R_SPI_CallbackSet (spi_ctrl_t * const          p_api_ctrl,
297                              void (                    * p_callback)(spi_callback_args_t *),
298                              void const * const          p_context,
299                              spi_callback_args_t * const p_callback_memory)
300 {
301     spi_instance_ctrl_t * p_ctrl = (spi_instance_ctrl_t *) p_api_ctrl;
302 
303 #if (SPI_CFG_PARAM_CHECKING_ENABLE)
304     FSP_ASSERT(p_ctrl);
305     FSP_ASSERT(p_callback);
306     FSP_ERROR_RETURN(SPI_OPEN == p_ctrl->open, FSP_ERR_NOT_OPEN);
307 #endif
308 
309 #if BSP_TZ_SECURE_BUILD
310 
311     /* Get security state of p_callback */
312     bool callback_is_secure =
313         (NULL == cmse_check_address_range((void *) p_callback, sizeof(void *), CMSE_AU_NONSECURE));
314 
315  #if SPI_CFG_PARAM_CHECKING_ENABLE
316 
317     /* In secure projects, p_callback_memory must be provided in non-secure space if p_callback is non-secure */
318     spi_callback_args_t * const p_callback_memory_checked = cmse_check_pointed_object(p_callback_memory,
319                                                                                       CMSE_AU_NONSECURE);
320     FSP_ERROR_RETURN(callback_is_secure || (NULL != p_callback_memory_checked), FSP_ERR_NO_CALLBACK_MEMORY);
321  #endif
322 #endif
323 
324     /* Store callback and context */
325 #if BSP_TZ_SECURE_BUILD
326     p_ctrl->p_callback = callback_is_secure ? p_callback :
327                          (void (*)(spi_callback_args_t *))cmse_nsfptr_create(p_callback);
328 #else
329     p_ctrl->p_callback = p_callback;
330 #endif
331     p_ctrl->p_context         = p_context;
332     p_ctrl->p_callback_memory = p_callback_memory;
333 
334     return FSP_SUCCESS;
335 }
336 
337 /*******************************************************************************************************************//**
338  * This function manages the closing of a channel by the following task. Implements @ref spi_api_t::close.
339  *
340  * Disables SPI operations by disabling the SPI bus.
341  * - Disables the SPI peripheral.
342  * - Disables all the associated interrupts.
343  * - Update control structure so it will not work with @ref SPI_API functions.
344  *
345  * @retval  FSP_SUCCESS              Channel successfully closed.
346  * @retval  FSP_ERR_ASSERTION        A required pointer argument is NULL.
347  * @retval  FSP_ERR_NOT_OPEN         The channel has not been opened. Open the channel first.
348  **********************************************************************************************************************/
R_SPI_Close(spi_ctrl_t * const p_api_ctrl)349 fsp_err_t R_SPI_Close (spi_ctrl_t * const p_api_ctrl)
350 {
351     spi_instance_ctrl_t * p_ctrl = (spi_instance_ctrl_t *) p_api_ctrl;
352 
353 #if SPI_CFG_PARAM_CHECKING_ENABLE
354     FSP_ASSERT(NULL != p_ctrl);
355     FSP_ERROR_RETURN(SPI_OPEN == p_ctrl->open, FSP_ERR_NOT_OPEN);
356 #endif
357 
358     p_ctrl->open = 0;
359 
360 #if SPI_DMA_SUPPORT_ENABLE == 1
361     if (NULL != p_ctrl->p_cfg->p_transfer_rx)
362     {
363         p_ctrl->p_cfg->p_transfer_rx->p_api->close(p_ctrl->p_cfg->p_transfer_rx->p_ctrl);
364     }
365 
366     if (NULL != p_ctrl->p_cfg->p_transfer_tx)
367     {
368         p_ctrl->p_cfg->p_transfer_tx->p_api->close(p_ctrl->p_cfg->p_transfer_tx->p_ctrl);
369     }
370 #endif
371 
372     /* Disable interrupts in NVIC. */
373     if (p_ctrl->p_cfg->txi_irq >= 0)
374     {
375         R_BSP_IrqDisable(p_ctrl->p_cfg->txi_irq);
376     }
377 
378     if (p_ctrl->p_cfg->rxi_irq >= 0)
379     {
380         R_BSP_IrqDisable(p_ctrl->p_cfg->rxi_irq);
381     }
382 
383     R_BSP_IrqDisable(p_ctrl->p_cfg->tei_irq);
384     R_BSP_IrqDisable(p_ctrl->p_cfg->eri_irq);
385 
386     /* Disable the SPI Transfer. */
387     p_ctrl->p_regs->SPCR_b.SPE = 0U;
388 
389     /* Clear the status register. */
390 
391     /* The status register must be read before cleared. Reference section 38.2.4 SPI Status Register (SPSR) in the
392      * RA6M3 manual R01UH0886EJ0100. */
393     p_ctrl->p_regs->SPSR;
394     p_ctrl->p_regs->SPSR = 0;
395 
396     return FSP_SUCCESS;
397 }
398 
399 /*******************************************************************************************************************//**
400  * Calculates the SPBR register value and the BRDV bits for a desired bitrate.
401  * If the desired bitrate is faster than the maximum bitrate, than the bitrate is set to the
402  * maximum bitrate. If the desired bitrate is slower than the minimum bitrate, than an error is returned.
403  *
404  * @param[in] bitrate             Desired bitrate
405  * @param[out] spck_div           Memory location to store bitrate register settings.
406  *
407  * @retval FSP_SUCCESS            Valid spbr and brdv values were calculated
408  * @retval FSP_ERR_UNSUPPORTED    Bitrate is not achievable
409  **********************************************************************************************************************/
R_SPI_CalculateBitrate(uint32_t bitrate,rspck_div_setting_t * spck_div)410 fsp_err_t R_SPI_CalculateBitrate (uint32_t bitrate, rspck_div_setting_t * spck_div)
411 {
412     /* desired_divider = Smallest integer greater than or equal to SPI_CLK / bitrate. */
413     uint32_t desired_divider = (R_FSP_SystemClockHzGet(BSP_FEATURE_SPI_CLK) + bitrate - 1) / bitrate;
414 
415     /* Can't achieve bitrate slower than desired. */
416     if (desired_divider > SPI_CLK_MAX_DIV)
417     {
418         return FSP_ERR_UNSUPPORTED;
419     }
420 
421     if (desired_divider < SPI_CLK_MIN_DIV)
422     {
423         /* Configure max bitrate (SPI_CLK / 2) */
424         spck_div->brdv = 0;
425         spck_div->spbr = 0;
426 
427         return FSP_SUCCESS;
428     }
429 
430     /*
431      * Possible SPI_CLK dividers for values of N:
432      *   N = 0; div = [2,4,6,..,512]
433      *   N = 1; div = [4,8,12,..,1024]
434      *   N = 2; div = [8,16,32,..,2048]
435      *   N = 3; div = [16,32,64,..,4096]
436      */
437     uint8_t i;
438     for (i = 0; i < 4; i++)
439     {
440         /* Select smallest value for N possible. */
441 
442         /* div <= 512; N = 0
443          * 512 < div <= 1024; N=1
444          * ...
445          */
446         if (desired_divider <= (SPI_CLK_N_DIV_MULTIPLIER << i))
447         {
448             break;
449         }
450     }
451 
452     spck_div->brdv = i & 0x03U;
453 
454     /*
455      * desired_divider = 2 * (spbr + 1) * 2^i.
456      *
457      * With desired_divider and i known, solve for spbr.
458      *
459      * spbr = SPI_CLK_DIV / (2 * 2^i) - 1
460      */
461     uint32_t spbr_divisor = (2U * (1U << i));
462 
463     /* spbr = (Smallest integer greater than or equal to SPI_CLK_DIV / (2 * 2^i)) - 1. */
464     spck_div->spbr = (uint8_t) (((desired_divider + spbr_divisor - 1U) / spbr_divisor) - 1U) & UINT8_MAX;
465 
466     return FSP_SUCCESS;
467 }
468 
469 /*******************************************************************************************************************//**
470  * @} (end addtogroup SPI)
471  **********************************************************************************************************************/
472 
473 /*******************************************************************************************************************//**
474  * Private Functions
475  **********************************************************************************************************************/
476 
477 /*******************************************************************************************************************//**
478  * Configure the given transfer instances for receiving and transmitting data without CPU intervention.
479  *
480  * @param      p_cfg           Configuration structure with references to receive and transmit transfer instances.
481  *
482  * @retval     FSP_SUCCESS     The given transfer instances were configured successfully.
483  * @return                     See @ref RENESAS_ERROR_CODES for other possible return codes. This function internally
484  *                             calls @ref transfer_api_t::open.
485  **********************************************************************************************************************/
r_spi_transfer_config(spi_cfg_t const * const p_cfg)486 static fsp_err_t r_spi_transfer_config (spi_cfg_t const * const p_cfg)
487 {
488     fsp_err_t err = FSP_SUCCESS;
489 
490 #if SPI_DMA_SUPPORT_ENABLE == 1
491     const transfer_instance_t * p_transfer_tx = p_cfg->p_transfer_tx;
492     void * p_spdr = (void *) &(SPI_REG(p_cfg->channel)->SPDR);
493     if (p_transfer_tx)
494     {
495         p_transfer_tx->p_cfg->p_info->transfer_settings_word = SPI_DTC_TX_TRANSFER_SETTINGS;
496         p_transfer_tx->p_cfg->p_info->p_dest                 = p_spdr;
497 
498         err = p_transfer_tx->p_api->open(p_transfer_tx->p_ctrl, p_transfer_tx->p_cfg);
499         FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
500     }
501 
502     const transfer_instance_t * p_transfer_rx = p_cfg->p_transfer_rx;
503     if (p_transfer_rx)
504     {
505         p_transfer_rx->p_cfg->p_info->transfer_settings_word = SPI_DTC_RX_TRANSFER_SETTINGS;
506         p_transfer_rx->p_cfg->p_info->p_src = p_spdr;
507 
508         err = p_transfer_rx->p_api->open(p_transfer_rx->p_ctrl, p_transfer_rx->p_cfg);
509 
510         if ((FSP_SUCCESS != err) && p_transfer_tx)
511         {
512             p_transfer_tx->p_api->close(p_transfer_tx->p_ctrl);
513         }
514     }
515 
516 #else
517     FSP_PARAMETER_NOT_USED(p_cfg);
518 #endif
519 
520     return err;
521 }
522 
523 /*******************************************************************************************************************//**
524  * Hardware configuration for settings given by the configuration structure.
525  *
526  * @param[in]  p_ctrl          pointer to control structure.
527  **********************************************************************************************************************/
r_spi_hw_config(spi_instance_ctrl_t * p_ctrl)528 static void r_spi_hw_config (spi_instance_ctrl_t * p_ctrl)
529 {
530     uint32_t spcr   = 0;
531     uint32_t sslp   = 0;
532     uint32_t sppcr  = 0;
533     uint32_t spcr2  = 0;
534     uint32_t spckd  = 0;
535     uint32_t sslnd  = 0;
536     uint32_t spnd   = 0;
537     uint32_t spcmd0 = 0;
538     uint32_t spdcr2 = 0;
539 
540     /* Enable Receive Buffer Full interrupt. */
541     spcr |= R_SPI0_SPCR_SPRIE_Msk;
542 
543     /* The TXI interrupt is not needed when TRANSMIT_FROM_RXI_ISR optimization is enabled. */
544 #if SPI_TRANSMIT_FROM_RXI_ISR == 0
545 
546     /* Enable Transmit Buffer Empty interrupt. */
547     spcr |= R_SPI0_SPCR_SPTIE_Msk;
548 #endif
549 
550     /* Enable Error interrupt. */
551     spcr |= R_SPI0_SPCR_SPEIE_Msk;
552 
553     /* Configure Master Mode setting. */
554     spcr |= (uint32_t) (SPI_MODE_MASTER == p_ctrl->p_cfg->operating_mode) << R_SPI0_SPCR_MSTR_Pos;
555 
556     /* Enable SCK Auto Stop setting in order to prevent RX Overflow in Master Mode */
557     spcr2 |= (uint32_t) (SPI_MODE_MASTER == p_ctrl->p_cfg->operating_mode) << R_SPI0_SPCR2_SCKASE_Pos;
558 
559     /* Configure CPHA setting. */
560     spcmd0 |= (uint32_t) p_ctrl->p_cfg->clk_phase << R_SPI0_SPCMD0_CPHA_Pos;
561 
562     /* Configure CPOL setting. */
563     spcmd0 |= (uint32_t) p_ctrl->p_cfg->clk_polarity << R_SPI0_SPCMD0_CPOL_Pos;
564 
565     /* Configure Bit Order (MSB,LSB) */
566     spcmd0 |= (uint32_t) p_ctrl->p_cfg->bit_order << R_SPI0_SPCMD0_LSBF_Pos;
567 
568     if (p_ctrl->p_cfg->p_transfer_tx)
569     {
570         /* Transmit Buffer Empty IRQ must be enabled for DTC even if TRANSMIT_FROM_RXI is enabled. */
571         spcr |= R_SPI0_SPCR_SPTIE_Msk;
572     }
573 
574     spi_extended_cfg_t * p_extend = ((spi_extended_cfg_t *) p_ctrl->p_cfg->p_extend);
575 
576     if (SPI_SSL_MODE_SPI == p_extend->spi_clksyn)
577     {
578 #if BSP_FEATURE_SPI_HAS_SSL_LEVEL_KEEP == 1
579         if ((1 << p_ctrl->p_cfg->channel) & BSP_FEATURE_SPI_SSL_LEVEL_KEEP_VALID_CHANNEL_MASK)
580         {
581             /* Configure SSL Level Keep Setting. */
582             spcmd0 |= (uint32_t) (!p_ctrl->p_cfg->operating_mode << R_SPI0_SPCMD0_SSLKP_Pos);
583         }
584 #endif
585 
586         /* Configure 4-Wire Mode Setting. */
587         spcr &= ~R_SPI0_SPCR_SPMS_Msk;
588     }
589     else
590     {
591         /* Configure 3-Wire Mode Setting. */
592         spcr |= R_SPI0_SPCR_SPMS_Msk;
593     }
594 
595     /* Configure Full Duplex or TX Only Setting. */
596     spcr &= (uint32_t) ~(p_extend->spi_comm << R_SPI0_SPCR_SPRIE_Pos),
597     spcr |=
598         (uint32_t) ((p_extend->spi_comm << R_SPI0_SPCR_TXMD_Pos) |
599                     (p_extend->spi_comm << R_SPI0_SPCR_SPTIE_Pos));
600 
601     /* Configure SSLn polarity setting. */
602     sslp &= ~0x0FU;
603     sslp |= (uint32_t) p_extend->ssl_polarity << p_extend->ssl_select;
604 
605     /* Configure SSLn setting. (SSL0, SSL1, SSL2, SSL3)*/
606     spcmd0 &= ~R_SPI0_SPCMD0_SSLA_Msk;
607     spcmd0 |= (uint32_t) p_extend->ssl_select << R_SPI0_SPCMD0_SSLA_Pos;
608 
609     if (SPI_MOSI_IDLE_VALUE_FIXING_DISABLE != p_extend->mosi_idle)
610     {
611         /* Enable mosi value fixing */
612         sppcr |= R_SPI0_SPPCR_MOIFE_Msk;
613 
614         if (SPI_MOSI_IDLE_VALUE_FIXING_HIGH == p_extend->mosi_idle)
615         {
616             sppcr |= R_SPI0_SPPCR_MOIFV_Msk;
617         }
618     }
619 
620     if (SPI_PARITY_MODE_DISABLE != p_extend->parity)
621     {
622         /* Enable Parity Mode. */
623         spcr2 |= R_SPI0_SPCR2_SPPE_Msk;
624 
625         if (SPI_PARITY_MODE_ODD == p_extend->parity)
626         {
627             /* Configure ODD Parity Setting. */
628             spcr2 |= R_SPI0_SPCR2_SPOE_Msk;
629         }
630     }
631 
632     /* Configure byte swapping for 16/32-Bit mode. */
633     spdcr2 |= p_extend->byte_swap;
634 
635     /* Configure the Bit Rate Division Setting */
636     spcmd0 |= (uint32_t) p_extend->spck_div.brdv << R_SPI0_SPCMD0_BRDV_Pos;
637 
638     /* Enable all delay settings. */
639     if (SPI_MODE_MASTER == p_ctrl->p_cfg->operating_mode)
640     {
641         /* Note that disabling delay settings is same as setting delay to 1. */
642         spcmd0 |= (uint32_t) R_SPI0_SPCMD0_SPNDEN_Msk | R_SPI0_SPCMD0_SLNDEN_Msk | R_SPI0_SPCMD0_SCKDEN_Msk;
643 
644         spckd = p_extend->spck_delay;
645         sslnd = p_extend->ssl_negation_delay;
646         spnd  = p_extend->next_access_delay;
647     }
648 
649     /* Power up the SPI module. */
650     R_BSP_MODULE_START(FSP_IP_SPI, p_ctrl->p_cfg->channel);
651 
652     /* Clear the status register. */
653 
654     /* The status register must be read before cleared. Reference section 38.2.4 SPI Status Register (SPSR) in the
655      * RA6M3 manual R01UH0886EJ0100. */
656     p_ctrl->p_regs->SPSR;
657     p_ctrl->p_regs->SPSR = 0;
658 
659     /* Write registers */
660     p_ctrl->p_regs->SPCR     = (uint8_t) spcr;
661     p_ctrl->p_regs->SSLP     = (uint8_t) sslp;
662     p_ctrl->p_regs->SPPCR    = (uint8_t) sppcr;
663     p_ctrl->p_regs->SPBR     = p_extend->spck_div.spbr;
664     p_ctrl->p_regs->SPCKD    = (uint8_t) spckd;
665     p_ctrl->p_regs->SSLND    = (uint8_t) sslnd;
666     p_ctrl->p_regs->SPND     = (uint8_t) spnd;
667     p_ctrl->p_regs->SPCR2    = (uint8_t) spcr2;
668     p_ctrl->p_regs->SPCMD[0] = (uint16_t) spcmd0;
669     p_ctrl->p_regs->SPDCR2   = (uint8_t) spdcr2;
670 
671 #if BSP_FEATURE_SPI_HAS_SPCR3 == 1
672     p_ctrl->p_regs->SPCR3 = R_SPI0_SPCR3_CENDIE_Msk;
673 #endif
674 }
675 
676 /*******************************************************************************************************************//**
677  * Enable Receive Buffer Full, Transmit Buffer Empty, and Error Interrupts in the NVIC.
678  *
679  * @param[in]  p_ctrl          pointer to control structure.
680  **********************************************************************************************************************/
r_spi_nvic_config(spi_instance_ctrl_t * p_ctrl)681 static void r_spi_nvic_config (spi_instance_ctrl_t * p_ctrl)
682 {
683     if (p_ctrl->p_cfg->txi_irq >= 0)
684     {
685         R_BSP_IrqCfgEnable(p_ctrl->p_cfg->txi_irq, p_ctrl->p_cfg->txi_ipl, p_ctrl);
686     }
687 
688     if (p_ctrl->p_cfg->rxi_irq >= 0)
689     {
690         R_BSP_IrqCfgEnable(p_ctrl->p_cfg->rxi_irq, p_ctrl->p_cfg->rxi_ipl, p_ctrl);
691     }
692 
693     R_BSP_IrqCfgEnable(p_ctrl->p_cfg->eri_irq, p_ctrl->p_cfg->eri_ipl, p_ctrl);
694 
695     R_BSP_IrqCfg(p_ctrl->p_cfg->tei_irq, p_ctrl->p_cfg->tei_ipl, p_ctrl);
696 
697     /* Note tei_irq is not enabled until the last data frame is transfered. */
698 }
699 
700 /*******************************************************************************************************************//**
701  * Setup the bit width configuration for a transfer.
702  *
703  * @param[in]  p_ctrl          pointer to control structure.
704  *
705  * Note: For 8-Bit wide data frames, the devices require the SPBYT bit to enable byte level access to the
706  * data register. Although this register is not documented in some MCU hardware manuals, it does seem to be available
707  * on all of them.
708  **********************************************************************************************************************/
r_spi_bit_width_config(spi_instance_ctrl_t * p_ctrl)709 static void r_spi_bit_width_config (spi_instance_ctrl_t * p_ctrl)
710 {
711     uint32_t spdcr  = p_ctrl->p_regs->SPDCR;
712     uint32_t spcmd0 = p_ctrl->p_regs->SPCMD[0];
713 
714     if (SPI_BIT_WIDTH_16_BITS < p_ctrl->bit_width) /* Bit Widths of 20, 24 or 32 bits */
715     {
716         /* Configure Word access to data register. */
717         spdcr &= ~R_SPI0_SPDCR_SPBYT_Msk;
718         spdcr |= R_SPI0_SPDCR_SPLW_Msk;
719     }
720     else if (SPI_BIT_WIDTH_8_BITS >= p_ctrl->bit_width) /* Bit Width of 8 bits*/
721     {
722         /* Set SPBYT so 8bit transfer works with the DTC/DMAC. */
723         spdcr |= R_SPI0_SPDCR_SPBYT_Msk;
724     }
725     else                               /* Bit Widths of 9, 10, 11, 12, 13, 14, 15 or 16 bits */
726     {
727         /* Configure Half-Word access to data register. */
728         spdcr &= ~(R_SPI0_SPDCR_SPBYT_Msk | R_SPI0_SPDCR_SPLW_Msk);
729     }
730 
731     /* Configure data length based on the selected bit width . */
732     uint32_t bit_width = p_ctrl->bit_width;
733     if (bit_width > SPI_BIT_WIDTH_16_BITS)
734     {
735         bit_width = ((bit_width + 1) >> 2) - 5;
736     }
737 
738     spcmd0 &= ~R_SPI0_SPCMD0_SPB_Msk;
739     spcmd0 |= bit_width << R_SPI0_SPCMD0_SPB_Pos;
740 
741     p_ctrl->p_regs->SPDCR    = (uint8_t) spdcr;
742     p_ctrl->p_regs->SPCMD[0] = (uint16_t) spcmd0;
743 }
744 
745 /*******************************************************************************************************************//**
746  * Initiates a SPI transfer by setting the SPE bit in SPCR.
747  *
748  * @param[in]  p_ctrl          pointer to control structure.
749  *
750  * Note: When not using the DTC to transmit, this function pre-loads the SPI shift-register and shift-register-buffer
751  * instead of waiting for the transmit buffer empty interrupt. This is required when transmitting from the
752  * Receive Buffer Full interrupt, but it does not interfere with transmitting when using the transmit buffer empty
753  * interrupt.
754  **********************************************************************************************************************/
r_spi_start_transfer(spi_instance_ctrl_t * p_ctrl)755 static void r_spi_start_transfer (spi_instance_ctrl_t * p_ctrl)
756 {
757 #if SPI_TRANSMIT_FROM_RXI_ISR == 1
758     if (!p_ctrl->p_cfg->p_transfer_tx)
759     {
760         /* Handle the first two transmit empty events here because transmit interrupt may not be enabled. */
761 
762         /* Critical section required so that the txi interrupt can be handled here instead of in the ISR. */
763         FSP_CRITICAL_SECTION_DEFINE;
764         FSP_CRITICAL_SECTION_ENTER;
765 
766         /* Enable the SPI Transfer. */
767         p_ctrl->p_regs->SPCR_b.SPE = 1;
768 
769         /* Must call transmit to kick off transfer when transmitting from rxi ISR. */
770         r_spi_transmit(p_ctrl);        ///< First data immediately copied into the SPI shift register.
771 
772         /* Second transmit significantly improves slave mode performance. */
773         r_spi_transmit(p_ctrl);        ///< Second data copied into the SPI transmit buffer.
774 
775         /* Must clear the txi IRQ status (The interrupt was handled here). */
776         R_BSP_IrqEnable(p_ctrl->p_cfg->txi_irq);
777 
778         FSP_CRITICAL_SECTION_EXIT;
779     }
780     else
781     {
782         /* Enable the SPI Transfer and TX buffer empty interrupt */
783         p_ctrl->p_regs->SPCR |= R_SPI0_SPCR_SPTIE_Msk | R_SPI0_SPCR_SPE_Msk;
784     }
785 
786 #else
787 
788     /* Enable the SPI Transfer and TX buffer empty interrupt */
789     p_ctrl->p_regs->SPCR |= R_SPI0_SPCR_SPTIE_Msk | R_SPI0_SPCR_SPE_Msk;
790 #endif
791 }
792 
793 /*******************************************************************************************************************//**
794  * Configures the driver state and initiates a SPI transfer for all modes of operation.
795  *
796  * @param[in]  p_api_ctrl        pointer to control structure.
797  * @param      p_src             Buffer to transmit data from.
798  * @param      p_dest            Buffer to store received data in.
799  * @param[in]  length            Number of transfers
800  * @param[in]  bit_width         Data frame size (8-Bit, 16-Bit, 32-Bit)
801  *
802  * @retval     FSP_SUCCESS       Transfer was started successfully.
803  * @retval     FSP_ERR_ASSERTION An argument is invalid.
804  * @retval     FSP_ERR_NOT_OPEN  The instance has not been initialized.
805  * @retval     FSP_ERR_IN_USE    A transfer is already in progress.
806  * @return                       See @ref RENESAS_ERROR_CODES for other possible return codes. This function internally
807  *                               calls @ref transfer_api_t::reconfigure.
808  **********************************************************************************************************************/
r_spi_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)809 static fsp_err_t r_spi_write_read_common (spi_ctrl_t * const    p_api_ctrl,
810                                           void const          * p_src,
811                                           void                * p_dest,
812                                           uint32_t const        length,
813                                           spi_bit_width_t const bit_width)
814 {
815     spi_instance_ctrl_t * p_ctrl = (spi_instance_ctrl_t *) p_api_ctrl;
816 
817 #if SPI_CFG_PARAM_CHECKING_ENABLE
818     FSP_ASSERT(NULL != p_ctrl);
819     FSP_ERROR_RETURN(SPI_OPEN == p_ctrl->open, FSP_ERR_NOT_OPEN);
820     FSP_ASSERT(p_src || p_dest);
821     FSP_ASSERT(0 != length);
822 
823  #if SPI_DMA_SUPPORT_ENABLE
824     if (NULL != p_ctrl->p_cfg->p_transfer_rx)
825     {
826         transfer_properties_t transfer_info;
827         fsp_err_t             err = p_ctrl->p_cfg->p_transfer_rx->p_api->infoGet(p_ctrl->p_cfg->p_transfer_rx->p_ctrl,
828                                                                                  &transfer_info);
829         FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
830         FSP_ASSERT(length <= transfer_info.transfer_length_max);
831     }
832 
833     if (NULL != p_ctrl->p_cfg->p_transfer_tx)
834     {
835         transfer_properties_t transfer_info;
836         fsp_err_t             err = p_ctrl->p_cfg->p_transfer_tx->p_api->infoGet(p_ctrl->p_cfg->p_transfer_tx->p_ctrl,
837                                                                                  &transfer_info);
838         FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
839         FSP_ASSERT(length <= transfer_info.transfer_length_max);
840     }
841  #endif
842 
843     /* Reject bit width settings not compatible with R_SPI */
844     FSP_ASSERT(!((bit_width < SPI_BIT_WIDTH_8_BITS) ||
845                  ((bit_width > SPI_BIT_WIDTH_16_BITS) && ((bit_width + 1) & 0x3)) ||
846                  (bit_width == SPI_BIT_WIDTH_28_BITS)));
847 #endif
848 
849     FSP_ERROR_RETURN(0 == (p_ctrl->p_regs->SPCR & R_SPI0_SPCR_SPE_Msk), FSP_ERR_IN_USE);
850 
851     p_ctrl->p_tx_data = p_src;
852     p_ctrl->p_rx_data = p_dest;
853     p_ctrl->tx_count  = 0;
854     p_ctrl->rx_count  = 0;
855     p_ctrl->count     = length;
856     p_ctrl->bit_width = bit_width;
857 
858 #if SPI_DMA_SUPPORT_ENABLE == 1
859     if (p_ctrl->p_cfg->p_transfer_rx)
860     {
861         /* When the rxi interrupt is called, all transfers will be finished. */
862         p_ctrl->rx_count = length;
863 
864         /* Configure the receive DMA instance. */
865         if (SPI_BIT_WIDTH_16_BITS < p_ctrl->bit_width)
866         {
867             p_ctrl->p_cfg->p_transfer_rx->p_cfg->p_info->transfer_settings_word_b.size = TRANSFER_SIZE_4_BYTE;
868         }
869         else if (SPI_BIT_WIDTH_8_BITS >= p_ctrl->bit_width)
870         {
871             p_ctrl->p_cfg->p_transfer_rx->p_cfg->p_info->transfer_settings_word_b.size = TRANSFER_SIZE_1_BYTE;
872         }
873         else
874         {
875             p_ctrl->p_cfg->p_transfer_rx->p_cfg->p_info->transfer_settings_word_b.size = TRANSFER_SIZE_2_BYTE;
876         }
877 
878         p_ctrl->p_cfg->p_transfer_rx->p_cfg->p_info->transfer_settings_word_b.dest_addr_mode =
879             TRANSFER_ADDR_MODE_INCREMENTED;
880         p_ctrl->p_cfg->p_transfer_rx->p_cfg->p_info->length = (uint16_t) length;
881         p_ctrl->p_cfg->p_transfer_rx->p_cfg->p_info->p_dest = p_dest;
882 
883         if (NULL == p_dest)
884         {
885             static uint32_t dummy_rx;
886             p_ctrl->p_cfg->p_transfer_rx->p_cfg->p_info->transfer_settings_word_b.dest_addr_mode =
887                 TRANSFER_ADDR_MODE_FIXED;
888             p_ctrl->p_cfg->p_transfer_rx->p_cfg->p_info->p_dest = &dummy_rx;
889         }
890 
891         fsp_err_t err = p_ctrl->p_cfg->p_transfer_rx->p_api->reconfigure(p_ctrl->p_cfg->p_transfer_rx->p_ctrl,
892                                                                          p_ctrl->p_cfg->p_transfer_rx->p_cfg->p_info);
893 
894         FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
895     }
896 
897     if (p_ctrl->p_cfg->p_transfer_tx)
898     {
899         /* When the txi interrupt is called, all transfers will be finished. */
900         p_ctrl->tx_count = length;
901 
902         /* Configure the transmit DMA instance. */
903         if (SPI_BIT_WIDTH_16_BITS < p_ctrl->bit_width)
904         {
905             p_ctrl->p_cfg->p_transfer_tx->p_cfg->p_info->transfer_settings_word_b.size = TRANSFER_SIZE_4_BYTE;
906         }
907         else if (SPI_BIT_WIDTH_8_BITS >= p_ctrl->bit_width)
908         {
909             p_ctrl->p_cfg->p_transfer_tx->p_cfg->p_info->transfer_settings_word_b.size = TRANSFER_SIZE_1_BYTE;
910         }
911         else
912         {
913             p_ctrl->p_cfg->p_transfer_tx->p_cfg->p_info->transfer_settings_word_b.size = TRANSFER_SIZE_2_BYTE;
914         }
915 
916         p_ctrl->p_cfg->p_transfer_tx->p_cfg->p_info->transfer_settings_word_b.src_addr_mode =
917             TRANSFER_ADDR_MODE_INCREMENTED;
918         p_ctrl->p_cfg->p_transfer_tx->p_cfg->p_info->length = (uint16_t) length;
919         p_ctrl->p_cfg->p_transfer_tx->p_cfg->p_info->p_src  = p_src;
920 
921         if (NULL == p_src)
922         {
923             static uint32_t dummy_tx = 0;
924             p_ctrl->p_cfg->p_transfer_tx->p_cfg->p_info->transfer_settings_word_b.src_addr_mode =
925                 TRANSFER_ADDR_MODE_FIXED;
926             p_ctrl->p_cfg->p_transfer_tx->p_cfg->p_info->p_src = &dummy_tx;
927         }
928 
929         /* Disable the TX buffer empty interrupt before enabling transfer. */
930         p_ctrl->p_regs->SPCR_b.SPTIE = 0;
931 
932         fsp_err_t err = p_ctrl->p_cfg->p_transfer_tx->p_api->reconfigure(p_ctrl->p_cfg->p_transfer_tx->p_ctrl,
933                                                                          p_ctrl->p_cfg->p_transfer_tx->p_cfg->p_info);
934 
935         FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
936     }
937 #endif
938 
939     r_spi_bit_width_config(p_ctrl);
940     r_spi_start_transfer(p_ctrl);
941 
942     return FSP_SUCCESS;
943 }
944 
945 /*******************************************************************************************************************//**
946  * Copy configured bit width from the SPI data register to the current rx data location.
947  * If the receive buffer is NULL, just read the SPI data register.
948  * If the total transfer length has already been received than do nothing.
949  *
950  * @param[in]  p_ctrl          pointer to control structure.
951  **********************************************************************************************************************/
r_spi_receive(spi_instance_ctrl_t * p_ctrl)952 static void r_spi_receive (spi_instance_ctrl_t * p_ctrl)
953 {
954     uint32_t rx_count = p_ctrl->rx_count;
955     if (rx_count == p_ctrl->count)
956     {
957         return;
958     }
959 
960     if (0 == p_ctrl->p_rx_data)
961     {
962         /* Read the received data but do nothing with it. */
963         p_ctrl->p_regs->SPDR;
964     }
965     else
966     {
967         if (SPI_BIT_WIDTH_16_BITS < p_ctrl->bit_width)      /* Bit Widths of 20, 24 or 32 bits */
968         {
969             ((uint32_t *) (p_ctrl->p_rx_data))[rx_count] = p_ctrl->p_regs->SPDR;
970         }
971         else if (SPI_BIT_WIDTH_8_BITS >= p_ctrl->bit_width) /* Bit Width of 8 bits*/
972         {
973             ((uint8_t *) (p_ctrl->p_rx_data))[rx_count] = p_ctrl->p_regs->SPDR_BY;
974         }
975         else                                                /* Bit Widths of 9, 10, 11, 12, 13, 14, 15 or 16 bits */
976         {
977             ((uint16_t *) (p_ctrl->p_rx_data))[rx_count] = p_ctrl->p_regs->SPDR_HA;
978         }
979     }
980 
981     p_ctrl->rx_count = rx_count + 1;
982 }
983 
984 /*******************************************************************************************************************//**
985  * Copy configured bit width from the current tx data location into the SPI data register.
986  * If the transmit buffer is NULL, than write zero to the SPI data register.
987  * If the total transfer length has already been transmitted than do nothing.
988  *
989  * @param[in]  p_ctrl          pointer to control structure.
990  **********************************************************************************************************************/
r_spi_transmit(spi_instance_ctrl_t * p_ctrl)991 static void r_spi_transmit (spi_instance_ctrl_t * p_ctrl)
992 {
993     uint32_t tx_count = p_ctrl->tx_count;
994     if (tx_count == p_ctrl->count)
995     {
996         return;
997     }
998 
999     if (0 == p_ctrl->p_tx_data)
1000     {
1001         /* Transmit zero if no tx buffer present. */
1002         p_ctrl->p_regs->SPDR = 0;
1003     }
1004     else
1005     {
1006         if (SPI_BIT_WIDTH_16_BITS < p_ctrl->bit_width)      /* Bit Widths of 20, 24 or 32 bits */
1007         {
1008             p_ctrl->p_regs->SPDR = ((uint32_t *) p_ctrl->p_tx_data)[tx_count];
1009         }
1010         else if (SPI_BIT_WIDTH_8_BITS >= p_ctrl->bit_width) /* Bit Width of 8 bits*/
1011         {
1012             p_ctrl->p_regs->SPDR_BY = ((uint8_t *) p_ctrl->p_tx_data)[tx_count];
1013         }
1014         else                                                /* Bit Widths of 9, 10, 11, 12, 13, 14, 15 or 16 bits */
1015         {
1016             p_ctrl->p_regs->SPDR_HA = ((uint16_t *) p_ctrl->p_tx_data)[tx_count];
1017         }
1018     }
1019 
1020     p_ctrl->tx_count = tx_count + 1;
1021 }
1022 
1023 /*******************************************************************************************************************//**
1024  * Calls user callback.
1025  *
1026  * @param[in]     p_ctrl     Pointer to SPI instance control block
1027  * @param[in]     event      Event code
1028  **********************************************************************************************************************/
r_spi_call_callback(spi_instance_ctrl_t * p_ctrl,spi_event_t event)1029 static void r_spi_call_callback (spi_instance_ctrl_t * p_ctrl, spi_event_t event)
1030 {
1031     spi_callback_args_t args;
1032 
1033     /* Store callback arguments in memory provided by user if available.  This allows callback arguments to be
1034      * stored in non-secure memory so they can be accessed by a non-secure callback function. */
1035     spi_callback_args_t * p_args = p_ctrl->p_callback_memory;
1036     if (NULL == p_args)
1037     {
1038         /* Store on stack */
1039         p_args = &args;
1040     }
1041     else
1042     {
1043         /* Save current arguments on the stack in case this is a nested interrupt. */
1044         args = *p_args;
1045     }
1046 
1047     p_args->channel   = p_ctrl->p_cfg->channel;
1048     p_args->event     = event;
1049     p_args->p_context = p_ctrl->p_context;
1050 
1051 #if BSP_TZ_SECURE_BUILD
1052 
1053     /* p_callback can point to a secure function or a non-secure function. */
1054     if (!cmse_is_nsfptr(p_ctrl->p_callback))
1055     {
1056         /* If p_callback is secure, then the project does not need to change security state. */
1057         p_ctrl->p_callback(p_args);
1058     }
1059     else
1060     {
1061         /* If p_callback is Non-secure, then the project must change to Non-secure state in order to call the callback. */
1062         spi_prv_ns_callback p_callback = (spi_prv_ns_callback) (p_ctrl->p_callback);
1063         p_callback(p_args);
1064     }
1065 
1066 #else
1067 
1068     /* If the project is not Trustzone Secure, then it will never need to change security state in order to call the callback. */
1069     p_ctrl->p_callback(p_args);
1070 #endif
1071     if (NULL != p_ctrl->p_callback_memory)
1072     {
1073         /* Restore callback memory in case this is a nested interrupt. */
1074         *p_ctrl->p_callback_memory = args;
1075     }
1076 }
1077 
1078 /*******************************************************************************************************************//**
1079  * Callback that must be called after a RX DMAC transfer completes.
1080  *
1081  * @param[in]     p_ctrl     Pointer to SPI instance control block
1082  **********************************************************************************************************************/
spi_rx_dmac_callback(spi_instance_ctrl_t const * const p_ctrl)1083 void spi_rx_dmac_callback (spi_instance_ctrl_t const * const p_ctrl)
1084 {
1085     /* If the transmit and receive ISRs are too slow to keep up at high bitrates,
1086      * the hardware will generate an interrupt before all of the transfers are completed.
1087      * By enabling the transfer end ISR here, all of the transfers are guaranteed to be completed. */
1088     R_BSP_IrqEnableNoClear(p_ctrl->p_cfg->tei_irq);
1089 }
1090 
1091 /*******************************************************************************************************************//**
1092  * ISR called when data is loaded into SPI data register from the shift register.
1093  **********************************************************************************************************************/
spi_rxi_isr(void)1094 void spi_rxi_isr (void)
1095 {
1096     /* Save context if RTOS is used */
1097     FSP_CONTEXT_SAVE
1098 
1099     IRQn_Type irq = R_FSP_CurrentIrqGet();
1100     R_BSP_IrqStatusClear(irq);
1101 
1102     spi_instance_ctrl_t * p_ctrl = (spi_instance_ctrl_t *) R_FSP_IsrContextGet(irq);
1103 
1104     r_spi_receive(p_ctrl);
1105 
1106 #if SPI_TRANSMIT_FROM_RXI_ISR == 1
1107 
1108     /* It is a little faster to handle the transmit buffer empty event in the receive buffer full ISR.
1109      * Note that this is only possible when the instance is not using a transfer instance to receive data. */
1110     r_spi_transmit(p_ctrl);
1111 #endif
1112 
1113     if (p_ctrl->rx_count == p_ctrl->count)
1114     {
1115         /* If the transmit and receive ISRs are too slow to keep up at high bitrates,
1116          * the hardware will generate an interrupt before all of the transfers are completed.
1117          * By enabling the transfer end ISR here, all of the transfers are guaranteed to be completed. */
1118         R_BSP_IrqEnableNoClear(p_ctrl->p_cfg->tei_irq);
1119     }
1120 
1121     /* Restore context if RTOS is used */
1122     FSP_CONTEXT_RESTORE
1123 }
1124 
1125 /*******************************************************************************************************************//**
1126  * Callback that must be called after a TX DMAC transfer completes.
1127  *
1128  * @param[in]     p_ctrl     Pointer to SPI instance control block
1129  **********************************************************************************************************************/
spi_tx_dmac_callback(spi_instance_ctrl_t const * const p_ctrl)1130 void spi_tx_dmac_callback (spi_instance_ctrl_t const * const p_ctrl)
1131 {
1132 #if SPI_TRANSMIT_FROM_RXI_ISR == 0
1133     spi_extended_cfg_t * p_extend = ((spi_extended_cfg_t *) p_ctrl->p_cfg->p_extend);
1134     if (p_extend && (SPI_COMMUNICATION_TRANSMIT_ONLY == p_extend->spi_comm))
1135     {
1136         /* Only enable the transfer end ISR if there are no receive buffer full interrupts expected to be handled
1137          * after this interrupt. */
1138 
1139         /* If DMA is used to transmit data, enable the interrupt after all the data has been transfered, but do not
1140          * clear the IRQ Pending Bit. */
1141         R_BSP_IrqEnableNoClear(p_ctrl->p_cfg->tei_irq);
1142     }
1143 
1144 #else
1145     FSP_PARAMETER_NOT_USED(p_ctrl);
1146 #endif
1147 }
1148 
1149 /*******************************************************************************************************************//**
1150  * ISR called when data is copied from the SPI data register into the SPI shift register.
1151  **********************************************************************************************************************/
spi_txi_isr(void)1152 void spi_txi_isr (void)
1153 {
1154     /* Save context if RTOS is used */
1155     FSP_CONTEXT_SAVE
1156 
1157     IRQn_Type irq = R_FSP_CurrentIrqGet();
1158     R_BSP_IrqStatusClear(irq);
1159 
1160 #if SPI_TRANSMIT_FROM_RXI_ISR == 0
1161     spi_instance_ctrl_t * p_ctrl = (spi_instance_ctrl_t *) R_FSP_IsrContextGet(irq);
1162 
1163     spi_extended_cfg_t * p_extend = ((spi_extended_cfg_t *) p_ctrl->p_cfg->p_extend);
1164     if (p_extend && (SPI_COMMUNICATION_TRANSMIT_ONLY == p_extend->spi_comm))
1165     {
1166         /* Only enable the transfer end ISR if there are no receive buffer full interrupts expected to be handled
1167          * after this interrupt. */
1168         if (p_ctrl->tx_count == p_ctrl->count - 1)
1169         {
1170             /* If the transmit and receive ISRs are too slow to keep up at high bitrates,
1171              * the hardware will generate an interrupt before all of the transfers are completed.
1172              * By enabling the transfer end ISR here, all of the transfers are guaranteed to be completed. */
1173             R_BSP_IrqEnable(p_ctrl->p_cfg->tei_irq);
1174         }
1175         else if (p_ctrl->p_cfg->p_transfer_tx)
1176         {
1177             /* If DMA is used to transmit data, enable the interrupt after all the data has been transfered, but do not
1178              * clear the IRQ Pending Bit. */
1179             R_BSP_IrqEnableNoClear(p_ctrl->p_cfg->tei_irq);
1180         }
1181         else
1182         {
1183         }
1184     }
1185 
1186     /* Transmit happens after checking if the last transfer has been written to the transmit buffer in order
1187      * to ensure that the end interrupt is not enabled while there is data still in the transmit buffer. */
1188     r_spi_transmit(p_ctrl);
1189 #endif
1190 
1191     /* Restore context if RTOS is used */
1192     FSP_CONTEXT_RESTORE
1193 }
1194 
1195 /*******************************************************************************************************************//**
1196  * ISR called when the SPI peripheral transitions from the transferring state to the IDLE state.
1197  **********************************************************************************************************************/
spi_tei_isr(void)1198 void spi_tei_isr (void)
1199 {
1200     /* Save context if RTOS is used */
1201     FSP_CONTEXT_SAVE
1202 
1203     IRQn_Type irq = R_FSP_CurrentIrqGet();
1204     R_BSP_IrqStatusClear(irq);
1205 
1206     spi_instance_ctrl_t * p_ctrl = (spi_instance_ctrl_t *) R_FSP_IsrContextGet(irq);
1207 
1208     if ((0 == p_ctrl->p_regs->SPSR_b.IDLNF) || (SPI_MODE_SLAVE == p_ctrl->p_cfg->operating_mode))
1209     {
1210         R_BSP_IrqDisable(irq);
1211 
1212         /* Writing 0 to SPE generates a TXI IRQ. Disable the TXI IRQ.
1213          * (See Section 38.2.1 SPI Control Register in the RA6M3 manual R01UH0886EJ0100). */
1214         if (p_ctrl->p_cfg->txi_irq >= 0)
1215         {
1216             R_BSP_IrqDisable(p_ctrl->p_cfg->txi_irq);
1217         }
1218 
1219         /* Disable the SPI Transfer. */
1220         p_ctrl->p_regs->SPCR_b.SPE = 0;
1221 
1222         /* Re-enable the TXI IRQ and clear the pending IRQ. */
1223         if (p_ctrl->p_cfg->txi_irq >= 0)
1224         {
1225             R_BSP_IrqEnable(p_ctrl->p_cfg->txi_irq);
1226         }
1227 
1228         /* Signal that a transfer has completed. */
1229         r_spi_call_callback(p_ctrl, SPI_EVENT_TRANSFER_COMPLETE);
1230     }
1231 
1232     /* Restore context if RTOS is used */
1233     FSP_CONTEXT_RESTORE
1234 }
1235 
1236 /*******************************************************************************************************************//**
1237  * ISR called in the event that an error occurs (Ex: RX_OVERFLOW).
1238  **********************************************************************************************************************/
spi_eri_isr(void)1239 void spi_eri_isr (void)
1240 {
1241     /* Save context if RTOS is used */
1242     FSP_CONTEXT_SAVE
1243 
1244     IRQn_Type             irq    = R_FSP_CurrentIrqGet();
1245     spi_instance_ctrl_t * p_ctrl = (spi_instance_ctrl_t *) R_FSP_IsrContextGet(irq);
1246 
1247     /* Writing 0 to SPE generatates a TXI IRQ. Disable the TXI IRQ.
1248      * (See Section 38.2.1 SPI Control Register in the RA6M3 manual R01UH0886EJ0100). */
1249     if (p_ctrl->p_cfg->txi_irq >= 0)
1250     {
1251         R_BSP_IrqDisable(p_ctrl->p_cfg->txi_irq);
1252     }
1253 
1254     /* Disable the SPI Transfer. */
1255     p_ctrl->p_regs->SPCR_b.SPE = 0;
1256 
1257     /* Re-enable the TXI IRQ and clear the pending IRQ. */
1258     if (p_ctrl->p_cfg->txi_irq >= 0)
1259     {
1260         R_BSP_IrqEnable(p_ctrl->p_cfg->txi_irq);
1261     }
1262 
1263     /* Read the status register. */
1264     uint8_t status = p_ctrl->p_regs->SPSR;
1265 
1266     /* Clear the status register. */
1267     p_ctrl->p_regs->SPSR = 0;
1268 
1269     /* Check if the error is a Parity Error. */
1270     if (R_SPI0_SPSR_PERF_Msk & status)
1271     {
1272         r_spi_call_callback(p_ctrl, SPI_EVENT_ERR_PARITY);
1273     }
1274 
1275     /* Check if the error is a Receive Buffer Overflow Error. */
1276     if (R_SPI0_SPSR_OVRF_Msk & status)
1277     {
1278         r_spi_call_callback(p_ctrl, SPI_EVENT_ERR_READ_OVERFLOW);
1279     }
1280 
1281     /* Check if the error is a Mode Fault Error. */
1282     if (R_SPI0_SPSR_MODF_Msk & status)
1283     {
1284         /* Check if the error is a Transmit Buffer Underflow Error. */
1285         if (R_SPI0_SPSR_UDRF_Msk & status)
1286         {
1287             r_spi_call_callback(p_ctrl, SPI_EVENT_ERR_MODE_UNDERRUN);
1288         }
1289     }
1290 
1291     R_BSP_IrqStatusClear(irq);
1292 
1293     /* Restore context if RTOS is used */
1294     FSP_CONTEXT_RESTORE
1295 }
1296 
1297 /* End of file R_SPI. */
1298