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