]> rtime.felk.cvut.cz Git - arc.git/blob - system/kernel/isr.c
c18420e2369455bef45dbcd3d735ad65a2b3ccef
[arc.git] / system / kernel / isr.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
17 #include <sys/types.h>
18 #include <stdint.h>
19 #include <string.h>
20 #include "Compiler.h"
21 #include "internal.h"
22 #include "isr.h"
23 #include "irq.h"
24 //#include "irq_config.h"
25
26
27 extern const uint8_t Os_VectorToIsr[NUMBER_OF_INTERRUPTS_AND_EXCEPTIONS];
28 extern const OsIsrConstType Os_IsrConstList[OS_ISR_CNT];
29
30 #if OS_ISR_MAX_CNT!=0
31 OsIsrVarType Os_IsrVarList[OS_ISR_MAX_CNT];
32 #endif
33
34 SECTION_BALIGN(0x10) uint8_t Os_IsrStack[OS_INTERRUPT_STACK_SIZE];
35
36 // TODO: remove. Make soft links or whatever
37 #if defined(CFG_ARM_CM3)
38 #include "irq_types.h"
39 //#include "stm32f10x.h"
40 //#include "stm32f10x_arc.h"
41 #endif
42
43 extern caddr_t *sbrk(int);
44
45 #define os_alloc(_x)    sbrk(_x)
46
47 OsTaskVarType * os_alloc_new_pcb( void ) {
48         void *h = os_alloc(sizeof(OsTaskVarType));
49         memset(h,0,sizeof(OsTaskVarType));
50         assert(h!=NULL);
51         return h;
52 }
53
54
55 //extern TaskType Os_AddTask( OsTaskVarType *pcb );
56
57 //static uint8 stackTop = 0x42;
58
59
60
61 void Os_IsrInit( void ) {
62
63         Irq_Init();
64
65         /* Attach the interrupts */
66         for (int i = 0; i < sizeof(Os_IsrConstList) / sizeof(OsIsrConstType); i++) {
67                 Os_IsrAdd(&Os_IsrConstList[i]);
68         }
69 }
70
71
72 /**
73  * Adds an ISR to a list of Isr's. The ISRType (id) is returned
74  * for the "created" ISR.
75  *
76  * @param isrPtr Pointer to const data holding ISR information.
77  * @return
78  */
79 ISRType Os_IsrAdd( const OsIsrConstType * restrict isrPtr ) {
80         ISRType id;
81
82         id = Os_Sys.isrCnt++;
83         /* We have no VAR entires for ISR1 */
84         if( isrPtr->type == ISR_TYPE_2) {
85                 Os_IsrVarList[id].constPtr = isrPtr;
86         }
87
88         Irq_EnableVector( isrPtr->vector, isrPtr->priority, Os_ApplGetCore(isrPtr->appOwner )  );
89
90         return id;
91 }
92
93 const OsIsrConstType * Os_IsrGet( int16_t vector) {
94         return &Os_IsrConstList[Os_VectorToIsr[vector]];
95 }
96
97 #if 0
98 void Os_IsrDisable( ISRType isr) {
99
100 }
101
102 void Os_IsrEnable( ISRType isr) {
103
104 }
105 #endif
106
107
108 /*
109  * Resources:
110  *   Irq_VectorTable[]
111  *   Irq_IsrTypeTable[]
112  *   Irq_PriorityTable[]
113  *
114  *   exception table
115  *   interrupt table
116  *
117  * Usual HW resources.
118  * - prio in HW (ppc and arm (even cortex m4))
119  *
120  *
121  * TOOL GENERATES ALL
122  *   Irq_VectorTable   CONST
123  *   Irq_IsrTypeTable  CONST
124  *   Irq_PriorityTable CONST  Can probably be a table with ISR_MAX number
125  *                            of for a CPU with prio registers.  For masking
126  *                            CPUs it's better to keep an array to that indexing
127  *                            can be used.
128  *
129  *   The problem with this approach is that the tool needs to know everything.
130  *
131  * TOOL GENERATES PART
132  *   Irq_VectorTable   VAR     Since we must add vectors later
133  *   Irq_IsrTypeTable  VAR     Since we must add vectors later
134  *   Irq_PriorityTable VAR
135  *
136  *   We move the
137  *
138  */
139
140
141
142 /**
143  * Before we have proper editor for ISR2 use this function to add resources
144  * to an ISR2
145  *
146  * @param isr
147  * @param resource
148  * @return
149  */
150 StatusType Os_IsrAddResource( TaskType isr, ResourceType resource ) {
151         return E_OK;
152 }
153
154 #if defined(CFG_ARM_CM3)
155 extern void Irq_EOI2( void );
156
157 void TailChaining(void *stack)
158 {
159         struct OsTaskVar *pPtr = NULL;
160
161         POSTTASKHOOK();
162
163         /* Save info for preempted pcb */
164         pPtr = get_curr_pcb();
165         pPtr->stack.curr = stack;
166         pPtr->state = ST_READY;
167         OS_DEBUG(D_TASK,"Preempted %s\n",pPtr->name);
168
169         Os_StackPerformCheck(pPtr);
170
171         /* We interrupted a task */
172         OsTaskVarType *new_pcb  = Os_TaskGetTop();
173
174         Os_StackPerformCheck(new_pcb);
175
176         if(     (new_pcb == Os_Sys.currTaskPtr) ||
177                         (Os_Sys.currTaskPtr->scheduling == NON) ||
178                         !Os_SchedulerResourceIsFree() )
179         {
180                 /* Just bring the preempted task back to running */
181                 Os_TaskSwapContextTo(NULL,Os_Sys.currTaskPtr);
182         } else {
183                 OS_DEBUG(D_TASK,"Found candidate %s\n",new_pcb->name);
184                 Os_TaskSwapContextTo(NULL,new_pcb);
185         }
186 }
187
188 void Os_Isr_cm3( void *isr_p ) {
189
190         struct OsTaskVar *isrPtr;
191
192         Os_Sys.intNestCnt++;
193
194         /* Grab the ISR "pcb" */
195         isrPtr = (struct OsTaskVar *)isr_p;
196         isrPtr->state = ST_RUNNING;
197
198         if( isrPtr->proc_type & ( PROC_EXTENDED | PROC_BASIC ) ) {
199                 assert(0);
200         }
201
202         Irq_Enable();
203         isrPtr->entry();
204         Irq_Disable();
205
206         /* Check so that ISR2 haven't disabled the interrupts */
207         /** @req OS368 */
208         if( Os_IrqAnyDisabled() ) {
209                 Os_IrqClearAll();
210                 ERRORHOOK(E_OS_DISABLEDINT);
211         }
212
213         /* Check so that the ISR2 have called ReleaseResource() for each GetResource() */
214         /** @req OS369 */
215         if( Os_TaskOccupiesResources(isrPtr) ) {
216                 Os_ResourceFreeAll(isrPtr);
217                 ERRORHOOK(E_OS_RESOURCE);
218         }
219
220         isrPtr->state = ST_SUSPENDED;
221
222         Irq_EOI();
223
224         --Os_Sys.intNestCnt;
225
226         /* Scheduling is done in PendSV handler for ARM CM3 */
227         *((uint32_t volatile *)0xE000ED04) = 0x10000000; // PendSV
228 }
229 #endif
230
231 /*-----------------------------------------------------------------*/
232
233 void Os_IsrGetStackInfo( OsIsrStackType *stack ) {
234         stack->top = Os_IsrStack;
235         stack->size = sizeof(Os_IsrStack);
236 }
237
238
239 /**
240  * Handle ISR type 2 interrupts from interrupt controller.
241  *
242  * @param stack Pointer to the current stack
243  * @param vector
244  */
245 void *Os_Isr( void *stack, int16_t vector ) {
246         uint8_t isrId = Os_VectorToIsr[vector];
247         OsTaskVarType *taskPtr = NULL;
248
249         /* Check if we interrupted a task or ISR */
250         if( Os_Sys.intNestCnt == 0 ) {
251                 /* We interrupted a task */
252                 POSTTASKHOOK();
253
254                 /* Save info for preempted pcb */
255                 taskPtr = get_curr_pcb();
256                 taskPtr->stack.curr = stack;
257                 taskPtr->state = ST_READY;
258                 OS_DEBUG(D_TASK,"Preempted %s\n",taskPtr->name);
259
260                 Os_StackPerformCheck(taskPtr);
261         } else {
262                 /* We interrupted an ISR */
263         }
264
265         Os_Sys.intNestCnt++;
266
267         /* Grab the ISR "pcb" */
268         Os_IsrVarList[isrId].state = ST_ISR_RUNNING;
269
270         Irq_SOI();
271
272 #if defined(CFG_HCS12D)
273         Os_IsrConstList[isrId].entry();
274 #else
275         Irq_Enable();
276         Os_IsrConstList[isrId].entry();
277         Irq_Disable();
278 #endif
279
280         /* Check so that ISR2 haven't disabled the interrupts */
281         /** @req OS368 */
282         if( Os_IrqAnyDisabled() ) {
283                 Os_IrqClearAll();
284                 ERRORHOOK(E_OS_DISABLEDINT);
285         }
286
287         /* Check so that the ISR2 have called ReleaseResource() for each GetResource() */
288         /** @req OS369 */
289         if( Os_TaskOccupiesResources(taskPtr) ) {
290                 Os_ResourceFreeAll(taskPtr);
291                 ERRORHOOK(E_OS_RESOURCE);
292         }
293
294         Os_IsrVarList[isrId].state = ST_ISR_NOT_RUNNING;
295
296         Irq_EOI();
297
298         --Os_Sys.intNestCnt;
299
300 #if defined(CFG_ARM_CM3)
301                 /* Scheduling is done in PendSV handler for ARM CM3 */
302                 *((uint32_t volatile *)0xE000ED04) = 0x10000000; // PendSV
303 #else
304         // We have preempted a task
305         if( (Os_Sys.intNestCnt == 0) ) {
306                 OsTaskVarType *new_pcb  = Os_TaskGetTop();
307
308                 Os_StackPerformCheck(new_pcb);
309
310                 if(     (new_pcb == Os_Sys.currTaskPtr) ||
311                                 (Os_Sys.currTaskPtr->constPtr->scheduling == NON) ||
312                                 !Os_SchedulerResourceIsFree() )
313                 {
314                         /* Just bring the preempted task back to running */
315                         Os_Sys.currTaskPtr->state = ST_RUNNING;
316                         PRETASKHOOK();
317                 } else {
318                         OS_DEBUG(D_TASK,"Found candidate %s\n",new_pcb->name);
319                         Os_TaskSwapContextTo(NULL,new_pcb);
320                 }
321         } else {
322                 /* We have a nested interrupt, do nothing */
323         }
324 #endif
325
326         return stack;
327 }