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