diff options
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.c | 276 |
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 | */ | ||
48 | OSAL_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 | */ | ||
71 | void 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 | */ | ||
102 | void 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 | */ | ||
213 | bool 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 | */ | ||
240 | void 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 | */ | ||
255 | uint32_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 | /** @} */ | ||