aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios/os/hal/ports/SPC5/SPC560Pxx/hal_lld.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios/os/hal/ports/SPC5/SPC560Pxx/hal_lld.c')
-rw-r--r--lib/chibios/os/hal/ports/SPC5/SPC560Pxx/hal_lld.c314
1 files changed, 314 insertions, 0 deletions
diff --git a/lib/chibios/os/hal/ports/SPC5/SPC560Pxx/hal_lld.c b/lib/chibios/os/hal/ports/SPC5/SPC560Pxx/hal_lld.c
new file mode 100644
index 000000000..4bcfe8a46
--- /dev/null
+++ b/lib/chibios/os/hal/ports/SPC5/SPC560Pxx/hal_lld.c
@@ -0,0 +1,314 @@
1/*
2 SPC5 HAL - Copyright (C) 2013 STMicroelectronics
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17/**
18 * @file SPC560Pxx/hal_lld.c
19 * @brief SPC560Pxx HAL subsystem low level driver source.
20 *
21 * @addtogroup HAL
22 * @{
23 */
24
25#include "hal.h"
26
27/*===========================================================================*/
28/* Driver exported variables. */
29/*===========================================================================*/
30
31/*===========================================================================*/
32/* Driver local variables and types. */
33/*===========================================================================*/
34
35/*===========================================================================*/
36/* Driver local functions. */
37/*===========================================================================*/
38
39/*===========================================================================*/
40/* Driver interrupt handlers. */
41/*===========================================================================*/
42
43/**
44 * @brief PIT channel 0 interrupt handler.
45 *
46 * @isr
47 */
48OSAL_IRQ_HANDLER(vector59) {
49
50 OSAL_IRQ_PROLOGUE();
51
52 osalSysLockFromISR();
53 osalOsTimerHandlerI();
54 osalSysUnlockFromISR();
55
56 /* Resets the PIT channel 0 IRQ flag.*/
57 PIT.CH[0].TFLG.R = 1;
58
59 OSAL_IRQ_EPILOGUE();
60}
61
62/*===========================================================================*/
63/* Driver exported functions. */
64/*===========================================================================*/
65
66/**
67 * @brief Low level HAL driver initialization.
68 *
69 * @notapi
70 */
71void hal_lld_init(void) {
72 uint32_t reg;
73
74 /* The system is switched to the RUN0 mode, the default for normal
75 operations.*/
76 if (halSPCSetRunMode(SPC5_FINAL_RUNMODE) == OSAL_FAILED) {
77 SPC5_CLOCK_FAILURE_HOOK();
78 }
79
80 /* PIT channel 0 initialization for Kernel ticks, the PIT is configured
81 to run in DRUN,RUN0...RUN3 and HALT0 modes, the clock is gated in other
82 modes.*/
83 INTC.PSR[59].R = SPC5_PIT0_IRQ_PRIORITY;
84 halSPCSetPeripheralClockMode(92,
85 SPC5_ME_PCTL_RUN(2) | SPC5_ME_PCTL_LP(2));
86 reg = halSPCGetSystemClock() / OSAL_ST_FREQUENCY - 1;
87 PIT.PITMCR.R = 1; /* PIT clock enabled, stop while debugging. */
88 PIT.CH[0].LDVAL.R = reg;
89 PIT.CH[0].CVAL.R = reg;
90 PIT.CH[0].TFLG.R = 1; /* Interrupt flag cleared. */
91 PIT.CH[0].TCTRL.R = 3; /* Timer active, interrupt enabled. */
92
93 /* EDMA initialization.*/
94 edmaInit();
95}
96
97/**
98 * @brief SPC560Pxx clocks and PLL initialization.
99 * @note All the involved constants come from the file @p board.h and
100 * @p hal_lld.h
101 * @note This function must be invoked only after the system reset.
102 *
103 * @special
104 */
105void spc_clock_init(void) {
106
107 /* Waiting for IRC stabilization before attempting anything else.*/
108 while (!ME.GS.B.S_RC)
109 ;
110
111#if !SPC5_NO_INIT
112
113 /* CMUs initialization.*/
114 CGM.CMU_0_HFREFR_A.R = SPC5_CMU0_HFREFR_INIT;
115 CGM.CMU_0_LFREFR_A.R = SPC5_CMU0_LFREFR_INIT;
116 CGM.CMU_0_MDR.R = SPC5_CMU0_MDR_INIT;
117 CGM.CMU_0_CSR.R = SPC5_CMU0_CSR_INIT;
118#if SPC5_HAS_CMU1
119 CGM.CMU_1_HFREFR_A.R = SPC5_CMU1_HFREFR_INIT;
120 CGM.CMU_1_LFREFR_A.R = SPC5_CMU1_LFREFR_INIT;
121 CGM.CMU_1_CSR.R = SPC5_CMU1_CSR_INIT;
122#endif
123
124#if SPC5_DISABLE_WATCHDOG
125 /* SWT disabled.*/
126 SWT.SR.R = 0xC520;
127 SWT.SR.R = 0xD928;
128 SWT.CR.R = 0xFF00000A;
129#endif
130
131 /* SSCM initialization. Setting up the most restrictive handling of
132 invalid accesses to peripherals.*/
133 SSCM.ERROR.R = 3; /* PAE and RAE bits. */
134
135 /* RGM errors clearing.*/
136 RGM.FES.R = 0xFFFF;
137 RGM.DES.R = 0xFFFF;
138
139 /* The system must be in DRUN mode on entry, if this is not the case then
140 it is considered a serious anomaly.*/
141 if (ME.GS.B.S_CURRENTMODE != SPC5_RUNMODE_DRUN) {
142 SPC5_CLOCK_FAILURE_HOOK();
143 }
144
145#if defined(SPC5_OSC_BYPASS)
146 /* If the board is equipped with an oscillator instead of a xtal then the
147 bypass must be activated.*/
148 CGM.OSC_CTL.B.OSCBYP = TRUE;
149#endif /* SPC5_OSC_BYPASS */
150
151 /* Setting the various dividers and source selectors.*/
152#if SPC5_HAS_AC0
153 CGM.AC0DC.R = SPC5_CGM_AC0_DC0;
154 CGM.AC0SC.R = SPC5_AUX0CLK_SRC;
155#endif
156#if SPC5_HAS_AC1
157 CGM.AC1DC.R = SPC5_CGM_AC1_DC0;
158 CGM.AC1SC.R = SPC5_AUX1CLK_SRC;
159#endif
160#if SPC5_HAS_AC2
161 CGM.AC2DC.R = SPC5_CGM_AC2_DC0;
162 CGM.AC2SC.R = SPC5_AUX2CLK_SRC;
163#endif
164#if SPC5_HAS_AC3
165 CGM.AC3DC.R = SPC5_CGM_AC3_DC0;
166 CGM.AC3SC.R = SPC5_AUX3CLK_SRC;
167#endif
168
169 /* Enables the XOSC in order to check its functionality before proceeding
170 with the initialization.*/
171 ME.DRUN.R = SPC5_ME_MC_SYSCLK_IRC | SPC5_ME_MC_IRCON | \
172 SPC5_ME_MC_XOSC0ON | SPC5_ME_MC_CFLAON_NORMAL | \
173 SPC5_ME_MC_DFLAON_NORMAL | SPC5_ME_MC_MVRON;
174 if (halSPCSetRunMode(SPC5_RUNMODE_DRUN) == OSAL_FAILED) {
175 SPC5_CLOCK_FAILURE_HOOK();
176 }
177
178 /* Initialization of the FMPLLs settings.*/
179 CGM.FMPLL[0].CR.R = SPC5_FMPLL0_ODF |
180 SPC5_FMPLL_IDF(SPC5_FMPLL0_IDF_VALUE) |
181 SPC5_FMPLL_NDIV(SPC5_FMPLL0_NDIV_VALUE) |
182 SPC5_FMPLL0_OPTIONS;
183 CGM.FMPLL[0].MR.R = SPC5_FMPLL0_MR_INIT;
184#if SPC5_HAS_FMPLL1
185 CGM.FMPLL[1].CR.R = SPC5_FMPLL1_ODF |
186 SPC5_FMPLL_IDF(SPC5_FMPLL1_IDF_VALUE) |
187 SPC5_FMPLL_NDIV(SPC5_FMPLL1_NDIV_VALUE) |
188 SPC5_FMPLL1_OPTIONS;
189 CGM.FMPLL[1].MR.R = SPC5_FMPLL1_MR_INIT;
190#endif
191
192 /* Run modes initialization.*/
193 ME.IS.R = 8; /* Resetting I_ICONF status.*/
194 ME.MER.R = SPC5_ME_ME_BITS; /* Enabled run modes. */
195 ME.TEST.R = SPC5_ME_TEST_MC_BITS; /* TEST run mode. */
196 ME.SAFE.R = SPC5_ME_SAFE_MC_BITS; /* SAFE run mode. */
197 ME.DRUN.R = SPC5_ME_DRUN_MC_BITS; /* DRUN run mode. */
198 ME.RUN[0].R = SPC5_ME_RUN0_MC_BITS; /* RUN0 run mode. */
199 ME.RUN[1].R = SPC5_ME_RUN1_MC_BITS; /* RUN1 run mode. */
200 ME.RUN[2].R = SPC5_ME_RUN2_MC_BITS; /* RUN2 run mode. */
201 ME.RUN[3].R = SPC5_ME_RUN3_MC_BITS; /* RUN0 run mode. */
202 ME.HALT0.R = SPC5_ME_HALT0_MC_BITS; /* HALT0 run mode. */
203 ME.STOP0.R = SPC5_ME_STOP0_MC_BITS; /* STOP0 run mode. */
204 if (ME.IS.B.I_CONF) {
205 /* Configuration rejected.*/
206 SPC5_CLOCK_FAILURE_HOOK();
207 }
208
209 /* Peripherals run and low power modes initialization.*/
210 ME.RUNPC[0].R = SPC5_ME_RUN_PC0_BITS;
211 ME.RUNPC[1].R = SPC5_ME_RUN_PC1_BITS;
212 ME.RUNPC[2].R = SPC5_ME_RUN_PC2_BITS;
213 ME.RUNPC[3].R = SPC5_ME_RUN_PC3_BITS;
214 ME.RUNPC[4].R = SPC5_ME_RUN_PC4_BITS;
215 ME.RUNPC[5].R = SPC5_ME_RUN_PC5_BITS;
216 ME.RUNPC[6].R = SPC5_ME_RUN_PC6_BITS;
217 ME.RUNPC[7].R = SPC5_ME_RUN_PC7_BITS;
218 ME.LPPC[0].R = SPC5_ME_LP_PC0_BITS;
219 ME.LPPC[1].R = SPC5_ME_LP_PC1_BITS;
220 ME.LPPC[2].R = SPC5_ME_LP_PC2_BITS;
221 ME.LPPC[3].R = SPC5_ME_LP_PC3_BITS;
222 ME.LPPC[4].R = SPC5_ME_LP_PC4_BITS;
223 ME.LPPC[5].R = SPC5_ME_LP_PC5_BITS;
224 ME.LPPC[6].R = SPC5_ME_LP_PC6_BITS;
225 ME.LPPC[7].R = SPC5_ME_LP_PC7_BITS;
226
227 /* CFLASH settings calculated for a maximum clock of 64MHz.*/
228 CFLASH.PFCR0.B.BK0_APC = 2;
229 CFLASH.PFCR0.B.BK0_RWSC = 2;
230
231 /* Switches again to DRUN mode (current mode) in order to update the
232 settings.*/
233 if (halSPCSetRunMode(SPC5_RUNMODE_DRUN) == OSAL_FAILED) {
234 SPC5_CLOCK_FAILURE_HOOK();
235 }
236
237 /* Clock Out selection after all the other configurations.*/
238 CGM.OCDSSC.R = SPC5_CLKOUT_SRC | SPC5_CGM_OCDS_SELDIV;
239#endif /* !SPC5_NO_INIT */
240}
241
242/**
243 * @brief Switches the system to the specified run mode.
244 *
245 * @param[in] mode one of the possible run modes
246 *
247 * @return The operation status.
248 * @retval OSAL_SUCCESS if the switch operation has been completed.
249 * @retval OSAL_FAILED if the switch operation failed.
250 */
251bool halSPCSetRunMode(spc5_runmode_t mode) {
252
253 /* Clearing status register bits I_IMODE(4) and I_IMTC(1).*/
254 ME.IS.R = 5;
255
256 /* Starts a transition process.*/
257 ME.MCTL.R = SPC5_ME_MCTL_MODE(mode) | SPC5_ME_MCTL_KEY;
258 ME.MCTL.R = SPC5_ME_MCTL_MODE(mode) | SPC5_ME_MCTL_KEY_INV;
259
260 /* Waits for the mode switch or an error condition.*/
261 while (TRUE) {
262 uint32_t r = ME.IS.R;
263 if (r & 1)
264 return OSAL_SUCCESS;
265 if (r & 4)
266 return OSAL_FAILED;
267 }
268}
269
270/**
271 * @brief Changes the clock mode of a peripheral.
272 *
273 * @param[in] n index of the @p PCTL register
274 * @param[in] pctl new value for the @p PCTL register
275 *
276 * @notapi
277 */
278void halSPCSetPeripheralClockMode(uint32_t n, uint32_t pctl) {
279 uint32_t mode;
280
281 ME.PCTL[n].R = pctl;
282 mode = ME.MCTL.B.TARGET_MODE;
283 ME.MCTL.R = SPC5_ME_MCTL_MODE(mode) | SPC5_ME_MCTL_KEY;
284 ME.MCTL.R = SPC5_ME_MCTL_MODE(mode) | SPC5_ME_MCTL_KEY_INV;
285}
286
287#if !SPC5_NO_INIT || defined(__DOXYGEN__)
288/**
289 * @brief Returns the system clock under the current run mode.
290 *
291 * @return The system clock in Hertz.
292 */
293uint32_t halSPCGetSystemClock(void) {
294 uint32_t sysclk;
295
296 sysclk = ME.GS.B.S_SYSCLK;
297 switch (sysclk) {
298 case SPC5_ME_GS_SYSCLK_IRC:
299 return SPC5_IRC_CLK;
300 case SPC5_ME_GS_SYSCLK_XOSC:
301 return SPC5_XOSC_CLK;
302 case SPC5_ME_GS_SYSCLK_FMPLL0:
303 return SPC5_FMPLL0_CLK;
304#if SPC5_HAS_FMPLL1
305 case SPC5_ME_GS_SYSCLK_FMPLL1:
306 return SPC5_FMPLL1_CLK;
307#endif
308 default:
309 return 0;
310 }
311}
312#endif /* !SPC5_NO_INIT */
313
314/** @} */