/* | |
* File: arm_cm4.c | |
* Purpose: Generic high-level routines for ARM Cortex M4 processors | |
* | |
* Notes: | |
*/ | |
#include "common.h" | |
/***********************************************************************/ | |
/* | |
* Configures the ARM system control register for STOP (deep sleep) mode | |
* and then executes the WFI instruction to enter the mode. | |
* | |
* Parameters: | |
* none | |
* | |
* Note: Might want to change this later to allow for passing in a parameter | |
* to optionally set the sleep on exit bit. | |
*/ | |
void stop (void) | |
{ | |
/* Set the SLEEPDEEP bit to enable deep sleep mode (STOP) */ | |
SCB_SCR |= SCB_SCR_SLEEPDEEP_MASK; | |
/* WFI instruction will start entry into STOP mode */ | |
asm("WFI"); | |
} | |
/***********************************************************************/ | |
/* | |
* Configures the ARM system control register for WAIT (sleep) mode | |
* and then executes the WFI instruction to enter the mode. | |
* | |
* Parameters: | |
* none | |
* | |
* Note: Might want to change this later to allow for passing in a parameter | |
* to optionally set the sleep on exit bit. | |
*/ | |
void wait (void) | |
{ | |
/* Clear the SLEEPDEEP bit to make sure we go into WAIT (sleep) mode instead | |
* of deep sleep. | |
*/ | |
SCB_SCR &= ~SCB_SCR_SLEEPDEEP_MASK; | |
/* WFI instruction will start entry into WAIT mode */ | |
asm("WFI"); | |
} | |
/***********************************************************************/ | |
/* | |
* Change the value of the vector table offset register to the specified value. | |
* | |
* Parameters: | |
* vtor new value to write to the VTOR | |
*/ | |
void write_vtor (int vtor) | |
{ | |
/* Write the VTOR with the new value */ | |
SCB_VTOR = vtor; | |
} | |
/***********************************************************************/ | |
/* | |
* Initialize the NVIC to enable the specified IRQ. | |
* | |
* NOTE: The function only initializes the NVIC to enable a single IRQ. | |
* Interrupts will also need to be enabled in the ARM core. This can be | |
* done using the EnableInterrupts macro. | |
* | |
* Parameters: | |
* irq irq number to be enabled (the irq number NOT the vector number) | |
*/ | |
void enable_irq (int irq) | |
{ | |
int div; | |
/* Determine which of the NVICISERs corresponds to the irq */ | |
div = irq/32; | |
switch (div) | |
{ | |
case 0x0: | |
NVICICPR0 = 1 << (irq%32); | |
NVICISER0 = 1 << (irq%32); | |
break; | |
case 0x1: | |
NVICICPR1 = 1 << (irq%32); | |
NVICISER1 = 1 << (irq%32); | |
break; | |
case 0x2: | |
NVICICPR2 = 1 << (irq%32); | |
NVICISER2 = 1 << (irq%32); | |
break; | |
} | |
} | |
/***********************************************************************/ | |
/* | |
* Initialize the NVIC to disable the specified IRQ. | |
* | |
* NOTE: The function only initializes the NVIC to disable a single IRQ. | |
* If you want to disable all interrupts, then use the DisableInterrupts | |
* macro instead. | |
* | |
* Parameters: | |
* irq irq number to be disabled (the irq number NOT the vector number) | |
*/ | |
void disable_irq (int irq) | |
{ | |
int div; | |
/* Determine which of the NVICICERs corresponds to the irq */ | |
div = irq/32; | |
switch (div) | |
{ | |
case 0x0: | |
NVICICER0 = 1 << (irq%32); | |
break; | |
case 0x1: | |
NVICICER1 = 1 << (irq%32); | |
break; | |
case 0x2: | |
NVICICER2 = 1 << (irq%32); | |
break; | |
} | |
} | |
/***********************************************************************/ | |
/* | |
* Initialize the NVIC to set specified IRQ priority. | |
* | |
* NOTE: The function only initializes the NVIC to set a single IRQ priority. | |
* Interrupts will also need to be enabled in the ARM core. This can be | |
* done using the EnableInterrupts macro. | |
* | |
* Parameters: | |
* irq irq number to be enabled (the irq number NOT the vector number) | |
* prio irq priority. 0-15 levels. 0 max priority | |
*/ | |
void set_irq_priority (int irq, int prio) | |
{ | |
/*irq priority pointer*/ | |
uint8 *prio_reg; | |
/* Determine which of the NVICIPx corresponds to the irq */ | |
prio_reg = (uint8 *)(((uint32)&NVICIP0) + irq); | |
/* Assign priority to IRQ */ | |
*prio_reg = ( (prio&0xF) << (8 - ARM_INTERRUPT_LEVEL_BITS) ); | |
} | |
/***********************************************************************/ | |