blob: cda27557277338e865a0948420a75ea62208246d [file] [log] [blame]
/*
* 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) );
}
/***********************************************************************/