1 /*
2 * Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6 
7 /***********************************************************************************************************************
8  * Includes
9  **********************************************************************************************************************/
10 #include "r_agt.h"
11 
12 /***********************************************************************************************************************
13  * Macro definitions
14  **********************************************************************************************************************/
15 
16 /** "AGT" in ASCII, used to determine if channel is open. */
17 #define AGT_OPEN                                (0x00414754ULL)
18 
19 #define AGT_COMPARE_MATCH_A_OUTPUT              (0x03U) ///< Enabling AGTOAn pin
20 #define AGT_COMPARE_MATCH_B_OUTPUT              (0x30U) ///< Enabling AGTOBn pin
21 
22 #define AGT_SOURCE_CLOCK_PCLKB_BITS             (0x3U)
23 
24 #define FSUB_FREQUENCY_HZ                       (32768U)
25 
26 #define AGT_PRV_CLOCK_PCLKB_DIV_8               (1U)
27 #define AGT_PRV_CLOCK_PCLKB_DIV_2               (3U)
28 
29 #define AGT_PRV_AGTMR1_TMOD_EVENT_COUNTER       (2U)
30 #define AGT_PRV_AGTMR1_TMOD_PULSE_WIDTH         (3U)
31 
32 #define AGT_PRV_AGTCR_FORCE_STOP                (0xF4U)
33 #define AGT_PRV_AGTCR_FORCE_STOP_CLEAR_FLAGS    (0x4U)
34 #define AGT_PRV_AGTCR_STATUS_FLAGS              (0xF0U)
35 #define AGT_PRV_AGTCR_STOP_TIMER                (0xF0U)
36 #define AGT_PRV_AGTCR_START_TIMER               (0xF1U)
37 
38 #define AGT_PRV_AGTCMSR_PIN_B_OFFSET            (4U)
39 #define AGT_PRV_AGTCMSR_VALID_BITS              (0x77U)
40 
41 #define AGT_PRV_MIN_CLOCK_FREQ                  (0U)
42 
43 #define AGT_PRV_CHANNEL_SIZE                    ((uint32_t) R_AGTX1_BASE - (uint32_t) R_AGTX0_BASE)
44 
45 #if BSP_FEATURE_AGT_AGTW_CHANNEL_COUNT
46  #if BSP_FEATURE_AGT_AGT_CHANNEL_COUNT
47   #define AGT_PRV_DETERMINE_IS_AGTW(p_cfg)          (((agt_extended_cfg_t const *) (p_cfg)->p_extend)-> \
48                                                      counter_bit_width == AGT_COUNTER_BIT_WIDTH_32)
49  #else
50   #define AGT_PRV_DETERMINE_IS_AGTW(p_cfg)          (true)
51  #endif
52 #else
53  #define AGT_PRV_DETERMINE_IS_AGTW(p_cfg)           (false)
54 #endif
55 
56 #define AGT_PRV_IS_AGTW(p_instance_ctrl)            ((p_instance_ctrl)->is_agtw)
57 
58 #define AGT_PRV_CHANNEL_OFFSET_AGT_AGTW(p_instance_ctrl,                                                                       \
59                                         channel)    ((uint8_t) ((AGT_PRV_IS_AGTW(p_instance_ctrl)) ? (channel) : ((            \
60                                                                                                                       channel) \
61                                                                                                                   +            \
62                                                                                                                   BSP_FEATURE_AGT_AGTW_CHANNEL_COUNT)))
63 
64 #define AGT_PRV_CTRL_PTR(p_instance_ctrl)           ((agt_prv_reg_ctrl_ptr_t) (AGT_PRV_IS_AGTW((p_instance_ctrl))      \
65                                                                                ? &(p_instance_ctrl)->p_reg->AGT32.CTRL \
66                                                                                : &(p_instance_ctrl)->p_reg->AGT16.CTRL))
67 
68 /**********************************************************************************************************************
69  * Typedef definitions
70  **********************************************************************************************************************/
71 #if defined(__ARMCC_VERSION) || defined(__ICCARM__)
72 typedef void (BSP_CMSE_NONSECURE_CALL * agt_prv_ns_callback)(timer_callback_args_t * p_args);
73 #elif defined(__GNUC__)
74 typedef BSP_CMSE_NONSECURE_CALL void (*volatile agt_prv_ns_callback)(timer_callback_args_t * p_args);
75 #endif
76 
77 typedef volatile R_AGTX0_AGT16_CTRL_Type * const agt_prv_reg_ctrl_ptr_t;
78 
79 /***********************************************************************************************************************
80  * Private function prototypes
81  **********************************************************************************************************************/
82 static void r_agt_period_register_set(agt_instance_ctrl_t * p_instance_ctrl, uint32_t period_counts);
83 
84 static void r_agt_hardware_cfg(agt_instance_ctrl_t * const p_instance_ctrl, timer_cfg_t const * const p_cfg);
85 
86 static uint32_t r_agt_clock_frequency_get(R_AGTX0_Type * p_agt_regs, bool is_agtw);
87 
88 static fsp_err_t r_agt_common_preamble(agt_instance_ctrl_t * p_instance_ctrl);
89 
90 #if AGT_CFG_PARAM_CHECKING_ENABLE
91 static fsp_err_t r_agt_open_param_checking(agt_instance_ctrl_t * p_instance_ctrl, timer_cfg_t const * const p_cfg);
92 
93 #endif
94 
95 /* ISRs. */
96 void agt_int_isr(void);
97 
98 /***********************************************************************************************************************
99  * Private global variables
100  **********************************************************************************************************************/
101 
102 /* The period for even channels must be known to calculate the frequency of odd channels if the count source is AGT
103  * underflow. */
104 static uint32_t gp_prv_agt_periods[BSP_FEATURE_AGT_AGT_CHANNEL_COUNT + BSP_FEATURE_AGT_AGTW_CHANNEL_COUNT];
105 
106 /***********************************************************************************************************************
107  * Global Variables
108  **********************************************************************************************************************/
109 
110 /** AGT Implementation of General Timer Driver  */
111 const timer_api_t g_timer_on_agt =
112 {
113     .open            = R_AGT_Open,
114     .stop            = R_AGT_Stop,
115     .start           = R_AGT_Start,
116     .reset           = R_AGT_Reset,
117     .enable          = R_AGT_Enable,
118     .disable         = R_AGT_Disable,
119     .periodSet       = R_AGT_PeriodSet,
120     .dutyCycleSet    = R_AGT_DutyCycleSet,
121     .compareMatchSet = R_AGT_CompareMatchSet,
122     .infoGet         = R_AGT_InfoGet,
123     .statusGet       = R_AGT_StatusGet,
124     .callbackSet     = R_AGT_CallbackSet,
125     .close           = R_AGT_Close,
126 };
127 
128 /*******************************************************************************************************************//**
129  * @addtogroup AGT
130  * @{
131  **********************************************************************************************************************/
132 
133 /***********************************************************************************************************************
134  * Functions
135  **********************************************************************************************************************/
136 
137 /*******************************************************************************************************************//**
138  * Initializes the AGT module instance. Implements @ref timer_api_t::open.
139  *
140  * The AGT hardware does not support one-shot functionality natively.  The one-shot feature is therefore implemented in
141  * the AGT HAL layer. For a timer configured as a one-shot timer, the timer is stopped upon the first timer expiration.
142  *
143  * The AGT implementation of the general timer can accept an optional agt_extended_cfg_t extension parameter.  For
144  * AGT, the extension specifies the clock to be used as timer source and the output pin configurations.  If the
145  * extension parameter is not specified (NULL), the default clock PCLKB is used and the output pins are disabled.
146  *
147  * Example:
148  * @snippet r_agt_example.c R_AGT_Open
149  *
150  * @retval FSP_SUCCESS                 Initialization was successful and timer has started.
151  * @retval FSP_ERR_ASSERTION           A required input pointer is NULL or the period is not in the valid range of
152  *                                     1 to 0xFFFF.
153  * @retval FSP_ERR_ALREADY_OPEN        R_AGT_Open has already been called for this p_ctrl.
154  * @retval FSP_ERR_IRQ_BSP_DISABLED    A required interrupt has not been enabled in the vector table.
155  * @retval FSP_ERR_IP_CHANNEL_NOT_PRESENT  Requested channel number is not available on AGT.
156  **********************************************************************************************************************/
R_AGT_Open(timer_ctrl_t * const p_ctrl,timer_cfg_t const * const p_cfg)157 fsp_err_t R_AGT_Open (timer_ctrl_t * const p_ctrl, timer_cfg_t const * const p_cfg)
158 {
159     agt_instance_ctrl_t * p_instance_ctrl = (agt_instance_ctrl_t *) p_ctrl;
160 
161 #if AGT_CFG_PARAM_CHECKING_ENABLE
162     fsp_err_t err = r_agt_open_param_checking(p_instance_ctrl, p_cfg);
163     FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
164 #else
165     p_instance_ctrl->p_cfg   = p_cfg;
166     p_instance_ctrl->is_agtw = AGT_PRV_DETERMINE_IS_AGTW(p_cfg);
167 #endif
168 
169 #if BSP_FEATURE_AGT_AGT_CHANNEL_COUNT && BSP_FEATURE_AGT_AGTW_CHANNEL_COUNT
170     uint32_t base_address = (uint32_t) ((AGT_PRV_IS_AGTW(p_instance_ctrl)) ? R_AGTW0 : R_AGT0);
171 #elif BSP_FEATURE_AGT_AGTW_CHANNEL_COUNT
172     uint32_t base_address = (uint32_t) R_AGTW0;
173 #else
174     uint32_t base_address = (uint32_t) R_AGT0;
175 #endif
176     uint32_t channel_base_address = base_address + (p_cfg->channel * AGT_PRV_CHANNEL_SIZE);
177     p_instance_ctrl->p_reg = (R_AGTX0_Type *) channel_base_address;
178 
179     agt_prv_reg_ctrl_ptr_t p_reg_ctrl = AGT_PRV_CTRL_PTR(p_instance_ctrl);
180 
181     /* Power on the AGT channel. */
182     R_BSP_MODULE_START(FSP_IP_AGT, AGT_PRV_CHANNEL_OFFSET_AGT_AGTW(p_instance_ctrl, p_cfg->channel));
183 
184     /* Clear AGTCR. This stops the timer if it is running and clears the flags. */
185     p_reg_ctrl->AGTCR = 0U;
186 
187     /* The timer is stopped in sync with the count clock, or in sync with PCLK in event and external count modes. */
188     FSP_HARDWARE_REGISTER_WAIT(0U, p_reg_ctrl->AGTCR_b.TCSTF);
189 
190     /* Clear AGTMR2 before AGTMR1 is set. Reference Note 3 in section 25.2.6 "AGT Mode Register 2 (AGTMR2)"
191      * of the RA6M3 manual R01UH0886EJ0100. */
192     p_reg_ctrl->AGTMR2 = 0U;
193 
194     /* Set count source and divider and configure pins. */
195     r_agt_hardware_cfg(p_instance_ctrl, p_cfg);
196 
197     /* Set period register and update duty cycle if output mode is used for one-shot or periodic mode. */
198     r_agt_period_register_set(p_instance_ctrl, p_cfg->period_counts);
199 
200     if (p_cfg->cycle_end_irq >= 0)
201     {
202         R_BSP_IrqCfgEnable(p_cfg->cycle_end_irq, p_cfg->cycle_end_ipl, p_instance_ctrl);
203     }
204 
205     /* Set callback and context pointers */
206     p_instance_ctrl->p_callback        = p_cfg->p_callback;
207     p_instance_ctrl->p_context         = p_cfg->p_context;
208     p_instance_ctrl->p_callback_memory = NULL;
209 
210     p_instance_ctrl->open = AGT_OPEN;
211 
212     /* All done.  */
213     return FSP_SUCCESS;
214 }
215 
216 /*******************************************************************************************************************//**
217  * Starts timer. Implements @ref timer_api_t::start.
218  *
219  * Example:
220  * @snippet r_agt_example.c R_AGT_Start
221  *
222  * @retval FSP_SUCCESS                 Timer started.
223  * @retval FSP_ERR_ASSERTION           p_ctrl is null.
224  * @retval FSP_ERR_NOT_OPEN            The instance control structure is not opened.
225  **********************************************************************************************************************/
R_AGT_Start(timer_ctrl_t * const p_ctrl)226 fsp_err_t R_AGT_Start (timer_ctrl_t * const p_ctrl)
227 {
228     agt_instance_ctrl_t * p_instance_ctrl = (agt_instance_ctrl_t *) p_ctrl;
229 
230     fsp_err_t err = r_agt_common_preamble(p_instance_ctrl);
231     FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
232 
233     agt_prv_reg_ctrl_ptr_t p_reg_ctrl = AGT_PRV_CTRL_PTR(p_instance_ctrl);
234 
235     /* Reload period register for one-shot timers. This must be done here instead of in the underflow interrupt because
236      * setting AGTCR.TSTOP causes AGT to be reset after 3 cycles of the count source. When the AGT count source is much
237      * slower than the core clock, 3 cycles of the count source is too long to wait in an interrupt. */
238     if (TIMER_MODE_ONE_SHOT == p_instance_ctrl->p_cfg->mode)
239     {
240         /* Set counter to period minus one. */
241         r_agt_period_register_set(p_instance_ctrl, p_instance_ctrl->period);
242     }
243 
244     /* Start timer */
245     p_reg_ctrl->AGTCR = AGT_PRV_AGTCR_START_TIMER;
246 
247 #if AGT_CFG_OUTPUT_SUPPORT_ENABLE
248 
249     /* If using output compare in one-shot mode, update the compare match registers after starting the timer. This
250      * ensures the output pin will not toggle again right after the period ends. */
251     if (TIMER_MODE_ONE_SHOT == p_instance_ctrl->p_cfg->mode)
252     {
253         /* Verify the timer is started before modifying any other AGT registers. Reference section 25.4.1 "Count
254          * Operation Start and Stop Control" in the RA6M3 manual R01UH0886EJ0100. */
255         FSP_HARDWARE_REGISTER_WAIT(1U, p_reg_ctrl->AGTCR_b.TCSTF);
256 
257         if (AGT_PRV_IS_AGTW(p_instance_ctrl))
258         {
259             p_instance_ctrl->p_reg->AGT32.AGTCMA = UINT32_MAX;
260             p_instance_ctrl->p_reg->AGT32.AGTCMB = UINT32_MAX;
261         }
262         else
263         {
264             p_instance_ctrl->p_reg->AGT16.AGTCMA = UINT16_MAX;
265             p_instance_ctrl->p_reg->AGT16.AGTCMB = UINT16_MAX;
266         }
267     }
268 #endif
269 
270     return FSP_SUCCESS;
271 }
272 
273 /*******************************************************************************************************************//**
274  * Stops the timer.  Implements @ref timer_api_t::stop.
275  *
276  * Example:
277  * @snippet r_agt_example.c R_AGT_Stop
278  *
279  * @retval FSP_SUCCESS                 Timer stopped.
280  * @retval FSP_ERR_ASSERTION           p_ctrl was NULL.
281  * @retval FSP_ERR_NOT_OPEN            The instance control structure is not opened.
282  **********************************************************************************************************************/
R_AGT_Stop(timer_ctrl_t * const p_ctrl)283 fsp_err_t R_AGT_Stop (timer_ctrl_t * const p_ctrl)
284 {
285     agt_instance_ctrl_t * p_instance_ctrl = (agt_instance_ctrl_t *) p_ctrl;
286 
287     fsp_err_t err = r_agt_common_preamble(p_instance_ctrl);
288     FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
289 
290     agt_prv_reg_ctrl_ptr_t p_reg_ctrl = AGT_PRV_CTRL_PTR(p_instance_ctrl);
291 
292     /* Stop timer */
293     p_reg_ctrl->AGTCR = AGT_PRV_AGTCR_STOP_TIMER;
294 
295     return FSP_SUCCESS;
296 }
297 
298 /*******************************************************************************************************************//**
299  * Resets the counter value to the period minus one. Implements @ref timer_api_t::reset.
300  *
301  * @retval FSP_SUCCESS                 Counter reset.
302  * @retval FSP_ERR_ASSERTION           p_ctrl is NULL
303  * @retval FSP_ERR_NOT_OPEN            The instance control structure is not opened.
304  **********************************************************************************************************************/
R_AGT_Reset(timer_ctrl_t * const p_ctrl)305 fsp_err_t R_AGT_Reset (timer_ctrl_t * const p_ctrl)
306 {
307     agt_instance_ctrl_t * p_instance_ctrl = (agt_instance_ctrl_t *) p_ctrl;
308 
309     fsp_err_t err = r_agt_common_preamble(p_instance_ctrl);
310     FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
311 
312     /* Reset counter to period minus one. */
313     if (AGT_PRV_IS_AGTW(p_instance_ctrl))
314     {
315         p_instance_ctrl->p_reg->AGT32.AGT = (uint32_t) (p_instance_ctrl->period - 1U);
316     }
317     else
318     {
319         p_instance_ctrl->p_reg->AGT16.AGT = (uint16_t) (p_instance_ctrl->period - 1U);
320     }
321 
322     return FSP_SUCCESS;
323 }
324 
325 /*******************************************************************************************************************//**
326  * Enables external event triggers that start, stop, clear, or capture the counter. Implements @ref timer_api_t::enable.
327  *
328  * Example:
329  * @snippet r_agt_example.c R_AGT_Enable
330  *
331  * @retval FSP_SUCCESS                 External events successfully enabled.
332  * @retval FSP_ERR_ASSERTION           p_ctrl was NULL.
333  * @retval FSP_ERR_NOT_OPEN            The instance is not opened.
334  **********************************************************************************************************************/
R_AGT_Enable(timer_ctrl_t * const p_ctrl)335 fsp_err_t R_AGT_Enable (timer_ctrl_t * const p_ctrl)
336 {
337     agt_instance_ctrl_t * p_instance_ctrl = (agt_instance_ctrl_t *) p_ctrl;
338 #if AGT_CFG_PARAM_CHECKING_ENABLE
339     FSP_ASSERT(NULL != p_instance_ctrl);
340     FSP_ERROR_RETURN(AGT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
341 #endif
342 
343     agt_prv_reg_ctrl_ptr_t p_reg_ctrl = AGT_PRV_CTRL_PTR(p_instance_ctrl);
344 
345     /* Reset counter to period minus one. */
346     if (AGT_PRV_IS_AGTW(p_instance_ctrl))
347     {
348         p_instance_ctrl->p_reg->AGT32.AGT = (uint32_t) (p_instance_ctrl->period - 1U);
349     }
350     else
351     {
352         p_instance_ctrl->p_reg->AGT16.AGT = (uint16_t) (p_instance_ctrl->period - 1U);
353     }
354 
355     /* Enable captures. */
356     p_reg_ctrl->AGTCR = AGT_PRV_AGTCR_START_TIMER;
357 
358     return FSP_SUCCESS;
359 }
360 
361 /*******************************************************************************************************************//**
362  * Disables external event triggers that start, stop, clear, or capture the counter. Implements @ref timer_api_t::disable.
363  *
364  * Example:
365  * @snippet r_agt_example.c R_AGT_Disable
366  *
367  * @retval FSP_SUCCESS                 External events successfully disabled.
368  * @retval FSP_ERR_ASSERTION           p_ctrl was NULL.
369  * @retval FSP_ERR_NOT_OPEN            The instance is not opened.
370  **********************************************************************************************************************/
R_AGT_Disable(timer_ctrl_t * const p_ctrl)371 fsp_err_t R_AGT_Disable (timer_ctrl_t * const p_ctrl)
372 {
373     agt_instance_ctrl_t * p_instance_ctrl = (agt_instance_ctrl_t *) p_ctrl;
374 #if AGT_CFG_PARAM_CHECKING_ENABLE
375     FSP_ASSERT(NULL != p_instance_ctrl);
376     FSP_ERROR_RETURN(AGT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
377 #endif
378 
379     agt_prv_reg_ctrl_ptr_t p_reg_ctrl = AGT_PRV_CTRL_PTR(p_instance_ctrl);
380 
381     /* Disable captures. */
382     p_reg_ctrl->AGTCR = AGT_PRV_AGTCR_STOP_TIMER;
383 
384     return FSP_SUCCESS;
385 }
386 
387 /*******************************************************************************************************************//**
388  * Updates period. The new period is updated immediately and the counter is reset to the maximum value. Implements
389  * @ref timer_api_t::periodSet.
390  *
391  * @warning If periodic output is used, the duty cycle buffer registers are updated after the period buffer register.
392  * If this function is called while the timer is running and an AGT underflow occurs during processing, the duty cycle
393  * will not be the desired 50% duty cycle until the counter underflow after processing completes.
394  *
395  * @warning Stop the timer before calling this function if one-shot output is used.
396  *
397  * Example:
398  * @snippet r_agt_example.c R_AGT_PeriodSet
399  *
400  * @retval FSP_SUCCESS                 Period value updated.
401  * @retval FSP_ERR_ASSERTION           A required pointer was NULL, or the period was not in the valid range of
402  *                                     1 to 0xFFFF.
403  * @retval FSP_ERR_NOT_OPEN            The instance control structure is not opened.
404  **********************************************************************************************************************/
R_AGT_PeriodSet(timer_ctrl_t * const p_ctrl,uint32_t const period_counts)405 fsp_err_t R_AGT_PeriodSet (timer_ctrl_t * const p_ctrl, uint32_t const period_counts)
406 {
407     agt_instance_ctrl_t * p_instance_ctrl = (agt_instance_ctrl_t *) p_ctrl;
408 
409     fsp_err_t err = r_agt_common_preamble(p_instance_ctrl);
410     FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
411 
412 #if AGT_CFG_PARAM_CHECKING_ENABLE
413     if (!AGT_PRV_IS_AGTW(p_instance_ctrl))
414     {
415         /* Validate period parameter. */
416         FSP_ASSERT(0U != period_counts);
417         FSP_ASSERT(period_counts <= AGT_MAX_PERIOD_16BIT);
418     }
419 #endif
420 
421     /* Set period. */
422     r_agt_period_register_set(p_instance_ctrl, period_counts);
423 
424     return FSP_SUCCESS;
425 }
426 
427 /*******************************************************************************************************************//**
428  * Updates duty cycle. If the timer is counting, the new duty cycle is reflected after the next counter underflow.
429  * Implements @ref timer_api_t::dutyCycleSet.
430  *
431  * Example:
432  * @snippet r_agt_example.c R_AGT_DutyCycleSet
433  *
434  * @retval FSP_SUCCESS                 Duty cycle updated.
435  * @retval FSP_ERR_ASSERTION           A required pointer was NULL, or the pin was not AGT_AGTO_AGTOA or AGT_AGTO_AGTOB.
436  * @retval FSP_ERR_INVALID_ARGUMENT    Duty cycle was not in the valid range of 0 to period (counts) - 1
437  * @retval FSP_ERR_NOT_OPEN            The instance control structure is not opened.
438  * @retval FSP_ERR_UNSUPPORTED         AGT_CFG_OUTPUT_SUPPORT_ENABLE is 0.
439  **********************************************************************************************************************/
R_AGT_DutyCycleSet(timer_ctrl_t * const p_ctrl,uint32_t const duty_cycle_counts,uint32_t const pin)440 fsp_err_t R_AGT_DutyCycleSet (timer_ctrl_t * const p_ctrl, uint32_t const duty_cycle_counts, uint32_t const pin)
441 {
442 #if AGT_CFG_OUTPUT_SUPPORT_ENABLE
443     agt_instance_ctrl_t * p_instance_ctrl = (agt_instance_ctrl_t *) p_ctrl;
444  #if AGT_CFG_PARAM_CHECKING_ENABLE
445     FSP_ASSERT((pin == AGT_OUTPUT_PIN_AGTOA) || (pin == AGT_OUTPUT_PIN_AGTOB));
446  #endif
447 
448     fsp_err_t err = r_agt_common_preamble(p_instance_ctrl);
449     FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
450 
451  #if AGT_CFG_PARAM_CHECKING_ENABLE
452     if (0U != p_instance_ctrl->period)
453     {
454         FSP_ERROR_RETURN(duty_cycle_counts < (p_instance_ctrl->period), FSP_ERR_INVALID_ARGUMENT);
455     }
456  #endif
457 
458     /* Set duty cycle. */
459     if (AGT_PRV_IS_AGTW(p_instance_ctrl))
460     {
461         volatile uint32_t * const p_agtcm = &p_instance_ctrl->p_reg->AGT32.AGTCMA;
462         p_agtcm[pin] = duty_cycle_counts;
463     }
464     else
465     {
466         volatile uint16_t * const p_agtcm = &p_instance_ctrl->p_reg->AGT16.AGTCMA;
467         p_agtcm[pin] = (uint16_t) duty_cycle_counts;
468     }
469 
470     return FSP_SUCCESS;
471 #else
472     FSP_PARAMETER_NOT_USED(p_ctrl);
473     FSP_PARAMETER_NOT_USED(duty_cycle_counts);
474     FSP_PARAMETER_NOT_USED(pin);
475 
476     FSP_RETURN(FSP_ERR_UNSUPPORTED);
477 #endif
478 }
479 
480 /*******************************************************************************************************************//**
481  * Placeholder for unsupported compareMatch function. Implements @ref timer_api_t::compareMatchSet.
482  *
483  * @retval FSP_ERR_UNSUPPORTED      AGT compare match is not supported.
484  **********************************************************************************************************************/
R_AGT_CompareMatchSet(timer_ctrl_t * const p_ctrl,uint32_t const compare_match_value,timer_compare_match_t const match_channel)485 fsp_err_t R_AGT_CompareMatchSet (timer_ctrl_t * const        p_ctrl,
486                                  uint32_t const              compare_match_value,
487                                  timer_compare_match_t const match_channel)
488 {
489     /* This function isn't supported. It is defined only to implement a required function of timer_api_t.
490      * Mark the input parameter as unused since this function isn't supported. */
491     FSP_PARAMETER_NOT_USED(p_ctrl);
492     FSP_PARAMETER_NOT_USED(compare_match_value);
493     FSP_PARAMETER_NOT_USED(match_channel);
494 
495     return FSP_ERR_UNSUPPORTED;
496 }
497 
498 /*******************************************************************************************************************//**
499  * Gets timer information and store it in provided pointer p_info. Implements @ref timer_api_t::infoGet.
500  *
501  * Example:
502  * @snippet r_agt_example.c R_AGT_InfoGet
503  *
504  * @retval FSP_SUCCESS                 Period, count direction, and frequency stored in p_info.
505  * @retval FSP_ERR_ASSERTION           A required pointer is NULL.
506  * @retval FSP_ERR_NOT_OPEN            The instance control structure is not opened.
507  **********************************************************************************************************************/
R_AGT_InfoGet(timer_ctrl_t * const p_ctrl,timer_info_t * const p_info)508 fsp_err_t R_AGT_InfoGet (timer_ctrl_t * const p_ctrl, timer_info_t * const p_info)
509 {
510     agt_instance_ctrl_t * p_instance_ctrl = (agt_instance_ctrl_t *) p_ctrl;
511 #if AGT_CFG_PARAM_CHECKING_ENABLE
512     FSP_ASSERT(NULL != p_info);
513 #endif
514 
515     fsp_err_t err = r_agt_common_preamble(p_instance_ctrl);
516     FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
517 
518     /* Get and store period */
519     p_info->period_counts = p_instance_ctrl->period;
520 
521     /* Get and store clock frequency */
522     agt_extended_cfg_t const * p_extend = (agt_extended_cfg_t const *) p_instance_ctrl->p_cfg->p_extend;
523     if (AGT_CLOCK_AGT_UNDERFLOW == p_extend->count_source)
524     {
525         /* Clock frequency of this channel is the clock frequency divided by the timer period of the source channel. */
526 
527         /* Source instance is the channel immediately preceding this one. */
528         if (0U ==
529             gp_prv_agt_periods[AGT_PRV_CHANNEL_OFFSET_AGT_AGTW(p_instance_ctrl, p_instance_ctrl->p_cfg->channel - 1)])
530         {
531             p_info->clock_frequency = AGT_PRV_MIN_CLOCK_FREQ;
532         }
533         else
534         {
535             R_AGTX0_Type * p_source_channel_reg =
536                 (R_AGTX0_Type *) ((uint32_t) p_instance_ctrl->p_reg - AGT_PRV_CHANNEL_SIZE);
537             p_info->clock_frequency =
538                 r_agt_clock_frequency_get(p_source_channel_reg, AGT_PRV_IS_AGTW(p_instance_ctrl)) /
539                 gp_prv_agt_periods[AGT_PRV_CHANNEL_OFFSET_AGT_AGTW(p_instance_ctrl,
540                                                                    p_instance_ctrl->p_cfg->channel - 1)];
541         }
542     }
543     else
544     {
545         p_info->clock_frequency = r_agt_clock_frequency_get(p_instance_ctrl->p_reg, AGT_PRV_IS_AGTW(p_instance_ctrl));
546     }
547 
548     /* AGT supports only counting down direction */
549     p_info->count_direction = TIMER_DIRECTION_DOWN;
550 
551     return FSP_SUCCESS;
552 }
553 
554 /*******************************************************************************************************************//**
555  * Retrieves the current state and counter value stores them in p_status. Implements @ref timer_api_t::statusGet.
556  *
557  * Example:
558  * @snippet r_agt_example.c R_AGT_StatusGet
559  *
560  * @retval FSP_SUCCESS                 Current status and counter value provided in p_status.
561  * @retval FSP_ERR_ASSERTION           A required pointer is NULL.
562  * @retval FSP_ERR_NOT_OPEN            The instance control structure is not opened.
563  **********************************************************************************************************************/
R_AGT_StatusGet(timer_ctrl_t * const p_ctrl,timer_status_t * const p_status)564 fsp_err_t R_AGT_StatusGet (timer_ctrl_t * const p_ctrl, timer_status_t * const p_status)
565 {
566     agt_instance_ctrl_t * p_instance_ctrl = (agt_instance_ctrl_t *) p_ctrl;
567 
568 #if AGT_CFG_PARAM_CHECKING_ENABLE
569     FSP_ASSERT(NULL != p_status);
570 #endif
571 
572     fsp_err_t err = r_agt_common_preamble(p_instance_ctrl);
573     FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
574 
575     agt_prv_reg_ctrl_ptr_t p_reg_ctrl = AGT_PRV_CTRL_PTR(p_instance_ctrl);
576 
577     /* Read the state. */
578     p_status->state = (timer_state_t) p_reg_ctrl->AGTCR_b.TCSTF;
579 
580     /* Read counter value */
581     p_status->counter =
582         AGT_PRV_IS_AGTW(p_instance_ctrl) ? p_instance_ctrl->p_reg->AGT32.AGT : p_instance_ctrl->p_reg->AGT16.AGT;
583 
584     return FSP_SUCCESS;
585 }
586 
587 /*******************************************************************************************************************//**
588  * Updates the user callback with the option to provide memory for the callback argument structure.
589  * Implements @ref timer_api_t::callbackSet.
590  *
591  * @retval  FSP_SUCCESS                  Callback updated successfully.
592  * @retval  FSP_ERR_ASSERTION            A required pointer is NULL.
593  * @retval  FSP_ERR_NOT_OPEN             The control block has not been opened.
594  * @retval  FSP_ERR_NO_CALLBACK_MEMORY   p_callback is non-secure and p_callback_memory is either secure or NULL.
595  **********************************************************************************************************************/
R_AGT_CallbackSet(timer_ctrl_t * const p_api_ctrl,void (* p_callback)(timer_callback_args_t *),void const * const p_context,timer_callback_args_t * const p_callback_memory)596 fsp_err_t R_AGT_CallbackSet (timer_ctrl_t * const          p_api_ctrl,
597                              void (                      * p_callback)(timer_callback_args_t *),
598                              void const * const            p_context,
599                              timer_callback_args_t * const p_callback_memory)
600 {
601     agt_instance_ctrl_t * p_ctrl = (agt_instance_ctrl_t *) p_api_ctrl;
602 
603 #if AGT_CFG_PARAM_CHECKING_ENABLE
604     FSP_ASSERT(p_ctrl);
605     FSP_ASSERT(p_callback);
606     FSP_ERROR_RETURN(AGT_OPEN == p_ctrl->open, FSP_ERR_NOT_OPEN);
607 #endif
608 
609 #if BSP_TZ_SECURE_BUILD
610 
611     /* Get security state of p_callback */
612     bool callback_is_secure =
613         (NULL == cmse_check_address_range((void *) p_callback, sizeof(void *), CMSE_AU_NONSECURE));
614 
615  #if AGT_CFG_PARAM_CHECKING_ENABLE
616 
617     /* In secure projects, p_callback_memory must be provided in non-secure space if p_callback is non-secure */
618     timer_callback_args_t * const p_callback_memory_checked = cmse_check_pointed_object(p_callback_memory,
619                                                                                         CMSE_AU_NONSECURE);
620     FSP_ERROR_RETURN(callback_is_secure || (NULL != p_callback_memory_checked), FSP_ERR_NO_CALLBACK_MEMORY);
621  #endif
622 #endif
623 
624     /* Store callback and context */
625 #if BSP_TZ_SECURE_BUILD
626     p_ctrl->p_callback = callback_is_secure ? p_callback :
627                          (void (*)(timer_callback_args_t *))cmse_nsfptr_create(p_callback);
628 #else
629     p_ctrl->p_callback = p_callback;
630 #endif
631     p_ctrl->p_context         = p_context;
632     p_ctrl->p_callback_memory = p_callback_memory;
633 
634     return FSP_SUCCESS;
635 }
636 
637 /*******************************************************************************************************************//**
638  * Stops counter, disables interrupts, disables output pins, and clears internal driver data.  Implements
639  * @ref timer_api_t::close.
640  *
641  *
642  *
643  * @retval FSP_SUCCESS                 Timer closed.
644  * @retval FSP_ERR_ASSERTION           p_ctrl is NULL.
645  * @retval FSP_ERR_NOT_OPEN            The instance control structure is not opened.
646  **********************************************************************************************************************/
R_AGT_Close(timer_ctrl_t * const p_ctrl)647 fsp_err_t R_AGT_Close (timer_ctrl_t * const p_ctrl)
648 {
649     agt_instance_ctrl_t * p_instance_ctrl = (agt_instance_ctrl_t *) p_ctrl;
650 
651     fsp_err_t err = r_agt_common_preamble(p_instance_ctrl);
652     FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
653 
654     agt_prv_reg_ctrl_ptr_t p_reg_ctrl = AGT_PRV_CTRL_PTR(p_instance_ctrl);
655 
656     /* Cleanup the device: Stop counter, disable interrupts, and power down if no other channels are in use. */
657 
658     /* Stop timer */
659     p_reg_ctrl->AGTCR = AGT_PRV_AGTCR_FORCE_STOP;
660 
661     /* Clear AGT output. */
662     p_reg_ctrl->AGTIOC = 0U;
663 
664     if (FSP_INVALID_VECTOR != p_instance_ctrl->p_cfg->cycle_end_irq)
665     {
666         NVIC_DisableIRQ(p_instance_ctrl->p_cfg->cycle_end_irq);
667         R_FSP_IsrContextSet(p_instance_ctrl->p_cfg->cycle_end_irq, p_instance_ctrl);
668     }
669 
670     p_instance_ctrl->open = 0U;
671 
672     return FSP_SUCCESS;
673 }
674 
675 /** @} (end addtogroup AGT) */
676 
677 /***********************************************************************************************************************
678  * Private Functions
679  **********************************************************************************************************************/
680 
681 #if AGT_CFG_PARAM_CHECKING_ENABLE
682 
683 /*******************************************************************************************************************//**
684  * Parameter checking for R_AGT_Open.
685  *
686  * @param[in] p_instance_ctrl          Pointer to instance control structure.
687  * @param[in] p_cfg                    Configuration structure for this instance
688  *
689  * @retval FSP_SUCCESS                 Initialization was successful and timer has started.
690  * @retval FSP_ERR_ASSERTION           A required input pointer is NULL or the period is not in the valid range of
691  *                                     1 to 0xFFFF.
692  * @retval FSP_ERR_ALREADY_OPEN        R_AGT_Open has already been called for this p_ctrl.
693  * @retval FSP_ERR_IRQ_BSP_DISABLED    A required interrupt has not been enabled in the vector table.
694  * @retval FSP_ERR_IP_CHANNEL_NOT_PRESENT  Requested channel number is not available on AGT.
695  **********************************************************************************************************************/
r_agt_open_param_checking(agt_instance_ctrl_t * p_instance_ctrl,timer_cfg_t const * const p_cfg)696 static fsp_err_t r_agt_open_param_checking (agt_instance_ctrl_t * p_instance_ctrl, timer_cfg_t const * const p_cfg)
697 {
698     FSP_ASSERT(NULL != p_instance_ctrl);
699     FSP_ASSERT(NULL != p_cfg);
700     FSP_ASSERT(NULL != p_cfg->p_extend);
701     FSP_ERROR_RETURN(AGT_OPEN != p_instance_ctrl->open, FSP_ERR_ALREADY_OPEN);
702 
703     /* Enable IRQ if user supplied a callback function,
704      *  or if the timer is a one-shot timer (so the driver is able to
705      *  turn off the timer after one period. */
706     if ((NULL != p_cfg->p_callback) || (TIMER_MODE_ONE_SHOT == p_cfg->mode))
707     {
708         /* Return error if IRQ is required and not in the vector table. */
709         FSP_ERROR_RETURN(p_cfg->cycle_end_irq >= 0, FSP_ERR_IRQ_BSP_DISABLED);
710     }
711 
712     /* Save pointer to config struct */
713     p_instance_ctrl->p_cfg   = p_cfg;
714     p_instance_ctrl->is_agtw = AGT_PRV_DETERMINE_IS_AGTW(p_cfg);
715 
716     if (!AGT_PRV_IS_AGTW(p_instance_ctrl))
717     {
718         FSP_ASSERT(0U != p_cfg->period_counts);
719 
720         /* Validate period parameter. */
721         FSP_ASSERT(p_cfg->period_counts <= AGT_MAX_PERIOD_16BIT);
722     }
723 
724     /* Validate channel number. */
725     FSP_ERROR_RETURN(((1U << p_cfg->channel) & BSP_FEATURE_AGT_VALID_CHANNEL_MASK), FSP_ERR_IP_CHANNEL_NOT_PRESENT);
726 
727     /* AGT_CLOCK_AGT_UNDERFLOW is not allowed on even AGT channels. */
728     agt_extended_cfg_t const * p_extend = (agt_extended_cfg_t const *) p_cfg->p_extend;
729     FSP_ASSERT((AGT_CLOCK_AGT_UNDERFLOW != p_extend->count_source) || (p_cfg->channel & 1U));
730 
731     /* Devices with RTCCR.TCEN support P402/P403/P404 as count sources. */
732  #if !BSP_FEATURE_RTC_HAS_TCEN
733     if (AGT_PRV_IS_AGTW(p_instance_ctrl))
734     {
735         /* Return error for MCUs that do not support P402, P403 and P404 as count sources*/
736         FSP_ASSERT(AGT_CLOCK_P402 != p_extend->count_source);
737         FSP_ASSERT(AGT_CLOCK_P403 != p_extend->count_source);
738         FSP_ASSERT(AGT_CLOCK_P404 != p_extend->count_source);
739     }
740  #endif
741 
742     /* Validate divider. */
743     if (AGT_CLOCK_PCLKB == p_extend->count_source)
744     {
745         /* Allowed dividers for PCLKB are 1, 2, and 8. */
746         FSP_ASSERT(p_cfg->source_div <= TIMER_SOURCE_DIV_8);
747         FSP_ASSERT(p_cfg->source_div != TIMER_SOURCE_DIV_4);
748     }
749     else if (AGT_CLOCK_AGT_UNDERFLOW == p_extend->count_source)
750     {
751         /* Divider not used if AGT0 underflow is selected as count source. */
752         FSP_ASSERT(p_cfg->source_div == TIMER_SOURCE_DIV_1);
753     }
754     else
755     {
756         /* Allowed dividers for LOCO and SUBCLOCK are 1, 2, 4, 8, 16, 32, 64, and 128. */
757         FSP_ASSERT(p_cfg->source_div <= TIMER_SOURCE_DIV_128);
758     }
759 
760     return FSP_SUCCESS;
761 }
762 
763 #endif
764 
765 /*******************************************************************************************************************//**
766  * Common code at the beginning of all AGT functions except open.
767  *
768  * @param[in] p_instance_ctrl          Pointer to instance control structure.
769  *
770  * @retval FSP_SUCCESS                 No invalid conditions detected, timer state matches expected state.
771  * @retval FSP_ERR_ASSERTION           p_ctrl is null.
772  * @retval FSP_ERR_NOT_OPEN            The instance control structure is not opened.
773  **********************************************************************************************************************/
r_agt_common_preamble(agt_instance_ctrl_t * p_instance_ctrl)774 static fsp_err_t r_agt_common_preamble (agt_instance_ctrl_t * p_instance_ctrl)
775 {
776 #if AGT_CFG_PARAM_CHECKING_ENABLE
777     FSP_ASSERT(NULL != p_instance_ctrl);
778     FSP_ERROR_RETURN(AGT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
779 #endif
780 
781     agt_prv_reg_ctrl_ptr_t p_reg_ctrl = AGT_PRV_CTRL_PTR(p_instance_ctrl);
782 
783     /* Ensure timer state reflects expected status. Reference section 25.4.1 "Count Operation Start and Stop Control"
784      * in the RA6M3 manual R01UH0886EJ0100. */
785     uint32_t agtcr_tstart = p_reg_ctrl->AGTCR_b.TSTART;
786     FSP_HARDWARE_REGISTER_WAIT(agtcr_tstart, p_reg_ctrl->AGTCR_b.TCSTF);
787 
788     return FSP_SUCCESS;
789 }
790 
791 /*******************************************************************************************************************//**
792  * Sets count source and divider.
793  *
794  * @note Counter must be stopped before entering this function.
795  *
796  * @param[in]  p_instance_ctrl    Control block for this instance
797  * @param[in]  p_cfg              Configuration structure for this instance
798  **********************************************************************************************************************/
r_agt_hardware_cfg(agt_instance_ctrl_t * const p_instance_ctrl,timer_cfg_t const * const p_cfg)799 static void r_agt_hardware_cfg (agt_instance_ctrl_t * const p_instance_ctrl, timer_cfg_t const * const p_cfg)
800 {
801     /* Update the divider for PCLKB. */
802     agt_prv_reg_ctrl_ptr_t     p_reg_ctrl = AGT_PRV_CTRL_PTR(p_instance_ctrl);
803     agt_extended_cfg_t const * p_extend   = (agt_extended_cfg_t const *) p_cfg->p_extend;
804     uint32_t count_source_int             = (uint32_t) p_extend->count_source;
805     uint32_t agtmr2  = 0U;
806     uint32_t agtcmsr = 0U;
807     uint32_t tedgsel = 0U;
808     uint32_t agtioc  = p_extend->agtio_filter;
809 
810     uint32_t mode = p_extend->measurement_mode & R_AGTX0_AGT16_CTRL_AGTMR1_TMOD_Msk;
811 
812     uint32_t edge = 0U;
813     if (AGT_CLOCK_PCLKB == p_extend->count_source)
814     {
815         if (TIMER_SOURCE_DIV_1 != p_cfg->source_div)
816         {
817             /* Toggle the second bit if the count_source_int is not 0 to map PCLKB / 8 to 1 and PCLKB / 2 to 3. */
818             count_source_int   = p_cfg->source_div ^ 2U;
819             count_source_int <<= R_AGTX0_AGT16_CTRL_AGTMR1_TCK_Pos;
820         }
821     }
822 
823 #if AGT_CFG_INPUT_SUPPORT_ENABLE
824     else if (AGT_CLOCK_AGTIO & p_extend->count_source)
825     {
826         /* If the count source is external, configure the AGT for event counter mode. */
827         mode             = AGT_PRV_AGTMR1_TMOD_EVENT_COUNTER;
828         count_source_int = 0U;
829 
830         edge              |= (p_extend->trigger_edge & R_AGTX0_AGT16_CTRL_AGTMR1_TEDGPL_Msk);
831         agtioc            |= (p_extend->enable_pin & R_AGTX0_AGT16_CTRL_AGTIOC_TIOGT_Msk);
832         p_reg_ctrl->AGTISR = (p_extend->enable_pin & R_AGTX0_AGT16_CTRL_AGTISR_EEPS_Msk);
833         if (AGT_PRV_IS_AGTW(p_instance_ctrl) && BSP_FEATURE_AGT_USE_AGTIOSEL_ALT)
834         {
835             /* The ALT register is only used for devices with an AGTW whose AGTIOSEL is at offset 0x0F. */
836             p_reg_ctrl->AGTIOSEL_ALT = (uint8_t) (p_extend->count_source & (uint8_t) ~AGT_CLOCK_AGTIO);
837         }
838         else
839         {
840             p_reg_ctrl->AGTIOSEL = (uint8_t) (p_extend->count_source & (uint8_t) ~AGT_CLOCK_AGTIO);
841         }
842     }
843 #endif
844     else if (AGT_CLOCK_AGT_UNDERFLOW != p_extend->count_source)
845     {
846         /* Update the divider for LOCO/subclock. */
847         agtmr2 = p_cfg->source_div;
848     }
849     else
850     {
851         /* No divider can be used when count source is AGT_CLOCK_AGT_UNDERFLOW. */
852     }
853 
854     uint32_t agtmr1 = (count_source_int | edge) | mode;
855 
856     /* Configure output settings. */
857 
858 #if AGT_CFG_OUTPUT_SUPPORT_ENABLE
859 
860     /* Set output if requested */
861     agtcmsr = p_extend->agtoab_settings & AGT_PRV_AGTCMSR_VALID_BITS;
862 
863     /* Set initial duty cycle for PWM mode in open.  Duty cycle is set for other modes in r_agt_period_register_set. */
864     if (TIMER_MODE_PWM == p_instance_ctrl->p_cfg->mode)
865     {
866         uint32_t inverted_duty_cycle = p_instance_ctrl->p_cfg->period_counts -
867                                        p_instance_ctrl->p_cfg->duty_cycle_counts - 1;
868         uint32_t agtcma = p_instance_ctrl->p_cfg->duty_cycle_counts;
869         uint32_t agtcmb = p_instance_ctrl->p_cfg->duty_cycle_counts;
870         if (AGT_PIN_CFG_START_LEVEL_HIGH == p_extend->agtoab_settings_b.agtoa)
871         {
872             agtcma = inverted_duty_cycle;
873         }
874 
875         if (AGT_PIN_CFG_START_LEVEL_HIGH == p_extend->agtoab_settings_b.agtob)
876         {
877             agtcmb = inverted_duty_cycle;
878         }
879 
880         if (AGT_PRV_IS_AGTW(p_instance_ctrl))
881         {
882             p_instance_ctrl->p_reg->AGT32.AGTCMA = agtcma;
883             p_instance_ctrl->p_reg->AGT32.AGTCMB = agtcmb;
884         }
885         else
886         {
887             p_instance_ctrl->p_reg->AGT16.AGTCMA = (uint16_t) agtcma;
888             p_instance_ctrl->p_reg->AGT16.AGTCMB = (uint16_t) agtcmb;
889         }
890     }
891 
892     /* Configure TEDGSEL bit based on user input. */
893     if (AGT_PIN_CFG_DISABLED != p_extend->agto)
894     {
895         /* Set the TOE bit if AGTO is enabled.  AGTO can be enabled in any mode. */
896         agtioc |= (1U << R_AGTX0_AGT16_CTRL_AGTIOC_TOE_Pos);
897 
898         if (AGT_PIN_CFG_START_LEVEL_LOW == p_extend->agto)
899         {
900             /* Configure the start level of AGTO. */
901             tedgsel |= (1U << R_AGTX0_AGT16_CTRL_AGTIOC_TEDGSEL_Pos);
902         }
903     }
904 #endif
905 #if AGT_CFG_INPUT_SUPPORT_ENABLE && AGT_CFG_OUTPUT_SUPPORT_ENABLE
906     else
907 #endif
908 #if AGT_CFG_INPUT_SUPPORT_ENABLE
909     {
910         /* This if statement applies when p_extend->measurement_mode is AGT_MEASURE_PULSE_WIDTH_LOW_LEVEL or
911          * AGT_MEASURE_PULSE_WIDTH_HIGH_LEVEL because the high level bit is in bit 4 and was masked off of mode. */
912         if (AGT_PRV_AGTMR1_TMOD_PULSE_WIDTH == mode)
913         {
914             /* Level is stored with measurement mode for pulse width mode. */
915             tedgsel = p_extend->measurement_mode >> 4U;
916         }
917         else
918         {
919             /* Use the trigger edge for pulse period or event counting modes. */
920             tedgsel = (p_extend->trigger_edge & R_AGTX0_AGT16_CTRL_AGTIOC_TEDGSEL_Msk);
921         }
922     }
923 #endif
924 
925     agtioc |= tedgsel;
926 
927     p_reg_ctrl->AGTIOC  = (uint8_t) agtioc;
928     p_reg_ctrl->AGTCMSR = (uint8_t) agtcmsr;
929     p_reg_ctrl->AGTMR1  = (uint8_t) agtmr1;
930     p_reg_ctrl->AGTMR2  = (uint8_t) agtmr2;
931 }
932 
933 /*******************************************************************************************************************//**
934  * Sets period register and updates compare match registers in one-shot and periodic mode.
935  *
936  * @param[in]  p_instance_ctrl    Control block for this instance
937  * @param[in]  period_counts      AGT period in counts
938  **********************************************************************************************************************/
r_agt_period_register_set(agt_instance_ctrl_t * p_instance_ctrl,uint32_t period_counts)939 static void r_agt_period_register_set (agt_instance_ctrl_t * p_instance_ctrl, uint32_t period_counts)
940 {
941     /* Store the period value so it can be retrieved later. */
942     p_instance_ctrl->period = period_counts;
943     gp_prv_agt_periods[AGT_PRV_CHANNEL_OFFSET_AGT_AGTW(p_instance_ctrl,
944                                                        p_instance_ctrl->p_cfg->channel)] = period_counts;
945 
946     uint32_t period_reg = (period_counts - 1U);
947 
948 #if AGT_CFG_OUTPUT_SUPPORT_ENABLE
949     uint32_t duty_cycle_counts = 0U;
950     if (TIMER_MODE_PERIODIC == p_instance_ctrl->p_cfg->mode)
951     {
952         duty_cycle_counts = (period_counts >> 1);
953     }
954     else if (TIMER_MODE_ONE_SHOT == p_instance_ctrl->p_cfg->mode)
955     {
956         duty_cycle_counts = period_reg;
957     }
958     else
959     {
960         /* Do nothing, duty cycle should not be updated in R_AGT_PeriodSet. */
961     }
962 
963     if (TIMER_MODE_PWM != p_instance_ctrl->p_cfg->mode)
964     {
965         if (AGT_PRV_IS_AGTW(p_instance_ctrl))
966         {
967             p_instance_ctrl->p_reg->AGT32.AGTCMA = duty_cycle_counts;
968             p_instance_ctrl->p_reg->AGT32.AGTCMB = duty_cycle_counts;
969         }
970         else
971         {
972             p_instance_ctrl->p_reg->AGT16.AGTCMA = (uint16_t) duty_cycle_counts;
973             p_instance_ctrl->p_reg->AGT16.AGTCMB = (uint16_t) duty_cycle_counts;
974         }
975     }
976 #endif
977 
978     /* Set counter to period minus one. */
979     if (AGT_PRV_IS_AGTW(p_instance_ctrl))
980     {
981         p_instance_ctrl->p_reg->AGT32.AGT = period_reg;
982     }
983     else
984     {
985         p_instance_ctrl->p_reg->AGT16.AGT = (uint16_t) period_reg;
986     }
987 }
988 
989 /*******************************************************************************************************************//**
990  * Obtains the clock frequency of AGT for all clock sources except AGT0 underflow, with divisor applied.
991  *
992  * @param[in]  p_agt_regs         Registers of AGT channel used
993  * @param[in]  is_agtw            Specifies this AGT channel is using the AGTW peripheral.
994  *
995  * @return Source clock frequency of AGT in Hz, divider applied.
996  **********************************************************************************************************************/
r_agt_clock_frequency_get(R_AGTX0_Type * p_agt_regs,bool is_agtw)997 static uint32_t r_agt_clock_frequency_get (R_AGTX0_Type * p_agt_regs, bool is_agtw)
998 {
999     agt_prv_reg_ctrl_ptr_t p_agt_regs_ctrl = is_agtw ? &p_agt_regs->AGT32.CTRL : &p_agt_regs->AGT16.CTRL;
1000 
1001     uint32_t           clock_freq_hz    = 0U;
1002     uint8_t            count_source_int = p_agt_regs_ctrl->AGTMR1_b.TCK;
1003     timer_source_div_t divider          = TIMER_SOURCE_DIV_1;
1004     if (0U == (count_source_int & (~AGT_SOURCE_CLOCK_PCLKB_BITS)))
1005     {
1006         /* Call CGC function to obtain current PCLKB clock frequency. */
1007         clock_freq_hz = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_PCLKB);
1008 
1009         /* If Clock source is PCLKB or derived from PCLKB */
1010         divider = (timer_source_div_t) count_source_int;
1011         if (0U != divider)
1012         {
1013             /* Set divider to 3 to divide by 8 when AGTMR1.TCK is 1 (PCLKB / 8). Set divider to 1 to divide by 2 when
1014              * AGTMR1.TCK is 3 (PCLKB / 2). XOR with 2 to convert 1 to 3 and 3 to 1. */
1015             divider ^= 2U;
1016         }
1017     }
1018     else
1019     {
1020         /* Else either fSUB clock or LOCO clock is used. The frequency is set to 32Khz (32768). This function does not
1021          * support AGT0 underflow as count source.  */
1022         clock_freq_hz = FSUB_FREQUENCY_HZ;
1023 
1024         divider = (timer_source_div_t) p_agt_regs_ctrl->AGTMR2_b.CKS;
1025     }
1026 
1027     clock_freq_hz >>= divider;
1028 
1029     return clock_freq_hz;
1030 }
1031 
1032 /*********************************************************************************************************************
1033  * AGT counter underflow interrupt.
1034  **********************************************************************************************************************/
agt_int_isr(void)1035 void agt_int_isr (void)
1036 {
1037     /* Save context if RTOS is used */
1038     FSP_CONTEXT_SAVE
1039 
1040     IRQn_Type irq = R_FSP_CurrentIrqGet();
1041 
1042     /* Clear pending IRQ to make sure it doesn't fire again after exiting */
1043     R_BSP_IrqStatusClear(irq);
1044 
1045     /* Recover ISR context saved in open. */
1046     agt_instance_ctrl_t  * p_instance_ctrl = (agt_instance_ctrl_t *) R_FSP_IsrContextGet(irq);
1047     agt_prv_reg_ctrl_ptr_t p_reg_ctrl      = AGT_PRV_CTRL_PTR(p_instance_ctrl);
1048 
1049     /* Save AGTCR to determine the source of the interrupt. */
1050     uint32_t agtcr = p_reg_ctrl->AGTCR;
1051 
1052     /* If the channel is configured to be one-shot mode, stop the timer. */
1053     if (TIMER_MODE_ONE_SHOT == p_instance_ctrl->p_cfg->mode)
1054     {
1055 #if AGT_CFG_OUTPUT_SUPPORT_ENABLE
1056 
1057         /* Forcibly stopping the timer resets AGTCMSR, AGTCMA, and AGTCMB. AGTCMA and AGTCMB are based on the
1058          * timer period, but AGTCMSR must be saved so it can be restored. */
1059         uint8_t agtcmsr = p_reg_ctrl->AGTCMSR;
1060 #endif
1061 
1062         /* Stop timer. This resets the timer period (AGT register). The AGT register is reconfigured in R_AGT_Start(). */
1063         p_reg_ctrl->AGTCR = AGT_PRV_AGTCR_FORCE_STOP;
1064         agtcr            &= AGT_PRV_AGTCR_STATUS_FLAGS;
1065         p_reg_ctrl->AGTCR = (uint8_t) agtcr;
1066 
1067 #if AGT_CFG_OUTPUT_SUPPORT_ENABLE
1068 
1069         /* Restore AGTCMSR. */
1070         p_reg_ctrl->AGTCMSR = agtcmsr;
1071 #endif
1072     }
1073 
1074     /* Invoke the callback function if it is set. */
1075     if (NULL != p_instance_ctrl->p_callback)
1076     {
1077         /* Setup parameters for the user-supplied callback function. */
1078         timer_callback_args_t callback_args;
1079 
1080         /* Store callback arguments in memory provided by user if available.  This allows callback arguments to be
1081          * stored in non-secure memory so they can be accessed by a non-secure callback function. */
1082         timer_callback_args_t * p_args = p_instance_ctrl->p_callback_memory;
1083         if (NULL == p_args)
1084         {
1085             /* Store on stack */
1086             p_args = &callback_args;
1087         }
1088         else
1089         {
1090             /* Save current arguments on the stack in case this is a nested interrupt. */
1091             callback_args = *p_args;
1092         }
1093 
1094         if (agtcr & R_AGTX0_AGT16_CTRL_AGTCR_TUNDF_Msk)
1095         {
1096             p_args->event = TIMER_EVENT_CYCLE_END;
1097         }
1098 
1099 #if AGT_CFG_INPUT_SUPPORT_ENABLE
1100         else
1101         {
1102             p_args->event = TIMER_EVENT_CAPTURE_A;
1103             uint32_t reload_value = p_instance_ctrl->period - 1U;
1104             if (AGT_PRV_IS_AGTW(p_instance_ctrl))
1105             {
1106                 p_args->capture = reload_value - p_instance_ctrl->p_reg->AGT32.AGT;
1107             }
1108             else
1109             {
1110                 p_args->capture = reload_value - p_instance_ctrl->p_reg->AGT16.AGT;
1111             }
1112 
1113             /* The AGT counter is not reset in pulse width measurement mode. Reset it by software. Note that this
1114              * will restart the counter if a new capture has already started. Application writers must ensure that
1115              * this interrupt processing completes before the next capture begins. */
1116             if (AGT_PRV_AGTMR1_TMOD_PULSE_WIDTH == p_reg_ctrl->AGTMR1_b.TMOD)
1117             {
1118                 if (AGT_PRV_IS_AGTW(p_instance_ctrl))
1119                 {
1120                     p_instance_ctrl->p_reg->AGT32.AGT = reload_value;
1121                 }
1122                 else
1123                 {
1124                     p_instance_ctrl->p_reg->AGT16.AGT = (uint16_t) reload_value;
1125                 }
1126             }
1127             else
1128             {
1129                 /* Period of input pulse = (initial value of counter [AGT register] - reading value of the read-out buffer) + 1
1130                  * Reference section 25.4.5 of the RA6M3 manual R01UH0886EJ0100. */
1131                 p_args->capture++;
1132             }
1133         }
1134 #endif
1135 
1136         p_args->p_context = p_instance_ctrl->p_context;
1137 
1138 #if BSP_TZ_SECURE_BUILD
1139 
1140         /* p_callback can point to a secure function or a non-secure function. */
1141         if (!cmse_is_nsfptr(p_instance_ctrl->p_callback))
1142         {
1143             /* If p_callback is secure, then the project does not need to change security state. */
1144             p_instance_ctrl->p_callback(p_args);
1145         }
1146         else
1147         {
1148             /* If p_callback is Non-secure, then the project must change to Non-secure state in order to call the callback. */
1149             agt_prv_ns_callback p_callback = (agt_prv_ns_callback) (p_instance_ctrl->p_callback);
1150             p_callback(p_args);
1151         }
1152 
1153 #else
1154 
1155         /* If the project is not Trustzone Secure, then it will never need to change security state in order to call the callback. */
1156         p_instance_ctrl->p_callback(p_args);
1157 #endif
1158 
1159         if (NULL != p_instance_ctrl->p_callback_memory)
1160         {
1161             /* Restore callback memory in case this is a nested interrupt. */
1162             *p_instance_ctrl->p_callback_memory = callback_args;
1163         }
1164 
1165         /* Retreive AGTCR in case it was modified in the callback. */
1166         agtcr = p_reg_ctrl->AGTCR;
1167     }
1168 
1169     /* Clear flags in AGTCR. */
1170     p_reg_ctrl->AGTCR = (uint8_t) (agtcr & ~AGT_PRV_AGTCR_STATUS_FLAGS);
1171 
1172     /* Restore context if RTOS is used */
1173     FSP_CONTEXT_RESTORE
1174 }
1175