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_gpt.h"
11 #include "r_gpt_cfg.h"
12 
13 /***********************************************************************************************************************
14  * Macro definitions
15  **********************************************************************************************************************/
16 
17 /* "GPT" in ASCII, used to determine if channel is open. */
18 #define GPT_OPEN                                         (0x00475054ULL)
19 
20 #define GPT_PRV_GPTE_OR_GPTEH_CHANNEL_MASK               (BSP_FEATURE_GPT_GPTEH_CHANNEL_MASK | \
21                                                           BSP_FEATURE_GPT_GPTE_CHANNEL_MASK)
22 
23 #define GPT_PRV_ADC_TRIGGER_CHANNEL_MASK                 (GPT_PRV_GPTE_OR_GPTEH_CHANNEL_MASK | \
24                                                           BSP_FEATURE_GPT_AD_DIRECT_START_CHANNEL_MASK)
25 
26 #define GPT_PRV_GTWP_RESET_VALUE                         (0xA500U)
27 #define GPT_PRV_GTWP_WRITE_PROTECT                       (0xA501U)
28 
29 #define GPT_PRV_GTIOR_STOP_LEVEL_BIT                     (6)
30 #define GPT_PRV_GTIOR_INITIAL_LEVEL_BIT                  (4)
31 
32 #define GPT_PRV_GTIO_HIGH_COMPARE_MATCH_LOW_CYCLE_END    (0x6U)
33 #define GPT_PRV_GTIO_LOW_COMPARE_MATCH_HIGH_CYCLE_END    (0x9U)
34 
35 #define GPT_PRV_GTIO_TOGGLE_COMPARE_MATCH                (0x3U)
36 
37 #define GPT_PRV_GTBER_BUFFER_ENABLE_FORCE_TRANSFER       (0x550000U)
38 #define GPT_PRV_GTBER_DISABLE_BUFFER_OP_GTCCRA_GTCCRB    (0x500000U)
39 
40 #define GPT_PRV_ENABLE_GROUP_SOFTWARE_UPDATE             (0x80000000U)
41 
42 #define GPT_PRV_GTCCRA                                   (0U)
43 #define GPT_PRV_GTCCRB                                   (1U)
44 #define GPT_PRV_GTCCRC                                   (2U)
45 #define GPT_PRV_GTCCRE                                   (3U)
46 #define GPT_PRV_GTCCRD                                   (4U)
47 #define GPT_PRV_GTCCRF                                   (5U)
48 
49 /* GPT_CFG_OUTPUT_SUPPORT_ENABLE is set to 2 to enable extra features. */
50 #define GPT_PRV_EXTRA_FEATURES_ENABLED                   (2U)
51 
52 #define R_GPT0_GTINTAD_ADTRAUEN_Pos                      (16U)
53 
54 #define GPT_PRV_COMPARE_MATCH_A_MASK                     (0x01)
55 #define GPT_PRV_COMPARE_MATCH_B_MASK                     (0x02)
56 
57 /***********************************************************************************************************************
58  * Typedef definitions
59  **********************************************************************************************************************/
60 
61 /* Duty cycle mode. */
62 typedef enum e_gpt_duty_cycle_mode
63 {
64     GPT_DUTY_CYCLE_MODE_REGISTER    = 0, // Duty cycle depends on compare match
65     GPT_DUTY_CYCLE_MODE_0_PERCENT   = 2, // Output low
66     GPT_DUTY_CYCLE_MODE_100_PERCENT = 3, // Output high
67 } gpt_duty_cycle_mode_t;
68 
69 /* Count direction */
70 typedef enum e_gpt_dir
71 {
72     GPT_DIR_COUNT_DOWN = 0,
73     GPT_DIR_COUNT_UP   = 1
74 } gpt_dir_t;
75 
76 typedef struct st_gpt_prv_duty_registers
77 {
78     uint32_t gtccr_buffer;
79     uint32_t omdty;
80 } gpt_prv_duty_registers_t;
81 
82 typedef enum e_gpt_prv_capture_event
83 {
84     GPT_PRV_CAPTURE_EVENT_A,
85     GPT_PRV_CAPTURE_EVENT_B,
86 } gpt_prv_capture_event_t;
87 
88 #if defined(__ARMCC_VERSION) || defined(__ICCARM__)
89 typedef void (BSP_CMSE_NONSECURE_CALL * gpt_prv_ns_callback)(timer_callback_args_t * p_args);
90 #elif defined(__GNUC__)
91 typedef BSP_CMSE_NONSECURE_CALL void (*volatile gpt_prv_ns_callback)(timer_callback_args_t * p_args);
92 #endif
93 
94 /***********************************************************************************************************************
95  * Private function prototypes
96  **********************************************************************************************************************/
97 static void gpt_hardware_initialize(gpt_instance_ctrl_t * const p_instance_ctrl, timer_cfg_t const * const p_cfg);
98 
99 static void gpt_common_open(gpt_instance_ctrl_t * const p_instance_ctrl, timer_cfg_t const * const p_cfg);
100 
101 static uint32_t gpt_clock_frequency_get(gpt_instance_ctrl_t * const p_instance_ctrl);
102 
103 static void gpt_hardware_events_disable(gpt_instance_ctrl_t * p_instance_ctrl);
104 
105 static void r_gpt_disable_irq(IRQn_Type irq);
106 
107 static inline void r_gpt_write_protect_enable(gpt_instance_ctrl_t * const p_instance_ctrl,
108                                               uint32_t                    write_protect_setting);
109 static inline uint32_t r_gpt_write_protect_disable(gpt_instance_ctrl_t * const p_instance_ctrl);
110 
111 /* Noinline attribute added to reduce code size for CM23 GCC build. */
112 static void r_gpt_enable_irq(IRQn_Type const irq, uint32_t priority, void * p_context) __attribute__((noinline));
113 
114 #if GPT_CFG_OUTPUT_SUPPORT_ENABLE
115 
116 static void gpt_calculate_duty_cycle(gpt_instance_ctrl_t * const p_instance_ctrl,
117                                      uint32_t const              duty_cycle_counts,
118                                      gpt_prv_duty_registers_t  * p_duty_reg,
119                                      uint32_t                    pin);
120 
121 static uint32_t gpt_gtior_calculate(timer_cfg_t const * const p_cfg, gpt_pin_level_t const stop_level);
122 
123 #endif
124 
125 static void r_gpt_call_callback(gpt_instance_ctrl_t * p_ctrl, timer_event_t event, uint32_t capture);
126 
127 static void r_gpt_init_compare_match_channel(gpt_instance_ctrl_t * p_instance_ctrl);
128 
129 /***********************************************************************************************************************
130  * ISR prototypes
131  **********************************************************************************************************************/
132 void gpt_counter_overflow_isr(void);
133 void gpt_counter_underflow_isr(void);
134 void gpt_capture_compare_a_isr(void);
135 void gpt_capture_compare_b_isr(void);
136 
137 /***********************************************************************************************************************
138  * Private global variables
139  **********************************************************************************************************************/
140 
141 /***********************************************************************************************************************
142  * Global Variables
143  **********************************************************************************************************************/
144 
145 /* GPT implementation of timer interface  */
146 const timer_api_t g_timer_on_gpt =
147 {
148     .open            = R_GPT_Open,
149     .stop            = R_GPT_Stop,
150     .start           = R_GPT_Start,
151     .reset           = R_GPT_Reset,
152     .enable          = R_GPT_Enable,
153     .disable         = R_GPT_Disable,
154     .periodSet       = R_GPT_PeriodSet,
155     .dutyCycleSet    = R_GPT_DutyCycleSet,
156     .compareMatchSet = R_GPT_CompareMatchSet,
157     .infoGet         = R_GPT_InfoGet,
158     .statusGet       = R_GPT_StatusGet,
159     .callbackSet     = R_GPT_CallbackSet,
160     .close           = R_GPT_Close,
161 };
162 
163 /*******************************************************************************************************************//**
164  * @addtogroup GPT
165  * @{
166  **********************************************************************************************************************/
167 
168 /***********************************************************************************************************************
169  * Functions
170  **********************************************************************************************************************/
171 
172 /*******************************************************************************************************************//**
173  * Initializes the timer module and applies configurations. Implements @ref timer_api_t::open.
174  *
175  * GPT hardware does not support one-shot functionality natively.  When using one-shot mode, the timer will be stopped
176  * in an ISR after the requested period has elapsed.
177  *
178  * The GPT implementation of the general timer can accept a gpt_extended_cfg_t extension parameter.
179  *
180  * Example:
181  * @snippet r_gpt_example.c R_GPT_Open
182  *
183  * @retval FSP_SUCCESS                    Initialization was successful and timer has started.
184  * @retval FSP_ERR_ASSERTION              A required input pointer is NULL or the source divider is invalid.
185  * @retval FSP_ERR_ALREADY_OPEN           Module is already open.
186  * @retval FSP_ERR_IRQ_BSP_DISABLED       timer_cfg_t::mode is ::TIMER_MODE_ONE_SHOT or timer_cfg_t::p_callback is not
187  *                                        NULL, but ISR is not enabled.  ISR must be enabled to use one-shot mode or
188  *                                        callback.
189  * @retval FSP_ERR_INVALID_MODE           Triangle wave PWM is only supported if GPT_CFG_OUTPUT_SUPPORT_ENABLE is 2.
190  *                                        Selected channel does not support external count sources.
191  *                                        External and event count sources not are available in this mode.
192  * @retval FSP_ERR_IP_CHANNEL_NOT_PRESENT The channel requested in the p_cfg parameter is not available on this device.
193  **********************************************************************************************************************/
R_GPT_Open(timer_ctrl_t * const p_ctrl,timer_cfg_t const * const p_cfg)194 fsp_err_t R_GPT_Open (timer_ctrl_t * const p_ctrl, timer_cfg_t const * const p_cfg)
195 {
196     gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl;
197 #if GPT_CFG_PARAM_CHECKING_ENABLE
198     FSP_ASSERT(NULL != p_cfg);
199     FSP_ASSERT(NULL != p_cfg->p_extend);
200     FSP_ASSERT(NULL != p_instance_ctrl);
201 
202  #if (2U == BSP_FEATURE_GPT_CLOCK_DIVIDER_STEP_SIZE)
203   #if (BSP_FEATURE_GPT_CLOCK_DIVIDER_VALUE_7_9_VALID)
204     FSP_ASSERT(p_cfg->source_div <= 10U);
205   #else
206     FSP_ASSERT((p_cfg->source_div != 7U) && (p_cfg->source_div != 9U) && (p_cfg->source_div <= 10));
207   #endif
208  #else
209     FSP_ASSERT((0U == (p_cfg->source_div % 2U)) && (p_cfg->source_div <= 10));
210  #endif
211 
212  #if GPT_PRV_EXTRA_FEATURES_ENABLED != GPT_CFG_OUTPUT_SUPPORT_ENABLE
213     FSP_ERROR_RETURN(p_cfg->mode <= TIMER_MODE_ONE_SHOT_PULSE, FSP_ERR_INVALID_MODE);
214  #endif
215 
216     FSP_ERROR_RETURN(GPT_OPEN != p_instance_ctrl->open, FSP_ERR_ALREADY_OPEN);
217 #endif
218 
219     p_instance_ctrl->channel_mask = 1U << p_cfg->channel;
220 
221 #if GPT_CFG_PARAM_CHECKING_ENABLE
222     FSP_ERROR_RETURN((p_instance_ctrl->channel_mask & BSP_FEATURE_GPT_VALID_CHANNEL_MASK),
223                      FSP_ERR_IP_CHANNEL_NOT_PRESENT);
224     if ((p_cfg->p_callback) || (TIMER_MODE_ONE_SHOT == p_cfg->mode))
225     {
226         FSP_ERROR_RETURN(p_cfg->cycle_end_irq >= 0, FSP_ERR_IRQ_BSP_DISABLED);
227     }
228 
229     gpt_extended_cfg_t * p_extend = (gpt_extended_cfg_t *) p_cfg->p_extend;
230     FSP_ERROR_RETURN((!p_extend->count_up_source && !p_extend->count_down_source) ||
231                      (BSP_FEATURE_GPT_EVENT_COUNT_CHANNEL_MASK & p_instance_ctrl->channel_mask),
232                      FSP_ERR_INVALID_MODE);
233 
234  #if GPT_PRV_EXTRA_FEATURES_ENABLED == GPT_CFG_OUTPUT_SUPPORT_ENABLE
235 
236     /* Alternate count sources cannot be used in triangle PWM modes */
237     FSP_ERROR_RETURN(!((p_cfg->mode >= TIMER_MODE_ONE_SHOT_PULSE) &&
238                        (p_extend->count_up_source || p_extend->count_down_source)),
239                      FSP_ERR_INVALID_MODE);
240 
241     /* Callback is required if underflow interrupt is enabled. */
242     gpt_extended_pwm_cfg_t const * p_pwm_cfg = p_extend->p_pwm_cfg;
243 
244     if (NULL != p_pwm_cfg)
245     {
246         if (p_pwm_cfg->trough_irq >= 0)
247         {
248             FSP_ASSERT(NULL != p_cfg->p_callback);
249         }
250     }
251  #endif
252 #endif
253 
254     /* Initialize control structure based on configurations. */
255     gpt_common_open(p_instance_ctrl, p_cfg);
256 
257     gpt_hardware_initialize(p_instance_ctrl, p_cfg);
258 
259     p_instance_ctrl->open = GPT_OPEN;
260 
261     return FSP_SUCCESS;
262 }
263 
264 /*******************************************************************************************************************//**
265  * Stops timer. Implements @ref timer_api_t::stop.
266  *
267  * Example:
268  * @snippet r_gpt_example.c R_GPT_Stop
269  *
270  * @retval FSP_SUCCESS                 Timer successfully stopped.
271  * @retval FSP_ERR_ASSERTION           p_ctrl was NULL.
272  * @retval FSP_ERR_NOT_OPEN            The instance is not opened.
273  **********************************************************************************************************************/
R_GPT_Stop(timer_ctrl_t * const p_ctrl)274 fsp_err_t R_GPT_Stop (timer_ctrl_t * const p_ctrl)
275 {
276     gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl;
277 #if GPT_CFG_PARAM_CHECKING_ENABLE
278     FSP_ASSERT(NULL != p_instance_ctrl);
279     FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
280 #endif
281 
282     /* Stop timer */
283     p_instance_ctrl->p_reg->GTSTP = p_instance_ctrl->channel_mask;
284 
285     return FSP_SUCCESS;
286 }
287 
288 /*******************************************************************************************************************//**
289  * Starts timer. Implements @ref timer_api_t::start.
290  *
291  * Example:
292  * @snippet r_gpt_example.c R_GPT_Start
293  *
294  * @retval FSP_SUCCESS                 Timer successfully started.
295  * @retval FSP_ERR_ASSERTION           p_ctrl was NULL.
296  * @retval FSP_ERR_NOT_OPEN            The instance is not opened.
297  **********************************************************************************************************************/
R_GPT_Start(timer_ctrl_t * const p_ctrl)298 fsp_err_t R_GPT_Start (timer_ctrl_t * const p_ctrl)
299 {
300     gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl;
301 #if GPT_CFG_PARAM_CHECKING_ENABLE
302     FSP_ASSERT(NULL != p_instance_ctrl);
303     FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
304 #endif
305 
306     /* Start timer */
307     p_instance_ctrl->p_reg->GTSTR = p_instance_ctrl->channel_mask;
308 
309     return FSP_SUCCESS;
310 }
311 
312 /*******************************************************************************************************************//**
313  * Resets the counter value to 0. Implements @ref timer_api_t::reset.
314  *
315  * @note This function also updates to the new period if no counter overflow has occurred since the last call to
316  * R_GPT_PeriodSet().
317  *
318  * @retval FSP_SUCCESS                 Counter value written successfully.
319  * @retval FSP_ERR_ASSERTION           p_ctrl was NULL.
320  * @retval FSP_ERR_NOT_OPEN            The instance is not opened.
321  **********************************************************************************************************************/
R_GPT_Reset(timer_ctrl_t * const p_ctrl)322 fsp_err_t R_GPT_Reset (timer_ctrl_t * const p_ctrl)
323 {
324     gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl;
325 #if GPT_CFG_PARAM_CHECKING_ENABLE
326     FSP_ASSERT(NULL != p_instance_ctrl);
327     FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
328 #endif
329 
330     /* Clear timer counter. */
331     p_instance_ctrl->p_reg->GTCLR = p_instance_ctrl->channel_mask;
332 
333     return FSP_SUCCESS;
334 }
335 
336 /*******************************************************************************************************************//**
337  * Enables external event triggers that start, stop, clear, or capture the counter. Implements @ref timer_api_t::enable.
338  *
339  * Example:
340  * @snippet r_gpt_example.c R_GPT_Enable
341  *
342  * @retval FSP_SUCCESS                 External events successfully enabled.
343  * @retval FSP_ERR_ASSERTION           p_ctrl was NULL.
344  * @retval FSP_ERR_NOT_OPEN            The instance is not opened.
345  **********************************************************************************************************************/
R_GPT_Enable(timer_ctrl_t * const p_ctrl)346 fsp_err_t R_GPT_Enable (timer_ctrl_t * const p_ctrl)
347 {
348     gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl;
349 #if GPT_CFG_PARAM_CHECKING_ENABLE
350     FSP_ASSERT(NULL != p_instance_ctrl);
351     FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
352 #endif
353 
354     /* Enable use of GTSTR, GTSTP, and GTCLR for this channel. */
355     gpt_extended_cfg_t * p_extend = (gpt_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend;
356     uint32_t             gtssr    = GPT_PRV_ENABLE_GROUP_SOFTWARE_UPDATE;
357     uint32_t             gtpsr    = GPT_PRV_ENABLE_GROUP_SOFTWARE_UPDATE;
358     uint32_t             gtcsr    = GPT_PRV_ENABLE_GROUP_SOFTWARE_UPDATE;
359 
360     /* OR with user settings. */
361     gtssr |= p_extend->start_source;
362     gtpsr |= p_extend->stop_source;
363     gtcsr |= p_extend->clear_source;
364 
365     uint32_t wp = r_gpt_write_protect_disable(p_instance_ctrl);
366 
367     /* Set the count sources. Ensure stop and clear sources are set before start source, and capture sources are set
368      * after start source. */
369     p_instance_ctrl->p_reg->GTPSR   = gtpsr;
370     p_instance_ctrl->p_reg->GTCSR   = gtcsr;
371     p_instance_ctrl->p_reg->GTSSR   = gtssr;
372     p_instance_ctrl->p_reg->GTICASR = p_extend->capture_a_source;
373     p_instance_ctrl->p_reg->GTICBSR = p_extend->capture_b_source;
374 
375     r_gpt_write_protect_enable(p_instance_ctrl, wp | GPT_PRV_GTWP_RESET_VALUE);
376 
377     return FSP_SUCCESS;
378 }
379 
380 /*******************************************************************************************************************//**
381  * Disables external event triggers that start, stop, clear, or capture the counter. Implements @ref timer_api_t::disable.
382  *
383  * @note The timer could be running after R_GPT_Disable(). To ensure it is stopped, call R_GPT_Stop().
384  *
385  * Example:
386  * @snippet r_gpt_example.c R_GPT_Disable
387  *
388  * @retval FSP_SUCCESS                 External events successfully disabled.
389  * @retval FSP_ERR_ASSERTION           p_ctrl was NULL.
390  * @retval FSP_ERR_NOT_OPEN            The instance is not opened.
391  **********************************************************************************************************************/
R_GPT_Disable(timer_ctrl_t * const p_ctrl)392 fsp_err_t R_GPT_Disable (timer_ctrl_t * const p_ctrl)
393 {
394     gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl;
395 #if GPT_CFG_PARAM_CHECKING_ENABLE
396     FSP_ASSERT(NULL != p_instance_ctrl);
397     FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
398 #endif
399 
400     uint32_t wp = r_gpt_write_protect_disable(p_instance_ctrl);
401 
402     gpt_hardware_events_disable(p_instance_ctrl);
403 
404     r_gpt_write_protect_enable(p_instance_ctrl, wp | GPT_PRV_GTWP_RESET_VALUE);
405 
406     return FSP_SUCCESS;
407 }
408 
409 /*******************************************************************************************************************//**
410  * Sets period value provided. If the timer is running, the period will be updated after the next counter overflow.
411  * If the timer is stopped, this function resets the counter and updates the period.
412  * Implements @ref timer_api_t::periodSet.
413  *
414  * @warning If periodic output is used, the duty cycle buffer registers are updated after the period buffer register.
415  * If this function is called while the timer is running and a GPT overflow occurs during processing, the duty cycle
416  * will not be the desired 50% duty cycle until the counter overflow after processing completes.
417  *
418  * Example:
419  * @snippet r_gpt_example.c R_GPT_PeriodSet
420  *
421  * @retval FSP_SUCCESS                 Period value written successfully.
422  * @retval FSP_ERR_ASSERTION           p_ctrl was NULL.
423  * @retval FSP_ERR_NOT_OPEN            The instance is not opened.
424  **********************************************************************************************************************/
R_GPT_PeriodSet(timer_ctrl_t * const p_ctrl,uint32_t const period_counts)425 fsp_err_t R_GPT_PeriodSet (timer_ctrl_t * const p_ctrl, uint32_t const period_counts)
426 {
427     gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl;
428 #if GPT_CFG_PARAM_CHECKING_ENABLE
429     FSP_ASSERT(NULL != p_instance_ctrl);
430     FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
431 #endif
432 
433     uint32_t wp = r_gpt_write_protect_disable(p_instance_ctrl);
434 
435     /* Update period buffer register. The actual period is one cycle longer than the register value for saw waves
436      * and twice the register value for triangle waves. Reference section 23.2.21 "General PWM Timer Cycle Setting
437      * Register (GTPR)". The setting passed to the configuration is expected to be half the desired period for
438      * triangle waves. */
439     uint32_t new_gtpr = period_counts - 1U;
440 #if GPT_PRV_EXTRA_FEATURES_ENABLED == GPT_CFG_OUTPUT_SUPPORT_ENABLE
441     if (p_instance_ctrl->p_cfg->mode >= TIMER_MODE_TRIANGLE_WAVE_SYMMETRIC_PWM)
442     {
443         new_gtpr = period_counts;
444     }
445 #endif
446 
447     p_instance_ctrl->p_reg->GTPBR = new_gtpr;
448 
449 #if GPT_CFG_OUTPUT_SUPPORT_ENABLE
450 
451     /* Set a 50% duty cycle so the period of the waveform on the output pin matches the requested period. */
452     if (TIMER_MODE_PERIODIC == p_instance_ctrl->p_cfg->mode)
453     {
454         /* The  GTIOCA/GTIOCB pins transition 1 cycle after compare match when buffer operation is used. Reference
455          * Figure 23.34 "Example setting for saw-wave PWM mode" in the RA6M3 manual R01UH0886EJ0100. To get a duty cycle
456          * as close to 50% as possible, duty cycle (register) = (period (counts) / 2) - 1. */
457         uint32_t duty_cycle_50_percent = (period_counts >> 1) - 1U;
458         p_instance_ctrl->p_reg->GTCCR[GPT_PRV_GTCCRC] = duty_cycle_50_percent;
459         p_instance_ctrl->p_reg->GTCCR[GPT_PRV_GTCCRE] = duty_cycle_50_percent;
460     }
461 #endif
462 
463     /* If the counter is not counting, update period register and reset counter. */
464     if (0U == p_instance_ctrl->p_reg->GTCR_b.CST)
465     {
466         p_instance_ctrl->p_reg->GTPR = new_gtpr;
467 
468 #if GPT_CFG_OUTPUT_SUPPORT_ENABLE
469         p_instance_ctrl->p_reg->GTBER = GPT_PRV_GTBER_BUFFER_ENABLE_FORCE_TRANSFER;
470 #endif
471 
472         p_instance_ctrl->p_reg->GTCLR = p_instance_ctrl->channel_mask;
473     }
474 
475     r_gpt_write_protect_enable(p_instance_ctrl, wp | GPT_PRV_GTWP_RESET_VALUE);
476 
477     return FSP_SUCCESS;
478 }
479 
480 /*******************************************************************************************************************//**
481  * Sets duty cycle on requested pin. Implements @ref timer_api_t::dutyCycleSet.
482  *
483  * Duty cycle is updated in the buffer register. The updated duty cycle is reflected after the next cycle end (counter
484  * overflow).
485  *
486  * Example:
487  * @snippet r_gpt_example.c R_GPT_DutyCycleSet
488  *
489  * @param[in] p_ctrl                   Pointer to instance control block.
490  * @param[in] duty_cycle_counts        Duty cycle to set in counts.
491  * @param[in] pin                      Use gpt_io_pin_t to select GPT_IO_PIN_GTIOCA or GPT_IO_PIN_GTIOCB
492  *
493  * @retval FSP_SUCCESS                 Duty cycle updated successfully.
494  * @retval FSP_ERR_ASSERTION           p_ctrl was NULL or the pin is not one of gpt_io_pin_t
495  * @retval FSP_ERR_NOT_OPEN            The instance is not opened.
496  * @retval FSP_ERR_INVALID_ARGUMENT    Duty cycle is larger than period.
497  * @retval FSP_ERR_INVALID_MODE        GPT_IO_PIN_TROUGH, and GPT_IO_PIN_CREST settings are invalid in the this mode.
498  * @retval FSP_ERR_UNSUPPORTED         GPT_CFG_OUTPUT_SUPPORT_ENABLE is 0.
499  **********************************************************************************************************************/
R_GPT_DutyCycleSet(timer_ctrl_t * const p_ctrl,uint32_t const duty_cycle_counts,uint32_t const pin)500 fsp_err_t R_GPT_DutyCycleSet (timer_ctrl_t * const p_ctrl, uint32_t const duty_cycle_counts, uint32_t const pin)
501 {
502 #if GPT_CFG_OUTPUT_SUPPORT_ENABLE
503     uint32_t              tmp_pin         = pin & 3U;
504     gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl;
505  #if GPT_CFG_PARAM_CHECKING_ENABLE
506     FSP_ASSERT(NULL != p_instance_ctrl);
507     FSP_ASSERT(tmp_pin <= GPT_IO_PIN_GTIOCA_AND_GTIOCB);
508     bool pwm_mode3_pin = 0 != (pin & (GPT_IO_PIN_CREST | GPT_IO_PIN_TROUGH));
509     if (TIMER_MODE_TRIANGLE_WAVE_ASYMMETRIC_PWM_MODE3 == p_instance_ctrl->p_cfg->mode)
510     {
511         /* In TIMER_MODE_TRIANGLE_WAVE_ASYMMETRIC_PWM_MODE3, the duty cycle must be for either a trough or crest. */
512         FSP_ERROR_RETURN(pwm_mode3_pin, FSP_ERR_INVALID_MODE);
513     }
514     else
515     {
516         FSP_ERROR_RETURN((!pwm_mode3_pin) || (TIMER_MODE_ONE_SHOT_PULSE == p_instance_ctrl->p_cfg->mode),
517                          FSP_ERR_INVALID_MODE);
518     }
519 
520     FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
521     FSP_ERROR_RETURN(duty_cycle_counts <= (p_instance_ctrl->p_reg->GTPR + 1), FSP_ERR_INVALID_ARGUMENT);
522  #endif
523 
524     /* Set duty cycle. */
525     gpt_prv_duty_registers_t duty_regs = {UINT32_MAX, 0};
526 
527     gpt_calculate_duty_cycle(p_instance_ctrl, duty_cycle_counts, &duty_regs, pin);
528 
529     uint32_t wp = r_gpt_write_protect_disable(p_instance_ctrl);
530 
531     /* Read modify write bitfield access is used to update GTUDDTYC to make sure we don't clobber settings for the
532      * other pin. */
533     uint32_t gtuddtyc = p_instance_ctrl->p_reg->GTUDDTYC;
534 
535     /* Only update GTCCR if 0% or 100% duty is not requested */
536     if (!duty_regs.omdty)
537     {
538         uint32_t reg_offset = 2U;
539         if (0 != (pin & GPT_IO_PIN_CREST))
540         {
541             /*
542              * In TIMER_MODE_TRIANGLE_WAVE_ASYMMETRIC_PWM_MODE3, if this is a crest duty cycle, then update the crest
543              * duty cycle register. Otherwise, update the trough duty cycle register.
544              * Or in case of One-Shot pulse mode, buffer registers are either GTCCRC and GTCCRD for pulses on GTIOCnA pin
545              * or GTCCRE and GTCCRF for pulses on GTIOCnB pin.
546              * Hence update registers GTCCRD, GTCCRF for trailing edge dutycycle counts on GTIOCnA, GTIOCnB respectively, otherwise update
547              * registers GTCCRC,GTCCRE for leading edge dutycycle counts on GTIOCnA, GTIOCnB respectively.
548              */
549             reg_offset = 4U;
550         }
551 
552         if (0 != (pin & GPT_IO_PIN_GTIOCA_AND_GTIOCB))
553         {
554             p_instance_ctrl->p_reg->GTCCR[reg_offset]     = duty_regs.gtccr_buffer;
555             p_instance_ctrl->p_reg->GTCCR[reg_offset + 1] = duty_regs.gtccr_buffer;
556         }
557         else
558         {
559             p_instance_ctrl->p_reg->GTCCR[tmp_pin + reg_offset] = duty_regs.gtccr_buffer;
560         }
561     }
562 
563     if (0 != (pin & GPT_BUFFER_FORCE_PUSH))
564     {
565         /* Enable the compare match buffer. */
566         p_instance_ctrl->p_reg->GTBER |= 1U << R_GPT0_GTBER_CCRSWT_Pos;
567     }
568 
569     if (GPT_IO_PIN_GTIOCB != tmp_pin)
570     {
571         /* GTIOCA or both GTIOCA and GTIOCB. */
572         gtuddtyc &= ~R_GPT0_GTUDDTYC_OADTY_Msk;
573         gtuddtyc |= duty_regs.omdty << R_GPT0_GTUDDTYC_OADTY_Pos;
574     }
575 
576     if ((GPT_IO_PIN_GTIOCA_AND_GTIOCB == pin) && duty_regs.omdty)
577     {
578         /* When setting both pins to 0%/100% duty recalculate OBDTY before setting */
579         gpt_calculate_duty_cycle(p_instance_ctrl, duty_cycle_counts, &duty_regs, GPT_IO_PIN_GTIOCB);
580     }
581 
582     if (GPT_IO_PIN_GTIOCA != tmp_pin)
583     {
584         /* GTIOCB or both GTIOCA and GTIOCB. */
585         gtuddtyc &= ~R_GPT0_GTUDDTYC_OBDTY_Msk;
586         gtuddtyc |= duty_regs.omdty << R_GPT0_GTUDDTYC_OBDTY_Pos;
587     }
588 
589     p_instance_ctrl->p_reg->GTUDDTYC = gtuddtyc;
590 
591     r_gpt_write_protect_enable(p_instance_ctrl, wp | GPT_PRV_GTWP_RESET_VALUE);
592 
593     return FSP_SUCCESS;
594 #else
595     FSP_PARAMETER_NOT_USED(p_ctrl);
596     FSP_PARAMETER_NOT_USED(duty_cycle_counts);
597     FSP_PARAMETER_NOT_USED(pin);
598 
599     FSP_RETURN(FSP_ERR_UNSUPPORTED);
600 #endif
601 }
602 
603 /*******************************************************************************************************************//**
604  * Set value for compare match feature. Implements @ref timer_api_t::compareMatchSet.
605  *
606  * @note This API should be used when timer is stop counting. And shall not be used along with PWM operation.
607  *
608  * Example:
609  * @snippet r_gpt_example.c R_GPT_CompareMatchSet
610  *
611  * @retval FSP_SUCCESS              Set the compare match value successfully.
612  * @retval FSP_ERR_ASSERTION        p_ctrl was NULL.
613  * @retval FSP_ERR_NOT_OPEN         The instance is not opened.
614  * @retval FSP_ERR_NOT_ENABLED      Requested compare channel is disabled.
615  **********************************************************************************************************************/
R_GPT_CompareMatchSet(timer_ctrl_t * const p_ctrl,uint32_t const compare_match_value,timer_compare_match_t const match_channel)616 fsp_err_t R_GPT_CompareMatchSet (timer_ctrl_t * const        p_ctrl,
617                                  uint32_t const              compare_match_value,
618                                  timer_compare_match_t const match_channel)
619 {
620     gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl;
621 
622 #if GPT_CFG_PARAM_CHECKING_ENABLE
623     FSP_ASSERT(NULL != p_instance_ctrl);
624     FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
625 
626     gpt_extended_cfg_t * p_extend = (gpt_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend;
627 
628     /* Confirm that requested compare match channel is enabled */
629     FSP_ERROR_RETURN(1U == (1U & ((uint8_t) (p_extend->compare_match_status >> match_channel))), FSP_ERR_NOT_ENABLED);
630 #endif
631 
632     uint32_t wp = r_gpt_write_protect_disable(p_instance_ctrl);
633 
634     /* Set compare match value. As the counter counts from 0 to (period - 1), the compare match value from user's input
635      * should be minus one. */
636     p_instance_ctrl->p_reg->GTCCR[match_channel] = compare_match_value - 1U;
637 
638     r_gpt_write_protect_enable(p_instance_ctrl, wp | GPT_PRV_GTWP_RESET_VALUE);
639 
640     return FSP_SUCCESS;
641 }
642 
643 /*******************************************************************************************************************//**
644  * Get timer information and store it in provided pointer p_info. Implements @ref timer_api_t::infoGet.
645  *
646  * Example:
647  * @snippet r_gpt_example.c R_GPT_InfoGet
648  *
649  * @retval FSP_SUCCESS                 Period, count direction, frequency, and ELC event written to caller's
650  *                                     structure successfully.
651  * @retval FSP_ERR_ASSERTION           p_ctrl or p_info was NULL.
652  * @retval FSP_ERR_NOT_OPEN            The instance is not opened.
653  **********************************************************************************************************************/
R_GPT_InfoGet(timer_ctrl_t * const p_ctrl,timer_info_t * const p_info)654 fsp_err_t R_GPT_InfoGet (timer_ctrl_t * const p_ctrl, timer_info_t * const p_info)
655 {
656     gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl;
657 #if GPT_CFG_PARAM_CHECKING_ENABLE
658     FSP_ASSERT(NULL != p_instance_ctrl);
659     FSP_ASSERT(NULL != p_info);
660     FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
661 #endif
662 
663     /* Get and store period */
664     uint32_t gtpr          = p_instance_ctrl->p_reg->GTPR;
665     uint32_t period_counts = gtpr + 1;
666 #if GPT_PRV_EXTRA_FEATURES_ENABLED == GPT_CFG_OUTPUT_SUPPORT_ENABLE
667     if (p_instance_ctrl->p_cfg->mode >= TIMER_MODE_TRIANGLE_WAVE_SYMMETRIC_PWM)
668     {
669         period_counts = gtpr;
670     }
671 #endif
672     p_info->period_counts = period_counts;
673 
674     /* Get and store clock frequency */
675     p_info->clock_frequency = gpt_clock_frequency_get(p_instance_ctrl);
676 
677     /* Get and store clock counting direction. Read count direction setting */
678     p_info->count_direction = TIMER_DIRECTION_UP;
679 
680     return FSP_SUCCESS;
681 }
682 
683 /*******************************************************************************************************************//**
684  * Get current timer status and store it in provided pointer p_status. Implements @ref timer_api_t::statusGet.
685  *
686  * Example:
687  * @snippet r_gpt_example.c R_GPT_StatusGet
688  *
689  * @retval FSP_SUCCESS                 Current timer state and counter value set successfully.
690  * @retval FSP_ERR_ASSERTION           p_ctrl or p_status was NULL.
691  * @retval FSP_ERR_NOT_OPEN            The instance is not opened.
692  **********************************************************************************************************************/
R_GPT_StatusGet(timer_ctrl_t * const p_ctrl,timer_status_t * const p_status)693 fsp_err_t R_GPT_StatusGet (timer_ctrl_t * const p_ctrl, timer_status_t * const p_status)
694 {
695     gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl;
696 #if GPT_CFG_PARAM_CHECKING_ENABLE
697     FSP_ASSERT(NULL != p_instance_ctrl);
698     FSP_ASSERT(NULL != p_status);
699     FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
700 #endif
701 
702     /* Get counter state. */
703     p_status->state = (timer_state_t) p_instance_ctrl->p_reg->GTCR_b.CST;
704 
705     /* Get counter value */
706     p_status->counter = p_instance_ctrl->p_reg->GTCNT;
707 
708     return FSP_SUCCESS;
709 }
710 
711 /*******************************************************************************************************************//**
712  * Set counter value.
713  *
714  * @note Do not call this API while the counter is counting.  The counter value can only be updated while the counter
715  * is stopped.
716  *
717  * @retval FSP_SUCCESS                 Counter value updated.
718  * @retval FSP_ERR_ASSERTION           p_ctrl or p_status was NULL.
719  * @retval FSP_ERR_NOT_OPEN            The instance is not opened.
720  * @retval FSP_ERR_IN_USE              The timer is running.  Stop the timer before calling this function.
721  **********************************************************************************************************************/
R_GPT_CounterSet(timer_ctrl_t * const p_ctrl,uint32_t counter)722 fsp_err_t R_GPT_CounterSet (timer_ctrl_t * const p_ctrl, uint32_t counter)
723 {
724     gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl;
725 #if GPT_CFG_PARAM_CHECKING_ENABLE
726     FSP_ASSERT(NULL != p_instance_ctrl);
727     FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
728     FSP_ERROR_RETURN(0U == p_instance_ctrl->p_reg->GTCR_b.CST, FSP_ERR_IN_USE);
729 #endif
730 
731     uint32_t wp = r_gpt_write_protect_disable(p_instance_ctrl);
732 
733     /* Set counter value */
734     p_instance_ctrl->p_reg->GTCNT = counter;
735 
736     r_gpt_write_protect_enable(p_instance_ctrl, wp | GPT_PRV_GTWP_RESET_VALUE);
737 
738     return FSP_SUCCESS;
739 }
740 
741 /*******************************************************************************************************************//**
742  * Enable output for GTIOCA and/or GTIOCB.
743  *
744  * @retval FSP_SUCCESS                 Output is enabled.
745  * @retval FSP_ERR_ASSERTION           p_ctrl or p_status was NULL.
746  * @retval FSP_ERR_NOT_OPEN            The instance is not opened.
747  **********************************************************************************************************************/
R_GPT_OutputEnable(timer_ctrl_t * const p_ctrl,gpt_io_pin_t pin)748 fsp_err_t R_GPT_OutputEnable (timer_ctrl_t * const p_ctrl, gpt_io_pin_t pin)
749 {
750     gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl;
751 #if GPT_CFG_PARAM_CHECKING_ENABLE
752     FSP_ASSERT(NULL != p_instance_ctrl);
753     FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
754 #endif
755 
756     uint32_t wp = r_gpt_write_protect_disable(p_instance_ctrl);
757 
758     uint32_t gtior = p_instance_ctrl->p_reg->GTIOR;
759     if (GPT_IO_PIN_GTIOCB != pin)
760     {
761         /* GTIOCA or both GTIOCA and GTIOCB. */
762         gtior |= R_GPT0_GTIOR_OAE_Msk;
763     }
764 
765     if (GPT_IO_PIN_GTIOCA != pin)
766     {
767         /* GTIOCB or both GTIOCA and GTIOCB. */
768         gtior |= R_GPT0_GTIOR_OBE_Msk;
769     }
770 
771     p_instance_ctrl->p_reg->GTIOR = gtior;
772 
773     r_gpt_write_protect_enable(p_instance_ctrl, wp | GPT_PRV_GTWP_RESET_VALUE);
774 
775     return FSP_SUCCESS;
776 }
777 
778 /*******************************************************************************************************************//**
779  * Disable output for GTIOCA and/or GTIOCB.
780  *
781  * @retval FSP_SUCCESS                 Output is disabled.
782  * @retval FSP_ERR_ASSERTION           p_ctrl or p_status was NULL.
783  * @retval FSP_ERR_NOT_OPEN            The instance is not opened.
784  **********************************************************************************************************************/
R_GPT_OutputDisable(timer_ctrl_t * const p_ctrl,gpt_io_pin_t pin)785 fsp_err_t R_GPT_OutputDisable (timer_ctrl_t * const p_ctrl, gpt_io_pin_t pin)
786 {
787     gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl;
788 #if GPT_CFG_PARAM_CHECKING_ENABLE
789     FSP_ASSERT(NULL != p_instance_ctrl);
790     FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
791 #endif
792 
793     uint32_t wp = r_gpt_write_protect_disable(p_instance_ctrl);
794 
795     uint32_t gtior = p_instance_ctrl->p_reg->GTIOR;
796     if (GPT_IO_PIN_GTIOCB != pin)
797     {
798         /* GTIOCA or both GTIOCA and GTIOCB. */
799         gtior &= ~R_GPT0_GTIOR_OAE_Msk;
800     }
801 
802     if (GPT_IO_PIN_GTIOCA != pin)
803     {
804         /* GTIOCB or both GTIOCA and GTIOCB. */
805         gtior &= ~R_GPT0_GTIOR_OBE_Msk;
806     }
807 
808     p_instance_ctrl->p_reg->GTIOR = gtior;
809 
810     r_gpt_write_protect_enable(p_instance_ctrl, wp | GPT_PRV_GTWP_RESET_VALUE);
811 
812     return FSP_SUCCESS;
813 }
814 
815 /*******************************************************************************************************************//**
816  * Set A/D converter start request compare match value.
817  *
818  * @retval FSP_SUCCESS                 Counter value updated.
819  * @retval FSP_ERR_ASSERTION           p_ctrl or p_status was NULL.
820  * @retval FSP_ERR_NOT_OPEN            The instance is not opened.
821  **********************************************************************************************************************/
R_GPT_AdcTriggerSet(timer_ctrl_t * const p_ctrl,gpt_adc_compare_match_t which_compare_match,uint32_t compare_match_value)822 fsp_err_t R_GPT_AdcTriggerSet (timer_ctrl_t * const    p_ctrl,
823                                gpt_adc_compare_match_t which_compare_match,
824                                uint32_t                compare_match_value)
825 {
826     gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl;
827 #if GPT_CFG_PARAM_CHECKING_ENABLE
828     FSP_ASSERT(NULL != p_instance_ctrl);
829     FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
830 #endif
831 
832     uint32_t wp = r_gpt_write_protect_disable(p_instance_ctrl);
833 
834     /* Set A/D converter start request compare match value. */
835     volatile uint32_t * p_gtadtr = &p_instance_ctrl->p_reg->GTADTRA;
836     p_gtadtr[which_compare_match] = compare_match_value;
837 
838     r_gpt_write_protect_enable(p_instance_ctrl, wp | GPT_PRV_GTWP_RESET_VALUE);
839 
840     return FSP_SUCCESS;
841 }
842 
843 /*******************************************************************************************************************//**
844  * Set the Output Delay setting for the PWM output pin.
845  *
846  * @retval FSP_SUCCESS                 The output delay was set.
847  * @retval FSP_ERR_ASSERTION           An input parameter was invalid.
848  * @retval FSP_ERR_NOT_OPEN            The instance is not opened.
849  * @retval FSP_ERR_INVALID_CHANNEL     The channel does not support this feature.
850  * @retval FSP_ERR_NOT_INITIALIZED     The PWM Output Delay Circuit has not been initialized.
851  * @retval FSP_ERR_INVALID_STATE       The PWM Output Delay setting cannot be updated in the current state.
852  * @retval FSP_ERR_UNSUPPORTED         This feature is not supported on this MCU.
853  **********************************************************************************************************************/
R_GPT_PwmOutputDelaySet(timer_ctrl_t * const p_ctrl,gpt_pwm_output_delay_edge_t edge,gpt_pwm_output_delay_setting_t delay_setting,uint32_t const pin)854 fsp_err_t R_GPT_PwmOutputDelaySet (timer_ctrl_t * const           p_ctrl,
855                                    gpt_pwm_output_delay_edge_t    edge,
856                                    gpt_pwm_output_delay_setting_t delay_setting,
857                                    uint32_t const                 pin)
858 {
859 #if 0U != BSP_FEATURE_GPT_ODC_VALID_CHANNEL_MASK && GPT_CFG_OUTPUT_SUPPORT_ENABLE
860     gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl;
861 
862  #if GPT_CFG_PARAM_CHECKING_ENABLE
863     FSP_ASSERT(NULL != p_instance_ctrl);
864     FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
865     FSP_ERROR_RETURN(0U != (BSP_FEATURE_GPT_ODC_VALID_CHANNEL_MASK & p_instance_ctrl->channel_mask),
866                      FSP_ERR_INVALID_CHANNEL);
867     FSP_ERROR_RETURN(0U != (R_GPT_ODC->GTDLYCR1 & R_GPT_ODC_GTDLYCR1_DLLEN_Msk), FSP_ERR_NOT_INITIALIZED);
868 
869     if (TIMER_MODE_PWM == p_instance_ctrl->p_cfg->mode)
870     {
871         /* In Saw-wave mode, do not change the settings for the delay while the compare-match value is greater than or
872          * equal to GTPR - 2. */
873         uint32_t gtpr          = p_instance_ctrl->p_reg->GTPR;
874         uint32_t compare_match = p_instance_ctrl->p_reg->GTCCR[GPT_PRV_GTCCRC + pin];
875         FSP_ERROR_RETURN(gtpr - 2 > compare_match, FSP_ERR_INVALID_STATE);
876     }
877     else
878     {
879         uint32_t compare_match;
880         if ((TIMER_MODE_TRIANGLE_WAVE_ASYMMETRIC_PWM_MODE3 == p_instance_ctrl->p_cfg->mode) ||
881             (TIMER_MODE_ONE_SHOT_PULSE == p_instance_ctrl->p_cfg->mode))
882         {
883             /* In TIMER_MODE_TRIANGLE_WAVE_ASYMMETRIC_PWM_MODE3, the trough compare match value is set in
884              * GTCCRD, and GTCCRF. */
885             compare_match = p_instance_ctrl->p_reg->GTCCR[GPT_PRV_GTCCRD + pin];
886         }
887         else
888         {
889             /* In TIMER_MODE_TRIANGLE_WAVE_ASYMMETRIC_PWM and TIMER_MODE_TRIANGLE_WAVE_SYMMETRIC_PWM, the trough compare match value is
890              * set in GTCCRC, and GTCCRE. */
891             compare_match = p_instance_ctrl->p_reg->GTCCR[GPT_PRV_GTCCRC + pin];
892         }
893 
894         timer_direction_t count_direction = (timer_direction_t) p_instance_ctrl->p_reg->GTST_b.TUCF;
895 
896         /* In Triangle-wave mode, do not change the settings for the delay while the counter if going down and the compare-match
897          * value is less than or equal to 2. */
898         FSP_ERROR_RETURN(TIMER_DIRECTION_DOWN != count_direction || 2 < compare_match, FSP_ERR_INVALID_STATE);
899     }
900  #endif
901 
902     FSP_CRITICAL_SECTION_DEFINE;
903 
904     if (GPT_PWM_OUTPUT_DELAY_SETTING_BYPASS == delay_setting)
905     {
906         /* Enter a critical section in order to ensure that multiple GPT channels don't access the common
907          * register simultaneously. */
908         FSP_CRITICAL_SECTION_ENTER;
909 
910  #if GPT_CFG_WRITE_PROTECT_ENABLE
911 
912         /* GTDLYCR2 is protected by R_GPT::GTWP. */
913         uint32_t wp = R_GPT0->GTWP;
914         R_GPT0->GTWP = GPT_PRV_GTWP_RESET_VALUE;
915         R_GPT0->GTWP;
916  #endif
917 
918         /* Enable the Delay Generation Circuit bypass. */
919         R_GPT_ODC->GTDLYCR2 &= (uint16_t) (~p_instance_ctrl->channel_mask & UINT16_MAX);
920 
921  #if GPT_CFG_WRITE_PROTECT_ENABLE
922 
923         /* Restore the previous value of GTWP. */
924         R_GPT0->GTWP = wp | GPT_PRV_GTWP_RESET_VALUE;
925  #endif
926 
927         FSP_CRITICAL_SECTION_EXIT;
928     }
929     else
930     {
931         /* Calculate the offset for the register than needs to be set. */
932         uint32_t channel_offset = sizeof(uint32_t) * p_instance_ctrl->p_cfg->channel;
933         uint32_t pin_offset     =
934             (uint32_t) ((uint32_t) &R_GPT_ODC->GTDLYR[0].B - (uint32_t) &R_GPT_ODC->GTDLYR[0].A) * pin;
935         uint32_t edge_offset =
936             (uint32_t) ((uint32_t) &R_GPT_ODC->GTDLYF[0].A - (uint32_t) &R_GPT_ODC->GTDLYR[0].A) * edge;
937         uint16_t * p_gtdlyfnx =
938             (uint16_t *) ((uint32_t) &R_GPT_ODC->GTDLYR[0].A + channel_offset + pin_offset + edge_offset);
939 
940         /* Unprotect the delay setting register. */
941         uint32_t wp = r_gpt_write_protect_disable(p_instance_ctrl);
942 
943         /* Write the delay setting to the register. */
944         *p_gtdlyfnx = (uint16_t) delay_setting;
945 
946         /* Restore the previous value of GTWP. */
947         r_gpt_write_protect_enable(p_instance_ctrl, wp | GPT_PRV_GTWP_RESET_VALUE);
948 
949         /* Check if the channel has already been enabled. */
950         if (0U == (R_GPT_ODC->GTDLYCR2 & p_instance_ctrl->channel_mask))
951         {
952             /* Enter a critical section in order to ensure that multiple GPT channels don't access the common
953              * register simultaneously. */
954             FSP_CRITICAL_SECTION_ENTER;
955 
956  #if GPT_CFG_WRITE_PROTECT_ENABLE
957 
958             /* GTDLYCR2 is protected by R_GPT::GTWP. */
959             wp           = R_GPT0->GTWP;
960             R_GPT0->GTWP = GPT_PRV_GTWP_RESET_VALUE;
961             R_GPT0->GTWP;
962  #endif
963 
964             /* Disable the Delay Generation Circuit bypass. */
965             R_GPT_ODC->GTDLYCR2 |= (uint16_t) p_instance_ctrl->channel_mask;
966 
967  #if GPT_CFG_WRITE_PROTECT_ENABLE
968 
969             /* Restore the previous value of GTWP. */
970             R_GPT0->GTWP = wp | GPT_PRV_GTWP_RESET_VALUE;
971  #endif
972 
973             FSP_CRITICAL_SECTION_EXIT;
974         }
975     }
976 
977     return FSP_SUCCESS;
978 #else
979     FSP_PARAMETER_NOT_USED(p_ctrl);
980     FSP_PARAMETER_NOT_USED(edge);
981     FSP_PARAMETER_NOT_USED(delay_setting);
982     FSP_PARAMETER_NOT_USED(pin);
983 
984     return FSP_ERR_UNSUPPORTED;
985 #endif
986 }
987 
988 /*******************************************************************************************************************//**
989  * Updates the user callback with the option to provide memory for the callback argument structure.
990  * Implements @ref timer_api_t::callbackSet.
991  *
992  * @retval  FSP_SUCCESS                  Callback updated successfully.
993  * @retval  FSP_ERR_ASSERTION            A required pointer is NULL.
994  * @retval  FSP_ERR_NOT_OPEN             The control block has not been opened.
995  * @retval  FSP_ERR_NO_CALLBACK_MEMORY   p_callback is non-secure and p_callback_memory is either secure or NULL.
996  **********************************************************************************************************************/
R_GPT_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)997 fsp_err_t R_GPT_CallbackSet (timer_ctrl_t * const          p_api_ctrl,
998                              void (                      * p_callback)(timer_callback_args_t *),
999                              void const * const            p_context,
1000                              timer_callback_args_t * const p_callback_memory)
1001 {
1002     gpt_instance_ctrl_t * p_ctrl = (gpt_instance_ctrl_t *) p_api_ctrl;
1003 
1004 #if GPT_CFG_PARAM_CHECKING_ENABLE
1005     FSP_ASSERT(p_ctrl);
1006     FSP_ASSERT(p_callback);
1007     FSP_ERROR_RETURN(GPT_OPEN == p_ctrl->open, FSP_ERR_NOT_OPEN);
1008 #endif
1009 
1010 #if BSP_TZ_SECURE_BUILD
1011 
1012     /* Get security state of p_callback */
1013     bool callback_is_secure =
1014         (NULL == cmse_check_address_range((void *) p_callback, sizeof(void *), CMSE_AU_NONSECURE));
1015 
1016  #if GPT_CFG_PARAM_CHECKING_ENABLE
1017 
1018     /* In secure projects, p_callback_memory must be provided in non-secure space if p_callback is non-secure */
1019     timer_callback_args_t * const p_callback_memory_checked = cmse_check_pointed_object(p_callback_memory,
1020                                                                                         CMSE_AU_NONSECURE);
1021     FSP_ERROR_RETURN(callback_is_secure || (NULL != p_callback_memory_checked), FSP_ERR_NO_CALLBACK_MEMORY);
1022  #endif
1023 #endif
1024 
1025     /* Store callback and context */
1026 #if BSP_TZ_SECURE_BUILD
1027     p_ctrl->p_callback = callback_is_secure ? p_callback :
1028                          (void (*)(timer_callback_args_t *))cmse_nsfptr_create(p_callback);
1029 #else
1030     p_ctrl->p_callback = p_callback;
1031 #endif
1032     p_ctrl->p_context         = p_context;
1033     p_ctrl->p_callback_memory = p_callback_memory;
1034 
1035     return FSP_SUCCESS;
1036 }
1037 
1038 /*******************************************************************************************************************//**
1039  * Stops counter, disables output pins, and clears internal driver data. Implements @ref timer_api_t::close.
1040  *
1041  * @retval FSP_SUCCESS                 Successful close.
1042  * @retval FSP_ERR_ASSERTION           p_ctrl was NULL.
1043  * @retval FSP_ERR_NOT_OPEN            The instance is not opened.
1044  **********************************************************************************************************************/
R_GPT_Close(timer_ctrl_t * const p_ctrl)1045 fsp_err_t R_GPT_Close (timer_ctrl_t * const p_ctrl)
1046 {
1047     gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl;
1048     fsp_err_t             err             = FSP_SUCCESS;
1049 
1050 #if GPT_CFG_PARAM_CHECKING_ENABLE
1051     FSP_ASSERT(NULL != p_instance_ctrl);
1052     FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
1053 #endif
1054 
1055     /* Disable interrupts. */
1056     gpt_extended_cfg_t * p_extend = (gpt_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend;
1057     r_gpt_disable_irq(p_instance_ctrl->p_cfg->cycle_end_irq);
1058     r_gpt_disable_irq(p_extend->capture_a_irq);
1059     r_gpt_disable_irq(p_extend->capture_b_irq);
1060 #if GPT_PRV_EXTRA_FEATURES_ENABLED == GPT_CFG_OUTPUT_SUPPORT_ENABLE
1061     gpt_extended_pwm_cfg_t const * p_pwm_cfg = p_extend->p_pwm_cfg;
1062     if (NULL != p_pwm_cfg)
1063     {
1064         r_gpt_disable_irq(p_pwm_cfg->trough_irq);
1065     }
1066 #endif
1067 
1068     /* Clear open flag. */
1069     p_instance_ctrl->open = 0U;
1070 
1071     uint32_t wp = r_gpt_write_protect_disable(p_instance_ctrl);
1072 
1073     /* Stop counter. */
1074     p_instance_ctrl->p_reg->GTSTP = p_instance_ctrl->channel_mask;
1075 
1076     /* Disable output. */
1077     p_instance_ctrl->p_reg->GTIOR = 0U;
1078 
1079     r_gpt_write_protect_enable(p_instance_ctrl, wp | GPT_PRV_GTWP_RESET_VALUE);
1080 
1081     return err;
1082 }
1083 
1084 /*******************************************************************************************************************//**
1085  * Initialize the PWM Delay Generation Circuit (PDG).
1086  * This function must be called before calling @ref R_GPT_PwmOutputDelaySet.
1087  *
1088  * @note This function will delay for 20 microseconds.
1089  *
1090  * @retval FSP_SUCCESS                 Initialization sequence completed successfully.
1091  * @retval FSP_ERR_INVALID_STATE       The source clock frequnecy is out of the required range for the PDG.
1092  * @retval FSP_ERR_UNSUPPORTED         This feature is not supported.
1093  **********************************************************************************************************************/
R_GPT_PwmOutputDelayInitialize(void)1094 fsp_err_t R_GPT_PwmOutputDelayInitialize (void)
1095 {
1096 #if 0U != BSP_FEATURE_GPT_ODC_VALID_CHANNEL_MASK && GPT_CFG_OUTPUT_SUPPORT_ENABLE
1097  #if BSP_FEATURE_GPT_ODC_FRANGE_FREQ_MIN > 0 || GPT_CFG_PARAM_CHECKING_ENABLE
1098   #if BSP_FEATURE_BSP_HAS_GPT_CLOCK && GPT_CFG_GPTCLK_BYPASS == 0
1099 
1100     /* Calculate the GPTCK Divider. */
1101     uint32_t divider = R_SYSTEM->GPTCKDIVCR;
1102 
1103     if (0U == divider)
1104     {
1105         divider = 1U;
1106     }
1107     else
1108     {
1109         divider *= 2U;
1110     }
1111 
1112     /* Calculate the GPTCK Frequency. */
1113     uint32_t gpt_frequency = R_BSP_SourceClockHzGet((fsp_priv_source_clock_t) R_SYSTEM->GPTCKCR_b.GPTCKSEL) / divider;
1114   #else
1115 
1116     /* Calculate the PCLKD Frequency. */
1117     uint32_t gpt_frequency = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_PCLKD);
1118   #endif
1119  #endif
1120 
1121  #if GPT_CFG_PARAM_CHECKING_ENABLE
1122     FSP_ERROR_RETURN(BSP_FEATURE_GPT_ODC_FREQ_MAX >= gpt_frequency, FSP_ERR_INVALID_STATE);
1123     FSP_ERROR_RETURN(BSP_FEATURE_GPT_ODC_FREQ_MIN <= gpt_frequency, FSP_ERR_INVALID_STATE);
1124  #endif
1125 
1126     uint32_t gtdlycr1 = R_GPT_ODC_GTDLYCR1_DLYRST_Msk;
1127 
1128  #if BSP_FEATURE_GPT_ODC_FRANGE_FREQ_MIN > 0
1129     if (BSP_FEATURE_GPT_ODC_FRANGE_FREQ_MIN >= gpt_frequency)
1130     {
1131         gtdlycr1 |= R_GPT_ODC_GTDLYCR1_FRANGE_Msk;
1132     }
1133  #endif
1134 
1135  #if BSP_FEATURE_BSP_HAS_GPT_CLOCK && GPT_CFG_GPTCLK_BYPASS
1136 
1137     /* Bypass the GPTCLK. GPT instances will use PCLKD as the GPT Core clock. */
1138     R_GPT_GTCLK->GTCLKCR = 1U;
1139  #endif
1140 
1141     /* Cancel the module-stop state for the PDG. */
1142     R_BSP_MODULE_START(FSP_IP_GPT, 0);
1143 
1144  #if GPT_CFG_WRITE_PROTECT_ENABLE
1145 
1146     /* Disable write protection for GPT registers if they are protected. */
1147     R_GPT0->GTWP = GPT_PRV_GTWP_RESET_VALUE;
1148     R_GPT0->GTWP;
1149  #endif
1150 
1151     /* Reset the PWM Delay Generation Circuit. */
1152     R_GPT_ODC->GTDLYCR1 = (uint16_t) gtdlycr1;
1153     R_GPT_ODC->GTDLYCR2 = 0;
1154 
1155     /* Enable the DLL. */
1156     R_GPT_ODC->GTDLYCR1 = (uint16_t) (gtdlycr1 | R_GPT_ODC_GTDLYCR1_DLLEN_Msk);
1157 
1158     /* Wait for the DLL to be enabled. */
1159     R_BSP_SoftwareDelay(20, BSP_DELAY_UNITS_MICROSECONDS);
1160 
1161     /* Release the PWM Delay Generation Circuit from reset. */
1162     R_GPT_ODC->GTDLYCR1 &= (uint16_t) ~R_GPT_ODC_GTDLYCR1_DLYRST_Msk;
1163 
1164  #if GPT_CFG_WRITE_PROTECT_ENABLE
1165 
1166     /* Re-enable write protection for GPT registers. */
1167     R_GPT0->GTWP = GPT_PRV_GTWP_WRITE_PROTECT;
1168  #endif
1169 
1170     return FSP_SUCCESS;
1171 #else
1172 
1173     return FSP_ERR_UNSUPPORTED;
1174 #endif
1175 }
1176 
1177 /** @} (end addtogroup GPT) */
1178 
1179 /*******************************************************************************************************************//**
1180  * Private Functions
1181  **********************************************************************************************************************/
1182 
1183 /*******************************************************************************************************************//**
1184  * Enables write protection.
1185  *
1186  * @param[in]  p_instance_ctrl         Instance control block.
1187  * @param[in]  write_protect_setting   The value of GTWP prior to being cleared.
1188  **********************************************************************************************************************/
r_gpt_write_protect_enable(gpt_instance_ctrl_t * const p_instance_ctrl,uint32_t write_protect_setting)1189 static inline void r_gpt_write_protect_enable (gpt_instance_ctrl_t * const p_instance_ctrl,
1190                                                uint32_t                    write_protect_setting)
1191 {
1192 #if GPT_CFG_WRITE_PROTECT_ENABLE
1193     p_instance_ctrl->p_reg->GTWP = write_protect_setting;
1194 #else
1195     FSP_PARAMETER_NOT_USED(p_instance_ctrl);
1196     FSP_PARAMETER_NOT_USED(write_protect_setting);
1197 #endif
1198 }
1199 
1200 /*******************************************************************************************************************//**
1201  * Disables write protection.
1202  *
1203  * @param[in]  p_instance_ctrl         Instance control block.
1204  **********************************************************************************************************************/
r_gpt_write_protect_disable(gpt_instance_ctrl_t * const p_instance_ctrl)1205 static inline uint32_t r_gpt_write_protect_disable (gpt_instance_ctrl_t * const p_instance_ctrl)
1206 {
1207 #if GPT_CFG_WRITE_PROTECT_ENABLE
1208     uint32_t write_protect_setting = p_instance_ctrl->p_reg->GTWP;
1209     p_instance_ctrl->p_reg->GTWP = GPT_PRV_GTWP_RESET_VALUE;
1210 
1211     return write_protect_setting;
1212 #else
1213     FSP_PARAMETER_NOT_USED(p_instance_ctrl);
1214 
1215     return 0U;
1216 #endif
1217 }
1218 
1219 /*******************************************************************************************************************//**
1220  * Initializes control structure based on configuration.
1221  *
1222  * @param[in]  p_instance_ctrl         Instance control block.
1223  * @param[in]  p_cfg                   Pointer to timer configuration.
1224  **********************************************************************************************************************/
gpt_common_open(gpt_instance_ctrl_t * const p_instance_ctrl,timer_cfg_t const * const p_cfg)1225 static void gpt_common_open (gpt_instance_ctrl_t * const p_instance_ctrl, timer_cfg_t const * const p_cfg)
1226 {
1227     /* Initialize control structure.  */
1228     p_instance_ctrl->p_cfg = p_cfg;
1229 
1230     /* If callback is not null or timer mode is one shot, make sure the IRQ is enabled and store callback in the
1231      *  control block.
1232      *  @note The GPT hardware does not support one-shot mode natively.  To support one-shot mode, the timer will be
1233      *  stopped and cleared using software in the ISR. *//* Determine if this is a 32-bit or a 16-bit timer. */
1234     p_instance_ctrl->variant = TIMER_VARIANT_16_BIT;
1235     if (0U != (p_instance_ctrl->channel_mask & BSP_FEATURE_GPT_32BIT_CHANNEL_MASK))
1236     {
1237         p_instance_ctrl->variant = TIMER_VARIANT_32_BIT;
1238     }
1239 
1240     /* Save register base address. */
1241     uint32_t base_address = (uint32_t) R_GPT0 + (p_cfg->channel * ((uint32_t) R_GPT1 - (uint32_t) R_GPT0));
1242     p_instance_ctrl->p_reg = (R_GPT0_Type *) base_address;
1243 
1244     /* Set callback and context pointers, if configured */
1245     p_instance_ctrl->p_callback        = p_cfg->p_callback;
1246     p_instance_ctrl->p_context         = p_cfg->p_context;
1247     p_instance_ctrl->p_callback_memory = NULL;
1248 }
1249 
1250 /*******************************************************************************************************************//**
1251  * Performs hardware initialization of the GPT.
1252  *
1253  * @param[in]  p_instance_ctrl        Instance control block.
1254  * @param[in]  p_cfg                  Pointer to timer configuration.
1255  **********************************************************************************************************************/
gpt_hardware_initialize(gpt_instance_ctrl_t * const p_instance_ctrl,timer_cfg_t const * const p_cfg)1256 static void gpt_hardware_initialize (gpt_instance_ctrl_t * const p_instance_ctrl, timer_cfg_t const * const p_cfg)
1257 {
1258     /* Save pointer to extended configuration structure. */
1259     gpt_extended_cfg_t * p_extend = (gpt_extended_cfg_t *) p_cfg->p_extend;
1260 
1261 #if BSP_FEATURE_BSP_HAS_GPT_CLOCK && GPT_CFG_GPTCLK_BYPASS
1262 
1263     /* Bypass the GPTCLK. GPT instances will use PCLKD as the GPT Core clock. */
1264     R_GPT_GTCLK->GTCLKCR = 1U;
1265 #endif
1266 
1267     /* Power on GPT before setting any hardware registers. Make sure the counter is stopped before setting mode
1268      * register, PCLK divisor register, and counter register. */
1269     R_BSP_MODULE_START(FSP_IP_GPT, p_cfg->channel);
1270 
1271 #if GPT_CFG_OUTPUT_SUPPORT_ENABLE && BSP_FEATURE_GPT_ODC_VALID_CHANNEL_MASK
1272     if (0U != (BSP_FEATURE_GPT_ODC_VALID_CHANNEL_MASK & p_instance_ctrl->channel_mask))
1273     {
1274         /* Enter a critical section in order to ensure that multiple GPT channels don't access the common
1275          * register simultaneously. */
1276         FSP_CRITICAL_SECTION_DEFINE;
1277         FSP_CRITICAL_SECTION_ENTER;
1278 
1279  #if GPT_CFG_WRITE_PROTECT_ENABLE
1280 
1281         /* Disable write protection for GPT registers if they are protected. */
1282         uint32_t wp = R_GPT0->GTWP;
1283         R_GPT0->GTWP = GPT_PRV_GTWP_RESET_VALUE;
1284         R_GPT0->GTWP;
1285  #endif
1286 
1287         /* Enable the Delay Generation Circuit bypass. */
1288         R_GPT_ODC->GTDLYCR2 &= (uint16_t) (~p_instance_ctrl->channel_mask & UINT16_MAX);
1289 
1290  #if GPT_CFG_WRITE_PROTECT_ENABLE
1291         R_GPT0->GTWP = wp | GPT_PRV_GTWP_RESET_VALUE;
1292  #endif
1293 
1294         FSP_CRITICAL_SECTION_EXIT;
1295     }
1296 #endif
1297 
1298     /* Initialize all registers that may affect operation of this driver to reset values.  Skip these since they
1299      * affect all channels, and are initialized in GTCR and GTCNT: GTSTR, GTSTP, GTCLR. GTCR is set immediately after
1300      * clearing the module stop bit to ensure the timer is stopped before proceeding with configuration. */
1301     p_instance_ctrl->p_reg->GTWP  = GPT_PRV_GTWP_RESET_VALUE;
1302     p_instance_ctrl->p_reg->GTCR  = 0U;
1303     p_instance_ctrl->p_reg->GTST  = 0U;
1304     p_instance_ctrl->p_reg->GTCNT = 0U;
1305 
1306     /* GTPR, GTCCRn, GTIOR, GTSSR, GTPSR, GTCSR, GTUPSR, GTDNSR, GTPBR, and GTUDDTYC are set by this driver. */
1307 
1308     /* Initialization sets all register required for up counting as described in hardware manual (Figure 23.4 in the
1309      * RA6M3 manual R01UH0886EJ0100) and other registers required by the driver. */
1310 
1311     /* Dividers for GPT are half the enum value. */
1312     uint32_t gtcr_tpcs = p_cfg->source_div >> BSP_FEATURE_GPT_TPCS_SHIFT;
1313     uint32_t gtcr      = gtcr_tpcs << R_GPT0_GTCR_TPCS_Pos;
1314 
1315     /* Store period register setting. The actual period and is one cycle longer than the register value for saw waves
1316      * and twice the register value for triangle waves. Reference section 23.2.21 "General PWM Timer Cycle Setting
1317      * Register (GTPR)". The setting passed to the configuration is expected to be half the desired period for
1318      * triangle waves. */
1319     uint32_t gtpr = p_cfg->period_counts - 1U;
1320 
1321     /* Set GTCR.MD = 0x001 for TIMER_MODE_ONE_SHOT_PULSE mode. */
1322     if (TIMER_MODE_ONE_SHOT_PULSE == p_cfg->mode)
1323     {
1324         gtcr |= (1U << R_GPT0_GTCR_MD_Pos);
1325     }
1326 
1327 #if GPT_PRV_EXTRA_FEATURES_ENABLED == GPT_CFG_OUTPUT_SUPPORT_ENABLE
1328 
1329     /* Saw-wave PWM mode is set in GTCR.MD for all modes except TIMER_MODE_TRIANGLE_WAVE_SYMMETRIC_PWM and
1330      * TIMER_MODE_TRIANGLE_WAVE_ASYMMETRIC_PWM. */
1331     if (p_cfg->mode >= TIMER_MODE_TRIANGLE_WAVE_SYMMETRIC_PWM)
1332     {
1333         gtcr |= ((uint32_t) p_cfg->mode << R_GPT0_GTCR_MD_Pos);
1334         gtpr  = p_cfg->period_counts;
1335     }
1336 #endif
1337 
1338     /* Counter must be stopped to update TPCS. Reference section 23.2.12 "General PWM Timer Control Register (GTCR)"
1339      * in the RA6M3 manual R01UH0886EJ0100. */
1340     p_instance_ctrl->p_reg->GTCR = gtcr;
1341 
1342     gpt_hardware_events_disable(p_instance_ctrl);
1343 
1344     /* Configure the up/down count sources. These are not affected by enable/disable. */
1345     p_instance_ctrl->p_reg->GTUPSR = p_extend->count_up_source;
1346     p_instance_ctrl->p_reg->GTDNSR = p_extend->count_down_source;
1347 
1348     /* Set period. The actual period is one cycle longer than the register value. Reference section 23.2.21
1349      * "General PWM Timer Cycle Setting Register (GTPR)". */
1350     p_instance_ctrl->p_reg->GTPBR = gtpr;
1351     p_instance_ctrl->p_reg->GTPR  = gtpr;
1352 
1353     uint32_t gtuddtyc = 0U;
1354     uint32_t gtior    = p_extend->gtior_setting.gtior;
1355 
1356 #if GPT_CFG_OUTPUT_SUPPORT_ENABLE
1357 
1358     /* For one shot mode, the compare match buffer register must be loaded with a value that exceeds the timer
1359      * cycle end value so that second compare match event would never occur and hence there will be only a
1360      * single pulse.  Writing to the upper bits is ignored for 16-bit timers. */
1361     gpt_prv_duty_registers_t duty_regs = {UINT32_MAX, 0};
1362 
1363     if (TIMER_MODE_PERIODIC == p_cfg->mode)
1364     {
1365         /* The  GTIOCA/GTIOCB pins transition 1 cycle after compare match when buffer operation is used. Reference
1366          * Figure 23.34 "Example setting for saw-wave PWM mode" in the RA6M3 manual R01UH0886EJ0100. To get a duty cycle
1367          * as close to 50% as possible, duty cycle (register) = (period (counts) / 2) - 1. */
1368         uint32_t duty_cycle_50_percent = (p_cfg->period_counts >> 1) - 1U;
1369         duty_regs.gtccr_buffer = duty_cycle_50_percent;
1370     }
1371 
1372     if (p_cfg->mode >= TIMER_MODE_PWM)
1373     {
1374         gpt_calculate_duty_cycle(p_instance_ctrl, p_cfg->duty_cycle_counts, &duty_regs, GPT_IO_PIN_GTIOCA);
1375     }
1376 
1377     /* Set the compare match and compare match buffer registers based on previously calculated values. */
1378     p_instance_ctrl->p_reg->GTCCR[GPT_PRV_GTCCRC] = duty_regs.gtccr_buffer;
1379     p_instance_ctrl->p_reg->GTCCR[GPT_PRV_GTCCRE] = duty_regs.gtccr_buffer;
1380 
1381     if (p_cfg->mode >= TIMER_MODE_TRIANGLE_WAVE_SYMMETRIC_PWM)
1382     {
1383         /* Set the double buffer registers for triangle modes. */
1384         p_instance_ctrl->p_reg->GTCCR[GPT_PRV_GTCCRD] = duty_regs.gtccr_buffer;
1385         p_instance_ctrl->p_reg->GTCCR[GPT_PRV_GTCCRF] = duty_regs.gtccr_buffer;
1386     }
1387 
1388     /* If the requested duty cycle is 0% or 100%, set this in the registers. */
1389     gtuddtyc |= duty_regs.omdty << R_GPT0_GTUDDTYC_OADTY_Pos;
1390     gtuddtyc |= duty_regs.omdty << R_GPT0_GTUDDTYC_OBDTY_Pos;
1391 
1392     /* Check if custom GTIOR settings are provided. */
1393     if (0 == p_extend->gtior_setting.gtior)
1394     {
1395         /* If custom GTIOR settings are not provided, calculate GTIOR. */
1396         if (p_extend->gtioca.output_enabled)
1397         {
1398             uint32_t gtioca_gtior = gpt_gtior_calculate(p_cfg, p_extend->gtioca.stop_level);
1399             gtior |= gtioca_gtior << R_GPT0_GTIOR_GTIOA_Pos;
1400         }
1401 
1402         if (p_extend->gtiocb.output_enabled)
1403         {
1404             uint32_t gtiocb_gtior = gpt_gtior_calculate(p_cfg, p_extend->gtiocb.stop_level);
1405             gtior |= gtiocb_gtior << R_GPT0_GTIOR_GTIOB_Pos;
1406         }
1407     }
1408 #endif
1409 
1410     r_gpt_init_compare_match_channel(p_instance_ctrl);
1411 
1412 #if GPT_PRV_GPTE_OR_GPTEH_CHANNEL_MASK
1413     if ((1U << p_cfg->channel) & GPT_PRV_GPTE_OR_GPTEH_CHANNEL_MASK)
1414     {
1415         /* This register is available on GPTE and GPTEH only. It must be cleared before setting. When modifying the
1416          * IVTT[2:0] bits, first set the IVTC[1:0] bits to 00b.  Reference section 23.2.18 "General PWM Timer Interrupt
1417          * and A/D Converter Start Request Skipping Setting Register (GTITC)"" of the RA6M3 manual R01UH0886EJ0100. */
1418         p_instance_ctrl->p_reg->GTITC = 0U;
1419     }
1420 #endif
1421     uint32_t gtintad = 0;
1422     uint32_t gtdtcr  = 0;
1423 #if GPT_PRV_EXTRA_FEATURES_ENABLED == GPT_CFG_OUTPUT_SUPPORT_ENABLE
1424     gpt_extended_pwm_cfg_t const * p_pwm_cfg = p_extend->p_pwm_cfg;
1425     if (NULL != p_pwm_cfg)
1426     {
1427         gtintad |= ((uint32_t) p_pwm_cfg->output_disable << R_GPT0_GTINTAD_GRPDTE_Pos) |
1428                    ((uint32_t) p_pwm_cfg->poeg_link << R_GPT0_GTINTAD_GRP_Pos);
1429         p_instance_ctrl->p_reg->GTDVU = p_pwm_cfg->dead_time_count_up;
1430 
1431         /* Set GTDTCR.TDE only if one of the dead time values is non-zero. */
1432         gtdtcr |= ((p_pwm_cfg->dead_time_count_up > 0) || (p_pwm_cfg->dead_time_count_down > 0));
1433 
1434  #if GPT_PRV_ADC_TRIGGER_CHANNEL_MASK
1435         if ((1 << p_cfg->channel) & GPT_PRV_ADC_TRIGGER_CHANNEL_MASK)
1436         {
1437   #if GPT_PRV_GPTE_OR_GPTEH_CHANNEL_MASK
1438 
1439             /* These registers are only available on MCUs with GPTE, GPTEH, or GPT with A/D Converter Start. */
1440             p_instance_ctrl->p_reg->GTITC = ((uint32_t) p_pwm_cfg->interrupt_skip_source << R_GPT0_GTITC_IVTC_Pos) |
1441                                             ((uint32_t) p_pwm_cfg->interrupt_skip_count << R_GPT0_GTITC_IVTT_Pos) |
1442                                             ((uint32_t) p_pwm_cfg->interrupt_skip_adc << R_GPT0_GTITC_ADTAL_Pos);
1443             p_instance_ctrl->p_reg->GTDVD = p_pwm_cfg->dead_time_count_down;
1444   #endif
1445 
1446             /* Set A/D Conversion Start Request counts */
1447             p_instance_ctrl->p_reg->GTADTRA = p_pwm_cfg->adc_a_compare_match;
1448             p_instance_ctrl->p_reg->GTADTRB = p_pwm_cfg->adc_b_compare_match;
1449 
1450             gtintad |= ((uint32_t) p_pwm_cfg->adc_trigger << R_GPT0_GTINTAD_ADTRAUEN_Pos);
1451         }
1452  #endif
1453         p_instance_ctrl->p_reg->GTINTAD = gtintad;
1454 
1455         /* Check if custom GTIOR settings are provided. */
1456         if (0 == p_extend->gtior_setting.gtior)
1457         {
1458             /* If custom GTIOR settings are not provided, set gtioca_disable_settings and gtiocb_disable_settings. */
1459             gtior |= (uint32_t) (p_pwm_cfg->gtioca_disable_setting << R_GPT0_GTIOR_OADF_Pos);
1460             gtior |= (uint32_t) (p_pwm_cfg->gtiocb_disable_setting << R_GPT0_GTIOR_OBDF_Pos);
1461         }
1462     }
1463 #endif
1464 
1465     /* GTADTR* registers are unused if GTINTAD is cleared. */
1466     p_instance_ctrl->p_reg->GTINTAD = gtintad;
1467     p_instance_ctrl->p_reg->GTDTCR  = gtdtcr;
1468 
1469     /* GTDVU, GTDVD, GTDBU, GTDBD, and GTSOTR are not used if GTDTCR is cleared. */
1470 
1471     /* Check if custom GTIOR settings are provided. */
1472     if (0 == p_extend->gtior_setting.gtior)
1473     {
1474         /*
1475          * If custom GTIOR settings are not provided, configure the noise filter for
1476          * the GTIOC pins.
1477          */
1478         gtior |= (uint32_t) (p_extend->capture_filter_gtioca << R_GPT0_GTIOR_NFAEN_Pos);
1479         gtior |= (uint32_t) (p_extend->capture_filter_gtiocb << R_GPT0_GTIOR_NFBEN_Pos);
1480     }
1481 
1482     uint32_t gtber = GPT_PRV_GTBER_BUFFER_ENABLE_FORCE_TRANSFER;
1483 
1484     if (p_extend->compare_match_status)
1485     {
1486         /* If compare match being used, GTCCRA and GTCCRB will operate with no buffer. */
1487         gtber = GPT_PRV_GTBER_DISABLE_BUFFER_OP_GTCCRA_GTCCRB;
1488     }
1489 
1490     p_instance_ctrl->p_reg->GTBER = gtber;
1491 
1492 #if GPT_CFG_OUTPUT_SUPPORT_ENABLE
1493     if (TIMER_MODE_ONE_SHOT == p_cfg->mode)
1494     {
1495         /* In one shot mode, the output pin toggles when counting starts, then again when the period expires.
1496          * The buffer is enabled to set the compare match to UINT32_MAX after the one shot pulse is output
1497          * so that the pin level will not change if the period expires again before the timer is stopped in
1498          * the interrupt.*/
1499         p_instance_ctrl->p_reg->GTCCR[GPT_PRV_GTCCRA] = 0U;
1500         p_instance_ctrl->p_reg->GTCCR[GPT_PRV_GTCCRB] = 0U;
1501     }
1502 #endif
1503 
1504     /* Reset counter to 0. */
1505     p_instance_ctrl->p_reg->GTCLR = p_instance_ctrl->channel_mask;
1506 
1507     /* Set the I/O control register. */
1508     p_instance_ctrl->p_reg->GTIOR = gtior;
1509 
1510     /* Configure duty cycle and force timer to count up. GTUDDTYC must be set, then cleared to force the count
1511      * direction to be reflected when counting starts. Reference section 23.2.13 "General PWM Timer Count Direction
1512      * and Duty Setting Register (GTUDDTYC)" in the RA6M3 manual R01UH0886EJ0100. */
1513     p_instance_ctrl->p_reg->GTUDDTYC = gtuddtyc | 3U;
1514     p_instance_ctrl->p_reg->GTUDDTYC = gtuddtyc | 1U;
1515 
1516     r_gpt_write_protect_enable(p_instance_ctrl, GPT_PRV_GTWP_WRITE_PROTECT);
1517 
1518     /* Enable CPU interrupts if callback is not null.  Also enable interrupts for one shot mode.
1519      *  @note The GPT hardware does not support one-shot mode natively. To support one-shot mode, the timer will be
1520      *  stopped and cleared using software in the ISR. */
1521     r_gpt_enable_irq(p_cfg->cycle_end_irq, p_cfg->cycle_end_ipl, p_instance_ctrl);
1522     r_gpt_enable_irq(p_extend->capture_a_irq, p_extend->capture_a_ipl, p_instance_ctrl);
1523     r_gpt_enable_irq(p_extend->capture_b_irq, p_extend->capture_b_ipl, p_instance_ctrl);
1524 #if GPT_PRV_EXTRA_FEATURES_ENABLED == GPT_CFG_OUTPUT_SUPPORT_ENABLE
1525     if (NULL != p_pwm_cfg)
1526     {
1527         r_gpt_enable_irq(p_pwm_cfg->trough_irq, p_pwm_cfg->trough_ipl, p_instance_ctrl);
1528     }
1529 #endif
1530 }
1531 
1532 /*******************************************************************************************************************//**
1533  * Disables hardware events that would cause the timer to start, stop, clear, or capture.
1534  *
1535  * @param[in]  p_instance_ctrl         Instance control structure
1536  **********************************************************************************************************************/
gpt_hardware_events_disable(gpt_instance_ctrl_t * p_instance_ctrl)1537 static void gpt_hardware_events_disable (gpt_instance_ctrl_t * p_instance_ctrl)
1538 {
1539     /* Enable use of GTSTR, GTSTP, and GTCLR for this channel. */
1540     p_instance_ctrl->p_reg->GTSSR   = GPT_PRV_ENABLE_GROUP_SOFTWARE_UPDATE;
1541     p_instance_ctrl->p_reg->GTPSR   = GPT_PRV_ENABLE_GROUP_SOFTWARE_UPDATE;
1542     p_instance_ctrl->p_reg->GTCSR   = GPT_PRV_ENABLE_GROUP_SOFTWARE_UPDATE;
1543     p_instance_ctrl->p_reg->GTICASR = GPT_SOURCE_NONE;
1544     p_instance_ctrl->p_reg->GTICBSR = GPT_SOURCE_NONE;
1545 }
1546 
1547 /*******************************************************************************************************************//**
1548  * Disables interrupt if it is a valid vector number.
1549  *
1550  * @param[in]  irq                     Interrupt number
1551  **********************************************************************************************************************/
r_gpt_disable_irq(IRQn_Type irq)1552 static void r_gpt_disable_irq (IRQn_Type irq)
1553 {
1554     /* Disable interrupts. */
1555     if (irq >= 0)
1556     {
1557         R_BSP_IrqDisable(irq);
1558         R_FSP_IsrContextSet(irq, NULL);
1559     }
1560 }
1561 
1562 /*******************************************************************************************************************//**
1563  * Configures and enables interrupt if it is a valid vector number.
1564  *
1565  * @param[in]  irq                     Interrupt number
1566  * @param[in]  priority                NVIC priority of the interrupt
1567  * @param[in]  p_context               The interrupt context is a pointer to data required in the ISR.
1568  **********************************************************************************************************************/
r_gpt_enable_irq(IRQn_Type const irq,uint32_t priority,void * p_context)1569 static void r_gpt_enable_irq (IRQn_Type const irq, uint32_t priority, void * p_context)
1570 {
1571     if (irq >= 0)
1572     {
1573         R_BSP_IrqCfgEnable(irq, priority, p_context);
1574     }
1575 }
1576 
1577 #if GPT_CFG_OUTPUT_SUPPORT_ENABLE
1578 
1579 /*******************************************************************************************************************//**
1580  * Calculates duty cycle register values.  GTPBR must be set before entering this function.
1581  *
1582  * @param[in]  p_instance_ctrl         Instance control structure
1583  * @param[in]  duty_cycle_counts       Duty cycle to set
1584  * @param[out] p_duty_reg              Duty cycle register values
1585  **********************************************************************************************************************/
gpt_calculate_duty_cycle(gpt_instance_ctrl_t * const p_instance_ctrl,uint32_t const duty_cycle_counts,gpt_prv_duty_registers_t * p_duty_reg,uint32_t pin)1586 static void gpt_calculate_duty_cycle (gpt_instance_ctrl_t * const p_instance_ctrl,
1587                                       uint32_t const              duty_cycle_counts,
1588                                       gpt_prv_duty_registers_t  * p_duty_reg,
1589                                       uint32_t                    pin)
1590 {
1591     /* Determine the current period. The actual period is one cycle longer than the register value for saw waves
1592      * and twice the register value for triangle waves. Reference section 23.2.21 "General PWM Timer Cycle Setting
1593      * Register (GTPBR)". The setting passed to the configuration is expected to be half the desired duty cycle for
1594      * triangle waves. */
1595     uint32_t current_period = p_instance_ctrl->p_reg->GTPBR;
1596  #if GPT_PRV_EXTRA_FEATURES_ENABLED == GPT_CFG_OUTPUT_SUPPORT_ENABLE
1597     if (p_instance_ctrl->p_cfg->mode < TIMER_MODE_TRIANGLE_WAVE_SYMMETRIC_PWM)
1598  #endif
1599     {
1600         current_period++;
1601     }
1602 
1603     bool duty_zero = (0U == duty_cycle_counts);
1604     bool duty_high = (duty_cycle_counts >= current_period);
1605 
1606     if (duty_zero || duty_high)
1607     {
1608         uint32_t gtior;
1609 
1610         if (!(GPT_IO_PIN_GTIOCB & pin))
1611         {
1612             gtior = p_instance_ctrl->p_reg->GTIOR_b.GTIOA;
1613         }
1614         else
1615         {
1616             gtior = p_instance_ctrl->p_reg->GTIOR_b.GTIOB;
1617         }
1618 
1619         bool first_level_low;
1620 
1621         if (p_instance_ctrl->p_cfg->mode >= TIMER_MODE_TRIANGLE_WAVE_SYMMETRIC_PWM)
1622         {
1623             /* In triangle PWM modes use the initial pin level to determine 0%/100% setting. */
1624             first_level_low = !(gtior & 0x10);
1625         }
1626         else
1627         {
1628             /* In normal PWM mode use the cycle end setting to determine 0%/100% setting */
1629             first_level_low = (gtior & 0xC) == 0x4;
1630         }
1631 
1632         if ((duty_zero && !first_level_low) || (duty_high && first_level_low))
1633         {
1634             p_duty_reg->omdty = GPT_DUTY_CYCLE_MODE_0_PERCENT;
1635         }
1636         else
1637         {
1638             p_duty_reg->omdty = GPT_DUTY_CYCLE_MODE_100_PERCENT;
1639         }
1640     }
1641     else
1642     {
1643         uint32_t temp_duty_cycle = duty_cycle_counts;
1644 
1645  #if GPT_PRV_EXTRA_FEATURES_ENABLED == GPT_CFG_OUTPUT_SUPPORT_ENABLE
1646         if (p_instance_ctrl->p_cfg->mode >= TIMER_MODE_TRIANGLE_WAVE_SYMMETRIC_PWM)
1647         {
1648             p_duty_reg->gtccr_buffer = temp_duty_cycle;
1649         }
1650         else
1651  #endif
1652         {
1653             /* The GTIOCA/GTIOCB pins transition 1 cycle after compare match when buffer operation is used. Reference
1654              * Figure 23.34 "Example setting for saw-wave PWM mode" in the RA6M3 manual R01UH0886EJ0100. */
1655             temp_duty_cycle--;
1656             p_duty_reg->gtccr_buffer = temp_duty_cycle;
1657         }
1658     }
1659 }
1660 
1661 #endif
1662 
1663 /*******************************************************************************************************************//**
1664  * Calculates clock frequency of GPT counter.  Divides GPT clock by GPT clock divisor.
1665  *
1666  * @param[in]  p_instance_ctrl           Instance control block
1667  *
1668  * @return     Clock frequency of the GPT counter.
1669  **********************************************************************************************************************/
gpt_clock_frequency_get(gpt_instance_ctrl_t * const p_instance_ctrl)1670 static uint32_t gpt_clock_frequency_get (gpt_instance_ctrl_t * const p_instance_ctrl)
1671 {
1672     /* Look up PCLKD frequency and divide it by GPT PCLKD divider. */
1673     timer_source_div_t pclk_divisor =
1674         (timer_source_div_t) (p_instance_ctrl->p_reg->GTCR_b.TPCS << BSP_FEATURE_GPT_TPCS_SHIFT);
1675     uint32_t pclk_freq_hz = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_PCLKD);
1676 
1677     return pclk_freq_hz >> pclk_divisor;
1678 }
1679 
1680 #if GPT_CFG_OUTPUT_SUPPORT_ENABLE
1681 
1682 /*******************************************************************************************************************//**
1683  * Calculates GTIOR settings for given mode and stop level.
1684  *
1685  * @param[in]  p_instance_ctrl         Instance control block
1686  * @param[in]  p_cfg                   Timer configuration
1687  * @param[in]  level                   Output level after timer stops
1688  **********************************************************************************************************************/
gpt_gtior_calculate(timer_cfg_t const * const p_cfg,gpt_pin_level_t const stop_level)1689 static uint32_t gpt_gtior_calculate (timer_cfg_t const * const p_cfg, gpt_pin_level_t const stop_level)
1690 {
1691     /* The stop level is used as both the initial level and the stop level. */
1692     uint32_t gtior = R_GPT0_GTIOR_OAE_Msk | ((uint32_t) stop_level << R_GPT0_GTIOR_OADFLT_Pos) |
1693                      ((uint32_t) stop_level << GPT_PRV_GTIOR_INITIAL_LEVEL_BIT);
1694 
1695     uint32_t gtion = GPT_PRV_GTIO_LOW_COMPARE_MATCH_HIGH_CYCLE_END;
1696 
1697     if (TIMER_MODE_PWM == p_cfg->mode)
1698     {
1699         /* Use default: GTIOn is high at cycle end, then low at compare match. */
1700     }
1701 
1702  #if GPT_PRV_EXTRA_FEATURES_ENABLED == GPT_CFG_OUTPUT_SUPPORT_ENABLE
1703     else if (p_cfg->mode >= TIMER_MODE_TRIANGLE_WAVE_SYMMETRIC_PWM)
1704     {
1705         gtion = GPT_PRV_GTIO_TOGGLE_COMPARE_MATCH;
1706     }
1707  #endif
1708     else if (TIMER_MODE_ONE_SHOT_PULSE == p_cfg->mode)
1709     {
1710         gtion = GPT_PRV_GTIO_TOGGLE_COMPARE_MATCH;
1711     }
1712     else
1713     {
1714         /* In one-shot mode, the output pin goes high after the first compare match (one cycle after the timer starts counting). */
1715         if (GPT_PIN_LEVEL_LOW == stop_level)
1716         {
1717             gtion = GPT_PRV_GTIO_HIGH_COMPARE_MATCH_LOW_CYCLE_END;
1718         }
1719     }
1720 
1721     gtior |= gtion;
1722 
1723     return gtior;
1724 }
1725 
1726 #endif
1727 
1728 /*******************************************************************************************************************//**
1729  * Set compare match value from configure instance into corresponding compare match channel.
1730  **********************************************************************************************************************/
r_gpt_init_compare_match_channel(gpt_instance_ctrl_t * p_instance_ctrl)1731 static void r_gpt_init_compare_match_channel (gpt_instance_ctrl_t * p_instance_ctrl)
1732 {
1733     /* Save pointer to extended configuration structure. */
1734     gpt_extended_cfg_t * p_extend = (gpt_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend;
1735 
1736     /* Set commpare match value for GTCCRAn if this channel is enabled. */
1737     if (GPT_PRV_COMPARE_MATCH_A_MASK & p_extend->compare_match_status)
1738     {
1739         /* As the counter counts from 0 to (period - 1), the compare match value from user's input should be minus
1740          * one. */
1741         p_instance_ctrl->p_reg->GTCCR[GPT_PRV_GTCCRA] = p_extend->compare_match_value[0] - 1U;
1742     }
1743 
1744     /* Set commpare match value for GTCCRBn if this channel is enabled. */
1745     if (GPT_PRV_COMPARE_MATCH_B_MASK & p_extend->compare_match_status)
1746     {
1747         /* As the counter counts from 0 to (period - 1), the compare match value from user's input should be minus
1748          * one. */
1749         p_instance_ctrl->p_reg->GTCCR[GPT_PRV_GTCCRB] = p_extend->compare_match_value[1] - 1U;
1750     }
1751 }
1752 
1753 /*******************************************************************************************************************//**
1754  * Calls user callback.
1755  *
1756  * @param[in]     p_ctrl     Pointer to GPT instance control block
1757  * @param[in]     event      Event code
1758  * @param[in]     capture    Event capture counts (if applicable)
1759  **********************************************************************************************************************/
r_gpt_call_callback(gpt_instance_ctrl_t * p_ctrl,timer_event_t event,uint32_t capture)1760 static void r_gpt_call_callback (gpt_instance_ctrl_t * p_ctrl, timer_event_t event, uint32_t capture)
1761 {
1762     timer_callback_args_t args;
1763 
1764     /* Store callback arguments in memory provided by user if available.  This allows callback arguments to be
1765      * stored in non-secure memory so they can be accessed by a non-secure callback function. */
1766     timer_callback_args_t * p_args = p_ctrl->p_callback_memory;
1767     if (NULL == p_args)
1768     {
1769         /* Store on stack */
1770         p_args = &args;
1771     }
1772     else
1773     {
1774         /* Save current arguments on the stack in case this is a nested interrupt. */
1775         args = *p_args;
1776     }
1777 
1778     p_args->event     = event;
1779     p_args->capture   = capture;
1780     p_args->p_context = p_ctrl->p_context;
1781 
1782 #if BSP_TZ_SECURE_BUILD
1783 
1784     /* p_callback can point to a secure function or a non-secure function. */
1785     if (!cmse_is_nsfptr(p_ctrl->p_callback))
1786     {
1787         /* If p_callback is secure, then the project does not need to change security state. */
1788         p_ctrl->p_callback(p_args);
1789     }
1790     else
1791     {
1792         /* If p_callback is Non-secure, then the project must change to Non-secure state in order to call the callback. */
1793         gpt_prv_ns_callback p_callback = (gpt_prv_ns_callback) (p_ctrl->p_callback);
1794         p_callback(p_args);
1795     }
1796 
1797 #else
1798 
1799     /* If the project is not Trustzone Secure, then it will never need to change security state in order to call the callback. */
1800     p_ctrl->p_callback(p_args);
1801 #endif
1802 
1803     if (NULL != p_ctrl->p_callback_memory)
1804     {
1805         /* Restore callback memory in case this is a nested interrupt. */
1806         *p_ctrl->p_callback_memory = args;
1807     }
1808 }
1809 
1810 /*******************************************************************************************************************//**
1811  * Common processing for input capture interrupt.
1812  *
1813  * @param[in]  event  Which input capture event occurred
1814  **********************************************************************************************************************/
r_gpt_ccmp_common_isr(gpt_prv_capture_event_t event)1815 static void r_gpt_ccmp_common_isr (gpt_prv_capture_event_t event)
1816 {
1817     /* Save context if RTOS is used */
1818     FSP_CONTEXT_SAVE
1819 
1820     IRQn_Type irq = R_FSP_CurrentIrqGet();
1821 
1822     /* Clear pending IRQ to make sure it doesn't fire again after exiting */
1823     R_BSP_IrqStatusClear(irq);
1824 
1825     /* Recover ISR context saved in open. */
1826     gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) R_FSP_IsrContextGet(irq);
1827     gpt_extended_cfg_t  * p_extend        = (gpt_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend;
1828 
1829     uint32_t      counter    = 0U;
1830     timer_event_t event_base = TIMER_EVENT_COMPARE_A;
1831 
1832     /* Identify whether capture or compare match is in use */
1833     if (!p_extend->compare_match_status)
1834     {
1835         /* If both compare match equal to 0 which mean capture operation is in use. Update the captured value and send
1836          * back to user. */
1837         counter    = p_instance_ctrl->p_reg->GTCCR[event];
1838         event_base = TIMER_EVENT_CAPTURE_A;
1839     }
1840 
1841     timer_event_t callback_event = (timer_event_t) ((uint32_t) event_base + (uint32_t) event);
1842 
1843     /* If we captured a one-shot pulse, then disable future captures. */
1844     if (TIMER_MODE_ONE_SHOT == p_instance_ctrl->p_cfg->mode)
1845     {
1846         /* Disable captures. */
1847         gpt_hardware_events_disable(p_instance_ctrl);
1848 
1849         /* Clear pending interrupt to make sure it doesn't fire again if another overflow has already occurred. */
1850         R_BSP_IrqClearPending(irq);
1851     }
1852 
1853     /* If a callback is provided, then call it with the captured counter value. */
1854     if (NULL != p_instance_ctrl->p_callback)
1855     {
1856         r_gpt_call_callback(p_instance_ctrl, callback_event, counter);
1857     }
1858 
1859     /* Restore context if RTOS is used */
1860     FSP_CONTEXT_RESTORE
1861 }
1862 
1863 /*******************************************************************************************************************//**
1864  * Stops the timer if one-shot mode, clears interrupts, and calls callback if one was provided in the open function.
1865  **********************************************************************************************************************/
gpt_counter_overflow_isr(void)1866 void gpt_counter_overflow_isr (void)
1867 {
1868     /* Save context if RTOS is used */
1869     FSP_CONTEXT_SAVE
1870 
1871     IRQn_Type irq = R_FSP_CurrentIrqGet();
1872 
1873     /* Clear pending IRQ to make sure it doesn't fire again after exiting */
1874     R_BSP_IrqStatusClear(irq);
1875 
1876     /* Recover ISR context saved in open. */
1877     gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) R_FSP_IsrContextGet(irq);
1878 
1879     /* If one-shot mode is selected, stop the timer since period has expired. */
1880     if (TIMER_MODE_ONE_SHOT == p_instance_ctrl->p_cfg->mode)
1881     {
1882         uint32_t wp = r_gpt_write_protect_disable(p_instance_ctrl);
1883 
1884         p_instance_ctrl->p_reg->GTSTP = p_instance_ctrl->channel_mask;
1885 
1886         /* Clear the GPT counter and the overflow flag after the one shot pulse has being generated */
1887         p_instance_ctrl->p_reg->GTCNT                 = 0;
1888         p_instance_ctrl->p_reg->GTCCR[GPT_PRV_GTCCRA] = 0;
1889         p_instance_ctrl->p_reg->GTCCR[GPT_PRV_GTCCRB] = 0;
1890 
1891         r_gpt_write_protect_enable(p_instance_ctrl, wp | GPT_PRV_GTWP_RESET_VALUE);
1892 
1893         /* Clear pending interrupt to make sure it doesn't fire again if another overflow has already occurred. */
1894         R_BSP_IrqClearPending(irq);
1895     }
1896 
1897     if (NULL != p_instance_ctrl->p_callback)
1898     {
1899         r_gpt_call_callback(p_instance_ctrl, TIMER_EVENT_CYCLE_END, 0);
1900     }
1901 
1902     /* Restore context if RTOS is used */
1903     FSP_CONTEXT_RESTORE
1904 }
1905 
1906 #if GPT_PRV_EXTRA_FEATURES_ENABLED == GPT_CFG_OUTPUT_SUPPORT_ENABLE
1907 
1908 /*******************************************************************************************************************//**
1909  * Only supported for asymmetric triangle-wave PWM. Notifies application of trough event.
1910  **********************************************************************************************************************/
gpt_counter_underflow_isr(void)1911 void gpt_counter_underflow_isr (void)
1912 {
1913     /* Save context if RTOS is used */
1914     FSP_CONTEXT_SAVE
1915 
1916     IRQn_Type irq = R_FSP_CurrentIrqGet();
1917 
1918     /* Clear pending IRQ to make sure it doesn't fire again after exiting */
1919     R_BSP_IrqStatusClear(irq);
1920 
1921     /* Recover ISR context saved in open. */
1922     gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) R_FSP_IsrContextGet(irq);
1923 
1924     /* Call user callback. */
1925     r_gpt_call_callback(p_instance_ctrl, TIMER_EVENT_TROUGH, 0);
1926 
1927     /* Restore context if RTOS is used */
1928     FSP_CONTEXT_RESTORE
1929 }
1930 
1931 #endif
1932 
1933 /*******************************************************************************************************************//**
1934  * Interrupt triggered by a capture A source.
1935  *
1936  * Clears interrupt, disables captures if one-shot mode, and calls callback if one was provided in the open function.
1937  **********************************************************************************************************************/
gpt_capture_compare_a_isr(void)1938 void gpt_capture_compare_a_isr (void)
1939 {
1940     r_gpt_ccmp_common_isr(GPT_PRV_CAPTURE_EVENT_A);
1941 }
1942 
1943 /*******************************************************************************************************************//**
1944  * Interrupt triggered by a capture B source.
1945  *
1946  * Clears interrupt, disables captures if one-shot mode, and calls callback if one was provided in the open function.
1947  **********************************************************************************************************************/
gpt_capture_compare_b_isr(void)1948 void gpt_capture_compare_b_isr (void)
1949 {
1950     r_gpt_ccmp_common_isr(GPT_PRV_CAPTURE_EVENT_B);
1951 }
1952