⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serlock.c

📁 ARM入门的好帮手.包含了从简单到相对较复杂的程序.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*-C-*- * * $Revision: 1.16.4.3 $ *   $Author: rivimey $ *     $Date: 1998/01/23 18:47:42 $ * * Copyright (c) 1996 Advanced RISC Machines Limited. * All Rights Reserved. * *   Project: ANGEL * *     Title: Implementation of serialiser module */#include "serlock.h"#include "logging.h"#include "support.h"#include "arm.h"#include "devdriv.h"#include "devconf.h"#include "stacks.h"#if MINIMAL_ANGEL == 0/* #define DEBUG_TASKS *//* *        Function:  angel_StartTask * *         Purpose:  To execute a task. * *       Arguments:  regblock: a pointer to the angel_RegBlock structure *                             containing the registers to be instated *                             when the tasks executes * *    Special Note:  This is coded in serlasm.s, as it is not a normal *                   function.  However, the prototype is here because *                   it is needed by functions in this module. * *  Pre-conditions:  This code is called from SVC mode with IRQ and FIQ *                   disabled. * *          Effect:  The task described is executed - when that task *                   completes control will be returned to angel_NextTask. *                   This code just inststes all the registers precisely *                   as set up in regblock.  Thus for tasks which are being *                   started for the first time, sl, sp, fp, lr and cpsr *                   must have already been set up. * *    Special Note:  A second entry point to this function, *                   angel_StartTask_NonSVCEntry, which allows the exception *                   handlers a way to restart an aborted task using this *                   function, but without having to go into SVC mode. */extern void angel_StartTask(angel_RegBlock * regblock);/* *        Function:  angel_NextTask * *         Purpose:  Entered when any task completes * *       Arguments:  None * *    Special Note:  This is coded in serlasm.s, as it is not a normal *                   function.  However, the prototype is here because *                   it is needed by functions in this module. * *  Pre-conditions:  This code is called from either SVC mode or USR mode *                   with IRQ and FIQ enabled. * *          Effect:  SVC mode is entered and the SVC stack grabbed. *                   Interrupts are disabled, and then angel_SelectNextTask *                   is called. */extern void angel_NextTask(void);/* *        Function:  angel_IdleLoop * *         Purpose:  Entered when there are no tasks ready to execute and *                   there is nothing to do right now. * *       Arguments:  None * *    Special Note:  This is coded in serlasm.s, as it is not a normal *                   function.  However, the prototype is here because *                   it is needed by functions in this module. * *  Pre-conditions:  This code is called from either SVC mode *                   with IRQ and FIQ enabled. * *          Effect:  The SVC stack is emptied, and then interrupts are enabled *                   angel_Yield is then repeatedly called to see if there is *                   anything to do. */extern void angel_IdleLoop(void);/**********************************************************************/angel_RegBlock Angel_MutexSharedTempRegBlocks[2];/* * angel_TaskQueueItem: each item has a forward pointer a RegBlock *                      index and a priority. * * The index is the bit number used in angel_FreeBitmap. */typedef struct angel_TaskQueueItem{    struct angel_TaskQueueItem *next;    int index;    angel_TaskPriority pri;    bool new_task;              /* FALSE if interrupted thread */    angel_RegBlock rb;} angel_TaskQueueItem;static angel_TaskQueueItem *angel_TaskQueueHead;/* * This is the number of RegBlocks we support, and also the number of * entries we can cope with in the Task Queue.  If it is made to * exceed 31 then we must recode the bitmap manipulation stuff. */#define POOLSIZE   12/* This holds which of the pool entries are free and which used. * A set bit means that entry is FREE */static unsigned angel_FreeBitMap;static int angel_ApplicationBlocked;static angel_TaskPriority angel_LastExecutedTaskPriority;static angel_TaskQueueItem angel_TQ_Pool[POOLSIZE];/**********************************************************************//* * The freeing and allocation of register blocks may be done by index only. */#define ISFREE(n)  ((angel_FreeBitMap & (1 << (n))) != 0)#define ISALLOC(n) ((angel_FreeBitMap & (1 << (n))) == 0)#define FREE(n)    angel_FreeBitMap |= (1 << (n))#define ALLOC(n)   angel_FreeBitMap &= ~(1 << (n))/* angel_FreeToPool * * This function is passed the index of a pool entry to be freed. * * It will modify the queue pointers appropriately as well as marking * this pool element as free. */static void angel_FreeToPool(int n){    angel_TaskQueueItem *my_tqi = &angel_TQ_Pool[n];    angel_TaskQueueItem *tqi, *l_tqi;    if (ISFREE(n))        LogError(LOG_SERLOCK, ( "Attempt to deallocate free block %d.\n", n));    FREE(n);    /* Now we find it on the queue and remove it */    for (tqi = angel_TaskQueueHead, l_tqi = NULL;         (tqi != my_tqi && tqi != NULL);)    {        l_tqi = tqi;        tqi = tqi->next;    }    if (tqi == NULL)    {        LogError(LOG_SERLOCK, ( "Block could not be dequeued (%d).\n", n));        return;    }#ifdef DO_TRACE    LogTrace(LOG_SERLOCK, "SFreePool: %d\n", n);#endif    if (l_tqi == NULL)        angel_TaskQueueHead = my_tqi->next;    else        l_tqi->next = my_tqi->next;    my_tqi->next = NULL;}/* angel_AllocateFromPool * * This function is passed a priority and 'new task' flag and will return * the index number of the pool entry which has been set up. * * It will modify the queue pointers appropriately, and sets up the * priorities and new_flag members.  It does not set up the regblock * in any way. * * A task is put on the front of the part of the queue of the * appropriate priority only if it is neither a new task nor a yielded * task (ie. a real interrupted task).  All others are put an the end * of the part of the queue with the appropriate priority */static int angel_AllocateFromPool(angel_TaskPriority pri, bool new_task,                       bool yielded){    int i;    for (i = 0; i < POOLSIZE; i++)    {        if (ISFREE(i))        {            angel_TaskQueueItem *my_tqi = &angel_TQ_Pool[i];            angel_TaskQueueItem *tqi, *l_tqi;#ifdef DO_TRACE            LogTrace(LOG_SERLOCK, "SAllocPool: %d-p%d-n%d\n", i, pri, new_task);#endif            ALLOC(i);            /* Set up the priorities */            my_tqi->pri = pri;            my_tqi->new_task = new_task;            /* And insert the item into the queue.             * which first involves finding a task of same priority and             * inserting this task before it if not new, or after it if new.             */            /* if new or yielded, ensure it goes after any exisiting entry at pri */            if (new_task || yielded)                pri = (angel_TaskPriority) (pri - 1);            for (tqi = angel_TaskQueueHead, l_tqi = NULL;                 (tqi != NULL) && (tqi->pri > pri);)            {                l_tqi = tqi;                tqi = tqi->next;            }            /* We may have reached the end of the list, or we may not have */            my_tqi->next = tqi;            if (l_tqi == NULL)                angel_TaskQueueHead = my_tqi;            else                l_tqi->next = my_tqi;                        /* LogInfo(LOG_SERLOCK, ( "Allocated RegBlock %d\n",i)); */            return i;        }    }    LogError(LOG_SERLOCK, ( "AllocateFromPool: No free RegBlock\n"));#if DEBUG == 1    /*     * for (i = 0; i < POOLSIZE; i++)     *{     *  angel_TaskQueueItem *my_tqi = &angel_TQ_Pool[i];     *     *  LogWarning(LOG_SERLOCK, ( "Task %d: Pri=%d, New=%d, PC=%8x, PSR=%08x\n",     *                              i, my_tqi->pri, my_tqi->new_task,     *                              my_tqi->rb.r[15], my_tqi->rb.cpsr));     *}     */#endif    return -1;}/**********************************************************************//* * This routine looks for an interrupted queued task at the given * priority */static angel_RegBlock *angel_AccessQueuedRegBlock(angel_TaskPriority pri){    angel_TaskQueueItem *tqi;    /* Find a task with the required priority, not marked as new */    for (tqi = angel_TaskQueueHead;         (tqi != NULL) && !((tqi->pri == pri) && (!tqi->new_task));        )    {        tqi = tqi->next;    }    if (tqi == NULL)    {        LogTrace1("SAccessQueue: p%d-NT ", pri);        return NULL;    }    else    {        LogTrace2("SAccessQueue: p%d-t%d ", pri, tqi->index);        return &(tqi->rb);    }}angel_RegBlock *Angel_AccessApplicationRegBlock(void){    angel_RegBlock *rb;    /* Find a task with the Application priority */    rb = angel_AccessQueuedRegBlock(TP_Application);    if (rb == NULL)    {        LogWarning(LOG_SERLOCK, ( "Could not find application task.\n"));        return NULL;    }    return rb;}void Angel_BlockApplication(int value){    LogInfo(LOG_SERLOCK, ( "angel_BlockApplication - set to %d.\n", value));    angel_ApplicationBlocked = value;  /* yes, folks - that simple */}int Angel_IsApplicationBlocked(void){    LogInfo(LOG_SERLOCK, ("angel_IsApplicationBlocked - returns %d.\n",              angel_ApplicationBlocked));    return angel_ApplicationBlocked;}int Angel_IsApplicationRunning(void){    int running = (angel_LastExecutedTaskPriority == TP_Application) ||    (angel_LastExecutedTaskPriority == TP_ApplCallBack);    LogInfo(LOG_SERLOCK, ( "angel_IsApplicationRunning - returns %d.\n", running));    return running;}void Angel_FlushApplicationCallbacks(void){    angel_TaskQueueItem *tqi;    int found;    LogInfo(LOG_SERLOCK, ( "angel_FlushApplicationCallBakcs entered\n"));    /* Find all tasks with the Application priority.     * We have to start the loop from scratch each time we find one     * because angel_FreeToPool changes all the pointers !     */    do    {        for (found = 0, tqi = angel_TaskQueueHead;             (tqi != NULL && tqi->pri != TP_ApplCallBack);)        {            tqi = tqi->next;        }        if (tqi != NULL)        {            LogInfo(LOG_SERLOCK, ( "angel_FlushApplicationCallbacks - found task to flush\n"));            angel_FreeToPool(tqi->index);            found = 1;        }    }    while (found == 1);}/* *        Function:  angel_SetUpTaskEnvironment * *         Purpose:  To set up the execution environment for a task *                   depeneding on its priority. * *       Arguments:  rb    a pointer to the RegBlock to be updated. * *                   pri   the priority of the task * *   Pre-conditions: None * *          Effect:  sl, sp, fp, lr, cpsr are set up appropriately *                   according to the priority requested. * *  Post-conditions: None */static void angel_SetUpTaskEnvironment(angel_RegBlock * rb,                           angel_TaskPriority pri){    angel_RegBlock *env_rb;    /* LogInfo(LOG_SERLOCK, ("SetUpTaskEnvironment: p%d\n", pri)); */    switch (pri)    {        case TP_ApplCallBack:            {                LogInfo(LOG_SERLOCK, ( "SetUpTask: ApplCallBack\n"));                                env_rb = Angel_AccessApplicationRegBlock();                rb->r[10] = env_rb->r[10];  /* Copy sl from Application */                rb->r[13] = env_rb->r[13];  /* Copy sp from Application */                rb->r[11] = 0;      /* fp = 0 */                rb->r[14] = (unsigned)angel_NextTask;                rb->cpsr = USRmode;                break;            }                    case TP_AngelCallBack:            {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -