1 /* -------------------------------- Arctic Core ------------------------------
\r
2 * Arctic Core - the open source AUTOSAR platform http://arccore.com
\r
4 * Copyright (C) 2009 ArcCore AB <contact@arccore.com>
\r
6 * This source code is free software; you can redistribute it and/or modify it
\r
7 * under the terms of the GNU General Public License version 2 as published by the
\r
8 * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.
\r
10 * This program is distributed in the hope that it will be useful, but
\r
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
\r
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
\r
14 * -------------------------------- Arctic Core ------------------------------*/
\r
17 #if defined(__GNUC__)
\r
18 #include <sys/types.h>
\r
23 #include "Compiler.h"
\r
24 #include "internal.h"
\r
25 #include "application.h"
\r
30 #define ILL_VECTOR 0xff
\r
32 extern uint8_t Os_VectorToIsr[NUMBER_OF_INTERRUPTS_AND_EXCEPTIONS];
\r
34 extern const OsIsrConstType Os_IsrConstList[OS_ISR_CNT];
\r
37 #if OS_ISR_MAX_CNT!=0
\r
38 OsIsrVarType Os_IsrVarList[OS_ISR_MAX_CNT];
\r
41 SECTION_BALIGN(0x10) uint8_t Os_IsrStack[OS_INTERRUPT_STACK_SIZE];
\r
43 // TODO: remove. Make soft links or whatever
\r
44 #if defined(CFG_ARM_CM3)
\r
45 #include "irq_types.h"
\r
46 //#include "stm32f10x.h"
\r
47 //#include "stm32f10x_arc.h"
\r
51 extern caddr_t *sbrk(int);
\r
53 #define os_alloc(_x) sbrk(_x)
\r
55 OsTaskVarType * os_alloc_new_pcb( void ) {
\r
56 void *h = os_alloc(sizeof(OsTaskVarType));
\r
57 memset(h,0,sizeof(OsTaskVarType));
\r
64 //extern TaskType Os_AddTask( OsTaskVarType *pcb );
\r
66 //static uint8 stackTop = 0x42;
\r
68 static void Os_IsrAddWithId( const OsIsrConstType * restrict isrPtr, int id ) {
\r
69 Os_IsrVarList[id].constPtr = isrPtr;
\r
70 Os_IsrVarList[id].id = id;
\r
71 #if defined(CFG_OS_ISR_HOOKS)
\r
72 Os_IsrVarList[id].preemtedId = INVALID_ISR;
\r
74 Os_VectorToIsr[isrPtr->vector + IRQ_INTERRUPT_OFFSET ] = id;
\r
75 Irq_EnableVector( isrPtr->vector, isrPtr->priority, Os_ApplGetCore(isrPtr->appOwner ) );
\r
79 void Os_IsrInit( void ) {
\r
83 Os_Sys.isrCnt = OS_ISR_CNT;
\r
84 /* Probably something smarter, but I cant figure out what */
\r
85 memset(&Os_VectorToIsr[OS_ISR_CNT],ILL_VECTOR,NUMBER_OF_INTERRUPTS_AND_EXCEPTIONS-OS_ISR_CNT);
\r
88 /* Attach the interrupts */
\r
89 for (int i = 0; i < Os_Sys.isrCnt; i++) {
\r
90 Os_IsrAddWithId(&Os_IsrConstList[i],i);
\r
96 * Adds an ISR to a list of Isr's. The ISRType (id) is returned
\r
97 * for the "created" ISR.
\r
99 * @param isrPtr Pointer to const data holding ISR information.
\r
102 ISRType Os_IsrAdd( const OsIsrConstType * restrict isrPtr ) {
\r
104 ISRType installedId;
\r
106 assert( isrPtr != NULL );
\r
107 assert( (isrPtr->vector + IRQ_INTERRUPT_OFFSET) < NUMBER_OF_INTERRUPTS_AND_EXCEPTIONS );
\r
109 /* Check if we already have installed it */
\r
110 installedId = Os_VectorToIsr[isrPtr->vector + IRQ_INTERRUPT_OFFSET ];
\r
112 if( installedId != ILL_VECTOR ) {
\r
113 /* The vector is already installed */
\r
116 /* It a new vector */
\r
117 id = Os_Sys.isrCnt++;
\r
118 /* Since OS_ISR_MAX_CNT defines the allocation limit for Os_IsrVarList,
\r
119 * we must not allocate more IDs than that */
\r
120 assert(id<OS_ISR_MAX_CNT);
\r
122 Os_IsrVarList[id].constPtr = isrPtr;
\r
123 Os_IsrVarList[id].id = id;
\r
124 #if defined(CFG_OS_ISR_HOOKS)
\r
125 Os_IsrVarList[id].preemtedId = INVALID_ISR;
\r
127 Os_VectorToIsr[isrPtr->vector + IRQ_INTERRUPT_OFFSET ] = id;
\r
128 Irq_EnableVector( isrPtr->vector, isrPtr->priority, Os_ApplGetCore(isrPtr->appOwner ) );
\r
135 const OsIsrConstType * Os_IsrGet( int16_t vector) {
\r
136 return &Os_IsrConstList[Os_VectorToIsr[vector]];
\r
141 void Os_IsrDisable( ISRType isr) {
\r
145 void Os_IsrEnable( ISRType isr) {
\r
153 * Irq_VectorTable[]
\r
154 * Irq_IsrTypeTable[]
\r
155 * Irq_PriorityTable[]
\r
160 * Usual HW resources.
\r
161 * - prio in HW (ppc and arm (even cortex m4))
\r
164 * TOOL GENERATES ALL
\r
165 * Irq_VectorTable CONST
\r
166 * Irq_IsrTypeTable CONST
\r
167 * Irq_PriorityTable CONST Can probably be a table with ISR_MAX number
\r
168 * of for a CPU with prio registers. For masking
\r
169 * CPUs it's better to keep an array to that indexing
\r
172 * The problem with this approach is that the tool needs to know everything.
\r
174 * TOOL GENERATES PART
\r
175 * Irq_VectorTable VAR Since we must add vectors later
\r
176 * Irq_IsrTypeTable VAR Since we must add vectors later
\r
177 * Irq_PriorityTable VAR
\r
186 * Before we have proper editor for ISR2 use this function to add resources
\r
193 StatusType Os_IsrAddResource( TaskType isr, ResourceType resource ) {
\r
200 #if defined(CFG_ARM_CM3)
\r
201 extern void Irq_EOI2( void );
\r
203 void TailChaining(void *stack)
\r
205 struct OsTaskVar *pPtr = NULL;
\r
209 /* Save info for preempted pcb */
\r
210 pPtr = Os_SysTaskGetCurr();
\r
211 pPtr->stack.curr = stack;
\r
212 pPtr->state = ST_READY;
\r
213 OS_DEBUG(D_TASK,"Preempted %s\n",pPtr->name);
\r
215 Os_StackPerformCheck(pPtr);
\r
217 /* We interrupted a task */
\r
218 OsTaskVarType *new_pcb = Os_TaskGetTop();
\r
220 Os_StackPerformCheck(new_pcb);
\r
222 if( (new_pcb == Os_Sys.currTaskPtr) ||
\r
223 (Os_Sys.currTaskPtr->constPtr->scheduling == NON) ||
\r
224 !Os_SchedulerResourceIsFree() )
\r
226 /* Just bring the preempted task back to running */
\r
227 Os_TaskSwapContextTo(NULL,Os_Sys.currTaskPtr);
\r
229 OS_DEBUG(D_TASK,"Found candidate %s\n",new_pcb->name);
\r
230 Os_TaskSwapContextTo(NULL,new_pcb);
\r
234 void Os_Isr_cm3( int16_t vector ) {
\r
236 OsIsrVarType *isrPtr = &Os_IsrVarList[Os_VectorToIsr[vector]];
\r
238 assert( isrPtr != NULL );
\r
240 if( isrPtr->constPtr->type == ISR_TYPE_1) {
\r
241 isrPtr->constPtr->entry();
\r
245 Os_Sys.intNestCnt++;
\r
246 isrPtr->state = ST_ISR_RUNNING;
\r
249 isrPtr->constPtr->entry();
\r
252 /* Check so that ISR2 haven't disabled the interrupts */
\r
254 if( Os_SysIntAnyDisabled() ) {
\r
255 Os_SysIntClearAll();
\r
256 ERRORHOOK(E_OS_DISABLEDINT);
\r
259 /* Check so that the ISR2 have called ReleaseResource() for each GetResource() */
\r
261 if( Os_IsrOccupiesResources(isrPtr) ) {
\r
262 Os_IsrResourceFreeAll(isrPtr);
\r
263 ERRORHOOK(E_OS_RESOURCE);
\r
266 isrPtr->state = ST_SUSPENDED;
\r
270 --Os_Sys.intNestCnt;
\r
272 /* Scheduling is done in PendSV handler for ARM CM3 */
\r
273 *((uint32_t volatile *)0xE000ED04) = 0x10000000; // PendSV
\r
277 /*-----------------------------------------------------------------*/
\r
279 void Os_IsrGetStackInfo( OsIsrStackType *stack ) {
\r
280 stack->top = Os_IsrStack;
\r
281 stack->size = sizeof(Os_IsrStack);
\r
285 #if defined(CFG_ARM_CR4)
\r
286 void *Os_Isr_cr4( void *stack, int16_t virtualVector, int16_t vector ) {
\r
287 OsIsrVarType *isrPtr = &Os_IsrVarList[Os_VectorToIsr[virtualVector]];
\r
288 isrPtr->activeVector = vector;
\r
289 return Os_Isr(stack, virtualVector);
\r
294 * Handle ISR type 2 interrupts from interrupt controller.
\r
296 * @param stack Pointer to the current stack
\r
299 void *Os_Isr( void *stack, int16_t vector ) {
\r
301 OsIsrVarType *isrPtr = &Os_IsrVarList[Os_VectorToIsr[vector]];
\r
302 OsTaskVarType *taskPtr = NULL;
\r
303 OsIsrVarType *oldIsrPtr;
\r
305 assert( isrPtr != NULL );
\r
307 if( isrPtr->constPtr->type == ISR_TYPE_1) {
\r
308 isrPtr->constPtr->entry();
\r
313 /* Check if we interrupted a task or ISR */
\r
314 if( Os_Sys.intNestCnt == 0 ) {
\r
315 /* We interrupted a task */
\r
318 /* Save info for preempted pcb */
\r
319 taskPtr = Os_SysTaskGetCurr();
\r
320 taskPtr->stack.curr = stack;
\r
321 taskPtr->state = ST_READY;
\r
322 OS_DEBUG(D_TASK,"Preempted %s\n",taskPtr->constPtr->name);
\r
324 Os_StackPerformCheck(taskPtr);
\r
326 /* We interrupted an ISR, save it */
\r
327 oldIsrPtr = Os_Sys.currIsrPtr;
\r
328 #if defined(CFG_OS_ISR_HOOKS)
\r
329 isrPtr->preemtedId = oldIsrPtr->id;
\r
330 Os_PostIsrHook(oldIsrPtr->id);
\r
334 Os_Sys.intNestCnt++;
\r
336 isrPtr->state = ST_ISR_RUNNING;
\r
337 Os_Sys.currIsrPtr = isrPtr;
\r
341 #if defined(CFG_OS_ISR_HOOKS)
\r
342 Os_PreIsrHook(isrPtr->id);
\r
346 #if defined(CFG_HCS12D)
\r
347 isrPtr->constPtr->entry();
\r
350 isrPtr->constPtr->entry();
\r
354 #if defined(CFG_OS_ISR_HOOKS)
\r
355 Os_PostIsrHook(isrPtr->id );
\r
356 if( isrPtr->preemtedId != INVALID_ISR ) {
\r
357 Os_Sys.currIsrPtr = &Os_IsrVarList[isrPtr->preemtedId];
\r
358 Os_PreIsrHook(isrPtr->preemtedId );
\r
359 isrPtr->preemtedId = INVALID_ISR;
\r
364 /* Check so that ISR2 haven't disabled the interrupts */
\r
366 if( Os_SysIntAnyDisabled() ) {
\r
367 Os_SysIntClearAll();
\r
368 ERRORHOOK(E_OS_DISABLEDINT);
\r
371 /* Check so that the ISR2 have called ReleaseResource() for each GetResource() */
\r
373 if( Os_IsrOccupiesResources(isrPtr) ) {
\r
374 Os_IsrResourceFreeAll(isrPtr);
\r
375 ERRORHOOK(E_OS_RESOURCE);
\r
378 isrPtr->state = ST_ISR_NOT_RUNNING;
\r
379 Os_Sys.currIsrPtr = isrPtr;
\r
383 --Os_Sys.intNestCnt;
\r
385 #if defined(CFG_ARM_CM3)
\r
386 /* Scheduling is done in PendSV handler for ARM CM3 */
\r
387 *((uint32_t volatile *)0xE000ED04) = 0x10000000; // PendSV
\r
389 // We have preempted a task
\r
390 if( (Os_Sys.intNestCnt == 0) ) {
\r
391 OsTaskVarType *new_pcb = Os_TaskGetTop();
\r
393 Os_StackPerformCheck(new_pcb);
\r
395 if( (new_pcb == Os_Sys.currTaskPtr) ||
\r
396 (Os_Sys.currTaskPtr->constPtr->scheduling == NON) ||
\r
397 !Os_SchedulerResourceIsFree() )
\r
399 /* Just bring the preempted task back to running */
\r
400 Os_Sys.currTaskPtr->state = ST_RUNNING;
\r
403 OS_DEBUG(D_TASK,"Found candidate %s\n",new_pcb->constPtr->name);
\r
404 Os_TaskSwapContextTo(NULL,new_pcb);
\r
407 /* We have a nested interrupt */
\r
409 /* Restore current running ISR from stack */
\r
410 Os_Sys.currIsrPtr = oldIsrPtr;
\r