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_ulpt.h"
11 
12 /***********************************************************************************************************************
13  * Macro definitions
14  **********************************************************************************************************************/
15 
16 /** "ULPT" in ASCII, used to determine if channel is open. */
17 #define ULPT_OPEN                           (0x554C5054ULL)
18 
19 #define ULPT_PRV_ULPTCR_STATUS_FLAGS        (0xE0U)
20 #define ULPT_PRV_ULPTCMSR_VALID_BITS        (0x77U)
21 
22 #define ULPT_PRV_ULPTCR_START_TIMER         (0xE1U)
23 #define ULPT_PRV_ULPTCR_STOP_TIMER          (0xE0U)
24 #define ULPT_PRV_ULPTCR_FORCE_STOP_TIMER    (0xE4U)
25 
26 /**********************************************************************************************************************
27  * Typedef definitions
28  **********************************************************************************************************************/
29 #if defined(__ARMCC_VERSION) || defined(__ICCARM__)
30 typedef void (BSP_CMSE_NONSECURE_CALL * ulpt_prv_ns_callback)(timer_callback_args_t * p_args);
31 #elif defined(__GNUC__)
32 typedef BSP_CMSE_NONSECURE_CALL void (*volatile ulpt_prv_ns_callback)(timer_callback_args_t * p_args);
33 #endif
34 
35 /***********************************************************************************************************************
36  * Private function prototypes
37  **********************************************************************************************************************/
38 static fsp_err_t r_ulpt_common_preamble(ulpt_instance_ctrl_t * p_instance_ctrl);
39 
40 static void r_ulpt_hardware_cfg(ulpt_instance_ctrl_t * p_instance_ctrl, timer_cfg_t const * const p_cfg);
41 
42 static void     r_ulpt_period_register_set(ulpt_instance_ctrl_t * p_instance_ctrl, uint32_t period_counts);
43 static uint32_t r_ulpt_clock_frequency_get(R_ULPT0_Type * p_ulpt_regs);
44 
45 #if ULPT_CFG_PARAM_CHECKING_ENABLE
46 static fsp_err_t r_ulpt_open_param_checking(ulpt_instance_ctrl_t * p_instance_ctrl, timer_cfg_t const * const p_cfg);
47 
48 #endif
49 
50 /* ISRs. */
51 void ulpt_int_isr(void);
52 
53 /***********************************************************************************************************************
54  * Private global variables
55  **********************************************************************************************************************/
56 
57 /***********************************************************************************************************************
58  * Global Variables
59  **********************************************************************************************************************/
60 
61 /** ULPT implementation of General Timer Driver. */
62 const timer_api_t g_timer_on_ulpt =
63 {
64     .open            = R_ULPT_Open,
65     .stop            = R_ULPT_Stop,
66     .start           = R_ULPT_Start,
67     .reset           = R_ULPT_Reset,
68     .enable          = R_ULPT_Enable,
69     .disable         = R_ULPT_Disable,
70     .periodSet       = R_ULPT_PeriodSet,
71     .dutyCycleSet    = R_ULPT_DutyCycleSet,
72     .compareMatchSet = R_ULPT_CompareMatchSet,
73     .infoGet         = R_ULPT_InfoGet,
74     .statusGet       = R_ULPT_StatusGet,
75     .callbackSet     = R_ULPT_CallbackSet,
76     .close           = R_ULPT_Close,
77 };
78 
79 /*******************************************************************************************************************//**
80  * @addtogroup ULPT
81  * @{
82  **********************************************************************************************************************/
83 
84 /***********************************************************************************************************************
85  * Functions
86  **********************************************************************************************************************/
87 
88 /*******************************************************************************************************************//**
89  * Initializes the ULPT module instance. Implements @ref timer_api_t::open.
90  *
91  * The ULPT implementation of the general timer can accept an optional ulpt_extended_cfg_t extension parameter.  For
92  * ULPT, the extension specifies the clock to be used as timer source and the output pin configurations.  If the
93  * extension parameter is not specified (NULL), the default clock LOCO is used and the output pins are disabled.
94  *
95  * Example:
96  * @snippet r_ulpt_example.c R_ULPT_Open
97  *
98  * @retval FSP_SUCCESS                 Initialization was successful and timer has started.
99  * @retval FSP_ERR_ASSERTION           A required input pointer is NULL or the period is not in the valid range of
100  *                                     1 to 0xFFFF.
101  * @retval FSP_ERR_ALREADY_OPEN        R_ULPT_Open has already been called for this p_ctrl.
102  * @retval FSP_ERR_IRQ_BSP_DISABLED    A required interrupt has not been enabled in the vector table.
103  * @retval FSP_ERR_IP_CHANNEL_NOT_PRESENT  Requested channel number is not available on ULPT.
104  **********************************************************************************************************************/
R_ULPT_Open(timer_ctrl_t * const p_ctrl,timer_cfg_t const * const p_cfg)105 fsp_err_t R_ULPT_Open (timer_ctrl_t * const p_ctrl, timer_cfg_t const * const p_cfg)
106 {
107     ulpt_instance_ctrl_t * p_instance_ctrl = (ulpt_instance_ctrl_t *) p_ctrl;
108 
109 #if ULPT_CFG_PARAM_CHECKING_ENABLE
110     fsp_err_t err = r_ulpt_open_param_checking(p_instance_ctrl, p_cfg);
111     FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
112 #endif
113 
114     uint32_t base_address = (uint32_t) R_ULPT0_BASE +
115                             (p_cfg->channel * ((uint32_t) R_ULPT1_BASE - (uint32_t) R_ULPT0_BASE));
116     p_instance_ctrl->p_reg = (R_ULPT0_Type *) base_address;
117 
118     p_instance_ctrl->p_cfg = p_cfg;
119 
120     /* Power on the ULPT channel. */
121     R_BSP_MODULE_START(FSP_IP_ULPT, p_cfg->channel);
122 
123     /* Clear ULPTCR. This stops the timer if it is running and clears the flags. */
124     p_instance_ctrl->p_reg->ULPTCR = 0U;
125 
126     /* The timer is stopped in sync with the count source. */
127     FSP_HARDWARE_REGISTER_WAIT(0U, p_instance_ctrl->p_reg->ULPTCR_b.TCSTF);
128 
129     /* Clear ULPTMR2 before ULPTMR1 to prevent clock destablization if the mode is changed. */
130     p_instance_ctrl->p_reg->ULPTMR2 = 0U;
131 
132     /* Set count source and divider and configure pins. */
133     r_ulpt_hardware_cfg(p_instance_ctrl, p_cfg);
134 
135     /* Set period register and update duty cycle if output mode is used. */
136     r_ulpt_period_register_set(p_instance_ctrl, p_cfg->period_counts);
137 
138     if (p_cfg->cycle_end_irq >= 0)
139     {
140         R_BSP_IrqCfgEnable(p_cfg->cycle_end_irq, p_cfg->cycle_end_ipl, p_instance_ctrl);
141     }
142 
143     /* Set callback and context pointers */
144     p_instance_ctrl->p_callback        = p_cfg->p_callback;
145     p_instance_ctrl->p_context         = p_cfg->p_context;
146     p_instance_ctrl->p_callback_memory = NULL;
147 
148     p_instance_ctrl->open = ULPT_OPEN;
149 
150     /* All done.  */
151     return FSP_SUCCESS;
152 }
153 
154 /*******************************************************************************************************************//**
155  * Starts timer. Implements @ref timer_api_t::start.
156  *
157  * Example:
158  * @snippet r_ulpt_example.c R_ULPT_Start
159  *
160  * @retval FSP_SUCCESS                 Timer started.
161  * @retval FSP_ERR_ASSERTION           p_ctrl is null.
162  * @retval FSP_ERR_NOT_OPEN            The instance control structure is not opened.
163  **********************************************************************************************************************/
R_ULPT_Start(timer_ctrl_t * const p_ctrl)164 fsp_err_t R_ULPT_Start (timer_ctrl_t * const p_ctrl)
165 {
166     ulpt_instance_ctrl_t * p_instance_ctrl = (ulpt_instance_ctrl_t *) p_ctrl;
167 
168     fsp_err_t err = r_ulpt_common_preamble(p_instance_ctrl);
169     FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
170 
171     /* Start timer */
172     p_instance_ctrl->p_reg->ULPTCR = ULPT_PRV_ULPTCR_START_TIMER;
173 
174     return FSP_SUCCESS;
175 }
176 
177 /*******************************************************************************************************************//**
178  * Stops the timer.  Implements @ref timer_api_t::stop.
179  *
180  * Example:
181  * @snippet r_ulpt_example.c R_ULPT_Stop
182  *
183  * @retval FSP_SUCCESS                 Timer stopped.
184  * @retval FSP_ERR_ASSERTION           p_ctrl was NULL.
185  * @retval FSP_ERR_NOT_OPEN            The instance control structure is not opened.
186  **********************************************************************************************************************/
R_ULPT_Stop(timer_ctrl_t * const p_ctrl)187 fsp_err_t R_ULPT_Stop (timer_ctrl_t * const p_ctrl)
188 {
189     ulpt_instance_ctrl_t * p_instance_ctrl = (ulpt_instance_ctrl_t *) p_ctrl;
190 
191     fsp_err_t err = r_ulpt_common_preamble(p_instance_ctrl);
192     FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
193 
194     /* Stop timer */
195     p_instance_ctrl->p_reg->ULPTCR = ULPT_PRV_ULPTCR_STOP_TIMER;
196 
197     return FSP_SUCCESS;
198 }
199 
200 /*******************************************************************************************************************//**
201  * Resets the counter value to the period minus one. Implements @ref timer_api_t::reset.
202  *
203  * @retval FSP_SUCCESS                 Counter reset.
204  * @retval FSP_ERR_ASSERTION           p_ctrl is NULL
205  * @retval FSP_ERR_NOT_OPEN            The instance control structure is not opened.
206  **********************************************************************************************************************/
R_ULPT_Reset(timer_ctrl_t * const p_ctrl)207 fsp_err_t R_ULPT_Reset (timer_ctrl_t * const p_ctrl)
208 {
209     ulpt_instance_ctrl_t * p_instance_ctrl = (ulpt_instance_ctrl_t *) p_ctrl;
210 
211     fsp_err_t err = r_ulpt_common_preamble(p_instance_ctrl);
212     FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
213 
214     /* Reset counter to period minus one. */
215     p_instance_ctrl->p_reg->ULPTCNT = p_instance_ctrl->period - 1U;
216 
217     return FSP_SUCCESS;
218 }
219 
220 /*******************************************************************************************************************//**
221  * Enables external event triggers that start, stop, clear, or capture the counter. Implements @ref timer_api_t::enable.
222  *
223  * Example:
224  * @snippet r_ulpt_example.c R_ULPT_Enable
225  *
226  * @retval FSP_SUCCESS                 External events successfully enabled.
227  * @retval FSP_ERR_ASSERTION           p_ctrl was NULL.
228  * @retval FSP_ERR_NOT_OPEN            The instance is not opened.
229  **********************************************************************************************************************/
R_ULPT_Enable(timer_ctrl_t * const p_ctrl)230 fsp_err_t R_ULPT_Enable (timer_ctrl_t * const p_ctrl)
231 {
232     ulpt_instance_ctrl_t * p_instance_ctrl = (ulpt_instance_ctrl_t *) p_ctrl;
233 #if ULPT_CFG_PARAM_CHECKING_ENABLE
234     FSP_ASSERT(NULL != p_instance_ctrl);
235     FSP_ERROR_RETURN(ULPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
236 #endif
237 
238     /* Reset counter to period minus one. */
239     p_instance_ctrl->p_reg->ULPTCNT = p_instance_ctrl->period - 1U;
240 
241     /* Enable captures. */
242     p_instance_ctrl->p_reg->ULPTCR = ULPT_PRV_ULPTCR_START_TIMER;
243 
244     return FSP_SUCCESS;
245 }
246 
247 /*******************************************************************************************************************//**
248  * Disables external event triggers that start, stop, clear, or capture the counter. Implements @ref timer_api_t::disable.
249  *
250  * Example:
251  * @snippet r_ulpt_example.c R_ULPT_Disable
252  *
253  * @retval FSP_SUCCESS                 External events successfully disabled.
254  * @retval FSP_ERR_ASSERTION           p_ctrl was NULL.
255  * @retval FSP_ERR_NOT_OPEN            The instance is not opened.
256  **********************************************************************************************************************/
R_ULPT_Disable(timer_ctrl_t * const p_ctrl)257 fsp_err_t R_ULPT_Disable (timer_ctrl_t * const p_ctrl)
258 {
259     ulpt_instance_ctrl_t * p_instance_ctrl = (ulpt_instance_ctrl_t *) p_ctrl;
260 #if ULPT_CFG_PARAM_CHECKING_ENABLE
261     FSP_ASSERT(NULL != p_instance_ctrl);
262     FSP_ERROR_RETURN(ULPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
263 #endif
264 
265     /* Disable captures. */
266     p_instance_ctrl->p_reg->ULPTCR = ULPT_PRV_ULPTCR_STOP_TIMER;
267 
268     return FSP_SUCCESS;
269 }
270 
271 /*******************************************************************************************************************//**
272  * Updates period. The new period is updated immediately and the counter is reset to the maximum value. Implements
273  * @ref timer_api_t::periodSet.
274  *
275  * @warning If periodic output is used, the duty cycle buffer registers are updated after the period buffer register.
276  * If this function is called while the timer is running and an AGT underflow occurs during processing, the duty cycle
277  * will not be the desired 50% duty cycle until the counter underflow after processing completes.
278  *
279  * @warning Stop the timer before calling this function if one-shot output is used.
280  *
281  * Example:
282  * @snippet r_ulpt_example.c R_ULPT_PeriodSet
283  *
284  * @retval FSP_SUCCESS                 Period value updated.
285  * @retval FSP_ERR_ASSERTION           A required pointer was NULL, or the period was not in the valid range of
286  *                                     1 to 0xFFFF.
287  * @retval FSP_ERR_NOT_OPEN            The instance control structure is not opened.
288  **********************************************************************************************************************/
R_ULPT_PeriodSet(timer_ctrl_t * const p_ctrl,uint32_t const period_counts)289 fsp_err_t R_ULPT_PeriodSet (timer_ctrl_t * const p_ctrl, uint32_t const period_counts)
290 {
291     ulpt_instance_ctrl_t * p_instance_ctrl = (ulpt_instance_ctrl_t *) p_ctrl;
292 #if ULPT_CFG_PARAM_CHECKING_ENABLE
293 
294     /* Validate period parameter. */
295     FSP_ASSERT(0U != period_counts);
296 #endif
297 
298     fsp_err_t err = r_ulpt_common_preamble(p_instance_ctrl);
299     FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
300 
301     /* Set period. */
302     r_ulpt_period_register_set(p_instance_ctrl, period_counts);
303 
304     return FSP_SUCCESS;
305 }
306 
307 /*******************************************************************************************************************//**
308  * Updates duty cycle. If the timer is counting, the new duty cycle is reflected after the next counter underflow.
309  * Implements @ref timer_api_t::dutyCycleSet.
310  *
311  * Example:
312  * @snippet r_ulpt_example.c R_ULPT_DutyCycleSet
313  *
314  * @retval FSP_SUCCESS                 Duty cycle updated.
315  * @retval FSP_ERR_ASSERTION           A required pointer was NULL, or the pin was not ULPT_ULPTO_ULPTOA or ULPT_ULPTO_ULPTOB.
316  * @retval FSP_ERR_INVALID_ARGUMENT    Duty cycle was not in the valid range of 0 to period (counts) - 1
317  * @retval FSP_ERR_NOT_OPEN            The instance control structure is not opened.
318  * @retval FSP_ERR_UNSUPPORTED         ULPT_CFG_OUTPUT_SUPPORT_ENABLE is 0.
319  **********************************************************************************************************************/
R_ULPT_DutyCycleSet(timer_ctrl_t * const p_ctrl,uint32_t const duty_cycle_counts,uint32_t const pin)320 fsp_err_t R_ULPT_DutyCycleSet (timer_ctrl_t * const p_ctrl, uint32_t const duty_cycle_counts, uint32_t const pin)
321 {
322 #if ULPT_CFG_OUTPUT_SUPPORT_ENABLE
323     ulpt_instance_ctrl_t * p_instance_ctrl = (ulpt_instance_ctrl_t *) p_ctrl;
324  #if ULPT_CFG_PARAM_CHECKING_ENABLE
325     FSP_ASSERT((pin == ULPT_OUTPUT_PIN_ULPTOA) || (pin == ULPT_OUTPUT_PIN_ULPTOB));
326  #endif
327 
328     fsp_err_t err = r_ulpt_common_preamble(p_instance_ctrl);
329     FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
330 
331  #if ULPT_CFG_PARAM_CHECKING_ENABLE
332     if (0U != p_instance_ctrl->period)
333     {
334         FSP_ERROR_RETURN(duty_cycle_counts < (p_instance_ctrl->period), FSP_ERR_INVALID_ARGUMENT);
335     }
336  #endif
337 
338     uint32_t temp_duty_cycle_counts           = duty_cycle_counts;
339     uint32_t ulptcmsr_ulptoab_start_level_bit = 1U << 2 << (4 * pin); /* polarity set*/
340     ulpt_extended_cfg_t const * p_extend      = (ulpt_extended_cfg_t const *) p_instance_ctrl->p_cfg->p_extend;
341     if (p_extend->ulptoab_settings & ulptcmsr_ulptoab_start_level_bit)
342     {
343         /* Invert duty cycle if this pin starts high since the high portion is at the beginning of the cycle. */
344         temp_duty_cycle_counts = p_instance_ctrl->period - temp_duty_cycle_counts - 1;
345     }
346 
347     /* Set duty cycle. */
348     volatile uint32_t * const p_ulptcm = &p_instance_ctrl->p_reg->ULPTCMA;
349     p_ulptcm[pin] = temp_duty_cycle_counts;
350 
351     return FSP_SUCCESS;
352 #else
353     FSP_PARAMETER_NOT_USED(p_ctrl);
354     FSP_PARAMETER_NOT_USED(duty_cycle_counts);
355     FSP_PARAMETER_NOT_USED(pin);
356 
357     FSP_RETURN(FSP_ERR_UNSUPPORTED);
358 #endif
359 }
360 
361 /*******************************************************************************************************************//**
362  * Placeholder for unsupported compareMatch function. Implements @ref timer_api_t::compareMatchSet.
363  *
364  * @retval FSP_ERR_UNSUPPORTED      ULPT compare match is not supported.
365  **********************************************************************************************************************/
R_ULPT_CompareMatchSet(timer_ctrl_t * const p_ctrl,uint32_t const compare_match_value,timer_compare_match_t const match_channel)366 fsp_err_t R_ULPT_CompareMatchSet (timer_ctrl_t * const        p_ctrl,
367                                   uint32_t const              compare_match_value,
368                                   timer_compare_match_t const match_channel)
369 {
370     /* This function isn't supported. It is defined only to implement a required function of timer_api_t.
371      * Mark the input parameter as unused since this function isn't supported. */
372     FSP_PARAMETER_NOT_USED(p_ctrl);
373     FSP_PARAMETER_NOT_USED(compare_match_value);
374     FSP_PARAMETER_NOT_USED(match_channel);
375 
376     return FSP_ERR_UNSUPPORTED;
377 }
378 
379 /*******************************************************************************************************************//**
380  * Gets timer information and store it in provided pointer p_info. Implements @ref timer_api_t::infoGet.
381  *
382  * Example:
383  * @snippet r_ulpt_example.c R_ULPT_InfoGet
384  *
385  * @retval FSP_SUCCESS                 Period, count direction, and frequency stored in p_info.
386  * @retval FSP_ERR_ASSERTION           A required pointer is NULL.
387  * @retval FSP_ERR_NOT_OPEN            The instance control structure is not opened.
388  **********************************************************************************************************************/
R_ULPT_InfoGet(timer_ctrl_t * const p_ctrl,timer_info_t * const p_info)389 fsp_err_t R_ULPT_InfoGet (timer_ctrl_t * const p_ctrl, timer_info_t * const p_info)
390 {
391     ulpt_instance_ctrl_t * p_instance_ctrl = (ulpt_instance_ctrl_t *) p_ctrl;
392 #if ULPT_CFG_PARAM_CHECKING_ENABLE
393     FSP_ASSERT(NULL != p_info);
394 #endif
395 
396     fsp_err_t err = r_ulpt_common_preamble(p_instance_ctrl);
397     FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
398 
399     /* Get and store period */
400     p_info->period_counts = p_instance_ctrl->period;
401 
402     /* Get and store clock frequency */
403     /* ulpt_extended_cfg_t const * p_extend = (ulpt_extended_cfg_t const *) p_instance_ctrl->p_cfg->p_extend;*/
404     p_info->clock_frequency = r_ulpt_clock_frequency_get(p_instance_ctrl->p_reg);
405 
406     /* ULPT supports only counting down direction */
407     p_info->count_direction = TIMER_DIRECTION_DOWN;
408 
409     return FSP_SUCCESS;
410 }
411 
412 /*******************************************************************************************************************//**
413  * Retrieves the current state and counter value stores them in p_status. Implements @ref timer_api_t::statusGet.
414  *
415  * Example:
416  * @snippet r_ulpt_example.c R_ULPT_StatusGet
417  *
418  * @retval FSP_SUCCESS                 Current status and counter value provided in p_status.
419  * @retval FSP_ERR_ASSERTION           A required pointer is NULL.
420  * @retval FSP_ERR_NOT_OPEN            The instance control structure is not opened.
421  **********************************************************************************************************************/
R_ULPT_StatusGet(timer_ctrl_t * const p_ctrl,timer_status_t * const p_status)422 fsp_err_t R_ULPT_StatusGet (timer_ctrl_t * const p_ctrl, timer_status_t * const p_status)
423 {
424     ulpt_instance_ctrl_t * p_instance_ctrl = (ulpt_instance_ctrl_t *) p_ctrl;
425 
426 #if ULPT_CFG_PARAM_CHECKING_ENABLE
427     FSP_ASSERT(NULL != p_status);
428 #endif
429 
430     fsp_err_t err = r_ulpt_common_preamble(p_instance_ctrl);
431     FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
432 
433     /* Read the state. */
434     p_status->state = (timer_state_t) p_instance_ctrl->p_reg->ULPTCR_b.TCSTF;
435 
436     /* Read counter value */
437     p_status->counter = p_instance_ctrl->p_reg->ULPTCNT;
438 
439     return FSP_SUCCESS;
440 }
441 
442 /*******************************************************************************************************************//**
443  * Updates the user callback with the option to provide memory for the callback argument structure.
444  * Implements @ref timer_api_t::callbackSet.
445  *
446  * @retval  FSP_SUCCESS                  Callback updated successfully.
447  * @retval  FSP_ERR_ASSERTION            A required pointer is NULL.
448  * @retval  FSP_ERR_NOT_OPEN             The control block has not been opened.
449  * @retval  FSP_ERR_NO_CALLBACK_MEMORY   p_callback is non-secure and p_callback_memory is either secure or NULL.
450  **********************************************************************************************************************/
R_ULPT_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)451 fsp_err_t R_ULPT_CallbackSet (timer_ctrl_t * const          p_api_ctrl,
452                               void (                      * p_callback)(timer_callback_args_t *),
453                               void const * const            p_context,
454                               timer_callback_args_t * const p_callback_memory)
455 {
456     ulpt_instance_ctrl_t * p_ctrl = (ulpt_instance_ctrl_t *) p_api_ctrl;
457 
458 #if ULPT_CFG_PARAM_CHECKING_ENABLE
459     FSP_ASSERT(p_ctrl);
460     FSP_ASSERT(p_callback);
461     FSP_ERROR_RETURN(ULPT_OPEN == p_ctrl->open, FSP_ERR_NOT_OPEN);
462 #endif
463 
464 #if BSP_TZ_SECURE_BUILD
465 
466     /* Get security state of p_callback */
467     bool callback_is_secure =
468         (NULL == cmse_check_address_range((void *) p_callback, sizeof(void *), CMSE_AU_NONSECURE));
469 
470  #if ULPT_CFG_PARAM_CHECKING_ENABLE
471 
472     /* In secure projects, p_callback_memory must be provided in non-secure space if p_callback is non-secure */
473     timer_callback_args_t * const p_callback_memory_checked = cmse_check_pointed_object(p_callback_memory,
474                                                                                         CMSE_AU_NONSECURE);
475     FSP_ERROR_RETURN(callback_is_secure || (NULL != p_callback_memory_checked), FSP_ERR_NO_CALLBACK_MEMORY);
476  #endif
477 #endif
478 
479     /* Store callback and context */
480 #if BSP_TZ_SECURE_BUILD
481     p_ctrl->p_callback = callback_is_secure ? p_callback :
482                          (void (*)(timer_callback_args_t *))cmse_nsfptr_create(p_callback);
483 #else
484     p_ctrl->p_callback = p_callback;
485 #endif
486     p_ctrl->p_context         = p_context;
487     p_ctrl->p_callback_memory = p_callback_memory;
488 
489     return FSP_SUCCESS;
490 }
491 
492 /*******************************************************************************************************************//**
493  * Stops counter, disables interrupts, disables output pins, and clears internal driver data.  Implements
494  * @ref timer_api_t::close.
495  *
496  *
497  *
498  * @retval FSP_SUCCESS                 Timer closed.
499  * @retval FSP_ERR_ASSERTION           p_ctrl is NULL.
500  * @retval FSP_ERR_NOT_OPEN            The instance control structure is not opened.
501  **********************************************************************************************************************/
R_ULPT_Close(timer_ctrl_t * const p_ctrl)502 fsp_err_t R_ULPT_Close (timer_ctrl_t * const p_ctrl)
503 {
504     ulpt_instance_ctrl_t * p_instance_ctrl = (ulpt_instance_ctrl_t *) p_ctrl;
505 
506     fsp_err_t err = r_ulpt_common_preamble(p_instance_ctrl);
507     FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
508 
509     /* Cleanup the device: Stop counter, disable interrupts, and power down if no other channels are in use. */
510 
511     /* Stop timer */
512     p_instance_ctrl->p_reg->ULPTCR = ULPT_PRV_ULPTCR_FORCE_STOP_TIMER;
513 
514     /* Clear ULPT output. */
515     p_instance_ctrl->p_reg->ULPTIOC = 0U;
516 
517     if (FSP_INVALID_VECTOR != p_instance_ctrl->p_cfg->cycle_end_irq)
518     {
519         NVIC_DisableIRQ(p_instance_ctrl->p_cfg->cycle_end_irq);
520         R_FSP_IsrContextSet(p_instance_ctrl->p_cfg->cycle_end_irq, p_instance_ctrl);
521     }
522 
523     p_instance_ctrl->open = 0U;
524 
525     return FSP_SUCCESS;
526 }
527 
528 /** @} (end addtogroup ULPT) */
529 
530 /***********************************************************************************************************************
531  * Private Functions
532  **********************************************************************************************************************/
533 
534 #if ULPT_CFG_PARAM_CHECKING_ENABLE
535 
536 /*******************************************************************************************************************//**
537  * Parameter checking for R_ULPT_Open.
538  *
539  * @param[in] p_instance_ctrl              Pointer to instance control structure.
540  * @param[in] p_cfg                        Configuration structure for this instance
541  *
542  * @retval FSP_SUCCESS                     Initialization was successful and timer has started.
543  * @retval FSP_ERR_ASSERTION               A required input pointer is NULL or an invalid parameter exists.
544  * @retval FSP_ERR_ALREADY_OPEN            R_ULPT_Open has already been called for this p_ctrl.
545  * @retval FSP_ERR_IRQ_BSP_DISABLED        A required interrupt has not been enabled in the vector table.
546  * @retval FSP_ERR_IP_CHANNEL_NOT_PRESENT  Requested channel number is not available on ULPT.
547  **********************************************************************************************************************/
r_ulpt_open_param_checking(ulpt_instance_ctrl_t * p_instance_ctrl,timer_cfg_t const * const p_cfg)548 static fsp_err_t r_ulpt_open_param_checking (ulpt_instance_ctrl_t * p_instance_ctrl, timer_cfg_t const * const p_cfg)
549 {
550     FSP_ASSERT(NULL != p_instance_ctrl);
551     FSP_ASSERT(NULL != p_cfg);
552     FSP_ASSERT(NULL != p_cfg->p_extend);
553     FSP_ERROR_RETURN(ULPT_OPEN != p_instance_ctrl->open, FSP_ERR_ALREADY_OPEN);
554 
555     /* Validate channel number. */
556     FSP_ERROR_RETURN(((1U << p_cfg->channel) & BSP_FEATURE_ULPT_VALID_CHANNEL_MASK), FSP_ERR_IP_CHANNEL_NOT_PRESENT);
557 
558     /* Enable IRQ if user supplied a callback function,
559      *  or if the timer is a one-shot timer (so the driver is able to
560      *  turn off the timer after one period. */
561     if ((NULL != p_cfg->p_callback) || (TIMER_MODE_ONE_SHOT == p_cfg->mode))
562     {
563         /* Return error if IRQ is required and not in the vector table. */
564         FSP_ERROR_RETURN(p_cfg->cycle_end_irq >= 0, FSP_ERR_IRQ_BSP_DISABLED);
565     }
566 
567     ulpt_extended_cfg_t const * p_extend = (ulpt_extended_cfg_t const *) p_cfg->p_extend;
568 
569     /* Validate mode specific settings. */
570     if ((ULPT_CLOCK_LOCO == p_extend->count_source) || (ULPT_CLOCK_SUBCLOCK == p_extend->count_source))
571     {
572         /* Timer mode */
573 
574         /* Validate the divider. */
575         FSP_ASSERT(p_cfg->source_div <= TIMER_SOURCE_DIV_128);
576 
577         /* Count enable,start,amd restart functions are not allowed in timer mode. */
578         FSP_ASSERT(p_extend->enable_function != ULPT_ENABLE_FUNCTION_ENABLE_LOW);
579         FSP_ASSERT(p_extend->enable_function != ULPT_ENABLE_FUNCTION_ENABLE_HIGH);
580         FSP_ASSERT(p_extend->enable_function != ULPT_ENABLE_FUNCTION_START);
581         FSP_ASSERT(p_extend->enable_function != ULPT_ENABLE_FUNCTION_RESTART);
582     }
583     else
584     {
585         /* Event counter mode */
586         /* No Divider allowed. */
587         FSP_ASSERT(p_cfg->source_div <= TIMER_SOURCE_DIV_1);
588     }
589 
590     return FSP_SUCCESS;
591 }
592 
593 #endif
594 
595 /*******************************************************************************************************************//**
596  * Common code at the beginning of all ULPT functions except open.
597  *
598  * @param[in] p_instance_ctrl          Pointer to instance control structure.
599  *
600  * @retval FSP_SUCCESS                 No invalid conditions detected, timer state matches expected state.
601  * @retval FSP_ERR_ASSERTION           p_ctrl is null.
602  * @retval FSP_ERR_NOT_OPEN            The instance control structure is not opened.
603  **********************************************************************************************************************/
r_ulpt_common_preamble(ulpt_instance_ctrl_t * p_instance_ctrl)604 static fsp_err_t r_ulpt_common_preamble (ulpt_instance_ctrl_t * p_instance_ctrl)
605 {
606 #if ULPT_CFG_PARAM_CHECKING_ENABLE
607     FSP_ASSERT(NULL != p_instance_ctrl);
608     FSP_ERROR_RETURN(ULPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
609 #endif
610 
611     /* Ensure timer state reflects expected status. */
612     uint32_t ulptcr_tstart = p_instance_ctrl->p_reg->ULPTCR_b.TSTART;
613     FSP_HARDWARE_REGISTER_WAIT(ulptcr_tstart, p_instance_ctrl->p_reg->ULPTCR_b.TCSTF);
614 
615     return FSP_SUCCESS;
616 }
617 
618 /*******************************************************************************************************************//**
619  * Sets count source, divider, and other hardware registers.
620  *
621  * @note Counter must be stopped before entering this function.
622  *
623  * @param[in]  p_instance_ctrl    Control block for this instance
624  * @param[in]  p_cfg              Configuration structure for this instance
625  **********************************************************************************************************************/
626 
r_ulpt_hardware_cfg(ulpt_instance_ctrl_t * p_instance_ctrl,timer_cfg_t const * const p_cfg)627 static void r_ulpt_hardware_cfg (ulpt_instance_ctrl_t * p_instance_ctrl, timer_cfg_t const * const p_cfg)
628 {
629     ulpt_extended_cfg_t const * p_extend = (ulpt_extended_cfg_t const *) p_cfg->p_extend;
630 
631     /* ULPT register locals */
632     uint32_t ulptmr1  = 0U;
633     uint32_t ulptmr2  = 0U;
634     uint32_t ulptmr3  = 0U;
635     uint32_t ulptioc  = 0U;
636     uint32_t ulptisr  = 0U;
637     uint32_t ulptcmsr = 0U;
638 
639     /* Configure the count source(LOCO or SCK) and mode(event or Timer). */
640     ulptmr1 |= p_extend->count_source & (R_ULPT0_ULPTMR1_TMOD1_Msk | R_ULPT0_ULPTMR1_TCK1_Msk);
641 
642     if (TIMER_MODE_ONE_SHOT == p_cfg->mode)
643     {
644         ulptmr3 |= R_ULPT0_ULPTMR3_TCNTCTL_Msk;
645     }
646 
647     if (p_extend->count_source != ULPT_CLOCK_ULPTEVI)
648     {
649         /* Timer mode */
650         ulptmr1 &= ~R_ULPT0_ULPTMR1_TMOD1_Msk;
651 
652         /* The divider is only used for normal timer operation. */
653         ulptmr2 |= p_cfg->source_div & R_ULPT0_ULPTMR2_CKS_Msk;
654     }
655 
656 #if ULPT_CFG_INPUT_SUPPORT_ENABLE
657     else                               // (p_extend->count_source == ULPT_CLOCK_ULPTEVI)
658     {
659         /* Event counter mode */
660         ulptmr1 |= R_ULPT0_ULPTMR1_TMOD1_Msk;
661 
662         /* Set the edge selection for for event pin. */
663         /*  For Falling we set it for rising edge and flip the polarity */
664         ulptmr1 |= p_extend->event_pin & R_ULPT0_ULPTMR1_TEDGPL_Msk;
665         ulptmr3 |= p_extend->event_pin & R_ULPT0_ULPTMR3_TEVPOL_Msk;
666 
667         /* Configure input filtering */
668         ulptioc |= p_extend->ulptevi_filter & R_ULPT0_ULPTIOC_TIPF_Msk;
669 
670         /* Select if the ULPTEE pin should be ignored. */
671         ulptioc |= p_extend->enable_function & R_ULPT0_ULPTIOC_TIOGT0_Msk;
672 
673         /* Set the active polarity for ULPTEE. This is only set for count enable function. */
674         ulptisr |= p_extend->enable_function & R_ULPT0_ULPTISR_RCCPSEL2_Msk;
675     }
676 #endif
677 
678     /* ULPTEE can be used in either timer or event mode. */
679     /* Configure ULPTEE pin function and edge polarity for start or restart functions. */
680     ulptmr3 |= p_extend->enable_function & R_ULPT0_ULPTMR3_TEECTL_Msk;
681     ulptmr3 |= p_extend->trigger_edge & R_ULPT0_ULPTMR3_TEEPOL_Msk;
682 
683 #if ULPT_CFG_OUTPUT_SUPPORT_ENABLE
684 
685     /* Set output if requested. */
686     if (p_extend->ulpto != ULPT_PULSE_PIN_CFG_DISABLED)
687     {
688         ulptioc |= R_ULPT0_ULPTIOC_TOE_Msk;
689 
690         /* Now set the polarity*/
691         if (p_extend->ulpto == ULPT_PULSE_PIN_CFG_ENABLED_START_LEVEL_HIGH)
692         {
693             ulptmr3 |= R_ULPT0_ULPTMR3_TOPOL_Msk;
694         }
695         else
696         {
697             ulptmr3 &= ~R_ULPT0_ULPTMR3_TOPOL_Msk;
698         }
699     }
700 
701     /* set enable match, output, and polarity of both match outputs*/
702     ulptcmsr = p_extend->ulptoab_settings & ULPT_PRV_ULPTCMSR_VALID_BITS;
703 
704     /* Set initial duty cycle for PWM mode in open.  Duty cycle is set for other modes in r_agt_period_register_set. */
705     if (TIMER_MODE_PWM == p_instance_ctrl->p_cfg->mode)
706     {
707         uint32_t inverted_duty_cycle = p_instance_ctrl->p_cfg->period_counts -
708                                        p_instance_ctrl->p_cfg->duty_cycle_counts - 1;
709 
710         /*In this driver match A and match b have the same duty cycle*/
711         uint32_t ulptcma = p_instance_ctrl->p_cfg->duty_cycle_counts;
712         uint32_t ulptcmb = p_instance_ctrl->p_cfg->duty_cycle_counts;
713         if (ULPT_MATCH_PIN_CFG_DISABLED != p_extend->ulptoab_settings_b.ulptoa)
714         {
715             if (ULPT_MATCH_PIN_CFG_START_LEVEL_HIGH == p_extend->ulptoab_settings_b.ulptoa)
716             {
717                 ulptcma = inverted_duty_cycle;
718             }
719 
720             p_instance_ctrl->p_reg->ULPTCMA = ulptcma;
721         }
722 
723         if (ULPT_MATCH_PIN_CFG_DISABLED != p_extend->ulptoab_settings_b.ulptob)
724         {
725             if (ULPT_MATCH_PIN_CFG_START_LEVEL_HIGH == p_extend->ulptoab_settings_b.ulptob)
726             {
727                 ulptcmb = inverted_duty_cycle;
728             }
729 
730             p_instance_ctrl->p_reg->ULPTCMB = ulptcmb;
731         }
732     }
733 #endif
734 
735     p_instance_ctrl->p_reg->ULPTMR1  = (uint8_t) ulptmr1;
736     p_instance_ctrl->p_reg->ULPTMR2  = (uint8_t) ulptmr2;
737     p_instance_ctrl->p_reg->ULPTMR3  = (uint8_t) ulptmr3;
738     p_instance_ctrl->p_reg->ULPTIOC  = (uint8_t) ulptioc;
739     p_instance_ctrl->p_reg->ULPTISR  = (uint8_t) ulptisr;
740     p_instance_ctrl->p_reg->ULPTCMSR = (uint8_t) ulptcmsr;
741 }
742 
743 /*******************************************************************************************************************//**
744  * Sets period register and updates compare match registers in one-shot and periodic mode.
745  *
746  * @param[in]  p_instance_ctrl    Control block for this instance
747  * @param[in]  period_counts      ULPT period in counts
748  **********************************************************************************************************************/
r_ulpt_period_register_set(ulpt_instance_ctrl_t * p_instance_ctrl,uint32_t period_counts)749 static void r_ulpt_period_register_set (ulpt_instance_ctrl_t * p_instance_ctrl, uint32_t period_counts)
750 {
751     /* Store the period value so it can be retrieved later. */
752     p_instance_ctrl->period = period_counts;
753 
754     uint32_t period_reg = period_counts - 1U;
755 
756 #if ULPT_CFG_OUTPUT_SUPPORT_ENABLE
757     uint32_t duty_cycle_counts = 0U;
758     if (TIMER_MODE_PERIODIC == p_instance_ctrl->p_cfg->mode)
759     {
760         duty_cycle_counts = (period_counts >> 1);
761     }
762     else if (TIMER_MODE_ONE_SHOT == p_instance_ctrl->p_cfg->mode)
763     {
764         duty_cycle_counts = period_reg;
765     }
766     else
767     {
768         /* Do nothing, duty cycle should not be updated in R_ULPT_PeriodSet. */
769     }
770 
771     if (TIMER_MODE_PWM != p_instance_ctrl->p_cfg->mode)
772     {
773         p_instance_ctrl->p_reg->ULPTCMA = duty_cycle_counts;
774         p_instance_ctrl->p_reg->ULPTCMB = duty_cycle_counts;
775     }
776 #endif
777 
778     /* Set counter to period minus one. */
779     p_instance_ctrl->p_reg->ULPTCNT = period_reg;
780 }
781 
782 /*******************************************************************************************************************//**
783  * Obtains the clock frequency of ULPT for all clock sources
784  *
785  * @param[in]  p_ulpt_regs         Registers of ULPT channel used
786  *
787  * @return Source clock frequency of ULPT in Hz with prescaler divider applied
788  **********************************************************************************************************************/
r_ulpt_clock_frequency_get(R_ULPT0_Type * p_ulpt_regs)789 static uint32_t r_ulpt_clock_frequency_get (R_ULPT0_Type * p_ulpt_regs)
790 {
791     uint32_t clock_freq_hz    = 0U;
792     uint8_t  count_source_int = p_ulpt_regs->ULPTMR1_b.TCK1;
793     uint8_t  divider          = p_ulpt_regs->ULPTMR2_b.CKS;
794 
795     if (ULPT_CLOCK_SUBCLOCK == (count_source_int & R_ULPT0_ULPTMR1_TCK1_Msk))
796     {
797         clock_freq_hz = BSP_SUBCLOCK_FREQ_HZ;
798     }
799     else
800     {
801         clock_freq_hz = BSP_LOCO_FREQ_HZ;
802     }
803 
804     clock_freq_hz >>= divider;
805 
806     return clock_freq_hz;
807 }
808 
809 /*********************************************************************************************************************
810  * AGT counter underflow interrupt.
811  **********************************************************************************************************************/
ulpt_int_isr(void)812 void ulpt_int_isr (void)
813 {
814     /* Save context if RTOS is used */
815     FSP_CONTEXT_SAVE
816     uint32_t  statusMask;
817     IRQn_Type irq = R_FSP_CurrentIrqGet();
818 
819     /* Clear pending IRQ to make sure it doesn't fire again after exiting */
820     R_BSP_IrqStatusClear(irq);
821 
822     /* Recover ISR context saved in open. */
823     ulpt_instance_ctrl_t * p_instance_ctrl = (ulpt_instance_ctrl_t *) R_FSP_IsrContextGet(irq);
824 
825     /* Save ULPTCR to determine the source of the interrupt. */
826     uint32_t ulptcr = p_instance_ctrl->p_reg->ULPTCR;
827 
828     /* Invoke the callback function if it is set. */
829     if (NULL != p_instance_ctrl->p_callback)
830     {
831         /* Setup parameters for the user-supplied callback function. */
832         timer_callback_args_t callback_args;
833 
834         /* Store callback arguments in memory provided by user if available.  This allows callback arguments to be
835          * stored in non-secure memory so they can be accessed by a non-secure callback function. */
836         timer_callback_args_t * p_args = p_instance_ctrl->p_callback_memory;
837         if (NULL == p_args)
838         {
839             /* Store on stack */
840             p_args = &callback_args;
841         }
842         else
843         {
844             /* Save current arguments on the stack in case this is a nested interrupt. */
845             callback_args = *p_args;
846         }
847 
848         if (ulptcr & R_ULPT0_ULPTCR_TUNDF_Msk)
849         {
850             p_args->event = TIMER_EVENT_CYCLE_END;
851         }
852         else if (ulptcr & R_ULPT0_ULPTCR_TCMAF_Msk)
853         {
854             p_args->event = TIMER_EVENT_CAPTURE_A;
855         }
856         else if (ulptcr & R_ULPT0_ULPTCR_TCMBF_Msk)
857         {
858             p_args->event = TIMER_EVENT_CAPTURE_B;
859         }
860         else
861         {
862         }
863 
864         p_args->p_context = p_instance_ctrl->p_context;
865 
866 #if BSP_TZ_SECURE_BUILD
867 
868         /* p_callback can point to a secure function or a non-secure function. */
869         if (!cmse_is_nsfptr(p_instance_ctrl->p_callback))
870         {
871             /* If p_callback is secure, then the project does not need to change security state. */
872             p_instance_ctrl->p_callback(p_args);
873         }
874         else
875         {
876             /* If p_callback is Non-secure, then the project must change to Non-secure state in order to call the callback. */
877             ulpt_prv_ns_callback p_callback = (ulpt_prv_ns_callback) (p_instance_ctrl->p_callback);
878             p_callback(p_args);
879         }
880 
881 #else
882 
883         /* If the project is not Trustzone Secure, then it will never need to change security state in order to call the callback. */
884         p_instance_ctrl->p_callback(p_args);
885 #endif
886 
887         if (NULL != p_instance_ctrl->p_callback_memory)
888         {
889             /* Restore callback memory in case this is a nested interrupt. */
890             *p_instance_ctrl->p_callback_memory = callback_args;
891         }
892 
893         /* Retreive AGTCR in case it was modified in the callback. */
894         ulptcr = p_instance_ctrl->p_reg->ULPTCR;
895     }
896 
897     /* Clear flags in AGTCR. */
898     /* In one shot mode we need to stop the timer*/
899     statusMask = ULPT_PRV_ULPTCR_STATUS_FLAGS;
900     if (p_instance_ctrl->p_reg->ULPTMR3 & R_ULPT0_ULPTMR3_TCNTCTL_Msk)
901     {
902         statusMask |= R_ULPT0_ULPTCR_TSTART_Msk;
903     }
904 
905     p_instance_ctrl->p_reg->ULPTCR = (uint8_t) (ulptcr & ~statusMask);
906 
907     /* Restore context if RTOS is used */
908     FSP_CONTEXT_RESTORE
909 }
910