aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios/os/hal/ports/SPC5/SPC560BCxx/hal_lld.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios/os/hal/ports/SPC5/SPC560BCxx/hal_lld.c')
-rw-r--r--lib/chibios/os/hal/ports/SPC5/SPC560BCxx/hal_lld.c276
1 files changed, 276 insertions, 0 deletions
diff --git a/lib/chibios/os/hal/ports/SPC5/SPC560BCxx/hal_lld.c b/lib/chibios/os/hal/ports/SPC5/SPC560BCxx/hal_lld.c
new file mode 100644
index 000000000..d4b5b63c3
--- /dev/null
+++ b/lib/chibios/os/hal/ports/SPC5/SPC560BCxx/hal_lld.c
@@ -0,0 +1,276 @@
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 SPC560BCxx/hal_lld.c
19 * @brief SPC560B/Cxx 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_RUNMODE_RUN0) == 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
94/**
95 * @brief SPC560B/Cxx clocks and PLL initialization.
96 * @note All the involved constants come from the file @p board.h and
97 * @p hal_lld.h
98 * @note This function must be invoked only after the system reset.
99 *
100 * @special
101 */
102void spc_clock_init(void) {
103
104 /* Waiting for IRC stabilization before attempting anything else.*/
105 while (!ME.GS.B.S_FIRC)
106 ;
107
108#if !SPC5_NO_INIT
109
110#if SPC5_DISABLE_WATCHDOG
111 /* SWT disabled.*/
112 SWT.SR.R = 0xC520;
113 SWT.SR.R = 0xD928;
114 SWT.CR.R = 0xFF00000A;
115#endif
116
117 /* SSCM initialization. Setting up the most restrictive handling of
118 invalid accesses to peripherals.*/
119 SSCM.ERROR.R = 3; /* PAE and RAE bits. */
120
121 /* RGM errors clearing.*/
122 RGM.FES.R = 0xFFFF;
123 RGM.DES.R = 0xFFFF;
124
125 /* Oscillators dividers setup.*/
126 CGM.FIRC_CTL.B.RCDIV = SPC5_IRCDIV_VALUE - 1;
127 CGM.FXOSC_CTL.B.OSCDIV = SPC5_XOSCDIV_VALUE - 1;
128
129 /* The system must be in DRUN mode on entry, if this is not the case then
130 it is considered a serious anomaly.*/
131 if (ME.GS.B.S_CURRENTMODE != SPC5_RUNMODE_DRUN) {
132 SPC5_CLOCK_FAILURE_HOOK();
133 }
134
135#if defined(SPC5_OSC_BYPASS)
136 /* If the board is equipped with an oscillator instead of a xtal then the
137 bypass must be activated.*/
138 CGM.OSC_CTL.B.OSCBYP = TRUE;
139#endif /* SPC5_OSC_BYPASS */
140
141 /* Setting the various dividers and source selectors.*/
142 CGM.SC_DC[0].R = SPC5_CGM_SC_DC0;
143 CGM.SC_DC[1].R = SPC5_CGM_SC_DC1;
144 CGM.SC_DC[2].R = SPC5_CGM_SC_DC2;
145
146 /* Initialization of the FMPLLs settings.*/
147 CGM.FMPLL_CR.R = SPC5_FMPLL0_ODF |
148 ((SPC5_FMPLL0_IDF_VALUE - 1) << 26) |
149 (SPC5_FMPLL0_NDIV_VALUE << 16);
150 CGM.FMPLL_MR.R = 0; /* TODO: Add a setting. */
151
152 /* Run modes initialization.*/
153 ME.IS.R = 8; /* Resetting I_ICONF status.*/
154 ME.MER.R = SPC5_ME_ME_BITS; /* Enabled run modes. */
155 ME.TEST.R = SPC5_ME_TEST_MC_BITS; /* TEST run mode. */
156 ME.SAFE.R = SPC5_ME_SAFE_MC_BITS; /* SAFE run mode. */
157 ME.DRUN.R = SPC5_ME_DRUN_MC_BITS; /* DRUN run mode. */
158 ME.RUN[0].R = SPC5_ME_RUN0_MC_BITS; /* RUN0 run mode. */
159 ME.RUN[1].R = SPC5_ME_RUN1_MC_BITS; /* RUN1 run mode. */
160 ME.RUN[2].R = SPC5_ME_RUN2_MC_BITS; /* RUN2 run mode. */
161 ME.RUN[3].R = SPC5_ME_RUN3_MC_BITS; /* RUN0 run mode. */
162 ME.HALT0.R = SPC5_ME_HALT0_MC_BITS; /* HALT0 run mode. */
163 ME.STOP0.R = SPC5_ME_STOP0_MC_BITS; /* STOP0 run mode. */
164 ME.STANDBY0.R = SPC5_ME_STANDBY0_MC_BITS; /* STANDBY0 run mode. */
165 if (ME.IS.B.I_CONF) {
166 /* Configuration rejected.*/
167 SPC5_CLOCK_FAILURE_HOOK();
168 }
169
170 /* Peripherals run and low power modes initialization.*/
171 ME.RUNPC[0].R = SPC5_ME_RUN_PC0_BITS;
172 ME.RUNPC[1].R = SPC5_ME_RUN_PC1_BITS;
173 ME.RUNPC[2].R = SPC5_ME_RUN_PC2_BITS;
174 ME.RUNPC[3].R = SPC5_ME_RUN_PC3_BITS;
175 ME.RUNPC[4].R = SPC5_ME_RUN_PC4_BITS;
176 ME.RUNPC[5].R = SPC5_ME_RUN_PC5_BITS;
177 ME.RUNPC[6].R = SPC5_ME_RUN_PC6_BITS;
178 ME.RUNPC[7].R = SPC5_ME_RUN_PC7_BITS;
179 ME.LPPC[0].R = SPC5_ME_LP_PC0_BITS;
180 ME.LPPC[1].R = SPC5_ME_LP_PC1_BITS;
181 ME.LPPC[2].R = SPC5_ME_LP_PC2_BITS;
182 ME.LPPC[3].R = SPC5_ME_LP_PC3_BITS;
183 ME.LPPC[4].R = SPC5_ME_LP_PC4_BITS;
184 ME.LPPC[5].R = SPC5_ME_LP_PC5_BITS;
185 ME.LPPC[6].R = SPC5_ME_LP_PC6_BITS;
186 ME.LPPC[7].R = SPC5_ME_LP_PC7_BITS;
187
188 /* CFLASH settings calculated for a maximum clock of 64MHz.*/
189 CFLASH.PFCR0.B.BK0_APC = 2;
190 CFLASH.PFCR0.B.BK0_RWSC = 2;
191
192 /* CMU clock enable */
193 halSPCSetPeripheralClockMode(104,
194 SPC5_ME_PCTL_RUN(1) | SPC5_ME_PCTL_LP(2));
195
196 /* Switches again to DRUN mode (current mode) in order to update the
197 settings.*/
198 if (halSPCSetRunMode(SPC5_RUNMODE_DRUN) == OSAL_FAILED) {
199 SPC5_CLOCK_FAILURE_HOOK();
200 }
201#endif /* !SPC5_NO_INIT */
202}
203
204/**
205 * @brief Switches the system to the specified run mode.
206 *
207 * @param[in] mode one of the possible run modes
208 *
209 * @return The operation status.
210 * @retval OSAL_SUCCESS if the switch operation has been completed.
211 * @retval OSAL_FAILED if the switch operation failed.
212 */
213bool halSPCSetRunMode(spc5_runmode_t mode) {
214
215 /* Clearing status register bits I_IMODE(4) and I_IMTC(1).*/
216 ME.IS.R = 5;
217
218 /* Starts a transition process.*/
219 ME.MCTL.R = SPC5_ME_MCTL_MODE(mode) | SPC5_ME_MCTL_KEY;
220 ME.MCTL.R = SPC5_ME_MCTL_MODE(mode) | SPC5_ME_MCTL_KEY_INV;
221
222 /* Waits for the mode switch or an error condition.*/
223 while (TRUE) {
224 uint32_t r = ME.IS.R;
225 if (r & 1)
226 return OSAL_SUCCESS;
227 if (r & 4)
228 return OSAL_FAILED;
229 }
230}
231
232/**
233 * @brief Changes the clock mode of a peripheral.
234 *
235 * @param[in] n index of the @p PCTL register
236 * @param[in] pctl new value for the @p PCTL register
237 *
238 * @notapi
239 */
240void halSPCSetPeripheralClockMode(uint32_t n, uint32_t pctl) {
241 uint32_t mode;
242
243 ME.PCTL[n].R = pctl;
244 mode = ME.MCTL.B.TARGET_MODE;
245 ME.MCTL.R = SPC5_ME_MCTL_MODE(mode) | SPC5_ME_MCTL_KEY;
246 ME.MCTL.R = SPC5_ME_MCTL_MODE(mode) | SPC5_ME_MCTL_KEY_INV;
247}
248
249#if !SPC5_NO_INIT || defined(__DOXYGEN__)
250/**
251 * @brief Returns the system clock under the current run mode.
252 *
253 * @return The system clock in Hertz.
254 */
255uint32_t halSPCGetSystemClock(void) {
256 uint32_t sysclk;
257
258 sysclk = ME.GS.B.S_SYSCLK;
259 switch (sysclk) {
260 case SPC5_ME_GS_SYSCLK_IRC:
261 return SPC5_IRC_CLK;
262 case SPC5_ME_GS_SYSCLK_DIVIRC:
263 return SPC5_IRC_CLK / SPC5_IRCDIV_VALUE;
264 case SPC5_ME_GS_SYSCLK_XOSC:
265 return SPC5_XOSC_CLK / SPC5_XOSCDIV_VALUE;
266 case SPC5_ME_GS_SYSCLK_DIVXOSC:
267 return SPC5_XOSC_CLK;
268 case SPC5_ME_GS_SYSCLK_FMPLL0:
269 return SPC5_FMPLL0_CLK;
270 default:
271 return 0;
272 }
273}
274#endif /* !SPC5_NO_INIT */
275
276/** @} */