rtt-f030/bsp/efm32/hdl_interrupt.c
onelife.real ea6d73f140 *** EFM32 branch ***
1. Upgrade Cortex driver library (CMSIS -> CMSIS & Device): version 2.3.2 -> 3.0.1 & 3.0.0
 - Remove "bsp/efm32/Libraries/CMSIS/Lib/ARM", "bsp/efm32/Libraries/CMSIS/Lib/G++" and "bsp/efm32/Libraries/CMSIS/SVD" to save space
2. Upgrade EFM32 driver libraries (efm32lib -> emlib): version 2.3.2 -> 3.0.0
 - Remove "bsp/efm32/Libraries/Device/EnergyMicro/EFM32LG" and "bsp/efm32/Libraries/Device/EnergyMicro/EFM32TG" to save space
3. Upgrade EFM32GG_DK3750 development kit driver library: version 1.2.2 -> 2.0.1
4. Upgrade EFM32_Gxxx_DK development kit driver library: version 1.7.3 -> 2.0.1
5. Add energy management unit driver and test code
6. Modify linker script and related code to compatible with new version of libraries
7. Change EFM32 branch version number to 1.0
8. Add photo frame demo application

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@2122 bbd45198-f89e-11dd-88c7-29a3b14d5316
2012-05-18 04:40:40 +00:00

878 lines
23 KiB
C

