1 /*
2 * Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 /***********************************************************************************************************************
8 * Includes <System Includes> , "Project Includes"
9 **********************************************************************************************************************/
10
11 #include "r_adc_c.h"
12
13 /**********************************************************************************************************************
14 * Macro definitions
15 **********************************************************************************************************************/
16
17 #define ADC_C_OPEN (0x41444343U)
18
19 /* A/D converter stabilization wait time. */
20 #define ADC_C_STABILIZATION_DELAY_US (1U)
21 #define ADC_C_FRQ_DIV_RATIO (4U)
22 #define ADC_C_IDLE_TIME (0U)
23 #define ADC_C_PRV_ADM0_CLEAR_ADCE (~R_ADC_C_ADM0_ADCE_Msk)
24 #define ADC_C_DATA_SIZE_BUFFER_MODE_4 (4U)
25 #define ADC_C_INTERRUPT_CHANNEL_BUFFER_MODE_4 (0x8U)
26 #define ADC_C_4_BUFFER_CHANNEL_MASK (0xFU)
27
28 /***********************************************************************************************************************
29 * Typedef definitions
30 **********************************************************************************************************************/
31
32 #if defined(__ARMCC_VERSION) || defined(__ICCARM__)
33 typedef void (BSP_CMSE_NONSECURE_CALL * adc_prv_ns_callback)(adc_callback_args_t * p_args);
34 #elif defined(__GNUC__)
35 typedef BSP_CMSE_NONSECURE_CALL void (*volatile adc_prv_ns_callback)(adc_callback_args_t * p_args);
36 #endif
37
38 /***********************************************************************************************************************
39 * Private global variables and functions
40 **********************************************************************************************************************/
41
42 static void r_adc_c_open_sub(adc_c_instance_ctrl_t * const p_instance_ctrl, adc_cfg_t const * const p_cfg);
43 static void r_adc_c_scan_cfg(adc_c_instance_ctrl_t * const p_instance_ctrl,
44 adc_c_channel_cfg_t const * const p_channel_cfg);
45 void adc_c_scan_end_isr(void);
46 static void r_adc_c_irq_enable(IRQn_Type irq, uint8_t ipl, void * p_context);
47 static void r_adc_c_irq_disable(IRQn_Type irq);
48 static int32_t r_adc_c_lowest_channel_get(uint32_t adc_mask);
49 static int32_t r_adc_c_highest_channel_get(uint32_t adc_mask);
50
51 /***********************************************************************************************************************
52 * Global Variables
53 **********************************************************************************************************************/
54
55 /** ADC Implementation of ADC. */
56 const adc_api_t g_adc_on_adc =
57 {
58 .open = R_ADC_C_Open,
59 .scanCfg = R_ADC_C_ScanCfg,
60 .infoGet = R_ADC_C_InfoGet,
61 .scanStart = R_ADC_C_ScanStart,
62 .scanGroupStart = R_ADC_C_ScanGroupStart,
63 .scanStop = R_ADC_C_ScanStop,
64 .scanStatusGet = R_ADC_C_StatusGet,
65 .read = R_ADC_C_Read,
66 .read32 = R_ADC_C_Read32,
67 .close = R_ADC_C_Close,
68 .calibrate = R_ADC_C_Calibrate,
69 .offsetSet = R_ADC_C_OffsetSet,
70 .callbackSet = R_ADC_C_CallbackSet,
71 };
72
73 /*******************************************************************************************************************//**
74 * @addtogroup ADC_C
75 * @{
76 **********************************************************************************************************************/
77
78 /***********************************************************************************************************************
79 * Functions
80 **********************************************************************************************************************/
81
82 /*******************************************************************************************************************//**
83 * Initializes the ADC module and applies configurations.
84 *
85 * @retval FSP_SUCCESS Module is ready for use.
86 * @retval FSP_ERR_ASSERTION An input argument is invalid.
87 * @retval FSP_ERR_ALREADY_OPEN The instance control structure has already been opened.
88 * @retval FSP_ERR_IRQ_BSP_DISABLED A callback is provided, but the interrupt is not enabled.
89 **********************************************************************************************************************/
R_ADC_C_Open(adc_ctrl_t * p_ctrl,adc_cfg_t const * const p_cfg)90 fsp_err_t R_ADC_C_Open (adc_ctrl_t * p_ctrl, adc_cfg_t const * const p_cfg)
91 {
92 adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl;
93
94 /* Perform parameter checking */
95 #if ADC_C_CFG_PARAM_CHECKING_ENABLE
96
97 /* Verify the pointers are valid */
98 FSP_ASSERT(NULL != p_instance_ctrl);
99
100 /* Verify the configuration parameters are valid */
101 FSP_ASSERT(NULL != p_cfg);
102
103 /* Verify this unit has not already been initialized */
104 FSP_ERROR_RETURN(ADC_C_OPEN != p_instance_ctrl->opened, FSP_ERR_ALREADY_OPEN);
105
106 /* If a callback is used, then make sure an interrupt is enabled */
107 if (NULL != p_cfg->p_callback)
108 {
109 FSP_ERROR_RETURN((p_cfg->scan_end_irq >= 0), FSP_ERR_IRQ_BSP_DISABLED);
110 }
111 #endif
112
113 /* Save configurations. */
114 p_instance_ctrl->p_cfg = p_cfg;
115 p_instance_ctrl->p_callback = p_cfg->p_callback;
116 p_instance_ctrl->p_context = p_cfg->p_context;
117 p_instance_ctrl->p_callback_memory = NULL;
118
119 /* Calculate the register base address. */
120 p_instance_ctrl->p_reg = R_ADC_C;
121
122 /* Initialize the hardware based on the configuration. */
123 r_adc_c_open_sub(p_instance_ctrl, p_cfg);
124
125 /* Enable interrupts */
126 r_adc_c_irq_enable(p_cfg->scan_end_irq, p_cfg->scan_end_ipl, p_instance_ctrl);
127
128 /* Invalid scan mask (initialized for later). */
129 p_instance_ctrl->scan_mask = 0U;
130
131 /* Mark driver as opened by initializing it to "ADCC" in its ASCII equivalent for this unit. */
132 p_instance_ctrl->opened = ADC_C_OPEN;
133
134 /* Return the error code */
135 return FSP_SUCCESS;
136 }
137
138 /*******************************************************************************************************************//**
139 * Configures the ADC_C scan parameters. Channel specific settings are set in this function. Pass a pointer to
140 * @ref adc_c_channel_cfg_t to p_channel_cfg.
141 *
142 *
143 * @retval FSP_SUCCESS Channel specific settings applied.
144 * @retval FSP_ERR_ASSERTION An input argument is invalid.
145 * @retval FSP_ERR_NOT_OPEN Unit is not open.
146 **********************************************************************************************************************/
R_ADC_C_ScanCfg(adc_ctrl_t * p_ctrl,void const * const p_channel_cfg)147 fsp_err_t R_ADC_C_ScanCfg (adc_ctrl_t * p_ctrl, void const * const p_channel_cfg)
148 {
149 adc_c_channel_cfg_t const * p_adc_channel_cfg = (adc_c_channel_cfg_t const *) p_channel_cfg;
150 adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl;
151 fsp_err_t err = FSP_SUCCESS;
152
153 #if ADC_C_CFG_PARAM_CHECKING_ENABLE
154 FSP_ASSERT(NULL != p_instance_ctrl);
155 FSP_ASSERT(NULL != p_adc_channel_cfg);
156 FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN);
157
158 /* Multiple analog input channel selection is prohibited in select mode. */
159 FSP_ASSERT(!((ADC_C_OPERATING_MODE_SELECT == p_instance_ctrl->operating_mode) &&
160 ((ADC_C_MASK_CHANNEL_0 | ADC_C_MASK_CHANNEL_1) == p_adc_channel_cfg->scan_mask)));
161 #endif
162
163 /* Configure the hardware based on the configuration. */
164 r_adc_c_scan_cfg(p_instance_ctrl, p_adc_channel_cfg);
165
166 /* Save the scan mask locally; this is required for the infoGet function. */
167 p_instance_ctrl->scan_mask = p_adc_channel_cfg->scan_mask;
168
169 /* Return the error code. */
170 return err;
171 }
172
173 /*******************************************************************************************************************//**
174 * Updates the user callback and has option of providing memory for callback structure.
175 * Implements adc_api_t::callbackSet
176 *
177 * @retval FSP_SUCCESS Callback updated successfully.
178 * @retval FSP_ERR_ASSERTION A required pointer is NULL.
179 * @retval FSP_ERR_NOT_OPEN The control block has not been opened.
180 * @retval FSP_ERR_NO_CALLBACK_MEMORY p_callback is non-secure and p_callback_memory is either secure or NULL.
181 **********************************************************************************************************************/
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)182 fsp_err_t R_ADC_C_CallbackSet (adc_ctrl_t * const p_api_ctrl,
183 void ( * p_callback)(adc_callback_args_t *),
184 void const * const p_context,
185 adc_callback_args_t * const p_callback_memory)
186 {
187 adc_c_instance_ctrl_t * p_ctrl = (adc_c_instance_ctrl_t *) p_api_ctrl;
188
189 #if (ADC_C_CFG_PARAM_CHECKING_ENABLE)
190 FSP_ASSERT(p_ctrl);
191 FSP_ASSERT(p_callback);
192 FSP_ERROR_RETURN(ADC_C_OPEN == p_ctrl->opened, FSP_ERR_NOT_OPEN);
193 #endif
194
195 /* Store callback and context */
196
197 #if BSP_TZ_SECURE_BUILD
198
199 /* Get security state of p_callback */
200 bool callback_is_secure =
201 (NULL == cmse_check_address_range((void *) p_callback, sizeof(void *), CMSE_AU_NONSECURE));
202
203 #if ADC_C_CFG_PARAM_CHECKING_ENABLE
204
205 /* In secure projects, p_callback_memory must be provided in non-secure space if p_callback is non-secure */
206 adc_callback_args_t * const p_callback_memory_checked = cmse_check_pointed_object(p_callback_memory,
207 CMSE_AU_NONSECURE);
208 FSP_ERROR_RETURN(callback_is_secure || (NULL != p_callback_memory_checked), FSP_ERR_NO_CALLBACK_MEMORY);
209 #endif
210
211 p_ctrl->p_callback = callback_is_secure ? p_callback :
212 (void (*)(adc_callback_args_t *))cmse_nsfptr_create(p_callback);
213 #else
214 p_ctrl->p_callback = p_callback;
215 #endif
216
217 p_ctrl->p_context = p_context;
218 p_ctrl->p_callback_memory = p_callback_memory;
219
220 return FSP_SUCCESS;
221 }
222
223 /*******************************************************************************************************************//**
224 * Start A/D conversion.
225 *
226 * @pre Call R_ADC_C_ScanCfg after R_ADC_C_Open before starting a scan.
227 *
228 * @retval FSP_SUCCESS Scan started (software trigger) or hardware triggers enabled.
229 * @retval FSP_ERR_ASSERTION An input argument is invalid.
230 * @retval FSP_ERR_NOT_OPEN Unit is not open.
231 * @retval FSP_ERR_NOT_INITIALIZED Unit is not initialized.
232 * @retval FSP_ERR_IN_USE Another scan is still in progress (software trigger).
233 **********************************************************************************************************************/
R_ADC_C_ScanStart(adc_ctrl_t * p_ctrl)234 fsp_err_t R_ADC_C_ScanStart (adc_ctrl_t * p_ctrl)
235 {
236 adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl;
237
238 /* Perform parameter checking */
239 #if ADC_C_CFG_PARAM_CHECKING_ENABLE
240
241 /* Verify the pointers are valid */
242 FSP_ASSERT(NULL != p_instance_ctrl);
243 FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN);
244 FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->initialized, FSP_ERR_NOT_INITIALIZED);
245 FSP_ERROR_RETURN(0U == p_instance_ctrl->p_reg->ADM0_b.ADCE, FSP_ERR_IN_USE);
246 #endif
247
248 /* Start A/D conversion. */
249 p_instance_ctrl->p_reg->ADM0 = p_instance_ctrl->scan_start;
250
251 return FSP_SUCCESS;
252 }
253
254 /*******************************************************************************************************************//**
255 * @ref adc_api_t::scanGroupStart is not supported. Use scanStart instead.
256 *
257 * @retval FSP_ERR_UNSUPPORTED Function not supported in this implementation.
258 **********************************************************************************************************************/
R_ADC_C_ScanGroupStart(adc_ctrl_t * p_ctrl,adc_group_mask_t group_id)259 fsp_err_t R_ADC_C_ScanGroupStart (adc_ctrl_t * p_ctrl, adc_group_mask_t group_id)
260 {
261 FSP_PARAMETER_NOT_USED(p_ctrl);
262 FSP_PARAMETER_NOT_USED(group_id);
263
264 /* Return the unsupported error. */
265 return FSP_ERR_UNSUPPORTED;
266 }
267
268 /*******************************************************************************************************************//**
269 * Stop A/D conversion.
270 *
271 * @retval FSP_SUCCESS Scan stopped (software trigger) or hardware triggers disabled.
272 * @retval FSP_ERR_ASSERTION An input argument is invalid.
273 * @retval FSP_ERR_NOT_OPEN Unit is not open.
274 * @retval FSP_ERR_NOT_INITIALIZED Unit is not initialized.
275 **********************************************************************************************************************/
R_ADC_C_ScanStop(adc_ctrl_t * p_ctrl)276 fsp_err_t R_ADC_C_ScanStop (adc_ctrl_t * p_ctrl)
277 {
278 adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl;
279
280 /* Perform parameter checking */
281 #if ADC_C_CFG_PARAM_CHECKING_ENABLE
282
283 /* Verify the pointers are valid */
284 FSP_ASSERT(NULL != p_instance_ctrl);
285 FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN);
286 FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->initialized, FSP_ERR_NOT_INITIALIZED);
287 #endif
288
289 /* Stop A/D conversion. */
290 p_instance_ctrl->p_reg->ADM0 = (uint32_t) (p_instance_ctrl->scan_start & ADC_C_PRV_ADM0_CLEAR_ADCE);
291
292 /* Read ADM0 register to confirm that A/D conversion is stopped. */
293 FSP_HARDWARE_REGISTER_WAIT(p_instance_ctrl->p_reg->ADM0_b.ADCE, 0U);
294
295 return FSP_SUCCESS;
296 }
297
298 /*******************************************************************************************************************//**
299 * Get current ADC_C status and store it in provided pointer p_status.
300 *
301 * @retval FSP_SUCCESS Module status stored in the provided pointer p_status
302 * @retval FSP_ERR_ASSERTION An input argument is invalid.
303 * @retval FSP_ERR_NOT_OPEN Unit is not open.
304 **********************************************************************************************************************/
R_ADC_C_StatusGet(adc_ctrl_t * p_ctrl,adc_status_t * p_status)305 fsp_err_t R_ADC_C_StatusGet (adc_ctrl_t * p_ctrl, adc_status_t * p_status)
306 {
307 adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl;
308
309 #if ADC_C_CFG_PARAM_CHECKING_ENABLE
310 FSP_ASSERT(NULL != p_instance_ctrl);
311 FSP_ASSERT(NULL != p_status);
312 FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN);
313 #endif
314
315 /* Read the status of the ADBSY bit. ADBSY is set when a scan is in progress. */
316 p_status->state = (adc_state_t) p_instance_ctrl->p_reg->ADM0_b.ADBSY;
317
318 /* Return the error code */
319 return FSP_SUCCESS;
320 }
321
322 /*******************************************************************************************************************//**
323 * Reads conversion results from a single channel or sensor.
324 *
325 * @retval FSP_SUCCESS Data read into provided p_data.
326 * @retval FSP_ERR_ASSERTION An input argument is invalid.
327 * @retval FSP_ERR_NOT_OPEN Unit is not open.
328 * @retval FSP_ERR_NOT_INITIALIZED Unit is not initialized.
329 **********************************************************************************************************************/
R_ADC_C_Read(adc_ctrl_t * p_ctrl,adc_channel_t const reg_id,uint16_t * const p_data)330 fsp_err_t R_ADC_C_Read (adc_ctrl_t * p_ctrl, adc_channel_t const reg_id, uint16_t * const p_data)
331 {
332 adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl;
333
334 /* Perform parameter checking. */
335 #if ADC_C_CFG_PARAM_CHECKING_ENABLE
336
337 /* Verify the pointers are valid */
338 FSP_ASSERT(NULL != p_instance_ctrl);
339 FSP_ASSERT(NULL != p_data);
340 FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN);
341 FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->initialized, FSP_ERR_NOT_INITIALIZED);
342
343 /* Verify that the channel is valid for this MCU */
344 uint32_t requested_channel_mask = (1U << (uint32_t) reg_id);
345 FSP_ASSERT(0 != (requested_channel_mask & BSP_FEATURE_ADC_C_VALID_CHANNEL_MASK));
346 #endif
347
348 /* Read the data from the requested ADC conversion register and return it */
349 *p_data = *((uint16_t *) (&p_instance_ctrl->p_reg->ADCR0 + reg_id));
350
351 /* Return the error code */
352 return FSP_SUCCESS;
353 }
354
355 /*******************************************************************************************************************//**
356 * Reads conversion results from a single channel or sensor register into a 32-bit result.
357 *
358 * @retval FSP_SUCCESS Data read into provided p_data.
359 * @retval FSP_ERR_ASSERTION An input argument is invalid.
360 * @retval FSP_ERR_NOT_OPEN Unit is not open.
361 * @retval FSP_ERR_NOT_INITIALIZED Unit is not initialized.
362 **********************************************************************************************************************/
R_ADC_C_Read32(adc_ctrl_t * p_ctrl,adc_channel_t const reg_id,uint32_t * const p_data)363 fsp_err_t R_ADC_C_Read32 (adc_ctrl_t * p_ctrl, adc_channel_t const reg_id, uint32_t * const p_data)
364 {
365 uint16_t result = 0U;
366 uint32_t result_32 = 0U;
367
368 #if ADC_C_CFG_PARAM_CHECKING_ENABLE
369 FSP_ASSERT(NULL != p_data);
370 #endif
371
372 fsp_err_t err = R_ADC_C_Read(p_ctrl, reg_id, &result);
373 FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
374
375 result_32 = result;
376 *p_data = result_32;
377
378 return FSP_SUCCESS;
379 }
380
381 /*******************************************************************************************************************//**
382 * Sets the sample state count for individual channels. This only needs to be set for special use cases. Normally, use
383 * the default values out of reset.
384 *
385 * @note The sample states for the temperature and voltage sensor are set in R_ADC_C_ScanCfg.
386 *
387 * @retval FSP_SUCCESS Sample state count updated.
388 * @retval FSP_ERR_ASSERTION An input argument is invalid.
389 * @retval FSP_ERR_NOT_INITIALIZED Unit is not initialized.
390 * @retval FSP_ERR_NOT_OPEN Unit is not open.
391 * @retval FSP_ERR_IN_USE A/D conversion ongoing.
392 **********************************************************************************************************************/
R_ADC_C_SampleStateCountSet(adc_ctrl_t * p_ctrl,uint16_t num_states)393 fsp_err_t R_ADC_C_SampleStateCountSet (adc_ctrl_t * p_ctrl, uint16_t num_states)
394 {
395 adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl;
396 fsp_err_t err = FSP_SUCCESS;
397
398 /* Perform parameter checking */
399 #if ADC_C_CFG_PARAM_CHECKING_ENABLE
400
401 /* Verify the pointers are valid */
402 FSP_ASSERT(NULL != p_instance_ctrl);
403 FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN);
404 FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->initialized, FSP_ERR_NOT_INITIALIZED);
405 FSP_ERROR_RETURN(0 == p_instance_ctrl->p_reg->ADM0_b.ADBSY, FSP_ERR_IN_USE);
406
407 /* Verify the arguments are within the expected range. */
408 FSP_ASSERT((num_states >= BSP_FEATURE_ADC_C_SAMPLE_STATE_COUNT_MIN) &&
409 (num_states <= BSP_FEATURE_ADC_C_SAMPLE_STATE_COUNT_MAX));
410 #endif
411
412 /* Set the sample state count for the specified register */
413 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);
414 p_instance_ctrl->p_reg->ADM3 = adm3;
415
416 /* Return the error code */
417 return err;
418 }
419
420 /*******************************************************************************************************************//**
421 * Returns the address of the lowest number configured channel and the total number of bytes to be read in order to
422 * read the results of the configured channels. If no channels are configured, then a length of 0 is returned.
423 *
424 *
425 * @retval FSP_SUCCESS Information stored in p_adc_info.
426 * @retval FSP_ERR_ASSERTION An input argument is invalid.
427 * @retval FSP_ERR_NOT_OPEN Unit is not open.
428 **********************************************************************************************************************/
R_ADC_C_InfoGet(adc_ctrl_t * p_ctrl,adc_info_t * p_adc_info)429 fsp_err_t R_ADC_C_InfoGet (adc_ctrl_t * p_ctrl, adc_info_t * p_adc_info)
430 {
431 adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl;
432 fsp_err_t err = FSP_SUCCESS;
433 uint32_t adc_mask = 0;
434
435 #if ADC_C_CFG_PARAM_CHECKING_ENABLE
436 FSP_ASSERT(NULL != p_instance_ctrl);
437 FSP_ASSERT(NULL != p_adc_info);
438 FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN);
439 #endif
440
441 adc_c_extended_cfg_t * p_extend = (adc_c_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend;
442
443 /* Retrieve the scan mask of active channels from the control structure */
444 adc_mask = p_instance_ctrl->scan_mask;
445
446 if (ADC_C_BUFFER_MODE_4 == p_extend->buffer_mode)
447 {
448 p_adc_info->length = ADC_C_DATA_SIZE_BUFFER_MODE_4;
449 p_adc_info->p_address = &p_instance_ctrl->p_reg->ADCR0;
450 }
451 else
452 {
453 /* If at least one channel is configured, determine the highest and lowest configured channels. */
454 if (adc_mask != 0U)
455 {
456 uint32_t adc_mask_in_order = adc_mask;
457 int32_t lowest_channel = r_adc_c_lowest_channel_get(adc_mask_in_order);
458
459 p_adc_info->p_address = (uint32_t *) (&p_instance_ctrl->p_reg->ADCR0 + lowest_channel);
460
461 /* Determine the highest channel that is configured. */
462 int32_t highest_channel = r_adc_c_highest_channel_get(adc_mask_in_order);
463
464 /* Determine the size of data that must be read to read all the channels between and including the
465 * highest and lowest channels.*/
466 p_adc_info->length = (uint32_t) ((highest_channel - lowest_channel) + 1);
467 }
468 else
469 {
470 /* If no channels are configured, set the return length 0. */
471 p_adc_info->length = 0U;
472 }
473 }
474
475 p_adc_info->transfer_size = TRANSFER_SIZE_2_BYTE;
476
477 #if BSP_FEATURE_ADC_C_TSU_CONTROL_AVAILABLE
478
479 /* Read into memory. */
480 p_adc_info->calibration_data1 = R_TSU->OTPTSUTRIM0_REG_b.OTPTSUTRIM0;
481 p_adc_info->calibration_data2 = R_TSU->OTPTSUTRIM1_REG_b.OTPTSUTRIM1;
482 #else
483
484 /* Set Temp Sensor calibration data to invalid value */
485 p_adc_info->calibration_data1 = UINT32_MAX;
486 p_adc_info->calibration_data2 = UINT32_MAX;
487 #endif
488
489 return err;
490 }
491
492 /*******************************************************************************************************************//**
493 * This function ends any scan in progress, disables interrupts, and removes power to the A/D peripheral.
494 *
495 * @retval FSP_SUCCESS Module closed.
496 * @retval FSP_ERR_ASSERTION An input argument is invalid.
497 * @retval FSP_ERR_NOT_OPEN Unit is not open.
498 **********************************************************************************************************************/
R_ADC_C_Close(adc_ctrl_t * p_ctrl)499 fsp_err_t R_ADC_C_Close (adc_ctrl_t * p_ctrl)
500 {
501 adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) p_ctrl;
502
503 #if ADC_C_CFG_PARAM_CHECKING_ENABLE
504 FSP_ASSERT(NULL != p_instance_ctrl);
505 FSP_ERROR_RETURN(ADC_C_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN);
506 #endif
507
508 /* Mark driver as closed */
509 p_instance_ctrl->opened = 0U;
510 p_instance_ctrl->initialized = 0U;
511
512 /* Disable interrupts. */
513 r_adc_c_irq_disable(p_instance_ctrl->p_cfg->scan_end_irq);
514
515 /* Stop the ADC. */
516 p_instance_ctrl->p_reg->ADM0 = 0U;
517
518 /* Read ADM0 register to confirm that A/D conversion is stopped. */
519 FSP_HARDWARE_REGISTER_WAIT(p_instance_ctrl->p_reg->ADM0_b.ADCE, 0U);
520
521 /* Clear the interrupt cause flag and trigger detection flag. */
522 uint32_t adsts = (uint32_t) (1 << R_ADC_C_ADSTS_TRGS_Pos);
523 adsts |= (uint32_t) (BSP_FEATURE_ADC_C_VALID_CHANNEL_MASK << R_ADC_C_ADSTS_INTST_Pos);
524 p_instance_ctrl->p_reg->ADSTS = adsts;
525
526 R_BSP_MODULE_STOP(FSP_IP_ADC, 0);
527
528 if (p_instance_ctrl->scan_mask & ADC_C_MASK_CHANNEL_8)
529 {
530 #if BSP_FEATURE_ADC_C_TSU_CONTROL_AVAILABLE
531
532 /* Set the temperature sensor to place in the standby mode. */
533 R_TSU->TSU_SM = 0;
534
535 /* Stop the TSU. */
536 R_BSP_MODULE_STOP(FSP_IP_TSU, 0);
537 #endif
538 }
539
540 /* Return the error code */
541 return FSP_SUCCESS;
542 }
543
544 /*******************************************************************************************************************//**
545 * @ref adc_api_t::calibrate is not supported.
546 *
547 * @retval FSP_ERR_UNSUPPORTED Calibration not supported on this MCU.
548 **********************************************************************************************************************/
R_ADC_C_Calibrate(adc_ctrl_t * const p_ctrl,void const * p_extend)549 fsp_err_t R_ADC_C_Calibrate (adc_ctrl_t * const p_ctrl, void const * p_extend)
550 {
551 FSP_PARAMETER_NOT_USED(p_ctrl);
552 FSP_PARAMETER_NOT_USED(p_extend);
553
554 /* Return the unsupported error. */
555 return FSP_ERR_UNSUPPORTED;
556 }
557
558 /*******************************************************************************************************************//**
559 * @ref adc_api_t::offsetSet is not supported.
560 *
561 * @retval FSP_ERR_UNSUPPORTED Function not supported in this implementation.
562 **********************************************************************************************************************/
R_ADC_C_OffsetSet(adc_ctrl_t * const p_ctrl,adc_channel_t const reg_id,int32_t offset)563 fsp_err_t R_ADC_C_OffsetSet (adc_ctrl_t * const p_ctrl, adc_channel_t const reg_id, int32_t offset)
564 {
565 FSP_PARAMETER_NOT_USED(p_ctrl);
566 FSP_PARAMETER_NOT_USED(reg_id);
567 FSP_PARAMETER_NOT_USED(offset);
568
569 /* Return the unsupported error. */
570 return FSP_ERR_UNSUPPORTED;
571 }
572
573 /*******************************************************************************************************************//**
574 * @} (end addtogroup ADC_C)
575 **********************************************************************************************************************/
576
577 /***********************************************************************************************************************
578 * Private Functions
579 **********************************************************************************************************************/
580
581 /*******************************************************************************************************************//**
582 * The Open function applies power to the A/D peripheral, sets the value for ADM0, ADM1, ADM3, ADIVC, ADFIL.
583 *
584 * @param[in] p_instance_ctrl Pointer to instance control block
585 * @param[in] p_cfg Pointer to configuration structure
586 **********************************************************************************************************************/
r_adc_c_open_sub(adc_c_instance_ctrl_t * const p_instance_ctrl,adc_cfg_t const * const p_cfg)587 static void r_adc_c_open_sub (adc_c_instance_ctrl_t * const p_instance_ctrl, adc_cfg_t const * const p_cfg)
588 {
589 adc_c_extended_cfg_t const * p_cfg_extend = (adc_c_extended_cfg_t const *) p_cfg->p_extend;
590
591 /* Determine the value for ADM0, ADM1, ADM3, ADIVC, ADFIL.:
592 * The value to set in ADCSR to start a scan is stored in the control structure.
593 * ADM0.ADCE is set in R_ADC_ScanStart.
594 *//* Sets the trigger mode. */
595 uint32_t adm1 = (uint32_t) (p_cfg_extend->trigger_mode << R_ADC_C_ADM1_TRG_Pos);
596
597 /* When using hardware trigger mode, set the hardware trigger signal parameter. */
598 if (ADC_C_TRIGGER_MODE_HARDWARE == p_cfg_extend->trigger_mode)
599 {
600 adm1 |= (uint32_t) (p_cfg_extend->trigger_source << R_ADC_C_ADM1_TRGEN_Pos);
601 adm1 |= (uint32_t) (p_cfg_extend->input_mode << R_ADC_C_ADM1_TRGIN_Pos);
602
603 /* The trigger edge setting is valid only when the trigger source is ADC_TRG.
604 * Reference section "A/D Converter Mode Register 1 (ADM1)" of the user's manual. */
605 if (ADC_C_ACTIVE_TRIGGER_EXTERNAL == p_cfg_extend->trigger_source)
606 {
607 adm1 |= (uint32_t) (p_cfg_extend->trigger_edge << R_ADC_C_ADM1_EGA_Pos);
608 }
609 /* Otherwise falling edge is always valid. */
610 else
611 {
612 adm1 |= (uint32_t) (ADC_C_TRIGGER_EDGE_FALLING << R_ADC_C_ADM1_EGA_Pos);
613 }
614 }
615 else
616 {
617 /* Do nothing. */
618 }
619
620 /* Sets the operating mode and buffer mode. */
621 adm1 |= (uint32_t) (p_cfg_extend->operating_mode << R_ADC_C_ADM1_MS_Pos);
622
623 /* 1-Buffer mode and 4-Buffer mode can be set when using select mode. */
624 if (ADC_C_OPERATING_MODE_SELECT == p_cfg_extend->operating_mode)
625 {
626 adm1 |= (uint32_t) (p_cfg_extend->buffer_mode << R_ADC_C_ADM1_BS_Pos);
627 }
628
629 /* Repeat mode corresponds to ADC_MODE_CONTINUOUS_SCAN of API,
630 * but since the API value (=2) and repeat mode register setting value (=1) are different,
631 * it is necessary to convert them.
632 * Sets the conversion mode. */
633 adm1 |= (uint32_t) ((p_cfg->mode >> 1U) << R_ADC_C_ADM1_RPS_Pos);
634
635 #if BSP_FEATURE_ADC_C_HAS_ADIVC
636
637 /* Sets the frequency division ratio for dividing the frequency of ADC_ADCLK(TSUϕ). */
638 uint32_t adivc = (uint32_t) (ADC_C_FRQ_DIV_RATIO << R_ADC_C_ADIVC_DIVADC_Pos);
639 #endif
640
641 uint32_t adfil = 0;
642
643 /* Enables or disables the AD external trigger pin filter. */
644 if (ADC_C_FILTER_STAGE_SETTING_DISABLE != p_cfg_extend->external_trigger_filter)
645 {
646 adfil = (uint32_t) (1 << R_ADC_C_ADFIL_FILONOFF_Pos);
647
648 /* Set the number of stages of the AD external trigger pin filter. */
649 adfil |= (uint32_t) ((p_cfg_extend->external_trigger_filter - 1) << R_ADC_C_ADFIL_FILNUM_Pos);
650 }
651 else
652 {
653 /* Do nothing. */
654 }
655
656 /* Set the idle period. */
657 uint32_t adm3 = (uint32_t) (ADC_C_IDLE_TIME << R_ADC_C_ADM3_ADIL_Pos);
658
659 /* Set the conversion period and sampling period. */
660 adm3 |= (uint32_t) (BSP_FEATURE_ADC_C_CONVERSION_TIME << R_ADC_C_ADM3_ADCMP_Pos);
661 adm3 |= (uint32_t) (p_cfg_extend->sampling_time << R_ADC_C_ADM3_ADSMP_Pos);
662
663 /* Apply clock to peripheral. */
664 R_BSP_MODULE_START(FSP_IP_ADC, 0);
665
666 /* The following series of steps refer to "A/D conversion start procedure" in the user's manual. */
667 /* Release from software reset state. */
668 uint32_t adm0 = (uint32_t) (1 << R_ADC_C_ADM0_SRESB_Pos);
669 p_instance_ctrl->p_reg->ADM0 = adm0;
670
671 /* The waiting time until the reset state of the A/D converter is released is 2 × ADC_ADCLK(TSUϕ) (80 MHz),
672 * but since the minimum waiting time of R_BSP_SoftwareDelay is 1us,
673 * processing is executed with a waiting time of 1us. */
674 R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MICROSECONDS);
675
676 /* Clear the interrupt cause flag and trigger detection flag. */
677 uint32_t adsts = (uint32_t) (1 << R_ADC_C_ADSTS_TRGS_Pos);
678 adsts |= (uint32_t) (BSP_FEATURE_ADC_C_VALID_CHANNEL_MASK << R_ADC_C_ADSTS_INTST_Pos);
679 p_instance_ctrl->p_reg->ADSTS = adsts;
680
681 /* Set the predetermined values for ADM1, ADM3, ADINT, ADIVC, and ADFIL.
682 * ADM0.ADCE are set as configured in R_ADC_ScanStart. */
683 p_instance_ctrl->p_reg->ADM1 = adm1;
684 p_instance_ctrl->p_reg->ADM3 = adm3;
685 #if BSP_FEATURE_ADC_C_HAS_ADIVC
686 p_instance_ctrl->p_reg->ADIVC = adivc;
687 #endif
688 p_instance_ctrl->p_reg->ADFIL = adfil;
689
690 /* Change from power-saving mode to normal mode. */
691 adm0 |= (uint32_t) (1 << R_ADC_C_ADM0_PWDWNB_Pos);
692 p_instance_ctrl->p_reg->ADM0 = adm0;
693
694 /* Secure the A/D converter stabilization wait time. */
695 R_BSP_SoftwareDelay(ADC_C_STABILIZATION_DELAY_US, BSP_DELAY_UNITS_MICROSECONDS);
696
697 /* Set the ADCE bit. */
698 adm0 |= (uint32_t) (R_ADC_C_ADM0_ADCE_Msk);
699
700 p_instance_ctrl->scan_start = adm0;
701
702 /* Save the operating mode and buffer mode locally; this is required for the Scancfg function. */
703 p_instance_ctrl->operating_mode = p_cfg_extend->operating_mode;
704 p_instance_ctrl->buffer_mode = p_cfg_extend->buffer_mode;
705 }
706
707 /*******************************************************************************************************************//**
708 * This function does extensive checking on channel mask settings based upon operational mode. Mask registers are
709 * initialized and interrupts enabled in peripheral. Interrupts are also enabled in ICU if corresponding priority
710 * is not 0.
711 *
712 * @param[in] p_instance_ctrl Pointer to instance control block
713 * @param[in] p_channel_cfg Pointer to channel configuration
714 **********************************************************************************************************************/
r_adc_c_scan_cfg(adc_c_instance_ctrl_t * const p_instance_ctrl,adc_c_channel_cfg_t const * const p_channel_cfg)715 static void r_adc_c_scan_cfg (adc_c_instance_ctrl_t * const p_instance_ctrl,
716 adc_c_channel_cfg_t const * const p_channel_cfg)
717 {
718 if (p_channel_cfg->scan_mask & ADC_C_MASK_CHANNEL_8)
719 {
720 #if BSP_FEATURE_ADC_C_TSU_CONTROL_AVAILABLE
721
722 /* Apply clock to peripheral. */
723 R_BSP_MODULE_START(FSP_IP_TSU, 0);
724
725 /* Set the temperature sensor to place in the normal operating mode. */
726 R_TSU->TSU_SM = R_TSU_TSU_SM_EN_Msk;
727
728 /* Wait 30us. See the TSU "Operation" section of the RZ microprocessor manual. */
729 R_BSP_SoftwareDelay(BSP_FEATURE_ADC_C_TSU_ENABLE_STABILIZATION_TIME_US, BSP_DELAY_UNITS_MICROSECONDS);
730
731 /* Enable the temperature sensor. */
732 R_TSU->TSU_SM |= R_TSU_TSU_SM_OE_Msk;
733
734 /* Wait 1000us. See the TSU "Operation" section of the RZ microprocessor manual. */
735 R_BSP_SoftwareDelay(BSP_FEATURE_ADC_C_TSU_START_STABILIZATION_TIME_MS, BSP_DELAY_UNITS_MILLISECONDS);
736 #endif
737 }
738
739 /* Set mask for channels. */
740 p_instance_ctrl->p_reg->ADM2 = (uint32_t) (p_channel_cfg->scan_mask & (uint32_t) R_ADC_C_ADM2_CHSEL_Msk);
741
742 /* Disables the A/D conversion channel select error interrupt. */
743 uint32_t adint = (uint32_t) (0 << R_ADC_C_ADINT_CSEEN_Pos);
744
745 /* Enable or disable the conversion end interrupt of channel n (n = 0 to 3). */
746 if (ADC_C_INTERRUPT_CHANNEL_SETTING_ENABLE == p_channel_cfg->interrupt_setting)
747 {
748 /* Channel 3 interrupt output is enabled in 4-buffer mode.
749 * Reference section "Example of A/D Conversion in 4-Buffer Mode" of the user's manual.*/
750 if (ADC_C_BUFFER_MODE_4 == p_instance_ctrl->buffer_mode)
751 {
752 if (p_channel_cfg->scan_mask & ADC_C_4_BUFFER_CHANNEL_MASK)
753 {
754 adint |= (uint32_t) (R_ADC_C_ADCR0_AD3_Msk << R_ADC_C_ADINT_INTEN_Pos);
755 }
756 else if (p_channel_cfg->scan_mask & (ADC_C_4_BUFFER_CHANNEL_MASK << 4))
757 {
758 adint |= (uint32_t) (R_ADC_C_ADCR0_AD7_Msk << R_ADC_C_ADINT_INTEN_Pos);
759 }
760 else
761 {
762 adint |= (uint32_t) (R_ADC_C_ADCR0_AD11_Msk << R_ADC_C_ADINT_INTEN_Pos);
763 }
764 }
765 else
766 {
767 uint32_t adc_mask_in_order = p_channel_cfg->scan_mask;
768
769 /* Determine the highest channel that is configured. */
770 int32_t highest_channel = r_adc_c_highest_channel_get(adc_mask_in_order);
771
772 /* Highest channel interrupt output is enabled. */
773 adint |= (uint32_t) (1U << highest_channel);
774 }
775 }
776 else
777 {
778 /* Do nothing. */
779 }
780
781 p_instance_ctrl->p_reg->ADINT = adint;
782
783 p_instance_ctrl->initialized = ADC_C_OPEN;
784 }
785
786 /*******************************************************************************************************************//**
787 * Disables and clears context for the requested IRQ.
788 *
789 * @param[in] irq IRQ to enable
790 * @param[in] ipl Interrupt priority
791 * @param[in] p_context Pointer to interrupt context
792 **********************************************************************************************************************/
r_adc_c_irq_enable(IRQn_Type irq,uint8_t ipl,void * p_context)793 static void r_adc_c_irq_enable (IRQn_Type irq, uint8_t ipl, void * p_context)
794 {
795 if (irq >= 0)
796 {
797 R_BSP_IrqCfgEnable(irq, ipl, p_context);
798 }
799 }
800
801 /*******************************************************************************************************************//**
802 * Disables and clears context for the requested IRQ.
803 *
804 * @param[in] irq IRQ to disable
805 **********************************************************************************************************************/
r_adc_c_irq_disable(IRQn_Type irq)806 static void r_adc_c_irq_disable (IRQn_Type irq)
807 {
808 if (irq >= 0)
809 {
810 R_BSP_IrqDisable(irq);
811 R_FSP_IsrContextSet(irq, NULL);
812 }
813 }
814
815 /*******************************************************************************************************************//**
816 * Returns the lowest channel index that is configured in order to read the results of the configured channels.
817 *
818 * @param[in] adc_mask scan mask of active channels retrieved from the control structure
819 *
820 * @retval adc_mask_count index value of lowest channel
821 **********************************************************************************************************************/
r_adc_c_lowest_channel_get(uint32_t adc_mask)822 static int32_t r_adc_c_lowest_channel_get (uint32_t adc_mask)
823 {
824 /* Initialize the mask result */
825 uint32_t adc_mask_result = 0U;
826 int32_t adc_mask_count = -1;
827 while (0U == adc_mask_result)
828 {
829 /* Increment channel until a channel is found in the mask. */
830 adc_mask_count++;
831 adc_mask_result = (uint32_t) (adc_mask & (1U << adc_mask_count));
832 }
833
834 return adc_mask_count;
835 }
836
837 /*******************************************************************************************************************//**
838 * Returns the highest channel index that is configured in order to read the results of the configured channels.
839 *
840 * @param[in] adc_mask scan mask of active channels retrieved from the control structure
841 *
842 * @retval adc_mask_count index value of highest channel
843 **********************************************************************************************************************/
r_adc_c_highest_channel_get(uint32_t adc_mask)844 static int32_t r_adc_c_highest_channel_get (uint32_t adc_mask)
845 {
846 /* Initialize the mask result */
847 uint32_t adc_mask_result = 0U;
848 int32_t adc_mask_count = 31;
849 while (0U == adc_mask_result)
850 {
851 /* Decrement channel until a channel is found in the mask. */
852 adc_mask_count--;
853 adc_mask_result = (uint32_t) (adc_mask & (1U << adc_mask_count));
854 }
855
856 return adc_mask_count;
857 }
858
859 /*******************************************************************************************************************//**
860 * Calls user callback.
861 *
862 * @param[in] p_ctrl Pointer to ADC instance control block
863 * @param[in] p_args Pointer to arguments on stack
864 **********************************************************************************************************************/
r_adc_c_call_callback(adc_c_instance_ctrl_t * p_ctrl,adc_callback_args_t * p_args)865 static void r_adc_c_call_callback (adc_c_instance_ctrl_t * p_ctrl, adc_callback_args_t * p_args)
866 {
867 adc_callback_args_t args;
868
869 /* Store callback arguments in memory provided by user if available. This allows callback arguments to be
870 * stored in non-secure memory so they can be accessed by a non-secure callback function. */
871 adc_callback_args_t * p_args_memory = p_ctrl->p_callback_memory;
872 if (NULL == p_args_memory)
873 {
874 /* Use provided args struct on stack */
875 p_args_memory = p_args;
876 }
877 else
878 {
879 /* Save current arguments on the stack in case this is a nested interrupt. */
880 args = *p_args_memory;
881
882 /* Copy the stacked args to callback memory */
883 *p_args_memory = *p_args;
884 }
885
886 #if BSP_TZ_SECURE_BUILD
887
888 /* p_callback can point to a secure function or a non-secure function. */
889 if (!cmse_is_nsfptr(p_ctrl->p_callback))
890 {
891 /* If p_callback is secure, then the project does not need to change security state. */
892 p_ctrl->p_callback(p_args_memory);
893 }
894 else
895 {
896 /* If p_callback is Non-secure, then the project must change to Non-secure state in order to call the callback. */
897 adc_prv_ns_callback p_callback = (adc_prv_ns_callback) (p_ctrl->p_callback);
898 p_callback(p_args_memory);
899 }
900
901 #else
902
903 /* If the project is not Trustzone Secure, then it will never need to change security state in order to call the callback. */
904 p_ctrl->p_callback(p_args_memory);
905 #endif
906
907 if (NULL != p_ctrl->p_callback_memory)
908 {
909 /* Restore callback memory in case this is a nested interrupt. */
910 *p_ctrl->p_callback_memory = args;
911 }
912 }
913
914 /*******************************************************************************************************************//**
915 * This function implements interrupt handler for scan complete.
916 **********************************************************************************************************************/
adc_c_scan_end_isr(void)917 void adc_c_scan_end_isr (void)
918 {
919 /* Save context if RTOS is used */
920 FSP_CONTEXT_SAVE;
921
922 IRQn_Type irq = R_FSP_CurrentIrqGet();
923 adc_c_instance_ctrl_t * p_instance_ctrl = (adc_c_instance_ctrl_t *) R_FSP_IsrContextGet(irq);
924 adc_c_extended_cfg_t * p_extend = (adc_c_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend;
925
926 /* Clear the BSP IRQ Flag */
927 R_BSP_IrqStatusClear(irq);
928
929 adc_callback_args_t args;
930 args.event = ADC_EVENT_SCAN_COMPLETE;
931
932 /* Populate the context field. */
933 args.p_context = p_instance_ctrl->p_context;
934
935 uint32_t adsts = 0;
936
937 /* Clear the trigger detection flag. */
938 if (ADC_C_TRIGGER_MODE_HARDWARE == p_extend->trigger_mode)
939 {
940 adsts = (uint32_t) (1 << R_ADC_C_ADSTS_TRGS_Pos);
941 }
942
943 /* Clear the interrupt cause flag. */
944 adsts |= (uint32_t) (R_ADC_C_ADSTS_INTST_Msk << R_ADC_C_ADSTS_INTST_Pos);
945 p_instance_ctrl->p_reg->ADSTS = adsts;
946
947 /* Dummy read the ADSTS bit. */
948 volatile uint32_t dummy = p_instance_ctrl->p_reg->ADSTS;
949 FSP_PARAMETER_NOT_USED(dummy);
950
951 /* Initialize the unit to 0. It is not used in this implementation. */
952 args.unit = 0U;
953
954 /* Initialize the channel to 0. It is not used in this implementation. */
955 args.channel = ADC_CHANNEL_0;
956
957 /* If a callback was provided, call it with the argument */
958 if (NULL != p_instance_ctrl->p_callback)
959 {
960 r_adc_c_call_callback(p_instance_ctrl, &args);
961 }
962
963 /* Restore context if RTOS is used */
964 FSP_CONTEXT_RESTORE;
965 }
966