1 /* 2 * COPYRIGHT (C) 2013-2014, Shanghai Real-Thread Technology Co., Ltd 3 * 4 * All rights reserved. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License along 17 * with this program; if not, write to the Free Software Foundation, Inc., 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 */ 20 21 #include <rthw.h> 22 #include <rtthread.h> 23 #include "zynq7000.h" 24 #include "cp15.h" 25 #include "gic.h" 26 27 #define MAX_HANDLERS IRQ_Zynq7000_MAXNR 28 29 extern volatile rt_uint8_t rt_interrupt_nest; 30 31 /* exception and interrupt handler table */ 32 struct rt_irq_desc isr_table[MAX_HANDLERS]; 33 rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread; 34 rt_uint32_t rt_thread_switch_interrupt_flag; 35 36 static void rt_hw_interrupt_handle(int vector, void *param) 37 { 38 rt_kprintf("Unhandled interrupt %d occured!!!\n", vector); 39 } 40 41 const unsigned int VECTOR_BASE = 0x00; 42 extern int system_vectors; 43 44 static void rt_hw_vector_init(void) 45 { 46 int sctrl; 47 unsigned int *src = (unsigned int *)&system_vectors; 48 49 /* C12-C0 is only active when SCTLR.V = 0 */ 50 asm volatile ("mrc p15, #0, %0, c1, c0, #0" 51 :"=r" (sctrl)); 52 sctrl &= ~(1 << 13); 53 asm volatile ("mcr p15, #0, %0, c1, c0, #0" 54 : 55 :"r" (sctrl)); 56 57 asm volatile ("mcr p15, #0, %0, c12, c0, #0" 58 : 59 :"r" (src)); 60 } 61 62 /** 63 * This function will initialize hardware interrupt 64 */ 65 void rt_hw_interrupt_init(void) 66 { 67 register rt_uint32_t idx; 68 69 /* set vector table */ 70 rt_hw_vector_init(); 71 72 /* init exceptions table */ 73 rt_memset(isr_table, 0x00, sizeof(isr_table)); 74 for (idx = 0; idx < MAX_HANDLERS; idx++) 75 { 76 isr_table[idx].handler = rt_hw_interrupt_handle; 77 } 78 79 /* initialize ARM GIC */ 80 arm_gic_dist_init(0, Zynq7000_GIC_DIST_BASE, 0); 81 arm_gic_cpu_init(0, Zynq7000_GIC_CPU_BASE); 82 83 /* init interrupt nest, and context in thread sp */ 84 rt_interrupt_nest = 0; 85 rt_interrupt_from_thread = 0; 86 rt_interrupt_to_thread = 0; 87 rt_thread_switch_interrupt_flag = 0; 88 } 89 90 /** 91 * This function will mask a interrupt. 92 * @param vector the interrupt number 93 */ 94 void rt_hw_interrupt_mask(int vector) 95 { 96 arm_gic_mask(0, vector); 97 } 98 99 /** 100 * This function will un-mask a interrupt. 101 * @param vector the interrupt number 102 */ 103 void rt_hw_interrupt_umask(int vector) 104 { 105 arm_gic_umask(0, vector); 106 } 107 108 /** 109 * This function will install a interrupt service routine to a interrupt. 110 * @param vector the interrupt number 111 * @param new_handler the interrupt service routine to be installed 112 * @param old_handler the old interrupt service routine 113 */ 114 rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, 115 void *param, const char *name) 116 { 117 rt_isr_handler_t old_handler = RT_NULL; 118 119 if (vector < MAX_HANDLERS) 120 { 121 old_handler = isr_table[vector].handler; 122 123 if (handler != RT_NULL) 124 { 125 #ifdef RT_USING_INTERRUPT_INFO 126 rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX); 127 #endif /* RT_USING_INTERRUPT_INFO */ 128 isr_table[vector].handler = handler; 129 isr_table[vector].param = param; 130 } 131 /* set the interrupt to this cpu */ 132 arm_gic_set_cpu(0, vector, 1 << rt_cpu_get_smp_id()); 133 } 134 135 return old_handler; 136 } 137 138 void rt_hw_interrupt_clear(int vector) 139 { 140 /* SGI will be cleared automatically. */ 141 if (vector < 16) 142 return; 143 } 144