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