diff --git a/drivers/rz/CMakeLists.txt b/drivers/rz/CMakeLists.txt index e6960b45..73c6f4da 100644 --- a/drivers/rz/CMakeLists.txt +++ b/drivers/rz/CMakeLists.txt @@ -39,8 +39,13 @@ zephyr_library_sources_ifdef(CONFIG_USE_RZ_FSP_IOPORT zephyr_library_sources_ifdef(CONFIG_USE_RZ_FSP_SCIF_UART fsp/src/${SOC_SERIES_PREFIX}/r_scif_uart/r_scif_uart.c) -zephyr_library_sources_ifdef(CONFIG_USE_RZ_FSP_ADC - fsp/src/${SOC_SERIES_PREFIX}/r_adc_c/r_adc_c.c) +if(CONFIG_DT_HAS_RENESAS_RZ_ADC_C_ENABLED) + zephyr_library_sources_ifdef(CONFIG_USE_RZ_FSP_ADC + fsp/src/${SOC_SERIES_PREFIX}/r_adc_c/r_adc_c.c) +else() + zephyr_library_sources_ifdef(CONFIG_USE_RZ_FSP_ADC + fsp/src/${SOC_SERIES_PREFIX}/r_adc/r_adc.c) +endif() zephyr_library_sources_ifdef(CONFIG_USE_RZ_FSP_MHU fsp/src/${SOC_SERIES_PREFIX}/r_mhu_ns/r_mhu_ns.c) diff --git a/drivers/rz/README b/drivers/rz/README index e33cc30c..5cac70e1 100644 --- a/drivers/rz/README +++ b/drivers/rz/README @@ -69,3 +69,15 @@ Patch List: drivers/rz/fsp/src/rzg/r_gpt/r_gpt.c drivers/rz/fsp/src/rzt/r_gpt/r_gpt.c drivers/rz/fsp/src/rzn/r_gpt/r_gpt.c + + * Rename adc_scan_end_isr, g_adc_on_adc to adc_c_scan_end_isr, g_adc_on_adc_c with _c suffix + respectively to match with ADC_C FSP driver and make the Zephyr ADC driver generic + Impacted files: + drivers/rz/fsp/src/rza/r_adc_c/r_adc_c.c + drivers/rz/fsp/inc/instances/rza/r_adc_c.h + + * Rename g_adc_on_adc to g_adc_on_adc_c with _c suffix to match with ADC_C FSP driver and + make the Zephyr ADC driver generic + Impacted files: + drivers/rz/fsp/src/rzg/r_adc_c/r_adc_c.c + drivers/rz/fsp/inc/instances/rzg/r_adc_c.h diff --git a/drivers/rz/fsp/inc/api/r_elc_api.h b/drivers/rz/fsp/inc/api/r_elc_api.h new file mode 100644 index 00000000..89995654 --- /dev/null +++ b/drivers/rz/fsp/inc/api/r_elc_api.h @@ -0,0 +1,160 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*******************************************************************************************************************//** + * @ingroup RENESAS_SYSTEM_INTERFACES + * @defgroup ELC_API ELC Interface + * @brief Interface for the Event Link Controller. + * + * + * + * @{ + **********************************************************************************************************************/ + +#ifndef R_ELC_API_H +#define R_ELC_API_H + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ + +/* Register definitions, common services and error codes. */ +#include "bsp_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 + **********************************************************************************************************************/ +#ifndef ELC_PERIPHERAL_NUM + #define ELC_PERIPHERAL_NUM (23U) +#endif + +/********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +#ifndef BSP_OVERRIDE_ELC_PERIPHERAL_T + +/** Possible peripherals to be linked to event signals (not all available on all MCUs) */ +typedef enum e_elc_peripheral +{ + ELC_PERIPHERAL_GPT_A = (0), + ELC_PERIPHERAL_GPT_B = (1), + ELC_PERIPHERAL_GPT_C = (2), + ELC_PERIPHERAL_GPT_D = (3), + ELC_PERIPHERAL_GPT_E = (4), + ELC_PERIPHERAL_GPT_F = (5), + ELC_PERIPHERAL_GPT_G = (6), + ELC_PERIPHERAL_GPT_H = (7), + ELC_PERIPHERAL_ADC0 = (8), + ELC_PERIPHERAL_ADC0_B = (9), + ELC_PERIPHERAL_ADC1 = (10), + ELC_PERIPHERAL_ADC1_B = (11), + ELC_PERIPHERAL_DAC0 = (12), + ELC_PERIPHERAL_DAC1 = (13), + ELC_PERIPHERAL_IOPORT1 = (14), + ELC_PERIPHERAL_IOPORT2 = (15), + ELC_PERIPHERAL_IOPORT3 = (16), + ELC_PERIPHERAL_IOPORT4 = (17), + ELC_PERIPHERAL_CTSU = (18), + ELC_PERIPHERAL_DA8_0 = (19), + ELC_PERIPHERAL_DA8_1 = (20), + ELC_PERIPHERAL_SDADC0 = (22), +} elc_peripheral_t; + +#endif + +/** ELC control block. Allocate an instance specific control block to pass into the ELC API calls. + */ +typedef void elc_ctrl_t; + +/** Main configuration structure for the Event Link Controller */ +typedef struct st_elc_cfg +{ + elc_event_t const link[ELC_PERIPHERAL_NUM]; ///< Event link register settings + void const * p_extend; ///< Extension parameter for hardware specific settings +} elc_cfg_t; + +#ifndef BSP_OVERRIDE_ELC_SOFTWARE_EVENT_T + +/** Software event number */ +typedef enum e_elc_software_event +{ + ELC_SOFTWARE_EVENT_0, ///< Software event 0 + ELC_SOFTWARE_EVENT_1, ///< Software event 1 +} elc_software_event_t; + +#endif + +/** ELC driver structure. General ELC functions implemented at the HAL layer follow this API. */ +typedef struct st_elc_api +{ + /** Initialize all links in the Event Link Controller. + * + * @param[in] p_ctrl Pointer to control structure. + * @param[in] p_cfg Pointer to configuration structure. + **/ + fsp_err_t (* open)(elc_ctrl_t * const p_ctrl, elc_cfg_t const * const p_cfg); + + /** Disable all links in the Event Link Controller and close the API. + * + * @param[in] p_ctrl Pointer to control structure. + **/ + fsp_err_t (* close)(elc_ctrl_t * const p_ctrl); + + /** Generate a software event in the Event Link Controller. + * + * @param[in] p_ctrl Pointer to control structure. + * @param[in] eventNum Software event number to be generated. + **/ + fsp_err_t (* softwareEventGenerate)(elc_ctrl_t * const p_ctrl, elc_software_event_t event_num); + + /** Create a single event link. + * + * @param[in] p_ctrl Pointer to control structure. + * @param[in] peripheral The peripheral block that will receive the event signal. + * @param[in] signal The event signal. + **/ + fsp_err_t (* linkSet)(elc_ctrl_t * const p_ctrl, elc_peripheral_t peripheral, elc_event_t signal); + + /** Break an event link. + * + * @param[in] p_ctrl Pointer to control structure. + * @param[in] peripheral The peripheral that should no longer be linked. + **/ + fsp_err_t (* linkBreak)(elc_ctrl_t * const p_ctrl, elc_peripheral_t peripheral); + + /** Enable the operation of the Event Link Controller. + * + * @param[in] p_ctrl Pointer to control structure. + **/ + fsp_err_t (* enable)(elc_ctrl_t * const p_ctrl); + + /** Disable the operation of the Event Link Controller. + * + * @param[in] p_ctrl Pointer to control structure. + **/ + fsp_err_t (* disable)(elc_ctrl_t * const p_ctrl); +} elc_api_t; + +/** This structure encompasses everything that is needed to use an instance of this interface. */ +typedef struct st_elc_instance +{ + elc_ctrl_t * p_ctrl; ///< Pointer to the control structure for this instance + elc_cfg_t const * p_cfg; ///< Pointer to the configuration structure for this instance + elc_api_t const * p_api; ///< Pointer to the API structure for this instance +} elc_instance_t; + +/* 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 ELC_API) + **********************************************************************************************************************/ diff --git a/drivers/rz/fsp/inc/instances/rza/r_adc_c.h b/drivers/rz/fsp/inc/instances/rza/r_adc_c.h new file mode 100644 index 00000000..a2a91da5 --- /dev/null +++ b/drivers/rz/fsp/inc/instances/rza/r_adc_c.h @@ -0,0 +1,195 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*******************************************************************************************************************//** + * @addtogroup ADC + * @{ + **********************************************************************************************************************/ + +#ifndef R_ADC_C_H +#define R_ADC_C_H + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ + +#include +#include "r_adc_api.h" +#include "bsp_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 + **********************************************************************************************************************/ + +/** For ADC Scan configuration adc_channel_cfg_t::scan_mask. + * Use bitwise OR to combine these masks for desired channels. */ +typedef enum e_adc_c_mask +{ + ADC_C_MASK_OFF = (0U), ///< No channels selected + ADC_C_MASK_CHANNEL_0 = (1U << 0U), ///< Channel 0 mask + ADC_C_MASK_CHANNEL_1 = (1U << 1U), ///< Channel 1 mask +} adc_c_mask_t; + +/** ADC trigger mode select */ +typedef enum e_adc_c_trigger_mode +{ + ADC_C_TRIGGER_MODE_SOFTWARE = 0U, ///< Software trigger mode + ADC_C_TRIGGER_MODE_HARDWARE = 1U, ///< Hardware trigger mode +} adc_c_trigger_mode_t; + +/** ADC hardware trigger source select */ +typedef enum e_adc_c_active_trigger +{ + ADC_C_ACTIVE_TRIGGER_EXTERNAL = 0U, ///< External trigger input + ADC_C_ACTIVE_TRIGGER_TRGA0N = 1U, ///< Compare match with or input capture to MTU0.TGRA + ADC_C_ACTIVE_TRIGGER_TRGA1N = 2U, ///< Compare match with or input capture to MTU1.TGRA + ADC_C_ACTIVE_TRIGGER_TRGA2N = 3U, ///< Compare match with or input capture to MTU2.TGRA + ADC_C_ACTIVE_TRIGGER_TRGA3N = 4U, ///< Compare match with or input capture to MTU3.TGRA + ADC_C_ACTIVE_TRIGGER_TRGA4N = 5U, ///< Compare match with or input capture to MTU4.TGRA + ADC_C_ACTIVE_TRIGGER_TRGA6N = 6U, ///< Compare match with or input capture to MTU6.TGRA + ADC_C_ACTIVE_TRIGGER_TRGA7N = 7U, ///< Compare match with or input capture to MTU7.TGRA + ADC_C_ACTIVE_TRIGGER_TRG0N = 8U, ///< Compare match with MTU0.TGRE + ADC_C_ACTIVE_TRIGGER_TRG4AN = 9U, ///< Compare match between MTU4.TADCORA and MTU4.TCNT + ADC_C_ACTIVE_TRIGGER_TRG4BN = 10U, ///< Compare match between MTU4.TADCORB and MTU4.TCNT + ADC_C_ACTIVE_TRIGGER_TRG4AN_BN = 11U, ///< Compare match between MTU4.TADCORA and MTU4.TCNT, or between MTU4.TADCORB and MTU4.TCNT + ADC_C_ACTIVE_TRIGGER_TRG4ABN = 12U, ///< Compare match between MTU4.TADCORA and MTU4.TCNT, and between MTU4.TADCORB and MTU4.TCNT (when interrupt skipping function 2 is in use) + ADC_C_ACTIVE_TRIGGER_TRG7AN = 13U, ///< Compare match between MTU7.TADCORA and MTU7.TCNT + ADC_C_ACTIVE_TRIGGER_TRG7BN = 14U, ///< Compare match between MTU7.TADCORB and MTU7.TCNT + ADC_C_ACTIVE_TRIGGER_TRG7AN_BN = 15U, ///< Compare match between MTU7.TADCORA and MTU7.TCNT, or between MTU7.TADCORB and MTU7.TCNT + ADC_C_ACTIVE_TRIGGER_TRG7ABN = 16U, ///< Compare match between MTU7.TADCORA and MTU7.TCNT, and between MTU7.TADCORB and MTU7.TCNT +} adc_c_active_trigger_t; + +/** valid edge of the trigger select */ +typedef enum e_adc_c_trigger_edge +{ + ADC_C_TRIGGER_EDGE_FALLING = 1U, ///< Falling edge + ADC_C_TRIGGER_EDGE_RISING = 2U, ///< Rising edge + ADC_C_TRIGGER_EDGE_BOTH = 3U, ///< Both edges +} adc_c_trigger_edge_t; + +/** ADC trigger input mode select */ +typedef enum e_adc_c_input_mode +{ + ADC_C_INPUT_MODE_AUTO = 0U, ///< Auto mode + ADC_C_INPUT_MODE_STEP = 1U, ///< Step mode +} adc_c_input_mode_t; + +/** ADC operating mode select */ +typedef enum e_adc_c_operating_mode +{ + ADC_C_OPERATING_MODE_SCAN = 0U, ///< Scan mode + ADC_C_OPERATING_MODE_SELECT = 1U, ///< Select mode +} adc_c_operating_mode_t; + +/** ADC buffer mode select */ +typedef enum e_adc_c_buffer_mode +{ + ADC_C_BUFFER_MODE_1 = 0U, ///< 1-buffer mode + ADC_C_BUFFER_MODE_4 = 1U, ///< 4-buffer mode +} adc_c_buffer_mode_t; + +/** Select the number of stages of the AD external trigger pin filter. */ +typedef enum e_adc_c_filter_stage_setting +{ + ADC_C_FILTER_STAGE_SETTING_DISABLE = 0U, ///< Filter is disabled. + ADC_C_FILTER_STAGE_SETTING_4 = 1U, ///< 12.5 ns (80 MHz) x 4 stages + ADC_C_FILTER_STAGE_SETTING_8 = 2U, ///< 12.5 ns (80 MHz) x 8 stages + ADC_C_FILTER_STAGE_SETTING_12 = 3U, ///< 12.5 ns (80 MHz) x 12 stages + ADC_C_FILTER_STAGE_SETTING_16 = 4U, ///< 12.5 ns (80 MHz) x 16 stages +} adc_c_filter_stage_setting_t; + +/** Enable or disable the conversion end interrupt of channel */ +typedef enum e_adc_c_interrupt_channel_setting +{ + ADC_C_INTERRUPT_CHANNEL_SETTING_DISABLE = 0, ///< Interrupt output is disabled. + ADC_C_INTERRUPT_CHANNEL_SETTING_ENABLE = 1, ///< Interrupt output is enabled. +} adc_c_interrupt_channel_setting_t; + +/** Extended configuration structure for ADC. */ +typedef struct st_adc_c_extended_cfg +{ + adc_c_trigger_mode_t trigger_mode; ///< Trigger mode. + adc_c_active_trigger_t trigger_source; ///< Hardware trigger source. + adc_c_trigger_edge_t trigger_edge; ///< Valid edge of the trigger source. + adc_c_input_mode_t input_mode; ///< Trigger input mode. + adc_c_operating_mode_t operating_mode; ///< Operating mode. + adc_c_buffer_mode_t buffer_mode; ///< Buffer mode. + uint16_t sampling_time; ///< Sampling period. (6~2800) + adc_c_filter_stage_setting_t external_trigger_filter; ///< AD external trigger pin filter. +} adc_c_extended_cfg_t; + +/** ADC channel(s) configuration */ +typedef struct st_adc_c_channel_cfg +{ + uint32_t scan_mask; ///< Channels/bits: bit 0 is ch0; bit 1 is ch1. + adc_c_interrupt_channel_setting_t interrupt_setting; ///< Interrupt setting. +} adc_c_channel_cfg_t; + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +/** ADC instance control block. DO NOT INITIALIZE. Initialized in @ref adc_api_t::open(). */ +typedef struct +{ + R_ADC_Type * p_reg; // Base register + adc_cfg_t const * p_cfg; + uint32_t opened; // Boolean to verify that the Unit has been initialized + uint32_t initialized; // Initialized status of ADC + uint32_t scan_mask; // Scan mask used for Normal scan + uint32_t scan_start; + uint32_t operating_mode; + uint32_t buffer_mode; + + void (* p_callback)(adc_callback_args_t *); // Pointer to callback that is called when an adc_event_t occurs. + adc_callback_args_t * p_callback_memory; // Pointer to non-secure memory that can be used to pass arguments to a callback in non-secure memory. + + /* Pointer to context to be passed into callback function */ + void const * p_context; +} adc_c_instance_ctrl_t; + +/********************************************************************************************************************** + * Exported global variables + **********************************************************************************************************************/ + +/** @cond INC_HEADER_DEFS_SEC */ +/** Interface Structure for user access */ +extern const adc_api_t g_adc_on_adc_c; + +/** @endcond */ + +/*********************************************************************************************************************** + * Public APIs + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_Open(adc_ctrl_t * p_ctrl, adc_cfg_t const * const p_cfg); +fsp_err_t R_ADC_C_ScanCfg(adc_ctrl_t * p_ctrl, void const * const p_channel_cfg); +fsp_err_t R_ADC_C_InfoGet(adc_ctrl_t * p_ctrl, adc_info_t * p_adc_info); +fsp_err_t R_ADC_C_ScanStart(adc_ctrl_t * p_ctrl); +fsp_err_t R_ADC_C_ScanGroupStart(adc_ctrl_t * p_ctrl, adc_group_mask_t group_id); +fsp_err_t R_ADC_C_ScanStop(adc_ctrl_t * p_ctrl); +fsp_err_t R_ADC_C_StatusGet(adc_ctrl_t * p_ctrl, adc_status_t * p_status); +fsp_err_t R_ADC_C_Read(adc_ctrl_t * p_ctrl, adc_channel_t const reg_id, uint16_t * const p_data); +fsp_err_t R_ADC_C_Read32(adc_ctrl_t * p_ctrl, adc_channel_t const reg_id, uint32_t * const p_data); +fsp_err_t R_ADC_C_SampleStateCountSet(adc_ctrl_t * p_ctrl, uint16_t num_states); +fsp_err_t R_ADC_C_Close(adc_ctrl_t * p_ctrl); +fsp_err_t R_ADC_C_OffsetSet(adc_ctrl_t * const p_ctrl, adc_channel_t const reg_id, int32_t offset); +fsp_err_t R_ADC_C_Calibrate(adc_ctrl_t * const p_ctrl, void const * p_extend); +fsp_err_t R_ADC_C_CallbackSet(adc_ctrl_t * const p_api_ctrl, + void ( * p_callback)(adc_callback_args_t *), + void const * const p_context, + adc_callback_args_t * const p_callback_memory); + +/*******************************************************************************************************************//** + * @} (end defgroup ADC) + **********************************************************************************************************************/ + +/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER + +#endif diff --git a/drivers/rz/fsp/inc/instances/rzg/r_adc_c.h b/drivers/rz/fsp/inc/instances/rzg/r_adc_c.h index 75126185..5054f014 100644 --- a/drivers/rz/fsp/inc/instances/rzg/r_adc_c.h +++ b/drivers/rz/fsp/inc/instances/rzg/r_adc_c.h @@ -179,7 +179,7 @@ typedef struct /** @cond INC_HEADER_DEFS_SEC */ /** Interface Structure for user access */ -extern const adc_api_t g_adc_on_adc; +extern const adc_api_t g_adc_on_adc_c; /** @endcond */ diff --git a/drivers/rz/fsp/inc/instances/rzn/r_adc.h b/drivers/rz/fsp/inc/instances/rzn/r_adc.h new file mode 100644 index 00000000..0f35f204 --- /dev/null +++ b/drivers/rz/fsp/inc/instances/rzn/r_adc.h @@ -0,0 +1,359 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +#ifndef R_ADC_H +#define R_ADC_H + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ +#include + +/* Fixed width integer support. */ +#include + +/* bool support */ +#include +#include "bsp_api.h" +#include "r_adc_cfg.h" +#include "r_adc_api.h" + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ +FSP_HEADER + +/*******************************************************************************************************************//** + * @addtogroup ADC + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +#if 1U == BSP_FEATURE_ADC_SAMPLE_STATE_COUNT_TYPE + +/* Typical values that can be used to modify the sample states. + * The minimum sample state count value is either 6 or 7 depending on the clock ratios. + * It is fixed to 7 based on the fact that at the lowest ADC conversion clock supported (1 MHz) + * this extra state will lead to at worst a "1 microsecond" increase in conversion time. + * At 60 MHz the extra sample state will add 16.7 ns to the conversion time. + */ + #define ADC_SAMPLE_STATE_COUNT_MIN (7U) + #define ADC_SAMPLE_STATE_COUNT_MAX (255U) + +/* Typical values that can be used for the sample and hold counts for the channels 0-2*/ +/* Minimum sample and hold states */ + #define ADC_SAMPLE_STATE_HOLD_COUNT_MIN (4U) + +#elif 2U == BSP_FEATURE_ADC_SAMPLE_STATE_COUNT_TYPE + +/* Typical values that can be used to modify the sample states. + * The minimum sample state count value is either 6 or 7 depending on the clock ratios. + * It is fixed to 6 based on the fact that at the lowest ADC conversion clock supported (1 MHz) + * this extra state will lead to at worst a "1 microsecond" increase in conversion time. + * At 60 MHz the extra sample state will add 16.7 ns to the conversion time. + */ + #define ADC_SAMPLE_STATE_COUNT_MIN (6U) + #define ADC_SAMPLE_STATE_COUNT_MAX (255U) + +/* Typical values that can be used for the sample and hold counts for the channels 0-2*/ +/* Minimum sample and hold states */ + #define ADC_SAMPLE_STATE_HOLD_COUNT_MIN (8U) +#endif + +/* Default sample and hold states */ +#define ADC_SAMPLE_STATE_HOLD_COUNT_DEFAULT (24U) + +/** For ADC Scan configuration adc_channel_cfg_t::scan_mask, adc_channel_cfg_t::scan_mask_group_b, + * adc_channel_cfg_t::add_mask and adc_channel_cfg_t::sample_hold_mask. + * Use bitwise OR to combine these masks for desired channels and sensors. */ +typedef enum e_adc_mask +{ + ADC_MASK_OFF = (0U), ///< No channels selected + ADC_MASK_CHANNEL_0 = (1U << 0U), ///< Channel 0 mask + ADC_MASK_CHANNEL_1 = (1U << 1U), ///< Channel 1 mask + ADC_MASK_CHANNEL_2 = (1U << 2U), ///< Channel 2 mask + ADC_MASK_CHANNEL_3 = (1U << 3U), ///< Channel 3 mask + ADC_MASK_CHANNEL_4 = (1U << 4U), ///< Channel 4 mask + ADC_MASK_CHANNEL_5 = (1U << 5U), ///< Channel 5 mask + ADC_MASK_CHANNEL_6 = (1U << 6U), ///< Channel 6 mask + ADC_MASK_CHANNEL_7 = (1U << 7U), ///< Channel 7 mask + ADC_MASK_CHANNEL_8 = (1U << 8U), ///< Channel 8 mask + ADC_MASK_CHANNEL_9 = (1U << 9U), ///< Channel 9 mask + ADC_MASK_CHANNEL_10 = (1U << 10U), ///< Channel 10 mask + ADC_MASK_CHANNEL_11 = (1U << 11U), ///< Channel 11 mask + ADC_MASK_CHANNEL_12 = (1U << 12U), ///< Channel 12 mask + ADC_MASK_CHANNEL_13 = (1U << 13U), ///< Channel 13 mask + ADC_MASK_CHANNEL_14 = (1U << 14U), ///< Channel 14 mask + ADC_MASK_CHANNEL_15 = (1U << 15U), ///< Channel 15 mask +} adc_mask_t; + +/** ADC data sample addition and averaging options */ +typedef enum e_adc_add +{ + ADC_ADD_OFF = 0, ///< Addition turned off for channels/sensors + ADC_ADD_TWO = 1, ///< Add two samples + ADC_ADD_THREE = 2, ///< Add three samples + ADC_ADD_FOUR = 3, ///< Add four samples + ADC_ADD_SIXTEEN = 5, ///< Add sixteen samples + ADC_ADD_AVERAGE_TWO = 0x81, ///< Average two samples + ADC_ADD_AVERAGE_THREE = 0x82, ///< Average three samples + ADC_ADD_AVERAGE_FOUR = 0x83, ///< Average four samples + ADC_ADD_AVERAGE_SIXTEEN = 0x85, ///< Average sixteen samples +} adc_add_t; + +/** ADC clear after read definitions */ +typedef enum e_adc_clear +{ + ADC_CLEAR_AFTER_READ_OFF = 0, ///< Clear after read off + ADC_CLEAR_AFTER_READ_ON = 1 ///< Clear after read on +} adc_clear_t; + +/** ADC sample state registers */ +typedef enum e_adc_sample_state_reg +{ + ADC_SAMPLE_STATE_REG_CHANNEL_0 = 0, ///< Sample state register channel 0 + ADC_SAMPLE_STATE_REG_CHANNEL_1, ///< Sample state register channel 1 + ADC_SAMPLE_STATE_REG_CHANNEL_2, ///< Sample state register channel 2 + ADC_SAMPLE_STATE_REG_CHANNEL_3, ///< Sample state register channel 3 + ADC_SAMPLE_STATE_REG_CHANNEL_4, ///< Sample state register channel 4 + ADC_SAMPLE_STATE_REG_CHANNEL_5, ///< Sample state register channel 5 + ADC_SAMPLE_STATE_REG_CHANNEL_6, ///< Sample state register channel 6 + ADC_SAMPLE_STATE_REG_CHANNEL_7, ///< Sample state register channel 7 + ADC_SAMPLE_STATE_REG_CHANNEL_8, ///< Sample state register channel 8 + ADC_SAMPLE_STATE_REG_CHANNEL_9, ///< Sample state register channel 9 + ADC_SAMPLE_STATE_REG_CHANNEL_10, ///< Sample state register channel 10 + ADC_SAMPLE_STATE_REG_CHANNEL_11, ///< Sample state register channel 11 + ADC_SAMPLE_STATE_REG_CHANNEL_12, ///< Sample state register channel 12 + ADC_SAMPLE_STATE_REG_CHANNEL_13, ///< Sample state register channel 13 + ADC_SAMPLE_STATE_REG_CHANNEL_14, ///< Sample state register channel 14 + ADC_SAMPLE_STATE_REG_CHANNEL_15, ///< Sample state register channel 15 + ADC_SAMPLE_STATE_REG_CHANNEL_16_TO_31 = -3, ///< Sample state register channel 16 to 31 +} adc_sample_state_reg_t; + +/** ADC comparison settings */ +typedef enum e_adc_compare_cfg +{ +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + ADC_COMPARE_CFG_A_ENABLE = R_ADC121_ADCMPCR_CMPAE_Msk | R_ADC121_ADCMPCR_CMPAIE_Msk, ///< Window A operation enabled + ADC_COMPARE_CFG_B_ENABLE = R_ADC121_ADCMPCR_CMPBE_Msk | R_ADC121_ADCMPCR_CMPBIE_Msk, ///< Window B operation enabled + ADC_COMPARE_CFG_WINDOW_ENABLE = R_ADC121_ADCMPCR_WCMPE_Msk, ///< Window function enabled +#elif 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + ADC_COMPARE_CFG_A_ENABLE = R_ADC120_ADCMPCR_CMPAE_Msk | R_ADC120_ADCMPCR_CMPAIE_Msk, ///< Window A operation enabled + ADC_COMPARE_CFG_B_ENABLE = R_ADC120_ADCMPCR_CMPBE_Msk | R_ADC120_ADCMPCR_CMPBIE_Msk, ///< Window B operation enabled + ADC_COMPARE_CFG_WINDOW_ENABLE = R_ADC120_ADCMPCR_WCMPE_Msk, ///< Window function enabled +#endif +} adc_compare_cfg_t; + +/** ADC Window B channel */ +typedef enum e_adc_window_b_channel +{ + ADC_WINDOW_B_CHANNEL_0 = 0, ///< Window B channel 0 + ADC_WINDOW_B_CHANNEL_1, ///< Window B channel 1 + ADC_WINDOW_B_CHANNEL_2, ///< Window B channel 2 + ADC_WINDOW_B_CHANNEL_3, ///< Window B channel 3 + ADC_WINDOW_B_CHANNEL_4, ///< Window B channel 4 + ADC_WINDOW_B_CHANNEL_5, ///< Window B channel 5 + ADC_WINDOW_B_CHANNEL_6, ///< Window B channel 6 + ADC_WINDOW_B_CHANNEL_7, ///< Window B channel 7 + ADC_WINDOW_B_CHANNEL_8, ///< Window B channel 8 + ADC_WINDOW_B_CHANNEL_9, ///< Window B channel 9 + ADC_WINDOW_B_CHANNEL_10, ///< Window B channel 10 + ADC_WINDOW_B_CHANNEL_11, ///< Window B channel 11 + ADC_WINDOW_B_CHANNEL_12, ///< Window B channel 12 + ADC_WINDOW_B_CHANNEL_13, ///< Window B channel 13 + ADC_WINDOW_B_CHANNEL_14, ///< Window B channel 14 + ADC_WINDOW_B_CHANNEL_15, ///< Window B channel 15 +} adc_window_b_channel_t; + +/** ADC Window B comparison mode */ +typedef enum e_adc_window_b_mode +{ + ADC_WINDOW_B_MODE_LESS_THAN_OR_OUTSIDE = 0, ///< Window B comparison condition is less than or outside +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + ADC_WINDOW_B_MODE_GREATER_THAN_OR_INSIDE = R_ADC121_ADCMPBNSR_CMPLB_Msk, ///< Window B comparison condition is greater than or inside +#elif 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + ADC_WINDOW_B_MODE_GREATER_THAN_OR_INSIDE = R_ADC120_ADCMPBNSR_CMPLB_Msk, ///< Window B comparison condition is greater than or inside +#endif +} adc_window_b_mode_t; + +/** ADC action for group A interrupts group B scan. + * This enumeration is used to specify the priority between Group A and B in group mode. */ +typedef enum e_adc_group_a +{ + ADC_GROUP_A_PRIORITY_OFF = 0, ///< Group A ignored and does not interrupt ongoing group B scan + ADC_GROUP_A_GROUP_B_WAIT_FOR_TRIGGER = 1, ///< Group A interrupts Group B(single scan) which restarts at next Group B trigger + ADC_GROUP_A_GROUP_B_RESTART_SCAN = 3, ///< Group A interrupts Group B(single scan) which restarts immediately after Group A scan is complete + ADC_GROUP_A_GROUP_B_RESUME_SCAN = 0x4003, ///< Resume scanning of interrupted channels + ADC_GROUP_A_GROUP_B_CONTINUOUS_SCAN = 0x8001, ///< Group A interrupts Group B(continuous scan) which continues scanning without a new Group B trigger +} adc_group_a_t; + +/** Defines the registers settings for the ADC trigger. */ +typedef enum e_adc_active_trigger +{ + ADC_ACTIVE_TRIGGER_EXTERNAL = (0x00U), ///< Input pin for the trigger + + /* ADC_TRIGGER_TRGXX is unit 0 only */ + ADC_ACTIVE_TRIGGER_TRGA1N = (0x02U), ///< Compare match with or input capture to MTU1.TGRA + ADC_ACTIVE_TRIGGER_TRGA2N = (0x03U), ///< Compare match with or input capture to MTU2.TGRA + ADC_ACTIVE_TRIGGER_TRGA3N = (0x04U), ///< Compare match with or input capture to MTU3.TGRA + ADC_ACTIVE_TRIGGER_TRGA0N = (0x01U), ///< Compare match with or input capture to MTU0.TGRA + ADC_ACTIVE_TRIGGER_TRGA4N = (0x05U), ///< Compare match with or input capture to MTU4.TGRA, or an underflow of MTU4.TCNT (in the trough) in complementary PWM mode + ADC_ACTIVE_TRIGGER_TRGA6N = (0x06U), ///< Compare match with MTU6.TGRA + ADC_ACTIVE_TRIGGER_TRGA7N = (0x07U), ///< Compare match with MTU7.TGRA + ADC_ACTIVE_TRIGGER_TRG0N = (0x08U), ///< Compare match with MTU0.TGRE + ADC_ACTIVE_TRIGGER_TRG4AN = (0x09U), ///< Compare match between MTU4.TADCORA and MTU4.TCNT + ADC_ACTIVE_TRIGGER_TRG4BN = (0x0AU), ///< Compare match between MTU4.TADCORB and MTU4.TCNT + ADC_ACTIVE_TRIGGER_TRG4AN_BN = (0x0BU), ///< Compare match between MTU4.TADCORA and MTU4.TCNT, or between MTU4.TADCORB and MTU4.TCNT + ADC_ACTIVE_TRIGGER_TRG4ABN = (0x0CU), ///< Compare match between MTU4.TADCORA and MTU4.TCNT, and between MTU4.TADCORB and MTU4.TCNT (when interrupt skipping function 2 is in use) + ADC_ACTIVE_TRIGGER_TRG7AN = (0x0DU), ///< Compare match between MTU7.TADCORA and MTU7.TCNT + ADC_ACTIVE_TRIGGER_TRG7BN = (0x0EU), ///< Compare match between MTU7.TADCORB and MTU7.TCNT + ADC_ACTIVE_TRIGGER_TRG7AN_BN = (0x0FU), ///< Compare match between MTU7.TADCORA and MTU7.TCNT, or between MTU7.TADCORB and MTU7.TCNT + ADC_ACTIVE_TRIGGER_TRG7ABN = (0x10U), ///< Compare match between MTU7.TADCORA and MTU7.TCNT, and between MTU7.TADCORB and MTU7.TCNT + ///< (when interrupt skipping function 2 is in use) + + ADC_ACTIVE_TRIGGER_ELC_TRIGGER = (0x11U), ///< A/D Startup source A from ELC + ADC_ACTIVE_TRIGGER_ELC_TRIGGER_GROUP_B = (0x12U), ///< A/D Startup source B from ELC + ADC_ACTIVE_TRIGGER_DISABLED = (0x3FU) ///< A/D Start trigger disabled +} adc_active_trigger_t; + +/** ADC double-trigger mode definitions */ +typedef enum e_adc_double_trigger +{ + ADC_DOUBLE_TRIGGER_DISABLED = 0, ///< Double-triggering disabled + ADC_DOUBLE_TRIGGER_ENABLED = 1, ///< Double-triggering enabled + ADC_DOUBLE_TRIGGER_ENABLED_EXTENDED = 2, ///< Double-triggering enabled on both ADC ELC events +} adc_double_trigger_t; + +/** AD event link control definitions. */ +typedef enum e_adc_elc +{ + ADC_ELC_SINGLE_SCAN = 0x00U, ///< At the end of a single scan GCELC = 0b, ELCC[1:0] = 00b + ADC_ELC_CONTINUOUS_SCAN = 0x00U, ///< At the end of a contiuous scan GCELC = 0b, ELCC[1:0] = 00b + ADC_ELC_GROUP_A_SCAN = 0x00U, ///< At the end of a group_a scan GCELC = 0b, ELCC[1:0] = 00b + ADC_ELC_GROUP_B_SCAN = 0x01U, ///< At the end of a group_b scan GCELC = 0b, ELCC[1:0] = 01b + ADC_ELC_GROUP_A_B_C_SCAN = 0x02U, ///< At the end of a group_abc scan GCELC = 0b, ELCC[1:0] = 1xb + ADC_ELC_GROUP_C_SCAN = 0x04U, ///< At the end of a group_c scan GCELC = 1b, ELCC[1:0] = 00b +} adc_elc_t; + +/** ADC sample state configuration */ +typedef struct st_adc_sample_state +{ + adc_sample_state_reg_t reg_id; ///< Sample state register ID + uint8_t num_states; ///< Number of sampling states for conversion. Ch16-20/21 use the same value. +} adc_sample_state_t; + +/** ADC Window Compare configuration */ +typedef struct st_adc_window_cfg +{ + uint32_t compare_mask; ///< Channel mask to compare with Window A + uint32_t compare_mode_mask; ///< Per-channel condition mask for Window A + adc_compare_cfg_t compare_cfg; ///< Window Compare configuration + uint16_t compare_ref_low; ///< Window A lower reference value + uint16_t compare_ref_high; ///< Window A upper reference value + uint16_t compare_b_ref_low; ///< Window B lower reference value + uint16_t compare_b_ref_high; ///< Window B upper reference value + adc_window_b_channel_t compare_b_channel; ///< Window B channel + adc_window_b_mode_t compare_b_mode; ///< Window B condition setting +} adc_window_cfg_t; + +/** Extended configuration structure for ADC. */ +typedef struct st_adc_extended_cfg +{ + adc_add_t add_average_count; ///< Add or average samples + adc_clear_t clearing; ///< Clear after read + adc_trigger_t trigger_group_b; ///< Group B trigger source; valid only for group mode + adc_double_trigger_t double_trigger_mode; ///< Double-trigger mode setting + adc_active_trigger_t adc_start_trigger_a; ///< A/D Conversion Start Trigger Group A + adc_active_trigger_t adc_start_trigger_b; ///< A/D Conversion Start Trigger Group B + bool adc_start_trigger_c_enabled; ///< Set to true to enable Group C, false to disable Group C + adc_active_trigger_t adc_start_trigger_c; ///< A/D Conversion Start Trigger Group C + adc_elc_t adc_elc_ctrl; ///< A/D Event Link Control + IRQn_Type window_a_irq; ///< IRQ number for Window Compare A interrupts + uint8_t window_a_ipl; ///< Priority for Window Compare A interrupts + IRQn_Type window_b_irq; ///< IRQ number for Window Compare B interrupts + uint8_t window_b_ipl; ///< Priority for Window Compare B interrupts +} adc_extended_cfg_t; + +/** ADC channel(s) configuration */ +typedef struct st_adc_channel_cfg +{ + uint32_t scan_mask; ///< Channels/bits: bit 0 is ch0; bit 15 is ch15. + uint32_t scan_mask_group_b; ///< Valid for group modes. + uint32_t scan_mask_group_c; ///< Valid for group modes. + uint32_t add_mask; ///< Valid if add enabled in Open(). + adc_window_cfg_t * p_window_cfg; ///< Pointer to Window Compare configuration + adc_group_a_t priority_group_a; ///< Valid for group modes. + uint8_t sample_hold_mask; ///< Channels/bits 0-2. + uint8_t sample_hold_states; ///< Number of states to be used for sample and hold. Affects channels 0-2. +} adc_channel_cfg_t; + +/* Sample and hold Channel mask. Sample and hold is only available for channel 0,1,2*/ +#define ADC_SAMPLE_HOLD_CHANNELS (0x07U) + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +/** ADC instance control block. DO NOT INITIALIZE. Initialized in @ref adc_api_t::open(). */ +typedef struct +{ +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + R_ADC121_Type * p_reg; // Base register for this unit +#elif 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + R_ADC122_Type * p_reg; // Base register for this unit +#endif + adc_cfg_t const * p_cfg; + uint32_t opened; // Boolean to verify that the Unit has been initialized + uint32_t scan_mask; // Scan mask used for Normal scan. + uint16_t scan_start_adcsr; + + void (* p_callback)(adc_callback_args_t *); // Pointer to callback that is called when an adc_event_t occurs. + adc_callback_args_t * p_callback_memory; // Pointer to non-secure memory that can be used to pass arguments to a callback in non-secure memory. + + /* Pointer to context to be passed into callback function */ + void const * p_context; +} adc_instance_ctrl_t; + +/********************************************************************************************************************** + * Exported global variables + **********************************************************************************************************************/ + +/** @cond INC_HEADER_DEFS_SEC */ +/** Interface Structure for user access */ +extern const adc_api_t g_adc_on_adc; + +/** @endcond */ + +/*********************************************************************************************************************** + * Public APIs + **********************************************************************************************************************/ +fsp_err_t R_ADC_Open(adc_ctrl_t * p_ctrl, adc_cfg_t const * const p_cfg); +fsp_err_t R_ADC_ScanCfg(adc_ctrl_t * p_ctrl, void const * const p_channel_cfg); +fsp_err_t R_ADC_InfoGet(adc_ctrl_t * p_ctrl, adc_info_t * p_adc_info); +fsp_err_t R_ADC_ScanStart(adc_ctrl_t * p_ctrl); +fsp_err_t R_ADC_ScanGroupStart(adc_ctrl_t * p_ctrl, adc_group_mask_t group_mask); +fsp_err_t R_ADC_ScanStop(adc_ctrl_t * p_ctrl); +fsp_err_t R_ADC_StatusGet(adc_ctrl_t * p_ctrl, adc_status_t * p_status); +fsp_err_t R_ADC_Read(adc_ctrl_t * p_ctrl, adc_channel_t const reg_id, uint16_t * const p_data); +fsp_err_t R_ADC_Read32(adc_ctrl_t * p_ctrl, adc_channel_t const reg_id, uint32_t * const p_data); +fsp_err_t R_ADC_SampleStateCountSet(adc_ctrl_t * p_ctrl, adc_sample_state_t * p_sample); +fsp_err_t R_ADC_Close(adc_ctrl_t * p_ctrl); +fsp_err_t R_ADC_OffsetSet(adc_ctrl_t * const p_ctrl, adc_channel_t const reg_id, int32_t offset); +fsp_err_t R_ADC_Calibrate(adc_ctrl_t * const p_ctrl, void const * p_extend); +fsp_err_t R_ADC_CallbackSet(adc_ctrl_t * const p_ctrl, + void ( * p_callback)(adc_callback_args_t *), + void const * const p_context, + adc_callback_args_t * const p_callback_memory); + +/*******************************************************************************************************************//** + * @} (end defgroup ADC) + **********************************************************************************************************************/ + +/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER + +#endif diff --git a/drivers/rz/fsp/inc/instances/rzt/r_adc.h b/drivers/rz/fsp/inc/instances/rzt/r_adc.h new file mode 100644 index 00000000..6400d272 --- /dev/null +++ b/drivers/rz/fsp/inc/instances/rzt/r_adc.h @@ -0,0 +1,360 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +#ifndef R_ADC_H +#define R_ADC_H + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ +#include + +/* Fixed width integer support. */ +#include + +/* bool support */ +#include +#include "bsp_api.h" +#include "r_adc_cfg.h" +#include "r_adc_api.h" + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ +FSP_HEADER + +/*******************************************************************************************************************//** + * @addtogroup ADC + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ +#if 1U == BSP_FEATURE_ADC_SAMPLE_STATE_COUNT_TYPE + +/* Typical values that can be used to modify the sample states. + * The minimum sample state count value is either 6 or 7 depending on the clock ratios. + * It is fixed to 7 based on the fact that at the lowest ADC conversion clock supported (1 MHz) + * this extra state will lead to at worst a "1 microsecond" increase in conversion time. + * At 60 MHz the extra sample state will add 16.7 ns to the conversion time. + */ + #define ADC_SAMPLE_STATE_COUNT_MIN (7U) + #define ADC_SAMPLE_STATE_COUNT_MAX (255U) + +/* Typical values that can be used for the sample and hold counts for the channels 0-2*/ +/* Minimum sample and hold states */ + #define ADC_SAMPLE_STATE_HOLD_COUNT_MIN (4U) + +#elif 2U == BSP_FEATURE_ADC_SAMPLE_STATE_COUNT_TYPE + +/* Typical values that can be used to modify the sample states. + * The minimum sample state count value is either 6 or 7 depending on the clock ratios. + * It is fixed to 6 based on the fact that at the lowest ADC conversion clock supported (1 MHz) + * this extra state will lead to at worst a "1 microsecond" increase in conversion time. + * At 60 MHz the extra sample state will add 16.7 ns to the conversion time. + */ + #define ADC_SAMPLE_STATE_COUNT_MIN (6U) + #define ADC_SAMPLE_STATE_COUNT_MAX (255U) + +/* Typical values that can be used for the sample and hold counts for the channels 0-2*/ +/* Minimum sample and hold states */ + #define ADC_SAMPLE_STATE_HOLD_COUNT_MIN (8U) +#endif + +/* Default sample and hold states */ +#define ADC_SAMPLE_STATE_HOLD_COUNT_DEFAULT (24U) + +/** For ADC Scan configuration adc_channel_cfg_t::scan_mask, adc_channel_cfg_t::scan_mask_group_b, + * adc_channel_cfg_t::add_mask and adc_channel_cfg_t::sample_hold_mask. + * Use bitwise OR to combine these masks for desired channels and sensors. */ +typedef enum e_adc_mask +{ + ADC_MASK_OFF = (0U), ///< No channels selected + ADC_MASK_CHANNEL_0 = (1U << 0U), ///< Channel 0 mask + ADC_MASK_CHANNEL_1 = (1U << 1U), ///< Channel 1 mask + ADC_MASK_CHANNEL_2 = (1U << 2U), ///< Channel 2 mask + ADC_MASK_CHANNEL_3 = (1U << 3U), ///< Channel 3 mask + ADC_MASK_CHANNEL_4 = (1U << 4U), ///< Channel 4 mask + ADC_MASK_CHANNEL_5 = (1U << 5U), ///< Channel 5 mask + ADC_MASK_CHANNEL_6 = (1U << 6U), ///< Channel 6 mask + ADC_MASK_CHANNEL_7 = (1U << 7U), ///< Channel 7 mask + ADC_MASK_CHANNEL_8 = (1U << 8U), ///< Channel 8 mask + ADC_MASK_CHANNEL_9 = (1U << 9U), ///< Channel 9 mask + ADC_MASK_CHANNEL_10 = (1U << 10U), ///< Channel 10 mask + ADC_MASK_CHANNEL_11 = (1U << 11U), ///< Channel 11 mask + ADC_MASK_CHANNEL_12 = (1U << 12U), ///< Channel 12 mask + ADC_MASK_CHANNEL_13 = (1U << 13U), ///< Channel 13 mask + ADC_MASK_CHANNEL_14 = (1U << 14U), ///< Channel 14 mask + ADC_MASK_CHANNEL_15 = (1U << 15U), ///< Channel 15 mask +} adc_mask_t; + +/** ADC data sample addition and averaging options */ +typedef enum e_adc_add +{ + ADC_ADD_OFF = 0, ///< Addition turned off for channels/sensors + ADC_ADD_TWO = 1, ///< Add two samples + ADC_ADD_THREE = 2, ///< Add three samples + ADC_ADD_FOUR = 3, ///< Add four samples + ADC_ADD_SIXTEEN = 5, ///< Add sixteen samples + ADC_ADD_AVERAGE_TWO = 0x81, ///< Average two samples + ADC_ADD_AVERAGE_THREE = 0x82, ///< Average three samples + ADC_ADD_AVERAGE_FOUR = 0x83, ///< Average four samples + ADC_ADD_AVERAGE_SIXTEEN = 0x85, ///< Average sixteen samples +} adc_add_t; + +/** ADC clear after read definitions */ +typedef enum e_adc_clear +{ + ADC_CLEAR_AFTER_READ_OFF = 0, ///< Clear after read off + ADC_CLEAR_AFTER_READ_ON = 1 ///< Clear after read on +} adc_clear_t; + +/** ADC sample state registers */ +typedef enum e_adc_sample_state_reg +{ + ADC_SAMPLE_STATE_REG_CHANNEL_0 = 0, ///< Sample state register channel 0 + ADC_SAMPLE_STATE_REG_CHANNEL_1, ///< Sample state register channel 1 + ADC_SAMPLE_STATE_REG_CHANNEL_2, ///< Sample state register channel 2 + ADC_SAMPLE_STATE_REG_CHANNEL_3, ///< Sample state register channel 3 + ADC_SAMPLE_STATE_REG_CHANNEL_4, ///< Sample state register channel 4 + ADC_SAMPLE_STATE_REG_CHANNEL_5, ///< Sample state register channel 5 + ADC_SAMPLE_STATE_REG_CHANNEL_6, ///< Sample state register channel 6 + ADC_SAMPLE_STATE_REG_CHANNEL_7, ///< Sample state register channel 7 + ADC_SAMPLE_STATE_REG_CHANNEL_8, ///< Sample state register channel 8 + ADC_SAMPLE_STATE_REG_CHANNEL_9, ///< Sample state register channel 9 + ADC_SAMPLE_STATE_REG_CHANNEL_10, ///< Sample state register channel 10 + ADC_SAMPLE_STATE_REG_CHANNEL_11, ///< Sample state register channel 11 + ADC_SAMPLE_STATE_REG_CHANNEL_12, ///< Sample state register channel 12 + ADC_SAMPLE_STATE_REG_CHANNEL_13, ///< Sample state register channel 13 + ADC_SAMPLE_STATE_REG_CHANNEL_14, ///< Sample state register channel 14 + ADC_SAMPLE_STATE_REG_CHANNEL_15, ///< Sample state register channel 15 + ADC_SAMPLE_STATE_REG_CHANNEL_16_TO_31 = -3, ///< Sample state register channel 16 to 31 +} adc_sample_state_reg_t; + +/** ADC comparison settings */ +typedef enum e_adc_compare_cfg +{ +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + ADC_COMPARE_CFG_A_ENABLE = R_ADC121_ADCMPCR_CMPAE_Msk | R_ADC121_ADCMPCR_CMPAIE_Msk, ///< Window A operation enabled + ADC_COMPARE_CFG_B_ENABLE = R_ADC121_ADCMPCR_CMPBE_Msk | R_ADC121_ADCMPCR_CMPBIE_Msk, ///< Window B operation enabled + ADC_COMPARE_CFG_WINDOW_ENABLE = R_ADC121_ADCMPCR_WCMPE_Msk, ///< Window function enabled +#elif 2U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE || 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + ADC_COMPARE_CFG_A_ENABLE = R_ADC120_ADCMPCR_CMPAE_Msk | R_ADC120_ADCMPCR_CMPAIE_Msk, ///< Window A operation enabled + ADC_COMPARE_CFG_B_ENABLE = R_ADC120_ADCMPCR_CMPBE_Msk | R_ADC120_ADCMPCR_CMPBIE_Msk, ///< Window B operation enabled + ADC_COMPARE_CFG_WINDOW_ENABLE = R_ADC120_ADCMPCR_WCMPE_Msk, ///< Window function enabled +#endif +} adc_compare_cfg_t; + +/** ADC Window B channel */ +typedef enum e_adc_window_b_channel +{ + ADC_WINDOW_B_CHANNEL_0 = 0, ///< Window B channel 0 + ADC_WINDOW_B_CHANNEL_1, ///< Window B channel 1 + ADC_WINDOW_B_CHANNEL_2, ///< Window B channel 2 + ADC_WINDOW_B_CHANNEL_3, ///< Window B channel 3 + ADC_WINDOW_B_CHANNEL_4, ///< Window B channel 4 + ADC_WINDOW_B_CHANNEL_5, ///< Window B channel 5 + ADC_WINDOW_B_CHANNEL_6, ///< Window B channel 6 + ADC_WINDOW_B_CHANNEL_7, ///< Window B channel 7 + ADC_WINDOW_B_CHANNEL_8, ///< Window B channel 8 + ADC_WINDOW_B_CHANNEL_9, ///< Window B channel 9 + ADC_WINDOW_B_CHANNEL_10, ///< Window B channel 10 + ADC_WINDOW_B_CHANNEL_11, ///< Window B channel 11 + ADC_WINDOW_B_CHANNEL_12, ///< Window B channel 12 + ADC_WINDOW_B_CHANNEL_13, ///< Window B channel 13 + ADC_WINDOW_B_CHANNEL_14, ///< Window B channel 14 + ADC_WINDOW_B_CHANNEL_15, ///< Window B channel 15 +} adc_window_b_channel_t; + +/** ADC Window B comparison mode */ +typedef enum e_adc_window_b_mode +{ + ADC_WINDOW_B_MODE_LESS_THAN_OR_OUTSIDE = 0, ///< Window B comparison condition is less than or outside +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + ADC_WINDOW_B_MODE_GREATER_THAN_OR_INSIDE = R_ADC121_ADCMPBNSR_CMPLB_Msk, ///< Window B comparison condition is greater than or inside +#elif 2U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE || 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + ADC_WINDOW_B_MODE_GREATER_THAN_OR_INSIDE = R_ADC120_ADCMPBNSR_CMPLB_Msk, ///< Window B comparison condition is greater than or inside +#endif +} adc_window_b_mode_t; + +/** ADC action for group A interrupts group B scan. + * This enumeration is used to specify the priority between Group A and B in group mode. */ +typedef enum e_adc_group_a +{ + ADC_GROUP_A_PRIORITY_OFF = 0, ///< Group A ignored and does not interrupt ongoing group B scan + ADC_GROUP_A_GROUP_B_WAIT_FOR_TRIGGER = 1, ///< Group A interrupts Group B(single scan) which restarts at next Group B trigger + ADC_GROUP_A_GROUP_B_RESTART_SCAN = 3, ///< Group A interrupts Group B(single scan) which restarts immediately after Group A scan is complete + ADC_GROUP_A_GROUP_B_RESUME_SCAN = 0x4003, ///< Resume scanning of interrupted channels + ADC_GROUP_A_GROUP_B_CONTINUOUS_SCAN = 0x8001, ///< Group A interrupts Group B(continuous scan) which continues scanning without a new Group B trigger +} adc_group_a_t; + +/** Defines the registers settings for the ADC trigger. */ +typedef enum e_adc_active_trigger +{ + ADC_ACTIVE_TRIGGER_EXTERNAL = (0x00U), ///< Input pin for the trigger + + /* ADC_TRIGGER_TRGXX is unit 0 only */ + ADC_ACTIVE_TRIGGER_TRGA1N = (0x02U), ///< Compare match with or input capture to MTU1.TGRA + ADC_ACTIVE_TRIGGER_TRGA2N = (0x03U), ///< Compare match with or input capture to MTU2.TGRA + ADC_ACTIVE_TRIGGER_TRGA3N = (0x04U), ///< Compare match with or input capture to MTU3.TGRA + ADC_ACTIVE_TRIGGER_TRGA0N = (0x01U), ///< Compare match with or input capture to MTU0.TGRA + ADC_ACTIVE_TRIGGER_TRGA4N = (0x05U), ///< Compare match with or input capture to MTU4.TGRA, or an underflow of MTU4.TCNT (in the trough) in complementary PWM mode + ADC_ACTIVE_TRIGGER_TRGA6N = (0x06U), ///< Compare match with MTU6.TGRA + ADC_ACTIVE_TRIGGER_TRGA7N = (0x07U), ///< Compare match with MTU7.TGRA + ADC_ACTIVE_TRIGGER_TRG0N = (0x08U), ///< Compare match with MTU0.TGRE + ADC_ACTIVE_TRIGGER_TRG4AN = (0x09U), ///< Compare match between MTU4.TADCORA and MTU4.TCNT + ADC_ACTIVE_TRIGGER_TRG4BN = (0x0AU), ///< Compare match between MTU4.TADCORB and MTU4.TCNT + ADC_ACTIVE_TRIGGER_TRG4AN_BN = (0x0BU), ///< Compare match between MTU4.TADCORA and MTU4.TCNT, or between MTU4.TADCORB and MTU4.TCNT + ADC_ACTIVE_TRIGGER_TRG4ABN = (0x0CU), ///< Compare match between MTU4.TADCORA and MTU4.TCNT, and between MTU4.TADCORB and MTU4.TCNT (when interrupt skipping function 2 is in use) + ADC_ACTIVE_TRIGGER_TRG7AN = (0x0DU), ///< Compare match between MTU7.TADCORA and MTU7.TCNT + ADC_ACTIVE_TRIGGER_TRG7BN = (0x0EU), ///< Compare match between MTU7.TADCORB and MTU7.TCNT + ADC_ACTIVE_TRIGGER_TRG7AN_BN = (0x0FU), ///< Compare match between MTU7.TADCORA and MTU7.TCNT, or between MTU7.TADCORB and MTU7.TCNT + ADC_ACTIVE_TRIGGER_TRG7ABN = (0x10U), ///< Compare match between MTU7.TADCORA and MTU7.TCNT, and between MTU7.TADCORB and MTU7.TCNT + ///< (when interrupt skipping function 2 is in use) + ADC_ACTIVE_TRIGGER_ELC_TRIGGER = (0x11U), ///< A/D Startup source A from ELC + ADC_ACTIVE_TRIGGER_ELC_TRIGGER_GROUP_B = (0x12U), ///< A/D Startup source B from ELC + ADC_ACTIVE_TRIGGER_DISABLED = (0x3FU), ///< A/D Start trigger disabled +} adc_active_trigger_t; + +/** ADC double-trigger mode definitions */ +typedef enum e_adc_double_trigger +{ + ADC_DOUBLE_TRIGGER_DISABLED = 0, ///< Double-triggering disabled + ADC_DOUBLE_TRIGGER_ENABLED = 1, ///< Double-triggering enabled + ADC_DOUBLE_TRIGGER_ENABLED_EXTENDED = 2, ///< Double-triggering enabled on both ADC ELC events +} adc_double_trigger_t; + +/** AD event link control definitions. */ +typedef enum e_adc_elc +{ + ADC_ELC_SINGLE_SCAN = 0x00U, ///< At the end of a single scan GCELC = 0b, ELCC[1:0] = 00b + ADC_ELC_CONTINUOUS_SCAN = 0x00U, ///< At the end of a contiuous scan GCELC = 0b, ELCC[1:0] = 00b + ADC_ELC_GROUP_A_SCAN = 0x00U, ///< At the end of a group_a scan GCELC = 0b, ELCC[1:0] = 00b + ADC_ELC_GROUP_B_SCAN = 0x01U, ///< At the end of a group_b scan GCELC = 0b, ELCC[1:0] = 01b + ADC_ELC_GROUP_A_B_C_SCAN = 0x02U, ///< At the end of a group_abc scan GCELC = 0b, ELCC[1:0] = 1xb + ADC_ELC_GROUP_C_SCAN = 0x04U, ///< At the end of a group_c scan GCELC = 1b, ELCC[1:0] = 00b +} adc_elc_t; + +/** ADC sample state configuration */ +typedef struct st_adc_sample_state +{ + adc_sample_state_reg_t reg_id; ///< Sample state register ID + uint8_t num_states; ///< Number of sampling states for conversion. Ch16-20/21 use the same value. +} adc_sample_state_t; + +/** ADC Window Compare configuration */ +typedef struct st_adc_window_cfg +{ + uint32_t compare_mask; ///< Channel mask to compare with Window A + uint32_t compare_mode_mask; ///< Per-channel condition mask for Window A + adc_compare_cfg_t compare_cfg; ///< Window Compare configuration + uint16_t compare_ref_low; ///< Window A lower reference value + uint16_t compare_ref_high; ///< Window A upper reference value + uint16_t compare_b_ref_low; ///< Window B lower reference value + uint16_t compare_b_ref_high; ///< Window B upper reference value + adc_window_b_channel_t compare_b_channel; ///< Window B channel + adc_window_b_mode_t compare_b_mode; ///< Window B condition setting +} adc_window_cfg_t; + +/** Extended configuration structure for ADC. */ +typedef struct st_adc_extended_cfg +{ + adc_add_t add_average_count; ///< Add or average samples + adc_clear_t clearing; ///< Clear after read + adc_trigger_t trigger_group_b; ///< Group B trigger source; valid only for group mode + adc_double_trigger_t double_trigger_mode; ///< Double-trigger mode setting + adc_active_trigger_t adc_start_trigger_a; ///< A/D Conversion Start Trigger Group A + adc_active_trigger_t adc_start_trigger_b; ///< A/D Conversion Start Trigger Group B + bool adc_start_trigger_c_enabled; ///< Set to true to enable Group C, false to disable Group C + adc_active_trigger_t adc_start_trigger_c; ///< A/D Conversion Start Trigger Group C + adc_elc_t adc_elc_ctrl; ///< A/D Event Link Control + IRQn_Type window_a_irq; ///< IRQ number for Window Compare A interrupts + uint8_t window_a_ipl; ///< Priority for Window Compare A interrupts + IRQn_Type window_b_irq; ///< IRQ number for Window Compare B interrupts + uint8_t window_b_ipl; ///< Priority for Window Compare B interrupts +} adc_extended_cfg_t; + +/** ADC channel(s) configuration */ +typedef struct st_adc_channel_cfg +{ + uint32_t scan_mask; ///< Channels/bits: bit 0 is ch0; bit 15 is ch15. + uint32_t scan_mask_group_b; ///< Valid for group modes. + uint32_t scan_mask_group_c; ///< Valid for group modes. + uint32_t add_mask; ///< Valid if add enabled in Open(). + adc_window_cfg_t * p_window_cfg; ///< Pointer to Window Compare configuration + adc_group_a_t priority_group_a; ///< Valid for group modes. + uint8_t sample_hold_mask; ///< Channels/bits 0-2. + uint8_t sample_hold_states; ///< Number of states to be used for sample and hold. Affects channels 0-2. +} adc_channel_cfg_t; + +/* Sample and hold Channel mask. Sample and hold is only available for channel 0,1,2*/ +#define ADC_SAMPLE_HOLD_CHANNELS (0x07U) + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +/** ADC instance control block. DO NOT INITIALIZE. Initialized in @ref adc_api_t::open(). */ +typedef struct +{ +#if 1 == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + R_ADC121_Type * p_reg; // Base register for this unit +#elif 2 == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + R_ADC120_Type * p_reg; // Base register for this unit +#elif 3 == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + R_ADC122_Type * p_reg; // Base register for this unit +#endif + + adc_cfg_t const * p_cfg; + uint32_t opened; // Boolean to verify that the Unit has been initialized + uint32_t scan_mask; // Scan mask used for Normal scan. + uint16_t scan_start_adcsr; + + void (* p_callback)(adc_callback_args_t *); // Pointer to callback that is called when an adc_event_t occurs. + adc_callback_args_t * p_callback_memory; // Pointer to non-secure memory that can be used to pass arguments to a callback in non-secure memory. + + /* Pointer to context to be passed into callback function */ + void const * p_context; +} adc_instance_ctrl_t; + +/********************************************************************************************************************** + * Exported global variables + **********************************************************************************************************************/ + +/** @cond INC_HEADER_DEFS_SEC */ +/** Interface Structure for user access */ +extern const adc_api_t g_adc_on_adc; + +/** @endcond */ + +/*********************************************************************************************************************** + * Public APIs + **********************************************************************************************************************/ +fsp_err_t R_ADC_Open(adc_ctrl_t * p_ctrl, adc_cfg_t const * const p_cfg); +fsp_err_t R_ADC_ScanCfg(adc_ctrl_t * p_ctrl, void const * const p_channel_cfg); +fsp_err_t R_ADC_InfoGet(adc_ctrl_t * p_ctrl, adc_info_t * p_adc_info); +fsp_err_t R_ADC_ScanStart(adc_ctrl_t * p_ctrl); +fsp_err_t R_ADC_ScanGroupStart(adc_ctrl_t * p_ctrl, adc_group_mask_t group_mask); +fsp_err_t R_ADC_ScanStop(adc_ctrl_t * p_ctrl); +fsp_err_t R_ADC_StatusGet(adc_ctrl_t * p_ctrl, adc_status_t * p_status); +fsp_err_t R_ADC_Read(adc_ctrl_t * p_ctrl, adc_channel_t const reg_id, uint16_t * const p_data); +fsp_err_t R_ADC_Read32(adc_ctrl_t * p_ctrl, adc_channel_t const reg_id, uint32_t * const p_data); +fsp_err_t R_ADC_SampleStateCountSet(adc_ctrl_t * p_ctrl, adc_sample_state_t * p_sample); +fsp_err_t R_ADC_Close(adc_ctrl_t * p_ctrl); +fsp_err_t R_ADC_OffsetSet(adc_ctrl_t * const p_ctrl, adc_channel_t const reg_id, int32_t offset); +fsp_err_t R_ADC_Calibrate(adc_ctrl_t * const p_ctrl, void const * p_extend); +fsp_err_t R_ADC_CallbackSet(adc_ctrl_t * const p_ctrl, + void ( * p_callback)(adc_callback_args_t *), + void const * const p_context, + adc_callback_args_t * const p_callback_memory); + +/*******************************************************************************************************************//** + * @} (end defgroup ADC) + **********************************************************************************************************************/ + +/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER + +#endif diff --git a/drivers/rz/fsp/inc/instances/rzv/r_adc_c.h b/drivers/rz/fsp/inc/instances/rzv/r_adc_c.h new file mode 100644 index 00000000..5054f014 --- /dev/null +++ b/drivers/rz/fsp/inc/instances/rzv/r_adc_c.h @@ -0,0 +1,214 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*******************************************************************************************************************//** + * @addtogroup ADC_C + * @{ + **********************************************************************************************************************/ + +#ifndef R_ADC_C_H +#define R_ADC_C_H + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ + +#include "r_adc_c_cfg.h" +#include "r_adc_api.h" +#include "bsp_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 + **********************************************************************************************************************/ + +/** For ADC Scan configuration adc_channel_cfg_t::scan_mask. + * Use bitwise OR to combine these masks for desired channels. */ +typedef enum e_adc_c_mask +{ + ADC_C_MASK_OFF = (0U), ///< No channels selected + ADC_C_MASK_CHANNEL_0 = (1U << 0U), ///< Channel 0 mask + ADC_C_MASK_CHANNEL_1 = (1U << 1U), ///< Channel 1 mask + ADC_C_MASK_CHANNEL_2 = (1U << 2U), ///< Channel 2 mask + ADC_C_MASK_CHANNEL_3 = (1U << 3U), ///< Channel 3 mask + ADC_C_MASK_CHANNEL_4 = (1U << 4U), ///< Channel 4 mask + ADC_C_MASK_CHANNEL_5 = (1U << 5U), ///< Channel 5 mask + ADC_C_MASK_CHANNEL_6 = (1U << 6U), ///< Channel 6 mask + ADC_C_MASK_CHANNEL_7 = (1U << 7U), ///< Channel 7 mask + ADC_C_MASK_CHANNEL_8 = (1U << 8U), ///< Channel 8 mask (Temperature sensor channel mask) +} adc_c_mask_t; + +/** ADC trigger mode select */ +typedef enum e_adc_c_trigger_mode +{ + ADC_C_TRIGGER_MODE_SOFTWARE = 0U, ///< Software trigger mode + ADC_C_TRIGGER_MODE_HARDWARE = 1U, ///< Hardware trigger mode +} adc_c_trigger_mode_t; + +/** ADC hardware trigger source select */ +typedef enum e_adc_c_active_trigger +{ + ADC_C_ACTIVE_TRIGGER_EXTERNAL = 0U, ///< External trigger input + ADC_C_ACTIVE_TRIGGER_TRGA0N = 1U, ///< Compare match with or input capture to MTU0.TGRA + ADC_C_ACTIVE_TRIGGER_TRGA1N = 2U, ///< Compare match with or input capture to MTU1.TGRA + ADC_C_ACTIVE_TRIGGER_TRGA2N = 3U, ///< Compare match with or input capture to MTU2.TGRA + ADC_C_ACTIVE_TRIGGER_TRGA3N = 4U, ///< Compare match with or input capture to MTU3.TGRA + ADC_C_ACTIVE_TRIGGER_TRGA4N = 5U, ///< Compare match with or input capture to MTU4.TGRA + ADC_C_ACTIVE_TRIGGER_TRGA6N = 6U, ///< Compare match with or input capture to MTU6.TGRA + ADC_C_ACTIVE_TRIGGER_TRGA7N = 7U, ///< Compare match with or input capture to MTU7.TGRA + ADC_C_ACTIVE_TRIGGER_TRG0N = 8U, ///< Compare match with MTU0.TGRE + ADC_C_ACTIVE_TRIGGER_TRG4AN = 9U, ///< Compare match between MTU4.TADCORA and MTU4.TCNT + ADC_C_ACTIVE_TRIGGER_TRG4BN = 10U, ///< Compare match between MTU4.TADCORB and MTU4.TCNT + ADC_C_ACTIVE_TRIGGER_TRG4AN_BN = 11U, ///< Compare match between MTU4.TADCORA and MTU4.TCNT, or between MTU4.TADCORB and MTU4.TCNT + ADC_C_ACTIVE_TRIGGER_TRG4ABN = 12U, ///< Compare match between MTU4.TADCORA and MTU4.TCNT, and between MTU4.TADCORB and MTU4.TCNT (when interrupt skipping function 2 is in use) + ADC_C_ACTIVE_TRIGGER_TRG7AN = 13U, ///< Compare match between MTU7.TADCORA and MTU7.TCNT + ADC_C_ACTIVE_TRIGGER_TRG7BN = 14U, ///< Compare match between MTU7.TADCORB and MTU7.TCNT + ADC_C_ACTIVE_TRIGGER_TRG7AN_BN = 15U, ///< Compare match between MTU7.TADCORA and MTU7.TCNT, or between MTU7.TADCORB and MTU7.TCNT + ADC_C_ACTIVE_TRIGGER_TRG7ABN = 16U, ///< Compare match between MTU7.TADCORA and MTU7.TCNT, and between MTU7.TADCORB and MTU7.TCNT + ADC_C_ACTIVE_TRIGGER_ADTRGA0 = 17U, ///< Compare match with GPT0.GTADTRA + ADC_C_ACTIVE_TRIGGER_ADTRGB0 = 18U, ///< Compare match with GPT0.GTADTRB + ADC_C_ACTIVE_TRIGGER_ADTRGA1 = 19U, ///< Compare match with GPT1.GTADTRA + ADC_C_ACTIVE_TRIGGER_ADTRGB1 = 20U, ///< Compare match with GPT1.GTADTRB + ADC_C_ACTIVE_TRIGGER_ADTRGA2 = 21U, ///< Compare match with GPT2.GTADTRA + ADC_C_ACTIVE_TRIGGER_ADTRGB2 = 22U, ///< Compare match with GPT2.GTADTRB + ADC_C_ACTIVE_TRIGGER_ADTRGA3 = 23U, ///< Compare match with GPT3.GTADTRA + ADC_C_ACTIVE_TRIGGER_ADTRGB3 = 24U, ///< Compare match with GPT3.GTADTRB + ADC_C_ACTIVE_TRIGGER_ADTRGA0_B0 = 25U, ///< Compare match with GPT0.GTADTRA or GPT0.GTADTRB + ADC_C_ACTIVE_TRIGGER_ADTRGA1_B1 = 26U, ///< Compare match with GPT1.GTADTRA or GPT1.GTADTRB + ADC_C_ACTIVE_TRIGGER_ADTRGA2_B2 = 27U, ///< Compare match with GPT2.GTADTRA or GPT2.GTADTRB + ADC_C_ACTIVE_TRIGGER_ADTRGA3_B3 = 28U, ///< Compare match with GPT3.GTADTRA or GPT3.GTADTRB +} adc_c_active_trigger_t; + +/** valid edge of the trigger select */ +typedef enum e_adc_c_trigger_edge +{ + ADC_C_TRIGGER_EDGE_FALLING = 1U, ///< Falling edge + ADC_C_TRIGGER_EDGE_RISING = 2U, ///< Rising edge + ADC_C_TRIGGER_EDGE_BOTH = 3U, ///< Both edges +} adc_c_trigger_edge_t; + +/** ADC trigger input mode select */ +typedef enum e_adc_c_input_mode +{ + ADC_C_INPUT_MODE_AUTO = 0U, ///< Auto mode + ADC_C_INPUT_MODE_STEP = 1U, ///< Step mode +} adc_c_input_mode_t; + +/** ADC operating mode select */ +typedef enum e_adc_c_operating_mode +{ + ADC_C_OPERATING_MODE_SCAN = 0U, ///< Scan mode + ADC_C_OPERATING_MODE_SELECT = 1U, ///< Select mode +} adc_c_operating_mode_t; + +/** ADC buffer mode select */ +typedef enum e_adc_c_buffer_mode +{ + ADC_C_BUFFER_MODE_1 = 0U, ///< 1-buffer mode + ADC_C_BUFFER_MODE_4 = 1U, ///< 4-buffer mode +} adc_c_buffer_mode_t; + +/** Select the number of stages of the AD external trigger pin filter. */ +typedef enum e_adc_c_filter_stage_setting_t +{ + ADC_C_FILTER_STAGE_SETTING_DISABLE = 0U, ///< Filter is disabled. + ADC_C_FILTER_STAGE_SETTING_4 = 1U, ///< 12.5 ns (80 MHz) x 4 stages + ADC_C_FILTER_STAGE_SETTING_8 = 2U, ///< 12.5 ns (80 MHz) x 8 stages + ADC_C_FILTER_STAGE_SETTING_12 = 3U, ///< 12.5 ns (80 MHz) x 12 stages + ADC_C_FILTER_STAGE_SETTING_16 = 4U, ///< 12.5 ns (80 MHz) x 16 stages +} adc_c_filter_stage_setting_t; + +/** Enable or disable the conversion end interrupt of channel */ +typedef enum e_adc_c_interrupt_channel_setting +{ + ADC_C_INTERRUPT_CHANNEL_SETTING_DISABLE = 0, ///< Interrupt output is disabled. + ADC_C_INTERRUPT_CHANNEL_SETTING_ENABLE = 1, ///< Interrupt output is enabled. +} adc_c_interrupt_channel_setting_t; + +/** Extended configuration structure for ADC. */ +typedef struct st_adc_c_extended_cfg +{ + adc_c_trigger_mode_t trigger_mode; ///< Trigger mode. + adc_c_active_trigger_t trigger_source; ///< Hardware trigger source. + adc_c_trigger_edge_t trigger_edge; ///< Valid edge of the trigger source. + adc_c_input_mode_t input_mode; ///< Trigger input mode. + adc_c_operating_mode_t operating_mode; ///< Operating mode. + adc_c_buffer_mode_t buffer_mode; ///< Buffer mode. + uint16_t sampling_time; ///< Sampling period. (6~2800) + adc_c_filter_stage_setting_t external_trigger_filter; ///< AD external trigger pin filter. +} adc_c_extended_cfg_t; + +/** ADC channel(s) configuration */ +typedef struct st_adc_c_channel_cfg +{ + uint32_t scan_mask; ///< Channels/bits: bit 0 is ch0; bit 1 is ch1. + adc_c_interrupt_channel_setting_t interrupt_setting; ///< Interrupt setting. +} adc_c_channel_cfg_t; + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +/** ADC instance control block. DO NOT INITIALIZE. Initialized in @ref adc_api_t::open(). */ +typedef struct +{ + R_ADC_C_Type * p_reg; // Base register + adc_cfg_t const * p_cfg; + uint32_t opened; // Boolean to verify that the Unit has been initialized + uint32_t initialized; // Initialized status of ADC + uint32_t scan_mask; // Scan mask used for Normal scan + uint32_t scan_start; + uint32_t operating_mode; + uint32_t buffer_mode; + + void (* p_callback)(adc_callback_args_t *); // Pointer to callback that is called when an adc_event_t occurs. + adc_callback_args_t * p_callback_memory; // Pointer to non-secure memory that can be used to pass arguments to a callback in non-secure memory. + + /* Pointer to context to be passed into callback function */ + void const * p_context; +} adc_c_instance_ctrl_t; + +/********************************************************************************************************************** + * Exported global variables + **********************************************************************************************************************/ + +/** @cond INC_HEADER_DEFS_SEC */ +/** Interface Structure for user access */ +extern const adc_api_t g_adc_on_adc_c; + +/** @endcond */ + +/*********************************************************************************************************************** + * Public APIs + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_Open(adc_ctrl_t * p_ctrl, adc_cfg_t const * const p_cfg); +fsp_err_t R_ADC_C_ScanCfg(adc_ctrl_t * p_ctrl, void const * const p_channel_cfg); +fsp_err_t R_ADC_C_InfoGet(adc_ctrl_t * p_ctrl, adc_info_t * p_adc_info); +fsp_err_t R_ADC_C_ScanStart(adc_ctrl_t * p_ctrl); +fsp_err_t R_ADC_C_ScanGroupStart(adc_ctrl_t * p_ctrl, adc_group_mask_t group_id); +fsp_err_t R_ADC_C_ScanStop(adc_ctrl_t * p_ctrl); +fsp_err_t R_ADC_C_StatusGet(adc_ctrl_t * p_ctrl, adc_status_t * p_status); +fsp_err_t R_ADC_C_Read(adc_ctrl_t * p_ctrl, adc_channel_t const reg_id, uint16_t * const p_data); +fsp_err_t R_ADC_C_Read32(adc_ctrl_t * p_ctrl, adc_channel_t const reg_id, uint32_t * const p_data); +fsp_err_t R_ADC_C_SampleStateCountSet(adc_ctrl_t * p_ctrl, uint16_t num_states); +fsp_err_t R_ADC_C_Close(adc_ctrl_t * p_ctrl); +fsp_err_t R_ADC_C_OffsetSet(adc_ctrl_t * const p_ctrl, adc_channel_t const reg_id, int32_t offset); +fsp_err_t R_ADC_C_Calibrate(adc_ctrl_t * const p_ctrl, void const * p_extend); +fsp_err_t R_ADC_C_CallbackSet(adc_ctrl_t * const p_api_ctrl, + void ( * p_callback)(adc_callback_args_t *), + void const * const p_context, + adc_callback_args_t * const p_callback_memory); + +/*******************************************************************************************************************//** + * @} (end defgroup ADC_C) + **********************************************************************************************************************/ + +/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER + +#endif diff --git a/drivers/rz/fsp/src/rza/r_adc_c/r_adc_c.c b/drivers/rz/fsp/src/rza/r_adc_c/r_adc_c.c new file mode 100644 index 00000000..7a7b2947 --- /dev/null +++ b/drivers/rz/fsp/src/rza/r_adc_c/r_adc_c.c @@ -0,0 +1,906 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*********************************************************************************************************************** + * Includes , "Project Includes" + **********************************************************************************************************************/ + +#include "r_adc_c_cfg.h" +#include "r_adc_c.h" +#include "bsp_api.h" + +/********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +#define ADC_C_OPEN (0x41444343U) + +/* A/D converter stabilization wait time. */ +#define ADC_C_STABILIZATION_DELAY_US (1U) +#define ADC_C_FRQ_DIV_RATIO (4U) +#define ADC_C_IDLE_TIME (0U) +#define ADC_C_CONVERSION_TIME (14U) +#define ADC_C_PRV_ADM0_CLEAR_ADCE (~R_ADC_ADM0_ADCE_Msk) +#define ADC_C_DATA_SIZE_BUFFER_MODE_4 (4U) +#define ADC_C_INTERRUPT_CHANNEL_BUFFER_MODE_4 (0x8U) +#define ADC_C_SAMPLE_STATE_COUNT_MIN (6U) +#define ADC_C_SAMPLE_STATE_COUNT_MAX (2800U) + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +#if defined(__ARMCC_VERSION) || defined(__ICCARM__) +typedef void (BSP_CMSE_NONSECURE_CALL * adc_prv_ns_callback)(adc_callback_args_t * p_args); +#elif defined(__GNUC__) +typedef BSP_CMSE_NONSECURE_CALL void (*volatile adc_prv_ns_callback)(adc_callback_args_t * p_args); +#endif + +/*********************************************************************************************************************** + * Private global variables and functions + **********************************************************************************************************************/ + +static void r_adc_c_open_sub(adc_c_instance_ctrl_t * const p_instance_ctrl, adc_cfg_t const * const p_cfg); +static void r_adc_c_scan_cfg(adc_c_instance_ctrl_t * const p_instance_ctrl, + adc_c_channel_cfg_t const * const p_channel_cfg); +void adc_c_scan_end_isr(IRQn_Type irq); +static void r_adc_c_irq_enable(IRQn_Type irq, uint8_t ipl, void * p_context); +static void r_adc_c_irq_disable(IRQn_Type irq); +static uint32_t r_adc_c_lowest_channel_get(uint32_t adc_mask); +static uint32_t r_adc_c_highest_channel_get(uint32_t adc_mask); + +/*********************************************************************************************************************** + * Global Variables + **********************************************************************************************************************/ + +/** ADC Implementation of ADC. */ +const adc_api_t g_adc_on_adc_c = +{ + .open = R_ADC_C_Open, + .scanCfg = R_ADC_C_ScanCfg, + .infoGet = R_ADC_C_InfoGet, + .scanStart = R_ADC_C_ScanStart, + .scanGroupStart = R_ADC_C_ScanGroupStart, + .scanStop = R_ADC_C_ScanStop, + .scanStatusGet = R_ADC_C_StatusGet, + .read = R_ADC_C_Read, + .read32 = R_ADC_C_Read32, + .close = R_ADC_C_Close, + .calibrate = R_ADC_C_Calibrate, + .offsetSet = R_ADC_C_OffsetSet, + .callbackSet = R_ADC_C_CallbackSet, +}; + +/*******************************************************************************************************************//** + * @addtogroup ADC + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Initializes the ADC module and applies configurations. + * + * @retval FSP_SUCCESS Module is ready for use. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_ALREADY_OPEN The instance control structure has already been opened. + * @retval FSP_ERR_IRQ_BSP_DISABLED A callback is provided, but the interrupt is not enabled. + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_Open (adc_ctrl_t * p_ctrl, adc_cfg_t const * const p_cfg) +{ + adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl; + + /* Perform parameter checking */ +#if ADC_C_CFG_PARAM_CHECKING_ENABLE + + /* Verify the pointers are valid */ + FSP_ASSERT(NULL != p_instance_ctrl); + + /* Verify the configuration parameters are valid */ + FSP_ASSERT(NULL != p_cfg); + + /* Verify this unit has not already been initialized */ + FSP_ERROR_RETURN(ADC_C_OPEN != p_instance_ctrl->opened, FSP_ERR_ALREADY_OPEN); + + /* If a callback is used, then make sure an interrupt is enabled */ + if (NULL != p_cfg->p_callback) + { + FSP_ERROR_RETURN((p_cfg->scan_end_irq >= 0), FSP_ERR_IRQ_BSP_DISABLED); + } +#endif + + /* Save configurations. */ + p_instance_ctrl->p_cfg = p_cfg; + p_instance_ctrl->p_callback = p_cfg->p_callback; + p_instance_ctrl->p_context = p_cfg->p_context; + p_instance_ctrl->p_callback_memory = NULL; + + /* Calculate the register base address. */ + p_instance_ctrl->p_reg = R_ADC; + + /* Initialize the hardware based on the configuration. */ + r_adc_c_open_sub(p_instance_ctrl, p_cfg); + + /* Enable interrupts */ + r_adc_c_irq_enable(p_cfg->scan_end_irq, p_cfg->scan_end_ipl, p_instance_ctrl); + + /* Invalid scan mask (initialized for later). */ + p_instance_ctrl->scan_mask = 0U; + + /* Mark driver as opened by initializing it to "ADCC" in its ASCII equivalent for this unit. */ + p_instance_ctrl->opened = ADC_C_OPEN; + + /* Return the error code */ + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Configures the ADC_C scan parameters. Channel specific settings are set in this function. Pass a pointer to + * @ref adc_c_channel_cfg_t to p_channel_cfg. + * + * + * @retval FSP_SUCCESS Channel specific settings applied. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_ScanCfg (adc_ctrl_t * p_ctrl, void const * const p_channel_cfg) +{ + adc_c_channel_cfg_t const * p_adc_channel_cfg = (adc_c_channel_cfg_t const *) p_channel_cfg; + adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl; + fsp_err_t err = FSP_SUCCESS; + +#if ADC_C_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_adc_channel_cfg); + FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); + + /* Multiple analog input channel selection is prohibited in select mode. */ + FSP_ASSERT(!((ADC_C_OPERATING_MODE_SELECT == p_instance_ctrl->operating_mode) && + ((ADC_C_MASK_CHANNEL_0 | ADC_C_MASK_CHANNEL_1) == p_adc_channel_cfg->scan_mask))); +#endif + + /* Configure the hardware based on the configuration. */ + r_adc_c_scan_cfg(p_instance_ctrl, p_adc_channel_cfg); + + /* Save the scan mask locally; this is required for the infoGet function. */ + p_instance_ctrl->scan_mask = p_adc_channel_cfg->scan_mask; + + /* Return the error code. */ + return err; +} + +/*******************************************************************************************************************//** + * Updates the user callback and has option of providing memory for callback structure. + * Implements adc_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_ADC_C_CallbackSet (adc_ctrl_t * const p_api_ctrl, + void ( * p_callback)(adc_callback_args_t *), + void const * const p_context, + adc_callback_args_t * const p_callback_memory) +{ + adc_c_instance_ctrl_t * p_ctrl = (adc_c_instance_ctrl_t *) p_api_ctrl; + +#if (ADC_C_CFG_PARAM_CHECKING_ENABLE) + FSP_ASSERT(p_ctrl); + FSP_ASSERT(p_callback); + FSP_ERROR_RETURN(ADC_C_OPEN == p_ctrl->opened, FSP_ERR_NOT_OPEN); +#endif + + /* Store callback and context */ + +#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 ADC_C_CFG_PARAM_CHECKING_ENABLE + + /* In secure projects, p_callback_memory must be provided in non-secure space if p_callback is non-secure */ + adc_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 + + p_ctrl->p_callback = callback_is_secure ? p_callback : + (void (*)(adc_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; +} + +/*******************************************************************************************************************//** + * Start A/D conversion. + * + * @pre Call R_ADC_C_ScanCfg after R_ADC_C_Open before starting a scan. + * + * @retval FSP_SUCCESS Scan started (software trigger) or hardware triggers enabled. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + * @retval FSP_ERR_NOT_INITIALIZED Unit is not initialized. + * @retval FSP_ERR_IN_USE Another scan is still in progress (software trigger). + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_ScanStart (adc_ctrl_t * p_ctrl) +{ + adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl; + + /* Perform parameter checking */ +#if ADC_C_CFG_PARAM_CHECKING_ENABLE + + /* Verify the pointers are valid */ + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); + FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->initialized, FSP_ERR_NOT_INITIALIZED); + FSP_ERROR_RETURN(0U == p_instance_ctrl->p_reg->ADM0_b.ADCE, FSP_ERR_IN_USE); +#endif + + /* Start A/D conversion. */ + p_instance_ctrl->p_reg->ADM0 = p_instance_ctrl->scan_start; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * @ref adc_api_t::scanGroupStart is not supported. Use scanStart instead. + * + * @retval FSP_ERR_UNSUPPORTED Function not supported in this implementation. + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_ScanGroupStart (adc_ctrl_t * p_ctrl, adc_group_mask_t group_id) +{ + FSP_PARAMETER_NOT_USED(p_ctrl); + FSP_PARAMETER_NOT_USED(group_id); + + /* Return the unsupported error. */ + return FSP_ERR_UNSUPPORTED; +} + +/*******************************************************************************************************************//** + * Stop A/D conversion. + * + * @retval FSP_SUCCESS Scan stopped (software trigger) or hardware triggers disabled. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + * @retval FSP_ERR_NOT_INITIALIZED Unit is not initialized. + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_ScanStop (adc_ctrl_t * p_ctrl) +{ + adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl; + + /* Perform parameter checking */ +#if ADC_C_CFG_PARAM_CHECKING_ENABLE + + /* Verify the pointers are valid */ + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); + FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->initialized, FSP_ERR_NOT_INITIALIZED); +#endif + + /* Stop A/D conversion. */ + p_instance_ctrl->p_reg->ADM0 = (uint32_t) (p_instance_ctrl->scan_start & ADC_C_PRV_ADM0_CLEAR_ADCE); + + /* Read ADM0 register to confirm that A/D conversion is stopped. */ + FSP_HARDWARE_REGISTER_WAIT(p_instance_ctrl->p_reg->ADM0_b.ADCE, 0U); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Get current ADC_C status and store it in provided pointer p_status. + * + * @retval FSP_SUCCESS Module status stored in the provided pointer p_status + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_StatusGet (adc_ctrl_t * p_ctrl, adc_status_t * p_status) +{ + adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl; + +#if ADC_C_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_status); + FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); +#endif + + /* Read the status of the ADBSY bit. ADBSY is set when a scan is in progress. */ + p_status->state = (adc_state_t) p_instance_ctrl->p_reg->ADM0_b.ADBSY; + + /* Return the error code */ + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Reads conversion results from a single channel or sensor. + * + * @retval FSP_SUCCESS Data read into provided p_data. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + * @retval FSP_ERR_NOT_INITIALIZED Unit is not initialized. + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_Read (adc_ctrl_t * p_ctrl, adc_channel_t const reg_id, uint16_t * const p_data) +{ + adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl; + + /* Perform parameter checking. */ +#if ADC_C_CFG_PARAM_CHECKING_ENABLE + + /* Verify the pointers are valid */ + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_data); + FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); + FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->initialized, FSP_ERR_NOT_INITIALIZED); + + /* Verify that the channel is valid for this MCU */ + uint32_t requested_channel_mask = (1U << (uint32_t) reg_id); + FSP_ASSERT(0 != (requested_channel_mask & BSP_FEATURE_ADC_VALID_CHANNEL_MASK)); +#endif + + /* Read the data from the requested ADC conversion register and return it */ + *p_data = *((uint16_t *) (&p_instance_ctrl->p_reg->ADCR0 + reg_id)); + + /* Return the error code */ + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Reads conversion results from a single channel or sensor register into a 32-bit result. + * + * @retval FSP_SUCCESS Data read into provided p_data. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + * @retval FSP_ERR_NOT_INITIALIZED Unit is not initialized. + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_Read32 (adc_ctrl_t * p_ctrl, adc_channel_t const reg_id, uint32_t * const p_data) +{ + uint16_t result = 0U; + uint32_t result_32 = 0U; + +#if ADC_C_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_data); +#endif + + fsp_err_t err = R_ADC_C_Read(p_ctrl, reg_id, &result); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + result_32 = result; + *p_data = result_32; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Sets the sample state count for individual channels. This only needs to be set for special use cases. Normally, use + * the default values out of reset. + * + * @note The sample states for the temperature and voltage sensor are set in R_ADC_C_ScanCfg. + * + * @retval FSP_SUCCESS Sample state count updated. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_INITIALIZED Unit is not initialized. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + * @retval FSP_ERR_IN_USE A/D conversion ongoing. + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_SampleStateCountSet (adc_ctrl_t * p_ctrl, uint16_t num_states) +{ + adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl; + fsp_err_t err = FSP_SUCCESS; + + /* Perform parameter checking */ +#if ADC_C_CFG_PARAM_CHECKING_ENABLE + + /* Verify the pointers are valid */ + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); + FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->initialized, FSP_ERR_NOT_INITIALIZED); + FSP_ERROR_RETURN(0 == p_instance_ctrl->p_reg->ADM0_b.ADBSY, FSP_ERR_IN_USE); + + /* Verify the arguments are within the expected range. */ + FSP_ASSERT((num_states >= ADC_C_SAMPLE_STATE_COUNT_MIN) && (num_states <= ADC_C_SAMPLE_STATE_COUNT_MAX)); +#endif + + /* Set the sample state count for the specified register */ + p_instance_ctrl->p_reg->ADM3_b.ADSMP = num_states; + + /* Return the error code */ + return err; +} + +/*******************************************************************************************************************//** + * Returns the address of the lowest number configured channel and the total number of bytes to be read in order to + * read the results of the configured channels. If no channels are configured, then a length of 0 is returned. + * + * + * @retval FSP_SUCCESS Information stored in p_adc_info. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_InfoGet (adc_ctrl_t * p_ctrl, adc_info_t * p_adc_info) +{ + adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl; + fsp_err_t err = FSP_SUCCESS; + uint32_t adc_mask = 0; + +#if ADC_C_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_adc_info); + FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); +#endif + + adc_c_extended_cfg_t * p_extend = (adc_c_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + /* Retrieve the scan mask of active channels from the control structure */ + adc_mask = p_instance_ctrl->scan_mask; + + if (ADC_C_BUFFER_MODE_4 == p_extend->buffer_mode) + { + p_adc_info->length = ADC_C_DATA_SIZE_BUFFER_MODE_4; + p_adc_info->p_address = &p_instance_ctrl->p_reg->ADCR0; + } + else + { + /* If at least one channel is configured, determine the highest and lowest configured channels. */ + if (adc_mask != 0U) + { + uint32_t adc_mask_in_order = adc_mask; + uint32_t lowest_channel = r_adc_c_lowest_channel_get(adc_mask_in_order); + + p_adc_info->p_address = (uint32_t *) (&p_instance_ctrl->p_reg->ADCR0 + lowest_channel); + + /* Determine the highest channel that is configured. */ + uint32_t highest_channel = r_adc_c_highest_channel_get(adc_mask_in_order); + + /* Determine the size of data that must be read to read all the channels between and including the + * highest and lowest channels.*/ + p_adc_info->length = (uint32_t) ((highest_channel - lowest_channel) + 1); + } + else + { + /* If no channels are configured, set the return length 0. */ + p_adc_info->length = 0U; + } + } + + p_adc_info->transfer_size = TRANSFER_SIZE_2_BYTE; + + return err; +} + +/*******************************************************************************************************************//** + * This function ends any scan in progress, disables interrupts, and removes power to the A/D peripheral. + * + * @retval FSP_SUCCESS Module closed. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_Close (adc_ctrl_t * p_ctrl) +{ + adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl; + +#if ADC_C_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); +#endif + + /* Mark driver as closed */ + p_instance_ctrl->opened = 0U; + p_instance_ctrl->initialized = 0U; + + /* Disable interrupts. */ + r_adc_c_irq_disable(p_instance_ctrl->p_cfg->scan_end_irq); + + /* Stop the ADC. */ + p_instance_ctrl->p_reg->ADM0 = 0U; + + /* Read ADM0 register to confirm that A/D conversion is stopped. */ + FSP_HARDWARE_REGISTER_WAIT(p_instance_ctrl->p_reg->ADM0_b.ADCE, 0U); + + /* Clear the interrupt cause flag and trigger detection flag. */ + uint32_t adsts = (uint32_t) (1 << R_ADC_ADSTS_TRGS_Pos); + adsts |= (uint32_t) (BSP_FEATURE_ADC_VALID_CHANNEL_MASK << R_ADC_ADSTS_INTST_Pos); + p_instance_ctrl->p_reg->ADSTS = adsts; + + R_BSP_MODULE_STOP(FSP_IP_ADC, 0); + + /* Return the error code */ + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * @ref adc_api_t::calibrate is not supported. + * + * @retval FSP_ERR_UNSUPPORTED Calibration not supported on this MCU. + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_Calibrate (adc_ctrl_t * const p_ctrl, void const * p_extend) +{ + FSP_PARAMETER_NOT_USED(p_ctrl); + FSP_PARAMETER_NOT_USED(p_extend); + + /* Return the unsupported error. */ + return FSP_ERR_UNSUPPORTED; +} + +/*******************************************************************************************************************//** + * @ref adc_api_t::offsetSet is not supported. + * + * @retval FSP_ERR_UNSUPPORTED Function not supported in this implementation. + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_OffsetSet (adc_ctrl_t * const p_ctrl, adc_channel_t const reg_id, int32_t offset) +{ + FSP_PARAMETER_NOT_USED(p_ctrl); + FSP_PARAMETER_NOT_USED(reg_id); + FSP_PARAMETER_NOT_USED(offset); + + /* Return the unsupported error. */ + return FSP_ERR_UNSUPPORTED; +} + +/*******************************************************************************************************************//** + * @} (end addtogroup ADC) + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Private Functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * The Open function applies power to the A/D peripheral, sets the value for ADM0, ADM1, ADM3, ADIVC, ADFIL. + * + * @param[in] p_instance_ctrl Pointer to instance control block + * @param[in] p_cfg Pointer to configuration structure + **********************************************************************************************************************/ +static void r_adc_c_open_sub (adc_c_instance_ctrl_t * const p_instance_ctrl, adc_cfg_t const * const p_cfg) +{ + adc_c_extended_cfg_t const * p_cfg_extend = (adc_c_extended_cfg_t const *) p_cfg->p_extend; + + /* Determine the value for ADM0, ADM1, ADM3, ADIVC, ADFIL.: + * The value to set in ADCSR to start a scan is stored in the control structure. + * ADM0.ADCE is set in R_ADC_ScanStart. + *//* Sets the trigger mode. */ + uint32_t adm1 = (uint32_t) (p_cfg_extend->trigger_mode << R_ADC_ADM1_TRG_Pos); + + /* When using hardware trigger mode, set the hardware trigger signal parameter. */ + if (ADC_C_TRIGGER_MODE_HARDWARE == p_cfg_extend->trigger_mode) + { + adm1 |= (uint32_t) (p_cfg_extend->trigger_source << R_ADC_ADM1_TRGEN_Pos); + adm1 |= (uint32_t) (p_cfg_extend->input_mode << R_ADC_ADM1_TRGIN_Pos); + + /* The trigger edge setting is valid only when the trigger source is ADC_TRG. + * Reference section "A/D Converter Mode Register 1 (ADM1)" of the user's manual. */ + if (ADC_C_ACTIVE_TRIGGER_EXTERNAL == p_cfg_extend->trigger_source) + { + adm1 |= (uint32_t) (p_cfg_extend->trigger_edge << R_ADC_ADM1_EGA_Pos); + } + /* Otherwise falling edge is always valid. */ + else + { + adm1 |= (uint32_t) (ADC_C_TRIGGER_EDGE_FALLING << R_ADC_ADM1_EGA_Pos); + } + } + else + { + /* Do nothing. */ + } + + /* Sets the operating mode and buffer mode. */ + adm1 |= (uint32_t) (p_cfg_extend->operating_mode << R_ADC_ADM1_MS_Pos); + + /* 1-Buffer mode and 4-Buffer mode can be set when using select mode. */ + if (ADC_C_OPERATING_MODE_SELECT == p_cfg_extend->operating_mode) + { + adm1 |= (uint32_t) (p_cfg_extend->buffer_mode << R_ADC_ADM1_BS_Pos); + } + + /* Repeat mode corresponds to ADC_MODE_CONTINUOUS_SCAN of API, + * but since the API value (=2) and repeat mode register setting value (=1) are different, + * it is necessary to convert them. + * Sets the conversion mode. */ + adm1 |= (uint32_t) ((p_cfg->mode >> 1U) << R_ADC_ADM1_RPS_Pos); + + /* Sets the frequency division ratio for dividing the frequency of ADC_ADCLK(TSUϕ). */ + uint32_t adivc = (uint32_t) (ADC_C_FRQ_DIV_RATIO << R_ADC_ADIVC_DIVADC_Pos); + + uint32_t adfil = 0; + + /* Enables or disables the AD external trigger pin filter. */ + if (ADC_C_FILTER_STAGE_SETTING_DISABLE != p_cfg_extend->external_trigger_filter) + { + adfil = (uint32_t) (1 << R_ADC_ADFIL_FILONOFF_Pos); + + /* Set the number of stages of the AD external trigger pin filter. */ + adfil |= (uint32_t) ((p_cfg_extend->external_trigger_filter - 1) << R_ADC_ADFIL_FILNUM_Pos); + } + else + { + /* Do nothing. */ + } + + /* Set the idle period. */ + uint32_t adm3 = (uint32_t) (ADC_C_IDLE_TIME << R_ADC_ADM3_ADIL_Pos); + + /* Set the conversion period and sampling period. */ + adm3 |= (uint32_t) (ADC_C_CONVERSION_TIME << R_ADC_ADM3_ADCMP_Pos); + adm3 |= (uint32_t) (p_cfg_extend->sampling_time << R_ADC_ADM3_ADSMP_Pos); + + /* Apply clock to peripheral. */ + + R_BSP_MODULE_START(FSP_IP_ADC, 0); + + /* The following series of steps refer to "A/D conversion start procedure" in the user's manual. */ + /* Release from software reset state. */ + uint32_t adm0 = (uint32_t) (1 << R_ADC_ADM0_SRESB_Pos); + p_instance_ctrl->p_reg->ADM0 = adm0; + + /* The waiting time until the reset state of the A/D converter is released is 2 × ADC_ADCLK(TSUϕ) (80 MHz), + * but since the minimum waiting time of R_BSP_SoftwareDelay is 1us, + * processing is executed with a waiting time of 1us. */ + R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MICROSECONDS); + + /* Clear the interrupt cause flag and trigger detection flag. */ + uint32_t adsts = (uint32_t) (1 << R_ADC_ADSTS_TRGS_Pos); + adsts |= (uint32_t) (BSP_FEATURE_ADC_VALID_CHANNEL_MASK << R_ADC_ADSTS_INTST_Pos); + p_instance_ctrl->p_reg->ADSTS = adsts; + + /* Set the predetermined values for ADM1, ADM3, ADINT, ADIVC, and ADFIL. + * ADM0.ADCE are set as configured in R_ADC_ScanStart. */ + p_instance_ctrl->p_reg->ADM1 = adm1; + p_instance_ctrl->p_reg->ADM3 = adm3; + p_instance_ctrl->p_reg->ADIVC = adivc; + p_instance_ctrl->p_reg->ADFIL = adfil; + + /* Change from power-saving mode to normal mode. */ + adm0 |= (uint32_t) (1 << R_ADC_ADM0_PWDWNB_Pos); + p_instance_ctrl->p_reg->ADM0 = adm0; + + /* Secure the A/D converter stabilization wait time. */ + R_BSP_SoftwareDelay(ADC_C_STABILIZATION_DELAY_US, BSP_DELAY_UNITS_MICROSECONDS); + + /* Set the ADCE bit. */ + adm0 |= (uint32_t) (R_ADC_ADM0_ADCE_Msk); + + p_instance_ctrl->scan_start = adm0; + + /* Save the operating mode and buffer mode locally; this is required for the Scancfg function. */ + p_instance_ctrl->operating_mode = p_cfg_extend->operating_mode; + p_instance_ctrl->buffer_mode = p_cfg_extend->buffer_mode; +} + +/*******************************************************************************************************************//** + * This function does extensive checking on channel mask settings based upon operational mode. Mask registers are + * initialized and interrupts enabled in peripheral. Interrupts are also enabled in ICU if corresponding priority + * is not 0. + * + * @param[in] p_instance_ctrl Pointer to instance control block + * @param[in] p_channel_cfg Pointer to channel configuration + **********************************************************************************************************************/ +static void r_adc_c_scan_cfg (adc_c_instance_ctrl_t * const p_instance_ctrl, + adc_c_channel_cfg_t const * const p_channel_cfg) +{ + /* Set mask for channels. */ + p_instance_ctrl->p_reg->ADM2 = (uint32_t) (p_channel_cfg->scan_mask & (uint32_t) R_ADC_ADM2_CHSEL_Msk); + + /* Disables the A/D conversion channel select error interrupt. */ + uint32_t adint = (uint32_t) (0 << R_ADC_ADINT_CSEEN_Pos); + + /* Enable or disable the conversion end interrupt of channel n (n = 0 to 3). */ + if (ADC_C_INTERRUPT_CHANNEL_SETTING_ENABLE == p_channel_cfg->interrupt_setting) + { + /* Channel 3 interrupt output is enabled in 4-buffer mode. + * Reference section "Example of A/D Conversion in 4-Buffer Mode" of the user's manual.*/ + if (ADC_C_BUFFER_MODE_4 == p_instance_ctrl->buffer_mode) + { + adint |= (uint32_t) (ADC_C_INTERRUPT_CHANNEL_BUFFER_MODE_4 << R_ADC_ADINT_INTEN_Pos); + } + else + { + uint32_t adc_mask_in_order = p_channel_cfg->scan_mask; + + /* Determine the highest channel that is configured. */ + uint32_t highest_channel = r_adc_c_highest_channel_get(adc_mask_in_order); + + /* Highest channel interrupt output is enabled. */ + adint |= (uint32_t) (1U << highest_channel); + } + } + else + { + /* Do nothing. */ + } + + p_instance_ctrl->p_reg->ADINT = adint; + + p_instance_ctrl->initialized = ADC_C_OPEN; +} + +/*******************************************************************************************************************//** + * Disables and clears context for the requested IRQ. + * + * @param[in] irq IRQ to enable + * @param[in] ipl Interrupt priority + * @param[in] p_context Pointer to interrupt context + **********************************************************************************************************************/ +static void r_adc_c_irq_enable (IRQn_Type irq, uint8_t ipl, void * p_context) +{ + if (irq >= 0) + { + R_BSP_IrqCfgEnable(irq, ipl, p_context); + } +} + +/*******************************************************************************************************************//** + * Disables and clears context for the requested IRQ. + * + * @param[in] irq IRQ to disable + **********************************************************************************************************************/ +static void r_adc_c_irq_disable (IRQn_Type irq) +{ + if (irq >= 0) + { + R_BSP_IrqDisable(irq); + R_FSP_IsrContextSet(irq, NULL); + } +} + +/*******************************************************************************************************************//** + * Returns the lowest channel index that is configured in order to read the results of the configured channels. + * + * @param[in] adc_mask scan mask of active channels retrieved from the control structure + * + * @retval adc_mask_count index value of lowest channel + **********************************************************************************************************************/ +static uint32_t r_adc_c_lowest_channel_get (uint32_t adc_mask) +{ + /* Initialize the mask result */ + uint32_t adc_mask_result = 0U; + int32_t adc_mask_count = -1; + while (0U == adc_mask_result) + { + /* Increment channel until a channel is found in the mask. */ + adc_mask_count++; + adc_mask_result = (uint32_t) (adc_mask & (1U << adc_mask_count)); + } + + return (uint32_t) adc_mask_count; +} + +/*******************************************************************************************************************//** + * Returns the highest channel index that is configured in order to read the results of the configured channels. + * + * @param[in] adc_mask scan mask of active channels retrieved from the control structure + * + * @retval adc_mask_count index value of highest channel + **********************************************************************************************************************/ +static uint32_t r_adc_c_highest_channel_get (uint32_t adc_mask) +{ + /* Initialize the mask result */ + uint32_t adc_mask_result = 0U; + uint32_t adc_mask_count = 31; + while (0U == adc_mask_result) + { + /* Decrement channel until a channel is found in the mask. */ + adc_mask_count--; + adc_mask_result = (uint32_t) (adc_mask & (1U << adc_mask_count)); + } + + return adc_mask_count; +} + +/*******************************************************************************************************************//** + * Calls user callback. + * + * @param[in] p_ctrl Pointer to ADC instance control block + * @param[in] p_args Pointer to arguments on stack + **********************************************************************************************************************/ +static void r_adc_call_callback (adc_c_instance_ctrl_t * p_ctrl, adc_callback_args_t * p_args) +{ + adc_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. */ + adc_callback_args_t * p_args_memory = p_ctrl->p_callback_memory; + if (NULL == p_args_memory) + { + /* Use provided args struct on stack */ + p_args_memory = p_args; + } + else + { + /* Save current arguments on the stack in case this is a nested interrupt. */ + args = *p_args_memory; + + /* Copy the stacked args to callback memory */ + *p_args_memory = *p_args; + } + +#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_memory); + } + else + { + /* If p_callback is Non-secure, then the project must change to Non-secure state in order to call the callback. */ + adc_prv_ns_callback p_callback = (adc_prv_ns_callback) (p_ctrl->p_callback); + p_callback(p_args_memory); + } + +#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_memory); +#endif + + if (NULL != p_ctrl->p_callback_memory) + { + /* Restore callback memory in case this is a nested interrupt. */ + *p_ctrl->p_callback_memory = args; + } +} + +/*******************************************************************************************************************//** + * This function implements interrupt handler for scan complete. + **********************************************************************************************************************/ +void adc_c_scan_end_isr (IRQn_Type const irq) +{ + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE + + adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) R_FSP_IsrContextGet(irq); + adc_c_extended_cfg_t * p_extend = (adc_c_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + /* Clear the BSP IRQ Flag */ + R_BSP_IrqStatusClear(irq); + + adc_callback_args_t args; + args.event = ADC_EVENT_SCAN_COMPLETE; + + /* Populate the context field. */ + args.p_context = p_instance_ctrl->p_context; + + uint32_t adsts = 0; + + /* Clear the trigger detection flag. */ + if (ADC_C_TRIGGER_MODE_HARDWARE == p_extend->trigger_mode) + { + adsts = (uint32_t) (1 << R_ADC_ADSTS_TRGS_Pos); + } + + /* Clear the interrupt cause flag. */ + adsts |= (uint32_t) (BSP_FEATURE_ADC_VALID_CHANNEL_MASK << R_ADC_ADSTS_INTST_Pos); + p_instance_ctrl->p_reg->ADSTS = adsts; + + /* Dummy read the ADSTS bit. */ + volatile uint32_t dummy = p_instance_ctrl->p_reg->ADSTS; + FSP_PARAMETER_NOT_USED(dummy); + + /* Initialize the unit to 0. It is not used in this implementation. */ + args.unit = 0U; + + /* Initialize the channel to 0. It is not used in this implementation. */ + args.channel = ADC_CHANNEL_0; + + /* If a callback was provided, call it with the argument */ + if (NULL != p_instance_ctrl->p_callback) + { + r_adc_call_callback(p_instance_ctrl, &args); + } + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE +} diff --git a/drivers/rz/fsp/src/rzg/r_adc_c/r_adc_c.c b/drivers/rz/fsp/src/rzg/r_adc_c/r_adc_c.c index e68989d5..16bf9c19 100644 --- a/drivers/rz/fsp/src/rzg/r_adc_c/r_adc_c.c +++ b/drivers/rz/fsp/src/rzg/r_adc_c/r_adc_c.c @@ -53,7 +53,7 @@ static int32_t r_adc_c_highest_channel_get(uint32_t adc_mask); **********************************************************************************************************************/ /** ADC Implementation of ADC. */ -const adc_api_t g_adc_on_adc = +const adc_api_t g_adc_on_adc_c = { .open = R_ADC_C_Open, .scanCfg = R_ADC_C_ScanCfg, diff --git a/drivers/rz/fsp/src/rzn/r_adc/r_adc.c b/drivers/rz/fsp/src/rzn/r_adc/r_adc.c new file mode 100644 index 00000000..2a010e02 --- /dev/null +++ b/drivers/rz/fsp/src/rzn/r_adc/r_adc.c @@ -0,0 +1,1408 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*********************************************************************************************************************** + * Includes , "Project Includes" + **********************************************************************************************************************/ + +#include "bsp_api.h" + +/* Configuration for this package. */ +#include "r_adc_cfg.h" + +/* Private header file for this package. */ +#include "r_adc.h" + +/********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +#define ADC_PRV_USEC_PER_SEC (1000000U) +#define ADC_PRV_MIN_ADCLK_HZ (18750000U) + +#define ADC_PRV_HZ_PER_KHZ (1000U) + +#define ADC_SHIFT_LEFT_ALIGNED_32_BIT (16U) + +#define ADC_OPEN (0x52414443U) + +#define ADC_ADADC_AVEE_BIT (0x80U) + +/* Sample and hold bypass applies to these channels. */ +#define ADC_MASK_SAMPLE_HOLD_BYPASS_CHANNELS (0x7U) + +/* Sample and hold bypass starts at bit 8. */ +#define ADC_MASK_SAMPLE_HOLD_BYPASS_SHIFT (8U) + +/* Stabilization time when BGR is enabled */ +#define ADC_BGR_STABILIZATION_DELAY_US (150U) + +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + #define ADC_PRV_ADCSR_ADST_TRGE_MASK (R_ADC121_ADCSR_ADST_Msk | R_ADC121_ADCSR_TRGE_Msk) +#elif 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + #define ADC_PRV_ADCSR_ADST_TRGE_MASK (R_ADC120_ADCSR_ADST_Msk | R_ADC120_ADCSR_TRGE_Msk) +#endif +#define ADC_PRV_ADCSR_CLEAR_ADST_TRGE (~ADC_PRV_ADCSR_ADST_TRGE_MASK) + +#define ADC_ADCALCTL_SET_CAL (1U) + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Private global variables and functions + **********************************************************************************************************************/ +#if ADC_CFG_PARAM_CHECKING_ENABLE +static fsp_err_t r_adc_open_cfg_check(adc_cfg_t const * const p_cfg); +static fsp_err_t r_adc_open_cfg_resolution_check(adc_cfg_t const * const p_cfg); +static fsp_err_t r_adc_sample_state_cfg_check(adc_instance_ctrl_t * p_instance_ctrl, adc_sample_state_t * p_sample); + +static fsp_err_t r_adc_scan_cfg_check_sample_hold(adc_instance_ctrl_t * const p_instance_ctrl, + adc_channel_cfg_t const * const p_channel_cfg); +static fsp_err_t r_adc_scan_cfg_check_window_compare(adc_window_cfg_t const * const p_window_cfg); + +#endif + +static fsp_err_t r_adc_open_sub(adc_instance_ctrl_t * const p_instance_ctrl, adc_cfg_t const * const p_cfg); + +#if ADC_CFG_PARAM_CHECKING_ENABLE + +static fsp_err_t r_adc_scan_cfg_check(adc_instance_ctrl_t * const p_instance_ctrl, + adc_channel_cfg_t const * const p_channel_cfg); + +#endif + +static void r_adc_scan_cfg(adc_instance_ctrl_t * const p_instance_ctrl, + adc_channel_cfg_t const * const p_channel_cfg); +void adc_scan_end_b_isr(void); +void adc_scan_end_c_isr(void); +void adc_scan_end_isr(void); +void adc_window_compare_isr(void); +static int32_t r_adc_lowest_channel_get(uint32_t adc_mask); +static void r_adc_scan_end_common_isr(adc_event_t event); + +#if ADC_CFG_PARAM_CHECKING_ENABLE + +/** Mask of valid channels on this MCU. */ +static const uint32_t g_adc_valid_channels[] = +{ + BSP_FEATURE_ADC_UNIT_0_CHANNELS, + #if BSP_FEATURE_ADC_UNIT_1_CHANNELS + BSP_FEATURE_ADC_UNIT_1_CHANNELS, + #endif + #if BSP_FEATURE_ADC_UNIT_2_CHANNELS + BSP_FEATURE_ADC_UNIT_2_CHANNELS + #endif +}; +#endif + +/*********************************************************************************************************************** + * Global Variables + **********************************************************************************************************************/ + +/** ADC Implementation of ADC. */ +const adc_api_t g_adc_on_adc = +{ + .open = R_ADC_Open, + .scanCfg = R_ADC_ScanCfg, + .infoGet = R_ADC_InfoGet, + .scanStart = R_ADC_ScanStart, + .scanGroupStart = R_ADC_ScanGroupStart, + .scanStop = R_ADC_ScanStop, + .scanStatusGet = R_ADC_StatusGet, + .read = R_ADC_Read, + .read32 = R_ADC_Read32, + .close = R_ADC_Close, + .calibrate = R_ADC_Calibrate, + .offsetSet = R_ADC_OffsetSet, + .callbackSet = R_ADC_CallbackSet, +}; + +/*******************************************************************************************************************//** + * @addtogroup ADC + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Sets the operational mode, trigger sources, interrupt priority, and configurations for the peripheral as a whole. + * If interrupt is enabled, the function registers a callback function pointer for notifying the user whenever a scan + * has completed. + * + * @retval FSP_SUCCESS Module is ready for use. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_ALREADY_OPEN The instance control structure has already been opened. + * @retval FSP_ERR_IRQ_BSP_DISABLED A callback is provided, but the interrupt is not enabled. + * @retval FSP_ERR_IP_CHANNEL_NOT_PRESENT The requested unit does not exist on this MCU. + * @retval FSP_ERR_INVALID_HW_CONDITION The ADC clock must be at least 1 MHz + **********************************************************************************************************************/ +fsp_err_t R_ADC_Open (adc_ctrl_t * p_ctrl, adc_cfg_t const * const p_cfg) +{ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + + fsp_err_t err; + + /* Perform parameter checking */ +#if ADC_CFG_PARAM_CHECKING_ENABLE + + /* Verify the pointers are valid */ + FSP_ASSERT(NULL != p_instance_ctrl); + + /* Verify the configuration parameters are valid */ + err = r_adc_open_cfg_check(p_cfg); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + /* Check for valid argument values for options that are unique to the IP */ + err = r_adc_open_cfg_resolution_check(p_cfg); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + /* Verify this unit has not already been initialized */ + FSP_ERROR_RETURN(ADC_OPEN != p_instance_ctrl->opened, FSP_ERR_ALREADY_OPEN); + + /* If a callback is used, then make sure an interrupt is enabled */ + adc_extended_cfg_t const * p_extend = (adc_extended_cfg_t const *) p_cfg->p_extend; + if (NULL != p_cfg->p_callback) + { + FSP_ERROR_RETURN((p_cfg->scan_end_irq >= 0) || (p_extend->window_a_irq >= 0) || (p_extend->window_b_irq >= 0), + FSP_ERR_IRQ_BSP_DISABLED); + + /* Group B interrupts are never required since group B can be configured in continuous scan mode when group A + * has priority over group B. */ + } + +#else + adc_extended_cfg_t const * p_extend = (adc_extended_cfg_t const *) p_cfg->p_extend; +#endif + + /* Save configurations. */ + p_instance_ctrl->p_cfg = p_cfg; + p_instance_ctrl->p_callback = p_cfg->p_callback; + p_instance_ctrl->p_context = p_cfg->p_context; + p_instance_ctrl->p_callback_memory = NULL; + + /* Calculate the register base address. */ + uintptr_t base_address = (uintptr_t) R_ADC120; + if (0U == p_cfg->unit) + { + base_address = (uintptr_t) R_ADC120; + } + else if (1U == p_cfg->unit) + { + base_address = (uintptr_t) R_ADC121; + } + else + { +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + + /* Do Nothing */ +#elif 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + base_address = (uintptr_t) R_ADC122; +#endif + } + +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + p_instance_ctrl->p_reg = (R_ADC121_Type *) base_address; +#elif 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + p_instance_ctrl->p_reg = (R_ADC122_Type *) base_address; +#endif + + /* Initialize the hardware based on the configuration. */ + err = r_adc_open_sub(p_instance_ctrl, p_cfg); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + /* Set the interrupt priorities. */ + if (p_instance_ctrl->p_cfg->scan_end_irq >= 0) + { + R_BSP_IrqCfgEnable(p_instance_ctrl->p_cfg->scan_end_irq, p_cfg->scan_end_ipl, p_instance_ctrl); + } + + if (p_instance_ctrl->p_cfg->scan_end_b_irq >= 0) + { + R_BSP_IrqCfgEnable(p_instance_ctrl->p_cfg->scan_end_b_irq, p_cfg->scan_end_b_ipl, p_instance_ctrl); + } + + if (p_instance_ctrl->p_cfg->scan_end_c_irq >= 0) + { + R_BSP_IrqCfgEnable(p_instance_ctrl->p_cfg->scan_end_c_irq, p_cfg->scan_end_c_ipl, p_instance_ctrl); + } + + if (p_extend->window_a_irq >= 0) + { + R_BSP_IrqCfgEnable(p_extend->window_a_irq, p_extend->window_a_ipl, p_instance_ctrl); + } + + if (p_extend->window_b_irq >= 0) + { + R_BSP_IrqCfgEnable(p_extend->window_b_irq, p_extend->window_b_ipl, p_instance_ctrl); + } + + /* Invalid scan mask (initialized for later). */ + p_instance_ctrl->scan_mask = 0U; + + /* Mark driver as opened by initializing it to "RADC" in its ASCII equivalent for this unit. */ + p_instance_ctrl->opened = ADC_OPEN; + + /* Return the error code */ + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Configures the ADC scan parameters. Channel specific settings are set in this function. Pass a pointer to + * @ref adc_channel_cfg_t to p_channel_cfg. + * + * @note This starts group B scans if adc_channel_cfg_t::priority_group_a is set to ADC_GROUP_A_GROUP_B_CONTINUOUS_SCAN. + * + * @retval FSP_SUCCESS Channel specific settings applied. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_ScanCfg (adc_ctrl_t * p_ctrl, void const * const p_channel_cfg) +{ + adc_channel_cfg_t const * p_adc_channel_cfg = (adc_channel_cfg_t const *) p_channel_cfg; + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + fsp_err_t err = FSP_SUCCESS; + +#if ADC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_adc_channel_cfg); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); + + err = r_adc_scan_cfg_check(p_instance_ctrl, p_adc_channel_cfg); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); +#endif + + /* Configure the hardware based on the configuration */ + r_adc_scan_cfg(p_instance_ctrl, p_adc_channel_cfg); + + /* Save the scan mask locally; this is required for the infoGet function. */ + p_instance_ctrl->scan_mask = p_adc_channel_cfg->scan_mask; + + /* Return the error code */ + return err; +} + +/*******************************************************************************************************************//** + * Updates the user callback and has option of providing memory for callback structure. + * Implements adc_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_ADC_CallbackSet (adc_ctrl_t * const p_ctrl, + void ( * p_callback)(adc_callback_args_t *), + void const * const p_context, + adc_callback_args_t * const p_callback_memory) +{ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + +#if (ADC_CFG_PARAM_CHECKING_ENABLE) + FSP_ASSERT(p_instance_ctrl); + FSP_ASSERT(p_callback); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); +#endif + + /* Store callback and context */ + p_instance_ctrl->p_callback = p_callback; + p_instance_ctrl->p_context = p_context; + p_instance_ctrl->p_callback_memory = p_callback_memory; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Starts a software scan or enables the hardware trigger for a scan depending on how the triggers were configured in + * the R_ADC_Open call. If the unit was configured for ELC or external hardware triggering, then this function allows + * the trigger signal to get to the ADC unit. The function is not able to control the generation of the trigger itself. + * If the unit was configured for software triggering, then this function starts the software triggered scan. + * + * @pre Call R_ADC_ScanCfg after R_ADC_Open before starting a scan. + * + * @retval FSP_SUCCESS Scan started (software trigger) or hardware triggers enabled. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + * @retval FSP_ERR_IN_USE Another scan is still in progress (software trigger). + **********************************************************************************************************************/ +fsp_err_t R_ADC_ScanStart (adc_ctrl_t * p_ctrl) +{ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + + /* Perform parameter checking */ +#if ADC_CFG_PARAM_CHECKING_ENABLE + + /* Verify the pointers are valid */ + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); + if (ADC_GROUP_A_GROUP_B_CONTINUOUS_SCAN != p_instance_ctrl->p_reg->ADGSPCR) + { + FSP_ERROR_RETURN(0U == p_instance_ctrl->p_reg->ADCSR_b.ADST, FSP_ERR_IN_USE); + } +#endif + + /* Enable hardware trigger or start software scan depending on mode. */ + p_instance_ctrl->p_reg->ADCSR = p_instance_ctrl->scan_start_adcsr; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * @ref adc_api_t::scanGroupStart is not supported on the ADC. Use scanStart instead. + * + * @retval FSP_ERR_UNSUPPORTED Function not supported in this implementation. + **********************************************************************************************************************/ +fsp_err_t R_ADC_ScanGroupStart (adc_ctrl_t * p_ctrl, adc_group_mask_t group_mask) +{ + FSP_PARAMETER_NOT_USED(p_ctrl); + FSP_PARAMETER_NOT_USED(group_mask); + + /* Return the unsupported error. */ + return FSP_ERR_UNSUPPORTED; +} + +/*******************************************************************************************************************//** + * Stops the software scan or disables the unit from being triggered by the hardware trigger (ELC or external) based on + * what type of trigger the unit was configured for in the R_ADC_Open function. Stopping a hardware triggered scan via + * this function does not abort an ongoing scan, but prevents the next scan from occurring. Stopping a software + * triggered scan aborts an ongoing scan. + * + * @retval FSP_SUCCESS Scan stopped (software trigger) or hardware triggers disabled. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_ScanStop (adc_ctrl_t * p_ctrl) +{ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + + /* Perform parameter checking */ +#if ADC_CFG_PARAM_CHECKING_ENABLE + + /* Verify the pointers are valid */ + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); +#endif + + /* Disable hardware trigger or stop software scan depending on mode. */ + p_instance_ctrl->p_reg->ADCSR = 0U; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Provides the status of any scan process that was started, including scans started by ELC or external triggers. + * + * @retval FSP_SUCCESS Module status stored in the provided pointer p_status + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_StatusGet (adc_ctrl_t * p_ctrl, adc_status_t * p_status) +{ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + +#if ADC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_status); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); +#endif + + /* Read the status of the ADST bit. ADST is set when a scan is in progress. */ + p_status->state = (adc_state_t) p_instance_ctrl->p_reg->ADCSR_b.ADST; + + /* Return the error code */ + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Reads conversion results from a single channel or sensor. + * + * @retval FSP_SUCCESS Data read into provided p_data. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_Read (adc_ctrl_t * p_ctrl, adc_channel_t const reg_id, uint16_t * const p_data) +{ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + + /* Perform parameter checking. */ +#if ADC_CFG_PARAM_CHECKING_ENABLE + + /* Verify the pointers are valid */ + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_data); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); + + /* Verify that the channel is valid for this MCU */ + if ((reg_id >= ADC_CHANNEL_0) && ((uint32_t) reg_id <= 31U)) + { + uint32_t requested_channel_mask = (1U << (uint32_t) reg_id); + FSP_ASSERT(0 != (requested_channel_mask & g_adc_valid_channels[p_instance_ctrl->p_cfg->unit])); + } + else + { + FSP_ASSERT((reg_id == ADC_CHANNEL_DUPLEX) || (reg_id == ADC_CHANNEL_DUPLEX_A) || + (reg_id == ADC_CHANNEL_DUPLEX_B)); + } +#endif + + /* Read the data from the requested ADC conversion register and return it */ + *p_data = p_instance_ctrl->p_reg->ADDR[reg_id]; + + /* Return the error code */ + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Reads conversion results from a single channel or sensor register into a 32-bit result. + * + * @retval FSP_SUCCESS Data read into provided p_data. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_Read32 (adc_ctrl_t * p_ctrl, adc_channel_t const reg_id, uint32_t * const p_data) +{ + uint16_t result = 0U; + uint32_t result_32 = 0U; + +#if ADC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_data); +#endif + + fsp_err_t err = R_ADC_Read(p_ctrl, reg_id, &result); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + result_32 = result; + + /* Left shift the result into the upper 16 bits if the unit is configured for left alignment. */ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + if (ADC_ALIGNMENT_LEFT == p_instance_ctrl->p_cfg->alignment) + { + result_32 <<= ADC_SHIFT_LEFT_ALIGNED_32_BIT; + } + + *p_data = result_32; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Sets the sample state count for individual channels. This only needs to be set for special use cases. Normally, use + * the default values out of reset. + * + * @note The sample states for the temperature and voltage sensor are set in R_ADC_ScanCfg. + * + * @retval FSP_SUCCESS Sample state count updated. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_SampleStateCountSet (adc_ctrl_t * p_ctrl, adc_sample_state_t * p_sample) +{ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + fsp_err_t err = FSP_SUCCESS; + + /* Perform parameter checking */ +#if ADC_CFG_PARAM_CHECKING_ENABLE + + /* Verify the pointers are valid */ + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_sample); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); + + /* Verify arguments are legal */ + err = r_adc_sample_state_cfg_check(p_instance_ctrl, p_sample); + if (FSP_SUCCESS != err) + { + return err; + } +#endif + + /* Set the sample state count for the specified register */ + p_instance_ctrl->p_reg->ADSSTR[p_sample->reg_id] = p_sample->num_states; + + /* Return the error code */ + return err; +} + +/*******************************************************************************************************************//** + * Returns the address of the lowest number configured channel and the total number of bytes to be read in order to + * read the results of the configured channels and return the ELC Event name. If no channels are configured, then a + * length of 0 is returned. + * + * @note In group mode, information is returned for group A only. Calculating information for group B is not currently + * supported. + * + * @retval FSP_SUCCESS Information stored in p_adc_info. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_InfoGet (adc_ctrl_t * p_ctrl, adc_info_t * p_adc_info) +{ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + fsp_err_t err = FSP_SUCCESS; + uint32_t adc_mask = 0; + +#if ADC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_adc_info); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); +#endif + + /* Retrieve the scan mask of active channels from the control structure */ + adc_mask = p_instance_ctrl->scan_mask; + + /* If at least one channel is configured, determine the highest and lowest configured channels. */ + if (adc_mask != 0U) + { + int32_t lowest_channel = r_adc_lowest_channel_get(adc_mask); + p_adc_info->p_address = &p_instance_ctrl->p_reg->ADDR[lowest_channel]; + + /* Determine the highest channel that is configured. */ + int32_t highest_channel = 31 - __CLZ(adc_mask); + + /* Determine the size of data that must be read to read all the channels between and including the + * highest and lowest channels.*/ + p_adc_info->length = (uint32_t) ((highest_channel - lowest_channel) + 1); + } + else + { + /* If no channels are configured, set the return length 0. */ + p_adc_info->length = 0U; + } + + p_adc_info->transfer_size = TRANSFER_SIZE_2_BYTE; + +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + + /* Specify the peripheral name in the ELC list */ + p_adc_info->elc_event = + (elc_event_t) ((uint32_t) ELC_EVENT_ADC0_ADI + + (p_instance_ctrl->p_cfg->unit * + ((uint32_t) ELC_EVENT_ADC1_ADI - (uint32_t) ELC_EVENT_ADC0_ADI))); + + p_adc_info->elc_peripheral = (elc_peripheral_t) (ELC_PERIPHERAL_ADC0_A + (2U * p_instance_ctrl->p_cfg->unit)); +#elif 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + + /* Specify the peripheral name in the ELC list */ + p_adc_info->elc_event = + (elc_event_t) ((uint32_t) ELC_EVENT_ADC120_ADI + + (p_instance_ctrl->p_cfg->unit * + ((uint32_t) ELC_EVENT_ADC121_ADI - (uint32_t) ELC_EVENT_ADC120_ADI))); + + p_adc_info->elc_peripheral = (elc_peripheral_t) (ELC_PERIPHERAL_ADC0_A + (2U * p_instance_ctrl->p_cfg->unit)); +#endif + + return err; +} + +/*******************************************************************************************************************//** + * This function ends any scan in progress, disables interrupts, and removes power to the A/D peripheral. + * + * @retval FSP_SUCCESS Module closed. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_Close (adc_ctrl_t * p_ctrl) +{ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + +#if ADC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); +#endif + + /* Mark driver as closed */ + p_instance_ctrl->opened = 0U; + + /* Disable interrupts. */ + adc_extended_cfg_t const * p_extend = (adc_extended_cfg_t const *) p_instance_ctrl->p_cfg->p_extend; + + if (p_instance_ctrl->p_cfg->scan_end_irq >= 0) + { + R_BSP_IrqDisable(p_instance_ctrl->p_cfg->scan_end_irq); + R_FSP_IsrContextSet(p_instance_ctrl->p_cfg->scan_end_irq, NULL); + } + + if (p_instance_ctrl->p_cfg->scan_end_b_irq >= 0) + { + R_BSP_IrqDisable(p_instance_ctrl->p_cfg->scan_end_b_irq); + R_FSP_IsrContextSet(p_instance_ctrl->p_cfg->scan_end_b_irq, NULL); + } + + if (p_instance_ctrl->p_cfg->scan_end_c_irq >= 0) + { + R_BSP_IrqDisable(p_instance_ctrl->p_cfg->scan_end_c_irq); + R_FSP_IsrContextSet(p_instance_ctrl->p_cfg->scan_end_c_irq, NULL); + } + + if (p_extend->window_a_irq >= 0) + { + R_BSP_IrqDisable(p_extend->window_a_irq); + R_FSP_IsrContextSet(p_extend->window_a_irq, NULL); + } + + if (p_extend->window_b_irq >= 0) + { + R_BSP_IrqDisable(p_extend->window_b_irq); + R_FSP_IsrContextSet(p_extend->window_b_irq, NULL); + } + + /* Disable triggers. */ + p_instance_ctrl->p_reg->ADSTRGR = 0U; + p_instance_ctrl->p_reg->ADGCTRGR = 0U; + + /* Stop the ADC. */ + p_instance_ctrl->p_reg->ADCSR = 0U; + +#if BSP_FEATURE_ADC_HAS_SAMPLE_HOLD_REG + p_instance_ctrl->p_reg->ADSHCR = 0U; +#endif + + R_BSP_RegisterProtectDisable(BSP_REG_PROTECT_LPC_RESET); + R_BSP_MODULE_STOP(FSP_IP_ADC12, p_instance_ctrl->p_cfg->unit); + R_BSP_RegisterProtectEnable(BSP_REG_PROTECT_LPC_RESET); + + /* Return the error code */ + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * @ref adc_api_t::R_ADC_Calibrate is not supported on the ADC. + * + * @retval FSP_ERR_UNSUPPORTED Function not supported in this implementation. + **********************************************************************************************************************/ +fsp_err_t R_ADC_Calibrate (adc_ctrl_t * const p_ctrl, void const * p_extend) +{ + FSP_PARAMETER_NOT_USED(p_ctrl); + FSP_PARAMETER_NOT_USED(p_extend); + + /* Return the unsupported error. */ + return FSP_ERR_UNSUPPORTED; +} + +/*******************************************************************************************************************//** + * @ref adc_api_t::offsetSet is not supported on the ADC. + * + * @retval FSP_ERR_UNSUPPORTED Function not supported in this implementation. + **********************************************************************************************************************/ +fsp_err_t R_ADC_OffsetSet (adc_ctrl_t * const p_ctrl, adc_channel_t const reg_id, int32_t offset) +{ + FSP_PARAMETER_NOT_USED(p_ctrl); + FSP_PARAMETER_NOT_USED(reg_id); + FSP_PARAMETER_NOT_USED(offset); + + /* Return the unsupported error. */ + return FSP_ERR_UNSUPPORTED; +} + +/*******************************************************************************************************************//** + * @} (end addtogroup ADC) + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Private Functions + **********************************************************************************************************************/ + +#if ADC_CFG_PARAM_CHECKING_ENABLE + +/*******************************************************************************************************************//** + * Checks the sample state configuration. + * + * @param[in] p_instance_ctrl Pointer to instance control structure + * @param[in] p_sample Pointer to sample state configuration + * + * @retval FSP_SUCCESS No configuration errors detected + * @retval FSP_ERR_ASSERTION An input argument is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_adc_sample_state_cfg_check (adc_instance_ctrl_t * p_instance_ctrl, adc_sample_state_t * p_sample) +{ + /* Used to prevent compiler warning */ + FSP_PARAMETER_NOT_USED(p_instance_ctrl); + + adc_sample_state_reg_t reg_id = p_sample->reg_id; + + /* Verify the requested channel exists on the MCU. */ + if (reg_id >= ADC_SAMPLE_STATE_REG_CHANNEL_0) + { + uint32_t requested_channel_mask = (1U << (uint32_t) reg_id); + FSP_ASSERT(0 != (requested_channel_mask & g_adc_valid_channels[p_instance_ctrl->p_cfg->unit])); + } + + /* Verify the requested sample states is not less than the minimum. */ + FSP_ASSERT(p_sample->num_states >= ADC_SAMPLE_STATE_COUNT_MIN); + + return FSP_SUCCESS; +} + +#endif + +#if ADC_CFG_PARAM_CHECKING_ENABLE + +/*******************************************************************************************************************//** + * Validates the configuration arguments for illegal combinations or options. + * + * @param[in] p_cfg Pointer to configuration structure + * + * @retval FSP_SUCCESS No configuration errors detected + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_IP_CHANNEL_NOT_PRESENT ADC unit not present on this MCU + * @retval FSP_ERR_INVALID_HW_CONDITION The ADC clock must be at least 1 MHz + **********************************************************************************************************************/ +static fsp_err_t r_adc_open_cfg_check (adc_cfg_t const * const p_cfg) +{ + FSP_ASSERT(NULL != p_cfg); + + /* Verify the unit exists on the MCU. */ + FSP_ERROR_RETURN(((1U << p_cfg->unit) & BSP_FEATURE_ADC_VALID_UNIT_MASK), FSP_ERR_IP_CHANNEL_NOT_PRESENT); + + /* Verify the ADC clock frequency is 25 MHz. (ADCCLK is fixed at 25MHz) */ + uint32_t freq_hz = R_FSP_SystemClockHzGet(BSP_FEATURE_ADC_CLOCK_SOURCE); + FSP_ERROR_RETURN(freq_hz >= ADC_PRV_MIN_ADCLK_HZ, FSP_ERR_INVALID_HW_CONDITION); + + /* Check for valid argument values for addition/averaging. Reference section "A/D-Converted Value + * Addition/Average Count Select Register (ADADC)" in the RZ microprocessor User's Manual for details. */ + adc_extended_cfg_t const * p_cfg_extend = (adc_extended_cfg_t const *) p_cfg->p_extend; + if (ADC_ADD_OFF != p_cfg_extend->add_average_count) + { + #if BSP_FEATURE_ADC_ADDITION_SUPPORTED + + /* 3-time conversion and 16-time conversion in average mode are prohibited. */ + FSP_ASSERT(ADC_ADD_AVERAGE_THREE != p_cfg_extend->add_average_count); + FSP_ASSERT(ADC_ADD_AVERAGE_SIXTEEN != p_cfg_extend->add_average_count); + #else + + /* The ADC16 supports averaging only, it does not support addition. */ + FSP_ASSERT(0U != (ADC_ADADC_AVEE_BIT & p_cfg_extend->add_average_count)); + #endif + } + + /* Only synchronous triggers (ELC) allowed in group scan mode (reference TRSA documentation in section + * A/D conversion in Double Trigger Mode)" in the RZ microprocessor User's Manual for details. */ + if ((ADC_MODE_GROUP_SCAN == p_cfg->mode) || (ADC_DOUBLE_TRIGGER_DISABLED != p_cfg_extend->double_trigger_mode)) + { + FSP_ASSERT(ADC_TRIGGER_SYNC_ELC == p_cfg->trigger); + + if ((ADC_MODE_GROUP_SCAN == p_cfg->mode)) + { + FSP_ASSERT(ADC_TRIGGER_SYNC_ELC == p_cfg_extend->trigger_group_b); + } + } + + return FSP_SUCCESS; +} + +#endif + +#if ADC_CFG_PARAM_CHECKING_ENABLE + +/*******************************************************************************************************************//** + * This function validates the resolution configuration arguments for illegal combinations or options. + * + * @param[in] p_cfg Pointer to configuration structure + * + * @retval FSP_SUCCESS No configuration errors detected + * @retval FSP_ERR_ASSERTION An input argument is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_adc_open_cfg_resolution_check (adc_cfg_t const * const p_cfg) +{ + FSP_ASSERT(ADC_RESOLUTION_12_BIT == p_cfg->resolution); + + return FSP_SUCCESS; +} + +#endif + +#if ADC_CFG_PARAM_CHECKING_ENABLE + +/*******************************************************************************************************************//** + * Checks the sample and hold arguments + * + * @param[in] p_instance_ctrl Pointer to instance control block + * @param[in] p_channel_cfg Pointer to channel configuration + * + * @retval FSP_SUCCESS No configuration errors detected + * @retval FSP_ERR_ASSERTION An input argument is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_adc_scan_cfg_check_sample_hold (adc_instance_ctrl_t * const p_instance_ctrl, + adc_channel_cfg_t const * const p_channel_cfg) +{ + #if !BSP_FEATURE_ADC_HAS_SAMPLE_HOLD_REG + + /* If the MCU does not have sample and hold, verify the sample and hold feature is not used. */ + FSP_ASSERT(0U == p_channel_cfg->sample_hold_mask); + FSP_PARAMETER_NOT_USED(p_instance_ctrl); + #else + if (0U != p_channel_cfg->sample_hold_mask) + { + /* Sample and Hold channels can only be 0, 1, 2(unit 0 only) and must have at least minimum state count specified (reference + * section "A/D Sample and Hold Circuit Control Register (ADSHCR)" in the RZ microprocessor User's Manual for details. */ + #if 1U == BSP_FEATURE_ADC_HAS_SAMPLE_HOLD_UNIT_NUM + FSP_ASSERT(0U == p_instance_ctrl->p_cfg->unit); + #elif 3U == BSP_FEATURE_ADC_HAS_SAMPLE_HOLD_UNIT_NUM + + /* Unit 1, 2 can also be set*/ + FSP_PARAMETER_NOT_USED(p_instance_ctrl); + #endif + FSP_ASSERT(p_channel_cfg->sample_hold_mask <= ADC_SAMPLE_HOLD_CHANNELS); + FSP_ASSERT(p_channel_cfg->sample_hold_states >= ADC_SAMPLE_STATE_HOLD_COUNT_MIN); + } + #endif + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Enforces constraints on Window Compare function usage. Reference section "Compare function constraint" + * in the RZ microprocessor User's Manual for details. + * + * @param[in] p_window_cfg Pointer to window compare configuration + * + * @retval FSP_SUCCESS No configuration errors detected + * @retval FSP_ERR_ASSERTION An input argument is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_adc_scan_cfg_check_window_compare (adc_window_cfg_t const * const p_window_cfg) +{ + if (p_window_cfg) + { + uint32_t compare_cfg = p_window_cfg->compare_cfg; + if (0U != compare_cfg) + { + #if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + if ((compare_cfg & R_ADC121_ADCMPCR_CMPAE_Msk) && (compare_cfg & R_ADC121_ADCMPCR_CMPBE_Msk)) + #elif 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + if ((compare_cfg & R_ADC120_ADCMPCR_CMPAE_Msk) && (compare_cfg & R_ADC120_ADCMPCR_CMPBE_Msk)) + #endif + { + /* Ensure channels selected for Window A do not conflict with Window B */ + uint32_t compare_b_ch = p_window_cfg->compare_b_channel; + FSP_ASSERT(!(p_window_cfg->compare_mask & (uint32_t) (1 << compare_b_ch))); + } + + #if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + if (compare_cfg & R_ADC121_ADCMPCR_WCMPE_Msk) + #elif 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + if (compare_cfg & R_ADC120_ADCMPCR_WCMPE_Msk) + #endif + { + /* Ensure lower reference values are less than or equal to the high reference values */ + FSP_ASSERT((p_window_cfg->compare_ref_low <= p_window_cfg->compare_ref_high) && + (p_window_cfg->compare_b_ref_low <= p_window_cfg->compare_b_ref_high)); + } + } + } + + return FSP_SUCCESS; +} + +#endif + +/*******************************************************************************************************************//** + * The Open function applies power to the A/D peripheral, sets the operational mode, trigger sources, and + * configurations common to all channels and sensors. + * + * @param[in] p_instance_ctrl Pointer to instance control block + * @param[in] p_cfg Pointer to configuration structure + * + * @retval FSP_SUCCESS No configuration errors detected + * @retval FSP_ERR_INVALID_HW_CONDITION ADCCALCTL.CAL_ERR bit must be 0 + **********************************************************************************************************************/ +static fsp_err_t r_adc_open_sub (adc_instance_ctrl_t * const p_instance_ctrl, adc_cfg_t const * const p_cfg) +{ + adc_extended_cfg_t const * p_cfg_extend = (adc_extended_cfg_t const *) p_cfg->p_extend; + + /* Determine the value for ADCSR: + * * The configured mode is set in ADCSR.ADCS. + * * ADCSR.GBADIE is always set by this driver. It will only trigger an interrupt in group mode if the group B + * interrupt is enabled. + * * If double-trigger mode is selected ADCSR.DBLANS is set to the chosen double-trigger scan channel and + * ADCSR.DBLE is set to 1; otherwise, both are set to 0. + * * The configured trigger mode is set in ADCSR.EXTRG and ADCSR.TRGE. + * * The value to set in ADCSR to start a scan is stored in the control structure. ADCSR.ADST is set in + * R_ADC_ScanStart if software trigger mode is used. + */ +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + uint32_t adcsr = (uint32_t) (p_cfg->mode << R_ADC121_ADCSR_ADCS_Pos); + adcsr |= (uint32_t) (R_ADC121_ADCSR_GBADIE_Msk); + adcsr |= (uint32_t) (R_ADC121_ADCSR_ADIE_Msk); + adcsr |= ((uint32_t) p_cfg->trigger << R_ADC121_ADCSR_EXTRG_Pos); +#elif 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + uint32_t adcsr = (uint32_t) (p_cfg->mode << R_ADC120_ADCSR_ADCS_Pos); + adcsr |= (uint32_t) (R_ADC120_ADCSR_GBADIE_Msk); + adcsr |= (uint32_t) (R_ADC120_ADCSR_ADIE_Msk); + adcsr |= ((uint32_t) p_cfg->trigger << R_ADC120_ADCSR_EXTRG_Pos); +#endif + if (ADC_DOUBLE_TRIGGER_DISABLED != p_cfg_extend->double_trigger_mode) + { +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + adcsr |= R_ADC121_ADCSR_TRGE_Msk | R_ADC121_ADCSR_DBLE_Msk; +#elif 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + adcsr |= R_ADC120_ADCSR_TRGE_Msk | R_ADC120_ADCSR_DBLE_Msk; +#endif + } + else if (ADC_TRIGGER_SOFTWARE == p_cfg->trigger) + { +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + adcsr |= R_ADC121_ADCSR_ADST_Msk; +#elif 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + adcsr |= R_ADC120_ADCSR_ADST_Msk; +#endif + } + else + { + /* Do nothing. */ + } + + p_instance_ctrl->scan_start_adcsr = (uint16_t) adcsr; + + /* Determine the value for ADCER: + * * The resolution is set as configured in ADCER.ADPRC (on MCUs that have this bitfield). + * * The alignment is set as configured in ADCER.ADFMT (on MCUs that have this bitfield). + * * The clearing option is set as configured in ADCER.ACE. + * * Always select data range of 0 - 32767 in ADCER.INV (on MCUs that have this bitfield). + * * Always disable self-diagnosis (unsupported in this module). + */ + uint32_t adcer = 0U; +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + #if BSP_FEATURE_ADC_HAS_ADCER_ADPRC + adcer |= (uint32_t) p_cfg->resolution << R_ADC121_ADCER_ADPRC_Pos; + #endif + #if BSP_FEATURE_ADC_HAS_ADCER_ADRFMT + adcer |= (uint32_t) p_cfg->alignment << R_ADC121_ADCER_ADRFMT_Pos; + #endif + adcer |= (uint32_t) p_cfg_extend->clearing << R_ADC121_ADCER_ACE_Pos; +#elif 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + #if BSP_FEATURE_ADC_HAS_ADCER_ADPRC + adcer |= (uint32_t) p_cfg->resolution << R_ADC120_ADCER_ADPRC_Pos; + #endif + #if BSP_FEATURE_ADC_HAS_ADCER_ADRFMT + adcer |= (uint32_t) p_cfg->alignment << R_ADC120_ADCER_ADRFMT_Pos; + #endif + adcer |= (uint32_t) p_cfg_extend->clearing << R_ADC120_ADCER_ACE_Pos; +#endif + + /* Determine the value for ADADC: + * * The addition/averaging modes are set as configured in ADADC.ADC and ADADC.AVEE. + * * On MCUs that do not have the ADADC.AVEE bit (addition not supported), the ADADC.AVEE bit is cleared. + */ + uint32_t adadc = p_cfg_extend->add_average_count; +#if !BSP_FEATURE_ADC_ADDITION_SUPPORTED + adadc &= ~ADC_ADADC_AVEE_BIT; +#endif + + /* Apply clock to peripheral. */ + R_BSP_RegisterProtectDisable(BSP_REG_PROTECT_LPC_RESET); + R_BSP_MODULE_START(FSP_IP_ADC12, p_cfg->unit); + R_BSP_RegisterProtectEnable(BSP_REG_PROTECT_LPC_RESET); + +#if BSP_FEATURE_ADC_CALIBRATION_REG_AVAILABLE + + /* Enable calibrate. */ + R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_MICROSECONDS); + + /* Write ADCALCTL.CAL bit to 1 to start calibration. */ + p_instance_ctrl->p_reg->ADCALCTL_b.CAL = ADC_ADCALCTL_SET_CAL; + + /* Poll ADCALCTL.CAL_RDY bit until it is changed to 1. */ + FSP_HARDWARE_REGISTER_WAIT(p_instance_ctrl->p_reg->ADCALCTL_b.CAL_RDY, 1U); + + /* Confirm ADCALCTL.CAL_ERR bit is 0.*/ + FSP_ERROR_RETURN(p_instance_ctrl->p_reg->ADCALCTL_b.CAL_ERR == 0U, FSP_ERR_INVALID_HW_CONDITION); + + /* Write ADCALCTL.CAL bit to 0 */ + p_instance_ctrl->p_reg->ADCALCTL_b.CAL = 0U; +#endif + + /* Set the predetermined values for ADCSR, ADSTRGR, ADGCTRGR, ADCER, and ADADC without setting ADCSR.ADST or ADCSR.TRGE. + * ADCSR.ADST or ADCSR.TRGE are set as configured in R_ADC_ScanStart. */ + p_instance_ctrl->p_reg->ADCSR = (uint16_t) (adcsr & ADC_PRV_ADCSR_CLEAR_ADST_TRGE); +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + p_instance_ctrl->p_reg->ADSTRGR = (uint16_t) ((p_cfg_extend->adc_start_trigger_a << R_ADC121_ADSTRGR_TRSA_Pos) | + (p_cfg_extend->adc_start_trigger_b << R_ADC121_ADSTRGR_TRSB_Pos)); +#elif 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + p_instance_ctrl->p_reg->ADSTRGR = (uint16_t) ((p_cfg_extend->adc_start_trigger_a << R_ADC120_ADSTRGR_TRSA_Pos) | + (p_cfg_extend->adc_start_trigger_b << R_ADC120_ADSTRGR_TRSB_Pos)); +#endif + p_instance_ctrl->p_reg->ADCER = (uint16_t) adcer; + p_instance_ctrl->p_reg->ADADC = (uint8_t) adadc; + p_instance_ctrl->p_reg->ADELCCR = (uint8_t) p_cfg_extend->adc_elc_ctrl; + + if (true == p_cfg_extend->adc_start_trigger_c_enabled) + { +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + p_instance_ctrl->p_reg->ADGCTRGR = + (uint8_t) ((p_cfg_extend->adc_start_trigger_c << R_ADC121_ADGCTRGR_TRSC_Pos) | + (uint8_t) (R_ADC121_ADGCTRGR_GCADIE_Msk | + R_ADC121_ADGCTRGR_GRCE_Msk)); +#elif 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + p_instance_ctrl->p_reg->ADGCTRGR = + (uint8_t) ((p_cfg_extend->adc_start_trigger_c << R_ADC120_ADGCTRGR_TRSC_Pos) | + (uint8_t) (R_ADC120_ADGCTRGR_GCADIE_Msk | + R_ADC120_ADGCTRGR_GRCE_Msk)); +#endif + } + + return FSP_SUCCESS; +} + +#if ADC_CFG_PARAM_CHECKING_ENABLE + +/*******************************************************************************************************************//** + * This function does extensive checking on channel mask settings based upon operational mode. + * + * @param[in] p_instance_ctrl Pointer to instance control block + * @param[in] p_channel_cfg Pointer to channel configuration + * + * @retval FSP_SUCCESS No configuration errors detected + * @retval FSP_ERR_ASSERTION An input argument is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_adc_scan_cfg_check (adc_instance_ctrl_t * const p_instance_ctrl, + adc_channel_cfg_t const * const p_channel_cfg) +{ + fsp_err_t err; + uint16_t unit = p_instance_ctrl->p_cfg->unit; + adc_extended_cfg_t const * p_cfg_extend = (adc_extended_cfg_t const *) p_instance_ctrl->p_cfg->p_extend; + + /* Verify at least one channel is selected for normal / group A. */ + uint32_t valid_channels = g_adc_valid_channels[unit]; + FSP_ASSERT((0U != p_channel_cfg->scan_mask) && (0U == (p_channel_cfg->scan_mask & (~valid_channels)))); + + if (ADC_MODE_GROUP_SCAN == p_instance_ctrl->p_cfg->mode) + { + /* Verify at least one channel is selected for group B. */ + FSP_ASSERT((0U != p_channel_cfg->scan_mask_group_b) && + (0U == (p_channel_cfg->scan_mask_group_b & (~valid_channels)))); + + /* Cannot have the same channel in both groups. */ + FSP_ASSERT(0 == (p_channel_cfg->scan_mask & p_channel_cfg->scan_mask_group_b)); + + if (true == p_cfg_extend->adc_start_trigger_c_enabled) + { + /* Verify at least one channel is selected for group C. */ + FSP_ASSERT((0U != p_channel_cfg->scan_mask_group_c) && + (0U == (p_channel_cfg->scan_mask_group_c & (~valid_channels)))); + + /* Cannot have the same channel in both groups. */ + FSP_ASSERT(0 == (p_channel_cfg->scan_mask & p_channel_cfg->scan_mask_group_c)); + } + } + else + { + /* If group mode is not enabled, no channels can be selected for group B. */ + FSP_ASSERT(ADC_MASK_OFF == p_channel_cfg->scan_mask_group_b); + + /* If group mode is not enabled, no channels can be selected for group C. */ + FSP_ASSERT(ADC_MASK_OFF == p_channel_cfg->scan_mask_group_c); + } + + /* Verify that if addition is enabled, then at least one channel is selected. */ + if (ADC_ADD_OFF != p_cfg_extend->add_average_count) + { + /* Addition mask should not include bits from inactive channels. + * This also serves as a check for valid channels in the addition mask */ + uint32_t tmp_mask = p_channel_cfg->scan_mask_group_b | p_channel_cfg->scan_mask; + FSP_ASSERT((0U == (p_channel_cfg->add_mask & ~tmp_mask)) && (0U != p_channel_cfg->add_mask)); + } + else + { + /* Channels cannot be selected for addition if addition is not used. */ + FSP_ASSERT(ADC_MASK_OFF == p_channel_cfg->add_mask); + } + + /* Check sample and hold settings. */ + err = r_adc_scan_cfg_check_sample_hold(p_instance_ctrl, p_channel_cfg); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + /* Check window compare settings. */ + err = r_adc_scan_cfg_check_window_compare(p_channel_cfg->p_window_cfg); + + return err; +} + +#endif + +/*******************************************************************************************************************//** + * This function does extensive checking on channel mask settings based upon operational mode. Mask registers are + * initialized and interrupts enabled in peripheral. Interrupts are also enabled in ICU if corresponding priority + * is not 0. + * + * @param[in] p_instance_ctrl Pointer to instance control block + * @param[in] p_channel_cfg Pointer to channel configuration + **********************************************************************************************************************/ +static void r_adc_scan_cfg (adc_instance_ctrl_t * const p_instance_ctrl, adc_channel_cfg_t const * const p_channel_cfg) +{ + adc_extended_cfg_t const * p_cfg_extend = (adc_extended_cfg_t const *) p_instance_ctrl->p_cfg->p_extend; + + p_instance_ctrl->p_reg->ADANSA0 = (uint16_t) (p_channel_cfg->scan_mask); + p_instance_ctrl->p_reg->ADANSB0 = (uint16_t) (p_channel_cfg->scan_mask_group_b); + p_instance_ctrl->p_reg->ADANSC0 = (uint16_t) (p_channel_cfg->scan_mask_group_c); + p_instance_ctrl->p_reg->ADADS0 = (uint16_t) (p_channel_cfg->add_mask); + +#if BSP_FEATURE_ADC_HAS_SAMPLE_HOLD_REG + + /* Configure sample and hold. */ + uint32_t adshcr = p_channel_cfg->sample_hold_states; + adshcr |= (p_channel_cfg->sample_hold_mask & ADC_MASK_SAMPLE_HOLD_BYPASS_CHANNELS) << + ADC_MASK_SAMPLE_HOLD_BYPASS_SHIFT; + p_instance_ctrl->p_reg->ADSHCR = (uint16_t) adshcr; +#endif + + /* Save window compare config*/ + adc_window_cfg_t * p_window_cfg = p_channel_cfg->p_window_cfg; + + uint16_t adcmpcr = 0; + + if (p_window_cfg) + { + /* Save window compare config */ + adcmpcr = (uint16_t) p_window_cfg->compare_cfg; +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + if (p_window_cfg->compare_cfg & R_ADC121_ADCMPCR_CMPAE_Msk) +#elif 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + if (p_window_cfg->compare_cfg & R_ADC120_ADCMPCR_CMPAE_Msk) +#endif + { + /* Set Window A boundary values */ + p_instance_ctrl->p_reg->ADCMPCR = p_window_cfg->compare_cfg & UINT16_MAX; + p_instance_ctrl->p_reg->ADCMPDR0 = p_window_cfg->compare_ref_low; + p_instance_ctrl->p_reg->ADCMPDR1 = p_window_cfg->compare_ref_high; + + /* Set Window A channel mask */ + p_instance_ctrl->p_reg->ADCMPANSR0 = p_window_cfg->compare_mask & UINT16_MAX; + + /* Set Window A channel inequality mode mask */ + p_instance_ctrl->p_reg->ADCMPLR0 = p_window_cfg->compare_mode_mask & UINT16_MAX; + } + +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + if (p_window_cfg->compare_cfg & R_ADC121_ADCMPCR_CMPBE_Msk) +#elif 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + if (p_window_cfg->compare_cfg & R_ADC120_ADCMPCR_CMPBE_Msk) +#endif + { + /* Set Window B channel and mode */ + p_instance_ctrl->p_reg->ADCMPBNSR = (uint8_t) ((adc_window_b_mode_t) p_window_cfg->compare_b_channel | + p_window_cfg->compare_b_mode); + + /* Set Window B boundary values */ + p_instance_ctrl->p_reg->ADWINLLB = p_window_cfg->compare_b_ref_low; + p_instance_ctrl->p_reg->ADWINULB = p_window_cfg->compare_b_ref_high; + } + } + + /* Set window compare config */ + p_instance_ctrl->p_reg->ADCMPCR = adcmpcr; + + /* Set group A priority action (not interrupt priority!) + * This will also start the Group B scans if configured for ADC_GROUP_A_GROUP_B_CONTINUOUS_SCAN. + */ + p_instance_ctrl->p_reg->ADGSPCR = (uint16_t) p_channel_cfg->priority_group_a; + + /* In double-trigger mode set the channel select bits to the highest selected channel number then return. */ + if (ADC_DOUBLE_TRIGGER_DISABLED != p_cfg_extend->double_trigger_mode) + { + uintptr_t adcsr = p_instance_ctrl->p_reg->ADCSR; +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + adcsr = (adcsr & ~R_ADC121_ADCSR_DBLANS_Msk) + (31U - __CLZ(p_channel_cfg->scan_mask)); +#elif 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + adcsr = (adcsr & ~R_ADC120_ADCSR_DBLANS_Msk) + (31U - __CLZ(p_channel_cfg->scan_mask)); +#endif + + p_instance_ctrl->p_reg->ADCSR = (uint16_t) adcsr; + p_instance_ctrl->scan_start_adcsr |= (uint16_t) adcsr; + } +} + +/*******************************************************************************************************************//** + * Returns the lowest channel index that is configured in order to read the results of the configured channels. + * + * @param[in] adc_mask scan mask of active channels retrieved from the control structure + * + * @retval adc_mask_count index value of lowest channel + **********************************************************************************************************************/ +static int32_t r_adc_lowest_channel_get (uint32_t adc_mask) +{ + /* Initialize the mask result */ + uint32_t adc_mask_result = 0U; + int32_t adc_mask_count = -1; + while (0U == adc_mask_result) + { + /* Increment channel until a channel is found in the mask. */ + adc_mask_count++; + adc_mask_result = (uint32_t) (adc_mask & (1U << adc_mask_count)); + } + + return adc_mask_count; +} + +/*******************************************************************************************************************//** + * Clears interrupt flag and calls a callback to notify application of the event. + * + * @param[in] event Event that triggered the ISR + **********************************************************************************************************************/ +static void r_adc_scan_end_common_isr (adc_event_t event) +{ + ADC_CFG_MULTIPLEX_INTERRUPT_ENABLE; + + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE; + + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) R_FSP_IsrContextGet(R_FSP_CurrentIrqGet()); + adc_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. */ + adc_callback_args_t * p_args = p_instance_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; + + /* Store the unit number into the callback argument */ + p_args->unit = p_instance_ctrl->p_cfg->unit; + + /* Initialize the channel to 0. It is not used in this implementation. */ + p_args->channel = ADC_CHANNEL_0; + + /* Populate the context field. */ + p_args->p_context = p_instance_ctrl->p_context; + + /* If a callback was provided, call it with the argument */ + if (NULL != p_instance_ctrl->p_callback) + { + /* If the project is not Trustzone Secure, then it will never need to change security state in order to call the callback. */ + p_instance_ctrl->p_callback(p_args); + } + + if (NULL != p_instance_ctrl->p_callback_memory) + { + /* Restore callback memory in case this is a nested interrupt. */ + *p_instance_ctrl->p_callback_memory = args; + } + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE; + + ADC_CFG_MULTIPLEX_INTERRUPT_DISABLE; +} + +/*******************************************************************************************************************//** + * This function implements the unit 0 interrupt handler for normal/Group A/double trigger scan complete. + **********************************************************************************************************************/ +void adc_scan_end_isr (void) +{ + r_adc_scan_end_common_isr(ADC_EVENT_SCAN_COMPLETE); +} + +/*******************************************************************************************************************//** + * This function implements the interrupt handler for Group B scan complete. + **********************************************************************************************************************/ +void adc_scan_end_b_isr (void) +{ + r_adc_scan_end_common_isr(ADC_EVENT_SCAN_COMPLETE_GROUP_B); +} + +/*******************************************************************************************************************//** + * This function implements the interrupt handler for Group C scan complete. + **********************************************************************************************************************/ +void adc_scan_end_c_isr (void) +{ + r_adc_scan_end_common_isr(ADC_EVENT_SCAN_COMPLETE_GROUP_C); +} + +/*******************************************************************************************************************//** + * This function implements the interrupt handler for window compare events. + **********************************************************************************************************************/ +void adc_window_compare_isr (void) +{ + ADC_CFG_MULTIPLEX_INTERRUPT_ENABLE; + + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE; + + IRQn_Type irq = R_FSP_CurrentIrqGet(); + + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) R_FSP_IsrContextGet(irq); + adc_extended_cfg_t * p_extend = (adc_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + adc_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. */ + adc_callback_args_t * p_args = p_instance_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 = (irq == p_extend->window_a_irq) ? ADC_EVENT_WINDOW_COMPARE_A : ADC_EVENT_WINDOW_COMPARE_B; + + /* Store the unit number into the callback argument */ + p_args->unit = p_instance_ctrl->p_cfg->unit; + + if (ADC_EVENT_WINDOW_COMPARE_A == p_args->event) + { +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + R_ADC121_Type * p_reg = p_instance_ctrl->p_reg; +#elif 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + R_ADC122_Type * p_reg = p_instance_ctrl->p_reg; +#endif + + /* Get all Window A status registers */ + uint16_t adcmpsr0 = p_reg->ADCMPSR0; + + /* Get the lowest channel that meets Window A criteria */ + uint16_t lowest_channel = (uint16_t) __CLZ(__RBIT(adcmpsr0)); + + /* Get channel selected for Window A */ + p_args->channel = (adc_channel_t) lowest_channel; + + /* Clear the status flag corresponding to the lowest channel of window A */ + p_reg->ADCMPSR0 = (uint16_t) (adcmpsr0 & ~(1 << (lowest_channel & 0xF))); + } + else + { + /* Get channel selected for Window B */ + p_args->channel = (adc_channel_t) p_instance_ctrl->p_reg->ADCMPBNSR_b.CMPCHB; + + /* Clear window B flag */ + p_instance_ctrl->p_reg->ADCMPBSR_b.CMPSTB = 0; + } + + /* Populate the context field. */ + p_args->p_context = p_instance_ctrl->p_context; + + /* If a callback was provided, call it with the argument */ + if (NULL != p_instance_ctrl->p_callback) + { + /* If the project is not Trustzone Secure, then it will never need to change security state in order to call the callback. */ + p_instance_ctrl->p_callback(p_args); + } + + if (NULL != p_instance_ctrl->p_callback_memory) + { + /* Restore callback memory in case this is a nested interrupt. */ + *p_instance_ctrl->p_callback_memory = args; + } + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE; + ADC_CFG_MULTIPLEX_INTERRUPT_DISABLE; +} diff --git a/drivers/rz/fsp/src/rzt/r_adc/r_adc.c b/drivers/rz/fsp/src/rzt/r_adc/r_adc.c new file mode 100644 index 00000000..1c4e805a --- /dev/null +++ b/drivers/rz/fsp/src/rzt/r_adc/r_adc.c @@ -0,0 +1,1379 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*********************************************************************************************************************** + * Includes , "Project Includes" + **********************************************************************************************************************/ + +#include "bsp_api.h" + +/* Configuration for this package. */ +#include "r_adc_cfg.h" + +/* Private header file for this package. */ +#include "r_adc.h" + +/********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +#define ADC_PRV_USEC_PER_SEC (1000000U) +#define ADC_PRV_MIN_ADCLK_HZ (18750000U) + +#define ADC_PRV_HZ_PER_KHZ (1000U) + +#define ADC_SHIFT_LEFT_ALIGNED_32_BIT (16U) + +#define ADC_OPEN (0x52414443U) + +#define ADC_ADADC_AVEE_BIT (0x80U) + +/* Sample and hold bypass applies to these channels. */ +#define ADC_MASK_SAMPLE_HOLD_BYPASS_CHANNELS (0x7U) + +/* Sample and hold bypass starts at bit 8. */ +#define ADC_MASK_SAMPLE_HOLD_BYPASS_SHIFT (8U) + +/* Stabilization time when BGR is enabled */ +#define ADC_BGR_STABILIZATION_DELAY_US (150U) + +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + #define ADC_PRV_ADCSR_ADST_TRGE_MASK (R_ADC121_ADCSR_ADST_Msk | R_ADC121_ADCSR_TRGE_Msk) +#elif 2U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE || 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + #define ADC_PRV_ADCSR_ADST_TRGE_MASK (R_ADC120_ADCSR_ADST_Msk | R_ADC120_ADCSR_TRGE_Msk) +#endif +#define ADC_PRV_ADCSR_CLEAR_ADST_TRGE (~ADC_PRV_ADCSR_ADST_TRGE_MASK) + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Private global variables and functions + **********************************************************************************************************************/ +#if ADC_CFG_PARAM_CHECKING_ENABLE +static fsp_err_t r_adc_open_cfg_check(adc_cfg_t const * const p_cfg); +static fsp_err_t r_adc_open_cfg_resolution_check(adc_cfg_t const * const p_cfg); +static fsp_err_t r_adc_sample_state_cfg_check(adc_instance_ctrl_t * p_instance_ctrl, adc_sample_state_t * p_sample); + +static fsp_err_t r_adc_scan_cfg_check_sample_hold(adc_instance_ctrl_t * const p_instance_ctrl, + adc_channel_cfg_t const * const p_channel_cfg); +static fsp_err_t r_adc_scan_cfg_check_window_compare(adc_window_cfg_t const * const p_window_cfg); + +#endif + +static void r_adc_open_sub(adc_instance_ctrl_t * const p_instance_ctrl, adc_cfg_t const * const p_cfg); + +#if ADC_CFG_PARAM_CHECKING_ENABLE + +static fsp_err_t r_adc_scan_cfg_check(adc_instance_ctrl_t * const p_instance_ctrl, + adc_channel_cfg_t const * const p_channel_cfg); + +#endif + +static void r_adc_scan_cfg(adc_instance_ctrl_t * const p_instance_ctrl, adc_channel_cfg_t const * const p_channel_cfg); +void adc_scan_end_b_isr(void); +void adc_scan_end_c_isr(void); +void adc_scan_end_isr(void); +void adc_window_compare_isr(void); + +static int32_t r_adc_lowest_channel_get(uint32_t adc_mask); +static void r_adc_scan_end_common_isr(adc_event_t event); + +#if ADC_CFG_PARAM_CHECKING_ENABLE + +/** Mask of valid channels on this MCU. */ +static const uint32_t g_adc_valid_channels[] = +{ + BSP_FEATURE_ADC_UNIT_0_CHANNELS, + #if BSP_FEATURE_ADC_UNIT_1_CHANNELS + BSP_FEATURE_ADC_UNIT_1_CHANNELS, + #endif + #if BSP_FEATURE_ADC_UNIT_2_CHANNELS + BSP_FEATURE_ADC_UNIT_2_CHANNELS + #endif +}; +#endif + +/*********************************************************************************************************************** + * Global Variables + **********************************************************************************************************************/ + +/** ADC Implementation of ADC. */ +const adc_api_t g_adc_on_adc = +{ + .open = R_ADC_Open, + .scanCfg = R_ADC_ScanCfg, + .infoGet = R_ADC_InfoGet, + .scanStart = R_ADC_ScanStart, + .scanGroupStart = R_ADC_ScanGroupStart, + .scanStop = R_ADC_ScanStop, + .scanStatusGet = R_ADC_StatusGet, + .read = R_ADC_Read, + .read32 = R_ADC_Read32, + .close = R_ADC_Close, + .calibrate = R_ADC_Calibrate, + .offsetSet = R_ADC_OffsetSet, + .callbackSet = R_ADC_CallbackSet, +}; + +/*******************************************************************************************************************//** + * @addtogroup ADC + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Sets the operational mode, trigger sources, interrupt priority, and configurations for the peripheral as a whole. + * If interrupt is enabled, the function registers a callback function pointer for notifying the user whenever a scan + * has completed. + * + * @retval FSP_SUCCESS Module is ready for use. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_ALREADY_OPEN The instance control structure has already been opened. + * @retval FSP_ERR_IRQ_BSP_DISABLED A callback is provided, but the interrupt is not enabled. + * @retval FSP_ERR_IP_CHANNEL_NOT_PRESENT The requested unit does not exist on this MCU. + * @retval FSP_ERR_INVALID_HW_CONDITION The ADC clock must be at least 1 MHz + **********************************************************************************************************************/ +fsp_err_t R_ADC_Open (adc_ctrl_t * p_ctrl, adc_cfg_t const * const p_cfg) +{ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + + /* Perform parameter checking */ +#if ADC_CFG_PARAM_CHECKING_ENABLE + + /* Verify the pointers are valid */ + FSP_ASSERT(NULL != p_instance_ctrl); + + /* Verify the configuration parameters are valid */ + fsp_err_t err = r_adc_open_cfg_check(p_cfg); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + /* Check for valid argument values for options that are unique to the IP */ + err = r_adc_open_cfg_resolution_check(p_cfg); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + /* Verify this unit has not already been initialized */ + FSP_ERROR_RETURN(ADC_OPEN != p_instance_ctrl->opened, FSP_ERR_ALREADY_OPEN); + + /* If a callback is used, then make sure an interrupt is enabled */ + adc_extended_cfg_t const * p_extend = (adc_extended_cfg_t const *) p_cfg->p_extend; + if (NULL != p_cfg->p_callback) + { + FSP_ERROR_RETURN((p_cfg->scan_end_irq >= 0) || (p_extend->window_a_irq >= 0) || (p_extend->window_b_irq >= 0), + FSP_ERR_IRQ_BSP_DISABLED); + + /* Group B interrupts are never required since group B can be configured in continuous scan mode when group A + * has priority over group B. */ + } + +#else + adc_extended_cfg_t const * p_extend = (adc_extended_cfg_t const *) p_cfg->p_extend; +#endif + + /* Save configurations. */ + p_instance_ctrl->p_cfg = p_cfg; + p_instance_ctrl->p_callback = p_cfg->p_callback; + p_instance_ctrl->p_context = p_cfg->p_context; + p_instance_ctrl->p_callback_memory = NULL; + + /* Calculate the register base address. */ + uintptr_t base_address = (uintptr_t) R_ADC120; + if (0U == p_cfg->unit) + { + base_address = (uintptr_t) R_ADC120; + } + else if (1U == p_cfg->unit) + { + base_address = (uintptr_t) R_ADC121; + } + else + { +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE || 2U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + + /* Do Nothing */ +#elif 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + base_address = (uintptr_t) R_ADC122; +#endif + } + +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + p_instance_ctrl->p_reg = (R_ADC121_Type *) base_address; +#elif 2U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + p_instance_ctrl->p_reg = (R_ADC120_Type *) base_address; +#elif 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + p_instance_ctrl->p_reg = (R_ADC122_Type *) base_address; +#endif + + /* Initialize the hardware based on the configuration. */ + r_adc_open_sub(p_instance_ctrl, p_cfg); + + /* Set the interrupt priorities. */ + if (p_instance_ctrl->p_cfg->scan_end_irq >= 0) + { + R_BSP_IrqCfgEnable(p_instance_ctrl->p_cfg->scan_end_irq, p_cfg->scan_end_ipl, p_instance_ctrl); + } + + if (p_instance_ctrl->p_cfg->scan_end_b_irq >= 0) + { + R_BSP_IrqCfgEnable(p_instance_ctrl->p_cfg->scan_end_b_irq, p_cfg->scan_end_b_ipl, p_instance_ctrl); + } + + if (p_instance_ctrl->p_cfg->scan_end_c_irq >= 0) + { + R_BSP_IrqCfgEnable(p_instance_ctrl->p_cfg->scan_end_c_irq, p_cfg->scan_end_c_ipl, p_instance_ctrl); + } + + if (p_extend->window_a_irq >= 0) + { + R_BSP_IrqCfgEnable(p_extend->window_a_irq, p_extend->window_a_ipl, p_instance_ctrl); + } + + if (p_extend->window_b_irq >= 0) + { + R_BSP_IrqCfgEnable(p_extend->window_b_irq, p_extend->window_b_ipl, p_instance_ctrl); + } + + /* Invalid scan mask (initialized for later). */ + p_instance_ctrl->scan_mask = 0U; + + /* Mark driver as opened by initializing it to "RADC" in its ASCII equivalent for this unit. */ + p_instance_ctrl->opened = ADC_OPEN; + + /* Return the error code */ + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Configures the ADC scan parameters. Channel specific settings are set in this function. Pass a pointer to + * @ref adc_channel_cfg_t to p_channel_cfg. + * + * @note This starts group B scans if adc_channel_cfg_t::priority_group_a is set to ADC_GROUP_A_GROUP_B_CONTINUOUS_SCAN. + * + * @retval FSP_SUCCESS Channel specific settings applied. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_ScanCfg (adc_ctrl_t * p_ctrl, void const * const p_channel_cfg) +{ + adc_channel_cfg_t const * p_adc_channel_cfg = (adc_channel_cfg_t const *) p_channel_cfg; + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + fsp_err_t err = FSP_SUCCESS; + +#if ADC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_adc_channel_cfg); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); + + err = r_adc_scan_cfg_check(p_instance_ctrl, p_adc_channel_cfg); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); +#endif + + /* Configure the hardware based on the configuration */ + r_adc_scan_cfg(p_instance_ctrl, p_adc_channel_cfg); + + /* Save the scan mask locally; this is required for the infoGet function. */ + p_instance_ctrl->scan_mask = p_adc_channel_cfg->scan_mask; + + /* Return the error code */ + return err; +} + +/*******************************************************************************************************************//** + * Updates the user callback and has option of providing memory for callback structure. + * Implements adc_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_ADC_CallbackSet (adc_ctrl_t * const p_ctrl, + void ( * p_callback)(adc_callback_args_t *), + void const * const p_context, + adc_callback_args_t * const p_callback_memory) +{ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + +#if (ADC_CFG_PARAM_CHECKING_ENABLE) + FSP_ASSERT(p_instance_ctrl); + FSP_ASSERT(p_callback); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); +#endif + + /* Store callback and context */ + p_instance_ctrl->p_callback = p_callback; + p_instance_ctrl->p_context = p_context; + p_instance_ctrl->p_callback_memory = p_callback_memory; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Starts a software scan or enables the hardware trigger for a scan depending on how the triggers were configured in + * the R_ADC_Open call. If the unit was configured for ELC or external hardware triggering, then this function allows + * the trigger signal to get to the ADC unit. The function is not able to control the generation of the trigger itself. + * If the unit was configured for software triggering, then this function starts the software triggered scan. + * + * @pre Call R_ADC_ScanCfg after R_ADC_Open before starting a scan. + * + * @retval FSP_SUCCESS Scan started (software trigger) or hardware triggers enabled. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + * @retval FSP_ERR_IN_USE Another scan is still in progress (software trigger). + **********************************************************************************************************************/ +fsp_err_t R_ADC_ScanStart (adc_ctrl_t * p_ctrl) +{ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + + /* Perform parameter checking */ +#if ADC_CFG_PARAM_CHECKING_ENABLE + + /* Verify the pointers are valid */ + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); + if (ADC_GROUP_A_GROUP_B_CONTINUOUS_SCAN != p_instance_ctrl->p_reg->ADGSPCR) + { + FSP_ERROR_RETURN(0U == p_instance_ctrl->p_reg->ADCSR_b.ADST, FSP_ERR_IN_USE); + } +#endif + + /* Enable hardware trigger or start software scan depending on mode. */ + p_instance_ctrl->p_reg->ADCSR = p_instance_ctrl->scan_start_adcsr; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * @ref adc_api_t::scanGroupStart is not supported on the ADC. Use scanStart instead. + * + * @retval FSP_ERR_UNSUPPORTED Function not supported in this implementation. + **********************************************************************************************************************/ +fsp_err_t R_ADC_ScanGroupStart (adc_ctrl_t * p_ctrl, adc_group_mask_t group_mask) +{ + FSP_PARAMETER_NOT_USED(p_ctrl); + FSP_PARAMETER_NOT_USED(group_mask); + + /* Return the unsupported error. */ + return FSP_ERR_UNSUPPORTED; +} + +/*******************************************************************************************************************//** + * Stops the software scan or disables the unit from being triggered by the hardware trigger (ELC or external) based on + * what type of trigger the unit was configured for in the R_ADC_Open function. Stopping a hardware triggered scan via + * this function does not abort an ongoing scan, but prevents the next scan from occurring. Stopping a software + * triggered scan aborts an ongoing scan. + * + * @retval FSP_SUCCESS Scan stopped (software trigger) or hardware triggers disabled. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_ScanStop (adc_ctrl_t * p_ctrl) +{ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + + /* Perform parameter checking */ +#if ADC_CFG_PARAM_CHECKING_ENABLE + + /* Verify the pointers are valid */ + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); +#endif + + /* Disable hardware trigger or stop software scan depending on mode. */ + p_instance_ctrl->p_reg->ADCSR = 0U; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Provides the status of any scan process that was started, including scans started by ELC or external triggers. + * + * @retval FSP_SUCCESS Module status stored in the provided pointer p_status + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_StatusGet (adc_ctrl_t * p_ctrl, adc_status_t * p_status) +{ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + +#if ADC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_status); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); +#endif + + /* Read the status of the ADST bit. ADST is set when a scan is in progress. */ + p_status->state = (adc_state_t) p_instance_ctrl->p_reg->ADCSR_b.ADST; + + /* Return the error code */ + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Reads conversion results from a single channel or sensor. + * + * @retval FSP_SUCCESS Data read into provided p_data. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_Read (adc_ctrl_t * p_ctrl, adc_channel_t const reg_id, uint16_t * const p_data) +{ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + + /* Perform parameter checking. */ +#if ADC_CFG_PARAM_CHECKING_ENABLE + + /* Verify the pointers are valid */ + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_data); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); + + /* Verify that the channel is valid for this MCU */ + if ((reg_id >= ADC_CHANNEL_0) && ((uint32_t) reg_id <= 31U)) + { + uint32_t requested_channel_mask = (1U << (uint32_t) reg_id); + FSP_ASSERT(0 != (requested_channel_mask & g_adc_valid_channels[p_instance_ctrl->p_cfg->unit])); + } + else + { + FSP_ASSERT((reg_id == ADC_CHANNEL_DUPLEX) || (reg_id == ADC_CHANNEL_DUPLEX_A) || + (reg_id == ADC_CHANNEL_DUPLEX_B)); + } +#endif + + /* Read the data from the requested ADC conversion register and return it */ + *p_data = p_instance_ctrl->p_reg->ADDR[reg_id]; + + /* Return the error code */ + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Reads conversion results from a single channel or sensor register into a 32-bit result. + * + * @retval FSP_SUCCESS Data read into provided p_data. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_Read32 (adc_ctrl_t * p_ctrl, adc_channel_t const reg_id, uint32_t * const p_data) +{ + uint16_t result = 0U; + uint32_t result_32 = 0U; + +#if ADC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_data); +#endif + + fsp_err_t err = R_ADC_Read(p_ctrl, reg_id, &result); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + result_32 = result; + + /* Left shift the result into the upper 16 bits if the unit is configured for left alignment. */ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + if (ADC_ALIGNMENT_LEFT == p_instance_ctrl->p_cfg->alignment) + { + result_32 <<= ADC_SHIFT_LEFT_ALIGNED_32_BIT; + } + + *p_data = result_32; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Sets the sample state count for individual channels. This only needs to be set for special use cases. Normally, use + * the default values out of reset. + * + * @note The sample states for the temperature and voltage sensor are set in R_ADC_ScanCfg. + * + * @retval FSP_SUCCESS Sample state count updated. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_SampleStateCountSet (adc_ctrl_t * p_ctrl, adc_sample_state_t * p_sample) +{ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + fsp_err_t err = FSP_SUCCESS; + + /* Perform parameter checking */ +#if ADC_CFG_PARAM_CHECKING_ENABLE + + /* Verify the pointers are valid */ + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_sample); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); + + /* Verify arguments are legal */ + err = r_adc_sample_state_cfg_check(p_instance_ctrl, p_sample); + if (FSP_SUCCESS != err) + { + return err; + } +#endif + + /* Set the sample state count for the specified register */ + p_instance_ctrl->p_reg->ADSSTR[p_sample->reg_id] = p_sample->num_states; + + /* Return the error code */ + return err; +} + +/*******************************************************************************************************************//** + * Returns the address of the lowest number configured channel and the total number of bytes to be read in order to + * read the results of the configured channels and return the ELC Event name. If no channels are configured, then a + * length of 0 is returned. + * + * @note In group mode, information is returned for group A only. Calculating information for group B is not currently + * supported. + * + * @retval FSP_SUCCESS Information stored in p_adc_info. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_InfoGet (adc_ctrl_t * p_ctrl, adc_info_t * p_adc_info) +{ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + fsp_err_t err = FSP_SUCCESS; + uint32_t adc_mask = 0; + +#if ADC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_adc_info); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); +#endif + + /* Retrieve the scan mask of active channels from the control structure */ + adc_mask = p_instance_ctrl->scan_mask; + + /* If at least one channel is configured, determine the highest and lowest configured channels. */ + if (adc_mask != 0U) + { + int32_t lowest_channel = r_adc_lowest_channel_get(adc_mask); + p_adc_info->p_address = &p_instance_ctrl->p_reg->ADDR[lowest_channel]; + + /* Determine the highest channel that is configured. */ + int32_t highest_channel = 31 - __CLZ(adc_mask); + + /* Determine the size of data that must be read to read all the channels between and including the + * highest and lowest channels.*/ + p_adc_info->length = (uint32_t) ((highest_channel - lowest_channel) + 1); + } + else + { + /* If no channels are configured, set the return length 0. */ + p_adc_info->length = 0U; + } + + p_adc_info->transfer_size = TRANSFER_SIZE_2_BYTE; + + /* Specify the peripheral name in the ELC list */ +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE || 2U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + p_adc_info->elc_event = + (elc_event_t) ((uint32_t) ELC_EVENT_ADC0_ADI + + (p_instance_ctrl->p_cfg->unit * + ((uint32_t) ELC_EVENT_ADC1_ADI - (uint32_t) ELC_EVENT_ADC0_ADI))); + p_adc_info->elc_peripheral = (elc_peripheral_t) (ELC_PERIPHERAL_ADC0_A + (2U * p_instance_ctrl->p_cfg->unit)); +#elif 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + p_adc_info->elc_event = + (elc_event_t) ((uint32_t) ELC_EVENT_ADC120_ADI + + (p_instance_ctrl->p_cfg->unit * + ((uint32_t) ELC_EVENT_ADC121_ADI - (uint32_t) ELC_EVENT_ADC120_ADI))); + p_adc_info->elc_peripheral = (elc_peripheral_t) (ELC_PERIPHERAL_ADC0_A + (2U * p_instance_ctrl->p_cfg->unit)); +#endif + + return err; +} + +/*******************************************************************************************************************//** + * This function ends any scan in progress, disables interrupts, and removes power to the A/D peripheral. + * + * @retval FSP_SUCCESS Module closed. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_Close (adc_ctrl_t * p_ctrl) +{ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + +#if ADC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); +#endif + + /* Mark driver as closed */ + p_instance_ctrl->opened = 0U; + + /* Disable interrupts. */ + adc_extended_cfg_t const * p_extend = (adc_extended_cfg_t const *) p_instance_ctrl->p_cfg->p_extend; + + if (p_instance_ctrl->p_cfg->scan_end_irq >= 0) + { + R_BSP_IrqDisable(p_instance_ctrl->p_cfg->scan_end_irq); + R_FSP_IsrContextSet(p_instance_ctrl->p_cfg->scan_end_irq, NULL); + } + + if (p_instance_ctrl->p_cfg->scan_end_b_irq >= 0) + { + R_BSP_IrqDisable(p_instance_ctrl->p_cfg->scan_end_b_irq); + R_FSP_IsrContextSet(p_instance_ctrl->p_cfg->scan_end_b_irq, NULL); + } + + if (p_instance_ctrl->p_cfg->scan_end_c_irq >= 0) + { + R_BSP_IrqDisable(p_instance_ctrl->p_cfg->scan_end_c_irq); + R_FSP_IsrContextSet(p_instance_ctrl->p_cfg->scan_end_c_irq, NULL); + } + + if (p_extend->window_a_irq >= 0) + { + R_BSP_IrqDisable(p_extend->window_a_irq); + R_FSP_IsrContextSet(p_extend->window_a_irq, NULL); + } + + if (p_extend->window_b_irq >= 0) + { + R_BSP_IrqDisable(p_extend->window_b_irq); + R_FSP_IsrContextSet(p_extend->window_b_irq, NULL); + } + + /* Disable triggers. */ + p_instance_ctrl->p_reg->ADSTRGR = 0U; + p_instance_ctrl->p_reg->ADGCTRGR = 0U; + + /* Stop the ADC. */ + p_instance_ctrl->p_reg->ADCSR = 0U; + +#if BSP_FEATURE_ADC_HAS_SAMPLE_HOLD_REG + p_instance_ctrl->p_reg->ADSHCR = 0U; +#endif + + R_BSP_RegisterProtectDisable(BSP_REG_PROTECT_LPC_RESET); + R_BSP_MODULE_STOP(FSP_IP_ADC12, p_instance_ctrl->p_cfg->unit); + R_BSP_RegisterProtectEnable(BSP_REG_PROTECT_LPC_RESET); + + /* Return the error code */ + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * @ref adc_api_t::R_ADC_Calibrate is not supported on the ADC. + * + * @retval FSP_ERR_UNSUPPORTED Function not supported in this implementation. + **********************************************************************************************************************/ +fsp_err_t R_ADC_Calibrate (adc_ctrl_t * const p_ctrl, void const * p_extend) +{ + FSP_PARAMETER_NOT_USED(p_ctrl); + FSP_PARAMETER_NOT_USED(p_extend); + + /* Return the unsupported error. */ + return FSP_ERR_UNSUPPORTED; +} + +/*******************************************************************************************************************//** + * @ref adc_api_t::offsetSet is not supported on the ADC. + * + * @retval FSP_ERR_UNSUPPORTED Function not supported in this implementation. + **********************************************************************************************************************/ +fsp_err_t R_ADC_OffsetSet (adc_ctrl_t * const p_ctrl, adc_channel_t const reg_id, int32_t offset) +{ + FSP_PARAMETER_NOT_USED(p_ctrl); + FSP_PARAMETER_NOT_USED(reg_id); + FSP_PARAMETER_NOT_USED(offset); + + /* Return the unsupported error. */ + return FSP_ERR_UNSUPPORTED; +} + +/*******************************************************************************************************************//** + * @} (end addtogroup ADC) + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Private Functions + **********************************************************************************************************************/ + +#if ADC_CFG_PARAM_CHECKING_ENABLE + +/*******************************************************************************************************************//** + * Checks the sample state configuration. + * + * @param[in] p_instance_ctrl Pointer to instance control structure + * @param[in] p_sample Pointer to sample state configuration + * + * @retval FSP_SUCCESS No configuration errors detected + * @retval FSP_ERR_ASSERTION An input argument is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_adc_sample_state_cfg_check (adc_instance_ctrl_t * p_instance_ctrl, adc_sample_state_t * p_sample) +{ + /* Used to prevent compiler warning */ + FSP_PARAMETER_NOT_USED(p_instance_ctrl); + + adc_sample_state_reg_t reg_id = p_sample->reg_id; + + /* Verify the requested channel exists on the MCU. */ + if (reg_id >= ADC_SAMPLE_STATE_REG_CHANNEL_0) + { + uint32_t requested_channel_mask = (1U << (uint32_t) reg_id); + FSP_ASSERT(0 != (requested_channel_mask & g_adc_valid_channels[p_instance_ctrl->p_cfg->unit])); + } + + /* Verify the requested sample states is not less than the minimum. */ + FSP_ASSERT(p_sample->num_states >= ADC_SAMPLE_STATE_COUNT_MIN); + + return FSP_SUCCESS; +} + +#endif + +#if ADC_CFG_PARAM_CHECKING_ENABLE + +/*******************************************************************************************************************//** + * Validates the configuration arguments for illegal combinations or options. + * + * @param[in] p_cfg Pointer to configuration structure + * + * @retval FSP_SUCCESS No configuration errors detected + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_IP_CHANNEL_NOT_PRESENT ADC unit not present on this MCU + * @retval FSP_ERR_INVALID_HW_CONDITION The ADC clock must be at least 1 MHz + **********************************************************************************************************************/ +static fsp_err_t r_adc_open_cfg_check (adc_cfg_t const * const p_cfg) +{ + FSP_ASSERT(NULL != p_cfg); + + /* Verify the unit exists on the MCU. */ + FSP_ERROR_RETURN(((1U << p_cfg->unit) & BSP_FEATURE_ADC_VALID_UNIT_MASK), FSP_ERR_IP_CHANNEL_NOT_PRESENT); + + /* Verify the ADC clock frequency is 25 MHz. (ADCCLK is fixed at 25MHz) */ + uint32_t freq_hz = R_FSP_SystemClockHzGet(BSP_FEATURE_ADC_CLOCK_SOURCE); + FSP_ERROR_RETURN(freq_hz >= ADC_PRV_MIN_ADCLK_HZ, FSP_ERR_INVALID_HW_CONDITION); + + /* Check for valid argument values for addition/averaging. Reference section "A/D-Converted Value + * Addition/Average Count Select Register (ADADC)" in the RZ microprocessor User's Manual for details. */ + adc_extended_cfg_t const * p_cfg_extend = (adc_extended_cfg_t const *) p_cfg->p_extend; + if (ADC_ADD_OFF != p_cfg_extend->add_average_count) + { + #if BSP_FEATURE_ADC_ADDITION_SUPPORTED + + /* 3-time conversion and 16-time conversion in average mode are prohibited. */ + FSP_ASSERT(ADC_ADD_AVERAGE_THREE != p_cfg_extend->add_average_count); + FSP_ASSERT(ADC_ADD_AVERAGE_SIXTEEN != p_cfg_extend->add_average_count); + #else + + /* The ADC16 supports averaging only, it does not support addition. */ + FSP_ASSERT(0U != (ADC_ADADC_AVEE_BIT & p_cfg_extend->add_average_count)); + #endif + } + + /* Only synchronous triggers (ELC) allowed in group scan mode (reference TRSA documentation in section + * A/D conversion in Double Trigger Mode)" in the RZ microprocessor User's Manual for details. */ + if ((ADC_MODE_GROUP_SCAN == p_cfg->mode) || (ADC_DOUBLE_TRIGGER_DISABLED != p_cfg_extend->double_trigger_mode)) + { + FSP_ASSERT(ADC_TRIGGER_SYNC_ELC == p_cfg->trigger); + + if ((ADC_MODE_GROUP_SCAN == p_cfg->mode)) + { + FSP_ASSERT(ADC_TRIGGER_SYNC_ELC == p_cfg_extend->trigger_group_b); + } + } + + return FSP_SUCCESS; +} + +#endif + +#if ADC_CFG_PARAM_CHECKING_ENABLE + +/*******************************************************************************************************************//** + * This function validates the resolution configuration arguments for illegal combinations or options. + * + * @param[in] p_cfg Pointer to configuration structure + * + * @retval FSP_SUCCESS No configuration errors detected + * @retval FSP_ERR_ASSERTION An input argument is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_adc_open_cfg_resolution_check (adc_cfg_t const * const p_cfg) +{ + FSP_ASSERT(ADC_RESOLUTION_12_BIT == p_cfg->resolution); + + return FSP_SUCCESS; +} + +#endif + +#if ADC_CFG_PARAM_CHECKING_ENABLE + +/*******************************************************************************************************************//** + * Checks the sample and hold arguments + * + * @param[in] p_instance_ctrl Pointer to instance control block + * @param[in] p_channel_cfg Pointer to channel configuration + * + * @retval FSP_SUCCESS No configuration errors detected + * @retval FSP_ERR_ASSERTION An input argument is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_adc_scan_cfg_check_sample_hold (adc_instance_ctrl_t * const p_instance_ctrl, + adc_channel_cfg_t const * const p_channel_cfg) +{ + #if !BSP_FEATURE_ADC_HAS_SAMPLE_HOLD_REG + + /* If the MCU does not have sample and hold, verify the sample and hold feature is not used. */ + FSP_ASSERT(0U == p_channel_cfg->sample_hold_mask); + FSP_PARAMETER_NOT_USED(p_instance_ctrl); + #else + if (0U != p_channel_cfg->sample_hold_mask) + { + /* Sample and Hold channels can only be 0, 1, 2(unit 0 only) and must have at least minimum state count specified (reference + * section "A/D Sample and Hold Circuit Control Register (ADSHCR)" in the RZ microprocessor User's Manual for details. */ + #if 1U == BSP_FEATURE_ADC_HAS_SAMPLE_HOLD_UNIT_NUM + FSP_ASSERT(0U == p_instance_ctrl->p_cfg->unit); + #elif 2U == BSP_FEATURE_ADC_HAS_SAMPLE_HOLD_UNIT_NUM || 3U == BSP_FEATURE_ADC_HAS_SAMPLE_HOLD_UNIT_NUM + + /* Unit1 can also be set. */ + FSP_PARAMETER_NOT_USED(p_instance_ctrl); + #endif + FSP_ASSERT(p_channel_cfg->sample_hold_mask <= ADC_SAMPLE_HOLD_CHANNELS); + FSP_ASSERT(p_channel_cfg->sample_hold_states >= ADC_SAMPLE_STATE_HOLD_COUNT_MIN); + } + #endif + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Enforces constraints on Window Compare function usage. Reference section "Compare function constraint" + * in the RZ microprocessor User's Manual for details. + * + * @param[in] p_window_cfg Pointer to window compare configuration + * + * @retval FSP_SUCCESS No configuration errors detected + * @retval FSP_ERR_ASSERTION An input argument is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_adc_scan_cfg_check_window_compare (adc_window_cfg_t const * const p_window_cfg) +{ + if (p_window_cfg) + { + uint32_t compare_cfg = p_window_cfg->compare_cfg; + if (0U != compare_cfg) + { + #if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + if ((compare_cfg & R_ADC121_ADCMPCR_CMPAE_Msk) && (compare_cfg & R_ADC121_ADCMPCR_CMPBE_Msk)) + #elif 2U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE || 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + if ((compare_cfg & R_ADC120_ADCMPCR_CMPAE_Msk) && (compare_cfg & R_ADC120_ADCMPCR_CMPBE_Msk)) + #endif + { + /* Ensure channels selected for Window A do not conflict with Window B */ + uint32_t compare_b_ch = p_window_cfg->compare_b_channel; + FSP_ASSERT(!(p_window_cfg->compare_mask & (uint32_t) (1 << compare_b_ch))); + } + + #if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + if (compare_cfg & R_ADC121_ADCMPCR_WCMPE_Msk) + #elif 2U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE || 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + if (compare_cfg & R_ADC120_ADCMPCR_WCMPE_Msk) + #endif + { + /* Ensure lower reference values are less than or equal to the high reference values */ + FSP_ASSERT((p_window_cfg->compare_ref_low <= p_window_cfg->compare_ref_high) && + (p_window_cfg->compare_b_ref_low <= p_window_cfg->compare_b_ref_high)); + } + } + } + + return FSP_SUCCESS; +} + +#endif + +/*******************************************************************************************************************//** + * The Open function applies power to the A/D peripheral, sets the operational mode, trigger sources, and + * configurations common to all channels and sensors. + * + * @param[in] p_instance_ctrl Pointer to instance control block + * @param[in] p_cfg Pointer to configuration structure + **********************************************************************************************************************/ +static void r_adc_open_sub (adc_instance_ctrl_t * const p_instance_ctrl, adc_cfg_t const * const p_cfg) +{ + adc_extended_cfg_t const * p_cfg_extend = (adc_extended_cfg_t const *) p_cfg->p_extend; + + /* Determine the value for ADCSR: + * * The configured mode is set in ADCSR.ADCS. + * * ADCSR.GBADIE is always set by this driver. It will only trigger an interrupt in group mode if the group B + * interrupt is enabled. + * * If double-trigger mode is selected ADCSR.DBLANS is set to the chosen double-trigger scan channel and + * ADCSR.DBLE is set to 1; otherwise, both are set to 0. + * * The configured trigger mode is set in ADCSR.EXTRG and ADCSR.TRGE. + * * The value to set in ADCSR to start a scan is stored in the control structure. ADCSR.ADST is set in + * R_ADC_ScanStart if software trigger mode is used. + */ +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + uint32_t adcsr = (uint32_t) (p_cfg->mode << R_ADC121_ADCSR_ADCS_Pos); + adcsr |= (uint32_t) (R_ADC121_ADCSR_GBADIE_Msk); + adcsr |= (uint32_t) (R_ADC121_ADCSR_ADIE_Msk); + adcsr |= ((uint32_t) p_cfg->trigger << R_ADC121_ADCSR_EXTRG_Pos); +#elif 2U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE || 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + uint32_t adcsr = (uint32_t) (p_cfg->mode << R_ADC120_ADCSR_ADCS_Pos); + adcsr |= (uint32_t) (R_ADC120_ADCSR_GBADIE_Msk); + adcsr |= (uint32_t) (R_ADC120_ADCSR_ADIE_Msk); + adcsr |= ((uint32_t) p_cfg->trigger << R_ADC120_ADCSR_EXTRG_Pos); +#endif + if (ADC_DOUBLE_TRIGGER_DISABLED != p_cfg_extend->double_trigger_mode) + { +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + adcsr |= R_ADC121_ADCSR_TRGE_Msk | R_ADC121_ADCSR_DBLE_Msk; +#elif 2U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE || 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + adcsr |= R_ADC120_ADCSR_TRGE_Msk | R_ADC120_ADCSR_DBLE_Msk; +#endif + } + else if (ADC_TRIGGER_SOFTWARE == p_cfg->trigger) + { +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + adcsr |= R_ADC121_ADCSR_ADST_Msk; +#elif 2U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE || 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + adcsr |= R_ADC120_ADCSR_ADST_Msk; +#endif + } + else + { + /* Do nothing. */ + } + + p_instance_ctrl->scan_start_adcsr = (uint16_t) adcsr; + + /* Determine the value for ADCER: + * * The resolution is set as configured in ADCER.ADPRC (on MCUs that have this bitfield). + * * The alignment is set as configured in ADCER.ADFMT (on MCUs that have this bitfield). + * * The clearing option is set as configured in ADCER.ACE. + * * Always select data range of 0 - 32767 in ADCER.INV (on MCUs that have this bitfield). + * * Always disable self-diagnosis (unsupported in this module). + */ + uint32_t adcer = 0U; + +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + #if BSP_FEATURE_ADC_HAS_ADCER_ADPRC + adcer |= (uint32_t) p_cfg->resolution << R_ADC121_ADCER_ADPRC_Pos; + #endif + #if BSP_FEATURE_ADC_HAS_ADCER_ADRFMT + adcer |= (uint32_t) p_cfg->alignment << R_ADC121_ADCER_ADRFMT_Pos; + #endif + adcer |= (uint32_t) p_cfg_extend->clearing << R_ADC121_ADCER_ACE_Pos; +#elif 2U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE || 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + #if BSP_FEATURE_ADC_HAS_ADCER_ADPRC + adcer |= (uint32_t) p_cfg->resolution << R_ADC120_ADCER_ADPRC_Pos; + #endif + #if BSP_FEATURE_ADC_HAS_ADCER_ADRFMT + adcer |= (uint32_t) p_cfg->alignment << R_ADC120_ADCER_ADRFMT_Pos; + #endif + adcer |= (uint32_t) p_cfg_extend->clearing << R_ADC120_ADCER_ACE_Pos; +#endif + + /* Determine the value for ADADC: + * * The addition/averaging modes are set as configured in ADADC.ADC and ADADC.AVEE. + * * On MCUs that do not have the ADADC.AVEE bit (addition not supported), the ADADC.AVEE bit is cleared. + */ + uint32_t adadc = p_cfg_extend->add_average_count; +#if !BSP_FEATURE_ADC_ADDITION_SUPPORTED + adadc &= ~ADC_ADADC_AVEE_BIT; +#endif + + /* Apply clock to peripheral. */ + R_BSP_RegisterProtectDisable(BSP_REG_PROTECT_LPC_RESET); + R_BSP_MODULE_START(FSP_IP_ADC12, p_cfg->unit); + R_BSP_RegisterProtectEnable(BSP_REG_PROTECT_LPC_RESET); + + /* Set the predetermined values for ADCSR, ADSTRGR, ADGCTRGR, ADCER, and ADADC without setting ADCSR.ADST or ADCSR.TRGE. + * ADCSR.ADST or ADCSR.TRGE are set as configured in R_ADC_ScanStart. */ + p_instance_ctrl->p_reg->ADCSR = (uint16_t) (adcsr & ADC_PRV_ADCSR_CLEAR_ADST_TRGE); +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + p_instance_ctrl->p_reg->ADSTRGR = (uint16_t) ((p_cfg_extend->adc_start_trigger_a << R_ADC121_ADSTRGR_TRSA_Pos) | + (p_cfg_extend->adc_start_trigger_b << R_ADC121_ADSTRGR_TRSB_Pos)); +#elif 2U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE || 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + p_instance_ctrl->p_reg->ADSTRGR = (uint16_t) ((p_cfg_extend->adc_start_trigger_a << R_ADC120_ADSTRGR_TRSA_Pos) | + (p_cfg_extend->adc_start_trigger_b << R_ADC120_ADSTRGR_TRSB_Pos)); +#endif + p_instance_ctrl->p_reg->ADCER = (uint16_t) adcer; + p_instance_ctrl->p_reg->ADADC = (uint8_t) adadc; + p_instance_ctrl->p_reg->ADELCCR = (uint8_t) p_cfg_extend->adc_elc_ctrl; + + if (true == p_cfg_extend->adc_start_trigger_c_enabled) + { +#if (1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE) + p_instance_ctrl->p_reg->ADGCTRGR = + (uint8_t) ((p_cfg_extend->adc_start_trigger_c << R_ADC121_ADGCTRGR_TRSC_Pos) | + (uint8_t) (R_ADC121_ADGCTRGR_GCADIE_Msk | + R_ADC121_ADGCTRGR_GRCE_Msk)); +#elif (2U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE || 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE) + p_instance_ctrl->p_reg->ADGCTRGR = + (uint8_t) ((p_cfg_extend->adc_start_trigger_c << R_ADC120_ADGCTRGR_TRSC_Pos) | + (uint8_t) (R_ADC120_ADGCTRGR_GCADIE_Msk | + R_ADC120_ADGCTRGR_GRCE_Msk)); +#endif + } +} + +#if ADC_CFG_PARAM_CHECKING_ENABLE + +/*******************************************************************************************************************//** + * This function does extensive checking on channel mask settings based upon operational mode. + * + * @param[in] p_instance_ctrl Pointer to instance control block + * @param[in] p_channel_cfg Pointer to channel configuration + * + * @retval FSP_SUCCESS No configuration errors detected + * @retval FSP_ERR_ASSERTION An input argument is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_adc_scan_cfg_check (adc_instance_ctrl_t * const p_instance_ctrl, + adc_channel_cfg_t const * const p_channel_cfg) +{ + fsp_err_t err; + uint16_t unit = p_instance_ctrl->p_cfg->unit; + adc_extended_cfg_t const * p_cfg_extend = (adc_extended_cfg_t const *) p_instance_ctrl->p_cfg->p_extend; + + /* Verify at least one channel is selected for normal / group A. */ + uint32_t valid_channels = g_adc_valid_channels[unit]; + FSP_ASSERT((0U != p_channel_cfg->scan_mask) && (0U == (p_channel_cfg->scan_mask & (~valid_channels)))); + + if (ADC_MODE_GROUP_SCAN == p_instance_ctrl->p_cfg->mode) + { + /* Verify at least one channel is selected for group B. */ + FSP_ASSERT((0U != p_channel_cfg->scan_mask_group_b) && + (0U == (p_channel_cfg->scan_mask_group_b & (~valid_channels)))); + + /* Cannot have the same channel in both groups. */ + FSP_ASSERT(0 == (p_channel_cfg->scan_mask & p_channel_cfg->scan_mask_group_b)); + + if (true == p_cfg_extend->adc_start_trigger_c_enabled) + { + /* Verify at least one channel is selected for group C. */ + FSP_ASSERT((0U != p_channel_cfg->scan_mask_group_c) && + (0U == (p_channel_cfg->scan_mask_group_c & (~valid_channels)))); + + /* Cannot have the same channel in both groups. */ + FSP_ASSERT(0 == (p_channel_cfg->scan_mask & p_channel_cfg->scan_mask_group_c)); + } + } + else + { + /* If group mode is not enabled, no channels can be selected for group B. */ + FSP_ASSERT(ADC_MASK_OFF == p_channel_cfg->scan_mask_group_b); + + /* If group mode is not enabled, no channels can be selected for group C. */ + FSP_ASSERT(ADC_MASK_OFF == p_channel_cfg->scan_mask_group_c); + } + + /* Verify that if addition is enabled, then at least one channel is selected. */ + if (ADC_ADD_OFF != p_cfg_extend->add_average_count) + { + /* Addition mask should not include bits from inactive channels. + * This also serves as a check for valid channels in the addition mask */ + uint32_t tmp_mask = p_channel_cfg->scan_mask_group_b | p_channel_cfg->scan_mask; + FSP_ASSERT((0U == (p_channel_cfg->add_mask & ~tmp_mask)) && (0U != p_channel_cfg->add_mask)); + } + else + { + /* Channels cannot be selected for addition if addition is not used. */ + FSP_ASSERT(ADC_MASK_OFF == p_channel_cfg->add_mask); + } + + /* Check sample and hold settings. */ + err = r_adc_scan_cfg_check_sample_hold(p_instance_ctrl, p_channel_cfg); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + /* Check window compare settings. */ + err = r_adc_scan_cfg_check_window_compare(p_channel_cfg->p_window_cfg); + + return err; +} + +#endif + +/*******************************************************************************************************************//** + * This function does extensive checking on channel mask settings based upon operational mode. Mask registers are + * initialized and interrupts enabled in peripheral. Interrupts are also enabled in ICU if corresponding priority + * is not 0. + * + * @param[in] p_instance_ctrl Pointer to instance control block + * @param[in] p_channel_cfg Pointer to channel configuration + **********************************************************************************************************************/ +static void r_adc_scan_cfg (adc_instance_ctrl_t * const p_instance_ctrl, adc_channel_cfg_t const * const p_channel_cfg) +{ + adc_extended_cfg_t const * p_cfg_extend = (adc_extended_cfg_t const *) p_instance_ctrl->p_cfg->p_extend; + + p_instance_ctrl->p_reg->ADANSA0 = (uint16_t) (p_channel_cfg->scan_mask); + p_instance_ctrl->p_reg->ADANSB0 = (uint16_t) (p_channel_cfg->scan_mask_group_b); + p_instance_ctrl->p_reg->ADANSC0 = (uint16_t) (p_channel_cfg->scan_mask_group_c); + p_instance_ctrl->p_reg->ADADS0 = (uint16_t) (p_channel_cfg->add_mask); + +#if BSP_FEATURE_ADC_HAS_SAMPLE_HOLD_REG + + /* Configure sample and hold. */ + uint32_t adshcr = p_channel_cfg->sample_hold_states; + adshcr |= (p_channel_cfg->sample_hold_mask & ADC_MASK_SAMPLE_HOLD_BYPASS_CHANNELS) << + ADC_MASK_SAMPLE_HOLD_BYPASS_SHIFT; + p_instance_ctrl->p_reg->ADSHCR = (uint16_t) adshcr; +#endif + + /* Save window compare config*/ + adc_window_cfg_t * p_window_cfg = p_channel_cfg->p_window_cfg; + + uint16_t adcmpcr = 0; + + if (p_window_cfg) + { + /* Save window compare config */ + adcmpcr = (uint16_t) p_window_cfg->compare_cfg; +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + if (p_window_cfg->compare_cfg & R_ADC121_ADCMPCR_CMPAE_Msk) +#elif 2U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE || 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + if (p_window_cfg->compare_cfg & R_ADC120_ADCMPCR_CMPAE_Msk) +#endif + { + /* Set Window A boundary values */ + p_instance_ctrl->p_reg->ADCMPCR = p_window_cfg->compare_cfg & UINT16_MAX; + p_instance_ctrl->p_reg->ADCMPDR0 = p_window_cfg->compare_ref_low; + p_instance_ctrl->p_reg->ADCMPDR1 = p_window_cfg->compare_ref_high; + + /* Set Window A channel mask */ + p_instance_ctrl->p_reg->ADCMPANSR0 = p_window_cfg->compare_mask & UINT16_MAX; + + /* Set Window A channel inequality mode mask */ + p_instance_ctrl->p_reg->ADCMPLR0 = p_window_cfg->compare_mode_mask & UINT16_MAX; + } + +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + if (p_window_cfg->compare_cfg & R_ADC121_ADCMPCR_CMPBE_Msk) +#elif 2U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE || 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + if (p_window_cfg->compare_cfg & R_ADC120_ADCMPCR_CMPBE_Msk) +#endif + { + /* Set Window B channel and mode */ + p_instance_ctrl->p_reg->ADCMPBNSR = (uint8_t) ((adc_window_b_mode_t) p_window_cfg->compare_b_channel | + p_window_cfg->compare_b_mode); + + /* Set Window B boundary values */ + p_instance_ctrl->p_reg->ADWINLLB = p_window_cfg->compare_b_ref_low; + p_instance_ctrl->p_reg->ADWINULB = p_window_cfg->compare_b_ref_high; + } + } + + /* Set window compare config */ + p_instance_ctrl->p_reg->ADCMPCR = adcmpcr; + + /* Set group A priority action (not interrupt priority!) + * This will also start the Group B scans if configured for ADC_GROUP_A_GROUP_B_CONTINUOUS_SCAN. + */ + p_instance_ctrl->p_reg->ADGSPCR = (uint16_t) p_channel_cfg->priority_group_a; + + /* In double-trigger mode set the channel select bits to the highest selected channel number then return. */ + if (ADC_DOUBLE_TRIGGER_DISABLED != p_cfg_extend->double_trigger_mode) + { + uintptr_t adcsr = p_instance_ctrl->p_reg->ADCSR; +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + adcsr = (adcsr & ~R_ADC121_ADCSR_DBLANS_Msk) + (31U - __CLZ(p_channel_cfg->scan_mask)); +#elif 2U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE || 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + adcsr = (adcsr & ~R_ADC120_ADCSR_DBLANS_Msk) + (31U - __CLZ(p_channel_cfg->scan_mask)); +#endif + p_instance_ctrl->p_reg->ADCSR = (uint16_t) adcsr; + p_instance_ctrl->scan_start_adcsr |= (uint16_t) adcsr; + } +} + +/*******************************************************************************************************************//** + * Returns the lowest channel index that is configured in order to read the results of the configured channels. + * + * @param[in] adc_mask scan mask of active channels retrieved from the control structure + * + * @retval adc_mask_count index value of lowest channel + **********************************************************************************************************************/ +static int32_t r_adc_lowest_channel_get (uint32_t adc_mask) +{ + /* Initialize the mask result */ + uint32_t adc_mask_result = 0U; + int32_t adc_mask_count = -1; + while (0U == adc_mask_result) + { + /* Increment channel until a channel is found in the mask. */ + adc_mask_count++; + adc_mask_result = (uint32_t) (adc_mask & (1U << adc_mask_count)); + } + + return adc_mask_count; +} + +/*******************************************************************************************************************//** + * Clears interrupt flag and calls a callback to notify application of the event. + * + * @param[in] event Event that triggered the ISR + **********************************************************************************************************************/ +static void r_adc_scan_end_common_isr (adc_event_t event) +{ + ADC_CFG_MULTIPLEX_INTERRUPT_ENABLE; + + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE; + + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) R_FSP_IsrContextGet(R_FSP_CurrentIrqGet()); + adc_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. */ + adc_callback_args_t * p_args = p_instance_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; + + /* Store the unit number into the callback argument */ + p_args->unit = p_instance_ctrl->p_cfg->unit; + + /* Initialize the channel to 0. It is not used in this implementation. */ + p_args->channel = ADC_CHANNEL_0; + + /* Populate the context field. */ + p_args->p_context = p_instance_ctrl->p_context; + + /* If a callback was provided, call it with the argument */ + if (NULL != p_instance_ctrl->p_callback) + { + /* If the project is not Trustzone Secure, then it will never need to change security state in order to call the callback. */ + p_instance_ctrl->p_callback(p_args); + } + + if (NULL != p_instance_ctrl->p_callback_memory) + { + /* Restore callback memory in case this is a nested interrupt. */ + *p_instance_ctrl->p_callback_memory = args; + } + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE; + + ADC_CFG_MULTIPLEX_INTERRUPT_DISABLE; +} + +/*******************************************************************************************************************//** + * This function implements the unit 0 interrupt handler for normal/Group A/double trigger scan complete. + **********************************************************************************************************************/ +void adc_scan_end_isr (void) +{ + r_adc_scan_end_common_isr(ADC_EVENT_SCAN_COMPLETE); +} + +/*******************************************************************************************************************//** + * This function implements the interrupt handler for Group B scan complete. + **********************************************************************************************************************/ +void adc_scan_end_b_isr (void) +{ + r_adc_scan_end_common_isr(ADC_EVENT_SCAN_COMPLETE_GROUP_B); +} + +/*******************************************************************************************************************//** + * This function implements the interrupt handler for Group C scan complete. + **********************************************************************************************************************/ +void adc_scan_end_c_isr (void) +{ + r_adc_scan_end_common_isr(ADC_EVENT_SCAN_COMPLETE_GROUP_C); +} + +/*******************************************************************************************************************//** + * This function implements the interrupt handler for window compare events. + **********************************************************************************************************************/ +void adc_window_compare_isr (void) +{ + ADC_CFG_MULTIPLEX_INTERRUPT_ENABLE; + + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE; + + IRQn_Type irq = R_FSP_CurrentIrqGet(); + + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) R_FSP_IsrContextGet(irq); + adc_extended_cfg_t * p_extend = (adc_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + adc_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. */ + adc_callback_args_t * p_args = p_instance_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 = (irq == p_extend->window_a_irq) ? ADC_EVENT_WINDOW_COMPARE_A : ADC_EVENT_WINDOW_COMPARE_B; + + /* Store the unit number into the callback argument */ + p_args->unit = p_instance_ctrl->p_cfg->unit; + + if (ADC_EVENT_WINDOW_COMPARE_A == p_args->event) + { +#if 1U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + R_ADC121_Type * p_reg = p_instance_ctrl->p_reg; +#elif 2U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + R_ADC120_Type * p_reg = p_instance_ctrl->p_reg; +#elif 3U == BSP_FEATURE_ADC_REGISTER_MASK_TYPE + R_ADC122_Type * p_reg = p_instance_ctrl->p_reg; +#endif + + /* Get all Window A status registers */ + uint16_t adcmpsr0 = p_reg->ADCMPSR0; + + /* Get the lowest channel that meets Window A criteria */ + uint16_t lowest_channel = (uint16_t) __CLZ(__RBIT(adcmpsr0)); + + /* Get channel selected for Window A */ + p_args->channel = (adc_channel_t) lowest_channel; + + /* Clear the status flag corresponding to the lowest channel of window A */ + p_reg->ADCMPSR0 = (uint16_t) (adcmpsr0 & ~(1 << (lowest_channel & 0xF))); + } + else + { + /* Get channel selected for Window B */ + p_args->channel = (adc_channel_t) p_instance_ctrl->p_reg->ADCMPBNSR_b.CMPCHB; + + /* Clear window B flag */ + p_instance_ctrl->p_reg->ADCMPBSR_b.CMPSTB = 0; + } + + /* Populate the context field. */ + p_args->p_context = p_instance_ctrl->p_context; + + /* If a callback was provided, call it with the argument */ + if (NULL != p_instance_ctrl->p_callback) + { + /* If the project is not Trustzone Secure, then it will never need to change security state in order to call the callback. */ + p_instance_ctrl->p_callback(p_args); + } + + if (NULL != p_instance_ctrl->p_callback_memory) + { + /* Restore callback memory in case this is a nested interrupt. */ + *p_instance_ctrl->p_callback_memory = args; + } + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE; + ADC_CFG_MULTIPLEX_INTERRUPT_DISABLE; +} diff --git a/drivers/rz/fsp/src/rzv/r_adc_c/r_adc_c.c b/drivers/rz/fsp/src/rzv/r_adc_c/r_adc_c.c new file mode 100644 index 00000000..3c0ae87f --- /dev/null +++ b/drivers/rz/fsp/src/rzv/r_adc_c/r_adc_c.c @@ -0,0 +1,969 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*********************************************************************************************************************** + * Includes , "Project Includes" + **********************************************************************************************************************/ + +#include "r_adc_c.h" + +/********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +#define ADC_C_OPEN (0x41444343U) + +/* A/D converter stabilization wait time. */ +#define ADC_C_STABILIZATION_DELAY_US (1U) +#define ADC_C_FRQ_DIV_RATIO (4U) +#define ADC_C_IDLE_TIME (0U) +#define ADC_C_PRV_ADM0_CLEAR_ADCE (~R_ADC_C_ADM0_ADCE_Msk) +#define ADC_C_DATA_SIZE_BUFFER_MODE_4 (4U) +#define ADC_C_INTERRUPT_CHANNEL_BUFFER_MODE_4 (0x8U) +#define ADC_C_4_BUFFER_CHANNEL_MASK (0xFU) + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +#if defined(__ARMCC_VERSION) || defined(__ICCARM__) +typedef void (BSP_CMSE_NONSECURE_CALL * adc_prv_ns_callback)(adc_callback_args_t * p_args); +#elif defined(__GNUC__) +typedef BSP_CMSE_NONSECURE_CALL void (*volatile adc_prv_ns_callback)(adc_callback_args_t * p_args); +#endif + +/*********************************************************************************************************************** + * Private global variables and functions + **********************************************************************************************************************/ + +static void r_adc_c_open_sub(adc_c_instance_ctrl_t * const p_instance_ctrl, adc_cfg_t const * const p_cfg); +static void r_adc_c_scan_cfg(adc_c_instance_ctrl_t * const p_instance_ctrl, + adc_c_channel_cfg_t const * const p_channel_cfg); +void adc_c_scan_end_isr(void); +static void r_adc_c_irq_enable(IRQn_Type irq, uint8_t ipl, void * p_context); +static void r_adc_c_irq_disable(IRQn_Type irq); +static uint32_t r_adc_c_lowest_channel_get(uint32_t adc_mask); +static uint32_t r_adc_c_highest_channel_get(uint32_t adc_mask); + +/*********************************************************************************************************************** + * Global Variables + **********************************************************************************************************************/ + +/** ADC Implementation of ADC. */ +const adc_api_t g_adc_on_adc_c = +{ + .open = R_ADC_C_Open, + .scanCfg = R_ADC_C_ScanCfg, + .infoGet = R_ADC_C_InfoGet, + .scanStart = R_ADC_C_ScanStart, + .scanGroupStart = R_ADC_C_ScanGroupStart, + .scanStop = R_ADC_C_ScanStop, + .scanStatusGet = R_ADC_C_StatusGet, + .read = R_ADC_C_Read, + .read32 = R_ADC_C_Read32, + .close = R_ADC_C_Close, + .calibrate = R_ADC_C_Calibrate, + .offsetSet = R_ADC_C_OffsetSet, + .callbackSet = R_ADC_C_CallbackSet, +}; + +/*******************************************************************************************************************//** + * @addtogroup ADC_C + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Initializes the ADC module and applies configurations. + * + * @retval FSP_SUCCESS Module is ready for use. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_ALREADY_OPEN The instance control structure has already been opened. + * @retval FSP_ERR_IRQ_BSP_DISABLED A callback is provided, but the interrupt is not enabled. + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_Open (adc_ctrl_t * p_ctrl, adc_cfg_t const * const p_cfg) +{ + adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl; + + /* Perform parameter checking */ +#if ADC_C_CFG_PARAM_CHECKING_ENABLE + + /* Verify the pointers are valid */ + FSP_ASSERT(NULL != p_instance_ctrl); + + /* Verify the configuration parameters are valid */ + FSP_ASSERT(NULL != p_cfg); + + /* Verify this unit has not already been initialized */ + FSP_ERROR_RETURN(ADC_C_OPEN != p_instance_ctrl->opened, FSP_ERR_ALREADY_OPEN); + + /* If a callback is used, then make sure an interrupt is enabled */ + if (NULL != p_cfg->p_callback) + { + FSP_ERROR_RETURN((p_cfg->scan_end_irq >= 0), FSP_ERR_IRQ_BSP_DISABLED); + } +#endif + + /* Save configurations. */ + p_instance_ctrl->p_cfg = p_cfg; + p_instance_ctrl->p_callback = p_cfg->p_callback; + p_instance_ctrl->p_context = p_cfg->p_context; + p_instance_ctrl->p_callback_memory = NULL; + + /* Calculate the register base address. */ + p_instance_ctrl->p_reg = R_ADC_C; + + /* Initialize the hardware based on the configuration. */ + r_adc_c_open_sub(p_instance_ctrl, p_cfg); + + /* Enable interrupts */ + r_adc_c_irq_enable(p_cfg->scan_end_irq, p_cfg->scan_end_ipl, p_instance_ctrl); + + /* Invalid scan mask (initialized for later). */ + p_instance_ctrl->scan_mask = 0U; + + /* Mark driver as opened by initializing it to "ADCC" in its ASCII equivalent for this unit. */ + p_instance_ctrl->opened = ADC_C_OPEN; + + /* Return the error code */ + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Configures the ADC_C scan parameters. Channel specific settings are set in this function. Pass a pointer to + * @ref adc_c_channel_cfg_t to p_channel_cfg. + * + * + * @retval FSP_SUCCESS Channel specific settings applied. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_ScanCfg (adc_ctrl_t * p_ctrl, void const * const p_channel_cfg) +{ + adc_c_channel_cfg_t const * p_adc_channel_cfg = (adc_c_channel_cfg_t const *) p_channel_cfg; + adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl; + fsp_err_t err = FSP_SUCCESS; + +#if ADC_C_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_adc_channel_cfg); + FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); + + /* Multiple analog input channel selection is prohibited in select mode. */ + FSP_ASSERT(!((ADC_C_OPERATING_MODE_SELECT == p_instance_ctrl->operating_mode) && + ((ADC_C_MASK_CHANNEL_0 | ADC_C_MASK_CHANNEL_1) == p_adc_channel_cfg->scan_mask))); +#endif + + /* Configure the hardware based on the configuration. */ + r_adc_c_scan_cfg(p_instance_ctrl, p_adc_channel_cfg); + + /* Save the scan mask locally; this is required for the infoGet function. */ + p_instance_ctrl->scan_mask = p_adc_channel_cfg->scan_mask; + + /* Return the error code. */ + return err; +} + +/*******************************************************************************************************************//** + * Updates the user callback and has option of providing memory for callback structure. + * Implements adc_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_ADC_C_CallbackSet (adc_ctrl_t * const p_api_ctrl, + void ( * p_callback)(adc_callback_args_t *), + void const * const p_context, + adc_callback_args_t * const p_callback_memory) +{ + adc_c_instance_ctrl_t * p_ctrl = (adc_c_instance_ctrl_t *) p_api_ctrl; + +#if (ADC_C_CFG_PARAM_CHECKING_ENABLE) + FSP_ASSERT(p_ctrl); + FSP_ASSERT(p_callback); + FSP_ERROR_RETURN(ADC_C_OPEN == p_ctrl->opened, FSP_ERR_NOT_OPEN); +#endif + + /* Store callback and context */ + +#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 ADC_C_CFG_PARAM_CHECKING_ENABLE + + /* In secure projects, p_callback_memory must be provided in non-secure space if p_callback is non-secure */ + adc_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 + + p_ctrl->p_callback = callback_is_secure ? p_callback : + (void (*)(adc_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; +} + +/*******************************************************************************************************************//** + * Start A/D conversion. + * + * @pre Call R_ADC_C_ScanCfg after R_ADC_C_Open before starting a scan. + * + * @retval FSP_SUCCESS Scan started (software trigger) or hardware triggers enabled. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + * @retval FSP_ERR_NOT_INITIALIZED Unit is not initialized. + * @retval FSP_ERR_IN_USE Another scan is still in progress (software trigger). + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_ScanStart (adc_ctrl_t * p_ctrl) +{ + adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl; + + /* Perform parameter checking */ +#if ADC_C_CFG_PARAM_CHECKING_ENABLE + + /* Verify the pointers are valid */ + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); + FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->initialized, FSP_ERR_NOT_INITIALIZED); + FSP_ERROR_RETURN(0U == p_instance_ctrl->p_reg->ADM0_b.ADCE, FSP_ERR_IN_USE); +#endif + + /* Start A/D conversion. */ + p_instance_ctrl->p_reg->ADM0 = p_instance_ctrl->scan_start; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * @ref adc_api_t::scanGroupStart is not supported. Use scanStart instead. + * + * @retval FSP_ERR_UNSUPPORTED Function not supported in this implementation. + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_ScanGroupStart (adc_ctrl_t * p_ctrl, adc_group_mask_t group_id) +{ + FSP_PARAMETER_NOT_USED(p_ctrl); + FSP_PARAMETER_NOT_USED(group_id); + + /* Return the unsupported error. */ + return FSP_ERR_UNSUPPORTED; +} + +/*******************************************************************************************************************//** + * Stop A/D conversion. + * + * @retval FSP_SUCCESS Scan stopped (software trigger) or hardware triggers disabled. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + * @retval FSP_ERR_NOT_INITIALIZED Unit is not initialized. + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_ScanStop (adc_ctrl_t * p_ctrl) +{ + adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl; + + /* Perform parameter checking */ +#if ADC_C_CFG_PARAM_CHECKING_ENABLE + + /* Verify the pointers are valid */ + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); + FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->initialized, FSP_ERR_NOT_INITIALIZED); +#endif + + /* Stop A/D conversion. */ + p_instance_ctrl->p_reg->ADM0 = (uint32_t) (p_instance_ctrl->scan_start & ADC_C_PRV_ADM0_CLEAR_ADCE); + + /* Read ADM0 register to confirm that A/D conversion is stopped. */ + FSP_HARDWARE_REGISTER_WAIT(p_instance_ctrl->p_reg->ADM0_b.ADCE, 0U); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Get current ADC_C status and store it in provided pointer p_status. + * + * @retval FSP_SUCCESS Module status stored in the provided pointer p_status + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_StatusGet (adc_ctrl_t * p_ctrl, adc_status_t * p_status) +{ + adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl; + +#if ADC_C_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_status); + FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); +#endif + + /* Read the status of the ADBSY bit. ADBSY is set when a scan is in progress. */ + p_status->state = (adc_state_t) p_instance_ctrl->p_reg->ADM0_b.ADBSY; + + /* Return the error code */ + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Reads conversion results from a single channel or sensor. + * + * @retval FSP_SUCCESS Data read into provided p_data. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + * @retval FSP_ERR_NOT_INITIALIZED Unit is not initialized. + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_Read (adc_ctrl_t * p_ctrl, adc_channel_t const reg_id, uint16_t * const p_data) +{ + adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl; + + /* Perform parameter checking. */ +#if ADC_C_CFG_PARAM_CHECKING_ENABLE + + /* Verify the pointers are valid */ + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_data); + FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); + FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->initialized, FSP_ERR_NOT_INITIALIZED); + + /* Verify that the channel is valid for this MCU */ + uint32_t requested_channel_mask = (1U << (uint32_t) reg_id); + FSP_ASSERT(0 != (requested_channel_mask & BSP_FEATURE_ADC_C_VALID_CHANNEL_MASK)); +#endif + + /* Read the data from the requested ADC conversion register and return it */ + *p_data = *((uint16_t *) (&p_instance_ctrl->p_reg->ADCR0 + reg_id)); + + /* Return the error code */ + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Reads conversion results from a single channel or sensor register into a 32-bit result. + * + * @retval FSP_SUCCESS Data read into provided p_data. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + * @retval FSP_ERR_NOT_INITIALIZED Unit is not initialized. + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_Read32 (adc_ctrl_t * p_ctrl, adc_channel_t const reg_id, uint32_t * const p_data) +{ + uint16_t result = 0U; + uint32_t result_32 = 0U; + +#if ADC_C_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_data); +#endif + + fsp_err_t err = R_ADC_C_Read(p_ctrl, reg_id, &result); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + result_32 = result; + *p_data = result_32; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Sets the sample state count for individual channels. This only needs to be set for special use cases. Normally, use + * the default values out of reset. + * + * @note The sample states for the temperature and voltage sensor are set in R_ADC_C_ScanCfg. + * + * @retval FSP_SUCCESS Sample state count updated. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_INITIALIZED Unit is not initialized. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + * @retval FSP_ERR_IN_USE A/D conversion ongoing. + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_SampleStateCountSet (adc_ctrl_t * p_ctrl, uint16_t num_states) +{ + adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl; + fsp_err_t err = FSP_SUCCESS; + + /* Perform parameter checking */ +#if ADC_C_CFG_PARAM_CHECKING_ENABLE + + /* Verify the pointers are valid */ + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); + FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->initialized, FSP_ERR_NOT_INITIALIZED); + FSP_ERROR_RETURN(0 == p_instance_ctrl->p_reg->ADM0_b.ADBSY, FSP_ERR_IN_USE); + + /* Verify the arguments are within the expected range. */ + FSP_ASSERT((num_states >= BSP_FEATURE_ADC_C_SAMPLE_STATE_COUNT_MIN) && + (num_states <= BSP_FEATURE_ADC_C_SAMPLE_STATE_COUNT_MAX)); +#endif + + /* Set the sample state count for the specified register */ + uint32_t adm3 = (uint32_t) (ADC_C_IDLE_TIME << R_ADC_C_ADM3_ADIL_Pos) | + (uint32_t) (BSP_FEATURE_ADC_C_CONVERSION_TIME << R_ADC_C_ADM3_ADCMP_Pos) | + (num_states << R_ADC_C_ADM3_ADSMP_Pos); + p_instance_ctrl->p_reg->ADM3 = adm3; + + /* Return the error code */ + return err; +} + +/*******************************************************************************************************************//** + * Returns the address of the lowest number configured channel and the total number of bytes to be read in order to + * read the results of the configured channels. If no channels are configured, then a length of 0 is returned. + * + * + * @retval FSP_SUCCESS Information stored in p_adc_info. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_InfoGet (adc_ctrl_t * p_ctrl, adc_info_t * p_adc_info) +{ + adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl; + fsp_err_t err = FSP_SUCCESS; + uint32_t adc_mask = 0; + +#if ADC_C_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_adc_info); + FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); +#endif + + adc_c_extended_cfg_t * p_extend = (adc_c_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + /* Retrieve the scan mask of active channels from the control structure */ + adc_mask = p_instance_ctrl->scan_mask; + + if (ADC_C_BUFFER_MODE_4 == p_extend->buffer_mode) + { + p_adc_info->length = ADC_C_DATA_SIZE_BUFFER_MODE_4; + p_adc_info->p_address = &p_instance_ctrl->p_reg->ADCR0; + } + else + { + /* If at least one channel is configured, determine the highest and lowest configured channels. */ + if (adc_mask != 0U) + { + uint32_t adc_mask_in_order = adc_mask; + uint32_t lowest_channel = r_adc_c_lowest_channel_get(adc_mask_in_order); + + p_adc_info->p_address = (uint32_t *) (&p_instance_ctrl->p_reg->ADCR0 + lowest_channel); + + /* Determine the highest channel that is configured. */ + uint32_t highest_channel = r_adc_c_highest_channel_get(adc_mask_in_order); + + /* Determine the size of data that must be read to read all the channels between and including the + * highest and lowest channels.*/ + p_adc_info->length = (uint32_t) ((highest_channel - lowest_channel) + 1); + } + else + { + /* If no channels are configured, set the return length 0. */ + p_adc_info->length = 0U; + } + } + + p_adc_info->transfer_size = TRANSFER_SIZE_2_BYTE; + +#if BSP_FEATURE_ADC_C_TSU_CONTROL_AVAILABLE + + /* Read into memory. */ + p_adc_info->calibration_data1 = R_TSU->OTPTSUTRIM0_REG_b.OTPTSUTRIM0; + p_adc_info->calibration_data2 = R_TSU->OTPTSUTRIM1_REG_b.OTPTSUTRIM1; +#else + + /* Set Temp Sensor calibration data to invalid value */ + p_adc_info->calibration_data1 = UINT32_MAX; + p_adc_info->calibration_data2 = UINT32_MAX; +#endif + + return err; +} + +/*******************************************************************************************************************//** + * This function ends any scan in progress, disables interrupts, and removes power to the A/D peripheral. + * + * @retval FSP_SUCCESS Module closed. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_Close (adc_ctrl_t * p_ctrl) +{ + adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl; + +#if ADC_C_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); +#endif + + /* Mark driver as closed */ + p_instance_ctrl->opened = 0U; + p_instance_ctrl->initialized = 0U; + + /* Disable interrupts. */ + r_adc_c_irq_disable(p_instance_ctrl->p_cfg->scan_end_irq); + + /* Stop the ADC. */ + p_instance_ctrl->p_reg->ADM0 = 0U; + + /* Read ADM0 register to confirm that A/D conversion is stopped. */ + FSP_HARDWARE_REGISTER_WAIT(p_instance_ctrl->p_reg->ADM0_b.ADCE, 0U); + + /* Clear the interrupt cause flag and trigger detection flag. */ + uint32_t adsts = (uint32_t) (1 << R_ADC_C_ADSTS_TRGS_Pos); + adsts |= (uint32_t) (BSP_FEATURE_ADC_C_VALID_CHANNEL_MASK << R_ADC_C_ADSTS_INTST_Pos); + p_instance_ctrl->p_reg->ADSTS = adsts; + + R_BSP_MODULE_STOP(FSP_IP_ADC, 0); + + if (p_instance_ctrl->scan_mask & ADC_C_MASK_CHANNEL_8) + { +#if BSP_FEATURE_ADC_C_TSU_CONTROL_AVAILABLE + + /* Set the temperature sensor to place in the standby mode. */ + R_TSU->TSU_SM = 0; + + /* Stop the TSU. */ + R_BSP_MODULE_STOP(FSP_IP_TSU, 0); +#endif + } + + /* Return the error code */ + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * @ref adc_api_t::calibrate is not supported. + * + * @retval FSP_ERR_UNSUPPORTED Calibration not supported on this MCU. + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_Calibrate (adc_ctrl_t * const p_ctrl, void const * p_extend) +{ + FSP_PARAMETER_NOT_USED(p_ctrl); + FSP_PARAMETER_NOT_USED(p_extend); + + /* Return the unsupported error. */ + return FSP_ERR_UNSUPPORTED; +} + +/*******************************************************************************************************************//** + * @ref adc_api_t::offsetSet is not supported. + * + * @retval FSP_ERR_UNSUPPORTED Function not supported in this implementation. + **********************************************************************************************************************/ +fsp_err_t R_ADC_C_OffsetSet (adc_ctrl_t * const p_ctrl, adc_channel_t const reg_id, int32_t offset) +{ + FSP_PARAMETER_NOT_USED(p_ctrl); + FSP_PARAMETER_NOT_USED(reg_id); + FSP_PARAMETER_NOT_USED(offset); + + /* Return the unsupported error. */ + return FSP_ERR_UNSUPPORTED; +} + +/*******************************************************************************************************************//** + * @} (end addtogroup ADC_C) + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Private Functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * The Open function applies power to the A/D peripheral, sets the value for ADM0, ADM1, ADM3, ADIVC, ADFIL. + * + * @param[in] p_instance_ctrl Pointer to instance control block + * @param[in] p_cfg Pointer to configuration structure + **********************************************************************************************************************/ +static void r_adc_c_open_sub (adc_c_instance_ctrl_t * const p_instance_ctrl, adc_cfg_t const * const p_cfg) +{ + adc_c_extended_cfg_t const * p_cfg_extend = (adc_c_extended_cfg_t const *) p_cfg->p_extend; + + /* Determine the value for ADM0, ADM1, ADM3, ADIVC, ADFIL.: + * The value to set in ADCSR to start a scan is stored in the control structure. + * ADM0.ADCE is set in R_ADC_ScanStart. + */ + + /* Sets the trigger mode. */ + uint32_t adm1 = (uint32_t) (p_cfg_extend->trigger_mode << R_ADC_C_ADM1_TRG_Pos); + + /* When using hardware trigger mode, set the hardware trigger signal parameter. */ + if (ADC_C_TRIGGER_MODE_HARDWARE == p_cfg_extend->trigger_mode) + { + adm1 |= (uint32_t) (p_cfg_extend->trigger_source << R_ADC_C_ADM1_TRGEN_Pos); + adm1 |= (uint32_t) (p_cfg_extend->input_mode << R_ADC_C_ADM1_TRGIN_Pos); + + /* The trigger edge setting is valid only when the trigger source is ADC_TRG. + * Reference section "A/D Converter Mode Register 1 (ADM1)" of the user's manual. */ + if (ADC_C_ACTIVE_TRIGGER_EXTERNAL == p_cfg_extend->trigger_source) + { + adm1 |= (uint32_t) (p_cfg_extend->trigger_edge << R_ADC_C_ADM1_EGA_Pos); + } + /* Otherwise falling edge is always valid. */ + else + { + adm1 |= (uint32_t) (ADC_C_TRIGGER_EDGE_FALLING << R_ADC_C_ADM1_EGA_Pos); + } + } + else + { + /* Do nothing. */ + } + + /* Sets the operating mode and buffer mode. */ + adm1 |= (uint32_t) (p_cfg_extend->operating_mode << R_ADC_C_ADM1_MS_Pos); + + /* 1-Buffer mode and 4-Buffer mode can be set when using select mode. */ + if (ADC_C_OPERATING_MODE_SELECT == p_cfg_extend->operating_mode) + { + adm1 |= (uint32_t) (p_cfg_extend->buffer_mode << R_ADC_C_ADM1_BS_Pos); + } + + /* Repeat mode corresponds to ADC_MODE_CONTINUOUS_SCAN of API, + * but since the API value (=2) and repeat mode register setting value (=1) are different, + * it is necessary to convert them. + * Sets the conversion mode. */ + adm1 |= (uint32_t) ((p_cfg->mode >> 1U) << R_ADC_C_ADM1_RPS_Pos); + +#if BSP_FEATURE_ADC_C_HAS_ADIVC + + /* Sets the frequency division ratio for dividing the frequency of ADC_ADCLK(TSUϕ). */ + uint32_t adivc = (uint32_t) (ADC_C_FRQ_DIV_RATIO << R_ADC_C_ADIVC_DIVADC_Pos); +#endif + + uint32_t adfil = 0; + + /* Enables or disables the AD external trigger pin filter. */ + if (ADC_C_FILTER_STAGE_SETTING_DISABLE != p_cfg_extend->external_trigger_filter) + { + adfil = (uint32_t) (1 << R_ADC_C_ADFIL_FILONOFF_Pos); + + /* Set the number of stages of the AD external trigger pin filter. */ + adfil |= (uint32_t) ((p_cfg_extend->external_trigger_filter - 1) << R_ADC_C_ADFIL_FILNUM_Pos); + } + else + { + /* Do nothing. */ + } + + /* Set the idle period. */ + uint32_t adm3 = (uint32_t) (ADC_C_IDLE_TIME << R_ADC_C_ADM3_ADIL_Pos); + + /* Set the conversion period and sampling period. */ + adm3 |= (uint32_t) (BSP_FEATURE_ADC_C_CONVERSION_TIME << R_ADC_C_ADM3_ADCMP_Pos); + adm3 |= (uint32_t) (p_cfg_extend->sampling_time << R_ADC_C_ADM3_ADSMP_Pos); + + /* Apply clock to peripheral. */ + R_BSP_MODULE_START(FSP_IP_ADC, 0); + + /* The following series of steps refer to "A/D conversion start procedure" in the user's manual. */ + /* Release from software reset state. */ + uint32_t adm0 = (uint32_t) (1 << R_ADC_C_ADM0_SRESB_Pos); + p_instance_ctrl->p_reg->ADM0 = adm0; + + /* The waiting time until the reset state of the A/D converter is released is 2 × ADC_ADCLK(TSUϕ) (80 MHz), + * but since the minimum waiting time of R_BSP_SoftwareDelay is 1us, + * processing is executed with a waiting time of 1us. */ + R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MICROSECONDS); + + /* Clear the interrupt cause flag and trigger detection flag. */ + uint32_t adsts = (uint32_t) (1 << R_ADC_C_ADSTS_TRGS_Pos); + adsts |= (uint32_t) (BSP_FEATURE_ADC_C_VALID_CHANNEL_MASK << R_ADC_C_ADSTS_INTST_Pos); + p_instance_ctrl->p_reg->ADSTS = adsts; + + /* Set the predetermined values for ADM1, ADM3, ADINT, ADIVC, and ADFIL. + * ADM0.ADCE are set as configured in R_ADC_ScanStart. */ + p_instance_ctrl->p_reg->ADM1 = adm1; + p_instance_ctrl->p_reg->ADM3 = adm3; +#if BSP_FEATURE_ADC_C_HAS_ADIVC + p_instance_ctrl->p_reg->ADIVC = adivc; +#endif + p_instance_ctrl->p_reg->ADFIL = adfil; + + /* Change from power-saving mode to normal mode. */ + adm0 |= (uint32_t) (1 << R_ADC_C_ADM0_PWDWNB_Pos); + p_instance_ctrl->p_reg->ADM0 = adm0; + + /* Secure the A/D converter stabilization wait time. */ + R_BSP_SoftwareDelay(ADC_C_STABILIZATION_DELAY_US, BSP_DELAY_UNITS_MICROSECONDS); + + /* Set the ADCE bit. */ + adm0 |= (uint32_t) (R_ADC_C_ADM0_ADCE_Msk); + + p_instance_ctrl->scan_start = adm0; + + /* Save the operating mode and buffer mode locally; this is required for the Scancfg function. */ + p_instance_ctrl->operating_mode = p_cfg_extend->operating_mode; + p_instance_ctrl->buffer_mode = p_cfg_extend->buffer_mode; +} + +/*******************************************************************************************************************//** + * This function does extensive checking on channel mask settings based upon operational mode. Mask registers are + * initialized and interrupts enabled in peripheral. Interrupts are also enabled in ICU if corresponding priority + * is not 0. + * + * @param[in] p_instance_ctrl Pointer to instance control block + * @param[in] p_channel_cfg Pointer to channel configuration + **********************************************************************************************************************/ +static void r_adc_c_scan_cfg (adc_c_instance_ctrl_t * const p_instance_ctrl, + adc_c_channel_cfg_t const * const p_channel_cfg) +{ + if (p_channel_cfg->scan_mask & ADC_C_MASK_CHANNEL_8) + { +#if BSP_FEATURE_ADC_C_TSU_CONTROL_AVAILABLE + + /* Apply clock to peripheral. */ + R_BSP_MODULE_START(FSP_IP_TSU, 0); + + /* Set the temperature sensor to place in the normal operating mode. */ + R_TSU->TSU_SM = R_TSU_TSU_SM_EN_Msk; + + /* Wait 30us. See the TSU "Operation" section of the RZ microprocessor manual. */ + R_BSP_SoftwareDelay(BSP_FEATURE_ADC_C_TSU_ENABLE_STABILIZATION_TIME_US, BSP_DELAY_UNITS_MICROSECONDS); + + /* Enable the temperature sensor. */ + R_TSU->TSU_SM |= R_TSU_TSU_SM_OE_Msk; + + /* Wait 1000us. See the TSU "Operation" section of the RZ microprocessor manual. */ + R_BSP_SoftwareDelay(BSP_FEATURE_ADC_C_TSU_START_STABILIZATION_TIME_MS, BSP_DELAY_UNITS_MILLISECONDS); +#endif + } + + /* Set mask for channels. */ + p_instance_ctrl->p_reg->ADM2 = (uint32_t) (p_channel_cfg->scan_mask & (uint32_t) R_ADC_C_ADM2_CHSEL_Msk); + + /* Disables the A/D conversion channel select error interrupt. */ + uint32_t adint = (uint32_t) (0 << R_ADC_C_ADINT_CSEEN_Pos); + + /* Enable or disable the conversion end interrupt of channel n (n = 0 to 3). */ + if (ADC_C_INTERRUPT_CHANNEL_SETTING_ENABLE == p_channel_cfg->interrupt_setting) + { + /* Channel 3 interrupt output is enabled in 4-buffer mode. + * Reference section "Example of A/D Conversion in 4-Buffer Mode" of the user's manual.*/ + if (ADC_C_BUFFER_MODE_4 == p_instance_ctrl->buffer_mode) + { + if (p_channel_cfg->scan_mask & ADC_C_4_BUFFER_CHANNEL_MASK) + { + adint |= (uint32_t) (R_ADC_C_ADCR0_AD3_Msk << R_ADC_C_ADINT_INTEN_Pos); + } + else if (p_channel_cfg->scan_mask & (ADC_C_4_BUFFER_CHANNEL_MASK << 4)) + { + adint |= (uint32_t) (R_ADC_C_ADCR0_AD7_Msk << R_ADC_C_ADINT_INTEN_Pos); + } + else + { + adint |= (uint32_t) (R_ADC_C_ADCR0_AD11_Msk << R_ADC_C_ADINT_INTEN_Pos); + } + } + else + { + uint32_t adc_mask_in_order = p_channel_cfg->scan_mask; + + /* Determine the highest channel that is configured. */ + uint32_t highest_channel = r_adc_c_highest_channel_get(adc_mask_in_order); + + /* Highest channel interrupt output is enabled. */ + adint |= (uint32_t) (1U << highest_channel); + } + } + else + { + /* Do nothing. */ + } + + p_instance_ctrl->p_reg->ADINT = adint; + + p_instance_ctrl->initialized = ADC_C_OPEN; +} + +/*******************************************************************************************************************//** + * Disables and clears context for the requested IRQ. + * + * @param[in] irq IRQ to enable + * @param[in] ipl Interrupt priority + * @param[in] p_context Pointer to interrupt context + **********************************************************************************************************************/ +static void r_adc_c_irq_enable (IRQn_Type irq, uint8_t ipl, void * p_context) +{ + if (irq >= 0) + { + R_BSP_IrqCfgEnable(irq, ipl, p_context); + } +} + +/*******************************************************************************************************************//** + * Disables and clears context for the requested IRQ. + * + * @param[in] irq IRQ to disable + **********************************************************************************************************************/ +static void r_adc_c_irq_disable (IRQn_Type irq) +{ + if (irq >= 0) + { + R_BSP_IrqDisable(irq); + R_FSP_IsrContextSet(irq, NULL); + } +} + +/*******************************************************************************************************************//** + * Returns the lowest channel index that is configured in order to read the results of the configured channels. + * + * @param[in] adc_mask scan mask of active channels retrieved from the control structure + * + * @retval adc_mask_count index value of lowest channel + **********************************************************************************************************************/ +static uint32_t r_adc_c_lowest_channel_get (uint32_t adc_mask) +{ + /* Initialize the mask result */ + uint32_t adc_mask_result = 0U; + int32_t adc_mask_count = -1; + while (0U == adc_mask_result) + { + /* Increment channel until a channel is found in the mask. */ + adc_mask_count++; + adc_mask_result = (uint32_t) (adc_mask & (1U << adc_mask_count)); + } + + return (uint32_t) adc_mask_count; +} + +/*******************************************************************************************************************//** + * Returns the highest channel index that is configured in order to read the results of the configured channels. + * + * @param[in] adc_mask scan mask of active channels retrieved from the control structure + * + * @retval adc_mask_count index value of highest channel + **********************************************************************************************************************/ +static uint32_t r_adc_c_highest_channel_get (uint32_t adc_mask) +{ + /* Initialize the mask result */ + uint32_t adc_mask_result = 0U; + int32_t adc_mask_count = 31; + while (0U == adc_mask_result) + { + /* Decrement channel until a channel is found in the mask. */ + adc_mask_count--; + adc_mask_result = (uint32_t) (adc_mask & (1U << adc_mask_count)); + } + + return (uint32_t) adc_mask_count; +} + +/*******************************************************************************************************************//** + * Calls user callback. + * + * @param[in] p_ctrl Pointer to ADC instance control block + * @param[in] p_args Pointer to arguments on stack + **********************************************************************************************************************/ +static void r_adc_c_call_callback (adc_c_instance_ctrl_t * p_ctrl, adc_callback_args_t * p_args) +{ + adc_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. */ + adc_callback_args_t * p_args_memory = p_ctrl->p_callback_memory; + if (NULL == p_args_memory) + { + /* Use provided args struct on stack */ + p_args_memory = p_args; + } + else + { + /* Save current arguments on the stack in case this is a nested interrupt. */ + args = *p_args_memory; + + /* Copy the stacked args to callback memory */ + *p_args_memory = *p_args; + } + +#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_memory); + } + else + { + /* If p_callback is Non-secure, then the project must change to Non-secure state in order to call the callback. */ + adc_prv_ns_callback p_callback = (adc_prv_ns_callback) (p_ctrl->p_callback); + p_callback(p_args_memory); + } + +#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_memory); +#endif + + if (NULL != p_ctrl->p_callback_memory) + { + /* Restore callback memory in case this is a nested interrupt. */ + *p_ctrl->p_callback_memory = args; + } +} + +/*******************************************************************************************************************//** + * This function implements interrupt handler for scan complete. + **********************************************************************************************************************/ +void adc_c_scan_end_isr (void) +{ + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE; + + IRQn_Type irq = R_FSP_CurrentIrqGet(); + adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) R_FSP_IsrContextGet(irq); + adc_c_extended_cfg_t * p_extend = (adc_c_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + /* Clear the BSP IRQ Flag */ + R_BSP_IrqStatusClear(irq); + + adc_callback_args_t args; + args.event = ADC_EVENT_SCAN_COMPLETE; + + /* Populate the context field. */ + args.p_context = p_instance_ctrl->p_context; + + uint32_t adsts = 0; + + /* Clear the trigger detection flag. */ + if (ADC_C_TRIGGER_MODE_HARDWARE == p_extend->trigger_mode) + { + adsts = (uint32_t) (1 << R_ADC_C_ADSTS_TRGS_Pos); + } + + /* Clear the interrupt cause flag. */ + adsts |= (uint32_t) (R_ADC_C_ADSTS_INTST_Msk << R_ADC_C_ADSTS_INTST_Pos); + p_instance_ctrl->p_reg->ADSTS = adsts; + + /* Dummy read the ADSTS bit. */ + volatile uint32_t dummy = p_instance_ctrl->p_reg->ADSTS; + FSP_PARAMETER_NOT_USED(dummy); + + /* Initialize the unit to 0. It is not used in this implementation. */ + args.unit = 0U; + + /* Initialize the channel to 0. It is not used in this implementation. */ + args.channel = ADC_CHANNEL_0; + + /* If a callback was provided, call it with the argument */ + if (NULL != p_instance_ctrl->p_callback) + { + r_adc_c_call_callback(p_instance_ctrl, &args); + } + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE; +} diff --git a/zephyr/rz/rz_cfg/fsp_cfg/rza/r_adc_c_cfg.h b/zephyr/rz/rz_cfg/fsp_cfg/rza/r_adc_c_cfg.h new file mode 100644 index 00000000..ae2e09dc --- /dev/null +++ b/zephyr/rz/rz_cfg/fsp_cfg/rza/r_adc_c_cfg.h @@ -0,0 +1,18 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +#ifndef R_ADC_C_CFG_H_ +#define R_ADC_C_CFG_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#define ADC_C_CFG_PARAM_CHECKING_ENABLE (BSP_CFG_PARAM_CHECKING_ENABLE) + +#ifdef __cplusplus +} +#endif +#endif /* R_ADC_C_CFG_H_ */ diff --git a/zephyr/rz/rz_cfg/fsp_cfg/rzn/r_adc_cfg.h b/zephyr/rz/rz_cfg/fsp_cfg/rzn/r_adc_cfg.h new file mode 100644 index 00000000..84517d65 --- /dev/null +++ b/zephyr/rz/rz_cfg/fsp_cfg/rzn/r_adc_cfg.h @@ -0,0 +1,18 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +#ifndef R_ADC_CFG_H_ +#define R_ADC_CFG_H_ +#define ADC_CFG_PARAM_CHECKING_ENABLE (BSP_CFG_PARAM_CHECKING_ENABLE) +#define ADC_CFG_MULTIPLEX_INTERRUPT_SUPPORTED (0) +#if ADC_CFG_MULTIPLEX_INTERRUPT_SUPPORTED + #define ADC_CFG_MULTIPLEX_INTERRUPT_ENABLE BSP_INTERRUPT_ENABLE + #define ADC_CFG_MULTIPLEX_INTERRUPT_DISABLE BSP_INTERRUPT_DISABLE +#else +#define ADC_CFG_MULTIPLEX_INTERRUPT_ENABLE +#define ADC_CFG_MULTIPLEX_INTERRUPT_DISABLE +#endif +#endif /* R_ADC_CFG_H_ */ diff --git a/zephyr/rz/rz_cfg/fsp_cfg/rzt/r_adc_cfg.h b/zephyr/rz/rz_cfg/fsp_cfg/rzt/r_adc_cfg.h new file mode 100644 index 00000000..84517d65 --- /dev/null +++ b/zephyr/rz/rz_cfg/fsp_cfg/rzt/r_adc_cfg.h @@ -0,0 +1,18 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +#ifndef R_ADC_CFG_H_ +#define R_ADC_CFG_H_ +#define ADC_CFG_PARAM_CHECKING_ENABLE (BSP_CFG_PARAM_CHECKING_ENABLE) +#define ADC_CFG_MULTIPLEX_INTERRUPT_SUPPORTED (0) +#if ADC_CFG_MULTIPLEX_INTERRUPT_SUPPORTED + #define ADC_CFG_MULTIPLEX_INTERRUPT_ENABLE BSP_INTERRUPT_ENABLE + #define ADC_CFG_MULTIPLEX_INTERRUPT_DISABLE BSP_INTERRUPT_DISABLE +#else +#define ADC_CFG_MULTIPLEX_INTERRUPT_ENABLE +#define ADC_CFG_MULTIPLEX_INTERRUPT_DISABLE +#endif +#endif /* R_ADC_CFG_H_ */ diff --git a/zephyr/rz/rz_cfg/fsp_cfg/rzv/r_adc_c_cfg.h b/zephyr/rz/rz_cfg/fsp_cfg/rzv/r_adc_c_cfg.h new file mode 100644 index 00000000..b741702f --- /dev/null +++ b/zephyr/rz/rz_cfg/fsp_cfg/rzv/r_adc_c_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_ADC_C_CFG_H_ +#define R_ADC_C_CFG_H_ +#define ADC_C_CFG_PARAM_CHECKING_ENABLE (BSP_CFG_PARAM_CHECKING_ENABLE) +#endif /* R_ADC_C_CFG_H_ */