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