]> rtime.felk.cvut.cz Git - arc.git/blob - arch/arm/arm_cr4/kernel/irq.c
More work on TMS570 for Core 2.9.
[arc.git] / arch / arm / arm_cr4 / kernel / irq.c
1 /* -------------------------------- Arctic Core ------------------------------
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com
3  *
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>
5  *
6  * This source code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 as published by the
8  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * for more details.
14  * -------------------------------- Arctic Core ------------------------------*/
15
16 #include "internal.h"
17 #include "task_i.h"
18 #include "hooks.h"
19 #include "isr.h"
20 #include "irq_types.h"
21 #include "core_cr4.h"
22
23 extern TaskType Os_Arc_CreateIsr( void (*entry)(void ), uint8_t prio, const char *name );
24 extern void *Irq_VectorTable[NUMBER_OF_INTERRUPTS_AND_EXCEPTIONS];
25
26
27 static inline void Irq_Setup() {
28         vimREG->FIRQPR0 = 0x0;
29         vimREG->FIRQPR1 = 0x0;
30 }
31
32 void Irq_Init( void ) {
33         Irq_Setup();
34         Irq_Enable();
35 }
36
37
38 /**
39  *
40  * @param stack_p Ptr to the current stack.
41  *
42  * The stack holds C, NVGPR, VGPR and the EXC frame.
43  *
44  */
45 #define MAX_WAIT_COUNT 1000
46 void *Irq_Entry( void *stack_p )
47 {
48         uint32_t *stack;
49
50         // This is the current hardware interrupt channel that we are processing.
51         volatile sint8 channel;
52
53         // This is the current OS-interrupt vector that we are processing.
54         volatile sint8 virtualChannel;
55
56         // Get the highest pending interrupt.
57         volatile uint32 c = 0;
58         do {
59                 channel = IrqGetCurrentInterruptSource();
60                 c++;
61         } while (channel < 0 && c < MAX_WAIT_COUNT);
62
63         if (c >= MAX_WAIT_COUNT) {
64                 // No interrupt is pending
65                 return stack_p;
66         }
67
68         // In most cases the OS-channel is the same as the hardware channel.
69         virtualChannel = channel;
70
71         // Special case for software interrupts.
72         if (channel == SSI) {
73                 // Get the emulated interrupt channel.
74                 virtualChannel = systemREG1->SSISR1;
75         }
76
77         /*stack = (uint32_t *)stack_p;
78         struct OsTaskVar * pcb = (struct OsTaskVar *)Irq_VectorTable[virtualChannel];
79         // Save the hardware channel in the PCB, so that Os_Isr knows which interrupt channel to deactivate.
80         pcb->vector = channel;
81         */
82         // Don't know what to pass here yet. Use the virtual channel for now, but
83         // probably need to pass channel as well.
84         stack = Os_Isr(stack, virtualChannel);
85
86         //Irq_Enable();
87         return stack;
88 }
89
90 /**
91  * Attach an ISR type 1 to the interrupt controller.
92  *
93  * @param entry
94  * @param int_ctrl
95  * @param vector
96  * @param prio
97  */
98 void Irq_AttachIsr1( void (*entry)(void), void *int_ctrl, uint32_t vector, uint8_t prio) {
99
100         // TODO: Use NVIC_InitVector(vector, osPrioToCpuPio(pcb->prio)); here
101 }
102
103 /**
104  * NVIC prio have priority 0-15, 0-highest priority.
105  * Autosar does it the other way around, 0-Lowest priority
106  *
107  * Autosar    NVIC
108  *   31        0
109  *   30        0
110  *   ..
111  *   0         15
112  *   0         15
113  * @param prio
114  * @return
115  */
116 static inline int osPrioToCpuPio( uint8_t prio ) {
117         assert(prio<32);
118         prio = 31 - prio;
119         return (prio>>1);
120 }
121
122 /**
123  * Attach a ISR type 2 to the interrupt controller.
124  *
125  * @param tid
126  * @param int_ctrl
127  * @param vector
128  */
129 /*
130 void Irq_AttachIsr2(TaskType tid,void *int_ctrl,IrqType vector ) {
131         OsTaskVarType *pcb;
132
133         pcb = Os_TaskGet(tid);
134         Irq_VectorTable[vector] = (void *)pcb;
135         IrqActivateChannel(vector);
136
137         // TOdo replace NVIC_InitVector(vector, osPrioToCpuPio(pcb->prio));
138 }
139 */
140 void Irq_EnableVector( int16_t vector, int priority, int core ) {
141
142         if (vector < NUMBER_OF_INTERRUPTS_AND_EXCEPTIONS) {
143                 IrqActivateChannel(vector);
144         } else {
145                 /* Invalid vector! */
146                 assert(0);
147         }
148 }
149
150 /**
151  * Generates a soft interrupt, ie sets pending bit.
152  * This could also be implemented using ISPR regs.
153  *
154  * @param vector
155  */
156 void Irq_GenerateSoftInt( IrqType vector ) {
157         IrqActivateChannel(SSI);
158         systemREG1->SSISR1 = (0x75 << 8) | vector;
159 }
160
161 /**
162  * Get the current priority from the interrupt controller.
163  * @param cpu
164  * @return
165  */
166 uint8_t Irq_GetCurrentPriority( Cpu_t cpu) {
167
168         uint8_t prio = 0;
169
170         // SCB_ICSR contains the active vector
171         return prio;
172 }
173
174 typedef struct {
175         uint32_t dummy;
176 } exc_stack_t;
177
178