diff --git a/drivers/rz/README b/drivers/rz/README index 3a4ad5aa..64e6c3fd 100644 --- a/drivers/rz/README +++ b/drivers/rz/README @@ -88,3 +88,7 @@ Patch List: Impacted files: drivers/rz/fsp/src/rzg/r_gtm/r_gtm.c drivers/rz/fsp/src/rzv/r_gtm/r_gtm.c + + * Use r_transfer_api.h of rzv-fsp to support the callbackSet member of the transfer_api_t struct + Impacted files: + drivers/rz/fsp/inc/api/r_transfer_api.h diff --git a/drivers/rz/fsp/inc/api/r_transfer_api.h b/drivers/rz/fsp/inc/api/r_transfer_api.h index d25a3083..c1dd35fe 100644 --- a/drivers/rz/fsp/inc/api/r_transfer_api.h +++ b/drivers/rz/fsp/inc/api/r_transfer_api.h @@ -5,7 +5,7 @@ */ /*******************************************************************************************************************//** - * @ingroup RENESAS_INTERFACES + * @ingroup RENESAS_TRANSFER_INTERFACES * @defgroup TRANSFER_API Transfer Interface * * @brief Interface for data transfer functions. @@ -13,8 +13,6 @@ * @section TRANSFER_API_SUMMARY Summary * The transfer interface supports background data transfer (no CPU intervention). * - * Implemented by: - * - @ref DMAC_B * * @{ **********************************************************************************************************************/ @@ -49,8 +47,6 @@ FSP_HEADER **********************************************************************************************************************/ /** Transfer control block. Allocate an instance specific control block to pass into the transfer API calls. - * @par Implemented as - * - dmac_b_instance_ctrl_t */ typedef void transfer_ctrl_t; @@ -95,7 +91,8 @@ typedef enum e_transfer_size { TRANSFER_SIZE_1_BYTE = 0, ///< Each transfer transfers a 8-bit value TRANSFER_SIZE_2_BYTE = 1, ///< Each transfer transfers a 16-bit value - TRANSFER_SIZE_4_BYTE = 2 ///< Each transfer transfers a 32-bit value + TRANSFER_SIZE_4_BYTE = 2, ///< Each transfer transfers a 32-bit value + TRANSFER_SIZE_8_BYTE = 3 ///< Each transfer transfers a 64-bit value } transfer_size_t; #endif @@ -172,6 +169,16 @@ typedef enum e_transfer_irq #endif +#ifndef BSP_OVERRIDE_TRANSFER_CALLBACK_ARGS_T + +/** Callback function parameter data. */ +typedef struct st_transfer_callback_args_t +{ + void const * p_context; ///< Placeholder for user data. Set in @ref transfer_api_t::open function in ::transfer_cfg_t. +} transfer_callback_args_t; + +#endif + /** Driver specific information. */ typedef struct st_transfer_properties { @@ -266,8 +273,6 @@ typedef enum e_transfer_start_mode typedef struct st_transfer_api { /** Initial configuration. - * @par Implemented as - * - @ref R_DMAC_B_Open() * * @param[in,out] p_ctrl Pointer to control block. Must be declared by user. Elements set here. * @param[in] p_cfg Pointer to configuration structure. All elements of this structure @@ -277,8 +282,6 @@ typedef struct st_transfer_api /** Reconfigure the transfer. * Enable the transfer if p_info is valid. - * @par Implemented as - * - @ref R_DMAC_B_Reconfigure() * * @param[in,out] p_ctrl Pointer to control block. Must be declared by user. Elements set here. * @param[in] p_info Pointer to a new transfer info structure. @@ -287,8 +290,6 @@ typedef struct st_transfer_api /** Reset source address pointer, destination address pointer, and/or length, keeping all other settings the same. * Enable the transfer if p_src, p_dest, and length are valid. - * @par Implemented as - * - @ref R_DMAC_B_Reset() * * @param[in] p_ctrl Control block set in @ref transfer_api_t::open call for this transfer. * @param[in] p_src Pointer to source. Set to NULL if source pointer should not change. @@ -302,8 +303,6 @@ typedef struct st_transfer_api /** Enable transfer. Transfers occur after the activation source event (or when * @ref transfer_api_t::softwareStart is called if no peripheral event is chosen as activation source). - * @par Implemented as - * - @ref R_DMAC_B_Enable() * * @param[in] p_ctrl Control block set in @ref transfer_api_t::open call for this transfer. */ @@ -313,8 +312,6 @@ typedef struct st_transfer_api * @ref transfer_api_t::softwareStart is called if no peripheral event is chosen as the DMAC activation source). * @note If a transfer is in progress, it will be completed. Subsequent transfer requests do not cause a * transfer. - * @par Implemented as - * - @ref R_DMAC_B_Disable() * * @param[in] p_ctrl Control block set in @ref transfer_api_t::open call for this transfer. */ @@ -323,8 +320,6 @@ typedef struct st_transfer_api /** Start transfer in software. * @warning Only works if no peripheral event is chosen as the DMAC activation source. * @note Not supported for DTC. - * @par Implemented as - * - @ref R_DMAC_B_SoftwareStart() * * @param[in] p_ctrl Control block set in @ref transfer_api_t::open call for this transfer. * @param[in] mode Select mode from @ref transfer_start_mode_t. @@ -335,16 +330,12 @@ typedef struct st_transfer_api * @note Not supported for DTC. * @note Only applies for transfers started with TRANSFER_START_MODE_REPEAT. * @warning Only works if no peripheral event is chosen as the DMAC activation source. - * @par Implemented as - * - @ref R_DMAC_B_SoftwareStop() * * @param[in] p_ctrl Control block set in @ref transfer_api_t::open call for this transfer. */ fsp_err_t (* softwareStop)(transfer_ctrl_t * const p_ctrl); /** Provides information about this transfer. - * @par Implemented as - * - @ref R_DMAC_B_InfoGet() * * @param[in] p_ctrl Control block set in @ref transfer_api_t::open call for this transfer. * @param[out] p_properties Driver specific information. @@ -352,8 +343,6 @@ typedef struct st_transfer_api fsp_err_t (* infoGet)(transfer_ctrl_t * const p_ctrl, transfer_properties_t * const p_properties); /** Releases hardware lock. This allows a transfer to be reconfigured using @ref transfer_api_t::open. - * @par Implemented as - * - @ref R_DMAC_B_Close() * * @param[in] p_ctrl Control block set in @ref transfer_api_t::open call for this transfer. */ @@ -361,8 +350,6 @@ typedef struct st_transfer_api /** To update next transfer information without interruption during transfer. * Allow further transfer continuation. - * @par Implemented as - * - @ref R_DMAC_B_Reload() * * @param[in] p_ctrl Control block set in @ref transfer_api_t::open call for this transfer. * @param[in] p_src Pointer to source. Set to NULL if source pointer should not change. @@ -372,6 +359,16 @@ typedef struct st_transfer_api fsp_err_t (* reload)(transfer_ctrl_t * const p_ctrl, void const * p_src, void * p_dest, uint32_t const num_transfers); + /** Specify callback function and optional context pointer and working memory pointer. + * + * @param[in] p_ctrl Control block set in @ref transfer_api_t::open call for this transfer. + * @param[in] p_callback Callback function to register + * @param[in] p_context Pointer to send to callback function + * @param[in] p_callback_memory Pointer to volatile memory where callback structure can be allocated. + * Callback arguments allocated here are only valid during the callback. + */ + fsp_err_t (* callbackSet)(transfer_ctrl_t * const p_ctrl, void (* p_callback)(transfer_callback_args_t *), + void const * const p_context, transfer_callback_args_t * const p_callback_memory); } transfer_api_t; /** This structure encompasses everything that is needed to use an instance of this interface. */ diff --git a/drivers/rz/fsp/inc/instances/rzv/r_dmac_b.h b/drivers/rz/fsp/inc/instances/rzv/r_dmac_b.h new file mode 100644 index 00000000..40596bd3 --- /dev/null +++ b/drivers/rz/fsp/inc/instances/rzv/r_dmac_b.h @@ -0,0 +1,219 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*******************************************************************************************************************//** + * @addtogroup DMAC_B + * @{ + **********************************************************************************************************************/ + +#ifndef R_DMAC_B_H +#define R_DMAC_B_H + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ +#include "bsp_api.h" +#include "r_transfer_api.h" + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ +FSP_HEADER + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/** Max configurable number of transfers in TRANSFER_MODE_NORMAL. */ +#define DMAC_B_MAX_NORMAL_TRANSFER_LENGTH (0xFFFFFFFF) + +/** Max number of transfers per block in TRANSFER_MODE_BLOCK */ +#define DMAC_B_MAX_BLOCK_TRANSFER_LENGTH (0xFFFFFFFF) + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +typedef transfer_callback_args_t dmac_b_callback_args_t; + +/** Transfer size specifies the size of each individual transfer. */ +typedef enum e_dmac_b_transfer_size +{ + DMAC_B_TRANSFER_SIZE_1_BYTE = 0, ///< Each transfer transfers a 8-bit value. + DMAC_B_TRANSFER_SIZE_2_BYTE = 1, ///< Each transfer transfers a 16-bit value. + DMAC_B_TRANSFER_SIZE_4_BYTE = 2, ///< Each transfer transfers a 32-bit value. + DMAC_B_TRANSFER_SIZE_8_BYTE = 3, ///< Each transfer transfers a 64-bit value. + DMAC_B_TRANSFER_SIZE_16_BYTE = 4, ///< Each transfer transfers a 128-bit value. + DMAC_B_TRANSFER_SIZE_32_BYTE = 5, ///< Each transfer transfers a 256-bit value. + DMAC_B_TRANSFER_SIZE_64_BYTE = 6, ///< Each transfer transfers a 512-bit value. + DMAC_B_TRANSFER_SIZE_128_BYTE = 7, ///< Each transfer transfers a 1024-bit value. +} dmac_b_transfer_size_t; + +/** DACK output mode. See RZ/T2M hardware manual Table 14.19 DMA Transfer Request Detection Operation Setting Table. */ +typedef enum e_dmac_b_ack_mode +{ + DMAC_B_ACK_MODE_LEVEL_MODE = 1, ///< Level mode. + DMAC_B_ACK_MODE_BUS_CYCLE_MODE = 2, ///< Bus cycle mode. + DMAC_B_ACK_MODE_MASK_DACK_OUTPUT = 4, ///< Output is masked. +} dmac_b_ack_mode_t; + +#ifndef BSP_OVERRIDE_DMAC_B_EXTERNAL_DETECTION_T + +/** Detection method of the external DMA request signal. See RZ/T2M hardware manual Table 14.19 DMA Transfer Request Detection Operation Setting Table. */ +typedef enum e_dmac_b_external_detection +{ + DMAC_B_EXTERNAL_DETECTION_LOW_LEVEL = 0, ///< Low level detection. + DMAC_B_EXTERNAL_DETECTION_FALLING_EDGE = 1, ///< Falling edge detection. + DMAC_B_EXTERNAL_DETECTION_RISING_EDGE = 2, ///< Rising edge detection. + DMAC_B_EXTERNAL_DETECTION_FALLING_RISING_EDGE = 3, ///< Falling/Rising edge detection. +} dmac_b_external_detection_t; + +#endif + +/** Detection method of the internal DMA request signal. See RZ/T2M hardware manual Table 14.19 DMA Transfer Request Detection Operation Setting Table. */ +typedef enum e_dmac_b_internal_detection +{ + DMAC_B_INTERNAL_DETECTION_NO_DETECTION = 0, ///< Not using hardware detection. + DMAC_B_INTERNAL_DETECTION_FALLING_EDGE = 1, ///< Falling edge detection. + DMAC_B_INTERNAL_DETECTION_RISING_EDGE = 2, ///< Rising edge detection. + DMAC_B_INTERNAL_DETECTION_LOW_LEVEL = 5, ///< Low level detection. + DMAC_B_INTERNAL_DETECTION_HIGH_LEVEL = 6, ///< High level detection. +} dmac_b_internal_detection_t; + +/** DMA activation request source select. See RZ/T2M hardware manual Table 14.19 DMA Transfer Request Detection Operation Setting Table. */ +typedef enum e_dmac_b_request_direction +{ + DMAC_B_REQUEST_DIRECTION_SOURCE_MODULE = 0, ///< Requested by a transfer source module. + DMAC_B_REQUEST_DIRECTION_DESTINATION_MODULE = 1, ///< Requested by a transfer destination module. +} dmac_b_request_direction_t; + +/** Select the Next register set to be executed next. */ +typedef enum e_dmac_b_continuous_setting +{ + DMAC_B_CONTINUOUS_SETTING_TRANSFER_ONCE = 0x0, ///< Transfer only once using the Next0 register set. + DMAC_B_CONTINUOUS_SETTING_TRANSFER_ALTERNATELY = 0x3, ///< Transfers are performed alternately with the Next0 register set and the Next1 register set. +} dmac_b_continuous_setting_t; + +/** Register set settings. */ +typedef struct st_dmac_b_register_set_setting_t +{ + void const * p_src; ///< Source pointer. + void * p_dest; ///< Destination pointer. + uint32_t length; ///< Transfer byte. +} dmac_b_register_set_setting_t; + +/** DMAC channel scheduling. */ +typedef enum e_dmac_b_channel_scheduling +{ + DMAC_B_CHANNEL_SCHEDULING_FIXED = 0, ///< Fixed priority mode. + DMAC_B_CHANNEL_SCHEDULING_ROUND_ROBIN = 1, ///< Round-robin mode. +} dmac_b_channel_scheduling_t; + +/** DMAC mode setting. */ +typedef enum e_dmac_b_mode_select +{ + DMAC_B_MODE_SELECT_REGISTER = 0, ///< Register mode. + DMAC_B_MODE_SELECT_LINK = 1, ///< Link mode. +} dmac_b_mode_select_t; + +/** Control block used by driver. DO NOT INITIALIZE - this structure will be initialized in @ref transfer_api_t::open. */ +typedef struct st_dmac_b_instance_ctrl +{ + uint32_t open; // Driver ID + + transfer_cfg_t const * p_cfg; + + /* Pointer to base register. */ + R_DMAC_B0_Type * p_reg; + + void (* p_callback)(dmac_b_callback_args_t *); // Pointer to callback + dmac_b_callback_args_t * p_callback_memory; // Pointer to optional callback argument memory + void const * p_context; // Pointer to context to be passed into callback function +} dmac_b_instance_ctrl_t; + +/** DMAC transfer configuration extension. This extension is required. */ +typedef struct st_dmac_b_extended_cfg +{ + uint8_t unit; ///< Unit number + uint8_t channel; ///< Channel number + IRQn_Type dmac_int_irq; ///< DMAC interrupt number + uint8_t dmac_int_ipl; ///< DMAC interrupt priority + + /** Select which event will trigger the transfer. */ + dmac_trigger_event_t activation_source; + dmac_b_ack_mode_t ack_mode; ///< DACK output mode + dmac_b_external_input_pin_t dreq_input_pin; ///< DREQ input pin name + dmac_b_external_output_pin_t ack_output_pin; ///< DACK output pin name + dmac_b_external_output_pin_t tend_output_pin; ///< TEND output pin name + dmac_b_external_detection_t external_detection_mode; ///< DMAC request detection method for external pin + dmac_b_internal_detection_t internal_detection_mode; ///< DMAC request detection method for internal pin + dmac_b_request_direction_t activation_request_source_select; ///< DMAC activation request source + + dmac_b_mode_select_t dmac_mode; ///< DMAC Mode + dmac_b_continuous_setting_t continuous_setting; ///< Next register operation settings + uint16_t transfer_interval; ///< DMA transfer interval + dmac_b_channel_scheduling_t channel_scheduling; ///< DMA channel scheduling + + /** Callback for transfer end interrupt. */ + void (* p_callback)(dmac_b_callback_args_t * cb_data); + + /** Placeholder for user data. Passed to the user p_callback in ::transfer_callback_args_t. */ + void const * p_context; +} dmac_b_extended_cfg_t; + +/** DMAC transfer information configuration extension. This extension is required. */ +typedef struct st_dmac_b_extended_info +{ + /** Select number of source bytes to transfer at once. */ + dmac_b_transfer_size_t src_size; + + /** Select number of destination bytes to transfer at once. */ + dmac_b_transfer_size_t dest_size; + + /** Next1 Register set settings */ + dmac_b_register_set_setting_t * p_next1_register_setting; +} dmac_b_extended_info_t; + +/********************************************************************************************************************** + * Exported global variables + **********************************************************************************************************************/ + +/** @cond INC_HEADER_DEFS_SEC */ +/** Filled in Interface API structure for this Instance. */ +extern const transfer_api_t g_transfer_on_dmac_b; + +/** @endcond */ + +/*********************************************************************************************************************** + * Public Function Prototypes + **********************************************************************************************************************/ +fsp_err_t R_DMAC_B_Open(transfer_ctrl_t * const p_api_ctrl, transfer_cfg_t const * const p_cfg); +fsp_err_t R_DMAC_B_Reconfigure(transfer_ctrl_t * const p_api_ctrl, transfer_info_t * p_info); +fsp_err_t R_DMAC_B_Reset(transfer_ctrl_t * const p_api_ctrl, + void const * volatile p_src, + void * volatile p_dest, + uint16_t const num_transfers); +fsp_err_t R_DMAC_B_SoftwareStart(transfer_ctrl_t * const p_api_ctrl, transfer_start_mode_t mode); +fsp_err_t R_DMAC_B_SoftwareStop(transfer_ctrl_t * const p_api_ctrl); +fsp_err_t R_DMAC_B_Enable(transfer_ctrl_t * const p_api_ctrl); +fsp_err_t R_DMAC_B_Disable(transfer_ctrl_t * const p_api_ctrl); +fsp_err_t R_DMAC_B_InfoGet(transfer_ctrl_t * const p_api_ctrl, transfer_properties_t * const p_info); +fsp_err_t R_DMAC_B_Close(transfer_ctrl_t * const p_api_ctrl); +fsp_err_t R_DMAC_B_Reload(transfer_ctrl_t * const p_api_ctrl, + void const * p_src, + void * p_dest, + uint32_t const num_transfers); +fsp_err_t R_DMAC_B_CallbackSet(transfer_ctrl_t * const p_api_ctrl, + void ( * p_callback)(dmac_b_callback_args_t *), + void const * const p_context, + dmac_b_callback_args_t * const p_callback_memory); + +/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER + +#endif + +/*******************************************************************************************************************//** + * @} (end defgroup DMAC) + **********************************************************************************************************************/ diff --git a/drivers/rz/fsp/inc/instances/rzv/r_rspi.h b/drivers/rz/fsp/inc/instances/rzv/r_rspi.h new file mode 100644 index 00000000..6e808762 --- /dev/null +++ b/drivers/rz/fsp/inc/instances/rzv/r_rspi.h @@ -0,0 +1,179 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +#ifndef R_RSPI_H +#define R_RSPI_H + +/*******************************************************************************************************************//** + * @addtogroup RSPI + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ +#include "r_spi_api.h" + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ +FSP_HEADER + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/************************************************************************************************* + * Type defines for the RSPI interface API + *************************************************************************************************/ + +/** Slave Select Polarity. */ +typedef enum e_rspi_ssl_polarity +{ + RSPI_SSLP_LOW, ///< SSLP signal polarity active low + RSPI_SSLP_HIGH ///< SSLP signal polarity active high +} rspi_ssl_polarity_t; + +/** MOSI Idle Behavior. */ +typedef enum e_rspi_mosi_idle_value_fixing +{ + RSPI_MOSI_IDLE_VALUE_FIXING_DISABLE, ///< MOSI output value=value set in MOIFV bit + RSPI_MOSI_IDLE_VALUE_FIXING_LOW, ///< MOSIn level low during MOSI idling + RSPI_MOSI_IDLE_VALUE_FIXING_HIGH ///< MOSIn level high during MOSI idling +} rspi_mosi_idle_value_fixing_t; + +/** SSL Signal Level Keeping Enable/Disable. */ +typedef enum e_rspi_ssl_level_keep +{ + RSPI_SSL_LEVEL_KEEP_DISABLE, ///< Disable SSL Level Keep Mode + RSPI_SSL_LEVEL_KEEP_ENABLE ///< Enable SSL Level Keep Mode +} rspi_ssl_level_keep_t; + +/** Delay count for SPI delay settings. */ +typedef enum e_rspi_delay_count +{ + RSPI_DELAY_COUNT_1, ///< Set RSPCK delay count to 1 RSPCK + RSPI_DELAY_COUNT_2, ///< Set RSPCK delay count to 2 RSPCK + RSPI_DELAY_COUNT_3, ///< Set RSPCK delay count to 3 RSPCK + RSPI_DELAY_COUNT_4, ///< Set RSPCK delay count to 4 RSPCK + RSPI_DELAY_COUNT_5, ///< Set RSPCK delay count to 5 RSPCK + RSPI_DELAY_COUNT_6, ///< Set RSPCK delay count to 6 RSPCK + RSPI_DELAY_COUNT_7, ///< Set RSPCK delay count to 7 RSPCK + RSPI_DELAY_COUNT_8 ///< Set RSPCK delay count to 8 RSPCK +} rspi_delay_count_t; + +/** Transmitter FIFO trigger level. */ +typedef enum +{ + RSPI_TX_TRIGGER_7, ///< Trigger when 7 or less bytes in TX FIFO + RSPI_TX_TRIGGER_6, ///< Trigger when 6 or less bytes in TX FIFO + RSPI_TX_TRIGGER_4, ///< Trigger when 4 or less bytes in TX FIFO + RSPI_TX_TRIGGER_0, ///< Trigger when TX FIFO is empty +} rspi_tx_trigger_level_t; + +/** Receiver FIFO trigger level. */ +typedef enum +{ + RSPI_RX_TRIGGER_1, ///< Trigger when 1 or more bytes in RX FIFO + RSPI_RX_TRIGGER_2, ///< Trigger when 2 or more bytes in RX FIFO + RSPI_RX_TRIGGER_4, ///< Trigger when 4 or more bytes in RX FIFO + RSPI_RX_TRIGGER_8, ///< Trigger when 8 or more bytes in RX FIFO + RSPI_RX_TRIGGER_16, ///< Trigger when 16 or more bytes in RX FIFO + RSPI_RX_TRIGGER_24, ///< Trigger when 24 or more bytes in RX FIFO + RSPI_RX_TRIGGER_32, ///< Trigger when 32 or more bytes in RX FIFO + RSPI_RX_TRIGGER_5, ///< Trigger when 5 or more bytes in RX FIFO +} rspi_rx_trigger_level_t; + +/** RSPI Clock Divider settings. */ +typedef struct +{ + uint8_t spbr; ///< SPBR register setting + uint8_t brdv : 2; ///< BRDV setting in SPCMD0 +} rspi_rspck_div_setting_t; + +/** Extended RSPI interface configuration */ +typedef struct st_rspi_extended_cfg +{ + rspi_ssl_polarity_t ssl_polarity; ///< Select SSLn signal polarity + rspi_mosi_idle_value_fixing_t mosi_idle; ///< Select MOSI idle fixed value and selection + rspi_rspck_div_setting_t spck_div; ///< Register values for configuring the RSPI Clock Divider. + rspi_delay_count_t spck_delay; ///< SPI Clock Delay Register Setting + rspi_delay_count_t ssl_negation_delay; ///< SPI Slave Select Negation Delay Register Setting + rspi_delay_count_t next_access_delay; ///< SPI Next-Access Delay Register Setting + rspi_ssl_level_keep_t ssl_level_keep; ///< Select SSL signal level keep mode + rspi_rx_trigger_level_t rx_trigger_level; ///< Receiver FIFO trigger level + rspi_tx_trigger_level_t tx_trigger_level; ///< Transmitter FIFO trigger level +} rspi_extended_cfg_t; + +/** Channel control block. DO NOT INITIALIZE. Initialization occurs when @ref spi_api_t::open is called. */ +typedef struct st_rspi_instance_ctrl +{ + uint32_t open; ///< Indicates whether the open() API has been successfully called. + spi_cfg_t const * p_cfg; ///< Pointer to instance configuration + rspi_extended_cfg_t * p_ext; ///< Pointer to extended configuration + R_RSPI0_Type * p_regs; ///< Base register for this channel + void const * p_tx_data; ///< Buffer to transmit + void * p_rx_data; ///< Buffer to receive + uint32_t tx_count; ///< Number of Data Frames to transfer (8-bit, 16-bit, 32-bit) + uint32_t rx_count; ///< Number of Data Frames to transfer (8-bit, 16-bit, 32-bit) + spi_bit_width_t bit_width; ///< Bits per Data frame (8-bit, 16-bit, 32-bit) + + /* Pointer to callback and optional working memory */ + void (* p_callback)(spi_callback_args_t *); + spi_callback_args_t * p_callback_memory; + + /* Pointer to context to be passed into callback function */ + void const * p_context; + uint32_t rxfifo_trigger_bytes; ///< Receive buffer data triggering number + volatile bool transfer_is_pending; ///< Transfer is pending +} rspi_instance_ctrl_t; + +/********************************************************************************************************************** + * Exported global variables + **********************************************************************************************************************/ + +/** @cond INC_HEADER_DEFS_SEC */ +/** Filled in Interface API structure for this Instance. */ +extern const spi_api_t g_spi_on_rspi; + +/** @endcond */ + +/*********************************************************************************************************************** + * Public APIs + **********************************************************************************************************************/ +fsp_err_t R_RSPI_Open(spi_ctrl_t * p_api_ctrl, spi_cfg_t const * const p_cfg); + +fsp_err_t R_RSPI_Read(spi_ctrl_t * const p_api_ctrl, + void * p_dest, + uint32_t const length, + spi_bit_width_t const bit_width); + +fsp_err_t R_RSPI_Write(spi_ctrl_t * const p_api_ctrl, + void const * p_src, + uint32_t const length, + spi_bit_width_t const bit_width); + +fsp_err_t R_RSPI_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); + +fsp_err_t R_RSPI_Close(spi_ctrl_t * const p_api_ctrl); + +fsp_err_t R_RSPI_CalculateBitrate(uint32_t bitrate, rspi_rspck_div_setting_t * spck_div); + +fsp_err_t R_RSPI_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); + +/*******************************************************************************************************************//** + * @} (end ingroup RSPI) + **********************************************************************************************************************/ + +/** Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER + +#endif /* R_RSPI_H */ diff --git a/drivers/rz/fsp/src/rzv/r_dmac_b/r_dmac_b.c b/drivers/rz/fsp/src/rzv/r_dmac_b/r_dmac_b.c new file mode 100644 index 00000000..e0724d4b --- /dev/null +++ b/drivers/rz/fsp/src/rzv/r_dmac_b/r_dmac_b.c @@ -0,0 +1,991 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ +#include "r_dmac_b.h" +#include "r_dmac_b_cfg.h" +#if (BSP_FEATURE_BSP_HAS_MMU_SUPPORT) + #include "hal_data.h" +#endif + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/** Driver ID (DMAC in ASCII) */ +#define DMAC_B_ID (0x444d4143) + +/** Byte limited to 2^32-1 byte */ +#define DMAC_B_BLOCK_MAX_LENGTH (0xFFFFFFFF) +#define DMAC_B_BLOCK_COUNT_MAX_LENGTH (0xFFFFFFFF) + +#define DMAC_B_PRV_CHANNEL(channel) (channel % 8) +#define DMAC_B_PRV_GROUP(channel) (channel / 8) + +#define DMAC_B_PRV_DCTRL_DEFAULT_VALUE (0x00000000U) +#define DMAC_B_PRV_CHCFG_DEFAULT_VALUE (0x00000000U) + +/* Channel Configuration Register Bit Field Definitions */ +#define DMAC_B_PRV_CHCFG_SEL_VALUE_MASK (0x07U) +#define DMAC_B_PRV_CHCFG_REQD_VALUE_MASK (0x01U) +#define DMAC_B_PRV_CHCFG_DETECT_MODE_VALUE_MASK (0x07U) +#define DMAC_B_PRV_CHCFG_AM_VALUE_MASK (0x07U) +#define DMAC_B_PRV_CHCFG_SDS_VALUE_MASK (0x0FU) +#define DMAC_B_PRV_CHCFG_DDS_VALUE_MASK (0x0FU) +#define DMAC_B_PRV_CHCFG_SAD_VALUE_MASK (0x01U) +#define DMAC_B_PRV_CHCFG_DAD_VALUE_MASK (0x01U) +#define DMAC_B_PRV_CHCFG_TM_VALUE_MASK (0x01U) +#define DMAC_B_PRV_NEXT_REG_VALUE_MASK (0x03U) +#define DMAC_B_PRV_ACTIVATION_SOURCE_VALUE_MASK (0xFFFU) + +#define DMAC_B_PRV_ACK_MODE_VALUE_POS (0x10U) +#define DMAC_B_PRV_DETECT_MODE_VALUE_POS (0x18U) + +/* DMA Control Register Bit Field Definitions */ +#define DMAC_B_PRV_DCTRL_PR_OFFSET (0U) +#define DMAC_B_PRV_DCTRL_PR_VALUE_MASK (0x01U) + +/* DMAC Resource Select Register Bit Field Definitions */ +#define DMAC_B_PRV_DMARS_MID_RID_OFFSET (16U) +#define DMAC_B_PRV_DMARS_MID_RID_MASK (0x3FFU) + +/*********************************************************************************************************************** + * Private function prototypes + **********************************************************************************************************************/ +void dmac_b_int_isr(void); +void dmac_b_err_isr(void); + +static fsp_err_t r_dmac_b_prv_enable(dmac_b_instance_ctrl_t * p_ctrl); +static void r_dmac_b_prv_disable(dmac_b_instance_ctrl_t * p_ctrl); +static void r_dmac_b_config_transfer_info(dmac_b_instance_ctrl_t * p_ctrl, transfer_info_t * p_info); +static void r_dmac_b_call_callback (dmac_b_instance_ctrl_t * p_ctrl, transfer_event_t event); + +#if DMAC_B_CFG_PARAM_CHECKING_ENABLE +static fsp_err_t r_dmac_b_open_parameter_checking(dmac_b_instance_ctrl_t * const p_ctrl, + transfer_cfg_t const * const p_cfg); +static fsp_err_t r_dmac_b_info_paramter_checking(transfer_info_t const * const p_info); +static fsp_err_t r_dmac_b_enable_parameter_checking(dmac_b_instance_ctrl_t * const p_ctrl); + +#endif + +/*********************************************************************************************************************** + * Private global variables + **********************************************************************************************************************/ + +/* DMAC_B base address */ +static const uint32_t volatile * p_dmac_b_base_address[BSP_FEATURE_DMAC_MAX_UNIT] = +{ + (uint32_t *) R_DMAC_B0, +#if BSP_FEATURE_DMAC_MAX_UNIT > 1 + (uint32_t *) R_DMAC_B1, + #if BSP_FEATURE_DMAC_MAX_UNIT > 2 + (uint32_t *) R_DMAC_B2, + #if BSP_FEATURE_DMAC_MAX_UNIT > 3 + (uint32_t *) R_DMAC_B3, + #if BSP_FEATURE_DMAC_MAX_UNIT > 4 + (uint32_t *) R_DMAC_B4, + #endif + #endif + #endif +#endif +}; + +/*********************************************************************************************************************** + * Global Variables + **********************************************************************************************************************/ + +/** Channel control struct array */ +static dmac_b_instance_ctrl_t * gp_ctrl[BSP_FEATURE_DMAC_MAX_UNIT * BSP_FEATURE_DMAC_MAX_CHANNEL] = {NULL}; + +/** DMAC implementation of transfer API. */ +const transfer_api_t g_transfer_on_dmac_b = +{ + .open = R_DMAC_B_Open, + .reconfigure = R_DMAC_B_Reconfigure, + .reset = R_DMAC_B_Reset, + .infoGet = R_DMAC_B_InfoGet, + .softwareStart = R_DMAC_B_SoftwareStart, + .softwareStop = R_DMAC_B_SoftwareStop, + .enable = R_DMAC_B_Enable, + .disable = R_DMAC_B_Disable, + .close = R_DMAC_B_Close, + .reload = R_DMAC_B_Reload, + .callbackSet = R_DMAC_B_CallbackSet +}; + +/*******************************************************************************************************************//** + * @addtogroup DMAC_B + * @{ + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Configure a DMAC channel. + * + * @retval FSP_SUCCESS Successful open. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_IP_CHANNEL_NOT_PRESENT The configured channel is invalid. + * @retval FSP_ERR_IRQ_BSP_DISABLED The IRQ associated with the activation source is not enabled in the BSP. + * @retval FSP_ERR_ALREADY_OPEN The control structure is already opened. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_B_Open (transfer_ctrl_t * const p_api_ctrl, transfer_cfg_t const * const p_cfg) +{ +#if DMAC_B_CFG_PARAM_CHECKING_ENABLE + fsp_err_t err = FSP_SUCCESS; + err = r_dmac_b_open_parameter_checking(p_api_ctrl, p_cfg); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); +#endif + + dmac_b_instance_ctrl_t * p_ctrl = (dmac_b_instance_ctrl_t *) p_api_ctrl; + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_cfg->p_extend; + + p_ctrl->p_cfg = p_cfg; + p_ctrl->p_reg = (R_DMAC_B0_Type *) p_dmac_b_base_address[p_extend->unit]; + + /* Set callback and context pointers, if configured */ + p_ctrl->p_callback = p_extend->p_callback; + p_ctrl->p_context = p_extend->p_context; + p_ctrl->p_callback_memory = NULL; + + /* Supply clock to DMAC module. */ + R_BSP_MODULE_START(FSP_IP_DMAC, p_extend->unit); + + /* Configure the transfer settings. */ + r_dmac_b_config_transfer_info(p_ctrl, p_cfg->p_info); + + /* Mark driver as open by initializing "DMAC" in its ASCII equivalent.*/ + p_ctrl->open = DMAC_B_ID; + + /* Track ctrl struct */ + gp_ctrl[(p_extend->unit) * BSP_FEATURE_DMAC_MAX_CHANNEL + (p_extend->channel)] = p_ctrl; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Reconfigure the transfer with new transfer info. + * + * @retval FSP_SUCCESS Transfer is configured and will start when trigger occurs. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_ENABLED DMAC is not enabled. The current configuration must not be valid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_B_Reconfigure (transfer_ctrl_t * const p_api_ctrl, transfer_info_t * p_info) +{ + fsp_err_t err; + dmac_b_instance_ctrl_t * p_ctrl = (dmac_b_instance_ctrl_t *) p_api_ctrl; + +#if DMAC_B_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(p_ctrl != NULL); + FSP_ERROR_RETURN(p_ctrl->open == DMAC_B_ID, FSP_ERR_NOT_OPEN); + err = r_dmac_b_info_paramter_checking(p_info); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + FSP_ASSERT(p_ctrl->p_cfg->p_extend != NULL); + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + if (DMAC_B_CONTINUOUS_SETTING_TRANSFER_ONCE != p_extend->continuous_setting) + { + FSP_ASSERT(NULL != p_info->p_next1_src); + FSP_ASSERT(NULL != p_info->p_next1_dest); + FSP_ASSERT(0 != p_info->next1_length); + } +#endif + + /* Reconfigure the transfer settings. */ + r_dmac_b_config_transfer_info(p_ctrl, p_info); + + /* Enable the transfer configuration. */ + err = r_dmac_b_prv_enable(p_api_ctrl); + FSP_ERROR_RETURN(FSP_SUCCESS == err, FSP_ERR_NOT_ENABLED); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Reset transfer source, destination, and number of transfers. + * + * @retval FSP_ERR_UNSUPPORTED API not supported. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_B_Reset (transfer_ctrl_t * const p_api_ctrl, + void const * volatile p_src, + void * volatile p_dest, + uint16_t const num_transfers) +{ + FSP_PARAMETER_NOT_USED(p_api_ctrl); + FSP_PARAMETER_NOT_USED(p_src); + FSP_PARAMETER_NOT_USED(p_dest); + FSP_PARAMETER_NOT_USED(num_transfers); + + return FSP_ERR_UNSUPPORTED; +} + +/*******************************************************************************************************************//** + * If the mode is TRANSFER_START_MODE_SINGLE initiate a single transfer with software. If the mode is + * TRANSFER_START_MODE_REPEAT continue triggering transfers until all of the transfers are completed. + * + * @retval FSP_SUCCESS Transfer started written successfully. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_B_SoftwareStart (transfer_ctrl_t * const p_api_ctrl, transfer_start_mode_t mode) +{ + dmac_b_instance_ctrl_t * p_ctrl = (dmac_b_instance_ctrl_t *) p_api_ctrl; + +#if DMAC_B_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(p_ctrl->open == DMAC_B_ID, FSP_ERR_NOT_OPEN); +#endif + + FSP_PARAMETER_NOT_USED(mode); + + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_B_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_B_PRV_CHANNEL(p_extend->channel); + + /* Set auto clear bit and software start bit. */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = R_DMAC_B0_GRP_CH_CHCTRL_STG_Msk; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Stop software transfers if they were started with TRANSFER_START_MODE_REPEAT. + * + * @retval FSP_SUCCESS Transfer stopped written successfully. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_B_SoftwareStop (transfer_ctrl_t * const p_api_ctrl) +{ + dmac_b_instance_ctrl_t * p_ctrl = (dmac_b_instance_ctrl_t *) p_api_ctrl; + +#if DMAC_B_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(p_ctrl->open == DMAC_B_ID, FSP_ERR_NOT_OPEN); +#endif + + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_B_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_B_PRV_CHANNEL(p_extend->channel); + + /* Set Suspend. */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = R_DMAC_B0_GRP_CH_CHCTRL_SETSUS_Msk; + + /* Transfer is already stopped. */ + if (!(p_ctrl->p_reg->GRP[group].CH[channel].CHSTAT & R_DMAC_B0_GRP_CH_CHSTAT_EN_Msk)) + { + /* Software Reset */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = R_DMAC_B0_GRP_CH_CHCTRL_SWRST_Msk; + + return FSP_SUCCESS; + } + + /* Check whether a transfer is suspended. */ + FSP_HARDWARE_REGISTER_WAIT(p_ctrl->p_reg->GRP[group].CH[channel].CHSTAT_b.SUS, 1); + + /* Set clear enable and software stop bit. */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = R_DMAC_B0_GRP_CH_CHCTRL_CLREN_Msk; + + /* Check whether a transfer is stopped. */ + FSP_HARDWARE_REGISTER_WAIT(p_ctrl->p_reg->GRP[group].CH[channel].CHSTAT_b.TACT, 0); + + /* Software Reset */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL_b.SWRST = 1; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Enable transfers for the configured activation source. + * + * @retval FSP_SUCCESS Counter value written successfully. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_B_Enable (transfer_ctrl_t * const p_api_ctrl) +{ + dmac_b_instance_ctrl_t * p_ctrl = (dmac_b_instance_ctrl_t *) p_api_ctrl; +#if DMAC_B_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(p_ctrl->open == DMAC_B_ID, FSP_ERR_NOT_OPEN); +#endif + + return r_dmac_b_prv_enable(p_ctrl); +} + +/*******************************************************************************************************************//** + * Disable transfers so that they are no longer triggered by the activation source. + * + * @retval FSP_SUCCESS Counter value written successfully. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_B_Disable (transfer_ctrl_t * const p_api_ctrl) +{ + dmac_b_instance_ctrl_t * p_ctrl = (dmac_b_instance_ctrl_t *) p_api_ctrl; +#if DMAC_B_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(p_ctrl->open == DMAC_B_ID, FSP_ERR_NOT_OPEN); +#endif + + r_dmac_b_prv_disable(p_ctrl); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Set driver specific information in provided pointer. + * + * @retval FSP_SUCCESS Information has been written to p_info. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_B_InfoGet (transfer_ctrl_t * const p_api_ctrl, transfer_properties_t * const p_info) +{ + dmac_b_instance_ctrl_t * p_ctrl = (dmac_b_instance_ctrl_t *) p_api_ctrl; + +#if DMAC_B_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(p_ctrl->open == DMAC_B_ID, FSP_ERR_NOT_OPEN); + FSP_ASSERT(NULL != p_info); +#endif + + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_B_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_B_PRV_CHANNEL(p_extend->channel); + + p_info->transfer_length_max = DMAC_B_MAX_NORMAL_TRANSFER_LENGTH; + p_info->block_count_max = DMAC_B_BLOCK_COUNT_MAX_LENGTH; + + p_info->block_count_remaining = DMAC_B_MAX_BLOCK_TRANSFER_LENGTH; + p_info->transfer_length_remaining = (p_ctrl->p_reg->GRP[group].CH[channel].CRTB); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Disable transfer and clean up internal data. Implements @ref transfer_api_t::close. + * + * @retval FSP_SUCCESS Successful close. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_B_Close (transfer_ctrl_t * const p_api_ctrl) +{ + dmac_b_instance_ctrl_t * p_ctrl = (dmac_b_instance_ctrl_t *) p_api_ctrl; +#if DMAC_B_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(p_ctrl->open == DMAC_B_ID, FSP_ERR_NOT_OPEN); +#endif + + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_B_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_B_PRV_CHANNEL(p_extend->channel); + + /* Disable DMAC transfers on this channel. */ + R_BSP_DMAC_ACTIVATION_SOURCE_DISABLE(p_ctrl->p_reg, p_extend->unit, p_extend->channel); + + p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = R_DMAC_B0_GRP_CH_CHCTRL_CLREN_Msk; + FSP_HARDWARE_REGISTER_WAIT(p_ctrl->p_reg->GRP[group].CH[channel].CHSTAT_b.TACT, 0); + + p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = R_DMAC_B0_GRP_CH_CHCTRL_SWRST_Msk; + + if (p_extend->dmac_int_irq >= 0) + { + R_BSP_IrqDisable(p_extend->dmac_int_irq); + R_FSP_IsrContextSet(p_extend->dmac_int_irq, NULL); + } + + /* Clear ID so control block can be reused. */ + p_ctrl->open = 0U; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Make the following transfer settings to continue the transfer. + * + * @retval FSP_SUCCESS Successful continuous transfer settings. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_B_Reload (transfer_ctrl_t * const p_api_ctrl, + void const * volatile p_src, + void * volatile p_dest, + uint32_t const num_transfers) +{ + dmac_b_instance_ctrl_t * p_ctrl = (dmac_b_instance_ctrl_t *) p_api_ctrl; + + uint32_t * p_src_cast; + uint32_t * p_dest_cast; + +#if DMAC_B_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(p_ctrl->open == DMAC_B_ID, FSP_ERR_NOT_OPEN); +#endif + + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_B_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_B_PRV_CHANNEL(p_extend->channel); + +#if (BSP_FEATURE_BSP_HAS_MMU_SUPPORT) + uint64_t pa; /* Physical Address */ + uint64_t va; /* Virtual Address */ +#elif (BSP_FEATURE_BSP_SLAVE_ADDRESS_CONVERSION_SUPPORT) + uint32_t original_addr; /* Address before conversion */ + uint32_t converted_addr; /* Address after conversion */ +#endif + + if ((1 == p_ctrl->p_reg->GRP[group].CH[channel].CHSTAT_b.EN) && + (0 == p_ctrl->p_reg->GRP[group].CH[channel].CHCFG_b.REN)) + { + p_src_cast = (uint32_t *) &p_src; + p_dest_cast = (uint32_t *) &p_dest; + if (0 == p_ctrl->p_reg->GRP[group].CH[channel].CHSTAT_b.SR) + { +#if (BSP_FEATURE_BSP_HAS_MMU_SUPPORT) + va = *p_src_cast; + R_MMU_VAtoPA(&g_mmu_ctrl, va, (void *) &pa); + p_ctrl->p_reg->GRP[group].CH[channel].N[1].SA = (uint32_t) pa; + + va = *p_dest_cast; + R_MMU_VAtoPA(&g_mmu_ctrl, va, (void *) &pa); + p_ctrl->p_reg->GRP[group].CH[channel].N[1].DA = (uint32_t) pa; +#elif (BSP_FEATURE_BSP_SLAVE_ADDRESS_CONVERSION_SUPPORT) + original_addr = *p_src_cast; + converted_addr = R_BSP_SlaveAddressConversion(original_addr); + p_ctrl->p_reg->GRP[group].CH[channel].N[1].SA = converted_addr; + + original_addr = *p_dest_cast; + converted_addr = R_BSP_SlaveAddressConversion(original_addr); + p_ctrl->p_reg->GRP[group].CH[channel].N[1].DA = converted_addr; +#else + p_ctrl->p_reg->GRP[group].CH[channel].N[1].SA = *p_src_cast; + p_ctrl->p_reg->GRP[group].CH[channel].N[1].DA = *p_dest_cast; +#endif + p_ctrl->p_reg->GRP[group].CH[channel].N[1].TB = num_transfers; + } + else + { +#if (BSP_FEATURE_BSP_HAS_MMU_SUPPORT) + va = *p_src_cast; + R_MMU_VAtoPA(&g_mmu_ctrl, va, (void *) &pa); + p_ctrl->p_reg->GRP[group].CH[channel].N[0].SA = (uint32_t) pa; + + va = *p_dest_cast; + R_MMU_VAtoPA(&g_mmu_ctrl, va, (void *) &pa); + p_ctrl->p_reg->GRP[group].CH[channel].N[0].DA = (uint32_t) pa; +#elif (BSP_FEATURE_BSP_SLAVE_ADDRESS_CONVERSION_SUPPORT) + original_addr = *p_src_cast; + converted_addr = R_BSP_SlaveAddressConversion(original_addr); + p_ctrl->p_reg->GRP[group].CH[channel].N[0].SA = converted_addr; + + original_addr = *p_dest_cast; + converted_addr = R_BSP_SlaveAddressConversion(original_addr); + p_ctrl->p_reg->GRP[group].CH[channel].N[0].DA = converted_addr; +#else + p_ctrl->p_reg->GRP[group].CH[channel].N[0].SA = *p_src_cast; + p_ctrl->p_reg->GRP[group].CH[channel].N[0].DA = *p_dest_cast; +#endif + p_ctrl->p_reg->GRP[group].CH[channel].N[0].TB = num_transfers; + } + + p_ctrl->p_reg->GRP[group].CH[channel].CHCFG |= R_DMAC_B0_GRP_CH_CHCFG_REN_Msk; + } + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Updates the user callback with the option to provide memory for the callback argument structure. + * Implements @ref transfer_api_t::callbackSet. + * + * @retval FSP_SUCCESS Callback updated successfully. + * @retval FSP_ERR_ASSERTION A required pointer is NULL. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_B_CallbackSet (transfer_ctrl_t * const p_api_ctrl, + void ( * p_callback)(dmac_b_callback_args_t *), + void const * const p_context, + dmac_b_callback_args_t * const p_callback_memory) +{ + dmac_b_instance_ctrl_t * p_ctrl = (dmac_b_instance_ctrl_t *) p_api_ctrl; + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(p_instance_ctrl); + FSP_ASSERT(p_callback); + FSP_ERROR_RETURN(DMAC_B_ID == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + + /* Store callback, context and callback memory */ + p_ctrl->p_callback = p_callback; + p_ctrl->p_context = p_context; + p_ctrl->p_callback_memory = p_callback_memory; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * @} (end addtogroup DMAC_B) + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Private Functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Enable transfers for the channel. + * + * @param[in] p_ctrl Pointer to control structure. + * + * @retval FSP_SUCCESS Successful close. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_dmac_b_prv_enable (dmac_b_instance_ctrl_t * p_ctrl) +{ +#if DMAC_B_CFG_PARAM_CHECKING_ENABLE + fsp_err_t err = r_dmac_b_enable_parameter_checking(p_ctrl); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); +#endif + + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_B_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_B_PRV_CHANNEL(p_extend->channel); + + FSP_CRITICAL_SECTION_DEFINE; + FSP_CRITICAL_SECTION_ENTER; + + /* DMAC trigger source set. */ + R_BSP_DMAC_ACTIVATION_SOURCE_ENABLE(p_ctrl->p_reg, p_extend->unit, p_extend->channel, p_extend->activation_source); + + /* External DMAC REQ trigger set. */ + R_BSP_DMAC_DREQ_DETECT_METHOD_SELECT(p_ctrl->p_reg, + p_extend->channel, + p_extend->external_detection_mode, + p_extend->dreq_input_pin); + + FSP_CRITICAL_SECTION_EXIT; + + if (p_extend->dmac_int_irq >= 0) + { + /* Enable transfer end interrupt requests. */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCFG &= ~((uint32_t) R_DMAC_B0_GRP_CH_CHCFG_DEM_Msk); + + /* Enable the IRQ in the GIC. */ + R_BSP_IrqCfgEnable(p_extend->dmac_int_irq, p_extend->dmac_int_ipl, p_ctrl); + + /* Set detect type of DMAC end interrupt */ + R_BSP_DMAC_B_TRANSFER_END_DETECT_METHOD_SELECT(p_extend->unit, p_extend->channel, 1); + } + else + { + /* Disable transfer end interrupt requests. */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCFG |= R_DMAC_B0_GRP_CH_CHCFG_DEM_Msk; + } + + /* Resets the channel status register. */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = R_DMAC_B0_GRP_CH_CHCTRL_SWRST_Msk; + + /* Enable transfer. */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = R_DMAC_B0_GRP_CH_CHCTRL_SETEN_Msk; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Disable transfers for the channel. + * + * @param p_ctrl Pointer to the control structure + **********************************************************************************************************************/ +static void r_dmac_b_prv_disable (dmac_b_instance_ctrl_t * p_ctrl) +{ + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_B_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_B_PRV_CHANNEL(p_extend->channel); + + /* Disable DMA transfer. */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = R_DMAC_B0_GRP_CH_CHCTRL_CLREN_Msk; + + /* Wait DMA stop */ + FSP_HARDWARE_REGISTER_WAIT(p_ctrl->p_reg->GRP[group].CH[channel].CHSTAT_b.TACT, 0); + + /* Software Reset */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = R_DMAC_B0_GRP_CH_CHCTRL_SWRST_Msk; + + /* Disable DMAC transfers on this channel. */ + R_BSP_DMAC_ACTIVATION_SOURCE_DISABLE(p_ctrl->p_reg, p_extend->unit, p_extend->channel); + + /* Set DMA transfer end interrupt mask */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCFG |= R_DMAC_B0_GRP_CH_CHCFG_DEM_Msk; +} + +/*******************************************************************************************************************//** + * Write the transfer info to the hardware registers. + * + * @param[in] p_ctrl Pointer to control structure. + * @param p_info Pointer to transfer info. + **********************************************************************************************************************/ +static void r_dmac_b_config_transfer_info (dmac_b_instance_ctrl_t * p_ctrl, transfer_info_t * p_info) +{ + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_B_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_B_PRV_CHANNEL(p_extend->channel); + + uint32_t * p_src_cast; + uint32_t * p_dest_cast; + +#if (BSP_FEATURE_BSP_HAS_MMU_SUPPORT) + uint64_t pa; /* Physical Address */ + uint64_t va; /* Virtual Address */ +#elif (BSP_FEATURE_BSP_SLAVE_ADDRESS_CONVERSION_SUPPORT) + uint32_t original_addr; /* Address before conversion */ + uint32_t converted_addr; /* Address after conversion */ +#endif + + uint32_t dctrl = DMAC_B_PRV_DCTRL_DEFAULT_VALUE; + uint32_t chcfg = DMAC_B_PRV_CHCFG_DEFAULT_VALUE; + + /* Disable transfers if they are currently enabled. */ + r_dmac_b_prv_disable(p_ctrl); + + /* Priority control select */ + dctrl |= ((p_extend->channel_scheduling) & DMAC_B_PRV_DCTRL_PR_VALUE_MASK) << R_DMAC_B0_GRP_DCTRL_PR_Pos; + + /* Configure channel */ + chcfg = ((p_extend->channel % 8 & DMAC_B_PRV_CHCFG_SEL_VALUE_MASK) << R_DMAC_B0_GRP_CH_CHCFG_SEL_Pos) | + ((p_extend->activation_request_source_select & DMAC_B_PRV_CHCFG_REQD_VALUE_MASK) << + R_DMAC_B0_GRP_CH_CHCFG_REQD_Pos) | + ((p_extend->internal_detection_mode & DMAC_B_PRV_CHCFG_DETECT_MODE_VALUE_MASK) << + R_DMAC_B0_GRP_CH_CHCFG_LOEN_Pos) | + ((p_extend->ack_mode & DMAC_B_PRV_CHCFG_AM_VALUE_MASK) << R_DMAC_B0_GRP_CH_CHCFG_AM_Pos) | + ((p_info->src_size & DMAC_B_PRV_CHCFG_SDS_VALUE_MASK) << R_DMAC_B0_GRP_CH_CHCFG_SDS_Pos) | + ((p_info->dest_size & DMAC_B_PRV_CHCFG_DDS_VALUE_MASK) << R_DMAC_B0_GRP_CH_CHCFG_DDS_Pos) | + ((p_info->src_addr_mode & DMAC_B_PRV_CHCFG_SAD_VALUE_MASK) << R_DMAC_B0_GRP_CH_CHCFG_SAD_Pos) | + ((p_info->dest_addr_mode & DMAC_B_PRV_CHCFG_DAD_VALUE_MASK) << R_DMAC_B0_GRP_CH_CHCFG_DAD_Pos) | + ((p_info->mode & DMAC_B_PRV_CHCFG_TM_VALUE_MASK) << R_DMAC_B0_GRP_CH_CHCFG_TM_Pos); + + /* Set the output destination of the DMAACK signal. */ + R_BSP_DMAC_DACK_OUTPUT_PIN_SET(p_extend->unit, p_extend->channel, p_extend->ack_output_pin); + + /* Set the output destination of the DMATEND signal. */ + R_BSP_DMAC_TEND_OUTPUT_PIN_SET(p_extend->unit, p_extend->channel, p_extend->tend_output_pin); + + if (DMAC_B_CONTINUOUS_SETTING_TRANSFER_ONCE != p_extend->continuous_setting) + { + /* Transfer end interrupt mask. */ + chcfg |= R_DMAC_B0_GRP_CH_CHCFG_DEM_Msk; + + /* Configure Register Set Reverse Select */ + chcfg |= ((p_extend->continuous_setting & DMAC_B_PRV_NEXT_REG_VALUE_MASK) << R_DMAC_B0_GRP_CH_CHCFG_RSW_Pos); + } + + p_ctrl->p_reg->GRP[group].DCTRL = dctrl; + + p_src_cast = (uint32_t *) &p_info->p_src; + p_dest_cast = (uint32_t *) &p_info->p_dest; + + /* Next0 transfer setting. */ +#if (BSP_FEATURE_BSP_HAS_MMU_SUPPORT) + va = *p_src_cast; + R_MMU_VAtoPA(&g_mmu_ctrl, va, (void *) &pa); + p_ctrl->p_reg->GRP[group].CH[channel].N[0].SA = (uint32_t) pa; + + va = *p_dest_cast; + R_MMU_VAtoPA(&g_mmu_ctrl, va, (void *) &pa); + p_ctrl->p_reg->GRP[group].CH[channel].N[0].DA = (uint32_t) pa; +#elif (BSP_FEATURE_BSP_SLAVE_ADDRESS_CONVERSION_SUPPORT) + original_addr = *p_src_cast; + converted_addr = R_BSP_SlaveAddressConversion(original_addr); + p_ctrl->p_reg->GRP[group].CH[channel].N[0].SA = converted_addr; + + original_addr = *p_dest_cast; + converted_addr = R_BSP_SlaveAddressConversion(original_addr); + p_ctrl->p_reg->GRP[group].CH[channel].N[0].DA = converted_addr; +#else + p_ctrl->p_reg->GRP[group].CH[channel].N[0].SA = *p_src_cast; + p_ctrl->p_reg->GRP[group].CH[channel].N[0].DA = *p_dest_cast; +#endif + + p_ctrl->p_reg->GRP[group].CH[channel].N[0].TB = p_info->length; + + p_ctrl->p_reg->GRP[group].CH[channel].CHCFG = chcfg; + p_ctrl->p_reg->GRP[group].CH[channel].CHITVL = p_extend->transfer_interval; + + if (DMAC_B_CONTINUOUS_SETTING_TRANSFER_ONCE != p_extend->continuous_setting) + { + p_src_cast = (uint32_t *) &p_info->p_next1_src; + p_dest_cast = (uint32_t *) &p_info->p_next1_dest; + + /* Next1 transfer setting. */ +#if (BSP_FEATURE_BSP_HAS_MMU_SUPPORT) + va = *p_src_cast; + R_MMU_VAtoPA(&g_mmu_ctrl, va, (void *) &pa); + p_ctrl->p_reg->GRP[group].CH[channel].N[1].SA = (uint32_t) pa; + + va = *p_dest_cast; + R_MMU_VAtoPA(&g_mmu_ctrl, va, (void *) &pa); + p_ctrl->p_reg->GRP[group].CH[channel].N[1].DA = (uint32_t) pa; +#elif (BSP_FEATURE_BSP_SLAVE_ADDRESS_CONVERSION_SUPPORT) + original_addr = *p_src_cast; + converted_addr = R_BSP_SlaveAddressConversion(original_addr); + p_ctrl->p_reg->GRP[group].CH[channel].N[1].SA = converted_addr; + + original_addr = *p_dest_cast; + converted_addr = R_BSP_SlaveAddressConversion(original_addr); + p_ctrl->p_reg->GRP[group].CH[channel].N[1].DA = converted_addr; +#else + p_ctrl->p_reg->GRP[group].CH[channel].N[1].SA = *p_src_cast; + p_ctrl->p_reg->GRP[group].CH[channel].N[1].DA = *p_dest_cast; +#endif + p_ctrl->p_reg->GRP[group].CH[channel].N[1].TB = p_info->next1_length; + } +} + +#if DMAC_B_CFG_PARAM_CHECKING_ENABLE + +/*******************************************************************************************************************//** + * Parameter checking of R_DMAC_B_Open. + * + * @param[in] p_ctrl Pointer to control structure. + * @param[in] p_cfg Pointer to configuration structure. All elements of the structure must be + * set by user. + * + * @retval FSP_SUCCESS Input Parameters are Valid. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_IP_CHANNEL_NOT_PRESENT The configured channel is invalid. + * @retval FSP_ERR_IRQ_BSP_DISABLED Callback is NULL and the DMAC IRQ is not enabled. + * @retval FSP_ERR_ALREADY_OPEN The control structure is already opened. + **********************************************************************************************************************/ +static fsp_err_t r_dmac_b_open_parameter_checking (dmac_b_instance_ctrl_t * const p_ctrl, + transfer_cfg_t const * const p_cfg) +{ + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(p_ctrl->open != DMAC_B_ID, FSP_ERR_ALREADY_OPEN); + FSP_ASSERT(NULL != p_cfg); + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_cfg->p_extend; + FSP_ASSERT(NULL != p_cfg->p_extend); + FSP_ERROR_RETURN(p_extend->channel < BSP_FEATURE_DMAC_MAX_CHANNEL, FSP_ERR_IP_CHANNEL_NOT_PRESENT); + + if (DMAC_B_CONTINUOUS_SETTING_TRANSFER_ONCE != p_extend->continuous_setting) + { + FSP_ASSERT(NULL != p_cfg->p_info->p_next1_src); + FSP_ASSERT(NULL != p_cfg->p_info->p_next1_dest); + FSP_ASSERT(0 != p_cfg->p_info->next1_length); + } + + if (NULL != p_extend->p_callback) + { + FSP_ERROR_RETURN(p_extend->dmac_int_irq >= 0, FSP_ERR_IRQ_BSP_DISABLED); + } + + fsp_err_t err = r_dmac_b_info_paramter_checking(p_cfg->p_info); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Checks for errors in the transfer into structure. + * + * @param[in] p_info Pointer transfer info. + * + * @retval FSP_SUCCESS The transfer info is valid. + * @retval FSP_ERR_ASSERTION A transfer info setting is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_dmac_b_info_paramter_checking (transfer_info_t const * const p_info) +{ + FSP_ASSERT(p_info != NULL); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Parameter checking for r_dmac_b_prv_enable. + * + * @param[in] p_ctrl Pointer to control structure. + * + * @retval FSP_SUCCESS Alignment on source and destination pointers is valid. + * @retval FSP_ERR_ASSERTION The current configuration is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_dmac_b_enable_parameter_checking (dmac_b_instance_ctrl_t * const p_ctrl) +{ + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_B_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_B_PRV_CHANNEL(p_extend->channel); + + uint32_t * p_src_cast = (uint32_t *) &p_ctrl->p_reg->GRP[group].CH[channel].N[1].SA; + uint32_t * p_dest_cast = (uint32_t *) &p_ctrl->p_reg->GRP[group].CH[channel].N[1].DA; + void const * p_src = (void const *) p_src_cast; + void const * p_dest = (void const *) p_dest_cast; + + /* The source and destination pointers cannot be NULL. */ + FSP_ASSERT(NULL != p_src); + FSP_ASSERT(NULL != p_dest); + + if (1 == p_ctrl->p_reg->GRP[group].CH[channel].CHCFG_b.RSW) + { + void const * p_src_next1; + void const * p_dest_next1; + p_src_cast = (uint32_t *) &p_ctrl->p_reg->GRP[group].CH[channel].N[1].SA; + p_dest_cast = (uint32_t *) &p_ctrl->p_reg->GRP[group].CH[channel].N[1].DA; + p_src_next1 = (void const *) p_src_cast; + p_dest_next1 = (void const *) p_dest_cast; + + /* The next1 register set source and destination pointers cannot be NULL. */ + FSP_ASSERT(NULL != p_src_next1); + FSP_ASSERT(NULL != p_dest_next1); + } + + return FSP_SUCCESS; +} + +#endif + +/*******************************************************************************************************************//** + * Calls user callback. + * + * @param[in] p_ctrl Pointer to DMAC instance control block + * @param[in] event Event code + **********************************************************************************************************************/ +static void r_dmac_b_call_callback (dmac_b_instance_ctrl_t * p_ctrl, transfer_event_t event) +{ + dmac_b_callback_args_t args; + + /* Store callback arguments in memory provided by user if available. */ + dmac_b_callback_args_t * p_args = p_ctrl->p_callback_memory; + if (NULL == p_args) + { + /* Store on stack */ + p_args = &args; + } + else + { + /* Save current arguments on the stack in case this is a nested interrupt. */ + args = *p_args; + } + + p_args->event = event; + p_args->p_context = p_ctrl->p_context; + + p_ctrl->p_callback(p_args); + + if (NULL != p_ctrl->p_callback_memory) + { + /* Restore callback memory in case this is a nested interrupt. */ + *p_ctrl->p_callback_memory = args; + } +} + +/*******************************************************************************************************************//** + * DMAC ISR + **********************************************************************************************************************/ +void dmac_b_int_isr (void) +{ + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE + + IRQn_Type irq = R_FSP_CurrentIrqGet(); + dmac_b_instance_ctrl_t * p_ctrl = (dmac_b_instance_ctrl_t *) R_FSP_IsrContextGet(irq); + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_B_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_B_PRV_CHANNEL(p_extend->channel); + + if (DMAC_TRIGGER_EVENT_SOFTWARE_TRIGGER != p_extend->activation_source) + { + /* Activation source disabled */ + if (1 != p_ctrl->p_reg->GRP[group].CH[channel].CHSTAT_b.EN) + { + R_BSP_DMAC_ACTIVATION_SOURCE_DISABLE(p_ctrl->p_reg, p_extend->unit, p_extend->channel); + } + } + + /* Clear the DREQ request status. */ + R_BSP_DMAC_DREQ_STATUS_CLEAR(p_extend->dreq_input_pin); + + /* Clear interrupt condition. */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = R_DMAC_B0_GRP_CH_CHCTRL_CLREND_Msk; + + /* Dummy read to ensure that interrupt event is cleared. */ + volatile uint32_t dummy = p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL; + FSP_PARAMETER_NOT_USED(dummy); + + /* Call user callback */ + if (NULL != p_ctrl->p_callback) + { + r_dmac_b_call_callback(p_ctrl, TRANSFER_EVENT_TRANSFER_END); + } + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE +} + +/*******************************************************************************************************************//** + * DMAC ERR ISR + **********************************************************************************************************************/ +void dmac_b_err_isr (void) +{ + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE + + /* Get the DMAC unit where the error occurred from the argument id. */ + IRQn_Type irq = R_FSP_CurrentIrqGet(); + dmac_b_instance_ctrl_t * p_ctrl = (dmac_b_instance_ctrl_t *) R_FSP_IsrContextGet(irq); + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + + uint8_t unit = p_extend->unit; + + /* Get the channel error information DSTAT_ER. */ + R_DMAC_B0_Type * p_base_reg = (R_DMAC_B0_Type *) p_dmac_b_base_address[unit]; + uint32_t dstat_err_upper = p_base_reg->GRP[1].DSTAT_ER; + uint32_t dstat_err_lower = p_base_reg->GRP[0].DSTAT_ER; + uint32_t dstat_err_mask = (dstat_err_upper << 8) | dstat_err_lower; + + uint32_t dmac_error_channel = 0; + + /* After going through the event scan, the interrupt handler ends */ + while (dstat_err_mask) + { + /* Scan and search for error factors one by one */ + uint32_t next_err = __CLZ(__RBIT(dstat_err_mask)); + dstat_err_mask >>= next_err; + dmac_error_channel += next_err; + + uint8_t group = (uint8_t) DMAC_B_PRV_GROUP(dmac_error_channel); + uint8_t channel = (uint8_t) DMAC_B_PRV_CHANNEL(dmac_error_channel); + + p_ctrl = gp_ctrl[unit * BSP_FEATURE_DMAC_MAX_CHANNEL + dmac_error_channel]; + + /* Call user registered callback */ + if (NULL != p_ctrl) + { + /* Clear the error bit and software reset. */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL_b.SWRST = 1; + + /* Invoke the callback function if it is set. */ + if (NULL != p_ctrl->p_callback) + { + /* Call user callback */ + r_dmac_b_call_callback(p_ctrl, TRANSFER_EVENT_TRANSFER_ERROR); + } + } + + /* Clear the scanned flags one by one */ + dstat_err_mask &= ~(1UL); + } + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE +} diff --git a/drivers/rz/fsp/src/rzv/r_rspi/r_rspi.c b/drivers/rz/fsp/src/rzv/r_rspi/r_rspi.c new file mode 100644 index 00000000..954a673e --- /dev/null +++ b/drivers/rz/fsp/src/rzv/r_rspi/r_rspi.c @@ -0,0 +1,1383 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ +#include "r_rspi.h" +#include "r_rspi_cfg.h" + +#if RSPI_CFG_DMAC_ENABLE + #include "r_dmac_b.h" +#endif + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/** "RSPI" in ASCII, used to determine if channel is open. */ +#define RSPI_OPEN (0x52535049ULL) + +/** RSPI base register access macro. */ + +#define RSPI_CLK_N_DIV_MULTIPLIER (512U) ///< Maximum divider for N=0 + +/** RSPI parameter */ +#define RSPI_TX_FIFO_SIZE (8) ///< TX FIFO size +#define RSPI_SPDCR_WIDTH_8BIT (1 << R_RSPI0_SPDCR_SPLW_Pos) +#define RSPI_SPDCR_WIDTH_16BIT (2 << R_RSPI0_SPDCR_SPLW_Pos) +#define RSPI_SPDCR_WIDTH_32BIT (3 << R_RSPI0_SPDCR_SPLW_Pos) +#define RSPI_SPCMD_WIDTH_8BIT (7 << R_RSPI0_SPCMD0_SPB_Pos) +#define RSPI_SPCMD_WIDTH_16BIT (15 << R_RSPI0_SPCMD0_SPB_Pos) +#define RSPI_SPCMD_WIDTH_32BIT (3 << R_RSPI0_SPCMD0_SPB_Pos) +#define RSPI_RXTRG_32BYTE (6) +#define RSPI_RXTRG_24BYTE (5) +#define RSPI_RXTRG_16BYTE (4) +#define RSPI_RXTRG_8BYTE (3) +#define RSPI_RXTRG_5BYTE (7) +#define RSPI_RXTRG_4BYTE (2) +#define RSPI_RXTRG_2BYTE (1) +#define RSPI_RXTRG_1BYTE (0) +#define RSPI_RXTRG_32BYTE_COUNT (32) +#define RSPI_RXTRG_24BYTE_COUNT (24) +#define RSPI_RXTRG_16BYTE_COUNT (16) +#define RSPI_RXTRG_8BYTE_COUNT (8) +#define RSPI_RXTRG_5BYTE_COUNT (5) +#define RSPI_RXTRG_4BYTE_COUNT (4) +#define RSPI_RXTRG_2BYTE_COUNT (2) +#define RSPI_RXTRG_1BYTE_COUNT (1) + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ +#if defined(__ARMCC_VERSION) || defined(__ICCARM__) +typedef void (BSP_CMSE_NONSECURE_CALL * spi_prv_ns_callback)(spi_callback_args_t * p_args); +#elif defined(__GNUC__) +typedef BSP_CMSE_NONSECURE_CALL void (*volatile spi_prv_ns_callback)(spi_callback_args_t * p_args); +#endif + +/*********************************************************************************************************************** + * Private function declarations + **********************************************************************************************************************/ +static void r_rspi_init_control_structure(rspi_instance_ctrl_t * p_ctrl, spi_cfg_t const * const p_cfg); +static void r_rspi_hw_config(rspi_instance_ctrl_t * p_ctrl); +static void r_rspi_nvic_config(rspi_instance_ctrl_t * p_ctrl); +static void r_rspi_bit_width_config(rspi_instance_ctrl_t * p_ctrl); +static void r_rspi_set_rx_fifo_hint(rspi_instance_ctrl_t * p_ctrl); +static void r_rspi_set_rxtrg(rspi_instance_ctrl_t * p_ctrl, rspi_rx_trigger_level_t level); +static void r_rspi_set_rx_fifo_level(rspi_instance_ctrl_t * p_ctrl); +static fsp_err_t r_rspi_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); +static void r_rspi_receive(rspi_instance_ctrl_t * p_ctrl); +static void r_rspi_transmit(rspi_instance_ctrl_t * p_ctrl); +static void r_rspi_call_callback(rspi_instance_ctrl_t * p_ctrl, spi_event_t event); + +#if RSPI_CFG_DMAC_ENABLE + +static fsp_err_t r_rspi_transfer_config(rspi_instance_ctrl_t * p_ctrl, spi_cfg_t const * const p_cfg); +void rspi_tx_dmac_callback(rspi_instance_ctrl_t * p_ctrl); +void rspi_rx_dmac_callback(rspi_instance_ctrl_t * p_ctrl); + +#endif + +/*********************************************************************************************************************** + * ISR prototypes + **********************************************************************************************************************/ +void rspi_rxi_isr(void); +void rspi_txi_isr(void); +void rspi_eri_isr(void); + +/*********************************************************************************************************************** + * Private global variables + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Global variables + **********************************************************************************************************************/ + +/* RSPI implementation of SPI interface. */ +const spi_api_t g_spi_on_rspi = +{ + .open = R_RSPI_Open, + .read = R_RSPI_Read, + .write = R_RSPI_Write, + .writeRead = R_RSPI_WriteRead, + .close = R_RSPI_Close, + .callbackSet = R_RSPI_CallbackSet +}; + +/*******************************************************************************************************************//** + * @addtogroup RSPI + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * This functions initializes a channel for SPI communication mode. Implements @ref spi_api_t::open. + * + * This function performs the following tasks: + * - Performs parameter checking and processes error conditions. + * - Configures the pperipheral registers acording to the configuration. + * - Initialize the control structure for use in other @ref SPI_API functions. + * + * @retval FSP_SUCCESS Channel initialized successfully. + * @retval FSP_ERR_ALREADY_OPEN Instance was already initialized. + * @retval FSP_ERR_ASSERTION An invalid argument was given in the configuration structure. + * @retval FSP_ERR_IP_CHANNEL_NOT_PRESENT The channel number is invalid. + * @return See @ref RENESAS_ERROR_CODES or functions called by this function for other possible return codes. + * @note This function is reentrant. + **********************************************************************************************************************/ +fsp_err_t R_RSPI_Open (spi_ctrl_t * p_api_ctrl, spi_cfg_t const * const p_cfg) +{ + fsp_err_t err = FSP_SUCCESS; + + rspi_instance_ctrl_t * p_ctrl = (rspi_instance_ctrl_t *) p_api_ctrl; + +#if RSPI_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(RSPI_OPEN != p_ctrl->open, FSP_ERR_ALREADY_OPEN); + FSP_ASSERT(NULL != p_cfg); + FSP_ASSERT(NULL != p_cfg->p_extend); + FSP_ERROR_RETURN(BSP_FEATURE_RSPI_VALID_CHANNELS_MASK & (1 << p_cfg->channel), FSP_ERR_IP_CHANNEL_NOT_PRESENT); + FSP_ASSERT(p_cfg->eri_irq >= 0); +#endif + + /* Initialize the control structure */ + r_rspi_init_control_structure(p_ctrl, p_cfg); + + /* Configure hardware registers according to the r_spi_api configuration structure. */ + r_rspi_hw_config(p_ctrl); + + /* Enable interrupts in NVIC. */ + r_rspi_nvic_config(p_ctrl); + +#if RSPI_CFG_DMAC_ENABLE + + /* Configure transfers if they are provided in p_cfg. */ + err = r_rspi_transfer_config(p_ctrl, p_cfg); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); +#endif + + p_ctrl->open = RSPI_OPEN; + + return err; +} + +/*******************************************************************************************************************//** + * This function receives data from a SPI device. Implements @ref spi_api_t::read. + * + * The function performs the following tasks: + * - Performs parameter checking and processes error conditions. + * - Sets up the instance to complete a SPI read operation. + * + * @retval FSP_SUCCESS Read operation successfully completed. + * @retval FSP_ERR_ASSERTION NULL pointer to control or destination parameters or transfer length is zero. + * @retval FSP_ERR_NOT_OPEN The channel has not been opened. Open channel first. + * @retval FSP_ERR_IN_USE A transfer is already in progress. + * @retval FSP_ERR_INVALID_ARGUMENT A bit length not supported by this device was assigned to the argument. + **********************************************************************************************************************/ +fsp_err_t R_RSPI_Read (spi_ctrl_t * const p_api_ctrl, + void * p_dest, + uint32_t const length, + spi_bit_width_t const bit_width) +{ +#if RSPI_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(p_dest != NULL); +#endif + + return r_rspi_write_read_common(p_api_ctrl, NULL, p_dest, length, bit_width); +} + +/*******************************************************************************************************************//** + * This function transmits data to a SPI device using the TX Only Communications Operation Mode. + * Implements @ref spi_api_t::write. + * + * The function performs the following tasks: + * - Performs parameter checking and processes error conditions. + * - Sets up the instance to complete a SPI write operation. + * + * @retval FSP_SUCCESS Write operation successfully completed. + * @retval FSP_ERR_ASSERTION NULL pointer to control or source parameters or transfer length is zero. + * @retval FSP_ERR_NOT_OPEN The channel has not been opened. Open the channel first. + * @retval FSP_ERR_IN_USE A transfer is already in progress. + * @retval FSP_ERR_INVALID_ARGUMENT A bit length not supported by this device was assigned to the argument. + **********************************************************************************************************************/ +fsp_err_t R_RSPI_Write (spi_ctrl_t * const p_api_ctrl, + void const * p_src, + uint32_t const length, + spi_bit_width_t const bit_width) +{ +#if RSPI_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(p_src != NULL); +#endif + + return r_rspi_write_read_common(p_api_ctrl, p_src, NULL, length, bit_width); +} + +/*******************************************************************************************************************//** + * This function simultaneously transmits and receive data. Implements @ref spi_api_t::writeRead. + * + * The function performs the following tasks: + * - Performs parameter checking and processes error conditions. + * - Sets up the instance to complete a SPI writeRead operation. + * + * @retval FSP_SUCCESS Write operation successfully completed. + * @retval FSP_ERR_ASSERTION NULL pointer to control, source or destination parameters or + * transfer length is zero. + * @retval FSP_ERR_NOT_OPEN The channel has not been opened. Open the channel first. + * @retval FSP_ERR_IN_USE A transfer is already in progress. + * @retval FSP_ERR_INVALID_ARGUMENT A bit length not supported by this device was assigned to the argument. + *********************************************************************************************************************/ +fsp_err_t R_RSPI_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) +{ +#if RSPI_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(p_src != NULL); + FSP_ASSERT(p_dest != NULL); +#endif + + return r_rspi_write_read_common(p_api_ctrl, p_src, p_dest, length, bit_width); +} + +/*******************************************************************************************************************//** + * Updates the user callback and has option of providing memory for callback structure. + * Implements spi_api_t::callbackSet + * + * @retval FSP_SUCCESS Callback updated successfully. + * @retval FSP_ERR_ASSERTION A required pointer is NULL. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened. + * @retval FSP_ERR_NO_CALLBACK_MEMORY p_callback is non-secure and p_callback_memory is either secure or NULL. + **********************************************************************************************************************/ +fsp_err_t R_RSPI_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) +{ + rspi_instance_ctrl_t * p_ctrl = (rspi_instance_ctrl_t *) p_api_ctrl; + +#if (RSPI_CFG_PARAM_CHECKING_ENABLE) + FSP_ASSERT(p_ctrl); + FSP_ASSERT(p_callback); + FSP_ERROR_RETURN(RSPI_OPEN == p_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + +#if BSP_TZ_SECURE_BUILD + + /* Get security state of p_callback */ + bool callback_is_secure = + (NULL == cmse_check_address_range((void *) p_callback, sizeof(void *), CMSE_AU_NONSECURE)); + + #if RSPI_CFG_PARAM_CHECKING_ENABLE + + /* In secure projects, p_callback_memory must be provided in non-secure space if p_callback is non-secure */ + spi_callback_args_t * const p_callback_memory_checked = cmse_check_pointed_object(p_callback_memory, + CMSE_AU_NONSECURE); + FSP_ERROR_RETURN(callback_is_secure || (NULL != p_callback_memory_checked), FSP_ERR_NO_CALLBACK_MEMORY); + #endif +#endif + + /* Store callback and context */ +#if BSP_TZ_SECURE_BUILD + p_ctrl->p_callback = callback_is_secure ? p_callback : + (void (*)(spi_callback_args_t *))cmse_nsfptr_create(p_callback); +#else + p_ctrl->p_callback = p_callback; +#endif + p_ctrl->p_context = p_context; + p_ctrl->p_callback_memory = p_callback_memory; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * This function manages the closing of a channel by the following task. Implements @ref spi_api_t::close. + * + * Disables SPI operations by disabling the SPI bus. + * - Disables the SPI peripheral. + * - Disables all the associated interrupts. + * - Update control structure so it will not work with @ref SPI_API functions. + * + * @retval FSP_SUCCESS Channel successfully closed. + * @retval FSP_ERR_ASSERTION A required pointer argument is NULL. + * @retval FSP_ERR_NOT_OPEN The channel has not been opened. Open the channel first. + **********************************************************************************************************************/ +fsp_err_t R_RSPI_Close (spi_ctrl_t * const p_api_ctrl) +{ + rspi_instance_ctrl_t * p_ctrl = (rspi_instance_ctrl_t *) p_api_ctrl; + +#if RSPI_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(RSPI_OPEN == p_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + + p_ctrl->open = 0; + +#if RSPI_CFG_DMAC_ENABLE + if (NULL != p_ctrl->p_cfg->p_transfer_rx) + { + p_ctrl->p_cfg->p_transfer_rx->p_api->close(p_ctrl->p_cfg->p_transfer_rx->p_ctrl); + } + + if (NULL != p_ctrl->p_cfg->p_transfer_tx) + { + p_ctrl->p_cfg->p_transfer_tx->p_api->close(p_ctrl->p_cfg->p_transfer_tx->p_ctrl); + } +#endif + + /* Disable interrupts in NVIC. */ + if (p_ctrl->p_cfg->txi_irq >= 0) + { + R_BSP_IrqDisable(p_ctrl->p_cfg->txi_irq); + } + + if (p_ctrl->p_cfg->rxi_irq >= 0) + { + R_BSP_IrqDisable(p_ctrl->p_cfg->rxi_irq); + } + + R_BSP_IrqDisable(p_ctrl->p_cfg->eri_irq); + + /* Disable the SPI Transfer. */ + p_ctrl->p_regs->SPCR_b.SPE = 0U; + + /* Clear the status register. */ + + /* The status register must be read before cleared. */ + p_ctrl->p_regs->SPSR; + p_ctrl->p_regs->SPSR = 0; + + /* Remove power to the channel. */ + R_BSP_MODULE_STOP(FSP_IP_RSPI, p_ctrl->p_cfg->channel); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Calculates the SPBR register value and the BRDV bits for a desired bitrate. + * Calculates the SPBR register value and the BRDV bits for a desired bitrate. + * If the desired bitrate is faster than the maximum bitrate, then the bitrate is set to the + * maximum bitrate and an error is returned. + * If the desired bitrate is slower than the minimum bitrate, then an error is returned. + * + * @param[in] bitrate Desired bitrate. + * @param[out] spck_div Memory location to store bitrate register settings. + * + * @retval FSP_SUCCESS Valid spbr and brdv values were calculated. + * @retval FSP_ERR_UNSUPPORTED Bitrate is out of the settable range. + **********************************************************************************************************************/ +fsp_err_t R_RSPI_CalculateBitrate (uint32_t bitrate, rspi_rspck_div_setting_t * spck_div) +{ + /* desired_divider = Smallest integer greater than or equal to RSPI_CLOCK / bitrate. */ + uint32_t desired_divider = (R_FSP_SystemClockHzGet(BSP_FEATURE_RSPI_CLOCK) + bitrate - 1) / bitrate; + + /* + * Possible SPI_CLK dividers for values of N: + * N = 0; div = [2,4,6,..,512] + * N = 1; div = [4,8,12,..,1024] + * N = 2; div = [8,16,32,..,2048] + * N = 3; div = [16,32,64,..,4096] + */ + uint8_t i; + for (i = 0; i < 4; i++) + { + /* Select smallest value for N possible. */ + + /* div <= 512; N = 0 + * 512 < div <= 1024; N=1 + * ... + */ + if (desired_divider <= (RSPI_CLK_N_DIV_MULTIPLIER << i)) + { + break; + } + } + + spck_div->brdv = i & 0x03U; + + /* + * desired_divider = 2 * (spbr + 1) * 2^i. + * + * With desired_divider and i known, solve for spbr. + * + * spbr = SPI_CLK_DIV / (2 * 2^i) - 1 + */ + uint32_t spbr_divisor = (2U * (1U << i)); + + /* spbr = (Smallest integer greater than or equal to SPI_CLK_DIV / (2 * 2^i)) - 1. */ + spck_div->spbr = (uint8_t) (((desired_divider + spbr_divisor - 1U) / spbr_divisor) - 1U) & UINT8_MAX; + + /* Can't achieve bitrate faster or slower than desired. */ + if ((desired_divider > BSP_FEATURE_RSPI_CLK_MAX_DIV) || + ((R_FSP_SystemClockHzGet(BSP_FEATURE_RSPI_CLOCK) / bitrate) < BSP_FEATURE_RSPI_CLK_MIN_DIV)) + { + return FSP_ERR_UNSUPPORTED; + } + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * @} (end addtogroup RSPI) + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Private Functions + **********************************************************************************************************************/ + +#if RSPI_CFG_DMAC_ENABLE + +/*******************************************************************************************************************//** + * Configure the given transfer instances for receiving and transmitting data without CPU intervention. + * + * @param p_cfg Configuration structure with references to receive and transmit transfer instances. + * + * @retval FSP_SUCCESS The given transfer instances were configured successfully. + * @return See @ref RENESAS_ERROR_CODES for other possible return codes. This function internally + * calls @ref transfer_api_t::open. + **********************************************************************************************************************/ +static fsp_err_t r_rspi_transfer_config (rspi_instance_ctrl_t * p_ctrl, spi_cfg_t const * const p_cfg) +{ + fsp_err_t err = FSP_SUCCESS; + + const transfer_instance_t * p_transfer_tx = p_cfg->p_transfer_tx; + void * p_spdr = (void *) &(p_ctrl->p_regs->SPDR); + + if (p_transfer_tx) + { + p_transfer_tx->p_cfg->p_info->p_dest = p_spdr; + + err = p_transfer_tx->p_api->open(p_transfer_tx->p_ctrl, p_transfer_tx->p_cfg); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + } + + const transfer_instance_t * p_transfer_rx = p_cfg->p_transfer_rx; + if (p_transfer_rx) + { + p_transfer_rx->p_cfg->p_info->p_src = p_spdr; + + err = p_transfer_rx->p_api->open(p_transfer_rx->p_ctrl, p_transfer_rx->p_cfg); + + if ((FSP_SUCCESS != err) && p_transfer_tx) + { + p_transfer_tx->p_api->close(p_transfer_tx->p_ctrl); + } + } + + return err; +} + +#endif + +/*******************************************************************************************************************//** + * initialize control structure + * + * @param[in] p_ctrl pointer to control structure. + * @param[in] p_cfg pointer to API configuration structure. + **********************************************************************************************************************/ +static void r_rspi_init_control_structure (rspi_instance_ctrl_t * p_ctrl, spi_cfg_t const * const p_cfg) +{ + /* initialize by config parameter */ + p_ctrl->p_cfg = p_cfg; + p_ctrl->p_callback = p_cfg->p_callback; + p_ctrl->p_context = p_cfg->p_context; + p_ctrl->p_ext = (rspi_extended_cfg_t *) p_cfg->p_extend; + p_ctrl->p_callback_memory = NULL; + + /* register base address */ + ptrdiff_t size_of_regs = (ptrdiff_t) R_RSPI1 - (ptrdiff_t) R_RSPI0; + p_ctrl->p_regs = (R_RSPI0_Type *) ((ptrdiff_t) R_RSPI0 + (size_of_regs * p_ctrl->p_cfg->channel)); + + /* Clear flags */ + p_ctrl->transfer_is_pending = false; +} + +/*******************************************************************************************************************//** + * Hardware configuration for settings given by the configuration structure. + * + * @param[in] p_ctrl pointer to control structure. + **********************************************************************************************************************/ +static void r_rspi_hw_config (rspi_instance_ctrl_t * p_ctrl) +{ + uint32_t sslp = 0; + uint32_t sppcr = 0; + uint32_t spdcr = 0; + uint32_t spckd = 0; + uint32_t sslnd = 0; + uint32_t spnd = 0; + uint32_t spcmd0 = 0; + uint32_t spbfcr = 0; + uint32_t spcr = 0; + + /* Enable IP */ + R_BSP_MODULE_START(FSP_IP_RSPI, p_ctrl->p_cfg->channel); + + /* Reset SPI controller */ + p_ctrl->p_regs->SPCR = (uint8_t) spcr; + + /* Enable Error interrupt only in slave mode. */ + if (SPI_MODE_SLAVE == p_ctrl->p_cfg->operating_mode) + { + spcr |= R_RSPI0_SPCR_SPEIE_Msk; + } + + /* Configure Master Mode setting. */ + if (SPI_MODE_MASTER == p_ctrl->p_cfg->operating_mode) + { + spcr |= R_RSPI0_SPCR_MSTR_Msk; + } + + /* Configure CPHA setting. */ + if (SPI_CLK_PHASE_EDGE_EVEN == p_ctrl->p_cfg->clk_phase) + { + spcmd0 |= R_RSPI0_SPCMD0_CPHA_Msk; + } + + /* Configure CPOL setting. */ + if (SPI_CLK_POLARITY_HIGH == p_ctrl->p_cfg->clk_polarity) + { + spcmd0 |= R_RSPI0_SPCMD0_CPOL_Msk; + } + + /* Configure Bit Order (MSB,LSB) */ + if (SPI_BIT_ORDER_LSB_FIRST == p_ctrl->p_cfg->bit_order) + { + spcmd0 |= R_RSPI0_SPCMD0_LSBF_Msk; + } + + rspi_extended_cfg_t * p_extend = ((rspi_extended_cfg_t *) p_ctrl->p_cfg->p_extend); + + /* Configure SSL Level Keep Setting.(Can be set only in master mode)*/ + spcmd0 |= + (uint32_t) (((!p_ctrl->p_cfg->operating_mode) & p_extend->ssl_level_keep) << R_RSPI0_SPCMD0_SSLKP_Pos); + + /* Configure SSLn polarity setting. */ + if (RSPI_SSLP_HIGH == p_extend->ssl_polarity) + { + sslp |= R_RSPI0_SSLP_SSL0P_Msk; + } + + if (RSPI_MOSI_IDLE_VALUE_FIXING_DISABLE != p_extend->mosi_idle) + { + /* Enable mosi value fixing */ + sppcr |= R_RSPI0_SPPCR_MOIFE_Msk; + + if (RSPI_MOSI_IDLE_VALUE_FIXING_HIGH == p_extend->mosi_idle) + { + sppcr |= R_RSPI0_SPPCR_MOIFV_Msk; + } + } + + /* Configure the Bit Rate Division Setting */ + spcmd0 |= ((unsigned) p_extend->spck_div.brdv << R_RSPI0_SPCMD0_BRDV_Pos); + + /* Set 8bit transfer */ + spcmd0 |= RSPI_SPCMD_WIDTH_8BIT; + + /* Enable all delay settings. */ + if (SPI_MODE_MASTER == p_ctrl->p_cfg->operating_mode) + { + /* Note that disabling delay settings is same as setting delay to 1. */ + spcmd0 |= (R_RSPI0_SPCMD0_SPNDEN_Msk | R_RSPI0_SPCMD0_SLNDEN_Msk | R_RSPI0_SPCMD0_SCKDEN_Msk); + + spckd = p_extend->spck_delay; + sslnd = p_extend->ssl_negation_delay; + spnd = p_extend->next_access_delay; + } + + /* Pre-storing TX FIFO trigger level (not write at this time) */ + if (p_ctrl->p_cfg->p_transfer_tx) + { + spbfcr |= ((unsigned) RSPI_TX_TRIGGER_0 << R_RSPI0_SPBFCR_TXTRG_Pos); + } + else + { + spbfcr |= ((unsigned) p_extend->tx_trigger_level << R_RSPI0_SPBFCR_TXTRG_Pos); + } + + /* Reset FIFOs */ + p_ctrl->p_regs->SPBFCR = (uint8_t) (spbfcr | R_RSPI0_SPBFCR_RXRST_Msk | R_RSPI0_SPBFCR_TXRST_Msk); + + /* Clear the status register. */ + p_ctrl->p_regs->SPSR; + p_ctrl->p_regs->SPSR = 0; + + /* Write registers */ + p_ctrl->p_regs->SSLP = (uint8_t) sslp; + p_ctrl->p_regs->SPPCR = (uint8_t) sppcr; + p_ctrl->p_regs->SPBR = p_extend->spck_div.spbr; + p_ctrl->p_regs->SPDCR = (uint8_t) spdcr; + p_ctrl->p_regs->SPCKD = (uint8_t) spckd; + p_ctrl->p_regs->SSLND = (uint8_t) sslnd; + p_ctrl->p_regs->SPND = (uint8_t) spnd; + p_ctrl->p_regs->SPCMD0 = (uint16_t) spcmd0; + p_ctrl->p_regs->SPSCR = 0; + p_ctrl->p_regs->SPBFCR = (uint8_t) spbfcr; + p_ctrl->p_regs->SPCR = (uint8_t) spcr; +} + +/*******************************************************************************************************************//** + * Enable Receive Buffer Full, Transmit Buffer Empty, and Error Interrupts in the NVIC. + * + * @param[in] p_ctrl pointer to control structure. + **********************************************************************************************************************/ +static void r_rspi_nvic_config (rspi_instance_ctrl_t * p_ctrl) +{ + if (p_ctrl->p_cfg->txi_irq >= 0) + { + R_BSP_IrqCfgEnable(p_ctrl->p_cfg->txi_irq, p_ctrl->p_cfg->txi_ipl, p_ctrl); + } + + if (p_ctrl->p_cfg->rxi_irq >= 0) + { + R_BSP_IrqCfgEnable(p_ctrl->p_cfg->rxi_irq, p_ctrl->p_cfg->rxi_ipl, p_ctrl); + } + + R_BSP_IrqCfgEnable(p_ctrl->p_cfg->eri_irq, p_ctrl->p_cfg->eri_ipl, p_ctrl); +} + +/*******************************************************************************************************************//** + * Setup the bit width configuration for a transfer. + * + * @param[in] p_ctrl pointer to control structure. + * + * Note: For 8-Bit wide data frames, the devices require the SPBYT bit to enable byte level access to the + * data register. Although this register is not documented in some MCU hardware manuals, it does seem to be available + * on all of them. + **********************************************************************************************************************/ +static void r_rspi_bit_width_config (rspi_instance_ctrl_t * p_ctrl) +{ + uint32_t spdcr = p_ctrl->p_regs->SPDCR; + uint32_t spcmd0 = p_ctrl->p_regs->SPCMD0; + + spdcr &= (uint32_t) (~R_RSPI0_SPDCR_SPLW_Msk); + spcmd0 &= (uint32_t) (~R_RSPI0_SPCMD0_SPB_Msk); + if (SPI_BIT_WIDTH_8_BITS == p_ctrl->bit_width) + { + /* Configure byte access to data register. */ + spdcr |= RSPI_SPDCR_WIDTH_8BIT; + + /* Configure 8-Bit Mode. */ + spcmd0 |= RSPI_SPCMD_WIDTH_8BIT; + } + else if (SPI_BIT_WIDTH_16_BITS == p_ctrl->bit_width) + { + /* Configure Half-Word access to data register. */ + spdcr |= RSPI_SPDCR_WIDTH_16BIT; + + /* Configure 16-Bit Mode. */ + spcmd0 |= RSPI_SPCMD_WIDTH_16BIT; + } + else /* SPI_BIT_WIDTH_32_BITS */ + { + /* Configure Word access to data register. */ + spdcr |= RSPI_SPDCR_WIDTH_32BIT; + + /* Configure 32-Bit Mode. */ + spcmd0 |= RSPI_SPCMD_WIDTH_32BIT; + } + + p_ctrl->p_regs->SPDCR = (uint8_t) spdcr; + p_ctrl->p_regs->SPCMD0 = (uint16_t) spcmd0; +} + +/*******************************************************************************************************************//** + * Setup hint of RX FIFO trigger level + * + * @param[in] p_ctrl pointer to control structure. + **********************************************************************************************************************/ +static void r_rspi_set_rx_fifo_hint (rspi_instance_ctrl_t * p_ctrl) +{ + rspi_rx_trigger_level_t level = p_ctrl->p_ext->rx_trigger_level; + if (SPI_BIT_WIDTH_8_BITS == p_ctrl->bit_width) + { + /* No restrictions */ + } + else if (SPI_BIT_WIDTH_16_BITS == p_ctrl->bit_width) + { + /* at least 2 bytes required, override as 2 byte */ + switch (level) + { + case RSPI_RX_TRIGGER_1: + { + level = RSPI_RX_TRIGGER_2; + break; + } + + default: + { + break; + } + } + } + else + { + /* at least 4 bytes required, override as 4 byte */ + switch (level) + { + case RSPI_RX_TRIGGER_1: + case RSPI_RX_TRIGGER_2: + { + level = RSPI_RX_TRIGGER_4; + break; + } + + default: + { + break; + } + } + } + + /* Save hint value */ + switch (level) + { + case RSPI_RX_TRIGGER_1: + { + p_ctrl->rxfifo_trigger_bytes = RSPI_RXTRG_1BYTE_COUNT; + break; + } + + case RSPI_RX_TRIGGER_2: + { + p_ctrl->rxfifo_trigger_bytes = RSPI_RXTRG_2BYTE_COUNT; + break; + } + + case RSPI_RX_TRIGGER_4: + { + p_ctrl->rxfifo_trigger_bytes = RSPI_RXTRG_4BYTE_COUNT; + break; + } + + case RSPI_RX_TRIGGER_8: + { + p_ctrl->rxfifo_trigger_bytes = RSPI_RXTRG_8BYTE_COUNT; + break; + } + + case RSPI_RX_TRIGGER_16: + { + p_ctrl->rxfifo_trigger_bytes = RSPI_RXTRG_16BYTE_COUNT; + break; + } + + case RSPI_RX_TRIGGER_24: + { + p_ctrl->rxfifo_trigger_bytes = RSPI_RXTRG_24BYTE_COUNT; + break; + } + + case RSPI_RX_TRIGGER_32: + { + p_ctrl->rxfifo_trigger_bytes = RSPI_RXTRG_32BYTE_COUNT; + break; + } + + default: + { + p_ctrl->rxfifo_trigger_bytes = RSPI_RXTRG_5BYTE_COUNT; + break; + } + } + + r_rspi_set_rxtrg(p_ctrl, level); +} + +/*******************************************************************************************************************//** + * Setup RXTRG bit + * + * @param[in] p_ctrl pointer to control structure. + * @param[in] level trigger level + **********************************************************************************************************************/ +static void r_rspi_set_rxtrg (rspi_instance_ctrl_t * p_ctrl, rspi_rx_trigger_level_t level) +{ + if (p_ctrl->p_cfg->p_transfer_rx) + { + level = RSPI_RX_TRIGGER_1; + } + + uint8_t spbfcr = p_ctrl->p_regs->SPBFCR; + spbfcr &= (uint8_t) (~R_RSPI0_SPBFCR_RXTRG_Msk); + spbfcr |= (uint8_t) (level << R_RSPI0_SPBFCR_RXTRG_Pos); + p_ctrl->p_regs->SPBFCR = spbfcr; +} + +/*******************************************************************************************************************//** + * Setup RX FIFO level for fitting in transfer progress. + * + * @param[in] p_ctrl pointer to control structure. + **********************************************************************************************************************/ +static void r_rspi_set_rx_fifo_level (rspi_instance_ctrl_t * p_ctrl) +{ + uint32_t bytes_remained = p_ctrl->rx_count * (p_ctrl->bit_width + 1) >> 3; + if (bytes_remained >= p_ctrl->rxfifo_trigger_bytes) + { + /* More than FIFO trigger data left : do nothing */ + } + else if (bytes_remained >= RSPI_RXTRG_24BYTE_COUNT) + { + /* more than or equal 24: to 24 bytes */ + r_rspi_set_rxtrg(p_ctrl, RSPI_RXTRG_24BYTE); + } + else if (bytes_remained >= RSPI_RXTRG_16BYTE_COUNT) + { + /* more than or equal 16: to 16 bytes */ + r_rspi_set_rxtrg(p_ctrl, RSPI_RXTRG_16BYTE); + } + else if (bytes_remained >= RSPI_RXTRG_8BYTE_COUNT) + { + /* more than or equal 8: to 8 bytes */ + r_rspi_set_rxtrg(p_ctrl, RSPI_RXTRG_8BYTE); + } + else if (bytes_remained >= RSPI_RXTRG_5BYTE_COUNT) + { + /* more than or equal 5: to 5 bytes */ + r_rspi_set_rxtrg(p_ctrl, RSPI_RXTRG_5BYTE); + } + else if (bytes_remained >= RSPI_RXTRG_4BYTE_COUNT) + { + /* more than or equal 4: to 4 bytes */ + r_rspi_set_rxtrg(p_ctrl, RSPI_RXTRG_4BYTE); + } + else if (bytes_remained >= RSPI_RXTRG_2BYTE_COUNT) + { + /* more than or equal 2: to 2 bytes */ + r_rspi_set_rxtrg(p_ctrl, RSPI_RXTRG_2BYTE); + } + else + { + /* 1: to 1 bytes */ + r_rspi_set_rxtrg(p_ctrl, RSPI_RXTRG_1BYTE); + } +} + +/*******************************************************************************************************************//** + * Configures the driver state and initiates a SPI transfer for all modes of operation. + * + * @param[in] p_api_ctrl pointer to control structure. + * @param p_src Buffer to transmit data from. + * @param p_dest Buffer to store received data in. + * @param[in] length Number of transfers + * @param[in] bit_width Data frame size (8-Bit, 16-Bit, 32-Bit) + * + * @retval FSP_SUCCESS Transfer was started successfully. + * @retval FSP_ERR_ASSERTION An argument is invalid. + * @retval FSP_ERR_NOT_OPEN The instance has not been initialized. + * @retval FSP_ERR_IN_USE A transfer is already in progress. + * @retval FSP_ERR_INVALID_ARGUMENT A bit length not supported by this device was assigned to the argument. + * @return See @ref RENESAS_ERROR_CODES for other possible return codes. This function internally + * calls @ref transfer_api_t::reconfigure. + **********************************************************************************************************************/ +static fsp_err_t r_rspi_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) +{ + rspi_instance_ctrl_t * p_ctrl = (rspi_instance_ctrl_t *) p_api_ctrl; + +#if RSPI_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(RSPI_OPEN == p_ctrl->open, FSP_ERR_NOT_OPEN); + FSP_ASSERT(p_src || p_dest); + FSP_ASSERT(0 != length); +#endif + + /* Reject bit width settings not compatible with R_RSPI */ + FSP_ERROR_RETURN(((SPI_BIT_WIDTH_8_BITS == bit_width) || + (SPI_BIT_WIDTH_16_BITS == bit_width) || + (SPI_BIT_WIDTH_32_BITS == bit_width)), + FSP_ERR_INVALID_ARGUMENT); + + FSP_ERROR_RETURN(false == p_ctrl->transfer_is_pending, FSP_ERR_IN_USE); + + /* Save transfer data */ + p_ctrl->p_tx_data = p_src; + p_ctrl->p_rx_data = p_dest; + p_ctrl->tx_count = length; + p_ctrl->rx_count = length; + p_ctrl->bit_width = bit_width; + +#if RSPI_CFG_DMAC_ENABLE + if (p_ctrl->p_cfg->p_transfer_rx) + { + /* When the rxi interrupt is called, all transfers will be finished. */ + p_ctrl->rx_count = 0; + + /* The number of bytes transferred by DMAC is specified here, but it varies depending on the data width. */ + p_ctrl->p_cfg->p_transfer_rx->p_cfg->p_info->length = length; + + /* Configure the receive DMA instance. */ + if (SPI_BIT_WIDTH_16_BITS < p_ctrl->bit_width) + { + p_ctrl->p_cfg->p_transfer_rx->p_cfg->p_info->length = length * 4; + + p_ctrl->p_cfg->p_transfer_rx->p_cfg->p_info->src_size = TRANSFER_SIZE_4_BYTE; + p_ctrl->p_cfg->p_transfer_rx->p_cfg->p_info->dest_size = TRANSFER_SIZE_4_BYTE; + } + else if (SPI_BIT_WIDTH_8_BITS >= p_ctrl->bit_width) + { + p_ctrl->p_cfg->p_transfer_rx->p_cfg->p_info->src_size = TRANSFER_SIZE_1_BYTE; + p_ctrl->p_cfg->p_transfer_rx->p_cfg->p_info->dest_size = TRANSFER_SIZE_1_BYTE; + } + else + { + p_ctrl->p_cfg->p_transfer_rx->p_cfg->p_info->length = length * 2; + + p_ctrl->p_cfg->p_transfer_rx->p_cfg->p_info->src_size = TRANSFER_SIZE_2_BYTE; + p_ctrl->p_cfg->p_transfer_rx->p_cfg->p_info->dest_size = TRANSFER_SIZE_2_BYTE; + } + + p_ctrl->p_cfg->p_transfer_rx->p_cfg->p_info->dest_addr_mode = TRANSFER_ADDR_MODE_INCREMENTED; + p_ctrl->p_cfg->p_transfer_rx->p_cfg->p_info->p_dest = p_dest; + + if (NULL == p_dest) + { + static uint32_t dummy_rx; + p_ctrl->p_cfg->p_transfer_rx->p_cfg->p_info->dest_addr_mode = TRANSFER_ADDR_MODE_FIXED; + p_ctrl->p_cfg->p_transfer_rx->p_cfg->p_info->p_dest = &dummy_rx; + } + + fsp_err_t err = p_ctrl->p_cfg->p_transfer_rx->p_api->reconfigure(p_ctrl->p_cfg->p_transfer_rx->p_ctrl, + p_ctrl->p_cfg->p_transfer_rx->p_cfg->p_info); + + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + } + + if (p_ctrl->p_cfg->p_transfer_tx) + { + /* When the txi interrupt is called, all transfers will be finished. */ + p_ctrl->tx_count = 0; + + /* The number of bytes transferred by DMAC is specified here, but it varies depending on the data width. */ + p_ctrl->p_cfg->p_transfer_tx->p_cfg->p_info->length = length; + + /* Configure the transmit DMA instance. */ + if (SPI_BIT_WIDTH_16_BITS < p_ctrl->bit_width) + { + p_ctrl->p_cfg->p_transfer_tx->p_cfg->p_info->length = length * 4; + + p_ctrl->p_cfg->p_transfer_tx->p_cfg->p_info->src_size = TRANSFER_SIZE_4_BYTE; + p_ctrl->p_cfg->p_transfer_tx->p_cfg->p_info->dest_size = TRANSFER_SIZE_4_BYTE; + } + else if (SPI_BIT_WIDTH_8_BITS >= p_ctrl->bit_width) + { + p_ctrl->p_cfg->p_transfer_tx->p_cfg->p_info->src_size = TRANSFER_SIZE_1_BYTE; + p_ctrl->p_cfg->p_transfer_tx->p_cfg->p_info->dest_size = TRANSFER_SIZE_1_BYTE; + } + else + { + p_ctrl->p_cfg->p_transfer_tx->p_cfg->p_info->length = length * 2; + + p_ctrl->p_cfg->p_transfer_tx->p_cfg->p_info->src_size = TRANSFER_SIZE_2_BYTE; + p_ctrl->p_cfg->p_transfer_tx->p_cfg->p_info->dest_size = TRANSFER_SIZE_2_BYTE; + } + + p_ctrl->p_cfg->p_transfer_tx->p_cfg->p_info->src_addr_mode = TRANSFER_ADDR_MODE_INCREMENTED; + p_ctrl->p_cfg->p_transfer_tx->p_cfg->p_info->p_src = p_src; + + if (NULL == p_src) + { + static uint32_t dummy_tx = 0; + p_ctrl->p_cfg->p_transfer_tx->p_cfg->p_info->src_addr_mode = TRANSFER_ADDR_MODE_FIXED; + p_ctrl->p_cfg->p_transfer_tx->p_cfg->p_info->p_src = &dummy_tx; + } + + /* Disable the TX buffer empty interrupt before enabling transfer. */ + p_ctrl->p_regs->SPCR_b.SPTIE = 0; + + fsp_err_t err = p_ctrl->p_cfg->p_transfer_tx->p_api->reconfigure(p_ctrl->p_cfg->p_transfer_tx->p_ctrl, + p_ctrl->p_cfg->p_transfer_tx->p_cfg->p_info); + + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + } +#endif + + /* Set transfer width */ + r_rspi_bit_width_config(p_ctrl); + + /* Set hint value for RX FIFO level */ + r_rspi_set_rx_fifo_hint(p_ctrl); + + /* Update receiver FIFO trigger level */ + r_rspi_set_rx_fifo_level(p_ctrl); + + /* Preparing transmitter */ + r_rspi_transmit(p_ctrl); + + uint32_t spcr = p_ctrl->p_regs->SPCR; + if (p_ctrl->tx_count || p_ctrl->p_cfg->p_transfer_tx) + { + /* More data remained */ + spcr |= R_RSPI0_SPCR_SPTIE_Msk; + } + + /* Enable receiver interrupt */ + spcr |= R_RSPI0_SPCR_SPRIE_Msk; + + /* Set pending flag */ + p_ctrl->transfer_is_pending = true; + + /* Set spcr.SPE (may cleared by error interrupt) */ + spcr |= R_RSPI0_SPCR_SPE_Msk; + + /* Write register */ + p_ctrl->p_regs->SPCR = (uint8_t) spcr; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Receive and store + * If the receive buffer is NULL, just read the RSPI data register. + * If the total transfer length has already been received then do termination the transaction + * + * @param[in] p_ctrl pointer to control structure. + **********************************************************************************************************************/ +static void r_rspi_receive (rspi_instance_ctrl_t * p_ctrl) +{ + uint32_t rx_count = p_ctrl->rx_count; + uint32_t data_count = (p_ctrl->p_regs->SPBFDR & R_RSPI0_SPBFDR_R_Msk) >> R_RSPI0_SPBFDR_R_Pos; + + if (SPI_BIT_WIDTH_8_BITS == p_ctrl->bit_width) + { + uint8_t * p_rbuf = p_ctrl->p_rx_data; + data_count /= 1; + while (data_count && rx_count) + { + uint8_t data = p_ctrl->p_regs->SPDR_byte.LL; + if (p_rbuf) + { + *p_rbuf = data; + ++p_rbuf; + } + + --data_count; + --rx_count; + } + + p_ctrl->p_rx_data = p_rbuf; + p_ctrl->rx_count = rx_count; + } + else if (SPI_BIT_WIDTH_16_BITS == p_ctrl->bit_width) + { + uint16_t * p_rbuf = p_ctrl->p_rx_data; + data_count /= 2; + while (data_count && rx_count) + { + uint16_t data = p_ctrl->p_regs->SPDR_hword.L; + if (p_rbuf) + { + *p_rbuf = data; + ++p_rbuf; + } + + --data_count; + --rx_count; + } + + p_ctrl->p_rx_data = p_rbuf; + p_ctrl->rx_count = rx_count; + } + else /* SPI_BIT_WIDTH_32_BITS */ + { + uint32_t * p_rbuf = p_ctrl->p_rx_data; + data_count /= 4; + while (data_count && rx_count) + { + uint32_t data = p_ctrl->p_regs->SPDR; + if (p_rbuf) + { + *p_rbuf = data; + ++p_rbuf; + } + + --data_count; + --rx_count; + } + + p_ctrl->p_rx_data = p_rbuf; + p_ctrl->rx_count = rx_count; + } + + /* Update RX FIFO trigger level */ + r_rspi_set_rx_fifo_level(p_ctrl); + + if (0 == rx_count) + { + /* Disable receive interrupt */ + p_ctrl->p_regs->SPCR &= (uint8_t) (~R_RSPI0_SPCR_SPRIE_Msk); + + /* Clear transfer pending flag */ + p_ctrl->transfer_is_pending = false; + + /* Signal that a transfer has completed. */ + r_rspi_call_callback(p_ctrl, SPI_EVENT_TRANSFER_COMPLETE); + } +} + +/*******************************************************************************************************************//** + * Load and transmit + * If the transmit buffer is NULL, than write zero to the RSPI data register. + * If the total transfer length has already been transmitted then do nothing. + * + * @param[in] p_ctrl pointer to control structure. + **********************************************************************************************************************/ +static void r_rspi_transmit (rspi_instance_ctrl_t * p_ctrl) +{ + uint32_t data_count = (p_ctrl->p_regs->SPBFDR & R_RSPI0_SPBFDR_T_Msk) >> R_RSPI0_SPBFDR_T_Pos; + data_count = RSPI_TX_FIFO_SIZE - data_count; + uint32_t tx_count = p_ctrl->tx_count; + + if (SPI_BIT_WIDTH_8_BITS == p_ctrl->bit_width) + { + /* transfer by 8bit */ + uint8_t * p_tbuf = (uint8_t *) p_ctrl->p_tx_data; + data_count /= 1; + while (data_count && tx_count) + { + uint8_t data; + if (p_tbuf) + { + data = *p_tbuf; + ++p_tbuf; + } + else + { + data = 0; + } + + p_ctrl->p_regs->SPDR_byte.LL = data; + --data_count; + --tx_count; + } + + p_ctrl->p_tx_data = p_tbuf; + p_ctrl->tx_count = tx_count; + } + else if (SPI_BIT_WIDTH_16_BITS == p_ctrl->bit_width) + { + /* transfer by 16bit */ + uint16_t * p_tbuf = (uint16_t *) p_ctrl->p_tx_data; + data_count /= 2; + while (data_count && tx_count) + { + uint16_t data; + if (p_tbuf) + { + data = *p_tbuf; + ++p_tbuf; + } + else + { + data = 0; + } + + p_ctrl->p_regs->SPDR_hword.L = data; + --data_count; + --tx_count; + } + + p_ctrl->p_tx_data = p_tbuf; + p_ctrl->tx_count = tx_count; + } + else /* SPI_BIT_WIDTH_32_BITS */ + { + /* transfer by 32bit */ + uint32_t * p_tbuf = (uint32_t *) p_ctrl->p_tx_data; + data_count /= 4; + while (data_count && tx_count) + { + uint32_t data; + if (p_tbuf) + { + data = *p_tbuf; + ++p_tbuf; + } + else + { + data = 0; + } + + p_ctrl->p_regs->SPDR = data; + --data_count; + --tx_count; + } + + p_ctrl->p_tx_data = p_tbuf; + p_ctrl->tx_count = tx_count; + } + + if (0 == tx_count) + { + /* Disable transmit interrupt if no more transmit data */ + p_ctrl->p_regs->SPCR &= (uint8_t) (~R_RSPI0_SPCR_SPTIE_Msk); + } +} + +/*******************************************************************************************************************//** + * Calls user callback. + * + * @param[in] p_ctrl Pointer to RSPI instance control block + * @param[in] event Event code + **********************************************************************************************************************/ +static void r_rspi_call_callback (rspi_instance_ctrl_t * p_ctrl, spi_event_t event) +{ + spi_callback_args_t args; + + /* Store callback arguments in memory provided by user if available. This allows callback arguments to be + * stored in non-secure memory so they can be accessed by a non-secure callback function. */ + spi_callback_args_t * p_args = p_ctrl->p_callback_memory; + if (NULL == p_args) + { + /* Store on stack */ + p_args = &args; + } + else + { + /* Save current arguments on the stack in case this is a nested interrupt. */ + args = *p_args; + } + + p_args->channel = p_ctrl->p_cfg->channel; + p_args->event = event; + p_args->p_context = p_ctrl->p_context; + +#if BSP_TZ_SECURE_BUILD + + /* p_callback can point to a secure function or a non-secure function. */ + if (!cmse_is_nsfptr(p_ctrl->p_callback)) + { + /* If p_callback is secure, then the project does not need to change security state. */ + p_ctrl->p_callback(p_args); + } + else + { + /* If p_callback is Non-secure, then the project must change to Non-secure state in order to call the + * callback. */ + spi_prv_ns_callback p_callback = (spi_prv_ns_callback) (p_ctrl->p_callback); + p_callback(p_args); + } + +#else + + /* If the project is not Trustzone Secure, then it will never need to change security state in order to call the + * callback. */ + p_ctrl->p_callback(p_args); +#endif + if (NULL != p_ctrl->p_callback_memory) + { + /* Restore callback memory in case this is a nested interrupt. */ + *p_ctrl->p_callback_memory = args; + } +} + +/*******************************************************************************************************************//** + * ISR called when data is loaded into SPI data register from the shift register. + **********************************************************************************************************************/ +void rspi_rxi_isr (void) +{ + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE + + IRQn_Type irq = R_FSP_CurrentIrqGet(); + R_BSP_IrqStatusClear(irq); + + rspi_instance_ctrl_t * p_ctrl = (rspi_instance_ctrl_t *) R_FSP_IsrContextGet(irq); + + r_rspi_receive(p_ctrl); + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE +} + +/*******************************************************************************************************************//** + * ISR called when data is copied from the SPI data register into the SPI shift register. + **********************************************************************************************************************/ +void rspi_txi_isr (void) +{ + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE + + IRQn_Type irq = R_FSP_CurrentIrqGet(); + R_BSP_IrqStatusClear(irq); + + rspi_instance_ctrl_t * p_ctrl = (rspi_instance_ctrl_t *) R_FSP_IsrContextGet(irq); + + r_rspi_transmit(p_ctrl); + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE +} + +/*******************************************************************************************************************//** + * ISR called in the event that an error occurs (Ex: RX_OVERFLOW). + **********************************************************************************************************************/ +void rspi_eri_isr (void) +{ + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE + + IRQn_Type irq = R_FSP_CurrentIrqGet(); + rspi_instance_ctrl_t * p_ctrl = (rspi_instance_ctrl_t *) R_FSP_IsrContextGet(irq); + + /* Disable the SPI Transfer. */ + p_ctrl->p_regs->SPCR_b.SPE = 0; + + /* Read the status register. */ + uint8_t status = p_ctrl->p_regs->SPSR; + + /* Clear the status register. */ + p_ctrl->p_regs->SPSR = 0; + + /* Check if the error is a Receive Buffer Overflow Error. */ + if (R_RSPI0_SPSR_OVRF_Msk & status) + { + r_rspi_call_callback(p_ctrl, SPI_EVENT_ERR_READ_OVERFLOW); + } + + /* Check if the error is a Mode Fault Error. */ + if (R_RSPI0_SPSR_MODF_Msk & status) + { + r_rspi_call_callback(p_ctrl, SPI_EVENT_ERR_MODE_FAULT); + } + + R_BSP_IrqStatusClear(irq); + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE +} + +#if RSPI_CFG_DMAC_ENABLE + +/*******************************************************************************************************************//** + * Dedicated function for DMAC linkage at the time of transmission. + **********************************************************************************************************************/ +void rspi_tx_dmac_callback (rspi_instance_ctrl_t * p_ctrl) +{ + r_rspi_transmit(p_ctrl); +} + +/*******************************************************************************************************************//** + * Dedicated function for DMAC linkage at the time of reception. + **********************************************************************************************************************/ +void rspi_rx_dmac_callback (rspi_instance_ctrl_t * p_ctrl) +{ + r_rspi_receive(p_ctrl); +} + +#endif + +/* End of file R_SPI. */ diff --git a/zephyr/rz/rz_cfg/fsp_cfg/rzv/r_dmac_b_cfg.h b/zephyr/rz/rz_cfg/fsp_cfg/rzv/r_dmac_b_cfg.h new file mode 100644 index 00000000..81b55656 --- /dev/null +++ b/zephyr/rz/rz_cfg/fsp_cfg/rzv/r_dmac_b_cfg.h @@ -0,0 +1,10 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +#ifndef R_DMAC_B_CFG_H_ +#define R_DMAC_B_CFG_H_ +#define DMAC_B_CFG_PARAM_CHECKING_ENABLE (BSP_CFG_PARAM_CHECKING_ENABLE) +#endif /* R_DMAC_B_CFG_H_ */ diff --git a/zephyr/rz/rz_cfg/fsp_cfg/rzv/r_rspi_cfg.h b/zephyr/rz/rz_cfg/fsp_cfg/rzv/r_rspi_cfg.h new file mode 100644 index 00000000..7f18296a --- /dev/null +++ b/zephyr/rz/rz_cfg/fsp_cfg/rzv/r_rspi_cfg.h @@ -0,0 +1,19 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +#ifndef R_RSPI_CFG_H_ +#define R_RSPI_CFG_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#define RSPI_CFG_PARAM_CHECKING_ENABLE (BSP_CFG_PARAM_CHECKING_ENABLE) +#define RSPI_CFG_DMAC_ENABLE (1) + +#ifdef __cplusplus +} +#endif +#endif /* R_RSPI_CFG_H_ */