]> rtime.felk.cvut.cz Git - arc.git/blob - system/kernel/isr.c
Fixed bug in interrupt handler caused by change in GetTaskID implementation.
[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 #include <sys/types.h>
17 #include <stdint.h>
18 #include <string.h>
19 #include "internal.h"
20 #include "irq.h"
21 #if 0
22
23
24 #include <stdint.h>
25 #include <stdlib.h>
26 #include <assert.h>
27 #include <sys/queue.h>
28 #include <string.h>
29 #include "internal.h"
30
31 #endif
32
33
34 // TODO: remove. Make soft links or whatever
35 #if defined(CFG_ARM_CM3)
36 #include "irq_types.h"
37 //#include "stm32f10x.h"
38 //#include "stm32f10x_arc.h"
39 #endif
40
41 extern caddr_t *sbrk(int);
42
43 #define os_alloc(_x)    sbrk(_x)
44
45 OsPcbType * os_alloc_new_pcb( void ) {
46         void *h = os_alloc(sizeof(OsPcbType));
47         memset(h,0,sizeof(OsPcbType));
48         assert(h!=NULL);
49         return h;
50 }
51
52 #if 0
53 typedef void (*Os_IsrEntryType)(void);
54
55
56 typedef Os_IsrInfo_s {
57         Os_IsrEntryType entry;
58         uint32_t vector;
59         uint8_t priority;
60 } Os_IsrInfoType;
61 #endif
62
63
64 extern TaskType Os_AddTask( OsPcbType *pcb );
65
66 static uint8 stackTop = 0x42;
67
68 /**
69  * Creates an ISR dynamically
70  * @param entry
71  * @param prio
72  * @param name
73  *
74  * @return The PID of the ISR created
75  */
76 TaskType Os_Arc_CreateIsr( void (*entry)(void ), uint8_t prio, const char *name )
77 {
78         OsPcbType *pcb = os_alloc_new_pcb();
79         strncpy(pcb->name,name,TASK_NAME_SIZE);
80         pcb->vector = -1;
81         pcb->prio = prio;
82         /* TODO: map to interrupt controller priority */
83         assert(prio<=OS_TASK_PRIORITY_MAX);
84         pcb->proc_type  = PROC_ISR2;
85         pcb->state = ST_SUSPENDED;
86         pcb->entry = entry;
87         pcb->stack.top = &stackTop;
88
89         return Os_AddTask(pcb);
90 }
91
92 /**
93  * Before we have proper editor for ISR2 use this function to add resources
94  * to an ISR2
95  *
96  * @param isr
97  * @param resource
98  * @return
99  */
100 StatusType Os_IsrAddResource( TaskType isr, ResourceType resource ) {
101         return E_OK;
102 }
103
104 #if defined(CFG_ARM_CM3)
105 extern void Irq_EOI2( void );
106
107 void TailChaining(void *stack)
108 {
109         struct OsPcb *pPtr = NULL;
110
111         POSTTASKHOOK();
112
113         /* Save info for preempted pcb */
114         pPtr = get_curr_pcb();
115         pPtr->stack.curr = stack;
116         pPtr->state = ST_READY;
117         OS_DEBUG(D_TASK,"Preempted %s\n",pPtr->name);
118
119         Os_StackPerformCheck(pPtr);
120
121         /* We interrupted a task */
122         OsPcbType *new_pcb  = Os_TaskGetTop();
123
124         Os_StackPerformCheck(new_pcb);
125
126         if(     (new_pcb == os_sys.curr_pcb) ||
127                         (os_sys.curr_pcb->scheduling == NON) ||
128                         !Os_SchedulerResourceIsFree() )
129         {
130                 /* Just bring the preempted task back to running */
131                 Os_TaskSwapContextTo(NULL,os_sys.curr_pcb);
132         } else {
133                 OS_DEBUG(D_TASK,"Found candidate %s\n",new_pcb->name);
134                 Os_TaskSwapContextTo(NULL,new_pcb);
135         }
136 }
137
138 void Os_Isr_cm3( void *isr_p ) {
139
140         struct OsPcb *isrPtr;
141
142         os_sys.int_nest_cnt++;
143
144         /* Grab the ISR "pcb" */
145         isrPtr = (struct OsPcb *)isr_p;
146         isrPtr->state = ST_RUNNING;
147
148         if( isrPtr->proc_type & ( PROC_EXTENDED | PROC_BASIC ) ) {
149                 assert(0);
150         }
151
152         Irq_Enable();
153         isrPtr->entry();
154         Irq_Disable();
155
156         /* Check so that ISR2 haven't disabled the interrupts */
157         /** @req OS368 */
158         if( Os_IrqAnyDisabled() ) {
159                 Os_IrqClearAll();
160                 ERRORHOOK(E_OS_DISABLEDINT);
161         }
162
163         /* Check so that the ISR2 have called ReleaseResource() for each GetResource() */
164         /** @req OS369 */
165         if( Os_TaskOccupiesResources(isrPtr) ) {
166                 Os_ResourceFreeAll(isrPtr);
167                 ERRORHOOK(E_OS_RESOURCE);
168         }
169
170         isrPtr->state = ST_SUSPENDED;
171
172         Irq_EOI();
173
174         --os_sys.int_nest_cnt;
175
176         /* Scheduling is done in PendSV handler for ARM CM3 */
177         *((uint32_t volatile *)0xE000ED04) = 0x10000000; // PendSV
178 }
179 #endif
180
181 /**
182  * Handle ISR type 2 interrupts from interrupt controller.
183  *
184  * @param stack Ptr to the current stack
185  * @param vector The vector that took the interrupt
186  */
187 void *Os_Isr( void *stack, void *isr_p ) {
188         struct OsPcb *isrPtr;
189         struct OsPcb *pPtr = NULL;
190
191         /* Check if we interrupted a task or ISR */
192         if( os_sys.int_nest_cnt == 0 ) {
193                 /* We interrupted a task */
194                 POSTTASKHOOK();
195
196                 /* Save info for preempted pcb */
197                 pPtr = get_curr_pcb();
198                 pPtr->stack.curr = stack;
199                 pPtr->state = ST_READY;
200                 OS_DEBUG(D_TASK,"Preempted %s\n",pPtr->name);
201
202                 Os_StackPerformCheck(pPtr);
203         } else {
204                 /* We interrupted an ISR */
205         }
206
207         os_sys.int_nest_cnt++;
208
209         /* Grab the ISR "pcb" */
210         isrPtr = (struct OsPcb *)isr_p;
211         isrPtr->state = ST_RUNNING;
212
213         if( isrPtr->proc_type & ( PROC_EXTENDED | PROC_BASIC ) ) {
214                 assert(0);
215         }
216
217         Irq_SOI();
218
219 #if !defined(CFG_HCS12D)
220         Irq_Enable();
221         isrPtr->entry();
222         Irq_Disable();
223 #else
224         isrPtr->entry();
225 #endif
226
227         /* Check so that ISR2 haven't disabled the interrupts */
228         /** @req OS368 */
229         if( Os_IrqAnyDisabled() ) {
230                 Os_IrqClearAll();
231                 ERRORHOOK(E_OS_DISABLEDINT);
232         }
233
234         /* Check so that the ISR2 have called ReleaseResource() for each GetResource() */
235         /** @req OS369 */
236         if( Os_TaskOccupiesResources(isrPtr) ) {
237                 Os_ResourceFreeAll(isrPtr);
238                 ERRORHOOK(E_OS_RESOURCE);
239         }
240
241         isrPtr->state = ST_SUSPENDED;
242
243         Irq_EOI();
244
245         --os_sys.int_nest_cnt;
246
247 #if defined(CFG_ARM_CM3)
248                 /* Scheduling is done in PendSV handler for ARM CM3 */
249                 *((uint32_t volatile *)0xE000ED04) = 0x10000000; // PendSV
250 #else
251         // We have preempted a task
252         if( (os_sys.int_nest_cnt == 0) ) {
253                 OsPcbType *new_pcb  = Os_TaskGetTop();
254
255                 Os_StackPerformCheck(new_pcb);
256
257                 if(     (new_pcb == os_sys.curr_pcb) ||
258                                 (os_sys.curr_pcb->scheduling == NON) ||
259                                 !Os_SchedulerResourceIsFree() )
260                 {
261                         /* Just bring the preempted task back to running */
262                         os_sys.curr_pcb->state = ST_RUNNING;
263                         PRETASKHOOK();
264                 } else {
265                         OS_DEBUG(D_TASK,"Found candidate %s\n",new_pcb->name);
266                         Os_TaskSwapContextTo(NULL,new_pcb);
267                 }
268         } else {
269                 /* We have a nested interrupt, do nothing */
270         }
271 #endif
272
273         return stack;
274 }