/***************************************************************************//**
* @file hdl_interrupt.c
* @brief Interrupt handler of RT-Thread RTOS for EFM32
* COPYRIGHT (C) 2012, RT-Thread Development Team
* @author onelife
* @version 1.0
*******************************************************************************
* @section License
* The license and distribution terms for this file may be found in the file
* LICENSE in this distribution or at http://www.rt-thread.org/license/LICENSE
*******************************************************************************
* @section Change Logs
* Date Author Notes
* 2010-12-29 onelife Initial creation for EFM32
* 2011-07-12 onelife Disable interrupts in GPIO handler
* 2011-12-09 onelife Add giant gecko support
* 2011-12-09 onelife Add UART module support
* 2011-12-09 onelife Add LEUART module support
* 2011-12-27 onelife Utilize "XXX_PRESENT" and "XXX_COUNT"
******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "board.h"
#include "hdl_interrupt.h"
/***************************************************************************//**
* @addtogroup efm32
* @{
******************************************************************************/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
#ifdef RT_IRQHDL_DEBUG
#define hdl_debug(format,args...) rt_kprintf(format, ##args)
#else
#define hdl_debug(format,args...)
#endif
/* Private variables ---------------------------------------------------------*/
efm32_irq_hook_t dmaCbTable[DMA_CHAN_COUNT * 2] = {RT_NULL};
efm32_irq_hook_t timerCbTable[TIMER_COUNT] = {RT_NULL};
#if defined(LETIMER_PRESENT)
efm32_irq_hook_t letimerCbTable[LETIMER_COUNT] = {RT_NULL};
#endif
efm32_irq_hook_t rtcCbTable[RTC_COUNT] = {RT_NULL};
efm32_irq_hook_t gpioCbTable[16] = {RT_NULL};
efm32_irq_hook_t acmpCbTable[ACMP_COUNT] = {RT_NULL};
#if defined(USART_PRESENT)
#if defined(UART_PRESENT)
efm32_irq_hook_t usartCbTable[USART_COUNT * 2 + UART_COUNT * 2] = {RT_NULL};
#else
efm32_irq_hook_t usartCbTable[USART_COUNT * 2] = {RT_NULL};
#endif
#endif
#if defined(LEUART_PRESENT)
efm32_irq_hook_t leuartCbTable[LEUART_COUNT] = {RT_NULL};
#endif
#if defined(I2C_PRESENT)
efm32_irq_hook_t iicCbTable[I2C_COUNT] = {RT_NULL};
#endif
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/***************************************************************************//**
* @brief
* NMI exception handler
*
* @details
*
* @note
******************************************************************************/
void NMI_Handler(void)
{
hdl_debug("[NMI_Handler: NOP]\n");
}
/***************************************************************************//**
* @brief
* Memory manage exception handler
*
* @details
*
* @note
******************************************************************************/
void MemManage_Handler(void)
{
hdl_debug("[MemManage_Handler: infinite loop]\n");
while (1);
}
/***************************************************************************//**
* @brief
* Bus fault exception handler
*
* @details
*
* @note
******************************************************************************/
void BusFault_Handler(void)
{
hdl_debug("[BusFault_Handler: infinite loop]\n");
while (1);
}
/***************************************************************************//**
* @brief
* Usage fault exception handler
*
* @details
*
* @note
******************************************************************************/
void UsageFault_Handler(void)
{
hdl_debug("[UsageFault_Handler: infinite loop]\n");
while (1);
}
/***************************************************************************//**
* @brief
* Supervisor call exception handler
*
* @details
*
* @note
******************************************************************************/
void SVC_Handler(void)
{
hdl_debug("[SVC_Handler: NOP]\n");
}
/***************************************************************************//**
* @brief
* Debug monitor exception handler
*
* @details
*
* @note
******************************************************************************/
void DebugMon_Handler(void)
{
hdl_debug("[DebugMon_Handler: NOP]\n");
}
/***************************************************************************//**
* @brief
* System tick timer interrupt handler
*
* @details
*
* @note
*
******************************************************************************/
void SysTick_Handler(void)
{
/* enter interrupt */
rt_interrupt_enter();
rt_tick_increase();
/* leave interrupt */
rt_interrupt_leave();
}
/*******************************************************************************
* STM32F10x Peripherals Interrupt Handlers
* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the
* available peripheral interrupt handler's name please refer to the startup
* file (startup_stm32f10x_xx.s).
/******************************************************************************/
/***************************************************************************//**
* @brief
* Common DMA interrupt handler
*
* @details
*
* @note
*
******************************************************************************/
void DMA_IRQHandler_All(rt_uint32_t channel, rt_bool_t primary, void *user)
{
/* enter interrupt */
rt_interrupt_enter();
/* invoke callback function */
if (dmaCbTable[channel].cbFunc != RT_NULL)
{
(dmaCbTable[channel].cbFunc)(dmaCbTable[channel].userPtr);
}
/* leave interrupt */
rt_interrupt_leave();
}
/***************************************************************************//**
* @brief
* Common Timer0 interrupt handler
*
* @details
* This function handles Timer0 counter overflow interrupt request
*
* @note
*
******************************************************************************/
void TIMER0_IRQHandler(void)
{
if (TIMER0->IF & TIMER_IF_OF)
{
/* invoke callback function */
if (timerCbTable[0].cbFunc != RT_NULL)
{
(timerCbTable[0].cbFunc)(timerCbTable[0].userPtr);
}
/* clear interrupt */
BITBAND_Peripheral(&(TIMER0->IFC), _TIMER_IF_OF_SHIFT, 0x1UL);
}
}
/***************************************************************************//**
* @brief
* Common Timer1 interrupt handler
*
* @details
* This function handles Timer1 counter overflow interrupt request
*
* @note
*
******************************************************************************/
void TIMER1_IRQHandler(void)
{
if (TIMER1->IF & TIMER_IF_OF)
{
/* invoke callback function */
if (timerCbTable[1].cbFunc != RT_NULL)
{
(timerCbTable[1].cbFunc)(timerCbTable[1].userPtr);
}
/* clear interrupt */
BITBAND_Peripheral(&(TIMER1->IFC), _TIMER_IF_OF_SHIFT, 0x1UL);
}
}
/***************************************************************************//**
* @brief
* Common Timer2 interrupt handler
*
* @details
* This function handles Timer2 counter overflow interrupt request
*
* @note
*
******************************************************************************/
void TIMER2_IRQHandler(void)
{
if (TIMER2->IF & TIMER_IF_OF)
{
/* invoke callback function */
if (timerCbTable[2].cbFunc != RT_NULL)
{
(timerCbTable[2].cbFunc)(timerCbTable[2].userPtr);
}
/* clear interrupt */
BITBAND_Peripheral(&(TIMER2->IFC), _TIMER_IF_OF_SHIFT, 0x1UL);
}
}
#if defined(LETIMER_PRESENT)
/***************************************************************************//**
* @brief
* Common Low Energy Timer0 interrupt handler
*
* @details
* This function handles Timer0 counter overflow interrupt request
*
* @note
*
******************************************************************************/
void LETIMER0_IRQHandler(void)
{
if (LETIMER0->IF & LETIMER_IF_UF)
{
/* enter interrupt */
rt_interrupt_enter();
rt_tick_increase();
/* leave interrupt */
rt_interrupt_leave();
/* invoke callback function */
/* if (letimerCbTable[0].cbFunc != RT_NULL)
{
(letimerCbTable[0].cbFunc)(letimerCbTable[0].userPtr);
}
*/
/* clear interrupt */
BITBAND_Peripheral(&(LETIMER0->IFC), _LETIMER_IF_UF_SHIFT, 0x1UL);
}
}
#endif
/***************************************************************************//**
* @brief
* Common RTC interrupt handler
*
* @details
* This function handles RTC counter overflow interrupt request
*
* @note
*
******************************************************************************/
void RTC_IRQHandler(void)
{
/* enter interrupt */
rt_interrupt_enter();
if (RTC->IF & RTC_IF_OF)
{
/* invoke callback function */
if (rtcCbTable[0].cbFunc != RT_NULL)
{
(rtcCbTable[0].cbFunc)(rtcCbTable[0].userPtr);
}
}
/* leave interrupt */
rt_interrupt_leave();
}
/***************************************************************************//**
* @brief
* Common even number GPIO interrupt handler
*
* @details
*
* @note
*
******************************************************************************/
void GPIO_EVEN_IRQHandler(void)
{
rt_uint16_t flag, n;
rt_base_t level;
/* Disable interrupt */
level = rt_hw_interrupt_disable();
/* Enter ISR */
rt_interrupt_enter();
/* invoke callback function */
flag = (rt_uint16_t)(GPIO->IF & 0xFFFF);
for ( n = 0; flag > 0; flag = flag >> 2, n = n + 2)
{
if ((flag & 0x0001) && (gpioCbTable[n].cbFunc != RT_NULL))
{
(gpioCbTable[n].cbFunc)(gpioCbTable[n].userPtr);
}
}
/* clear interrupt */
GPIO->IFC = 0x5555UL;
/* Leave ISR */
rt_interrupt_leave();
/* Enable interrupt */
rt_hw_interrupt_enable(level);
}
/***************************************************************************//**
* @brief
* Common odd number GPIO interrupt handler
*
* @details
*
* @note
*
******************************************************************************/
void GPIO_ODD_IRQHandler(void)
{
rt_uint16_t flag, n;
rt_base_t level;
/* Disable interrupt */
level = rt_hw_interrupt_disable();
/* Enter ISR */
rt_interrupt_enter();
/* invoke callback function */
flag = (rt_uint16_t)(GPIO->IF & 0xFFFF) >> 1;
for ( n = 1; flag > 0; flag = flag >> 2, n = n + 2)
{
if ((flag & 0x0001) && (gpioCbTable[n].cbFunc != RT_NULL))
{
(gpioCbTable[n].cbFunc)(gpioCbTable[n].userPtr);
}
}
/* clear interrupt */
GPIO->IFC = 0xAAAAUL;
/* Leave ISR */
rt_interrupt_leave();
/* Enable interrupt */
rt_hw_interrupt_enable(level);
}
/***************************************************************************//**
* @brief
* Common ACMP interrupt handler
*
* @details
* This function handles ACMP edge trigger interrupt request
*
* @note
*
******************************************************************************/
void ACMP0_IRQHandler(void)
{
/* enter interrupt */
rt_interrupt_enter();
if (ACMP0->IF & ACMP_IF_EDGE)
{
/* invoke callback function */
if (acmpCbTable[0].cbFunc != RT_NULL)
{
(acmpCbTable[0].cbFunc)(acmpCbTable[0].userPtr);
}
/* clear interrupt */
BITBAND_Peripheral(&(ACMP0->IFC), _ACMP_IF_EDGE_SHIFT, 0x1UL);
}
if (ACMP1->IF & ACMP_IF_EDGE)
{
/* invoke callback function */
if (acmpCbTable[1].cbFunc != RT_NULL)
{
(acmpCbTable[1].cbFunc)(acmpCbTable[1].userPtr);
}
/* clear interrupt */
BITBAND_Peripheral(&(ACMP1->IFC), _ACMP_IF_EDGE_SHIFT, 0x1UL);
}
/* leave interrupt */
rt_interrupt_leave();
}
#if defined(USART_PRESENT)
/***************************************************************************//**
* @brief
* Common USART0 TX interrupt handler
*
* @details
* This function handles USART0 TX complete interrupt request
*
* @note
*
******************************************************************************/
void USART0_TX_IRQHandler(void)
{
/* enter interrupt */
rt_interrupt_enter();
if (USART0->IF & USART_IF_TXC)
{
/* invoke callback function */
if (usartCbTable[0].cbFunc != RT_NULL)
{
(usartCbTable[0].cbFunc)(usartCbTable[0].userPtr);
}
/* clear interrupt */
BITBAND_Peripheral(&(USART0->IFC), _USART_IF_TXC_SHIFT, 0x1UL);
}
/* leave interrupt */
rt_interrupt_leave();
}
/***************************************************************************//**
* @brief
* Common USART0 RX interrupt handler
*
* @details
* This function handles USART0 RX data valid interrupt request
*
* @note
*
******************************************************************************/
void USART0_RX_IRQHandler(void)
{
if (USART0->IF & USART_IF_RXDATAV)
{
/* invoke callback function */
if (usartCbTable[1].cbFunc != RT_NULL)
{
(usartCbTable[1].cbFunc)(usartCbTable[1].userPtr);
}
}
}
#endif
#if (defined(USART_PRESENT) && (USART_COUNT > 1))
/***************************************************************************//**
* @brief
* Common USART1 TX interrupt handler
*
* @details
* This function handles USART1 TX complete interrupt request
*
* @note
*
******************************************************************************/
void USART1_TX_IRQHandler(void)
{
/* enter interrupt */
rt_interrupt_enter();
if (USART1->IF & USART_IF_TXC)
{
/* invoke callback function */
if (usartCbTable[2].cbFunc != RT_NULL)
{
(usartCbTable[2].cbFunc)(usartCbTable[2].userPtr);
}
/* clear interrupt */
BITBAND_Peripheral(&(USART1->IFC), _USART_IF_TXC_SHIFT, 0x1UL);
}
/* leave interrupt */
rt_interrupt_leave();
}
/***************************************************************************//**
* @brief
* Common USART1 RX interrupt handler
*
* @details
* This function handles USART1 RX data valid interrupt request
*
* @note
*
******************************************************************************/
void USART1_RX_IRQHandler(void)
{
if (USART1->IF & USART_IF_RXDATAV)
{
/* invoke callback function */
if (usartCbTable[3].cbFunc != RT_NULL)
{
(usartCbTable[3].cbFunc)(usartCbTable[3].userPtr);
}
}
}
#endif
#if (defined(USART_PRESENT) && (USART_COUNT > 2))
/***************************************************************************//**
* @brief
* Common USART2 TX interrupt handler
*
* @details
* This function handles USART2 TX complete interrupt request
*
* @note
*
******************************************************************************/
void USART2_TX_IRQHandler(void)
{
/* enter interrupt */
rt_interrupt_enter();
if (USART2->IF & USART_IF_TXC)
{
/* invoke callback function */
if (usartCbTable[4].cbFunc != RT_NULL)
{
(usartCbTable[4].cbFunc)(usartCbTable[4].userPtr);
}
/* clear interrupt */
BITBAND_Peripheral(&(USART2->IFC), _USART_IF_TXC_SHIFT, 0x1UL);
}
/* leave interrupt */
rt_interrupt_leave();
}
/***************************************************************************//**
* @brief
* Common USART2 RX interrupt handler
*
* @details
* This function handles USART2 RX data valid interrupt request
*
* @note
*
******************************************************************************/
void USART2_RX_IRQHandler(void)
{
if (USART2->IF & USART_IF_RXDATAV)
{
/* invoke callback function */
if (usartCbTable[5].cbFunc != RT_NULL)
{
(usartCbTable[5].cbFunc)(usartCbTable[5].userPtr);
}
}
}
#endif
#if defined(UART_PRESENT)
/***************************************************************************//**
* @brief
* Common UART0 TX interrupt handler
*
* @details
* This function handles UART0 TX complete interrupt request
*
* @note
*
******************************************************************************/
void UART0_TX_IRQHandler(void)
{
/* enter interrupt */
rt_interrupt_enter();
if (UART0->IF & UART_IF_TXC)
{
/* invoke callback function */
if (usartCbTable[USART_COUNT * 2].cbFunc != RT_NULL)
{
(usartCbTable[USART_COUNT * 2].cbFunc)(usartCbTable[USART_COUNT * 2].userPtr);
}
/* clear interrupt */
BITBAND_Peripheral(&(UART0->IFC), _UART_IF_TXC_SHIFT, 0x1UL);
}
/* leave interrupt */
rt_interrupt_leave();
}
/***************************************************************************//**
* @brief
* Common UART0 RX interrupt handler
*
* @details
* This function handles UART0 RX data valid interrupt request
*
* @note
*
******************************************************************************/
void UART0_RX_IRQHandler(void)
{
if (UART0->IF & UART_IF_RXDATAV)
{
/* invoke callback function */
if (usartCbTable[USART_COUNT * 2 + 1].cbFunc != RT_NULL)
{
(usartCbTable[USART_COUNT * 2 + 1].cbFunc)(usartCbTable[USART_COUNT * 2 + 1].userPtr);
}
}
}
#endif
#if (defined(UART_PRESENT) && (UART_COUNT > 1))
/***************************************************************************//**
* @brief
* Common UART1 TX interrupt handler
*
* @details
* This function handles UART1 TX complete interrupt request
*
* @note
*
******************************************************************************/
void UART1_TX_IRQHandler(void)
{
/* enter interrupt */
rt_interrupt_enter();
if (UART1->IF & UART_IF_TXC)
{
/* invoke callback function */
if (usartCbTable[USART_COUNT * 2 + 2].cbFunc != RT_NULL)
{
(usartCbTable[USART_COUNT * 2 + 2].cbFunc)(usartCbTable[USART_COUNT * 2 + 2].userPtr);
}
/* clear interrupt */
BITBAND_Peripheral(&(UART1->IFC), _UART_IF_TXC_SHIFT, 0x1UL);
}
/* leave interrupt */
rt_interrupt_leave();
}
/***************************************************************************//**
* @brief
* Common UART1 RX interrupt handler
*
* @details
* This function handles UART1 RX data valid interrupt request
*
* @note
*
******************************************************************************/
void UART1_RX_IRQHandler(void)
{
if (UART1->IF & UART_IF_RXDATAV)
{
/* invoke callback function */
if (usartCbTable[USART_COUNT * 2 + 3].cbFunc != RT_NULL)
{
(usartCbTable[USART_COUNT * 2 + 3].cbFunc)(usartCbTable[USART_COUNT * 2 + 3].userPtr);
}
}
}
#endif
#if defined(LEUART_PRESENT)
/***************************************************************************//**
* @brief
* Common LEUART0 interrupt handler
*
* @details
* This function handles LEUART0 interrupt request
*
* @note
*
******************************************************************************/
void LEUART0_IRQHandler(void)
{
if (LEUART0->IF & LEUART_IF_RXDATAV)
{
/* invoke callback function */
if (leuartCbTable[0].cbFunc != RT_NULL)
{
(leuartCbTable[0].cbFunc)(leuartCbTable[0].userPtr);
}
}
}
#endif
#if (defined(LEUART_PRESENT) && (LEUART_COUNT > 1))
/***************************************************************************//**
* @brief
* Common LEUART1 interrupt handler
*
* @details
* This function handles LEUART1 interrupt request
*
* @note
*
******************************************************************************/
void LEUART1_IRQHandler(void)
{
if (LEUART1->IF & LEUART_IF_RXDATAV)
{
/* invoke callback function */
if (leuartCbTable[1].cbFunc != RT_NULL)
{
(leuartCbTable[1].cbFunc)(leuartCbTable[1].userPtr);
}
}
}
#endif
#if defined(I2C_PRESENT)
/***************************************************************************//**
* @brief
* Common IIC0 interrupt handler
*
* @details
* This function handles IIC0 slave mode interrupt requests
*
* @note
*
******************************************************************************/
void I2C0_IRQHandler(void)
{
if ((I2C0->IF & I2C_IF_ADDR) || \
(I2C0->IF & I2C_IF_RXDATAV) || \
(I2C0->IF & I2C_IF_SSTOP))
{
/* invoke callback function */
if (iicCbTable[0].cbFunc != RT_NULL)
{
(iicCbTable[0].cbFunc)(iicCbTable[0].userPtr);
}
}
I2C_IntClear(I2C0, I2C_IFC_ADDR | I2C_IFC_SSTOP);
}
#endif
/***************************************************************************//**
* @brief
* EFM32 common interrupt handlers register function
*
* @details
*
* @note
*
******************************************************************************/
void efm32_irq_hook_register(efm32_irq_hook_init_t *hook)
{
switch (hook->type)
{
case efm32_irq_type_dma:
dmaCbTable[hook->unit].cbFunc = hook->cbFunc;
dmaCbTable[hook->unit].userPtr = hook->userPtr;
break;
case efm32_irq_type_rtc:
rtcCbTable[hook->unit].cbFunc = hook->cbFunc;
rtcCbTable[hook->unit].userPtr = hook->userPtr;
break;
case efm32_irq_type_timer:
timerCbTable[hook->unit].cbFunc = hook->cbFunc;
timerCbTable[hook->unit].userPtr = hook->userPtr;
break;
case efm32_irq_type_letimer:
letimerCbTable[hook->unit].cbFunc = hook->cbFunc;
letimerCbTable[hook->unit].userPtr = hook->userPtr;
break;
case efm32_irq_type_gpio:
gpioCbTable[hook->unit].cbFunc = hook->cbFunc;
gpioCbTable[hook->unit].userPtr = hook->userPtr;
break;
case efm32_irq_type_acmp:
acmpCbTable[hook->unit].cbFunc = hook->cbFunc;
acmpCbTable[hook->unit].userPtr = hook->userPtr;
break;
#if defined(USART_PRESENT)
case efm32_irq_type_usart:
usartCbTable[hook->unit].cbFunc = hook->cbFunc;
usartCbTable[hook->unit].userPtr = hook->userPtr;
break;
#endif
#if defined(LEUART_PRESENT)
case efm32_irq_type_leuart:
leuartCbTable[hook->unit].cbFunc = hook->cbFunc;
leuartCbTable[hook->unit].userPtr = hook->userPtr;
break;
#endif
#if defined(I2C_PRESENT)
case efm32_irq_type_iic:
iicCbTable[hook->unit].cbFunc = hook->cbFunc;
iicCbTable[hook->unit].userPtr = hook->userPtr;
break;
#endif
default:
break;
}
hdl_debug("Hook Registered: type: %s, unit: %x, cbFunc: %x, userPtr: %x\n", \
hook->type, hook->unit, hook->cbFunc, hook->userPtr);
}
/***************************************************************************//**
* @}
******************************************************************************/