Contiki 3.x
cpu.c
1 /*-----------------------------------------------------------------------------------------------------------------------------------*/
2 /* cpu.c
3  *
4  * Initialisation & Interrupt handler for CPU on the Freescale FRDM-KL25z Freedom Board
5  *
6  * Author: Graeme Bragg
7  * ARM-ECS / Pervasive Systems Centre
8  * School of Electronics & Computer Science
9  * University of Southampton
10  *
11  *
12  * 27/2/2013 Rev.01 Configures CPU for 20.97152MHz Bus, Core and MCG Clock sources from the internal 32K reference oscillator.
13  * CPU runs in FEI. MGCIRCLK source is set to the slow internal oscillator.
14  * VLPM, LLS and VLLS are "allowed". NMI Interrupt is enabled on PTA4, Reset is PTA20.
15  * 5/3/2013 Rev.02 Functions to enter low power modes.
16  * 12/3/2013 Rev.03 Added definitions for clock values.
17  * 18/2/2014 Rev.04 Options for 21MHz (from 32k internal) or 48MHz (from 8MHz external) clocks.
18  *
19  *
20  * Page references relate to the KL25 Sub-Family Reference Manual, Document No. KL25P80M48SF0RM, Rev. 3 September 2012
21  * Available on 25/02/2013 from http://cache.freescale.com/files/32bit/doc/ref_manual/KL25P80M48SF0RM.pdf?fr=gdc
22  *
23  * Page references to "M0 Book" refer to "The Definitive Guide to the ARM Cortex-M0" by Joseph Yiu, ISBN 978-0-12-385477-3.
24  *
25  *
26  * ***NB*** This file is intended for use with a new "Bareboard" project (with no rapid-development) in Code Warrior.
27  * If this is not the case, you MUST ensure that an appropriate entry of "NMI_Handler" exists in entry 2
28  * (address 0x00000008) of the VectorTable.
29  *
30  * Appropriate entries for the interrupt handler exist in the vector table contained in the generated
31  * kinetis_sysinit.c file
32  */
33 /*-----------------------------------------------------------------------------------------------------------------------------------*/
34 
35 #include "derivative.h" /* I/O map for MKL25Z128VLK4 */
36 #include "cpu.h"
37 
38 void port_enable(uint8_t PortMask) /* Enable clock to used ports. This is required before configuring the port. Page 206. */
39 {
40  SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; /* Enable clock to PortA as this is ALWAYS required for NMI and Reset pin. */
41 
42  if(PortMask & PORTB_EN_MASK) /* If PortB Enable Mask, */
43  {
44  SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK; /* Enable Clock to PortB. */
45  }
46  if(PortMask & PORTC_EN_MASK) /* If PortC Enable Mask, */
47  {
48  SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK; /* Enable Clock to PortC. */
49  }
50  if(PortMask & PORTD_EN_MASK) /* If PortD Enable Mask, */
51  {
52  SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK; /* Enable Clock to PortD. */
53  }
54  if(PortMask & PORTE_EN_MASK) /* If PortE Enable Mask, */
55  {
56  SIM_SCGC5 |= SIM_SCGC5_PORTE_MASK; /* Enable Clock to PortE. */
57  }
58 }
59 
60 void cpu_init(void)
61 {
62 
63  /* CPU Pin Allocations */
64  PORTA_PCR20 = (uint32_t)((PORTA_PCR20 & ~0x01000000) | 0x0700); /* Set PORTA_PCR20 as Reset, ISF=0,MUX=7 */
65  PORTA_PCR4 = (uint32_t)((PORTA_PCR4 & ~0x01000000) | 0x0700); /* Set PORTA_PCR4 as NMI, ISF=0,MUX=7. */
66 
67  NVIC->IP[1] &= (uint32_t)~0x00FF0000; /* Set NVIC_IPR1: Irq 4 to 7 Priority Register. PRI_6=0 */
68 
69  cpu_cpsie();
70 
71 
72 }
73 
74 
75 void cpu_run(void) /* Place core into RUN mode. */
76 {
77  SCB->SCR &= (uint32_t)~(SCB_SCR_SLEEPDEEP_MASK | SCB_SCR_SLEEPONEXIT_MASK); /* Clear Sleep Deep mask and Sleep on Exit mask. M0 book Page 457. */
78 }
79 
80 void cpu_wait(void) /* Place Core into WAIT mode (or VLPW if in VLPR). */
81 {
82  SCB->SCR &= (uint32_t)~(SCB_SCR_SLEEPDEEP_MASK); /* Clear Sleep Deep mask so that WFI puts CPU into wait. M0 book Page 457. */
83  SCB->SCR |= (uint32_t)SCB_SCR_SLEEPONEXIT_MASK; /* Set Sleep On Exit mask so that CPU returns to wait after interrupt. M0 book Page 457. */
84  asm("DSB"); /* DSB instruction to ensure effect of of previous writes. See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0321a/BIHBGGHF.html */
85  asm("WFI"); /* Enter sleep/wait. Page 141 to 143. */
86 }
87 
88 void cpu_stop(Type_StopMode StopMode) /* Place core into one of the STOP modes. Similar to ARM Deep Sleep. */
89 {
90  /* Clear Low Leakage Wakeup Unit flags */
91  LLWU_F1 = (uint8_t)0xFF; /* CLear LLWU_F1: Write 1 to all bits. Page 255. */
92  LLWU_F2 = (uint8_t)0xFF; /* CLear LLWU_F2: Write 1 to all bits. Page 257. */
93  //LLWU_F3 = (uint8_t)0xFF; /* CLear LLWU_F3: Write 1 to all bits. Page 258. */
94  LLWU_FILT1 |= LLWU_FILT1_FILTF_MASK; /* Clear LLWU_FILT1: Write 1 to FILTF bit. Page 260. */
95  LLWU_FILT2 |= LLWU_FILT2_FILTF_MASK; /* Clear LLWU_FILT2: Write 1 to FILTF bit. Page 261. */
96 
97  SCB->SCR |= (uint32_t)(SCB_SCR_SLEEPDEEP_MASK); /* Set Sleep Deep mask so that WFI puts CPU into sleep. M0 book Page 457. */
98 
99  switch(StopMode) { /* Set the stop mode */
100  case Mode_Stop:
101  SMC_PMCTRL = (uint8_t)((SMC_PMCTRL & ~SMC_PMCTRL_STOPM_MASK) | 0x00); /* Set SMC_PMCTRL: Normal Stop. STOPM=4. Page 221. */
102  SMC_STOPCTRL = (uint8_t)((SMC_STOPCTRL & ~SMC_STOPCTRL_PSTOPO_MASK) | 0x00); /* Set SMC_STOPCTRL: Normal Stop. PSTOPO = 0. Page 222. */
103  break;
104 
105  case Mode_PStop1:
106  SMC_PMCTRL = (uint8_t)((SMC_PMCTRL & ~SMC_PMCTRL_STOPM_MASK) | 0x00); /* Set SMC_PMCTRL: Normal Stop. STOPM=4. Page 221. */
107  SMC_STOPCTRL = (uint8_t)((SMC_STOPCTRL & ~SMC_STOPCTRL_PSTOPO_MASK) | 0x40); /* Set SMC_STOPCTRL: Partial Stop 1. PSTOPO = 1. Page 222. */
108  break;
109 
110  case Mode_PStop2:
111  SMC_PMCTRL = (uint8_t)((SMC_PMCTRL & ~SMC_PMCTRL_STOPM_MASK) | 0x00); /* Set SMC_PMCTRL: Normal Stop. STOPM=4. Page 221. */
112  SMC_STOPCTRL = (uint8_t)((SMC_STOPCTRL & ~SMC_STOPCTRL_PSTOPO_MASK) | 0x80); /* Set SMC_STOPCTRL: Partial Stop 2. PSTOPO = 2. Page 222. */
113  break;
114 
115  case Mode_VLPS:
116  SMC_PMCTRL = (uint8_t)((SMC_PMCTRL & ~SMC_PMCTRL_STOPM_MASK) | 0x02); /* Set SMC_PMCTRL: Very-Low-Power Stop. STOPM=4. Page 221. */
117  break;
118 
119  case Mode_LLS:
120  SMC_PMCTRL = (uint8_t)((SMC_PMCTRL & ~SMC_PMCTRL_STOPM_MASK) | 0x03); /* Set SMC_PMCTRL: Low-Leakage Stop. STOPM=4. Page 221. */
121  break;
122 
123  case Mode_VLLS0:
124  SMC_PMCTRL = (uint8_t)((SMC_PMCTRL & ~SMC_PMCTRL_STOPM_MASK) | 0x04); /* Set SMC_PMCTRL: Very-Low-Leakage Stop. STOPM=4. Page 221. */
125  SMC_STOPCTRL = (uint8_t)((SMC_STOPCTRL & ~SMC_STOPCTRL_VLLSM_MASK) | 0x40); /* Set SMC_STOPCTRL: VLLS0. VLLS = 0. Page 222. */
126  SMC_STOPCTRL = SMC_STOPCTRL_PORPO_MASK; /* Set SMC_STOPCTRL: Disable POR in VLLS0. PSTOPO=0,PORPO=1,VLLSM=0. Page 222. */
127  break;
128 
129  case Mode_VLLS1:
130  SMC_PMCTRL = (uint8_t)((SMC_PMCTRL & ~SMC_PMCTRL_STOPM_MASK) | 0x04); /* Set SMC_PMCTRL: Very-Low-Leakage Stop. STOPM=4. Page 221. */
131  SMC_STOPCTRL = (uint8_t)((SMC_STOPCTRL & ~SMC_STOPCTRL_VLLSM_MASK) | 0x01); /* Set SMC_STOPCTRL: VLLSp. VLLS = 1. Page 222. */
132  break;
133 
134  case Mode_VLLS3:
135  SMC_PMCTRL = (uint8_t)((SMC_PMCTRL & ~SMC_PMCTRL_STOPM_MASK) | 0x04); /* Set SMC_PMCTRL: Very-Low-Leakage Stop. STOPM=4. Page 221. */
136  SMC_STOPCTRL = (uint8_t)((SMC_STOPCTRL & ~SMC_STOPCTRL_VLLSM_MASK) | 0x03); /* Set SMC_STOPCTRL: VLLS3. VLLS = 3. Page 222. */
137  break;
138 
139  default: SMC_PMCTRL = (uint8_t)((SMC_PMCTRL & ~SMC_PMCTRL_STOPM_MASK) | 0x00); /* Default to Normal STOP. */
140  }
141 
142  SCB->SCR &= (uint32_t)~(SCB_SCR_SLEEPONEXIT_MASK); /* Clear Sleep On Exit mask so that CPU does not return to sleep after interrupt. M0 book Page 457. */
143  //SCB_SCR |= (uint32_t)SCB_SCR_SLEEPONEXIT_MASK; /* Set Sleep On Exit mask so that CPU returns to sleep after interrupt. M0 book Page 457. */
144  (void)(SMC_PMCTRL == 0); /* Dummy read of SMC_PMCTRL to ensure the register is written */
145  asm("DSB"); /* DSB instruction to ensure effect of of previous writes. See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0321a/BIHBGGHF.html */
146  asm("WFI"); /* Enter sleep/wait. Page 141 to 143. */
147 }
148 
149 
150 /* Interrupt enable/disable functions. */
151 unsigned long __attribute__((naked))
153 {
154  unsigned long ret;
155 
156  /* Read PRIMASK and enable interrupts */
157  __asm(" mrs r0, PRIMASK\n"
158  " cpsie i\n"
159  " bx lr\n"
160  : "=r" (ret));
161 
162  /* The inline asm returns, we never reach here.
163  * We add a return statement to keep the compiler happy */
164  return ret;
165 }
166 
167 unsigned long __attribute__((naked))
169 {
170  unsigned long ret;
171 
172  /* Read PRIMASK and disable interrupts */
173  __asm(" mrs r0, PRIMASK\n"
174  " cpsid i\n"
175  " bx lr\n"
176  : "=r" (ret));
177 
178  /* The inline asm returns, we never reach here.
179  * We add a return statement to keep the compiler happy */
180  return ret;
181 }
182 
183 void cpu_reboot_src(void) {
184  uint8_t source0, source1;
185  source0 = RCM->SRS0;
186  source1 = RCM->SRS1;
187 
188  if(source0 & (RCM_SRS0_POR_MASK | RCM_SRS0_LVD_MASK)) {
189  printf("Reset due to POR with LVD.\n\r");
190  } else if(source0 & RCM_SRS0_POR_MASK){
191  printf("Reset due to POR.\n\r");
192  } else if(source0 & RCM_SRS0_LVD_MASK){
193  printf("Reset due to LVD.\n\r");
194  } else if(source0 & RCM_SRS0_WDOG_MASK){
195  printf("Reset due to Watchdog.\n\r");
196  } else if(source0 & (RCM_SRS0_PIN_MASK | RCM_SRS0_WAKEUP_MASK)){
197  printf("Reset due to RST Wakeup.\n\r");
198  } else if(source0 & RCM_SRS0_WAKEUP_MASK){
199  printf("Reset due to Wakeup.\n\r");
200  } else if(source0 & RCM_SRS0_PIN_MASK){
201  printf("Reset due to RST.\n\r");
202  } else if(source0 & RCM_SRS0_LOC_MASK){
203  printf("Reset due to LOC.\n\r");
204  } else if(source0 & RCM_SRS0_LOL_MASK){
205  printf("Reset due to LOL.\n\r");
206  } else if(source1 & RCM_SRS1_LOCKUP_MASK){
207  printf("Reset due to LOCKUP.\n\r");
208  } else if(source1 & RCM_SRS1_SW_MASK){
209  printf("Reset due to Software.\n\r");
210  } else if(source1 & RCM_SRS1_MDM_AP_MASK){
211  printf("Reset due to MDM_AP.\n\r");
212  } else if(source1 & RCM_SRS1_SACKERR_MASK){
213  printf("Reset due to SACKERR.\n\r");
214  } else {
215  printf("Unknown reset source.\n\r");
216  }
217 
218 }
219 
220 /*---------------------------------------------------------------------------*/
221 void NMI_Handler(void) /* NMI Interrupt Handler. Required as NMI fires during init and default causes a break. */
222 {
223  printf("NMI Fire");;
224 }
225 
226 /**
227  **===========================================================================
228  ** Default interrupt handlers
229  **===========================================================================
230  */
231 void Default_Handler()
232 {
233  printf("Default Handler - BREAKPOINT");
234  __asm("bkpt");
235 }
236 
237 void Default_Handler_NMI()
238 {
239  printf("NMI Handler - BREAKPOINT");
240  __asm("bkpt");
241 }
242 
243 void Default_Handler_HardFault()
244 {
245  printf("HardFault Handler - BREAKPOINT");
246  __asm("bkpt");
247 }
248 
249 void Default_Handler_SVC()
250 {
251  printf("SVC Handler - BREAKPOINT");
252  __asm("bkpt");
253 }
254 
255 void Default_Handler_PendSV()
256 {
257  printf("PendSV Handler - BREAKPOINT");
258  __asm("bkpt");
259 }
260 
261 void Default_Handler_SysTick()
262 {
263  printf("Systick Handler - BREAKPOINT");
264  __asm("bkpt");
265 }
266 
267 void Default_Handler_DMA0()
268 {
269  printf("DMA0 Handler - BREAKPOINT");
270  __asm("bkpt");
271 }
272 
273 void Default_Handler_DMA1()
274 {
275  printf("DMA1 Handler - BREAKPOINT");
276  __asm("bkpt");
277 }
278 
279 void Default_Handler_DMA2()
280 {
281  printf("DMA2 Handler - BREAKPOINT");
282  __asm("bkpt");
283 }
284 
285 void Default_Handler_DMA3()
286 {
287  printf("DMA3 Handler - BREAKPOINT");
288  __asm("bkpt");
289 }
290 
291 void Default_Handler_MCM()
292 {
293  printf("MCM Handler - BREAKPOINT");
294  __asm("bkpt");
295 }
296 
297 void Default_Handler_FTFL()
298 {
299  printf("FTFL Handler - BREAKPOINT");
300  __asm("bkpt");
301 }
302 
303 void Default_Handler_PMC()
304 {
305  printf("PMC Handler - BREAKPOINT");
306  __asm("bkpt");
307 }
308 
309 void Default_Handler_LLW()
310 {
311  printf("LLW Handler - BREAKPOINT");
312  __asm("bkpt");
313 }
314 
315 void Default_Handler_I2C0()
316 {
317  printf("I2C0 Handler - BREAKPOINT");
318  __asm("bkpt");
319 }
320 
321 void Default_Handler_I2C1()
322 {
323  printf("I2C1 Handler - BREAKPOINT");
324  __asm("bkpt");
325 }
326 
327 void Default_Handler_SPI0()
328 {
329  printf("SPI0 Handler - BREAKPOINT");
330  __asm("bkpt");
331 }
332 
333 void Default_Handler_SPI1()
334 {
335  printf("SPI1 Handler - BREAKPOINT");
336  __asm("bkpt");
337 }
338 
339 void Default_Handler_UART0()
340 {
341  printf("UART0 Handler - BREAKPOINT");
342  __asm("bkpt");
343 }
344 
345 void Default_Handler_UART1()
346 {
347  printf("UART1 Handler - BREAKPOINT");
348  __asm("bkpt");
349 }
350 
351 void Default_Handler_UART2()
352 {
353  printf("UART2 Handler - BREAKPOINT");
354  __asm("bkpt");
355 }
356 
357 void Default_Handler_ADC0()
358 {
359  printf("ADC0 Handler - BREAKPOINT");
360  __asm("bkpt");
361 }
362 
363 void Default_Handler_CMP0()
364 {
365  printf("CMP0 Handler - BREAKPOINT");
366  __asm("bkpt");
367 }
368 
369 void Default_Handler_TPM0()
370 {
371  printf("TPM0 Handler - BREAKPOINT");
372  __asm("bkpt");
373 }
374 
375 void Default_Handler_TPM1()
376 {
377  printf("TPM1 Handler - BREAKPOINT");
378  __asm("bkpt");
379 }
380 
381 void Default_Handler_TPM2()
382 {
383  printf("TPM2 Handler - BREAKPOINT");
384  __asm("bkpt");
385 }
386 
387 void Default_Handler_RTC_Alarm()
388 {
389  printf("RTC Alarm Handler - BREAKPOINT");
390  __asm("bkpt");
391 }
392 
393 void Default_Handler_RTC_Seconds()
394 {
395  printf("RTC Seconds Handler - BREAKPOINT");
396  __asm("bkpt");
397 }
398 
399 void Default_Handler_PIT()
400 {
401  printf("PIT Handler - BREAKPOINT");
402  __asm("bkpt");
403 }
404 
405 void Default_Handler_USBOTG()
406 {
407  printf("USBOTG Handler - BREAKPOINT");
408  __asm("bkpt");
409 }
410 
411 void Default_Handler_DAC0()
412 {
413  printf("DAC0 Handler - BREAKPOINT");
414  __asm("bkpt");
415 }
416 
417 void Default_Handler_TSI0()
418 {
419  printf("TSI0 Handler - BREAKPOINT");
420  __asm("bkpt");
421 }
422 
423 void Default_Handler_MCG()
424 {
425  printf("MCG Handler - BREAKPOINT");
426  __asm("bkpt");
427 }
428 
429 void Default_Handler_LPTimer()
430 {
431  printf("LPTMR Handler - BREAKPOINT");
432  __asm("bkpt");
433 }
434 
435 void Default_Handler_PORTA()
436 {
437  printf("PORTA Handler - BREAKPOINT");
438  __asm("bkpt");
439 }
440 
441 void Default_Handler_PORTD()
442 {
443  printf("PORTD Handler - BREAKPOINT");
444  __asm("bkpt");
445 }
446 
447 /* Weak definitions of handlers point to Default_Handler if not implemented */
448 void HardFault_Handler() __attribute__ ((weak, alias("Default_Handler_HardFault")));
449 void SVC_Handler() __attribute__ ((weak, alias("Default_Handler_SVC")));
450 void PendSV_Handler() __attribute__ ((weak, alias("Default_Handler_PendSV")));
451 void SysTick_Handler() __attribute__ ((weak, alias("Default_Handler_SysTick")));
452 void DMA0_IRQHandler() __attribute__ ((weak, alias("Default_Handler_DMA0")));
453 void DMA1_IRQHandler() __attribute__ ((weak, alias("Default_Handler_DMA1")));
454 void DMA2_IRQHandler() __attribute__ ((weak, alias("Default_Handler_DMA2")));
455 void DMA3_IRQHandler() __attribute__ ((weak, alias("Default_Handler_DMA3")));
456 void LLWU_IRQHandler() __attribute__ ((weak, alias("Default_Handler_LLW")));
457 void I2C0_IRQHandler() __attribute__ ((weak, alias("Default_Handler_I2C0")));
458 void I2C1_IRQHandler() __attribute__ ((weak, alias("Default_Handler_I2C1")));
459 void SPI0_IRQHandler() __attribute__ ((weak, alias("Default_Handler_SPI0")));
460 void SPI1_IRQHandler() __attribute__ ((weak, alias("Default_Handler_SPI1")));
461 void UART0_IRQHandler() __attribute__ ((weak, alias("Default_Handler_UART0")));
462 void UART1_IRQHandler() __attribute__ ((weak, alias("Default_Handler_UART1")));
463 void UART2_IRQHandler() __attribute__ ((weak, alias("Default_Handler_UART2")));
464 void ADC0_IRQHandler() __attribute__ ((weak, alias("Default_Handler_ADC0")));
465 void CMP0_IRQHandler() __attribute__ ((weak, alias("Default_Handler_CMP0")));
466 void TPM0_IRQHandler() __attribute__ ((weak, alias("Default_Handler_TPM0")));
467 void TPM1_IRQHandler() __attribute__ ((weak, alias("Default_Handler_TPM1")));
468 void TPM2_IRQHandler() __attribute__ ((weak, alias("Default_Handler_TPM2")));
469 void RTC_IRQHandler() __attribute__ ((weak, alias("Default_Handler_RTC_Alarm")));
470 void RTC_Seconds_IRQHandler() __attribute__ ((weak, alias("Default_Handler_RTC_Seconds")));
471 void PIT_IRQHandler() __attribute__ ((weak, alias("Default_Handler_PIT")));
472 void USB0_IRQHandler() __attribute__ ((weak, alias("Default_Handler_USBOTG")));
473 void DAC0_IRQHandler() __attribute__ ((weak, alias("Default_Handler_DAC0")));
474 void TSI0_IRQHandler() __attribute__ ((weak, alias("Default_Handler_TSI0")));
475 void MCG_IRQHandler() __attribute__ ((weak, alias("Default_Handler_MCG")));
476 void LPTMR0_IRQHandler() __attribute__ ((weak, alias("Default_Handler_LPTimer")));
477 void PORTA_IRQHandler() __attribute__ ((weak, alias("Default_Handler_PORTA")));
478 void PORTD_IRQHandler() __attribute__ ((weak, alias("Default_Handler_PORTD")));
#define NVIC
Definition: core_cm0.h:496
#define __attribute__(nothing)
Define attribute to nothing since it isn't handled by IAR.
Definition: iar.h:194
#define RCM
Peripheral RCM base pointer.
Definition: MKL25Z4.h:4791
#define SCB
Definition: core_cm0.h:494
unsigned long cpu_cpsid(void)
Disables all CPU interrupts.
Definition: cpu.c:56
unsigned long cpu_cpsie(void)
Enables all CPU interrupts.
Definition: cpu.c:40