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