/*****************************************************************************
 * 
 * Freescale Semiconductor Inc.
 * (c) Copyright 2004-2012 Freescale Semiconductor, Inc.
 * 
 * ALL RIGHTS RESERVED
 * 
 * ***************************************************************************
 * 
 * @file	nvic.c
 * 
 * @author	
 * 
 * @version	1.0.0
 * 
 * @date	May-31-2012
 * 
 * @brief	C source file for NVIC functions
 * 
 ******************************************************************************/

/******************************************************************************
*                               Header files
******************************************************************************/
#include "nvic.h"
#include "derivative.h"

/******************************************************************************
*                                 Functions
******************************************************************************/

/***********************************************************************/
/*
 * 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)
 * 
 * Return:
 * unsigned char: Error status (NVIC_OK or NVIC_ERR)
 */
unsigned char u8NvicEnableIrq(int irq)
{
    int div;
    
    /* Make sure that the IRQ is an allowable number. Right now up to 91 is 
     * used.
     */
    if(irq > 91)
      return NVIC_ERR;
    
    /* 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;
    }            
    return NVIC_OK;
}
/***********************************************************************/
/*
 * 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)
 * 
 * Return:
 * unsigned char: Error status (NVIC_OK or NVIC_ERR)
 */

unsigned char u8NvicDisableIrq(int irq)
{
    int div;
    
    /* Make sure that the IRQ is an allowable number. Right now up to 91 is 
     * used.
     */
    if (irq > 91)
      return NVIC_ERR;
    
    /* 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;
    }      
    return NVIC_OK;
}
/***********************************************************************/
/*
 * 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
 * 
 * Return:
 * unsigned char: Error status (NVIC_OK or NVIC_ERR)
 */

unsigned char u8NvicSetIrqPriority (int irq, int prio)
{
    /*irq priority pointer*/
    unsigned char *prio_reg;
    
    /* Make sure that the IRQ is an allowable number. Right now up to 91 is 
     * used.
     */
    if (irq > 91)
      return NVIC_ERR;

    if (prio > 15)
       for(;;)
      {
        //Invalid priority value passed to priority irq function!
      }
      
    /* Determine which of the NVICIPx corresponds to the irq */
    prio_reg = (unsigned char *)(((unsigned int)&NVICIP0) + irq);
    /* Assign priority to IRQ */
    *prio_reg = ( (prio&0xF) << 0x04u );   
    
    return NVIC_OK;
}

/* End of file */
