1 /***************************************************************************//**
2 * \file system_psoc6_cm0plus.c
3 * \version 2.95.1
4 *
5 * The device system-source file.
6 *
7 ********************************************************************************
8 * \copyright
9 * Copyright 2016-2021 Cypress Semiconductor Corporation
10 * SPDX-License-Identifier: Apache-2.0
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *******************************************************************************/
24
25 #include <stdbool.h>
26 #include "system_psoc6.h"
27 #include "cy_device.h"
28 #include "cy_device_headers.h"
29 #include "cy_syslib.h"
30 #include "cy_sysclk.h"
31 #include "cy_wdt.h"
32
33 #if !defined(CY_IPC_DEFAULT_CFG_DISABLE)
34 #include "cy_ipc_sema.h"
35 #include "cy_ipc_pipe.h"
36 #include "cy_ipc_drv.h"
37
38 #if defined(CY_DEVICE_PSOC6ABLE2)
39 #include "cy_flash.h"
40 #endif /* defined(CY_DEVICE_PSOC6ABLE2) */
41 #endif /* !defined(CY_IPC_DEFAULT_CFG_DISABLE) */
42
43 #if defined(CY_DEVICE_SECURE)
44 #include "cy_pra.h"
45 #endif /* defined(CY_DEVICE_SECURE) */
46
47
48 /*******************************************************************************
49 * SystemCoreClockUpdate()
50 *******************************************************************************/
51
52 /** Default HFClk frequency in Hz */
53 #define CY_CLK_HFCLK0_FREQ_HZ_DEFAULT (8000000UL)
54
55 /** Default PeriClk frequency in Hz */
56 #define CY_CLK_PERICLK_FREQ_HZ_DEFAULT (4000000UL)
57
58 /** Default SlowClk system core frequency in Hz */
59 #define CY_CLK_SYSTEM_FREQ_HZ_DEFAULT (4000000UL)
60
61
62 /** \cond */
63 /**
64 * Holds the SlowClk (Cortex-M0+) or FastClk (Cortex-M4) system core clock,
65 * which is the system clock frequency supplied to the SysTick timer and the
66 * processor core clock.
67 * This variable implements CMSIS Core global variable.
68 * Refer to the [CMSIS documentation]
69 * (http://www.keil.com/pack/doc/CMSIS/Core/html/group__system__init__gr.html "System and Clock Configuration")
70 * for more details.
71 * This variable can be used by debuggers to query the frequency
72 * of the debug timer or to configure the trace clock speed.
73 *
74 * \attention Compilers must be configured to avoid removing this variable in case
75 * the application program is not using it. Debugging systems require the variable
76 * to be physically present in memory so that it can be examined to configure the debugger. */
77 uint32_t SystemCoreClock = CY_CLK_SYSTEM_FREQ_HZ_DEFAULT;
78
79 /** Holds the HFClk0 clock frequency. Updated by \ref SystemCoreClockUpdate(). */
80 uint32_t cy_Hfclk0FreqHz = CY_CLK_HFCLK0_FREQ_HZ_DEFAULT;
81
82 /** Holds the PeriClk clock frequency. Updated by \ref SystemCoreClockUpdate(). */
83 uint32_t cy_PeriClkFreqHz = CY_CLK_PERICLK_FREQ_HZ_DEFAULT;
84
85 /** Holds the Alternate high frequency clock in Hz. Updated by \ref Cy_BLE_EcoConfigure(). */
86 uint32_t cy_BleEcoClockFreqHz = 0UL;
87
88 /** Holds the AHB frequency. Updated by \ref SystemCoreClockUpdate(). */
89 uint32_t cy_AhbFreqHz = CY_CLK_SYSTEM_FREQ_HZ_DEFAULT;
90 /** \endcond */
91
92
93 /*******************************************************************************
94 * SystemInit()
95 *******************************************************************************/
96
97 /* CLK_FLL_CONFIG default values */
98 #define CY_FB_CLK_FLL_CONFIG_VALUE (0x01000000u)
99 #define CY_FB_CLK_FLL_CONFIG2_VALUE (0x00020001u)
100 #define CY_FB_CLK_FLL_CONFIG3_VALUE (0x00002800u)
101 #define CY_FB_CLK_FLL_CONFIG4_VALUE (0x000000FFu)
102
103
104 /*******************************************************************************
105 * SystemCoreClockUpdate (void)
106 *******************************************************************************/
107
108 /* Do not use these definitions directly in your application */
109 #define CY_DELAY_MS_OVERFLOW_THRESHOLD (0x8000u)
110 #define CY_DELAY_1K_THRESHOLD (1000u)
111 #define CY_DELAY_1M_THRESHOLD (1000000u)
112
113 uint32_t cy_delayFreqKhz = CY_SYSLIB_DIV_ROUNDUP(CY_CLK_SYSTEM_FREQ_HZ_DEFAULT, CY_DELAY_1K_THRESHOLD);
114
115 uint8_t cy_delayFreqMhz = (uint8_t)CY_SYSLIB_DIV_ROUNDUP(CY_CLK_SYSTEM_FREQ_HZ_DEFAULT, CY_DELAY_1M_THRESHOLD);
116
117
118 /*******************************************************************************
119 * Cy_SysEnableCM4(), Cy_SysRetainCM4(), and Cy_SysResetCM4()
120 *******************************************************************************/
121 #define CY_SYS_CM4_PWR_CTL_KEY_OPEN (0x05FAUL)
122 #define CY_SYS_CM4_PWR_CTL_KEY_CLOSE (0xFA05UL)
123 #define CY_SYS_CM4_VECTOR_TABLE_VALID_ADDR (0x000003FFUL)
124
125
SystemInit(void)126 void SystemInit(void)
127 {
128 Cy_PDL_Init(CY_DEVICE_CFG);
129
130 /* Restore FLL registers to the default state as they are not restored by the ROM code */
131 uint32_t copy = SRSS->CLK_FLL_CONFIG;
132 copy &= ~SRSS_CLK_FLL_CONFIG_FLL_ENABLE_Msk;
133 SRSS->CLK_FLL_CONFIG = copy;
134
135 copy = SRSS->CLK_ROOT_SELECT[0u];
136 copy &= ~SRSS_CLK_ROOT_SELECT_ROOT_DIV_Msk; /* Set ROOT_DIV = 0*/
137 SRSS->CLK_ROOT_SELECT[0u] = copy;
138
139 SRSS->CLK_FLL_CONFIG = CY_FB_CLK_FLL_CONFIG_VALUE;
140 SRSS->CLK_FLL_CONFIG2 = CY_FB_CLK_FLL_CONFIG2_VALUE;
141 SRSS->CLK_FLL_CONFIG3 = CY_FB_CLK_FLL_CONFIG3_VALUE;
142 SRSS->CLK_FLL_CONFIG4 = CY_FB_CLK_FLL_CONFIG4_VALUE;
143
144 /* Unlock and disable WDT */
145 Cy_WDT_Unlock();
146 Cy_WDT_Disable();
147
148 Cy_SystemInit();
149 SystemCoreClockUpdate();
150
151 /* Clear data register of IPC structure #7, reserved for the Deep-Sleep operations. */
152 REG_IPC_STRUCT_DATA(CY_IPC_STRUCT_PTR(CY_IPC_CHAN_DDFT)) = 0UL;
153
154 /* Release IPC structure #7 to avoid deadlocks in case of SW or WDT reset during Deep-Sleep entering. */
155 REG_IPC_STRUCT_RELEASE(CY_IPC_STRUCT_PTR(CY_IPC_CHAN_DDFT)) = 0UL;
156
157 #if !defined(CY_IPC_DEFAULT_CFG_DISABLE)
158 /* Allocate and initialize semaphores for the system operations. */
159 CY_SECTION_SHAREDMEM
160 static uint32_t ipcSemaArray[CY_IPC_SEMA_COUNT / CY_IPC_SEMA_PER_WORD];
161
162 (void) Cy_IPC_Sema_Init(CY_IPC_CHAN_SEMA, CY_IPC_SEMA_COUNT, ipcSemaArray);
163
164
165 /********************************************************************************
166 *
167 * Initializes the system pipes. The system pipes are used by BLE and Flash.
168 *
169 * If the default startup file is not used, or SystemInit() is not called in your
170 * project, call the following three functions prior to executing any flash or
171 * EmEEPROM write or erase operation:
172 * -# Cy_IPC_Sema_Init()
173 * -# Cy_IPC_Pipe_Config()
174 * -# Cy_IPC_Pipe_Init()
175 * -# Cy_Flash_Init()
176 *
177 *******************************************************************************/
178
179 /* Create an array of endpoint structures */
180 static cy_stc_ipc_pipe_ep_t systemIpcPipeEpArray[CY_IPC_MAX_ENDPOINTS];
181
182 Cy_IPC_Pipe_Config(systemIpcPipeEpArray);
183
184 static cy_ipc_pipe_callback_ptr_t systemIpcPipeSysCbArray[CY_SYS_CYPIPE_CLIENT_CNT];
185
186 static const cy_stc_ipc_pipe_config_t systemIpcPipeConfigCm0 =
187 {
188 /* .ep0ConfigData */
189 {
190 /* .ipcNotifierNumber */ CY_IPC_INTR_CYPIPE_EP0,
191 /* .ipcNotifierPriority */ CY_SYS_INTR_CYPIPE_PRIOR_EP0,
192 /* .ipcNotifierMuxNumber */ CY_SYS_INTR_CYPIPE_MUX_EP0,
193 /* .epAddress */ CY_IPC_EP_CYPIPE_CM0_ADDR,
194 /* .epConfig */ CY_SYS_CYPIPE_CONFIG_EP0
195 },
196 /* .ep1ConfigData */
197 {
198 /* .ipcNotifierNumber */ CY_IPC_INTR_CYPIPE_EP1,
199 /* .ipcNotifierPriority */ CY_SYS_INTR_CYPIPE_PRIOR_EP1,
200 /* .ipcNotifierMuxNumber */ 0u,
201 /* .epAddress */ CY_IPC_EP_CYPIPE_CM4_ADDR,
202 /* .epConfig */ CY_SYS_CYPIPE_CONFIG_EP1
203 },
204 /* .endpointClientsCount */ CY_SYS_CYPIPE_CLIENT_CNT,
205 /* .endpointsCallbacksArray */ systemIpcPipeSysCbArray,
206 /* .userPipeIsrHandler */ &Cy_SysIpcPipeIsrCm0
207 };
208
209 Cy_IPC_Pipe_Init(&systemIpcPipeConfigCm0);
210
211 #if defined(CY_DEVICE_PSOC6ABLE2)
212 Cy_Flash_Init();
213 #endif /* defined(CY_DEVICE_PSOC6ABLE2) */
214
215 #endif /* !defined(CY_IPC_DEFAULT_CFG_DISABLE) */
216
217 #if defined(CY_DEVICE_SECURE)
218 /* Initialize Protected Regsiter Access driver. */
219 Cy_PRA_Init();
220 #endif /* defined(CY_DEVICE_SECURE) */
221 }
222
223
224 /*******************************************************************************
225 * Function Name: Cy_SystemInit
226 ****************************************************************************//**
227 *
228 * The function is called during device startup. Once project compiled as part of
229 * the PSoC Creator project, the Cy_SystemInit() function is generated by the
230 * PSoC Creator.
231 *
232 * The function generated by PSoC Creator performs all of the necessary device
233 * configuration based on the design settings. This includes settings from the
234 * Design Wide Resources (DWR) such as Clocks and Pins as well as any component
235 * configuration that is necessary.
236 *
237 *******************************************************************************/
Cy_SystemInit(void)238 __WEAK void Cy_SystemInit(void)
239 {
240 /* Empty weak function. The actual implementation to be in the PSoC Creator
241 * generated strong function.
242 */
243 }
244
245
SystemCoreClockUpdate(void)246 void SystemCoreClockUpdate (void)
247 {
248 uint32 locHf0Clock = Cy_SysClk_ClkHfGetFrequency(0UL);
249
250 if (0UL != locHf0Clock)
251 {
252 cy_Hfclk0FreqHz = locHf0Clock;
253 cy_PeriClkFreqHz = locHf0Clock / (1UL + (uint32_t)Cy_SysClk_ClkPeriGetDivider());
254 SystemCoreClock = cy_PeriClkFreqHz / (1UL + (uint32_t)Cy_SysClk_ClkSlowGetDivider());
255
256 /* Sets clock frequency for Delay API */
257 cy_delayFreqMhz = (uint8_t)CY_SYSLIB_DIV_ROUNDUP(SystemCoreClock, CY_DELAY_1M_THRESHOLD);
258 cy_delayFreqKhz = CY_SYSLIB_DIV_ROUNDUP(SystemCoreClock, CY_DELAY_1K_THRESHOLD);
259
260 /* Get the frequency of AHB source, CLK HF0 is the source for AHB*/
261 cy_AhbFreqHz = Cy_SysClk_ClkHfGetFrequency(0UL);
262 }
263 }
264
265
266 #if (CY_SYSTEM_CPU_CM0P == 1UL) || defined(CY_DOXYGEN)
267 /*******************************************************************************
268 * Function Name: Cy_SysGetCM4Status
269 ****************************************************************************//**
270 *
271 * Returns the Cortex-M4 core power mode.
272 *
273 * \return \ref group_system_config_cm4_status_macro
274 *
275 *******************************************************************************/
Cy_SysGetCM4Status(void)276 uint32_t Cy_SysGetCM4Status(void)
277 {
278 uint32_t regValue;
279
280 /* Get current power mode */
281 regValue = CPUSS->CM4_PWR_CTL & CPUSS_CM4_PWR_CTL_PWR_MODE_Msk;
282
283 return (regValue);
284 }
285
286
287 /*******************************************************************************
288 * Function Name: Cy_SysEnableCM4
289 ****************************************************************************//**
290 *
291 * Sets vector table base address and enables the Cortex-M4 core.
292 *
293 * \note If the CPU is already enabled, it is reset and then enabled.
294 *
295 * \param vectorTableOffset The offset of the vector table base address from
296 * memory address 0x00000000. The offset should be multiple to 1024 bytes.
297 *
298 *******************************************************************************/
Cy_SysEnableCM4(uint32_t vectorTableOffset)299 void Cy_SysEnableCM4(uint32_t vectorTableOffset)
300 {
301 uint32_t regValue;
302 uint32_t interruptState;
303 uint32_t cpuState;
304
305 CY_ASSERT_L2((vectorTableOffset & CY_SYS_CM4_VECTOR_TABLE_VALID_ADDR) == 0UL);
306
307 interruptState = Cy_SysLib_EnterCriticalSection();
308
309 cpuState = Cy_SysGetCM4Status();
310 if (CY_SYS_CM4_STATUS_ENABLED == cpuState)
311 {
312 Cy_SysResetCM4();
313 }
314
315 CPUSS->CM4_VECTOR_TABLE_BASE = vectorTableOffset;
316
317 regValue = CPUSS->CM4_PWR_CTL & ~(CPUSS_CM4_PWR_CTL_VECTKEYSTAT_Msk | CPUSS_CM4_PWR_CTL_PWR_MODE_Msk);
318 regValue |= _VAL2FLD(CPUSS_CM4_PWR_CTL_VECTKEYSTAT, CY_SYS_CM4_PWR_CTL_KEY_OPEN);
319 regValue |= CY_SYS_CM4_STATUS_ENABLED;
320 CPUSS->CM4_PWR_CTL = regValue;
321
322 while((CPUSS->CM4_STATUS & CPUSS_CM4_STATUS_PWR_DONE_Msk) == 0UL)
323 {
324 /* Wait for the power mode to take effect */
325 }
326
327 Cy_SysLib_ExitCriticalSection(interruptState);
328 }
329
330
331 /*******************************************************************************
332 * Function Name: Cy_SysDisableCM4
333 ****************************************************************************//**
334 *
335 * Disables the Cortex-M4 core and waits for the mode to take the effect.
336 *
337 * \warning Do not call the function while the Cortex-M4 is executing because
338 * such a call may corrupt/abort a pending bus-transaction by the CPU and cause
339 * unexpected behavior in the system including a deadlock. Call the function
340 * while the Cortex-M4 core is in the Sleep or Deep Sleep low-power mode. Use
341 * the \ref group_syspm Power Management (syspm) API to put the CPU into the
342 * low-power modes. Use the \ref Cy_SysPm_ReadStatus() to get a status of the
343 * CPU.
344 *
345 *******************************************************************************/
Cy_SysDisableCM4(void)346 void Cy_SysDisableCM4(void)
347 {
348 uint32_t interruptState;
349 uint32_t regValue;
350
351 interruptState = Cy_SysLib_EnterCriticalSection();
352
353 regValue = CPUSS->CM4_PWR_CTL & ~(CPUSS_CM4_PWR_CTL_VECTKEYSTAT_Msk | CPUSS_CM4_PWR_CTL_PWR_MODE_Msk);
354 regValue |= _VAL2FLD(CPUSS_CM4_PWR_CTL_VECTKEYSTAT, CY_SYS_CM4_PWR_CTL_KEY_OPEN);
355 regValue |= CY_SYS_CM4_STATUS_DISABLED;
356 CPUSS->CM4_PWR_CTL = regValue;
357
358 while((CPUSS->CM4_STATUS & CPUSS_CM4_STATUS_PWR_DONE_Msk) == 0UL)
359 {
360 /* Wait for the power mode to take effect */
361 }
362
363 Cy_SysLib_ExitCriticalSection(interruptState);
364 }
365
366
367 /*******************************************************************************
368 * Function Name: Cy_SysRetainCM4
369 ****************************************************************************//**
370 *
371 * Retains the Cortex-M4 core and exists without waiting for the mode to take
372 * effect.
373 *
374 * \note The retained mode can be entered only from the enabled mode.
375 *
376 * \warning Do not call the function while the Cortex-M4 is executing because
377 * such a call may corrupt/abort a pending bus-transaction by the CPU and cause
378 * unexpected behavior in the system including a deadlock. Call the function
379 * while the Cortex-M4 core is in the Sleep or Deep Sleep low-power mode. Use
380 * the \ref group_syspm Power Management (syspm) API to put the CPU into the
381 * low-power modes. Use the \ref Cy_SysPm_ReadStatus() to get a status of the CPU.
382 *
383 *******************************************************************************/
Cy_SysRetainCM4(void)384 void Cy_SysRetainCM4(void)
385 {
386 uint32_t interruptState;
387 uint32_t regValue;
388
389 interruptState = Cy_SysLib_EnterCriticalSection();
390
391 regValue = CPUSS->CM4_PWR_CTL & ~(CPUSS_CM4_PWR_CTL_VECTKEYSTAT_Msk | CPUSS_CM4_PWR_CTL_PWR_MODE_Msk);
392 regValue |= _VAL2FLD(CPUSS_CM4_PWR_CTL_VECTKEYSTAT, CY_SYS_CM4_PWR_CTL_KEY_OPEN);
393 regValue |= CY_SYS_CM4_STATUS_RETAINED;
394 CPUSS->CM4_PWR_CTL = regValue;
395
396 Cy_SysLib_ExitCriticalSection(interruptState);
397 }
398
399
400 /*******************************************************************************
401 * Function Name: Cy_SysResetCM4
402 ****************************************************************************//**
403 *
404 * Resets the Cortex-M4 core and waits for the mode to take the effect.
405 *
406 * \note The reset mode can not be entered from the retained mode.
407 *
408 * \warning Do not call the function while the Cortex-M4 is executing because
409 * such a call may corrupt/abort a pending bus-transaction by the CPU and cause
410 * unexpected behavior in the system including a deadlock. Call the function
411 * while the Cortex-M4 core is in the Sleep or Deep Sleep low-power mode. Use
412 * the \ref group_syspm Power Management (syspm) API to put the CPU into the
413 * low-power modes. Use the \ref Cy_SysPm_ReadStatus() to get a status of the CPU.
414 *
415 *******************************************************************************/
Cy_SysResetCM4(void)416 void Cy_SysResetCM4(void)
417 {
418 uint32_t interruptState;
419 uint32_t regValue;
420
421 interruptState = Cy_SysLib_EnterCriticalSection();
422
423 regValue = CPUSS->CM4_PWR_CTL & ~(CPUSS_CM4_PWR_CTL_VECTKEYSTAT_Msk | CPUSS_CM4_PWR_CTL_PWR_MODE_Msk);
424 regValue |= _VAL2FLD(CPUSS_CM4_PWR_CTL_VECTKEYSTAT, CY_SYS_CM4_PWR_CTL_KEY_OPEN);
425 regValue |= CY_SYS_CM4_STATUS_RESET;
426 CPUSS->CM4_PWR_CTL = regValue;
427
428 while((CPUSS->CM4_STATUS & CPUSS_CM4_STATUS_PWR_DONE_Msk) == 0UL)
429 {
430 /* Wait for the power mode to take effect */
431 }
432
433 Cy_SysLib_ExitCriticalSection(interruptState);
434 }
435 #endif /* #if (CY_SYSTEM_CPU_CM0P == 1UL) || defined(CY_DOXYGEN) */
436
437 #if !defined(CY_IPC_DEFAULT_CFG_DISABLE)
438 /*******************************************************************************
439 * Function Name: Cy_SysIpcPipeIsrCm0
440 ****************************************************************************//**
441 *
442 * This is the interrupt service routine for the system pipe.
443 *
444 *******************************************************************************/
Cy_SysIpcPipeIsrCm0(void)445 void Cy_SysIpcPipeIsrCm0(void)
446 {
447 Cy_IPC_Pipe_ExecuteCallback(CY_IPC_EP_CYPIPE_CM0_ADDR);
448 }
449 #endif
450
451
452 /*******************************************************************************
453 * Function Name: Cy_MemorySymbols
454 ****************************************************************************//**
455 *
456 * The intention of the function is to declare boundaries of the memories for the
457 * MDK compilers. For the rest of the supported compilers, this is done using
458 * linker configuration files. The following symbols used by the cymcuelftool.
459 *
460 *******************************************************************************/
461 #if defined (__ARMCC_VERSION) && (__ARMCC_VERSION < 6010050)
Cy_MemorySymbols(void)462 __asm void Cy_MemorySymbols(void)
463 {
464 /* Flash */
465 EXPORT __cy_memory_0_start
466 EXPORT __cy_memory_0_length
467 EXPORT __cy_memory_0_row_size
468
469 /* Working Flash */
470 EXPORT __cy_memory_1_start
471 EXPORT __cy_memory_1_length
472 EXPORT __cy_memory_1_row_size
473
474 /* Supervisory Flash */
475 EXPORT __cy_memory_2_start
476 EXPORT __cy_memory_2_length
477 EXPORT __cy_memory_2_row_size
478
479 /* XIP */
480 EXPORT __cy_memory_3_start
481 EXPORT __cy_memory_3_length
482 EXPORT __cy_memory_3_row_size
483
484 /* eFuse */
485 EXPORT __cy_memory_4_start
486 EXPORT __cy_memory_4_length
487 EXPORT __cy_memory_4_row_size
488
489 /* Flash */
490 __cy_memory_0_start EQU __cpp(CY_FLASH_BASE)
491 __cy_memory_0_length EQU __cpp(CY_FLASH_SIZE)
492 __cy_memory_0_row_size EQU 0x200
493
494 /* Flash region for EEPROM emulation */
495 __cy_memory_1_start EQU __cpp(CY_EM_EEPROM_BASE)
496 __cy_memory_1_length EQU __cpp(CY_EM_EEPROM_SIZE)
497 __cy_memory_1_row_size EQU 0x200
498
499 /* Supervisory Flash */
500 __cy_memory_2_start EQU __cpp(CY_SFLASH_BASE)
501 __cy_memory_2_length EQU __cpp(CY_SFLASH_SIZE)
502 __cy_memory_2_row_size EQU 0x200
503
504 /* XIP */
505 __cy_memory_3_start EQU __cpp(CY_XIP_BASE)
506 __cy_memory_3_length EQU __cpp(CY_XIP_SIZE)
507 __cy_memory_3_row_size EQU 0x200
508
509 /* eFuse */
510 __cy_memory_4_start EQU __cpp(0x90700000)
511 __cy_memory_4_length EQU __cpp(0x100000)
512 __cy_memory_4_row_size EQU __cpp(1)
513 }
514 #endif /* defined (__ARMCC_VERSION) && (__ARMCC_VERSION < 6010050) */
515
516
517 /* [] END OF FILE */
518