1 /***********************************************************************************************************************
2 * Copyright [2015-2017] Renesas Electronics Corporation and/or its licensors. All Rights Reserved.
3 *
4 * This file is part of Renesas SynergyTM Software Package (SSP)
5 *
6 * The contents of this file (the "contents") are proprietary and confidential to Renesas Electronics Corporation
7 * and/or its licensors ("Renesas") and subject to statutory and contractual protections.
8 *
9 * This file is subject to a Renesas SSP license agreement. Unless otherwise agreed in an SSP license agreement with
10 * Renesas: 1) you may not use, copy, modify, distribute, display, or perform the contents; 2) you may not use any name
11 * or mark of Renesas for advertising or publicity purposes or in connection with your use of the contents; 3) RENESAS
12 * MAKES NO WARRANTY OR REPRESENTATIONS ABOUT THE SUITABILITY OF THE CONTENTS FOR ANY PURPOSE; THE CONTENTS ARE PROVIDED
13 * "AS IS" WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
14 * PARTICULAR PURPOSE, AND NON-INFRINGEMENT; AND 4) RENESAS SHALL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, OR
15 * CONSEQUENTIAL DAMAGES, INCLUDING DAMAGES RESULTING FROM LOSS OF USE, DATA, OR PROJECTS, WHETHER IN AN ACTION OF
16 * CONTRACT OR TORT, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE CONTENTS. Third-party contents
17 * included in this file may be subject to different terms.
18 **********************************************************************************************************************/
19
20 /**********************************************************************************************************************
21 * File Name : r_cgc.c
22 * Description : HAL driver for the Clock Generation circuit.
23 **********************************************************************************************************************/
24
25
26 /***********************************************************************************************************************
27 * Includes
28 **********************************************************************************************************************/
29 #include "r_cgc.h"
30 #include "r_cgc_private.h"
31 #include "r_cgc_private_api.h"
32 #include "./hw/hw_cgc_private.h"
33 /* Configuration for this package. */
34 #include "r_cgc_cfg.h"
35 #include "./hw/hw_cgc.h"
36
37 #if (1 == BSP_CFG_RTOS)
38 #include "tx_api.h"
39 #endif
40
41
42 /***********************************************************************************************************************
43 * Macro definitions
44 **********************************************************************************************************************/
45 /** Macro for error logger. */
46 #ifndef CGC_ERROR_RETURN
47 /*LDRA_INSPECTED 77 S This macro does not work when surrounded by parentheses. */
48 #define CGC_ERROR_RETURN(a, err) SSP_ERROR_RETURN((a), (err), g_module_name, &g_cgc_version)
49 #endif
50
51 #ifndef CGC_ERROR_LOG
52 /*LDRA_INSPECTED 77 S This macro does not work when surrounded by parentheses. */
53 #define CGC_ERROR_LOG(err) SSP_ERROR_LOG((err), g_module_name, &g_cgc_version)
54 #endif
55
56 #define CGC_LDC_INVALID_CLOCK (0xFFU)
57
58 #define CGC_LCD_CFG_TIMEOUT (0xFFFFFU)
59 #define CGC_SDADC_CFG_TIMEOUT (0xFFFFFU)
60
61 /* From user's manual and discussions with hardware group,
62 * using the maximum is safe for all MCUs, will be updated and restored in LPMV2 when entering
63 * low power mode on S7 and S5 MCUs (lowPowerModeEnter())
64 */
65 #define MAXIMUM_HOCOWTR_HSTS ((uint8_t)0x6U)
66
67 #define CGC_PLL_DIV_1_SETTING 0
68 #define CGC_PLL_DIV_2_SETTING 1
69 #define CGC_PLL_DIV_4_SETTING 2
70
71 #if BSP_FEATURE_HAS_CGC_PLL
72 #define CGC_CLOCK_NUM_CLOCKS ((uint8_t) CGC_CLOCK_PLL + 1U)
73 #else
74 #define CGC_CLOCK_NUM_CLOCKS ((uint8_t) CGC_CLOCK_SUBCLOCK + 1U)
75 #endif
76
77 /***********************************************************************************************************************
78 * Typedef definitions
79 **********************************************************************************************************************/
80
81 /***********************************************************************************************************************
82 * Private function prototypes
83 **********************************************************************************************************************/
84 static ssp_err_t r_cgc_clock_start_stop(cgc_clock_change_t clock_state, cgc_clock_t clock_to_change, cgc_clocks_cfg_t const *p_clk_cfg);
85 static ssp_err_t r_cgc_stabilization_wait(cgc_clock_t clock);
86
87 #if (CGC_CFG_PARAM_CHECKING_ENABLE == 1)
88 static ssp_err_t r_cgc_check_peripheral_clocks(cgc_system_clocks_t clock);
89 static ssp_err_t r_cgc_check_dividers(cgc_system_clock_cfg_t const * const p_clock_cfg, uint32_t min_div);
90 static ssp_err_t r_cgc_check_config_dividers(cgc_system_clock_cfg_t const * const p_clock_cfg);
91 #if BSP_FEATURE_HAS_CGC_PLL
92 static bool r_cgc_clockcfg_valid_check (cgc_clock_cfg_t * cfg);
93 #endif
94 #endif
95
96 static bool r_cgc_subosc_mode_possible(void);
97 static bool r_cgc_low_speed_mode_possible(void);
98 static void r_cgc_operating_mode_set(cgc_clock_t const clock_source, uint32_t const current_system_clock);
99 static ssp_err_t r_cgc_wait_to_complete(cgc_clock_t const clock_source, cgc_clock_change_t option);
100 static ssp_err_t r_cgc_clock_running_status_check(cgc_clock_t const clock_source);
101 static void r_cgc_adjust_subosc_speed_mode(void);
102 static ssp_err_t r_cgc_apply_start_stop_options(cgc_clocks_cfg_t const * const p_clock_cfg, cgc_clock_change_t const * const options);
103 static void r_cgc_hw_init (void);
104 static void r_cgc_main_clock_drive_set (R_SYSTEM_Type * p_system_reg, uint8_t val);
105 static void r_cgc_subclock_drive_set (R_SYSTEM_Type * p_system_reg, uint8_t val);
106 static void r_cgc_clock_start (R_SYSTEM_Type * p_system_reg, cgc_clock_t clock);
107 static void r_cgc_clock_stop (R_SYSTEM_Type * p_system_reg, cgc_clock_t clock);
108 static bool r_cgc_clock_check (R_SYSTEM_Type * p_system_reg, cgc_clock_t clock);
109 static void r_cgc_mainosc_source_set (R_SYSTEM_Type * p_system_reg, cgc_osc_source_t osc);
110 static void r_cgc_clock_wait_set (R_SYSTEM_Type * p_system_reg, cgc_clock_t clock, uint8_t time);
111 static void r_cgc_clock_source_set (R_SYSTEM_Type * p_system_reg, cgc_clock_t clock);
112 static void r_cgc_system_dividers_get (R_SYSTEM_Type * p_system_reg, cgc_system_clock_cfg_t * cfg);
113 static uint32_t r_cgc_clock_divider_get (R_SYSTEM_Type * p_system_reg, cgc_system_clocks_t clock);
114 static uint32_t r_cgc_clock_hzget (R_SYSTEM_Type * p_system_reg, cgc_system_clocks_t clock);
115 static uint32_t r_cgc_clockhz_calculate (cgc_clock_t source_clock, cgc_sys_clock_div_t divider);
116 static void r_cgc_oscstop_detect_enable (R_SYSTEM_Type * p_system_reg);
117 static void r_cgc_oscstop_detect_disable (R_SYSTEM_Type * p_system_reg);
118 static bool r_cgc_oscstop_status_clear (R_SYSTEM_Type * p_system_reg);
119 static void r_cgc_clockout_cfg (R_SYSTEM_Type * p_system_reg, cgc_clock_t clock, cgc_clockout_dividers_t divider);
120 static void r_cgc_clockout_enable (R_SYSTEM_Type * p_system_reg);
121 static void r_cgc_clockout_disable (R_SYSTEM_Type * p_system_reg);
122 static bool r_cgc_systick_update(uint32_t ticks_per_second);
123 static void r_cgc_system_dividers_set (R_SYSTEM_Type * p_system_reg, cgc_system_clock_cfg_t const * const cfg);
124
125 #if BSP_FEATURE_HAS_CGC_PLL
126 static ssp_err_t r_cgc_prepare_pll_clock(cgc_clock_cfg_t * p_clock_cfg);
127 static void r_cgc_init_pllfreq (R_SYSTEM_Type * p_system_reg);
128 static cgc_clock_t r_cgc_pll_clocksource_get (R_SYSTEM_Type * p_system_reg);
129 #if BSP_FEATURE_HAS_CGC_PLL_SRC_CFG
130 static void r_cgc_pll_clocksource_set (R_SYSTEM_Type * p_system_reg, cgc_clock_t clock);
131 #endif
132 /*LDRA_INSPECTED 90 s float used because float32_t is not part of the C99 standard integer definitions. */
133 static void r_cgc_pll_multiplier_set (R_SYSTEM_Type * p_system_reg, float multiplier);
134 /*LDRA_INSPECTED 90 s float used because float32_t is not part of the C99 standard integer definitions. */
135 static float r_cgc_pll_multiplier_get (R_SYSTEM_Type * p_system_reg);
136 static void r_cgc_pll_divider_set (R_SYSTEM_Type * p_system_reg, cgc_pll_div_t divider);
137 static uint16_t r_cgc_pll_divider_get (R_SYSTEM_Type * p_system_reg);
138 #endif /* #if BSP_FEATURE_HAS_CGC_PLL */
139
140 #if (CGC_CFG_SUBCLOCK_AT_RESET_ENABLE == 1)
141 static void r_cgc_delay_cycles (R_SYSTEM_Type * p_system_reg, cgc_clock_t clock, uint16_t cycles);
142 #endif
143
144 /***********************************************************************************************************************
145 * Private global variables
146 **********************************************************************************************************************/
147 #if defined(__GNUC__)
148 /* This structure is affected by warnings from a GCC compiler bug. This pragma suppresses the warnings in this
149 * structure only.*/
150 /*LDRA_INSPECTED 69 S */
151 #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
152 #endif
153 /** Version data structure used by error logger macro. */
154 static const ssp_version_t g_cgc_version =
155 {
156 .api_version_minor = CGC_API_VERSION_MINOR,
157 .api_version_major = CGC_API_VERSION_MAJOR,
158 .code_version_major = CGC_CODE_VERSION_MAJOR,
159 .code_version_minor = CGC_CODE_VERSION_MINOR
160 };
161 #if defined(__GNUC__)
162 /* Restore warning settings for 'missing-field-initializers' to as specified on command line. */
163 /*LDRA_INSPECTED 69 S */
164 #pragma GCC diagnostic pop
165 #endif
166
167 /** Name of module used by error logger macro */
168 #if BSP_CFG_ERROR_LOG != 0
169 static const char g_module_name[] = "cgc";
170 #endif
171 /*LDRA_NOANALYSIS LDRA_INSPECTED below not working. */
172 /* This is initialized in cgc_api_t::init, which is called before the C runtime environment is initialized. */
173 /*LDRA_INSPECTED 219 S */
174 bsp_feature_cgc_t const * gp_cgc_feature BSP_PLACE_IN_SECTION_V2(".noinit");
175 /*LDRA_ANALYSIS */
176
177 /** Pointer to CGC base register. */
178 /* This variable is not initialized at declaration because it is initialized and used before C runtime initialization. */
179 /*LDRA_INSPECTED 57 D *//*LDRA_INSPECTED 57 D */
180 static R_SYSTEM_Type * gp_system_reg BSP_PLACE_IN_SECTION_V2(".noinit");
181
182 #if BSP_FEATURE_HAS_CGC_LCD_CLK
183 /** LCD clock selection register values. */
184 static const uint8_t g_lcd_clock_settings[] =
185 {
186 [CGC_CLOCK_HOCO] = 0x04U, ///< The high speed on chip oscillator.
187 [CGC_CLOCK_MOCO] = CGC_LDC_INVALID_CLOCK,
188 [CGC_CLOCK_LOCO] = 0x00U, ///< The low speed on chip oscillator.
189 [CGC_CLOCK_MAIN_OSC] = 0x02U, ///< The main oscillator.
190 [CGC_CLOCK_SUBCLOCK] = 0x01U, ///< The subclock oscillator.
191 #if BSP_FEATURE_HAS_CGC_PLL
192 [CGC_CLOCK_PLL] = CGC_LDC_INVALID_CLOCK,
193 #endif /* #if BSP_FEATURE_HAS_CGC_PLL */
194 };
195 #endif /* #if BSP_FEATURE_HAS_CGC_LCD_CLK */
196
197
198 /** This section of RAM should not be initialized by the C runtime environment */
199 /*LDRA_NOANALYSIS LDRA_INSPECTED below not working. */
200 /* This is initialized in cgc_api_t::init, which is called before the C runtime environment is initialized. */
201 /*LDRA_INSPECTED 219 S */
202 static uint32_t g_clock_freq[CGC_CLOCK_NUM_CLOCKS] BSP_PLACE_IN_SECTION_V2(".noinit");
203 /*LDRA_ANALYSIS */
204
205 #if BSP_FEATURE_HAS_CGC_PLL
206 /** These are the divisor values to use when calculating the system clock frequency, using the CGC_PLL_DIV enum type */
207 static const uint16_t g_pllccr_div_value[] =
208 {
209 [CGC_PLL_DIV_1] = 0x01U,
210 [CGC_PLL_DIV_2] = 0x02U,
211 [CGC_PLL_DIV_3] = 0x03U
212 };
213 /** These are the values to use to set the PLL divider register according to the CGC_PLL_DIV enum type */
214 static const uint16_t g_pllccr_div_setting[] =
215 {
216 [CGC_PLL_DIV_1] = 0x00U,
217 [CGC_PLL_DIV_2] = 0x01U,
218 [CGC_PLL_DIV_3] = 0x02U
219 };
220 /** These are the divisor values to use when calculating the system clock frequency, using the CGC_PLL_DIV enum type */
221 static const uint16_t g_pllccr2_div_value[] =
222 {
223 [CGC_PLL_DIV_1_SETTING] = 0x01U,
224 [CGC_PLL_DIV_2_SETTING] = 0x02U,
225 [CGC_PLL_DIV_4_SETTING] = 0x04U
226 };
227
228 /** These are the values to use to set the PLL divider register according to the CGC_PLL_DIV enum type */
229 static const uint16_t g_pllccr2_div_setting[] =
230 {
231 [CGC_PLL_DIV_1] = 0x00U,
232 [CGC_PLL_DIV_2] = 0x01U,
233 [CGC_PLL_DIV_4] = 0x02U
234 };
235 #endif
236
237
238
239 /***********************************************************************************************************************
240 * Global Variables
241 **********************************************************************************************************************/
242 /*LDRA_INSPECTED 27 D This structure must be accessible in user code. It cannot be static. */
243 const cgc_api_t g_cgc_on_cgc =
244 {
245 .init = R_CGC_Init,
246 .clocksCfg = R_CGC_ClocksCfg,
247 .clockStart = R_CGC_ClockStart,
248 .clockStop = R_CGC_ClockStop,
249 .systemClockSet = R_CGC_SystemClockSet,
250 .systemClockGet = R_CGC_SystemClockGet,
251 .systemClockFreqGet = R_CGC_SystemClockFreqGet,
252 .clockCheck = R_CGC_ClockCheck,
253 .oscStopDetect = R_CGC_OscStopDetect,
254 .oscStopStatusClear = R_CGC_OscStopStatusClear,
255 .busClockOutCfg = R_CGC_BusClockOutCfg,
256 .busClockOutEnable = R_CGC_BusClockOutEnable,
257 .busClockOutDisable = R_CGC_BusClockOutDisable,
258 .clockOutCfg = R_CGC_ClockOutCfg,
259 .clockOutEnable = R_CGC_ClockOutEnable,
260 .clockOutDisable = R_CGC_ClockOutDisable,
261 .lcdClockCfg = R_CGC_LCDClockCfg,
262 .lcdClockEnable = R_CGC_LCDClockEnable,
263 .lcdClockDisable = R_CGC_LCDClockDisable,
264 .sdadcClockCfg = R_CGC_SDADCClockCfg,
265 .sdadcClockEnable = R_CGC_SDADCClockEnable,
266 .sdadcClockDisable = R_CGC_SDADCClockDisable,
267 .sdramClockOutEnable = R_CGC_SDRAMClockOutEnable,
268 .sdramClockOutDisable = R_CGC_SDRAMClockOutDisable,
269 .usbClockCfg = R_CGC_USBClockCfg,
270 .systickUpdate = R_CGC_SystickUpdate,
271 .versionGet = R_CGC_VersionGet
272 };
273
274 /*******************************************************************************************************************//**
275 * @ingroup HAL_Library
276 * @addtogroup CGC
277 * @brief Clock Generation Circuit Hardware Functions
278 *
279 * @{
280 **********************************************************************************************************************/
281
282 /***********************************************************************************************************************
283 * Functions
284 **********************************************************************************************************************/
285
286 /*******************************************************************************************************************//**
287 * @brief Initialize the CGC API.
288 *
289 * Configures the following for the clock generator module
290 * -If CGC_CFG_SUBCLOCK_AT_RESET_ENABLE is set to true:
291 * - SubClock drive capacity (Compile time configurable: CGC_CFG_SUBCLOCK_DRIVE)
292 * - Initial setting for the SubClock
293 *
294 * THIS FUNCTION MUST BE EXECUTED ONCE AT STARTUP BEFORE ANY OF THE OTHER CGC FUNCTIONS
295 * CAN BE USED OR THE CLOCK SOURCE IS CHANGED FROM THE MOCO.
296 * @retval SSP_SUCCESS Clock initialized successfully.
297 * @retval SSP_ERR_HARDWARE_TIMEOUT Hardware timed out.
298 **********************************************************************************************************************/
R_CGC_Init(void)299 ssp_err_t R_CGC_Init (void)
300 {
301 /* Initialize MCU specific feature pointer. */
302 R_BSP_FeatureCgcGet(&gp_cgc_feature);
303
304 ssp_feature_t ssp_feature= {{(ssp_ip_t) 0U}};
305 fmi_feature_info_t info = {0U};
306 ssp_feature.channel = 0U;
307 ssp_feature.unit = 0U;
308 ssp_feature.id = SSP_IP_CGC;
309 g_fmi_on_fmi.productFeatureGet(&ssp_feature, &info);
310 gp_system_reg = (R_SYSTEM_Type *) info.ptr;
311
312 volatile uint32_t timeout;
313 timeout = MAX_REGISTER_WAIT_COUNT;
314 /* Update HOCOWTCR_b.HSTS */
315 if(true == r_cgc_clock_run_state_get(gp_system_reg, CGC_CLOCK_HOCO))
316 {
317 /* Make sure the HOCO is stable before changing wait control register */
318 while ((false == r_cgc_clock_check(gp_system_reg, CGC_CLOCK_HOCO)) && (0U != timeout))
319 {
320 /* wait until the clock state is stable */
321 timeout--;
322 }
323 CGC_ERROR_RETURN(timeout, SSP_ERR_HARDWARE_TIMEOUT);
324 }
325
326 /* Set HOCOWTCR_b.HSTS */
327 r_cgc_hoco_wait_control_set(gp_system_reg, MAXIMUM_HOCOWTR_HSTS);
328
329 timeout = MAX_REGISTER_WAIT_COUNT;
330 r_cgc_hw_init(); // initialize hardware functions
331
332 /** SubClock will stop only if configurable setting is Enabled */
333 #if (CGC_CFG_SUBCLOCK_AT_RESET_ENABLE == 1)
334 r_cgc_clock_stop(gp_system_reg, CGC_CLOCK_SUBCLOCK); // stop SubClock
335 CGC_ERROR_RETURN((SSP_SUCCESS == r_cgc_wait_to_complete(CGC_CLOCK_SUBCLOCK, CGC_CLOCK_CHANGE_STOP)), SSP_ERR_HARDWARE_TIMEOUT);
336 r_cgc_delay_cycles(gp_system_reg, CGC_CLOCK_SUBCLOCK, SUBCLOCK_DELAY); // Delay for 5 SubClock cycles.
337 r_cgc_subclock_drive_set(gp_system_reg, CGC_CFG_SUBCLOCK_DRIVE); // set the SubClock drive according to the configuration
338 #endif
339 return SSP_SUCCESS;
340 }
341
342 /*******************************************************************************************************************//**
343 * @brief Reconfigure all main system clocks.
344 *
345 * @retval SSP_SUCCESS Clock initialized successfully.
346 * @retval SSP_ERR_INVALID_ARGUMENT Invalid argument used.
347 * @retval SSP_ERR_MAIN_OSC_INACTIVE PLL Initialization attempted with Main OCO turned off/unstable.
348 * @retval SSP_ERR_CLOCK_ACTIVE Active clock source specified for modification. This applies specifically to the
349 * PLL dividers/multipliers which cannot be modified if the PLL is active. It has
350 * to be stopped first before modification.
351 * @retval SSP_ERR_NOT_STABILIZED The Clock source is not stabilized after being turned off.
352 * @retval SSP_ERR_CLKOUT_EXCEEDED The main oscillator can be only 8 or 16 MHz.
353 * @retval SSP_ERR_ASSERTION A NULL is passed for configuration data when PLL is the clock_source.
354 * @retval SSP_ERR_INVALID_MODE Attempt to start a clock in a restricted operating power control mode.
355 *
356 **********************************************************************************************************************/
R_CGC_ClocksCfg(cgc_clocks_cfg_t const * const p_clock_cfg)357 ssp_err_t R_CGC_ClocksCfg(cgc_clocks_cfg_t const * const p_clock_cfg)
358 {
359 #if (CGC_CFG_PARAM_CHECKING_ENABLE == 1)
360 SSP_ASSERT(NULL != p_clock_cfg);
361 #endif /* CGC_CFG_PARAM_CHECKING_ENABLE */
362 ssp_err_t err = SSP_SUCCESS;
363 cgc_clock_t requested_system_clock = p_clock_cfg->system_clock;
364 #if CGC_CFG_PARAM_CHECKING_ENABLE
365 #if BSP_FEATURE_HAS_CGC_PLL
366 cgc_clock_cfg_t * p_pll_cfg = (cgc_clock_cfg_t *)&(p_clock_cfg->pll_cfg);
367 #endif /* BSP_FEATURE_HAS_CGC_PLL */
368 #endif
369 cgc_system_clock_cfg_t sys_cfg = {
370 .pclka_div = CGC_SYS_CLOCK_DIV_1,
371 .pclkb_div = CGC_SYS_CLOCK_DIV_1,
372 .pclkc_div = CGC_SYS_CLOCK_DIV_1,
373 .pclkd_div = CGC_SYS_CLOCK_DIV_1,
374 .bclk_div = CGC_SYS_CLOCK_DIV_1,
375 .fclk_div = CGC_SYS_CLOCK_DIV_1,
376 .iclk_div = CGC_SYS_CLOCK_DIV_1,
377 };
378 bool power_mode_adjustment = false;
379 cgc_clock_t current_system_clock = CGC_CLOCK_HOCO;
380 R_CGC_SystemClockGet(¤t_system_clock, &sys_cfg);
381
382 cgc_clock_change_t options[CGC_CLOCK_NUM_CLOCKS];
383 options[CGC_CLOCK_HOCO] = p_clock_cfg->hoco_state;
384 options[CGC_CLOCK_LOCO] = p_clock_cfg->loco_state;
385 options[CGC_CLOCK_MOCO] = p_clock_cfg->moco_state;
386 options[CGC_CLOCK_MAIN_OSC] = p_clock_cfg->mainosc_state;
387 options[CGC_CLOCK_SUBCLOCK] = p_clock_cfg->subosc_state;
388 #if BSP_FEATURE_HAS_CGC_PLL
389 options[CGC_CLOCK_PLL] = p_clock_cfg->pll_state;
390 #endif /* BSP_FEATURE_HAS_CGC_PLL */
391
392 #if CGC_CFG_PARAM_CHECKING_ENABLE
393 CGC_ERROR_RETURN(HW_CGC_ClockSourceValidCheck(requested_system_clock), SSP_ERR_INVALID_ARGUMENT);
394 CGC_ERROR_RETURN(CGC_CLOCK_CHANGE_STOP != options[p_clock_cfg->system_clock], SSP_ERR_INVALID_ARGUMENT);
395 #if BSP_FEATURE_HAS_CGC_PLL
396 if (CGC_CLOCK_CHANGE_START == options[CGC_CLOCK_PLL])
397 {
398 CGC_ERROR_RETURN(HW_CGC_ClockSourceValidCheck(p_pll_cfg->source_clock), SSP_ERR_INVALID_ARGUMENT);
399 CGC_ERROR_RETURN(CGC_CLOCK_CHANGE_STOP != options[p_pll_cfg->source_clock], SSP_ERR_INVALID_ARGUMENT);
400 }
401 #endif /* BSP_FEATURE_HAS_CGC_PLL */
402 #endif /* CGC_CFG_PARAM_CHECKING_ENABLE */
403
404 err = r_cgc_apply_start_stop_options(p_clock_cfg, &options[0]);
405 CGC_ERROR_RETURN(SSP_SUCCESS == err, err);
406
407 err = r_cgc_stabilization_wait(requested_system_clock);
408 CGC_ERROR_RETURN(SSP_SUCCESS == err, err);
409
410 /* Check if clocks PLL, MOSC, HOCO and MOCO are stopped as a precondition to enter Subosc Speed Mode */
411 /* If not, it will require to review the power mode after setting the clock, because the precondition can change */
412 power_mode_adjustment = (CGC_CLOCK_SUBCLOCK == requested_system_clock) && (!r_cgc_subosc_mode_possible());
413
414 /* Set which clock to use for system clock and divisors for all system clocks. */
415 err = R_CGC_SystemClockSet(requested_system_clock, &(p_clock_cfg->sys_cfg));
416 CGC_ERROR_RETURN(SSP_SUCCESS == err, err);
417
418 /* If the system clock has changed, stop previous system clock if requested. */
419 if (requested_system_clock != current_system_clock)
420 {
421 if (CGC_CLOCK_CHANGE_STOP == options[current_system_clock])
422 {
423 err = r_cgc_clock_start_stop(CGC_CLOCK_CHANGE_STOP, current_system_clock, p_clock_cfg);
424 CGC_ERROR_RETURN(SSP_SUCCESS == err, err);
425 }
426 }
427 if (power_mode_adjustment)
428 {
429 r_cgc_operating_mode_set(requested_system_clock, bsp_cpu_clock_get());
430 }
431
432 return SSP_SUCCESS;
433 }
434
435 /*******************************************************************************************************************//**
436 * @brief Start the specified clock if it is not currently active.
437 *
438 * Configures the following when starting the Main Clock Oscillator:
439 * - MainClock drive capacity (Configured based on external clock frequency)
440 * - MainClock stabilization wait time (Compile time configurable: CGC_CFG_MAIN_OSC_WAIT)
441 * - To update the subclock driven capacity, stop the subclock first before calling this function.
442 **
443 * @retval SSP_SUCCESS Clock initialized successfully.
444 * @retval SSP_ERR_INVALID_ARGUMENT Invalid argument used.
445 * @retval SSP_ERR_MAIN_OSC_INACTIVE PLL Initialization attempted with Main OCO turned off/unstable.
446 * @retval SSP_ERR_CLOCK_ACTIVE Active clock source specified for modification. This applies specifically to the
447 * PLL dividers/multipliers which cannot be modified if the PLL is active. It has
448 * to be stopped first before modification.
449 * @retval SSP_ERR_NOT_STABILIZED The Clock source is not stabilized after being turned off.
450 * @retval SSP_ERR_CLKOUT_EXCEEDED The main oscillator can be only 8 or 16 MHz.
451 * @retval SSP_ERR_ASSERTION A NULL is passed for configuration data when PLL is the clock_source.
452 * @retval SSP_ERR_INVALID_MODE Attempt to start a clock in a restricted operating power control mode.
453 * @retval SSP_ERR_HARDWARE_TIMEOUT Hardware timed out.
454 **********************************************************************************************************************/
455
R_CGC_ClockStart(cgc_clock_t clock_source,cgc_clock_cfg_t * p_clock_cfg)456 ssp_err_t R_CGC_ClockStart (cgc_clock_t clock_source, cgc_clock_cfg_t * p_clock_cfg)
457 {
458
459
460 #if !BSP_FEATURE_HAS_CGC_PLL
461 SSP_PARAMETER_NOT_USED(p_clock_cfg);
462 #endif
463
464 /* return error if invalid clock source or not supported by hardware */
465 CGC_ERROR_RETURN((HW_CGC_ClockSourceValidCheck(clock_source)), SSP_ERR_INVALID_ARGUMENT);
466
467 if (true == r_cgc_clock_run_state_get(gp_system_reg, clock_source))
468 {
469 #if BSP_FEATURE_HAS_CGC_PLL
470 r_cgc_init_pllfreq(gp_system_reg); /* calculate PLL clock frequency and save it */
471 #endif /* BSP_FEATURE_HAS_CGC_PLL */
472 CGC_ERROR_LOG(SSP_ERR_CLOCK_ACTIVE);
473 return SSP_ERR_CLOCK_ACTIVE;
474 }
475
476 /* some clocks (other than LOCO and MOCO require some additional work before starting them */
477 if (CGC_CLOCK_SUBCLOCK == clock_source)
478 {
479 /* Set SubClockDrive only if clock is not running */
480 r_cgc_subclock_drive_set(gp_system_reg, CGC_CFG_SUBCLOCK_DRIVE); //Set the SubClock Drive
481 }
482 else if (CGC_CLOCK_MOCO == clock_source)
483 {
484 r_cgc_adjust_subosc_speed_mode();
485 }
486 else if (CGC_CLOCK_HOCO == clock_source)
487 {
488 /* make sure the oscillator has stopped before starting again */
489 CGC_ERROR_RETURN(!(r_cgc_clock_check(gp_system_reg, CGC_CLOCK_HOCO)), SSP_ERR_NOT_STABILIZED);
490 r_cgc_adjust_subosc_speed_mode();
491 }
492 else if (CGC_CLOCK_MAIN_OSC == clock_source)
493 {
494 /* make sure the oscillator has stopped before starting again */
495 CGC_ERROR_RETURN(!(r_cgc_clock_check(gp_system_reg, CGC_CLOCK_MAIN_OSC)), SSP_ERR_NOT_STABILIZED);
496
497 r_cgc_adjust_subosc_speed_mode();
498 r_cgc_main_clock_drive_set(gp_system_reg, gp_cgc_feature->mainclock_drive); /* set the Main Clock drive according to
499 * the configuration */
500 r_cgc_mainosc_source_set(gp_system_reg, (cgc_osc_source_t) CGC_CFG_MAIN_OSC_CLOCK_SOURCE); /* set the main osc source
501 * to resonator or
502 * external osc. */
503 r_cgc_clock_wait_set(gp_system_reg, CGC_CLOCK_MAIN_OSC, CGC_CFG_MAIN_OSC_WAIT); /* set the main osc wait time */
504 }
505
506 #if BSP_FEATURE_HAS_CGC_PLL
507 /* if clock source is PLL */
508 else if (CGC_CLOCK_PLL == clock_source)
509 {
510 ssp_err_t err;
511 err = r_cgc_prepare_pll_clock(p_clock_cfg);
512 CGC_ERROR_RETURN(SSP_SUCCESS == err, err);
513
514 #if BSP_FEATURE_HAS_CGC_MIDDLE_SPEED
515 /** See if we need to switch to Middle or High Speed mode before starting the PLL. */
516 cgc_system_clock_cfg_t current_clock_cfg1;
517 r_cgc_system_dividers_get(gp_system_reg, ¤t_clock_cfg1); // Get the current iclk divider value.
518 uint32_t requested_frequency_hz = r_cgc_clockhz_calculate(CGC_CLOCK_PLL, current_clock_cfg1.iclk_div);
519 if (requested_frequency_hz > gp_cgc_feature->middle_speed_max_freq_hz)
520 {
521 HW_CGC_SetHighSpeedMode(gp_system_reg);
522 }
523 else
524 {
525 HW_CGC_SetMiddleSpeedMode(gp_system_reg); // PLL will only run in High or Middle Speed modes.
526 }
527 #else
528 HW_CGC_SetHighSpeedMode(gp_system_reg);
529 #endif /* BSP_FEATURE_HAS_CGC_MIDDLE_SPEED */
530
531 }
532 #endif /* BSP_FEATURE_HAS_CGC_PLL */
533
534 else
535 {
536 /* statement here to follow coding standard */
537 }
538
539 r_cgc_clock_start(gp_system_reg, clock_source); // start the clock
540 CGC_ERROR_RETURN((SSP_SUCCESS == r_cgc_wait_to_complete(clock_source, CGC_CLOCK_CHANGE_START)), SSP_ERR_HARDWARE_TIMEOUT);
541
542 return SSP_SUCCESS;
543 }
544
545 /*******************************************************************************************************************//**
546 * @brief Stop the specified clock if it is active and not configured as the system clock.
547 * @retval SSP_SUCCESS Clock stopped successfully.
548 * @retval SSP_ERR_CLOCK_ACTIVE Current System clock source specified for stopping. This is not allowed.
549 * @retval SSP_ERR_OSC_STOP_DET_ENABLED Illegal attempt to stop MOCO when Oscillation stop is enabled.
550 * @retval SSP_ERR_NOT_STABILIZED Clock not stabilized after starting. A finite stabilization time after starting the
551 * clock has to elapse before it can be stopped.
552 * @retval SSP_ERR_INVALID_ARGUMENT Invalid argument used.
553 * @retval SSP_ERR_HARDWARE_TIMEOUT Hardware timed out.
554 **********************************************************************************************************************/
555
R_CGC_ClockStop(cgc_clock_t clock_source)556 ssp_err_t R_CGC_ClockStop (cgc_clock_t clock_source)
557 {
558 cgc_clock_t current_clock;
559
560 /* return error if invalid clock source or not supported by hardware */
561 CGC_ERROR_RETURN(HW_CGC_ClockSourceValidCheck(clock_source), SSP_ERR_INVALID_ARGUMENT);
562
563 current_clock = HW_CGC_ClockSourceGet(gp_system_reg); // The currently active system clock source cannot be stopped
564
565 /* if clock source is the current system clock, return error */
566 CGC_ERROR_RETURN((clock_source != current_clock), SSP_ERR_CLOCK_ACTIVE);
567
568 #if BSP_FEATURE_HAS_CGC_PLL
569 /* If either PLL is the current system clock, or if PLL is not current system clock but it is operating, and the clock source of PLL is same as
570 * requested clock_source to stop, return an error.
571 */
572
573 CGC_ERROR_RETURN(!(((CGC_CLOCK_PLL == current_clock) || (r_cgc_clock_run_state_get(gp_system_reg, CGC_CLOCK_PLL)))
574 && (r_cgc_pll_clocksource_get(gp_system_reg) == clock_source)), SSP_ERR_CLOCK_ACTIVE);
575 #endif /* BSP_FEATURE_HAS_CGC_PLL */
576
577 /* MOCO cannot be stopped if OSC Stop Detect is enabled */
578 CGC_ERROR_RETURN(!((clock_source == CGC_CLOCK_MOCO) && ((HW_CGC_OscStopDetectEnabledGet(gp_system_reg)))), SSP_ERR_OSC_STOP_DET_ENABLED);
579
580 if (!r_cgc_clock_run_state_get(gp_system_reg, clock_source))
581 {
582 return SSP_SUCCESS; // if clock is already inactive, return success
583 }
584
585 /* make sure the oscillator is stable before stopping */
586 CGC_ERROR_RETURN(r_cgc_clock_check(gp_system_reg, clock_source), SSP_ERR_NOT_STABILIZED);
587
588 r_cgc_clock_stop(gp_system_reg, clock_source); // stop the clock
589 /* return error if timed out */
590 CGC_ERROR_RETURN((SSP_SUCCESS == r_cgc_wait_to_complete(clock_source, CGC_CLOCK_CHANGE_STOP)), SSP_ERR_HARDWARE_TIMEOUT);
591
592 return SSP_SUCCESS;
593 }
594
595 /*******************************************************************************************************************//**
596 * @brief Set the specified clock as the system clock and configure the internal dividers for
597 * ICLK, PCLKA, PCLKB, PCLKC, PCLKD and FCLK.
598 *
599 * THIS FUNCTION DOES NOT CHECK TO SEE IF THE OPERATING MODE SUPPORTS THE SPECIFIED CLOCK SOURCE
600 * AND DIVIDER VALUES. SETTING A CLOCK SOURCE AND DVIDER OUTSIDE THE RANGE SUPPORTED BY THE
601 * CURRENT OPERATING MODE WILL RESULT IN UNDEFINED OPERATION.
602 *
603 * IF THE LOCO MOCO OR SUBCLOCK ARE CHOSEN AS THE SYSTEM CLOCK, THIS FUNCTION WILL SET THOSE AS THE
604 * SYSTEM CLOCK WITHOUT CHECKING FOR STABILIZATION. IT IS UP TO THE USER TO ENSURE THAT LOCO, MOCO
605 * OR SUBCLOCK ARE STABLE BEFORE USING THEM AS THE SYSTEM CLOCK.
606 *
607 * Additionally this function sets the RAM and ROM wait states for the MCU.
608 * For the S7 MCU the ROMWT register controls ROM wait states.
609 * For the S3 MCU the MEMWAIT register controls ROM wait states.
610 *
611 * @retval SSP_SUCCESS Operation performed successfully.
612 * @retval SSP_ERR_CLOCK_INACTIVE The specified clock source is inactive.
613 * @retval SSP_ERR_ASSERTION The p_clock_cfg parameter is NULL.
614 * @retval SSP_ERR_NOT_STABILIZED The clock source has not stabilized
615 * @retval SSP_ERR_INVALID_ARGUMENT Invalid argument used. ICLK is not set as the fastest clock.
616 * @retval SSP_ERR_INVALID_MODE Peripheral divisions are not valid in sub-osc mode
617 * @retval SSP_ERR_INVALID_MODE Oscillator stop detect not allowed in sub-osc mode
618 **********************************************************************************************************************/
619
R_CGC_SystemClockSet(cgc_clock_t clock_source,cgc_system_clock_cfg_t const * const p_clock_cfg)620 ssp_err_t R_CGC_SystemClockSet (cgc_clock_t clock_source, cgc_system_clock_cfg_t const * const p_clock_cfg)
621 {
622 cgc_clock_t current_clock;
623 bsp_clock_set_callback_args_t args;
624 ssp_err_t err;
625
626 /* return error if invalid clock source or not supported by hardware */
627 CGC_ERROR_RETURN((HW_CGC_ClockSourceValidCheck(clock_source)), SSP_ERR_INVALID_ARGUMENT);
628
629 #if (CGC_CFG_PARAM_CHECKING_ENABLE == 1)
630 SSP_ASSERT(NULL != p_clock_cfg);
631
632 err = r_cgc_check_config_dividers(p_clock_cfg);
633 CGC_ERROR_RETURN((SSP_SUCCESS == err), err);
634
635 /* Check if clock source is sub-oscillator clock */
636 if(CGC_CLOCK_SUBCLOCK == clock_source)
637 {
638 /* check if ICLK & FCLK divider is not 0 */
639 /* Peripheral divisions are not valid in sub-osc mode */
640 CGC_ERROR_RETURN(!(0U != p_clock_cfg->iclk_div), SSP_ERR_INVALID_MODE);
641 #if BSP_FEATURE_HAS_CGC_FLASH_CLOCK
642 CGC_ERROR_RETURN(!(0U != p_clock_cfg->fclk_div), SSP_ERR_INVALID_MODE);
643 #endif /* BSP_FEATURE_HAS_CGC_FLASH_CLOCK */
644
645 /* Oscillator stop detect not allowed in sub-osc mode */
646 CGC_ERROR_RETURN(!(true == HW_CGC_OscStopDetectEnabledGet(gp_system_reg)), SSP_ERR_INVALID_MODE);
647 }
648 #endif /* CGC_CFG_PARAM_CHECKING_ENABLE */
649
650 /** In order to correctly set the ROM and RAM wait state registers we need to know the current (S3A7 only) and
651 * requested iclk frequencies.
652 */
653
654 current_clock = HW_CGC_ClockSourceGet(gp_system_reg);
655 if (clock_source != current_clock) // if clock_source is not the current system clock, check stabilization
656 {
657 err = r_cgc_clock_running_status_check(clock_source);
658 CGC_ERROR_RETURN(SSP_SUCCESS == err, err);
659 }
660
661 /* In order to avoid a system clock (momentarily) higher than expected, the order of switching the clock and
662 * dividers must be so that the frequency of the clock goes lower, instead of higher, before being correct.
663 */
664
665 cgc_system_clock_cfg_t current_clock_cfg;
666 r_cgc_system_dividers_get(gp_system_reg, ¤t_clock_cfg);
667
668 /* Switch to high-speed to prevent any issues with the subsequent system clock change. */
669 HW_CGC_SetHighSpeedMode(gp_system_reg);
670
671 /* Adjust the MCU specific wait state right before the system clock is set, if the system clock frequency to be set is higher than previous */
672 args.event = BSP_CLOCK_SET_EVENT_PRE_CHANGE;
673 args.new_rom_wait_state = 0U;
674 args.requested_freq_hz = r_cgc_clockhz_calculate(clock_source, p_clock_cfg->iclk_div);
675 args.current_freq_hz = r_cgc_clock_hzget(gp_system_reg, CGC_SYSTEM_CLOCKS_ICLK);
676 err = bsp_clock_set_callback(&args);
677 CGC_ERROR_RETURN(SSP_SUCCESS == err, err);
678
679 /* If the current ICLK divider is less (higher frequency) than the requested ICLK divider,
680 * set the divider first.
681 */
682 if (current_clock_cfg.iclk_div < p_clock_cfg->iclk_div )
683 {
684 r_cgc_system_dividers_set(gp_system_reg, p_clock_cfg);
685 r_cgc_clock_source_set(gp_system_reg, clock_source);
686 }
687 /* The current ICLK divider is greater (lower frequency) than the requested ICLK divider, so
688 * set the clock source first.
689 */
690 else
691 {
692 r_cgc_clock_source_set(gp_system_reg, clock_source);
693 r_cgc_system_dividers_set(gp_system_reg, p_clock_cfg);
694 }
695
696 /* Clock is now at requested frequency. */
697
698 /* Adjust the MCU specific wait state soon after the system clock is set, if the system clock frequency to be set is lower than previous. */
699 args.current_freq_hz = r_cgc_clock_hzget(gp_system_reg, CGC_SYSTEM_CLOCKS_ICLK);
700 args.event = BSP_CLOCK_SET_EVENT_POST_CHANGE;
701 err = bsp_clock_set_callback(&args);
702 CGC_ERROR_RETURN(SSP_SUCCESS == err, err);
703
704 /* Update the CMSIS core clock variable so that it reflects the new Iclk freq */
705 SystemCoreClock = bsp_cpu_clock_get();
706
707 /* Make sure SystemCoreClock frequency should not be zero */
708 CGC_ERROR_RETURN((0U != SystemCoreClock), SSP_ERR_CLOCK_INACTIVE);
709
710 /* Set the Operating speed mode based on the new system clock source */
711 r_cgc_operating_mode_set(clock_source, SystemCoreClock);
712
713 #if (1 == BSP_CFG_RTOS)
714 /* If an RTOS is in use, Update the Systick period based on the new frequency, using the ThreadX systick period in Microsecs */
715 R_CGC_SystickUpdate((1000000 / TX_TIMER_TICKS_PER_SECOND), CGC_SYSTICK_PERIOD_UNITS_MICROSECONDS);
716 #endif
717
718 return SSP_SUCCESS;
719 }
720
721 /*******************************************************************************************************************//**
722 * @brief Return the current system clock source and configuration.
723 * @retval SSP_SUCCESS Parameters returned successfully.
724 * @retval SSP_ERR_ASSERTION A NULL is passed for configuration data.
725 * @retval SSP_ERR_ASSERTION A NULL is passed for clock source.
726 **********************************************************************************************************************/
727
R_CGC_SystemClockGet(cgc_clock_t * clock_source,cgc_system_clock_cfg_t * p_set_clock_cfg)728 ssp_err_t R_CGC_SystemClockGet (cgc_clock_t * clock_source, cgc_system_clock_cfg_t * p_set_clock_cfg)
729 {
730 #if (CGC_CFG_PARAM_CHECKING_ENABLE == 1)
731 SSP_ASSERT(NULL != clock_source);
732 SSP_ASSERT(NULL != p_set_clock_cfg);
733 #endif /* CGC_CFG_PARAM_CHECKING_ENABLE */
734 *clock_source = HW_CGC_ClockSourceGet(gp_system_reg);
735 r_cgc_system_dividers_get(gp_system_reg, p_set_clock_cfg);
736
737 return SSP_SUCCESS;
738 }
739
740 /*******************************************************************************************************************//**
741 * @brief Return the requested internal clock frequency in Hz.
742 * @retval SSP_SUCCESS Operation performed successfully.
743 * @retval SSP_ERR_INVALID_ARGUMENT Invalid clock specified.
744 * @retval SSP_ERR_ASSERTION A NULL is passed for frequency data.
745 **********************************************************************************************************************/
R_CGC_SystemClockFreqGet(cgc_system_clocks_t clock,uint32_t * p_freq_hz)746 ssp_err_t R_CGC_SystemClockFreqGet (cgc_system_clocks_t clock, uint32_t * p_freq_hz)
747 {
748 #if (CGC_CFG_PARAM_CHECKING_ENABLE == 1)
749 SSP_ASSERT(NULL != p_freq_hz);
750
751 /* Return error if invalid system clock or not supported by hardware */
752 ssp_err_t err;
753 if (CGC_SYSTEM_CLOCKS_ICLK == clock)
754 {
755 /* Valid clock for all MCUs. Do nothing. */
756 }
757 else if (CGC_SYSTEM_CLOCKS_FCLK == clock)
758 {
759 #if !BSP_FEATURE_HAS_CGC_FLASH_CLOCK
760 CGC_ERROR_LOG(SSP_ERR_INVALID_ARGUMENT);
761 return SSP_ERR_INVALID_ARGUMENT;
762 #endif /* if !BSP_FEATURE_HAS_CGC_FLASH_CLOCK */
763 }
764 else if (CGC_SYSTEM_CLOCKS_BCLK == clock)
765 {
766 #if !BSP_FEATURE_HAS_CGC_EXTERNAL_BUS
767 CGC_ERROR_LOG(SSP_ERR_INVALID_ARGUMENT);
768 return SSP_ERR_INVALID_ARGUMENT;
769 #endif /* if BSP_FEATURE_HAS_CGC_EXTERNAL_BUS */
770 }
771 else
772 {
773 err = r_cgc_check_peripheral_clocks(clock);
774 CGC_ERROR_RETURN((SSP_SUCCESS == err), SSP_ERR_INVALID_ARGUMENT);
775 }
776
777 #endif /* CGC_CFG_PARAM_CHECKING_ENABLE */
778
779 *p_freq_hz = 0x00U;
780 *p_freq_hz = r_cgc_clock_hzget(gp_system_reg, clock);
781 return SSP_SUCCESS;
782 }
783
784 /*******************************************************************************************************************//**
785 * @brief Check the specified clock for stability.
786 * @retval SSP_SUCCESS Operation performed successfully.
787 * @retval SSP_ERR_NOT_STABILIZED Clock not stabilized.
788 * @retval SSP_ERR_CLOCK_ACTIVE Clock active but not able to check for stability.
789 * @retval SSP_ERR_CLOCK_INACTIVE Clock not turned on.
790 * @retval SSP_ERR_INVALID_ARGUMENT Illegal parameter passed.
791 * @retval SSP_ERR_STABILIZED Clock stabilized.
792 **********************************************************************************************************************/
R_CGC_ClockCheck(cgc_clock_t clock_source)793 ssp_err_t R_CGC_ClockCheck (cgc_clock_t clock_source)
794 {
795 /* return error if invalid clock source or not supported by hardware */
796 CGC_ERROR_RETURN((HW_CGC_ClockSourceValidCheck(clock_source)), SSP_ERR_INVALID_ARGUMENT);
797
798 /* There is no function to check for LOCO, MOCO or SUBCLOCK stability */
799 if (((clock_source == CGC_CLOCK_LOCO) || (clock_source == CGC_CLOCK_MOCO)) || (clock_source == CGC_CLOCK_SUBCLOCK))
800 {
801 if (true == r_cgc_clock_run_state_get(gp_system_reg, clock_source))
802 {
803 return SSP_ERR_CLOCK_ACTIVE; // There is no hardware to check for stability so just check for state.
804 }
805 else
806 {
807 return SSP_ERR_CLOCK_INACTIVE; // There is no hardware to check for stability so just check for state.
808 }
809 }
810
811 /* There is a function to check for HOCO, MAIN_OSC and PLL stability */
812 #if BSP_FEATURE_HAS_CGC_PLL
813 else if (((clock_source == CGC_CLOCK_HOCO) || (clock_source == CGC_CLOCK_MAIN_OSC))
814 || (clock_source == CGC_CLOCK_PLL))
815 #else
816 else if (((clock_source == CGC_CLOCK_HOCO) || (clock_source == CGC_CLOCK_MAIN_OSC)))
817 #endif /* BSP_FEATURE_HAS_CGC_PLL */
818 {
819 /* if clock is not active, can't check for stability, return error */
820 CGC_ERROR_RETURN(r_cgc_clock_run_state_get(gp_system_reg, clock_source), SSP_ERR_CLOCK_INACTIVE);
821
822 /* check oscillator for stability, return error if not stable */
823 CGC_ERROR_RETURN(r_cgc_clock_check(gp_system_reg, clock_source), SSP_ERR_NOT_STABILIZED);
824 return SSP_ERR_STABILIZED; // otherwise, return affirmative, not really an error
825 }
826 else
827 {
828 /* statement here to follow coding standard */
829 }
830
831 return SSP_SUCCESS;
832 }
833
834 /*******************************************************************************************************************//**
835 * @brief Enable or disable the oscillation stop detection for the main clock.
836 * The MCU will automatically switch the system clock to MOCO when a stop is detected if Main Clock is
837 * the system clock. If the system clock is the PLL, then the clock source will not be changed and the
838 * PLL free running frequency will be the system clock frequency.
839 * @retval SSP_SUCCESS Operation performed successfully.
840 * @retval SSP_ERR_OSC_STOP_DETECTED The Oscillation stop detect status flag is set. Under this condition it is not
841 * possible to disable the Oscillation stop detection function.
842 * @retval SSP_ERR_ASSERTION Null pointer passed for callback function when the second argument is "true".
843 * @retval SSP_ERR_ASSERTION Cannot enable oscillator stop detect in sub-osc speed mode
844 * @retval SSP_ERR_ASSERTION Invalid peripheral clock divisions for oscillator stop detect
845 * @retval SSP_ERR_INVALID_MODE Invalid peripheral clock divider setting. Frequencies of peripherals should
846 * follow certain conditions.
847 **********************************************************************************************************************/
R_CGC_OscStopDetect(void (* p_callback)(cgc_callback_args_t * p_args),bool enable)848 ssp_err_t R_CGC_OscStopDetect (void (* p_callback) (cgc_callback_args_t * p_args), bool enable)
849 {
850 if (true == enable)
851 {
852 #if (CGC_CFG_PARAM_CHECKING_ENABLE == 1)
853 SSP_ASSERT(NULL != p_callback);
854 cgc_operating_modes_t operating_mode = r_cgc_operating_mode_get(gp_system_reg);
855 SSP_ASSERT(CGC_SUBOSC_SPEED_MODE != operating_mode);
856 cgc_system_clock_cfg_t clock_cfg;
857 r_cgc_system_dividers_get(gp_system_reg, &clock_cfg);
858 if((0U != gp_cgc_feature->low_speed_max_freq_hz) && (CGC_LOW_SPEED_MODE == operating_mode))
859 {
860 CGC_ERROR_RETURN((SSP_SUCCESS == r_cgc_check_dividers(&clock_cfg, gp_cgc_feature->low_speed_pclk_div_min)), SSP_ERR_INVALID_MODE);
861 }
862 else if((0U != gp_cgc_feature->low_voltage_max_freq_hz) && (CGC_LOW_VOLTAGE_MODE == operating_mode))
863 {
864 CGC_ERROR_RETURN((SSP_SUCCESS == r_cgc_check_dividers(&clock_cfg, gp_cgc_feature->low_voltage_pclk_div_min)), SSP_ERR_INVALID_MODE);
865 }
866 else
867 {
868 /* Do nothing */
869 }
870 #endif
871 /* - add callback function to BSP */
872 R_BSP_GroupIrqWrite(BSP_GRP_IRQ_OSC_STOP_DETECT, (bsp_grp_irq_cb_t) p_callback);
873 r_cgc_oscstop_detect_enable(gp_system_reg); // enable hardware oscillator stop detect
874 }
875 else
876 {
877 /* if oscillator stop detected, return error */
878 CGC_ERROR_RETURN(!(HW_CGC_OscStopDetectGet(gp_system_reg)), SSP_ERR_OSC_STOP_DETECTED);
879 r_cgc_oscstop_detect_disable(gp_system_reg); // disable hardware oscillator stop detect
880 }
881
882 return SSP_SUCCESS;
883 }
884
885 /*******************************************************************************************************************//**
886 * @brief Clear the Oscillation Stop Detection Status register.
887 *
888 * This register is not cleared automatically if the stopped clock is restarted.
889 * This function blocks for about 3 ICLK cycles until the status register is cleared.
890 * @retval SSP_SUCCESS Operation performed successfully.
891 * @retval SSP_ERR_OSC_STOP_CLOCK_ACTIVE The Oscillation Detect Status flag cannot be cleared if the
892 * Main Osc or PLL is set as the system clock. Change the
893 * system clock before attempting to clear this bit.
894 **********************************************************************************************************************/
895
R_CGC_OscStopStatusClear(void)896 ssp_err_t R_CGC_OscStopStatusClear (void)
897 {
898 cgc_clock_t current_clock;
899
900 if (HW_CGC_OscStopDetectGet(gp_system_reg)) // if oscillator stop detected
901 {
902 current_clock = HW_CGC_ClockSourceGet(gp_system_reg); // The currently active system clock source
903
904 #if BSP_FEATURE_HAS_CGC_PLL
905 /* MCU has PLL. */
906 if (gp_cgc_feature->pll_src_configurable)
907 {
908 cgc_clock_t alt_clock;
909 alt_clock = r_cgc_pll_clocksource_get(gp_system_reg);
910 /* cannot clear oscillator stop status if Main Osc is source of PLL */
911 CGC_ERROR_RETURN(!((CGC_CLOCK_PLL == current_clock) && (CGC_CLOCK_MAIN_OSC == alt_clock)), SSP_ERR_OSC_STOP_CLOCK_ACTIVE);
912 }
913 else
914 {
915 /* cannot clear oscillator stop status if PLL is current clock */
916 CGC_ERROR_RETURN(!(CGC_CLOCK_PLL == current_clock), SSP_ERR_OSC_STOP_CLOCK_ACTIVE);
917 }
918 #endif /* BSP_FEATURE_HAS_CGC_PLL */
919
920 /* cannot clear oscillator stop status if Main Osc is current clock */
921 CGC_ERROR_RETURN(!(CGC_CLOCK_MAIN_OSC == current_clock), SSP_ERR_OSC_STOP_CLOCK_ACTIVE);
922 }
923
924 r_cgc_oscstop_status_clear(gp_system_reg); // clear hardware oscillator stop detect status
925
926 return SSP_SUCCESS;
927 }
928
929 /*******************************************************************************************************************//**
930 * @brief Configure the secondary dividers for BCLKOUT. The primary divider is set using the
931 * bsp clock configuration and the R_CGC_SystemClockSet function.
932 * @retval SSP_SUCCESS Operation performed successfully.
933 **********************************************************************************************************************/
934
R_CGC_BusClockOutCfg(cgc_bclockout_dividers_t divider)935 ssp_err_t R_CGC_BusClockOutCfg (cgc_bclockout_dividers_t divider)
936 {
937 /* The application must set up the PFS register so the BCLK pin is an output */
938
939 #if !BSP_FEATURE_HAS_CGC_EXTERNAL_BUS
940 SSP_PARAMETER_NOT_USED(divider);
941 CGC_ERROR_LOG(SSP_ERR_UNSUPPORTED);
942 return SSP_ERR_UNSUPPORTED;
943 #else
944 HW_CGC_BusClockOutCfg(gp_system_reg, divider);
945 return SSP_SUCCESS;
946 #endif /* !BSP_FEATURE_HAS_CGC_EXTERNAL_BUS */
947 }
948
949 /*******************************************************************************************************************//**
950 * @brief Enable the BCLKOUT output.
951 * @retval SSP_SUCCESS Operation performed successfully.
952 **********************************************************************************************************************/
953
R_CGC_BusClockOutEnable(void)954 ssp_err_t R_CGC_BusClockOutEnable (void)
955 {
956 #if !BSP_FEATURE_HAS_CGC_EXTERNAL_BUS
957 CGC_ERROR_LOG(SSP_ERR_UNSUPPORTED);
958 return SSP_ERR_UNSUPPORTED;
959 #else
960 HW_CGC_BusClockOutEnable(gp_system_reg);
961 return SSP_SUCCESS;
962 #endif /* !BSP_FEATURE_HAS_CGC_EXTERNAL_BUS */
963 }
964
965 /*******************************************************************************************************************//**
966 * @brief Disable the BCLKOUT output.
967 * @retval SSP_SUCCESS Operation performed successfully.
968 **********************************************************************************************************************/
969
R_CGC_BusClockOutDisable(void)970 ssp_err_t R_CGC_BusClockOutDisable (void)
971 {
972 #if !BSP_FEATURE_HAS_CGC_EXTERNAL_BUS
973 CGC_ERROR_LOG(SSP_ERR_UNSUPPORTED);
974 return SSP_ERR_UNSUPPORTED;
975 #else
976 HW_CGC_BusClockOutDisable(gp_system_reg);
977 return SSP_SUCCESS;
978 #endif /* !BSP_FEATURE_HAS_CGC_EXTERNAL_BUS */
979 }
980
981 /*******************************************************************************************************************//**
982 * @brief Configure the dividers for CLKOUT.
983 * @retval SSP_SUCCESS Operation performed successfully.
984 * @retval SSP_ERR_INVALID_ARGUMENT return error if PLL is used as source for clock out
985 * @retval SSP_ERR_CLOCK_INACTIVE return error if sub clock is not started prior to using it for clock out
986 **********************************************************************************************************************/
R_CGC_ClockOutCfg(cgc_clock_t clock,cgc_clockout_dividers_t divider)987 ssp_err_t R_CGC_ClockOutCfg (cgc_clock_t clock, cgc_clockout_dividers_t divider)
988 {
989 /* The application must set up the PFS register so the CLKOUT pin is an output */
990 CGC_ERROR_RETURN(CGC_CLOCK_PLL != clock, SSP_ERR_INVALID_ARGUMENT); // return error if PLL is selected as source
991 /* Subclock needs to be started before using it for clock out return error if subclock is stopped */
992 CGC_ERROR_RETURN(((CGC_CLOCK_SUBCLOCK != clock) || ((CGC_CLOCK_SUBCLOCK == clock)
993 &&(true == r_cgc_clock_run_state_get(gp_system_reg, CGC_CLOCK_SUBCLOCK)))) , SSP_ERR_CLOCK_INACTIVE)
994 r_cgc_clockout_cfg(gp_system_reg, clock, divider);
995 return SSP_SUCCESS;
996 }
997
998 /*******************************************************************************************************************//**
999 * @brief Enable the CLKOUT output.
1000 * @retval SSP_SUCCESS Operation performed successfully.
1001 **********************************************************************************************************************/
1002
R_CGC_ClockOutEnable(void)1003 ssp_err_t R_CGC_ClockOutEnable (void)
1004 {
1005 r_cgc_clockout_enable(gp_system_reg);
1006 return SSP_SUCCESS;
1007 }
1008
1009 /*******************************************************************************************************************//**
1010 * @brief Disable the CLKOUT output.
1011 * @retval SSP_SUCCESS Operation performed successfully.
1012 **********************************************************************************************************************/
1013
R_CGC_ClockOutDisable(void)1014 ssp_err_t R_CGC_ClockOutDisable (void)
1015 {
1016 r_cgc_clockout_disable(gp_system_reg);
1017 return SSP_SUCCESS;
1018 }
1019
1020 /*******************************************************************************************************************//**
1021 * @brief Configure the source for the segment LCDCLK.
1022 * @retval SSP_SUCCESS Operation performed successfully.
1023 * @retval SSP_ERR_TIMEOUT Timed out.
1024 * @retval SSP_ERR_INVALID_ARGUMENT lcd_clock settings are invalid
1025 * @retval SSP_ERR_UNSUPPORTED lcd_clock configuration is not supported on this device
1026 **********************************************************************************************************************/
1027
R_CGC_LCDClockCfg(cgc_clock_t clock)1028 ssp_err_t R_CGC_LCDClockCfg (cgc_clock_t clock)
1029 {
1030 #if !BSP_FEATURE_HAS_CGC_LCD_CLK
1031 SSP_PARAMETER_NOT_USED(clock);
1032 CGC_ERROR_LOG(SSP_ERR_UNSUPPORTED);
1033 return SSP_ERR_UNSUPPORTED;
1034 #else
1035 /* The application must set up the PFS register so the LCDCLKOUT pin is an output */
1036 CGC_ERROR_RETURN(CGC_LDC_INVALID_CLOCK != g_lcd_clock_settings[clock], SSP_ERR_INVALID_ARGUMENT);
1037
1038 /* Protect OFF for CGC. */
1039 R_BSP_RegisterProtectDisable(BSP_REG_PROTECT_CGC);
1040
1041 bool lcd_clock_was_enabled = HW_CGC_LCDClockIsEnabled(gp_system_reg);
1042 R_CGC_LCDClockDisable();
1043 HW_CGC_LCDClockCfg(gp_system_reg, g_lcd_clock_settings[clock]);
1044 uint32_t timeout = CGC_LCD_CFG_TIMEOUT;
1045 while ((g_lcd_clock_settings[clock] != HW_CGC_LCDClockCfgGet(gp_system_reg)) && (0U != timeout)) /* wait for the bit to set */
1046 {
1047 timeout--;
1048 }
1049
1050 if (lcd_clock_was_enabled)
1051 {
1052 R_CGC_LCDClockEnable();
1053 }
1054
1055 /* Protect ON for CGC. */
1056 R_BSP_RegisterProtectEnable(BSP_REG_PROTECT_CGC);
1057
1058 CGC_ERROR_RETURN(timeout > 0U, SSP_ERR_TIMEOUT);
1059 return SSP_SUCCESS;
1060 #endif /* !BSP_FEATURE_HAS_CGC_LCD_CLK */
1061 }
1062
1063 /*******************************************************************************************************************//**
1064 * @brief Enable the segment LCDCLK output.
1065 * @retval SSP_SUCCESS Operation performed successfully.
1066 * @retval SSP_ERR_TIMEOUT Timed out.
1067 * @retval SSP_ERR_UNSUPPORTED lcd_clock is not supported on this device
1068 **********************************************************************************************************************/
1069
R_CGC_LCDClockEnable(void)1070 ssp_err_t R_CGC_LCDClockEnable (void)
1071 {
1072 #if !BSP_FEATURE_HAS_CGC_LCD_CLK
1073 CGC_ERROR_LOG(SSP_ERR_UNSUPPORTED);
1074 return SSP_ERR_UNSUPPORTED;
1075 #else
1076 /* Protect OFF for CGC. */
1077 R_BSP_RegisterProtectDisable(BSP_REG_PROTECT_CGC);
1078
1079 HW_CGC_LCDClockEnable(gp_system_reg);
1080 uint32_t timeout = CGC_LCD_CFG_TIMEOUT;
1081 while ((true != HW_CGC_LCDClockIsEnabled(gp_system_reg)) && (0U != timeout)) /* wait for the bit to set */
1082 {
1083 timeout--;
1084 }
1085
1086 /* Protect ON for CGC. */
1087 R_BSP_RegisterProtectEnable(BSP_REG_PROTECT_CGC);
1088
1089 CGC_ERROR_RETURN(timeout > 0U, SSP_ERR_TIMEOUT);
1090 return SSP_SUCCESS;
1091 #endif /* !BSP_FEATURE_HAS_CGC_LCD_CLK */
1092 }
1093
1094 /*******************************************************************************************************************//**
1095 * @brief Disable the segment LCDCLK output.
1096 * @retval SSP_SUCCESS Operation performed successfully.
1097 * @retval SSP_ERR_TIMEOUT Timed out.
1098 * @retval SSP_ERR_UNSUPPORTED lcd_clock is not supported on this device
1099 **********************************************************************************************************************/
1100
R_CGC_LCDClockDisable(void)1101 ssp_err_t R_CGC_LCDClockDisable (void)
1102 {
1103 #if !BSP_FEATURE_HAS_CGC_LCD_CLK
1104 CGC_ERROR_LOG(SSP_ERR_UNSUPPORTED);
1105 return SSP_ERR_UNSUPPORTED;
1106 #else
1107 /* Protect OFF for CGC. */
1108 R_BSP_RegisterProtectDisable(BSP_REG_PROTECT_CGC);
1109
1110 HW_CGC_LCDClockDisable(gp_system_reg);
1111 uint32_t timeout = CGC_LCD_CFG_TIMEOUT;
1112 while ((false != HW_CGC_LCDClockIsEnabled(gp_system_reg)) && (0U != timeout)) /* wait for the bit to set */
1113 {
1114 timeout--;
1115 }
1116
1117 /* Protect ON for CGC. */
1118 R_BSP_RegisterProtectEnable(BSP_REG_PROTECT_CGC);
1119
1120 CGC_ERROR_RETURN(timeout > 0U, SSP_ERR_TIMEOUT);
1121 return SSP_SUCCESS;
1122 #endif /* !BSP_FEATURE_HAS_CGC_LCD_CLK */
1123 }
1124
1125
1126
1127 /*******************************************************************************************************************//**
1128 * @brief Configure the source for the SDADCCLK.
1129 * @retval SSP_SUCCESS Operation performed successfully.
1130 * @retval SSP_ERR_UNSUPPORTED sdadc_clock configuration is not supported on this device
1131 * @retval SSP_ERR_INVALID_ARGUMENT Invalid clock used
1132 **********************************************************************************************************************/
1133
R_CGC_SDADCClockCfg(cgc_clock_t clock)1134 ssp_err_t R_CGC_SDADCClockCfg (cgc_clock_t clock)
1135 {
1136 #if !BSP_FEATURE_HAS_CGC_SDADC_CLK
1137 SSP_PARAMETER_NOT_USED(clock);
1138 CGC_ERROR_LOG(SSP_ERR_UNSUPPORTED);
1139 return SSP_ERR_UNSUPPORTED;
1140 #else
1141 /* check for valid clock source */
1142 CGC_ERROR_RETURN(!((CGC_CLOCK_MAIN_OSC != clock) && (CGC_CLOCK_HOCO != clock)), SSP_ERR_INVALID_ARGUMENT);
1143
1144 /* Protect OFF for CGC. */
1145 R_BSP_RegisterProtectDisable(BSP_REG_PROTECT_CGC);
1146
1147 bool sdadc_clock_was_enabled = HW_CGC_SDADCClockIsEnabled(gp_system_reg);
1148 R_CGC_SDADCClockDisable();
1149
1150 HW_CGC_SDADCClockCfg(gp_system_reg, clock);
1151
1152 if (sdadc_clock_was_enabled)
1153 {
1154 R_CGC_SDADCClockEnable();
1155 }
1156
1157 /* Protect ON for CGC. */
1158 R_BSP_RegisterProtectEnable(BSP_REG_PROTECT_CGC);
1159
1160 return SSP_SUCCESS;
1161 #endif /* !BSP_FEATURE_HAS_CGC_SDADC_CLK */
1162 }
1163
1164 /*******************************************************************************************************************//**
1165 * @brief Enable the SDADCCLK output.
1166 * @retval SSP_SUCCESS Operation performed successfully.
1167 * @retval SSP_ERR_UNSUPPORTED sdadc_clock is not supported on this device
1168 **********************************************************************************************************************/
1169
R_CGC_SDADCClockEnable(void)1170 ssp_err_t R_CGC_SDADCClockEnable (void)
1171 {
1172 #if !BSP_FEATURE_HAS_CGC_SDADC_CLK
1173 CGC_ERROR_LOG(SSP_ERR_UNSUPPORTED);
1174 return SSP_ERR_UNSUPPORTED;
1175 #else
1176 /* Protect OFF for CGC. */
1177 R_BSP_RegisterProtectDisable(BSP_REG_PROTECT_CGC);
1178
1179 HW_CGC_SDADCClockEnable(gp_system_reg);
1180
1181 /* Protect ON for CGC. */
1182 R_BSP_RegisterProtectEnable(BSP_REG_PROTECT_CGC);
1183 return SSP_SUCCESS;
1184 #endif /* !BSP_FEATURE_HAS_CGC_SDADC_CLK */
1185 }
1186
1187 /*******************************************************************************************************************//**
1188 * @brief Disable the SDADCCLK output.
1189 * @retval SSP_SUCCESS Operation performed successfully.
1190 * @retval SSP_ERR_UNSUPPORTED sdadc_clock is not supported on this device
1191 **********************************************************************************************************************/
1192
R_CGC_SDADCClockDisable(void)1193 ssp_err_t R_CGC_SDADCClockDisable (void)
1194 {
1195 #if !BSP_FEATURE_HAS_CGC_SDADC_CLK
1196 CGC_ERROR_LOG(SSP_ERR_UNSUPPORTED);
1197 return SSP_ERR_UNSUPPORTED;
1198 #else
1199 /* Protect OFF for CGC. */
1200 R_BSP_RegisterProtectDisable(BSP_REG_PROTECT_CGC);
1201 HW_CGC_SDADCClockDisable(gp_system_reg);
1202 /* Protect ON for CGC. */
1203 R_BSP_RegisterProtectEnable(BSP_REG_PROTECT_CGC);
1204 return SSP_SUCCESS;
1205 #endif /* !BSP_FEATURE_HAS_CGC_SDADC_CLK */
1206 }
1207
1208
1209 /*******************************************************************************************************************//**
1210 * @brief Enable the SDCLK output.
1211 * @retval SSP_SUCCESS Operation performed successfully.
1212 * @retval SSP_ERR_UNSUPPORTED sdram_clock is not supported on this device
1213 **********************************************************************************************************************/
1214
R_CGC_SDRAMClockOutEnable(void)1215 ssp_err_t R_CGC_SDRAMClockOutEnable (void)
1216 {
1217 #if !BSP_FEATURE_HAS_CGC_SDRAM_CLK
1218 CGC_ERROR_LOG(SSP_ERR_UNSUPPORTED);
1219 return SSP_ERR_UNSUPPORTED;
1220 #else
1221 HW_CGC_SDRAMClockOutEnable(gp_system_reg);
1222 return SSP_SUCCESS;
1223 #endif
1224 }
1225
1226 /*******************************************************************************************************************//**
1227 * @brief Disable the SDCLK output.
1228 * @retval SSP_SUCCESS Operation performed successfully.
1229 * @retval SSP_ERR_UNSUPPORTED sdram_clock is not supported on this device
1230 **********************************************************************************************************************/
1231
R_CGC_SDRAMClockOutDisable(void)1232 ssp_err_t R_CGC_SDRAMClockOutDisable (void)
1233 {
1234 #if !BSP_FEATURE_HAS_CGC_SDRAM_CLK
1235 CGC_ERROR_LOG(SSP_ERR_UNSUPPORTED);
1236 return SSP_ERR_UNSUPPORTED;
1237 #else
1238 HW_CGC_SDRAMClockOutDisable(gp_system_reg);
1239 return SSP_SUCCESS;
1240 #endif
1241 }
1242
1243 /*******************************************************************************************************************//**
1244 * @brief Configure the dividers for UCLK.
1245 * @retval SSP_SUCCESS Operation performed successfully.
1246 * @retval SSP_ERR_INVALID_ARGUMENT Invalid usb_clock divider specified
1247 ***********************************************************************************************************************/
1248
R_CGC_USBClockCfg(cgc_usb_clock_div_t divider)1249 ssp_err_t R_CGC_USBClockCfg (cgc_usb_clock_div_t divider)
1250 {
1251 #if !BSP_FEATURE_HAS_CGC_USB_CLK
1252 SSP_PARAMETER_NOT_USED(divider);
1253 CGC_ERROR_LOG(SSP_ERR_UNSUPPORTED);
1254 return SSP_ERR_UNSUPPORTED;
1255 #else
1256 /* The application must set up the PFS register so the USBCLKOUT pin is an output */
1257 HW_CGC_USBClockCfg(gp_system_reg, divider);
1258 return SSP_SUCCESS;
1259 #endif
1260 }
1261
1262 /*******************************************************************************************************************//**
1263 * @brief Re-Configure the systick based on the provided period and current system clock frequency.
1264 * @param[in] period_count The duration for the systick period.
1265 * @param[in] units The units for the provided period.
1266 * @retval SSP_SUCCESS Operation performed successfully.
1267 * @retval SSP_ERR_INVALID_ARGUMENT Invalid period specified.
1268 * @retval SSP_ERR_ABORTED Attempt to update systick timer failed.
1269 **********************************************************************************************************************/
R_CGC_SystickUpdate(uint32_t period_count,cgc_systick_period_units_t units)1270 ssp_err_t R_CGC_SystickUpdate(uint32_t period_count, cgc_systick_period_units_t units)
1271 {
1272 uint32_t requested_period_count = period_count;
1273 uint32_t reload_value;
1274 uint32_t freq;
1275 cgc_systick_period_units_t period_units = units;
1276 #if (__FPU_PRESENT != 0)
1277 /*LDRA_INSPECTED 90 s float used because float32_t is not part of the C99 standard integer definitions. */
1278 float period = 0.0f;
1279 #endif
1280
1281 #if (CGC_CFG_PARAM_CHECKING_ENABLE)
1282 if (0 == period_count)
1283 {
1284 SSP_ERROR_LOG((SSP_ERR_INVALID_ARGUMENT), (g_module_name), (g_cgc_version)); // Invalid period provided
1285 return (SSP_ERR_INVALID_ARGUMENT);
1286 }
1287 #endif
1288
1289 freq = bsp_cpu_clock_get(); // Get the current ICLK frequency
1290
1291 /* If an RTOS is in use then we want to set the Systick period to that defined by the RTOS. So we'll convert the macro
1292 * settings use the existing code and calculate the reload value
1293 */
1294 #if (1 == BSP_CFG_RTOS)
1295 period_units = CGC_SYSTICK_PERIOD_UNITS_MICROSECONDS;
1296 requested_period_count = (RELOAD_COUNT_FOR_1US) / TX_TIMER_TICKS_PER_SECOND; // Convert ticks per sec to ticks per us
1297 #endif
1298
1299 #if (__FPU_PRESENT == 0)
1300 reload_value = (uint32_t)(((uint64_t)(requested_period_count) * (uint64_t)(freq) + (uint64_t)(period_units/2)) / period_units);
1301 #else
1302 /*LDRA_INSPECTED 90 s *//*LDRA_INSPECTED 90 s */
1303 period = ((1.0f)/(float)freq) * (float)period_units; // This is the period in the provided units
1304 /*LDRA_INSPECTED 90 s */
1305 reload_value = (uint32_t)((float)requested_period_count/period);
1306 #endif
1307
1308 // Configure the systick period as requested
1309 CGC_ERROR_RETURN(r_cgc_systick_update(reload_value), SSP_ERR_ABORTED);
1310 return SSP_SUCCESS;
1311 }
1312
1313
1314 /*******************************************************************************************************************//**
1315 * @brief Return the driver version.
1316 * @retval SSP_SUCCESS Operation performed successfully.
1317 * @retval SSP_ERR_ASSERTION The parameter p_version is NULL..
1318 **********************************************************************************************************************/
1319
R_CGC_VersionGet(ssp_version_t * const p_version)1320 ssp_err_t R_CGC_VersionGet (ssp_version_t * const p_version)
1321 {
1322 #if (CGC_CFG_PARAM_CHECKING_ENABLE == 1)
1323 SSP_ASSERT(NULL != p_version);
1324 #endif /* CGC_CFG_PARAM_CHECKING_ENABLE */
1325 p_version->version_id = g_cgc_version.version_id;
1326 return SSP_SUCCESS;
1327 }
1328
1329 /*******************************************************************************************************************//**
1330 * @brief Return the Stabilization Status.
1331 * @param[in] clock clock to be checked
1332 * @retval SSP_SUCCESS Operation performed successfully.
1333 * @retval SSP_ERR_STABILIZED Clock stabilized
1334 * @retval SSP_ERR_NOT_STABILIZED CLock not stabilized
1335 * @retval SPP_ERR_CLOCK_ACTIVE Specified clock source is already stabilized
1336 **********************************************************************************************************************/
1337
r_cgc_stabilization_wait(cgc_clock_t clock)1338 static ssp_err_t r_cgc_stabilization_wait(cgc_clock_t clock)
1339 {
1340 ssp_err_t err = SSP_ERR_NOT_STABILIZED;
1341
1342 int32_t timeout = MAX_REGISTER_WAIT_COUNT;
1343 while (SSP_ERR_NOT_STABILIZED == err)
1344 {
1345 /* Wait for clock source to stabilize */
1346 timeout--;
1347 CGC_ERROR_RETURN(0 < timeout, SSP_ERR_NOT_STABILIZED);
1348 err = R_CGC_ClockCheck(clock);
1349 }
1350
1351 CGC_ERROR_RETURN((SSP_SUCCESS == err) || (SSP_ERR_STABILIZED == err) ||
1352 (SSP_ERR_CLOCK_ACTIVE == err), err);
1353
1354 return SSP_SUCCESS;
1355 }
1356
1357 /*******************************************************************************************************************//**
1358 * @brief Functionality of this function is to change the clock state and modifies the clock source
1359 * as per input parameters
1360 * @param[in] clock_state required clock state
1361 * @param[in] clock_to_change required clock source
1362 * @param[in] p_clk_cfg Pointer to the clock configuration structure
1363 * @retval SSP_SUCCESS Operation performed successfully.
1364 * @retval SPP_ERR_CLOCK_ACTIVE Specified clock is already running
1365 * @retval SSP_ERR_OSC_STOP_DET_ENABLED Illegal attempt to stop MOCO when Oscillation stop is enabled.
1366 * @retval SSP_ERR_NOT_STABILIZED Clock not stabilized after starting. A finite stabilization time after starting the
1367 * clock has to elapse before it can be stopped.
1368 * @retval SSP_ERR_INVALID_ARGUMENT Invalid argument used.
1369 * @retval SSP_ERR_HARDWARE_TIMEOUT Hardware timed out.
1370 **********************************************************************************************************************/
r_cgc_clock_start_stop(cgc_clock_change_t clock_state,cgc_clock_t clock_to_change,cgc_clocks_cfg_t const * p_clk_cfg)1371 static ssp_err_t r_cgc_clock_start_stop(cgc_clock_change_t clock_state, cgc_clock_t clock_to_change, cgc_clocks_cfg_t const *p_clk_cfg)
1372 {
1373 cgc_clock_cfg_t * p_pll_cfg = (cgc_clock_cfg_t *)&(p_clk_cfg->pll_cfg);
1374 ssp_err_t err = SSP_SUCCESS;
1375
1376 if(CGC_CLOCK_CHANGE_STOP == clock_state)
1377 {
1378 err = R_CGC_ClockStop(clock_to_change);
1379 CGC_ERROR_RETURN(SSP_SUCCESS == err, err);
1380 }
1381 else if(CGC_CLOCK_CHANGE_START == clock_state)
1382 {
1383 #if BSP_FEATURE_HAS_CGC_PLL
1384 if (CGC_CLOCK_PLL == clock_to_change)
1385 {
1386 /* Need to start PLL source clock and let it stabilize before starting PLL */
1387 err = R_CGC_ClockStart(p_pll_cfg->source_clock, (cgc_clock_cfg_t *)p_clk_cfg);
1388 CGC_ERROR_RETURN((SSP_SUCCESS == err) || (SSP_ERR_CLOCK_ACTIVE == err), err);
1389
1390 err = r_cgc_stabilization_wait(p_pll_cfg->source_clock);
1391 CGC_ERROR_RETURN(SSP_SUCCESS == err, err);
1392 }
1393 #endif /* BSP_FEATURE_HAS_CGC_PLL */
1394 err = R_CGC_ClockStart(clock_to_change, p_pll_cfg);
1395 CGC_ERROR_RETURN((SSP_SUCCESS == err) || (SSP_ERR_CLOCK_ACTIVE == err), err);
1396 }
1397 else /* CGC_CLOCK_OPTION_NO_CHANGE */
1398 {
1399 /* Do nothing */
1400 }
1401
1402 return SSP_SUCCESS;
1403 }
1404
1405 #if (CGC_CFG_PARAM_CHECKING_ENABLE == 1)
1406 /*******************************************************************************************************************//**
1407 * @brief Check if the given peripheral clock is valid for the current MCU.
1408 * @param[in] clock current system clock
1409 * @retval SSP_SUCCESS Given peripheral clock is valid for the current MCU.
1410 * @retval SSP_ERR_INVALID_ARGUMENT Given peripheral clock is invalid for the current MCU.
1411 **********************************************************************************************************************/
r_cgc_check_peripheral_clocks(cgc_system_clocks_t clock)1412 static ssp_err_t r_cgc_check_peripheral_clocks (cgc_system_clocks_t clock)
1413 {
1414 if (CGC_SYSTEM_CLOCKS_PCLKA == clock)
1415 {
1416 #if BSP_FEATURE_HAS_CGC_PCKA
1417 return SSP_SUCCESS;
1418 #else
1419 CGC_ERROR_LOG(SSP_ERR_INVALID_ARGUMENT);
1420 return SSP_ERR_INVALID_ARGUMENT;
1421 #endif /* BSP_FEATURE_HAS_CGC_PCKA */
1422 }
1423 else if (CGC_SYSTEM_CLOCKS_PCLKB == clock)
1424 {
1425 #if BSP_FEATURE_HAS_CGC_PCKB
1426 return SSP_SUCCESS;
1427 #else
1428 CGC_ERROR_LOG(SSP_ERR_INVALID_ARGUMENT);
1429 return SSP_ERR_INVALID_ARGUMENT;
1430 #endif /* BSP_FEATURE_HAS_CGC_PCKB */
1431 }
1432 else if (CGC_SYSTEM_CLOCKS_PCLKC == clock)
1433 {
1434 #if BSP_FEATURE_HAS_CGC_PCKC
1435 return SSP_SUCCESS;
1436 #else
1437 CGC_ERROR_LOG(SSP_ERR_INVALID_ARGUMENT);
1438 return SSP_ERR_INVALID_ARGUMENT;
1439 #endif /* BSP_FEATURE_HAS_CGC_PCKC */
1440 }
1441 else if (CGC_SYSTEM_CLOCKS_PCLKD == clock)
1442 {
1443 #if BSP_FEATURE_HAS_CGC_PCKD
1444 return SSP_SUCCESS;
1445 #else
1446 CGC_ERROR_LOG(SSP_ERR_INVALID_ARGUMENT);
1447 return SSP_ERR_INVALID_ARGUMENT;
1448 #endif /* BSP_FEATURE_HAS_CGC_PCKD */
1449 }
1450 else
1451 {
1452 CGC_ERROR_LOG(SSP_ERR_INVALID_ARGUMENT);
1453 return SSP_ERR_INVALID_ARGUMENT;
1454 }
1455 }
1456 #endif
1457
1458 /*******************************************************************************************************************//**
1459 * @brief Verifies if Sub-osc Mode is possible
1460 * @retval true Sub-osc mode is possible or feature does not exist (hence no reason to try it later)
1461 * @retval false Sub-osc mode feature is available but could not be used at this time (not meeting conditions)
1462 **********************************************************************************************************************/
r_cgc_subosc_mode_possible(void)1463 static bool r_cgc_subosc_mode_possible(void)
1464 {
1465 #if BSP_FEATURE_HAS_CGC_PLL
1466 if ((false == r_cgc_clock_run_state_get(gp_system_reg, CGC_CLOCK_PLL)) && (false == r_cgc_clock_run_state_get(gp_system_reg, CGC_CLOCK_MAIN_OSC)) &&
1467 (false == r_cgc_clock_run_state_get(gp_system_reg, CGC_CLOCK_HOCO)) && (false == r_cgc_clock_run_state_get(gp_system_reg, CGC_CLOCK_MOCO)))
1468 {
1469 return true;
1470 }
1471 #else
1472 if ((false == r_cgc_clock_run_state_get(gp_system_reg, CGC_CLOCK_MAIN_OSC)) &&
1473 (false == r_cgc_clock_run_state_get(gp_system_reg, CGC_CLOCK_HOCO)) && (false == r_cgc_clock_run_state_get(gp_system_reg, CGC_CLOCK_MOCO)))
1474 {
1475 return true;
1476 }
1477 #endif
1478 return false;
1479 }
1480
1481 /*******************************************************************************************************************//**
1482 * @brief Verifies if Low-speed Mode is possible
1483 * @retval true Low-speed mode is possible
1484 * @retval false Low-speed mode is not possible (not meeting conditions)
1485 **********************************************************************************************************************/
r_cgc_low_speed_mode_possible(void)1486 static bool r_cgc_low_speed_mode_possible(void)
1487 {
1488 #if BSP_FEATURE_HAS_CGC_PLL
1489 return !r_cgc_clock_run_state_get(gp_system_reg, CGC_CLOCK_PLL);
1490 #else /* BSP_FEATURE_HAS_CGC_PLL */
1491 return true;
1492 #endif /* BSP_FEATURE_HAS_CGC_PLL */
1493 }
1494
1495
1496 /*******************************************************************************************************************//**
1497 * @brief Set the optimum operating speed mode based on new system clock
1498 * @param[in] clock_source Clock that will have the operating mode prepared for
1499 * @param[in] current_system_clock Current clock, as before changing the speed mode
1500 **********************************************************************************************************************/
r_cgc_operating_mode_set(cgc_clock_t const clock_source,uint32_t const current_system_clock)1501 static void r_cgc_operating_mode_set(cgc_clock_t const clock_source, uint32_t const current_system_clock)
1502 {
1503 #if BSP_FEATURE_HAS_CGC_PLL && BSP_FEATURE_HAS_CGC_MIDDLE_SPEED
1504 /* Checks if clock source is PLL */
1505 if (CGC_CLOCK_PLL == clock_source)
1506 {
1507 /* PLL will only run in High or Middle Speed modes. */
1508 if (current_system_clock <= gp_cgc_feature->middle_speed_max_freq_hz)
1509 {
1510 /* Switch to middle speed mode */
1511 HW_CGC_SetMiddleSpeedMode(gp_system_reg);
1512 }
1513 else
1514 {
1515 /* Nothing to do, stay in high speed mode */
1516 }
1517 return;
1518 }
1519 #endif /* BSP_FEATURE_HAS_CGC_PLL */
1520 /* For all other remaining clock sources i.e., HOCO, MOCO, LOCO, SUBCLOCK, MOSC */
1521 #if CGC_CFG_USE_LOW_VOLTAGE_MODE
1522 /* System clock should be less than or equal to Low voltage max frequency */
1523 if (current_system_clock <= (gp_cgc_feature->low_voltage_max_freq_hz))
1524 {
1525 /* Switch to low voltage mode */
1526 HW_CGC_SetLowVoltageMode(gp_system_reg);
1527
1528 /* Low voltage mode is conditionally compiled. If the Low voltage mode is executed,
1529 * no other operating power mode needs to be checked for execution, hence the function returns from here.
1530 * If the low voltage mode feature was not conditionally compiled, the next statement would be an 'else if()'
1531 * instead of an 'if()' would be added to choose the optimum power control mode */
1532 return;
1533 }
1534 #endif
1535
1536 /* Checks if MCU supports sub oscillator speed mode and also clock source should be subclock or LOCO */
1537 #if BSP_FEATURE_HAS_CGC_SUBOSC_SPEED
1538 if ((CGC_CLOCK_SUBCLOCK == clock_source) || (CGC_CLOCK_LOCO == clock_source))
1539 {
1540 /* Verify that clocks PLL, MOSC, HOCO and MOCO are stopped as a precondition to enter Subosc Speed Mode */
1541 if (true == r_cgc_subosc_mode_possible())
1542 {
1543 /* Switch to sub oscillator mode */
1544 HW_CGC_SetSubOscSpeedMode(gp_system_reg);
1545 return;
1546 }
1547 /* If sub-osc mode was not available will try the lowest available */
1548 }
1549 #endif
1550
1551 /* System clock should be less than or equal to Low speed max frequency */
1552 if (current_system_clock <= gp_cgc_feature->low_speed_max_freq_hz)
1553 {
1554 if(true == r_cgc_low_speed_mode_possible())
1555 {
1556 /* Switch to low speed mode */
1557 HW_CGC_SetLowSpeedMode(gp_system_reg);
1558 return;
1559 }
1560 }
1561
1562 #if BSP_FEATURE_HAS_CGC_MIDDLE_SPEED
1563 /* System clock should be less than or equal to Middle speed max frequency */
1564 if (current_system_clock <= gp_cgc_feature->middle_speed_max_freq_hz)
1565 {
1566 /* Switch to middle speed mode */
1567 HW_CGC_SetMiddleSpeedMode(gp_system_reg);
1568 }
1569 else
1570 {
1571 /* Nothing to do, stay in high speed mode */
1572 }
1573 #endif /* BSP_FEATURE_HAS_CGC_MIDDLE_SPEED */
1574 }
1575
1576 #if (CGC_CFG_PARAM_CHECKING_ENABLE == 1)
1577 /*******************************************************************************************************************//**
1578 * @brief Check dividers values
1579 * @param[in] p_clock_cfg pointer to the clock configuration structure
1580 * @param[in] min_div minimum low speed clock divider value
1581 * @retval SSP_SUCCESS Operation performed successfully
1582 * @retval SSP_ERR_INVALID_MODE clock divider is divider is greater than minimum low speed clock divider and is invalid
1583 **********************************************************************************************************************/
r_cgc_check_dividers(cgc_system_clock_cfg_t const * const p_clock_cfg,uint32_t min_div)1584 static ssp_err_t r_cgc_check_dividers(cgc_system_clock_cfg_t const * const p_clock_cfg, uint32_t min_div)
1585 {
1586 #if BSP_FEATURE_HAS_CGC_PCKA
1587 /* check if the MCU has PCLKA and PCLKA divider is greater than minimum low speed clock divider*/
1588 CGC_ERROR_RETURN(!(p_clock_cfg->pclka_div < min_div), SSP_ERR_INVALID_MODE);
1589 #endif /* BSP_FEATURE_HAS_CGC_PCKA */
1590
1591 #if BSP_FEATURE_HAS_CGC_PCKB
1592 /* check if the MCU has PCLKB and PCLKB divider is greater than minimum low speed clock divider*/
1593 CGC_ERROR_RETURN(!(p_clock_cfg->pclkb_div < min_div), SSP_ERR_INVALID_MODE);
1594 #endif /* BSP_FEATURE_HAS_CGC_PCKB */
1595
1596 #if BSP_FEATURE_HAS_CGC_PCKC
1597 /* check if the MCU has PCLKC and PCLKC divider is greater than minimum low speed clock divider*/
1598 CGC_ERROR_RETURN(!(p_clock_cfg->pclkc_div < min_div), SSP_ERR_INVALID_MODE);
1599 #endif /* BSP_FEATURE_HAS_CGC_PCKC */
1600
1601 #if BSP_FEATURE_HAS_CGC_PCKD
1602 /* check if the MCU has PCLKD and PCLKD divider is greater than minimum low speed clock divider*/
1603 CGC_ERROR_RETURN(!(p_clock_cfg->pclkd_div < min_div), SSP_ERR_INVALID_MODE);
1604 #endif /* BSP_FEATURE_HAS_CGC_PCKD */
1605
1606 #if BSP_FEATURE_HAS_CGC_FLASH_CLOCK
1607 /* check if the MCU has FCLK and FCLK divider is greater than minimum low speed clock divider*/
1608 CGC_ERROR_RETURN(!(p_clock_cfg->fclk_div < min_div), SSP_ERR_INVALID_MODE);
1609 #endif /* BSP_FEATURE_HAS_CGC_FLASH_CLOCK */
1610
1611 #if BSP_FEATURE_HAS_CGC_EXTERNAL_BUS
1612 /* check if the MCU has BCLK and BCLK divider is greater than minimum low speed clock divider*/
1613 CGC_ERROR_RETURN(!(p_clock_cfg->bclk_div < min_div), SSP_ERR_INVALID_MODE);
1614 #endif /* BSP_FEATURE_HAS_CGC_EXTERNAL_BUS */
1615
1616 /* check if the ICLK is greater than minimum low speed clock divider*/
1617 CGC_ERROR_RETURN(p_clock_cfg->iclk_div >= min_div, SSP_ERR_INVALID_MODE);
1618
1619 return SSP_SUCCESS;
1620 }
1621
1622 /*******************************************************************************************************************//**
1623 * @brief Check config dividers values
1624 * @param[in] p_clock_cfg pointer to clock system configuration
1625 * @retval SSP_SUCCESS Operation performed successfully.
1626 * @retval SSP_ERR_INVALID_ARGUMENT One or more divider values are not satisfying the conditions
1627 * as per User Manual
1628 **********************************************************************************************************************/
r_cgc_check_config_dividers(cgc_system_clock_cfg_t const * const p_clock_cfg)1629 static ssp_err_t r_cgc_check_config_dividers(cgc_system_clock_cfg_t const * const p_clock_cfg)
1630 {
1631 /* Check if MCU supports PCLKA */
1632 #if BSP_FEATURE_HAS_CGC_PCKA
1633 /* Note: Below conditions are based on divider checking, frequency is inversely proportional */
1634 /* Check if ICLK is greater than PCLKA */
1635 CGC_ERROR_RETURN(!(p_clock_cfg->pclka_div < p_clock_cfg->iclk_div), SSP_ERR_INVALID_ARGUMENT);
1636
1637 /* check if PCLKA is greater than PCLKB */
1638 CGC_ERROR_RETURN(!(p_clock_cfg->pclkb_div < p_clock_cfg->pclka_div), SSP_ERR_INVALID_ARGUMENT);
1639
1640 /* check if PCLKD is greater than PCLKA */
1641 CGC_ERROR_RETURN(!(p_clock_cfg->pclka_div < p_clock_cfg->pclkd_div), SSP_ERR_INVALID_ARGUMENT);
1642 #endif /* BSP_FEATURE_HAS_CGC_PCKA */
1643
1644 #if BSP_FEATURE_HAS_CGC_PCKB && BSP_FEATURE_HAS_CGC_PCKD
1645 /* Check if PCLKD is greater than PCLKB */
1646 CGC_ERROR_RETURN(!(p_clock_cfg->pclkb_div < p_clock_cfg->pclkd_div), SSP_ERR_INVALID_ARGUMENT);
1647 #endif /* BSP_FEATURE_HAS_CGC_PCKB && BSP_FEATURE_HAS_CGC_PCKD */
1648
1649 #if BSP_FEATURE_HAS_CGC_PCKB
1650 /* Check if ICLK is greater than PCLKB */
1651 CGC_ERROR_RETURN(!(p_clock_cfg->pclkb_div < p_clock_cfg->iclk_div), SSP_ERR_INVALID_ARGUMENT);
1652 #endif /* defined(BSP_FEATURE_HAS_CGC_PCKB) */
1653
1654 #if BSP_FEATURE_HAS_CGC_FLASH_CLOCK
1655 /* Check if MCU supports FCLK, then check if ICLK is greater than FCLK */
1656 CGC_ERROR_RETURN(!(p_clock_cfg->fclk_div < p_clock_cfg->iclk_div), SSP_ERR_INVALID_ARGUMENT);
1657 #endif /* BSP_FEATURE_HAS_CGC_FLASH_CLOCK */
1658
1659 #if BSP_FEATURE_HAS_CGC_EXTERNAL_BUS
1660 /* Check if MCU has BCLK, then check if ICLK > BCLK */
1661 CGC_ERROR_RETURN(!(p_clock_cfg->bclk_div < p_clock_cfg->iclk_div), SSP_ERR_INVALID_ARGUMENT);
1662 #endif /* BSP_FEATURE_HAS_CGC_EXTERNAL_BUS */
1663
1664 return SSP_SUCCESS;
1665 }
1666 #endif
1667
1668 /*******************************************************************************************************************//**
1669 * @brief Wait for the specified clock to complete the start or stop operation
1670 * @param[in] clock_source clock source that is waited for to complete operation
1671 * @param[in] option clock status value
1672 * @retval SSP_SUCCESS Operation performed successfully.
1673 * @retval SSP_ERR_HARDWARE_TIMEOUT Operation failed to complete
1674 **********************************************************************************************************************/
r_cgc_wait_to_complete(cgc_clock_t const clock_source,cgc_clock_change_t option)1675 static ssp_err_t r_cgc_wait_to_complete(cgc_clock_t const clock_source, cgc_clock_change_t option)
1676 {
1677 volatile uint32_t timeout;
1678 bool start_stop;
1679
1680 timeout = MAX_REGISTER_WAIT_COUNT;
1681
1682 if((option != CGC_CLOCK_CHANGE_NONE))
1683 {
1684 start_stop = (CGC_CLOCK_CHANGE_START == option);
1685 while((r_cgc_clock_run_state_get(gp_system_reg, clock_source) != start_stop) && (0U != timeout))
1686 {
1687 timeout--;
1688 }
1689 CGC_ERROR_RETURN(timeout, SSP_ERR_HARDWARE_TIMEOUT); // return error if timed out
1690 }
1691
1692 return SSP_SUCCESS;
1693 }
1694
1695 /*******************************************************************************************************************//**
1696 * @brief Check if the specified clock is running and stable
1697 * @param[in] clock_source clock to be verified
1698 * @retval SSP_SUCCESS Operation performed successfully.
1699 * @retval SSP_ERR_CLOCK_INACTIVE Specified clock is not running
1700 * @retval SSP_ERR_NOT_STABILIZED Clock not stabilized after starting. A finite stabilization time after starting the
1701 **********************************************************************************************************************/
r_cgc_clock_running_status_check(cgc_clock_t const clock_source)1702 static ssp_err_t r_cgc_clock_running_status_check(cgc_clock_t const clock_source)
1703 {
1704 #if defined(BSP_FEATURE_HAS_CGC_PLL)
1705 if (((clock_source == CGC_CLOCK_HOCO) || (clock_source == CGC_CLOCK_MAIN_OSC))
1706 || (clock_source == CGC_CLOCK_PLL))
1707 #else
1708 if (((clock_source == CGC_CLOCK_HOCO) || (clock_source == CGC_CLOCK_MAIN_OSC)))
1709 #endif /* defined(BSP_FEATURE_HAS_CGC_PLL) */
1710 {
1711 /* make sure the oscillator is stable before setting as system clock */
1712 CGC_ERROR_RETURN(r_cgc_clock_check(gp_system_reg, clock_source), SSP_ERR_NOT_STABILIZED);
1713 }
1714 else /* for CGC_CLOCK_MOCO, CGC_CLOCK_LOCO or CGC_CLOCK_SUBCLOCK */
1715 {
1716 /* Make sure the clock is not stopped before setting as system clock */
1717 /* There is no way to check stability for this clocks, we just check they are active */
1718 CGC_ERROR_RETURN(r_cgc_clock_run_state_get(gp_system_reg, clock_source), SSP_ERR_CLOCK_INACTIVE);
1719 }
1720
1721 return SSP_SUCCESS;
1722 }
1723
1724 /*******************************************************************************************************************//**
1725 * @brief Check if the system needs to go out from sub-osc speed mode
1726 **********************************************************************************************************************/
r_cgc_adjust_subosc_speed_mode(void)1727 static void r_cgc_adjust_subosc_speed_mode(void)
1728 {
1729 /* If system was in subosc speed mode and we turn on other higher speed clocks, subosc speed mode needs to be turned off */
1730 /* Since running speed is still under 32KHz, we can go to low-speed mode */
1731 if (CGC_SUBOSC_SPEED_MODE == r_cgc_operating_mode_get(gp_system_reg))
1732 {
1733 HW_CGC_SetLowSpeedMode(gp_system_reg);
1734 }
1735 }
1736
1737 /*******************************************************************************************************************//**
1738 * @brief Apply options set in configuration structure to all clocks
1739 * @param[in] p_clock_cfg pointer to clock system configuration
1740 * @param[in] options pointer to array of clock status values for all clocks
1741 * @retval SSP_SUCCESS Operation performed successfully.
1742 * @retval SSP_ERR_OSC_STOP_DET_ENABLED Illegal attempt to stop MOCO when Oscillation stop is enabled.
1743 * @retval SSP_ERR_NOT_STABILIZED Clock not stabilized after starting. A finite stabilization time after starting the
1744 * clock has to elapse before it can be stopped.
1745 * @retval SSP_ERR_INVALID_ARGUMENT Invalid argument used.
1746 * @retval SSP_ERR_HARDWARE_TIMEOUT Hardware timed out.
1747 **********************************************************************************************************************/
r_cgc_apply_start_stop_options(cgc_clocks_cfg_t const * const p_clock_cfg,cgc_clock_change_t const * const options)1748 static ssp_err_t r_cgc_apply_start_stop_options(cgc_clocks_cfg_t const * const p_clock_cfg, cgc_clock_change_t const * const options)
1749 {
1750 ssp_err_t err = SSP_SUCCESS;
1751
1752 /* start with PLL clock, so that we may stop it before trying to stop the PLL source clk */
1753 #if BSP_FEATURE_HAS_CGC_PLL
1754 err = r_cgc_clock_start_stop(options[CGC_CLOCK_PLL], CGC_CLOCK_PLL, p_clock_cfg);
1755 CGC_ERROR_RETURN((SSP_SUCCESS == err) || (SSP_ERR_CLOCK_ACTIVE == err), err);
1756 #endif /* BSP_FEATURE_HAS_CGC_PLL */
1757 for (uint32_t i = 0U; i < CGC_CLOCK_PLL; i++)
1758 {
1759 err = r_cgc_clock_start_stop(options[i], (cgc_clock_t) i, p_clock_cfg);
1760 CGC_ERROR_RETURN((SSP_SUCCESS == err) || (SSP_ERR_CLOCK_ACTIVE == err), err);
1761 }
1762
1763 return SSP_SUCCESS;
1764 }
1765
1766 #if BSP_FEATURE_HAS_CGC_PLL
1767 /*******************************************************************************************************************//**
1768 * @brief Check and prepare PLL registers for PLL clock start
1769 * @param[in] p_clock_cfg pointer to clock system configuration
1770 * @retval SSP_SUCCESS Operation performed successfully.
1771 * @retval SSP_ERR_INVALID_ARGUMENT configuration contains illegal parameters
1772 * @retval SSP_ERR_MAIN_OSC_INACTIVE PLL clock source is inactive
1773 * @retval SSP_ERR_NOT_STABILIZED PLL clock is not stabilized
1774 **********************************************************************************************************************/
r_cgc_prepare_pll_clock(cgc_clock_cfg_t * p_clock_cfg)1775 static ssp_err_t r_cgc_prepare_pll_clock(cgc_clock_cfg_t * p_clock_cfg)
1776 {
1777 #if (CGC_CFG_PARAM_CHECKING_ENABLE == 1)
1778 SSP_ASSERT(NULL != p_clock_cfg); // return error if NULL pointer to configuration
1779
1780 /* return error if configuration contains illegal parameters */
1781 CGC_ERROR_RETURN((r_cgc_clockcfg_valid_check(p_clock_cfg)), SSP_ERR_INVALID_ARGUMENT);
1782 /* if the PLL source clock isn't running, PLL cannot be turned on, return error */
1783 CGC_ERROR_RETURN(r_cgc_clock_run_state_get(gp_system_reg, p_clock_cfg->source_clock), SSP_ERR_MAIN_OSC_INACTIVE);
1784 /* make sure the PLL has stopped before starting again */
1785 CGC_ERROR_RETURN(!(r_cgc_clock_check(gp_system_reg, CGC_CLOCK_PLL)), SSP_ERR_NOT_STABILIZED);
1786 #endif /* CGC_CFG_PARAM_CHECKING_ENABLE */
1787
1788 r_cgc_adjust_subosc_speed_mode();
1789
1790 #if BSP_FEATURE_HAS_CGC_PLL_SRC_CFG
1791 r_cgc_pll_clocksource_set(gp_system_reg, p_clock_cfg->source_clock); // configure PLL source clock when needed
1792 #endif /* BSP_FEATURE_HAS_CGC_PLL_SRC_CFG */
1793
1794 r_cgc_pll_divider_set(gp_system_reg, p_clock_cfg->divider); // configure PLL divider
1795 r_cgc_pll_multiplier_set(gp_system_reg, p_clock_cfg->multiplier); // configure PLL multiplier
1796 r_cgc_init_pllfreq(gp_system_reg); // calculate PLL clock frequency
1797
1798 return SSP_SUCCESS;
1799 }
1800 #endif /* BSP_FEATURE_HAS_CGC_PLL */
1801
1802
1803
1804
1805 /*******************************************************************************************************************//**
1806 * @brief This function initializes CGC variables independent of the C runtime environment.
1807 * @retval none
1808 **********************************************************************************************************************/
1809
r_cgc_hw_init(void)1810 static void r_cgc_hw_init (void)
1811 {
1812 /** initialize the clock frequency array */
1813 g_clock_freq[CGC_CLOCK_HOCO] = gp_cgc_feature->hoco_freq_hz; // Initialize the HOCO value.
1814 g_clock_freq[CGC_CLOCK_MOCO] = CGC_MOCO_FREQ; // Initialize the MOCO value.
1815 g_clock_freq[CGC_CLOCK_LOCO] = CGC_LOCO_FREQ; // Initialize the LOCO value.
1816 g_clock_freq[CGC_CLOCK_MAIN_OSC] = gp_cgc_feature->main_osc_freq_hz; // Initialize the Main oscillator value.
1817 g_clock_freq[CGC_CLOCK_SUBCLOCK] = CGC_SUBCLOCK_FREQ; // Initialize the subclock value.
1818 #if BSP_FEATURE_HAS_CGC_PLL
1819 g_clock_freq[CGC_CLOCK_PLL] = CGC_PLL_FREQ; // The PLL value will be calculated at initialization.
1820 #endif /* BSP_FEATURE_HAS_CGC_PLL */
1821 }
1822
1823 #if BSP_FEATURE_HAS_CGC_PLL
1824 /*******************************************************************************************************************//**
1825 * @brief This function initializes PLL frequency value
1826 * @param[in] p_system_reg pointer to system register structure
1827 * @retval none
1828 **********************************************************************************************************************/
r_cgc_init_pllfreq(R_SYSTEM_Type * p_system_reg)1829 static void r_cgc_init_pllfreq (R_SYSTEM_Type * p_system_reg)
1830 {
1831 uint32_t divider = 0U;
1832 divider = r_cgc_pll_divider_get(p_system_reg);
1833 if (divider != 0U) /* prevent divide by 0 */
1834 {
1835 uint32_t clock_freq = 0U;
1836 if (1U == gp_cgc_feature->pllccr_type)
1837 {
1838 clock_freq = g_clock_freq[r_cgc_pll_clocksource_get(p_system_reg)];
1839 }
1840 if (2U == gp_cgc_feature->pllccr_type)
1841 {
1842 clock_freq = g_clock_freq[CGC_CLOCK_MAIN_OSC];
1843 }
1844 /* This casts the float result back to an integer. The multiplier is always a multiple of 0.5, and the clock
1845 * frequency is always a multiple of 2, so casting to an integer is safe. */
1846 /* Float used because float32_t is not part of the C99 standard integer definitions. */
1847 /*LDRA_INSPECTED 90 s *//*LDRA_INSPECTED 90 s */
1848 g_clock_freq[CGC_CLOCK_PLL] = (uint32_t)
1849 (((float) clock_freq / (float)divider) * r_cgc_pll_multiplier_get(p_system_reg));
1850 }
1851 }
1852 #endif /* BSP_FEATURE_HAS_CGC_PLL */
1853
1854 /*******************************************************************************************************************//**
1855 * @brief This function sets the main clock drive
1856 * @param[in] p_system_reg pointer to system register structure
1857 * @param[in] setting - clock drive setting
1858 * @retval none
1859 **********************************************************************************************************************/
1860
r_cgc_main_clock_drive_set(R_SYSTEM_Type * p_system_reg,uint8_t setting)1861 static void r_cgc_main_clock_drive_set (R_SYSTEM_Type * p_system_reg, uint8_t setting)
1862 {
1863 /* Set the drive capacity for the main clock. */
1864 uint8_t modrv_mask = gp_cgc_feature->modrv_mask;
1865 uint8_t modrv_shift = gp_cgc_feature->modrv_shift;
1866 HW_CGC_HardwareUnLock();
1867 p_system_reg->MOMCR =
1868 (uint8_t) ((p_system_reg->MOMCR & (~modrv_mask)) | ((setting << modrv_shift) & modrv_mask));
1869 HW_CGC_HardwareLock();
1870 }
1871
1872 /*******************************************************************************************************************//**
1873 * @brief This function sets the subclock drive
1874 *
1875 * @param[in] p_system_reg pointer to system register structure
1876 * @param[in] setting clock drive setting
1877 *
1878 * @retval none
1879 **********************************************************************************************************************/
1880
r_cgc_subclock_drive_set(R_SYSTEM_Type * p_system_reg,uint8_t setting)1881 static void r_cgc_subclock_drive_set (R_SYSTEM_Type * p_system_reg, uint8_t setting)
1882 {
1883 /* Set the drive capacity for the subclock. */
1884 uint8_t sodrv_mask = gp_cgc_feature->sodrv_mask;
1885 uint8_t sodrv_shift = gp_cgc_feature->sodrv_shift;
1886 HW_CGC_HardwareUnLock();
1887 /* Sub-Clock Drive Capability can be changed only if Sub-Clock is stopped */
1888 if (p_system_reg->SOSCCR_b.SOSTP)
1889 {
1890 p_system_reg->SOMCR =
1891 (uint8_t) ((p_system_reg->SOMCR & (~sodrv_mask)) | ((setting << sodrv_shift) & sodrv_mask));
1892 }
1893 HW_CGC_HardwareLock();
1894 }
1895
1896 /*******************************************************************************************************************//**
1897 * @brief This function starts the selected clock
1898 * @param[in] p_system_reg pointer to system register structure
1899 * @param[in] clock the clock to start
1900 * @retval none
1901 **********************************************************************************************************************/
1902
r_cgc_clock_start(R_SYSTEM_Type * p_system_reg,cgc_clock_t clock)1903 static void r_cgc_clock_start (R_SYSTEM_Type * p_system_reg, cgc_clock_t clock)
1904 {
1905 /* Start the selected clock. */
1906 HW_CGC_HardwareUnLock();
1907
1908 switch (clock)
1909 {
1910 case CGC_CLOCK_HOCO:
1911 p_system_reg->HOCOCR_b.HCSTP = 0U; /* Start the HOCO clock. */
1912 break;
1913
1914 case CGC_CLOCK_MOCO:
1915 p_system_reg->MOCOCR_b.MCSTP = 0U; /* Start the MOCO clock.*/
1916 break;
1917
1918 case CGC_CLOCK_LOCO:
1919 p_system_reg->LOCOCR_b.LCSTP = 0U; /* Start the LOCO clock.*/
1920 break;
1921
1922 case CGC_CLOCK_MAIN_OSC:
1923 p_system_reg->MOSCCR_b.MOSTP = 0U; /* Start the Main oscillator.*/
1924 break;
1925
1926 case CGC_CLOCK_SUBCLOCK:
1927 p_system_reg->SOSCCR_b.SOSTP = 0U; /* Start the subClock.*/
1928 break;
1929
1930 #if BSP_FEATURE_HAS_CGC_PLL
1931 case CGC_CLOCK_PLL:
1932 p_system_reg->PLLCR_b.PLLSTP = 0U; /* Start the PLL clock.*/
1933 break;
1934 #endif /* BSP_FEATURE_HAS_CGC_PLL */
1935
1936 default:
1937 break;
1938 }
1939
1940 HW_CGC_HardwareLock();
1941 }
1942
1943 /*******************************************************************************************************************//**
1944 * @brief This function stops the selected clock
1945 * @param[in] p_system_reg pointer to system register structure
1946 * @param[in] clock the clock to stop
1947 * @retval none
1948 **********************************************************************************************************************/
1949
r_cgc_clock_stop(R_SYSTEM_Type * p_system_reg,cgc_clock_t clock)1950 static void r_cgc_clock_stop (R_SYSTEM_Type * p_system_reg, cgc_clock_t clock)
1951 {
1952 /* Stop the selected clock. */
1953 HW_CGC_HardwareUnLock();
1954 switch (clock)
1955 {
1956 case CGC_CLOCK_HOCO:
1957 p_system_reg->HOCOCR_b.HCSTP = 1U; /* Stop the HOCO clock.*/
1958 break;
1959
1960 case CGC_CLOCK_MOCO:
1961 p_system_reg->MOCOCR_b.MCSTP = 1U; /* Stop the MOCO clock.*/
1962 break;
1963
1964 case CGC_CLOCK_LOCO:
1965 p_system_reg->LOCOCR_b.LCSTP = 1U; /* Stop the LOCO clock.*/
1966 break;
1967
1968 case CGC_CLOCK_MAIN_OSC:
1969 p_system_reg->MOSCCR_b.MOSTP = 1U; /* Stop the main oscillator.*/
1970 break;
1971
1972 case CGC_CLOCK_SUBCLOCK:
1973 p_system_reg->SOSCCR_b.SOSTP = 1U; /* Stop the subClock.*/
1974 break;
1975
1976 #if BSP_FEATURE_HAS_CGC_PLL
1977 case CGC_CLOCK_PLL:
1978 p_system_reg->PLLCR_b.PLLSTP = 1U; /* Stop PLL clock.*/
1979 break;
1980 #endif /* BSP_FEATURE_HAS_CGC_PLL */
1981
1982 default:
1983 break;
1984 }
1985
1986 HW_CGC_HardwareLock();
1987 }
1988
1989 /*******************************************************************************************************************//**
1990 * @brief This function checks the selected clock for stability
1991 * @param[in] p_system_reg pointer to system register structure
1992 * @param[in] clock the clock to check
1993 * @retval bool true if stable, false if not stable or stopped
1994 **********************************************************************************************************************/
1995
r_cgc_clock_check(R_SYSTEM_Type * p_system_reg,cgc_clock_t clock)1996 static bool r_cgc_clock_check (R_SYSTEM_Type * p_system_reg, cgc_clock_t clock)
1997 {
1998 /* Check for stability of selected clock. */
1999 switch (clock)
2000 {
2001 case CGC_CLOCK_HOCO:
2002 if (p_system_reg->OSCSF_b.HOCOSF)
2003 {
2004 return true; /* HOCO is stable */
2005 }
2006
2007 break;
2008
2009 case CGC_CLOCK_MAIN_OSC:
2010 if (p_system_reg->OSCSF_b.MOSCSF)
2011 {
2012 return true; /* Main Osc is stable */
2013 }
2014
2015 break;
2016
2017 #if BSP_FEATURE_HAS_CGC_PLL
2018 case CGC_CLOCK_PLL:
2019 if (p_system_reg->OSCSF_b.PLLSF)
2020 {
2021 return true; /* PLL is stable */
2022 }
2023
2024 break;
2025 #endif /* BSP_FEATURE_HAS_CGC_PLL */
2026
2027 default:
2028 /* All other clocks don't have a stability flag, return true */
2029 return true;
2030 break;
2031 }
2032
2033 return false;
2034 }
2035
2036 #if (CGC_CFG_SUBCLOCK_AT_RESET_ENABLE == 1)
2037 /*******************************************************************************************************************//**
2038 * @brief This function delays for a specified number of clock cycles, of the selected clock
2039 * @param[in] p_system_reg pointer to system register structure
2040 * @param[in] clock the clock to time
2041 * @param[in] cycles the number of cycles to delay
2042 * @retval none
2043 **********************************************************************************************************************/
2044
r_cgc_delay_cycles(R_SYSTEM_Type * p_system_reg,cgc_clock_t clock,uint16_t cycles)2045 static void r_cgc_delay_cycles (R_SYSTEM_Type * p_system_reg, cgc_clock_t clock, uint16_t cycles)
2046 {
2047 /* delay for number of clock cycles specified */
2048
2049 uint32_t delay_count;
2050 uint32_t clock_freq_in;
2051 uint32_t system_clock_freq;
2052
2053 system_clock_freq = r_cgc_clock_hzget(p_system_reg, CGC_SYSTEM_CLOCKS_ICLK);
2054 clock_freq_in = g_clock_freq[clock];
2055 if (clock_freq_in != 0U) // ensure divide by zero doesn't happen
2056 {
2057 delay_count = ((system_clock_freq / clock_freq_in) * cycles);
2058
2059 while (delay_count > 0U)
2060 {
2061 delay_count--;
2062 }
2063 }
2064 }
2065 #endif
2066
2067 /*******************************************************************************************************************//**
2068 * @brief This function sets the source of the main oscillator
2069 * @param[in] p_system_reg pointer to system register structure
2070 * @param[in] osc the source of the main clock oscillator
2071 * @retval none
2072 **********************************************************************************************************************/
2073
r_cgc_mainosc_source_set(R_SYSTEM_Type * p_system_reg,cgc_osc_source_t osc)2074 static void r_cgc_mainosc_source_set (R_SYSTEM_Type * p_system_reg, cgc_osc_source_t osc)
2075 {
2076 /* Set the source to resonator or external osc. */
2077 HW_CGC_HardwareUnLock();
2078 p_system_reg->MOMCR_b.MOSEL = osc;
2079 HW_CGC_HardwareLock();
2080 }
2081
2082 /*******************************************************************************************************************//**
2083 * @brief This function sets the clock wait time
2084 * @param[in] p_system_reg pointer to system register structure
2085 * @param[in] clock the clock to set the wait time for
2086 * @param[in] setting is wait time
2087 * @retval none
2088 **********************************************************************************************************************/
2089
r_cgc_clock_wait_set(R_SYSTEM_Type * p_system_reg,cgc_clock_t clock,uint8_t setting)2090 static void r_cgc_clock_wait_set (R_SYSTEM_Type * p_system_reg, cgc_clock_t clock, uint8_t setting)
2091 {
2092 SSP_PARAMETER_NOT_USED(clock);
2093 /* Set the clock wait time */
2094 HW_CGC_HardwareUnLock();
2095 p_system_reg->MOSCWTCR_b.MSTS = (uint8_t)(setting & 0x0F);
2096 HW_CGC_HardwareLock();
2097 }
2098
2099 /*******************************************************************************************************************//**
2100 * @brief This function sets the system clock source
2101 * @param[in] p_system_reg pointer to system register structure
2102 * @param[in] clock the clock to use for the system clock
2103 * @retval none
2104 **********************************************************************************************************************/
2105
r_cgc_clock_source_set(R_SYSTEM_Type * p_system_reg,cgc_clock_t clock)2106 static void r_cgc_clock_source_set (R_SYSTEM_Type * p_system_reg, cgc_clock_t clock)
2107 {
2108 /* Set the system clock source */
2109 HW_CGC_HardwareUnLock();
2110 p_system_reg->SCKSCR_b.CKSEL = clock; //set the system clock source
2111 HW_CGC_HardwareLock();
2112 }
2113
2114 #if BSP_FEATURE_HAS_CGC_PLL
2115 /*******************************************************************************************************************//**
2116 * @brief This function returns the PLL clock source
2117 * @param[in] p_system_reg pointer to system register structure
2118 * @retval clock type PLL clock source
2119 **********************************************************************************************************************/
2120
r_cgc_pll_clocksource_get(R_SYSTEM_Type * p_system_reg)2121 static cgc_clock_t r_cgc_pll_clocksource_get (R_SYSTEM_Type * p_system_reg)
2122 {
2123 /* PLL source selection only available on S7G2 */
2124 if (gp_cgc_feature->pll_src_configurable)
2125 {
2126 /* Get the PLL clock source */
2127 if (p_system_reg->PLLCCR_b.PLLSRCSEL == 1U)
2128 {
2129 return CGC_CLOCK_HOCO;
2130 }
2131 }
2132
2133 return CGC_CLOCK_MAIN_OSC;
2134 }
2135 #endif /* BSP_FEATURE_HAS_CGC_PLL */
2136
2137 #if BSP_FEATURE_HAS_CGC_PLL
2138 /*******************************************************************************************************************//**
2139 * @brief This function sets the PLL clock source
2140 * @param[in] p_system_reg pointer to system register structure
2141 * @param[in] clock current system clock
2142 * @retval none
2143 **********************************************************************************************************************/
2144 #if BSP_FEATURE_HAS_CGC_PLL_SRC_CFG
r_cgc_pll_clocksource_set(R_SYSTEM_Type * p_system_reg,cgc_clock_t clock)2145 static void r_cgc_pll_clocksource_set (R_SYSTEM_Type * p_system_reg, cgc_clock_t clock)
2146 {
2147 /* Set the PLL clock source */
2148 HW_CGC_HardwareUnLock();
2149 if (CGC_CLOCK_MAIN_OSC == clock)
2150 {
2151 p_system_reg->PLLCCR_b.PLLSRCSEL = CGC_PLL_MAIN_OSC;
2152 }
2153 else
2154 {
2155 /* The default value is HOCO. */
2156 p_system_reg->PLLCCR_b.PLLSRCSEL = CGC_PLL_HOCO;
2157 }
2158 HW_CGC_HardwareLock();
2159 }
2160 #endif
2161 #endif /* BSP_FEATURE_HAS_CGC_PLL */
2162 #if BSP_FEATURE_HAS_CGC_PLL
2163 /*******************************************************************************************************************//**
2164 * @brief This function sets the PLL multiplier
2165 * @param[in] p_system_reg pointer to system register structure
2166 * @param[in] multiplier multiplier value
2167 * @retval none
2168 **********************************************************************************************************************/
2169
2170 /*LDRA_INSPECTED 90 s float used because float32_t is not part of the C99 standard integer definitions. */
r_cgc_pll_multiplier_set(R_SYSTEM_Type * p_system_reg,float multiplier)2171 static void r_cgc_pll_multiplier_set (R_SYSTEM_Type * p_system_reg, float multiplier)
2172 {
2173 /* Set the PLL multiplier */
2174 if (1U == gp_cgc_feature->pllccr_type)
2175 {
2176 uint32_t write_val = (uint32_t) (multiplier * 2) - 1;
2177 HW_CGC_HardwareUnLock();
2178 p_system_reg->PLLCCR_b.PLLMUL = (uint8_t)(write_val & 0x3F);
2179 HW_CGC_HardwareLock();
2180 }
2181 if (2U == gp_cgc_feature->pllccr_type)
2182 {
2183 uint32_t write_val = (uint32_t) multiplier - 1;
2184 HW_CGC_HardwareUnLock();
2185 p_system_reg->PLLCCR2_b.PLLMUL = (uint8_t)(write_val & 0x1F);
2186 HW_CGC_HardwareLock();
2187 }
2188 }
2189 #endif /* BSP_FEATURE_HAS_CGC_PLL */
2190
2191
2192 #if BSP_FEATURE_HAS_CGC_PLL
2193 /*******************************************************************************************************************//**
2194 * @brief This function gets the PLL multiplier
2195 * @param[in] p_system_reg pointer to system register structure
2196 * @retval float multiplier value
2197 **********************************************************************************************************************/
2198
2199 /*LDRA_INSPECTED 90 s float used because float32_t is not part of the C99 standard integer definitions. */
r_cgc_pll_multiplier_get(R_SYSTEM_Type * p_system_reg)2200 static float r_cgc_pll_multiplier_get (R_SYSTEM_Type * p_system_reg)
2201 {
2202 /* Get the PLL multiplier */
2203 /*LDRA_INSPECTED 90 s */
2204 float pll_mul = 0.0f;
2205
2206 if (1U == gp_cgc_feature->pllccr_type)
2207 {
2208 /* This cast is used for compatibility with the S7 implementation. */
2209 /*LDRA_INSPECTED 90 s */
2210 pll_mul = ((float)(p_system_reg->PLLCCR_b.PLLMUL + 1U)) / 2.0f;
2211 }
2212 if (2U == gp_cgc_feature->pllccr_type)
2213 {
2214 /* This cast is used for compatibility with the S1 and S3 implementation. */
2215 /*LDRA_INSPECTED 90 s */
2216 pll_mul = (float) p_system_reg->PLLCCR2_b.PLLMUL + 1.0f;
2217 }
2218
2219 return pll_mul;
2220 }
2221 #endif /* BSP_FEATURE_HAS_CGC_PLL */
2222
2223 #if BSP_FEATURE_HAS_CGC_PLL
2224 /*******************************************************************************************************************//**
2225 * @brief This function sets the PLL divider
2226 * @param[in] p_system_reg pointer to system register structure
2227 * @param[in] divider divider value
2228 * @retval none
2229 **********************************************************************************************************************/
2230
r_cgc_pll_divider_set(R_SYSTEM_Type * p_system_reg,cgc_pll_div_t divider)2231 static void r_cgc_pll_divider_set (R_SYSTEM_Type * p_system_reg, cgc_pll_div_t divider)
2232 {
2233 /* Set the PLL divider */
2234 if (1U == gp_cgc_feature->pllccr_type)
2235 {
2236 uint16_t register_value = g_pllccr_div_setting[divider];
2237 HW_CGC_HardwareUnLock();
2238 p_system_reg->PLLCCR_b.PLIDIV = (uint16_t)(register_value & 0x3);
2239 HW_CGC_HardwareLock();
2240 }
2241 if (2U == gp_cgc_feature->pllccr_type)
2242 {
2243 uint16_t register_value = g_pllccr2_div_setting[divider];
2244 HW_CGC_HardwareUnLock();
2245 p_system_reg->PLLCCR2_b.PLODIV = (uint8_t)(register_value & 0x3);
2246 HW_CGC_HardwareLock();
2247 }
2248 }
2249 #endif /* BSP_FEATURE_HAS_CGC_PLL */
2250
2251 #if BSP_FEATURE_HAS_CGC_PLL
2252 /*******************************************************************************************************************//**
2253 * @brief This function gets the PLL divider
2254 * @param[in] p_system_reg pointer to system register structure
2255 * @retval divider
2256 **********************************************************************************************************************/
2257
r_cgc_pll_divider_get(R_SYSTEM_Type * p_system_reg)2258 static uint16_t r_cgc_pll_divider_get (R_SYSTEM_Type * p_system_reg)
2259 {
2260 /* Get the PLL divider */
2261 uint16_t ret = 1U;
2262 if (1U == gp_cgc_feature->pllccr_type)
2263 {
2264 /* This cast maps the register value to an enumerated list. */
2265 ret = g_pllccr_div_value[p_system_reg->PLLCCR_b.PLIDIV];
2266 }
2267 if (2U == gp_cgc_feature->pllccr_type)
2268 {
2269 /* This cast maps the register value to an enumerated list. */
2270 ret = g_pllccr2_div_value[p_system_reg->PLLCCR2_b.PLODIV];
2271 }
2272 return ret;
2273 }
2274 #endif /* BSP_FEATURE_HAS_CGC_PLL */
2275
2276 /*******************************************************************************************************************//**
2277 * @brief This function gets the system dividers
2278 * @param[in] p_system_reg pointer to system register structure
2279 * @param[in] cfg a pointer to a cgc_system_clock_cfg_t struct
2280 * @param[out] cfg a pointer to a cgc_system_clock_cfg_t struct
2281 * @retval none
2282 **********************************************************************************************************************/
2283
r_cgc_system_dividers_get(R_SYSTEM_Type * p_system_reg,cgc_system_clock_cfg_t * cfg)2284 static void r_cgc_system_dividers_get (R_SYSTEM_Type * p_system_reg, cgc_system_clock_cfg_t * cfg)
2285 {
2286 /* Get the system dividers */
2287 /* The cgc_sys_clock_div_t defines all valid values (3 bits each) for these registers as per the hardware manual,
2288 * and each of the elements of SCKDIVCR_b are 3 bits of a 32-bit value, so these casts are safe. */
2289 #if BSP_FEATURE_HAS_CGC_PCKA
2290 cfg->pclka_div = (cgc_sys_clock_div_t) p_system_reg->SCKDIVCR_b.PCKA;
2291 #else
2292 /* Fill the structure field with 0 which is the value of corresponding reserved bits in register */
2293 cfg->pclka_div = CGC_SYS_CLOCK_DIV_1;
2294 #endif /* BSP_FEATURE_HAS_CGC_PCKA */
2295 #if BSP_FEATURE_HAS_CGC_PCKB
2296 cfg->pclkb_div = (cgc_sys_clock_div_t) p_system_reg->SCKDIVCR_b.PCKB;
2297 #else
2298 /* Fill the structure field with 0 which is the value of corresponding reserved bits in register */
2299 cfg->pclkb_div = CGC_SYS_CLOCK_DIV_1;
2300 #endif /* BSP_FEATURE_HAS_CGC_PCKB */
2301 #if BSP_FEATURE_HAS_CGC_PCKC
2302 cfg->pclkc_div = (cgc_sys_clock_div_t) p_system_reg->SCKDIVCR_b.PCKC;
2303 #else
2304 /* Fill the structure field with 0 which is the value of corresponding reserved bits in register */
2305 cfg->pclkc_div = CGC_SYS_CLOCK_DIV_1;
2306 #endif /* BSP_FEATURE_HAS_CGC_PCKC */
2307 #if BSP_FEATURE_HAS_CGC_PCKD
2308 cfg->pclkd_div = (cgc_sys_clock_div_t) p_system_reg->SCKDIVCR_b.PCKD;
2309 #else
2310 /* Fill the structure field with 0 which is the value of corresponding reserved bits in register */
2311 cfg->pclkd_div = CGC_SYS_CLOCK_DIV_1;
2312 #endif /* BSP_FEATURE_HAS_CGC_PCKD */
2313 cfg->bclk_div = (cgc_sys_clock_div_t) p_system_reg->SCKDIVCR_b.BCK;
2314 cfg->fclk_div = (cgc_sys_clock_div_t) p_system_reg->SCKDIVCR_b.FCK;
2315 cfg->iclk_div = (cgc_sys_clock_div_t) p_system_reg->SCKDIVCR_b.ICK;
2316 }
2317
2318 #if (CGC_CFG_PARAM_CHECKING_ENABLE == 1)
2319 #if BSP_FEATURE_HAS_CGC_PLL
2320 /*******************************************************************************************************************//**
2321 * @brief This function tests the clock configuration for validity (only for systems with PLL)
2322 * @param[in] cfg a pointer to a cgc_clock_cfg_t struct
2323 * @retval bool true if configuration is valid
2324 **********************************************************************************************************************/
2325
r_cgc_clockcfg_valid_check(cgc_clock_cfg_t * cfg)2326 static bool r_cgc_clockcfg_valid_check (cgc_clock_cfg_t * cfg)
2327 {
2328 #if !BSP_FEATURE_HAS_CGC_PLL
2329 SSP_PARAMETER_NOT_USED(cfg);
2330 #else
2331 /* check for valid configuration */
2332
2333 /* Check maximum and minimum divider values */
2334 if (gp_cgc_feature->pll_div_max < cfg->divider)
2335 {
2336 return false; // Value is out of range.
2337 }
2338
2339 /* Check maximum and minimum multiplier values */
2340 /* Float used because float32_t is not part of the C99 standard integer definitions. */
2341 /*LDRA_INSPECTED 90 s *//*LDRA_INSPECTED 90 s */
2342 if (((float)gp_cgc_feature->pll_mul_max < cfg->multiplier) || ((float)gp_cgc_feature->pll_mul_min > cfg->multiplier))
2343 {
2344 return false; // Value is out of range.
2345 }
2346
2347 if ((CGC_CLOCK_MAIN_OSC != cfg->source_clock) && (CGC_CLOCK_HOCO != cfg->source_clock))
2348 {
2349 return false; // Value is out of range.
2350 }
2351 #endif /* #if BSP_FEATURE_HAS_CGC_PLL */
2352
2353 return true;
2354 }
2355 #endif
2356 #endif
2357
2358 /*******************************************************************************************************************//**
2359 * @brief This function returns the divider of the selected clock
2360 * @param[in] p_system_reg pointer to system register structure
2361 * @param[in] clock the system clock to get the divider for
2362 * @retval divider value
2363 **********************************************************************************************************************/
2364
r_cgc_clock_divider_get(R_SYSTEM_Type * p_system_reg,cgc_system_clocks_t clock)2365 static uint32_t r_cgc_clock_divider_get (R_SYSTEM_Type * p_system_reg, cgc_system_clocks_t clock)
2366 {
2367 /* get divider of selected clock */
2368 uint32_t divider;
2369 divider = 0U;
2370
2371 switch (clock)
2372 {
2373 #if BSP_FEATURE_HAS_CGC_PCKA
2374 case CGC_SYSTEM_CLOCKS_PCLKA:
2375 divider = p_system_reg->SCKDIVCR_b.PCKA;
2376 break;
2377 #endif /* #if BSP_FEATURE_HAS_CGC_PCKA */
2378
2379 #if BSP_FEATURE_HAS_CGC_PCKB
2380 case CGC_SYSTEM_CLOCKS_PCLKB:
2381 divider = p_system_reg->SCKDIVCR_b.PCKB;
2382 break;
2383 #endif /* #if BSP_FEATURE_HAS_CGC_PCKB */
2384
2385 #if BSP_FEATURE_HAS_CGC_PCKC
2386 case CGC_SYSTEM_CLOCKS_PCLKC:
2387 divider = p_system_reg->SCKDIVCR_b.PCKC;
2388 break;
2389 #endif /* #if BSP_FEATURE_HAS_CGC_PCKC */
2390
2391 #if BSP_FEATURE_HAS_CGC_PCKD
2392 case CGC_SYSTEM_CLOCKS_PCLKD:
2393 divider = p_system_reg->SCKDIVCR_b.PCKD;
2394 break;
2395 #endif /* #if BSP_FEATURE_HAS_CGC_PCKD */
2396
2397 #if BSP_FEATURE_HAS_CGC_EXTERNAL_BUS
2398 case CGC_SYSTEM_CLOCKS_BCLK:
2399 divider = p_system_reg->SCKDIVCR_b.BCK;
2400 break;
2401 #endif /* #if BSP_FEATURE_HAS_CGC_EXTERNAL_BUS */
2402
2403 #if BSP_FEATURE_HAS_CGC_FLASH_CLOCK
2404 case CGC_SYSTEM_CLOCKS_FCLK:
2405 divider = p_system_reg->SCKDIVCR_b.FCK;
2406 break;
2407 #endif /* #if BSP_FEATURE_HAS_CGC_FLASH_CLOCK */
2408
2409 case CGC_SYSTEM_CLOCKS_ICLK:
2410 divider = p_system_reg->SCKDIVCR_b.ICK;
2411 break;
2412 default:
2413 break;
2414 }
2415
2416 return (divider);
2417 }
2418
2419 /*******************************************************************************************************************//**
2420 * @brief This function returns the frequency of the selected clock
2421 * @param[in] p_system_reg pointer to system register structure
2422 * @param[in] clock the system clock to get the freq for
2423 * @retval frequency
2424 **********************************************************************************************************************/
2425
r_cgc_clock_hzget(R_SYSTEM_Type * p_system_reg,cgc_system_clocks_t clock)2426 static uint32_t r_cgc_clock_hzget (R_SYSTEM_Type * p_system_reg, cgc_system_clocks_t clock)
2427 {
2428 /* get frequency of selected clock */
2429 uint32_t divider;
2430 divider = r_cgc_clock_divider_get(p_system_reg, clock);
2431 return (uint32_t) ((g_clock_freq[HW_CGC_ClockSourceGet(p_system_reg)]) >> divider);
2432 }
2433
2434
2435 /*******************************************************************************************************************//**
2436 * @brief This function returns the frequency of the selected clock
2437 * @param[in] source_clock the source clock, such as the main osc or PLL
2438 * @param[in] divider divider value
2439 * @retval frequency
2440 **********************************************************************************************************************/
2441
r_cgc_clockhz_calculate(cgc_clock_t source_clock,cgc_sys_clock_div_t divider)2442 static uint32_t r_cgc_clockhz_calculate (cgc_clock_t source_clock, cgc_sys_clock_div_t divider)
2443 {
2444 /* calculate frequency of selected system clock, given the source clock and divider */
2445 return (uint32_t) ((g_clock_freq[source_clock]) >> (uint32_t)divider);
2446 }
2447
2448 /*******************************************************************************************************************//**
2449 * @brief This function enables the osc stop detection function and interrupt
2450 * @param[in] p_system_reg pointer to system register structure
2451 * @retval none
2452 **********************************************************************************************************************/
r_cgc_oscstop_detect_enable(R_SYSTEM_Type * p_system_reg)2453 static void r_cgc_oscstop_detect_enable (R_SYSTEM_Type * p_system_reg)
2454 {
2455 /* enable hardware oscillator stop detect function */
2456 HW_CGC_HardwareUnLock();
2457 p_system_reg->OSTDCR_b.OSTDE = 1U; // enable osc stop detection
2458 p_system_reg->OSTDCR_b.OSTDIE = 1U; // enable osc stop detection interrupt
2459 HW_CGC_HardwareLock();
2460 }
2461
2462 /*******************************************************************************************************************//**
2463 * @brief This function disables the osc stop detection function and interrupt
2464 * @param[in] p_system_reg pointer to system register structure
2465 * @retval none
2466 **********************************************************************************************************************/
r_cgc_oscstop_detect_disable(R_SYSTEM_Type * p_system_reg)2467 static void r_cgc_oscstop_detect_disable (R_SYSTEM_Type * p_system_reg)
2468 {
2469 /* disable hardware oscillator stop detect function */
2470 HW_CGC_HardwareUnLock();
2471 p_system_reg->OSTDCR_b.OSTDIE = 0U; // disable osc stop detection interrupt
2472 p_system_reg->OSTDCR_b.OSTDE = 0U; // disable osc stop detection
2473 HW_CGC_HardwareLock();
2474 }
2475
2476 /*******************************************************************************************************************//**
2477 * @brief This function clear the status of the stop detection function
2478 * @param[in] p_system_reg pointer to system register structure
2479 * @retval bool true if oscillator stop detection flag cleared, false if no oscillator stop detected
2480 **********************************************************************************************************************/
2481
r_cgc_oscstop_status_clear(R_SYSTEM_Type * p_system_reg)2482 static bool r_cgc_oscstop_status_clear (R_SYSTEM_Type * p_system_reg)
2483 {
2484 /* clear hardware oscillator stop detect status */
2485 if (p_system_reg->OSTDSR_b.OSTDF == 1U)
2486 {
2487 HW_CGC_HardwareUnLock();
2488 p_system_reg->OSTDSR_b.OSTDF = 0U;
2489 HW_CGC_HardwareLock();
2490 return true; // stop detection cleared
2491 }
2492
2493 return false; // can't clear flag because no stop detected
2494 }
2495
2496
2497 /*******************************************************************************************************************//**
2498 * @brief This function configures the ClockOut divider and clock source
2499 * @param[in] p_system_reg pointer to system register structure
2500 * @param[in] clock the clock out source
2501 * @param[in] divider the clock out divider
2502 * @retval none
2503 **********************************************************************************************************************/
2504
r_cgc_clockout_cfg(R_SYSTEM_Type * p_system_reg,cgc_clock_t clock,cgc_clockout_dividers_t divider)2505 static void r_cgc_clockout_cfg (R_SYSTEM_Type * p_system_reg, cgc_clock_t clock, cgc_clockout_dividers_t divider)
2506 {
2507 /* */
2508 HW_CGC_HardwareUnLock();
2509 p_system_reg->CKOCR_b.CKOEN = 0U; // disable CLKOUT to change configuration
2510 p_system_reg->CKOCR_b.CKODIV = divider; // set CLKOUT dividers
2511 p_system_reg->CKOCR_b.CKOSEL = clock; // set CLKOUT clock source
2512 HW_CGC_HardwareLock();
2513 }
2514
2515 /*******************************************************************************************************************//**
2516 * @brief This function enables ClockOut
2517 * @param[in] p_system_reg pointer to system register structure
2518 * @retval none
2519 **********************************************************************************************************************/
2520
r_cgc_clockout_enable(R_SYSTEM_Type * p_system_reg)2521 static void r_cgc_clockout_enable (R_SYSTEM_Type * p_system_reg)
2522 {
2523 /* Enable CLKOUT output */
2524 HW_CGC_HardwareUnLock();
2525 p_system_reg->CKOCR_b.CKOEN = 1U;
2526 HW_CGC_HardwareLock();
2527 }
2528
2529 /*******************************************************************************************************************//**
2530 * @brief This function disables ClockOut
2531 * @param[in] p_system_reg pointer to system register structure
2532 * @retval none
2533 **********************************************************************************************************************/
2534
r_cgc_clockout_disable(R_SYSTEM_Type * p_system_reg)2535 static void r_cgc_clockout_disable (R_SYSTEM_Type * p_system_reg)
2536 {
2537 /* Disable CLKOUT output */
2538 HW_CGC_HardwareUnLock();
2539 p_system_reg->CKOCR_b.CKOEN = 0U;
2540 HW_CGC_HardwareLock();
2541 }
2542
2543
2544 /*******************************************************************************************************************//**
2545 * @brief This updates the Systick timer period
2546 * @param[in] reload_value Reload value, calculated by caller
2547 * @retval bool true if reload is successful
2548 **********************************************************************************************************************/
r_cgc_systick_update(uint32_t reload_value)2549 static bool r_cgc_systick_update(uint32_t reload_value)
2550 {
2551 bool result = false;
2552 /* SysTick is defined by CMSIS and will not be modified. */
2553 /*LDRA_INSPECTED 93 S *//*LDRA_INSPECTED 96 S *//*LDRA_INSPECTED 330 S *//*LDRA_INSPECTED 330 S */
2554 uint32_t systick_ctrl = SysTick->CTRL;
2555
2556 /** If there is an RTOS in place AND the Systick interrupt is not yet enabled, just return and do nothing */
2557 #if (1 == BSP_CFG_RTOS)
2558 /*LDRA_INSPECTED 93 S *//*LDRA_INSPECTED 96 S *//*LDRA_INSPECTED 330 S *//*LDRA_INSPECTED 330 S */
2559 if ((SysTick->CTRL & SysTick_CTRL_TICKINT_Msk) == 0)
2560 {
2561 return(true); ///< Not really an error.
2562 }
2563 #endif
2564 /*LDRA_INSPECTED 93 S *//*LDRA_INSPECTED 96 S *//*LDRA_INSPECTED 330 S *//*LDRA_INSPECTED 330 S */
2565 SysTick->CTRL = 0U; ///< Disable systick while we reset the counter
2566
2567 // Number of ticks between two interrupts.
2568 /* Save the Priority for Systick Interrupt, will need to be restored after SysTick_Config() */
2569 uint32_t systick_priority = NVIC_GetPriority (SysTick_IRQn);
2570 if (0U == SysTick_Config(reload_value))
2571 {
2572 result = true;
2573 NVIC_SetPriority (SysTick_IRQn, systick_priority); ///< Restore systick priority
2574 }
2575 else
2576 {
2577 /*LDRA_INSPECTED 93 S *//*LDRA_INSPECTED 96 S *//*LDRA_INSPECTED 330 S *//*LDRA_INSPECTED 330 S */
2578 SysTick->CTRL = systick_ctrl; ///< If we were provided an invalid (ie too large) reload value,
2579 ///< keep using prior value.
2580 }
2581 return(result);
2582 }
2583
2584
2585 /*******************************************************************************************************************//**
2586 * @brief This function sets the system dividers
2587 * @param[in] p_system_reg pointer to system register structure
2588 * @param[in] cfg pointer to a cgc_system_clock_cfg_t struct
2589 * @retval none
2590 **********************************************************************************************************************/
2591
r_cgc_system_dividers_set(R_SYSTEM_Type * p_system_reg,cgc_system_clock_cfg_t const * const cfg)2592 static void r_cgc_system_dividers_set (R_SYSTEM_Type * p_system_reg, cgc_system_clock_cfg_t const * const cfg)
2593 {
2594 sckdivcr_clone_t sckdivcr;
2595 /* The cgc_sys_clock_div_t fits in the 3 bits, and each of the elements of sckdivcr_b are 3 bits of a 32-bit value,
2596 * so these casts are safe. */
2597 sckdivcr.sckdivcr_w = (uint32_t) 0x00;
2598
2599 #if BSP_FEATURE_HAS_CGC_PCKA
2600 sckdivcr.sckdivcr_b.pcka = (uint32_t)(cfg->pclka_div & 0x7);
2601 #endif /* BSP_FEATURE_HAS_CGC_PCKA */
2602 #if BSP_FEATURE_HAS_CGC_PCKB
2603 sckdivcr.sckdivcr_b.pckb = (uint32_t)(cfg->pclkb_div & 0x7);
2604 #endif /* BSP_FEATURE_HAS_CGC_PCKB */
2605 #if BSP_FEATURE_HAS_CGC_PCKC
2606 sckdivcr.sckdivcr_b.pckc = (uint32_t)(cfg->pclkc_div & 0x7);
2607 #endif /* BSP_FEATURE_HAS_CGC_PCKC */
2608 #if BSP_FEATURE_HAS_CGC_PCKD
2609 sckdivcr.sckdivcr_b.pckd = (uint32_t)(cfg->pclkd_div & 0x7);
2610 #endif /* BSP_FEATURE_HAS_CGC_PCKD */
2611 #if BSP_FEATURE_HAS_CGC_EXTERNAL_BUS
2612 sckdivcr.sckdivcr_b.bck = (uint32_t)(cfg->bclk_div & 0x7);
2613 #endif /* BSP_FEATURE_HAS_CGC_EXTERNAL_BUS */
2614 #if BSP_FEATURE_HAS_CGC_FLASH_CLOCK
2615 sckdivcr.sckdivcr_b.fck = (uint32_t)(cfg->fclk_div & 0x7);
2616 #endif /* BSP_FEATURE_HAS_CGC_FLASH_CLOCK */
2617
2618 /* All MCUs have ICLK. */
2619 sckdivcr.sckdivcr_b.ick = (uint32_t)(cfg->iclk_div & 0x7);
2620
2621 /* Set the system dividers */
2622 HW_CGC_HardwareUnLock();
2623 p_system_reg->SCKDIVCR = sckdivcr.sckdivcr_w;
2624 HW_CGC_HardwareLock();
2625 }
2626
2627 /**********************************************************************************************************************
2628 * Private Global Functions
2629 **********************************************************************************************************************/
2630 /*******************************************************************************************************************//**
2631 * @brief This function returns the run state of the selected clock
2632 * @param[in] clock the clock to check
2633 * @param[in] p_system_reg pointer to system register structure
2634 * @param[in] clock - the clock to check
2635 * @retval bool true if clock is running, false if stopped
2636 **********************************************************************************************************************/
2637
r_cgc_clock_run_state_get(R_SYSTEM_Type * p_system_reg,cgc_clock_t clock)2638 bool r_cgc_clock_run_state_get (R_SYSTEM_Type * p_system_reg, cgc_clock_t clock)
2639 {
2640 /* Get clock run state. */
2641
2642 switch (clock)
2643 {
2644 case CGC_CLOCK_HOCO:
2645 if (!(p_system_reg->HOCOCR_b.HCSTP))
2646 {
2647 return true; /* HOCO clock is running */
2648 }
2649
2650 break;
2651
2652 case CGC_CLOCK_MOCO:
2653 if (!(p_system_reg->MOCOCR_b.MCSTP))
2654 {
2655 return true; /* MOCO clock is running */
2656 }
2657
2658 break;
2659
2660 case CGC_CLOCK_LOCO:
2661 if (!(p_system_reg->LOCOCR_b.LCSTP))
2662 {
2663 return true; /* LOCO clock is running */
2664 }
2665
2666 break;
2667
2668 case CGC_CLOCK_MAIN_OSC:
2669 if (!(p_system_reg->MOSCCR_b.MOSTP))
2670 {
2671 return true; /* main osc clock is running */
2672 }
2673
2674 break;
2675
2676 case CGC_CLOCK_SUBCLOCK:
2677 if (!(p_system_reg->SOSCCR_b.SOSTP))
2678 {
2679 return true; /* Subclock is running */
2680 }
2681
2682 break;
2683
2684 #if BSP_FEATURE_HAS_CGC_PLL
2685 case CGC_CLOCK_PLL:
2686 if (!(p_system_reg->PLLCR_b.PLLSTP))
2687 {
2688 return true; /* PLL clock is running */
2689 }
2690
2691 break;
2692 #endif /* BSP_FEATURE_HAS_CGC_PLL */
2693
2694 default:
2695 break;
2696 }
2697
2698 return false;
2699 }
2700
2701
2702 /*******************************************************************************************************************//**
2703 * @brief This function checks the MCU for High Speed Mode
2704 * @param[in] p_system_reg pointer to system register structure
2705 * @retval operating_mode current mode of operation read from OPCCR register
2706 **********************************************************************************************************************/
2707
r_cgc_operating_mode_get(R_SYSTEM_Type * p_system_reg)2708 cgc_operating_modes_t r_cgc_operating_mode_get (R_SYSTEM_Type * p_system_reg)
2709 {
2710 cgc_operating_modes_t operating_mode = CGC_HIGH_SPEED_MODE;
2711 if (1U == p_system_reg->SOPCCR_b.SOPCM)
2712 {
2713 operating_mode = CGC_SUBOSC_SPEED_MODE;
2714 }
2715 else
2716 {
2717 operating_mode = (cgc_operating_modes_t)p_system_reg->OPCCR_b.OPCM;
2718 }
2719 return operating_mode;
2720 }
2721
2722 /*******************************************************************************************************************//**
2723 * @brief This function changes the operating power control mode
2724 * @param[in] p_system_reg pointer to system register structure
2725 * @param[in] operating_mode Operating power control mode
2726 **********************************************************************************************************************/
2727
r_cgc_operating_hw_modeset(R_SYSTEM_Type * p_system_reg,cgc_operating_modes_t operating_mode)2728 void r_cgc_operating_hw_modeset (R_SYSTEM_Type * p_system_reg, cgc_operating_modes_t operating_mode)
2729 {
2730 bsp_cache_state_t cache_state;
2731 volatile uint32_t timeout;
2732 timeout = CGC_HW_MAX_REGISTER_WAIT_COUNT;
2733
2734 /** Enable writing to OPCCR and SOPCCR registers. */
2735 HW_CGC_LPMHardwareUnLock();
2736
2737 cache_state = BSP_CACHE_STATE_OFF;
2738 R_BSP_CacheOff(&cache_state); // Turn the cache off.
2739
2740 while ((0U != p_system_reg->SOPCCR_b.SOPCMTSF) || (0U != p_system_reg->OPCCR_b.OPCMTSF))
2741 {
2742 /** Wait for transition to complete. */
2743 timeout--;
2744 if(0U == timeout)
2745 {
2746 /** Disable writing to OPCCR and SOPCCR registers. */
2747 HW_CGC_LPMHardwareLock();
2748 return;
2749 }
2750 }
2751
2752 /** The Sub-osc bit has to be cleared first. */
2753 p_system_reg->SOPCCR_b.SOPCM = CGC_SOPCCR_CLEAR_SUBOSC_SPEED_MODE;
2754 timeout = CGC_HW_MAX_REGISTER_WAIT_COUNT;
2755 while (((0U != p_system_reg->SOPCCR_b.SOPCMTSF) || (0U != p_system_reg->OPCCR_b.OPCMTSF)) && (0U != timeout))
2756 {
2757 /** Wait for transition to complete. */
2758 timeout--;
2759 }
2760
2761 /** Set OPCCR. */
2762 if(CGC_SUBOSC_SPEED_MODE == operating_mode)
2763 {
2764 p_system_reg->OPCCR_b.OPCM = CGC_OPPCR_OPCM_MASK & CGC_OPCCR_LOW_SPEED_MODE;
2765 }
2766 else
2767 {
2768 p_system_reg->OPCCR_b.OPCM = CGC_OPPCR_OPCM_MASK & (uint32_t)operating_mode;
2769 }
2770 timeout = CGC_HW_MAX_REGISTER_WAIT_COUNT;
2771 while (((0U != p_system_reg->SOPCCR_b.SOPCMTSF) || (0U != p_system_reg->OPCCR_b.OPCMTSF)) && (0U != timeout))
2772 {
2773 /** Wait for transition to complete. */
2774 timeout--;
2775 }
2776
2777 /** Set SOPCCR. */
2778 if(CGC_SUBOSC_SPEED_MODE == operating_mode)
2779 {
2780 p_system_reg->SOPCCR_b.SOPCM = CGC_SOPPCR_SOPCM_MASK & CGC_SOPCCR_SET_SUBOSC_SPEED_MODE;
2781 }
2782 else
2783 {
2784 p_system_reg->SOPCCR_b.SOPCM = CGC_SOPPCR_SOPCM_MASK & CGC_SOPCCR_CLEAR_SUBOSC_SPEED_MODE;
2785 }
2786 timeout = CGC_HW_MAX_REGISTER_WAIT_COUNT;
2787 while (((0U != p_system_reg->SOPCCR_b.SOPCMTSF) || (0U != p_system_reg->OPCCR_b.OPCMTSF)) && (0U != timeout))
2788 {
2789 /** Wait for transition to complete. */
2790 timeout--;
2791 }
2792
2793 R_BSP_CacheSet(cache_state); // Restore cache to previous state.
2794
2795 /** Disable writing to OPCCR and SOPCCR registers. */
2796 HW_CGC_LPMHardwareLock();
2797 }
2798
2799
2800 /*******************************************************************************************************************//**
2801 * @brief This function sets the HOCO wait time register
2802 * @param[in] hoco_wait HOCOWTCR HSTS setting
2803 * @param[in] p_system_reg pointer to system register structure
2804 * @retval none
2805 **********************************************************************************************************************/
2806
r_cgc_hoco_wait_control_set(R_SYSTEM_Type * p_system_reg,uint8_t hoco_wait)2807 void r_cgc_hoco_wait_control_set (R_SYSTEM_Type * p_system_reg, uint8_t hoco_wait)
2808 {
2809 /* Set the system clock source */
2810 HW_CGC_HardwareUnLock();
2811 /* Set HOCOWTCR_b.HSTS */
2812 p_system_reg->HOCOWTCR_b.HSTS = 0x7U & hoco_wait;
2813 HW_CGC_HardwareLock();
2814 }
2815
2816 /*******************************************************************************************************************//**
2817 * @} (end addtogroup CGC)
2818 **********************************************************************************************************************/
2819