/* * File : interrupt.c * This file is part of RT-Thread RTOS * COPYRIGHT (C) 2006 - 2013, RT-Thread Development Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Change Logs: * Date Author Notes * 2013-7-14 Peng Fan sep6200 implementation */ #include <rtthread.h> #include <rthw.h> #include <sep6200.h> #define MAX_HANDLERS 64 #define SEP6200_IRQ_TYPE 0 #define SEP6200_FIQ_TYPE 1 #define int_enable_all() \ do { \ *(volatile unsigned long*)SEP6200_VIC_INT_EN_L = ~0x0;\ *(volatile unsigned long*)SEP6200_VIC_INT_EN_H = ~0x0;\ }while(0) #define int_disable_all() \ do { \ *(volatile unsigned long*)SEP6200_VIC_INT_EN_L = 0x0;\ *(volatile unsigned long*)SEP6200_VIC_INT_EN_H = 0x0;\ }while(0) #define mask_all_int(int_type) \ do { \ if (int_type == SEP6200_IRQ_TYPE){ \ *(volatile unsigned long*)SEP6200_VIC_INT_MSK_ALL = 0x1;\ } else if (int_type == SEP6200_FIQ_TYPE) {\ *(volatile unsigned long*)SEP6200_VIC_INT_MSK_ALL = 0x2;\ }\ }while(0) #define unmask_all_int(int_type)\ do { \ if (int_type == SEP6200_IRQ_TYPE){ \ *(volatile unsigned long*)SEP6200_VIC_INT_MSK_ALL = ~0x1;\ } else if (int_type == SEP6200_FIQ_TYPE) {\ *(volatile unsigned long*)SEP6200_VIC_INT_MSK_ALL = ~0x2;\ }\ }while(0) #define SEP6200_INT_SET(intnum) \ do{ \ if(intnum < 32) \ *(volatile unsigned long*)SEP6200_VIC_SFT_INT_L |= (1 << intnum); \ else \ *(volatile unsigned long*)SEP6200_VIC_SFT_INT_H |= (1 << (intnum - 32)); \ }while(0) #define SEP6200_INT_CLR(intnum) \ do{ \ if(intnum < 32) \ *(volatile unsigned long*)SEP6200_VIC_SFT_INT_L &= ~(1 << intnum);\ else \ *(volatile unsigned long*)SEP6200_VIC_SFT_INT_H &= ~(1 << (intnum - 32)); \ }while(0) #define SEP6200_INT_ENABLE(intnum)\ do{ \ if(intnum < 32) \ *(volatile unsigned long*)SEP6200_VIC_INT_EN_L |= (1 << intnum); \ else \ *(volatile unsigned long*)SEP6200_VIC_INT_EN_H |= (1 << (intnum - 32)); \ }while(0) #define SEP6200_INT_DISABLE(intnum) \ do{ \ if(intnum < 32) \ *(volatile unsigned long*)SEP6200_VIC_INT_EN_L &= ~(1 << intnum); \ else \ *(volatile unsigned long*)SEP6200_VIC_INT_EN_H &= ~(1 << (intnum - 32)); \ }while(0) extern rt_uint32_t rt_interrupt_nest; /* exception and interrupt handler table */ struct rt_irq_desc isr_table[MAX_HANDLERS]; rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread; rt_uint32_t rt_thread_switch_interrupt_flag; /* -------------------------------------------------------------------- * Interrupt initialization * -------------------------------------------------------------------- */ /** * @addtogroup sep6200 */ /*@{*/ void rt_hw_interrupt_mask(int irq); void rt_hw_interrupt_umask(int irq); rt_inline void sep6200_irq_enable(rt_uint32_t irq) { SEP6200_INT_ENABLE(irq); } rt_inline void sep6200_irq_disable(rt_uint32_t irq) { SEP6200_INT_DISABLE(irq); } rt_inline void sep6200_irq_unmask(rt_uint32_t irq) { SEP6200_INT_ENABLE(irq); } rt_inline void sep6200_irq_mask(rt_uint32_t irq) { SEP6200_INT_DISABLE(irq); } rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t vector) { rt_kprintf("Unhandled interrupt %d occured!!!\n", vector); return RT_NULL; } /** * This function will initialize hardware interrupt */ void rt_hw_interrupt_init(void) { rt_int32_t i; register rt_uint32_t idx; /* init exceptions table */ for(idx=0; idx < MAX_HANDLERS; idx++) { isr_table[idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle; } int_disable_all(); mask_all_int(SEP6200_FIQ_TYPE); //int_enable_all(); unmask_all_int(SEP6200_IRQ_TYPE); /* init interrupt nest, and context in thread sp */ rt_interrupt_nest = 0; rt_interrupt_from_thread = 0; rt_interrupt_to_thread = 0; rt_thread_switch_interrupt_flag = 0; } /** * This function will mask a interrupt. * @param vector the interrupt number */ void rt_hw_interrupt_mask(int irq) { if (irq >= MAX_HANDLERS) { rt_kprintf("Wrong irq num to mask\n"); } else { sep6200_irq_mask(irq); } } /** * This function will un-mask a interrupt. * @param vector the interrupt number */ void rt_hw_interrupt_umask(int irq) { if (irq >= MAX_HANDLERS) { rt_kprintf("Wrong irq num to unmask\n"); } else { sep6200_irq_unmask(irq); } } /** * This function will install a interrupt service routine to a interrupt. * @param vector the interrupt number * @param new_handler the interrupt service routine to be installed * @param old_handler the old interrupt service routine */ rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, void *param, char *name) { rt_isr_handler_t old_handler = RT_NULL; if(vector < MAX_HANDLERS) { old_handler = isr_table[vector].handler; if (handler != RT_NULL) { #ifdef RT_USING_INTERRUPT_INFO rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX); #endif /* RT_USING_INTERRUPT_INFO */ isr_table[vector].handler = handler; isr_table[vector].param = param; } } return old_handler; } /*@}*/