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