Skip to content

Commit b9d62b4

Browse files
Thinh Le Congthenguyenyf
authored andcommitted
hal: renesas: ra: portable: rp_sci_spi: Add polling transfer support
Add polling transfer support for SCI SPI of Renesas RA Signed-off-by: Thinh Le Cong <thinh.le.xr@bp.renesas.com>
1 parent 37994a5 commit b9d62b4

File tree

3 files changed

+339
-0
lines changed

3 files changed

+339
-0
lines changed

zephyr/ra/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,5 @@ zephyr_library_sources_ifdef(CONFIG_USE_RA_FSP_I3C
1717
portable/src/rp_i3c/rp_i3c.c)
1818
zephyr_library_sources_ifdef(CONFIG_USE_RA_FSP_SCI_B_SPI
1919
portable/src/rp_sci_b_spi/rp_sci_b_spi.c)
20+
zephyr_library_sources_ifdef(CONFIG_USE_RA_FSP_SCI_SPI
21+
portable/src/rp_sci_spi/rp_sci_spi.c)
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright (c) 2020 - 2025 Renesas Electronics Corporation and/or its affiliates
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
#ifndef RP_SCI_SPI_H
8+
#define RP_SCI_SPI_H
9+
10+
/***********************************************************************************************************************
11+
* Includes
12+
**********************************************************************************************************************/
13+
#include "r_spi_api.h"
14+
#include "r_sci_spi.h"
15+
16+
/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */
17+
FSP_HEADER
18+
19+
/*****************************************************************************************************************//**
20+
* @ingroup SCI_SPI
21+
* @{
22+
********************************************************************************************************************/
23+
24+
/***********************************************************************************************************************
25+
* Macro definitions
26+
**********************************************************************************************************************/
27+
28+
/***********************************************************************************************************************
29+
* Typedef definitions
30+
**********************************************************************************************************************/
31+
32+
/***********************************************************************************************************************
33+
* Exported global variables
34+
**********************************************************************************************************************/
35+
36+
/***********************************************************************************************************************
37+
* Public Function Prototypes
38+
**********************************************************************************************************************/
39+
40+
fsp_err_t RP_SCI_SPI_WriteReadPolling(sci_spi_instance_ctrl_t * p_ctrl,
41+
const uint8_t * tx_buf,
42+
uint8_t * rx_buf,
43+
size_t length);
44+
fsp_err_t RP_SCI_SPI_WritePolling(sci_spi_instance_ctrl_t * p_ctrl, const uint8_t * tx_buf, size_t length);
45+
fsp_err_t RP_SCI_SPI_ReadPolling(sci_spi_instance_ctrl_t * p_ctrl, uint8_t * rx_buf, size_t length);
46+
fsp_err_t RP_SCI_SPI_StartTransferPolling(spi_ctrl_t * const p_api_ctrl);
47+
fsp_err_t RP_SCI_SPI_EndTransferPolling(spi_ctrl_t * const p_api_ctrl);
48+
49+
/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */
50+
FSP_FOOTER
51+
52+
#endif /* RP_SCI_SPI_H */
53+
54+
/*******************************************************************************************************************//**
55+
* @} (end ingroup SCI_SPI)
56+
**********************************************************************************************************************/
Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
/*
2+
* Copyright (c) 2020 - 2025 Renesas Electronics Corporation and/or its affiliates
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
/***********************************************************************************************************************
8+
* Includes
9+
**********************************************************************************************************************/
10+
#include "r_sci_spi.h"
11+
#include "r_sci_spi_cfg.h"
12+
13+
/***********************************************************************************************************************
14+
* Macro definitions
15+
**********************************************************************************************************************/
16+
17+
/***********************************************************************************************************************
18+
* Typedef definitions
19+
**********************************************************************************************************************/
20+
21+
/***********************************************************************************************************************
22+
* Private function declarations.
23+
**********************************************************************************************************************/
24+
static fsp_err_t rp_sci_spi_write_read_polling(spi_ctrl_t * const p_api_ctrl,
25+
uint8_t const * p_tx_data,
26+
uint8_t * p_rx_data,
27+
uint32_t const bytes);
28+
static fsp_err_t rp_sci_spi_write_one_byte_polling(sci_spi_instance_ctrl_t * p_ctrl, const uint8_t tx_byte);
29+
static fsp_err_t rp_sci_spi_read_one_byte_polling(sci_spi_instance_ctrl_t * p_ctrl, uint8_t * p_rx_byte);
30+
31+
/***********************************************************************************************************************
32+
* Functions
33+
**********************************************************************************************************************/
34+
35+
/*******************************************************************************************************************//**
36+
* @brief Perform a full-duplex SPI transfer in polling mode.
37+
*
38+
* Transmits and receives @p length bytes, blocking until each byte is completed. If either buffer is NULL,
39+
* dummy data is used for TX (0x00) and/or received data is discarded accordingly.
40+
*
41+
* @param[in] p_ctrl Pointer to the SCI SPI instance control block.
42+
* @param[in] tx_buf Pointer to transmit buffer. If NULL, 0x00 is shifted out for each byte.
43+
* @param[out] rx_buf Pointer to receive buffer. If NULL, incoming bytes are read and discarded.
44+
* @param[in] length Number of bytes to transfer.
45+
*
46+
* @pre @ref RP_SCI_SPI_StartTransferPolling must have been called to enable TE/RE and reset FIFOs.
47+
* @post No state is changed beyond data movement; to stop the peripheral call @ref RP_SCI_SPI_EndTransferPolling.
48+
*
49+
* @retval FSP_SUCCESS Operation completed.
50+
* @retval FSP_ERR_ASSERTION @p p_ctrl is NULL (when parameter checking is enabled).
51+
**********************************************************************************************************************/
52+
fsp_err_t RP_SCI_SPI_WriteReadPolling (sci_spi_instance_ctrl_t * p_ctrl,
53+
const uint8_t * tx_buf,
54+
uint8_t * rx_buf,
55+
size_t length)
56+
{
57+
#if SCI_SPI_CFG_PARAM_CHECKING_ENABLE
58+
FSP_ASSERT(NULL != p_ctrl);
59+
FSP_ASSERT(NULL != tx_buf || NULL != rx_buf);
60+
FSP_ASSERT(length > 0);
61+
#endif
62+
63+
return rp_sci_spi_write_read_polling(p_ctrl, tx_buf, rx_buf, length);
64+
}
65+
66+
/*******************************************************************************************************************//**
67+
* @brief Transmit a buffer in polling mode.
68+
*
69+
* Shifts out @p length bytes from @p tx_buf. Received bytes are read and discarded to keep the peripheral in sync.
70+
*
71+
* @param[in] p_ctrl Pointer to the SCI SPI instance control block.
72+
* @param[in] tx_buf Pointer to transmit buffer (must not be NULL).
73+
* @param[in] length Number of bytes to transmit.
74+
*
75+
* @pre @ref RP_SCI_SPI_StartTransferPolling must have been called to enable TE/RE and reset FIFOs.
76+
* @post To stop the peripheral after the session, call @ref RP_SCI_SPI_EndTransferPolling.
77+
*
78+
* @retval FSP_SUCCESS Operation completed.
79+
* @retval FSP_ERR_ASSERTION @p p_ctrl is NULL (when parameter checking is enabled).
80+
**********************************************************************************************************************/
81+
fsp_err_t RP_SCI_SPI_WritePolling (sci_spi_instance_ctrl_t * p_ctrl, const uint8_t * tx_buf, size_t length)
82+
{
83+
#if SCI_SPI_CFG_PARAM_CHECKING_ENABLE
84+
FSP_ASSERT(NULL != p_ctrl);
85+
FSP_ASSERT(NULL != tx_buf);
86+
FSP_ASSERT(length > 0);
87+
#endif
88+
89+
return rp_sci_spi_write_read_polling(p_ctrl, tx_buf, NULL, length);
90+
}
91+
92+
/*******************************************************************************************************************//**
93+
* @brief Receive a buffer in polling mode.
94+
*
95+
* Receives @p length bytes into @p rx_buf. Dummy 0x00 is shifted out on MOSI to generate clock.
96+
*
97+
* @param[in] p_ctrl Pointer to the SCI SPI instance control block.
98+
* @param[out] rx_buf Pointer to receive buffer (must not be NULL).
99+
* @param[in] length Number of bytes to receive.
100+
*
101+
* @pre @ref RP_SCI_SPI_StartTransferPolling must have been called to enable TE/RE and reset FIFOs.
102+
* @post To stop the peripheral after the session, call @ref RP_SCI_SPI_EndTransferPolling.
103+
*
104+
* @retval FSP_SUCCESS Operation completed.
105+
* @retval FSP_ERR_ASSERTION @p p_ctrl is NULL (when parameter checking is enabled).
106+
**********************************************************************************************************************/
107+
fsp_err_t RP_SCI_SPI_ReadPolling (sci_spi_instance_ctrl_t * p_ctrl, uint8_t * rx_buf, size_t length)
108+
{
109+
#if SCI_SPI_CFG_PARAM_CHECKING_ENABLE
110+
FSP_ASSERT(NULL != p_ctrl);
111+
FSP_ASSERT(NULL != rx_buf);
112+
FSP_ASSERT(length > 0);
113+
#endif
114+
115+
return rp_sci_spi_write_read_polling(p_ctrl, NULL, rx_buf, length);
116+
}
117+
118+
/*******************************************************************************************************************//**
119+
* @brief Start a SPI transfer session in polling mode.
120+
*
121+
* Resets the TX/RX FIFOs and enables the transmitter and receiver (TE/RE) bits to prepare for subsequent calls to
122+
* @ref RP_SCI_SPI_WriteReadPolling, @ref RP_SCI_SPI_WritePolling, or @ref RP_SCI_SPI_ReadPolling.
123+
*
124+
* @param[in] p_api_ctrl Generic pointer to the SCI SPI instance control block.
125+
*
126+
* @retval FSP_SUCCESS Operation completed.
127+
* @retval FSP_ERR_ASSERTION @p p_api_ctrl is NULL (when parameter checking is enabled).
128+
**********************************************************************************************************************/
129+
fsp_err_t RP_SCI_SPI_StartTransferPolling (spi_ctrl_t * const p_api_ctrl)
130+
{
131+
sci_spi_instance_ctrl_t * p_ctrl = (sci_spi_instance_ctrl_t *) p_api_ctrl;
132+
133+
#if SCI_SPI_CFG_PARAM_CHECKING_ENABLE
134+
FSP_ASSERT(NULL != p_ctrl);
135+
#endif
136+
137+
/* Set FCR. Reset FIFO/data registers. */
138+
p_ctrl->p_reg->FCR = (R_SCI0_FCR_TFRST_Msk | R_SCI0_FCR_RFRST_Msk);
139+
140+
/* Enable transfer data bit */
141+
p_ctrl->p_reg->SCR |= (R_SCI0_SCR_TE_Msk | R_SCI0_SCR_RE_Msk);
142+
143+
return FSP_SUCCESS;
144+
}
145+
146+
/*******************************************************************************************************************//**
147+
* @brief End a SPI transfer session in polling mode.
148+
*
149+
* Waits until the transmission is complete (TEND = 1) and then clears the TE/RE bits to stop the peripheral.
150+
*
151+
* @param[in] p_api_ctrl Generic pointer to the SCI SPI instance control block.
152+
*
153+
* @retval FSP_SUCCESS Operation completed.
154+
* @retval FSP_ERR_ASSERTION @p p_api_ctrl is NULL (when parameter checking is enabled).
155+
**********************************************************************************************************************/
156+
fsp_err_t RP_SCI_SPI_EndTransferPolling (spi_ctrl_t * const p_api_ctrl)
157+
{
158+
sci_spi_instance_ctrl_t * p_ctrl = (sci_spi_instance_ctrl_t *) p_api_ctrl;
159+
uint32_t scr_temp;
160+
161+
#if SCI_SPI_CFG_PARAM_CHECKING_ENABLE
162+
FSP_ASSERT(NULL != p_ctrl);
163+
#endif
164+
165+
/* Wait for transmision complete */
166+
FSP_HARDWARE_REGISTER_WAIT(p_ctrl->p_reg->SSR_b.TEND, 1U);
167+
168+
/* Disable the transfer and receive bit */
169+
scr_temp = p_ctrl->p_reg->SCR;
170+
scr_temp &= (uint32_t) ~(R_SCI0_SCR_TE_Msk | R_SCI0_SCR_RE_Msk);
171+
p_ctrl->p_reg->SCR = scr_temp;
172+
173+
return FSP_SUCCESS;
174+
}
175+
176+
/*******************************************************************************************************************//**
177+
* @brief (Internal) Write one byte in polling mode.
178+
*
179+
* Waits for @c TDRE = 1 and writes the data to TDR.
180+
*
181+
* @param[in] p_ctrl Pointer to the SCI SPI instance control block.
182+
* @param[in] tx_byte Byte to transmit.
183+
*
184+
* @retval FSP_SUCCESS Operation completed.
185+
**********************************************************************************************************************/
186+
static fsp_err_t rp_sci_spi_write_one_byte_polling (sci_spi_instance_ctrl_t * p_ctrl, const uint8_t tx_byte)
187+
{
188+
/* Wait the TDR data to empty */
189+
FSP_HARDWARE_REGISTER_WAIT(p_ctrl->p_reg->SSR_b.TDRE, 1U);
190+
191+
/* Write data to TDR */
192+
p_ctrl->p_reg->TDR = tx_byte;
193+
194+
return FSP_SUCCESS;
195+
}
196+
197+
/*******************************************************************************************************************//**
198+
* @brief (Internal) Read one byte in polling mode.
199+
*
200+
* Waits for @c RDRF = 1 and then reads a byte from RDR.
201+
*
202+
* @param[in] p_ctrl Pointer to the SCI SPI instance control block.
203+
* @param[out] p_rx_byte Pointer to destination byte.
204+
*
205+
* @retval FSP_SUCCESS Operation completed.
206+
* @retval FSP_ERR_ASSERTION @p p_rx_byte is NULL (when parameter checking is enabled).
207+
**********************************************************************************************************************/
208+
static fsp_err_t rp_sci_spi_read_one_byte_polling (sci_spi_instance_ctrl_t * p_ctrl, uint8_t * p_rx_byte)
209+
{
210+
/* Wait until data available in RDR */
211+
FSP_HARDWARE_REGISTER_WAIT(p_ctrl->p_reg->SSR_b.RDRF, 1U);
212+
213+
/* Read the data in RDR register */
214+
*p_rx_byte = (uint8_t) (p_ctrl->p_reg->RDR);
215+
216+
return FSP_SUCCESS;
217+
}
218+
219+
/*******************************************************************************************************************//**
220+
* @brief (Internal) Byte-wise full-duplex transfer loop in polling mode.
221+
*
222+
* Performs a blocking transfer of @p bytes bytes. For each iteration, the function waits for @c TDRE, writes one
223+
* byte to TDR (using 0x00 if @p p_tx_data is NULL), then waits for @c RDRF and reads one byte from RDR into
224+
* @p p_rx_data if provided, otherwise the byte is read into a dummy variable and discarded.
225+
*
226+
* @param[in] p_api_ctrl Generic pointer to the SCI SPI instance control block.
227+
* @param[in] p_tx_data Pointer to TX buffer, or NULL to transmit 0x00 per byte.
228+
* @param[out] p_rx_data Pointer to RX buffer, or NULL to discard received bytes.
229+
* @param[in] bytes Number of bytes to transfer.
230+
*
231+
* @pre TE/RE must already be set and FIFOs reset, e.g. via @ref RP_SCI_SPI_StartTransferPolling.
232+
* @note This routine is synchronous and blocks the CPU until all bytes complete. It is intended for short
233+
* transfers or bring-up; consider using interrupt/DMA driven APIs for longer transfers.
234+
*
235+
* @retval FSP_SUCCESS Operation completed.
236+
* @retval FSP_ERR_ASSERTION @p p_api_ctrl is NULL (when parameter checking is enabled).
237+
* @retval Others Any error returned by internal helpers, if extended in the future.
238+
**********************************************************************************************************************/
239+
static fsp_err_t rp_sci_spi_write_read_polling (spi_ctrl_t * const p_api_ctrl,
240+
uint8_t const * p_tx_data,
241+
uint8_t * p_rx_data,
242+
uint32_t const bytes)
243+
{
244+
sci_spi_instance_ctrl_t * p_ctrl = (sci_spi_instance_ctrl_t *) p_api_ctrl;
245+
fsp_err_t err = FSP_SUCCESS;
246+
247+
for (uint32_t i = 0; i < bytes; i++)
248+
{
249+
uint8_t tx_byte = p_tx_data ? p_tx_data[i] : 0U; /* Use dummy byte if no TX */
250+
251+
/* Write one byte */
252+
err = rp_sci_spi_write_one_byte_polling(p_ctrl, tx_byte);
253+
if (FSP_SUCCESS != err)
254+
{
255+
return err;
256+
}
257+
258+
if (p_rx_data)
259+
{
260+
/* Read one byte */
261+
err = rp_sci_spi_read_one_byte_polling(p_ctrl, &p_rx_data[i]);
262+
if (FSP_SUCCESS != err)
263+
{
264+
return err;
265+
}
266+
}
267+
else
268+
{
269+
uint8_t dummy;
270+
271+
/* Read and discard one byte */
272+
err = rp_sci_spi_read_one_byte_polling(p_ctrl, &dummy);
273+
if (FSP_SUCCESS != err)
274+
{
275+
return err;
276+
}
277+
}
278+
}
279+
280+
return FSP_SUCCESS;
281+
}

0 commit comments

Comments
 (0)