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

📄 picoos.c

📁 picoos源码。The RTOS and the TCP/IP stack will be built automatically.
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 *  Copyright (c) 2004-2005, Dennis Kuschel.
 *  All rights reserved. 
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *   3. The name of the author may not be used to endorse or promote
 *      products derived from this software without specific prior written
 *      permission. 
 *
 *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
 *  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 *  INDIRECT,  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 *  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 *  OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */


/**
 * @file   picoos.c
 * @brief  pico]OS core file
 * @author Dennis Kuschel
 *
 * This file is originally from the pico]OS realtime operating system
 * (http://picoos.sourceforge.net).
 *
 * CVS-ID $Id: picoos.c,v 1.15 2006/04/16 08:48:26 dkuschel Exp $
 */


#define _POSCORE_C
#define PICOS_PRIVINCL
#include <picoos.h>



/*---------------------------------------------------------------------------
 *  MACROS FOR MEMORY ALIGNMENT
 *-------------------------------------------------------------------------*/

#if POSCFG_ALIGNMENT < 2
#define ALIGNEDSIZE(size)               (size)
#define ALIGNEDBUFSIZE(elemsize, count) ((elemsize)*(count))
#define MEMALIGN(type, var)             (type)((void*)(var))
#define NEXTALIGNED(type, var)          (((type)((void*)(var))) + 1)
#else
#define ALIGNEDSIZE(size) \
  (((size) + (POSCFG_ALIGNMENT - 1)) & ~(POSCFG_ALIGNMENT - 1))
#define ALIGNEDBUFSIZE(elemsize, count) \
  (ALIGNEDSIZE(elemsize)*(count) + (POSCFG_ALIGNMENT - 1))
#define MEMALIGN(type, var)  (type)((void*) \
  ((((MEMPTR_t)(var))+POSCFG_ALIGNMENT-1)&~(POSCFG_ALIGNMENT-1)))
#define NEXTALIGNED(type, var) \
  (type)((void*)(((MEMPTR_t)(var)) + ALIGNEDSIZE(sizeof(*(var)))))
#endif  /* POSCFG_ALIGNMENT */

#define STATICBUFFER(glblvar, size, count)  static UVAR_t \
  glblvar[((ALIGNEDSIZE(size)*count) + POSCFG_ALIGNMENT + sizeof(UVAR_t)-2) \
          / sizeof(UVAR_t)]



/*---------------------------------------------------------------------------
 *  LOCAL TYPES AND VARIABLES
 *-------------------------------------------------------------------------*/

typedef struct TBITS {
  UVAR_t         xtable[SYS_TASKTABSIZE_Y];
#if SYS_TASKTABSIZE_Y > 1
  UVAR_t         ymask;
#endif
} TBITS_t;


#if SYS_FEATURE_EVENTS != 0

typedef union EVENT {
  struct {
#if POSCFG_ARGCHECK > 1
    UVAR_t       magic;
#endif
    union EVENT *next;
  } l;
  struct {
#if POSCFG_ARGCHECK > 1
    UVAR_t       magic;
#endif
    union {
      INT_t      counter;
#if POSCFG_FEATURE_FLAGS != 0
      UVAR_t     flags;
#endif
    } d;
    TBITS_t      pend;
#if POSCFG_FEATURE_MUTEXES != 0
    POSTASK_t    task;
#endif
#ifdef POS_DEBUGHELP
    struct PICOEVENT deb;
#endif
  } e;
} *EVENT_t;


static EVENT_t   posFreeEvents_g;

#if (POSCFG_DYNAMIC_MEMORY == 0) && \
    ((POSCFG_MAX_EVENTS + SYS_MSGBOXEVENTS) != 0)
STATICBUFFER(posStaticEventMem_g, sizeof(union EVENT), \
             (POSCFG_MAX_EVENTS + SYS_MSGBOXEVENTS));
#endif

#endif  /* SYS_FEATURE_EVENTS */


#if POSCFG_FEATURE_MSGBOXES != 0

typedef struct MSGBUF {
#if POSCFG_MSG_MEMORY != 0
  unsigned char  buffer[POSCFG_MSG_BUFSIZE];
#else
  void           *bufptr;
#endif
#if POSCFG_ARGCHECK > 1
  UVAR_t         magic;
#endif
  struct MSGBUF *next;
} MSGBUF_t;

static POSSEMA_t msgAllocSyncSem_g;
static POSSEMA_t msgAllocWaitSem_g;
static UVAR_t    msgAllocWaitReq_g;
static MSGBUF_t  *posFreeMessagebuf_g;

#if (POSCFG_DYNAMIC_MEMORY == 0) && (POSCFG_MAX_MESSAGES != 0)
STATICBUFFER(posStaticMessageMem_g, sizeof(MSGBUF_t), POSCFG_MAX_MESSAGES);
#endif

#endif /* POSCFG_FEATURE_MSGBOXES */


#if POSCFG_FEATURE_TIMER != 0

typedef struct TIMER {
#if POSCFG_ARGCHECK > 1
  UVAR_t         magic;
#endif
  struct TIMER   *prev;
  struct TIMER   *next;
  POSSEMA_t      sema;
  UINT_t         counter;
  UINT_t         wait;
  UINT_t         reload;
#if POSCFG_FEATURE_TIMERFIRED != 0
  VAR_t          fired;
#endif
} TIMER_t;

static TIMER_t   *posFreeTimer_g;
static TIMER_t   *posActiveTimers_g;

#if (POSCFG_DYNAMIC_MEMORY == 0) && (POSCFG_MAX_TIMER != 0)
STATICBUFFER(posStaticTmrMem_g, sizeof(TIMER_t), POSCFG_MAX_TIMER);
#endif

#endif /* POSCFG_FEATURE_TIMER */


#if POSCFG_FEATURE_JIFFIES != 0
#if POSCFG_FEATURE_LARGEJIFFIES == 0
volatile JIF_t jiffies;
#else
static volatile JIF_t pos_jiffies_g;
#endif
#endif /* POSCFG_FEATURE_JIFFIES */


static UVAR_t    posMustSchedule_g;
static TBITS_t   posReadyTasks_g;
static TBITS_t   posAllocatedTasks_g;
static POSTASK_t posSleepingTasks_g;
static POSTASK_t posFreeTasks_g;
static POSTASK_t posTaskTable_g[SYS_TASKTABSIZE_X * SYS_TASKTABSIZE_Y];

#if POSCFG_CTXSW_COMBINE > 1
static UVAR_t    posCtxCombineCtr_g;
#endif

#if POSCFG_FEATURE_INHIBITSCHED != 0
static UVAR_t    posInhibitSched_g;
#endif

#if POSCFG_FEATURE_IDLETASKHOOK != 0
static POSIDLEFUNC_t  posIdleTaskFuncHook_g;
#endif

#if (POSCFG_DYNAMIC_MEMORY == 0) && (POSCFG_MAX_TASKS != 0)
STATICBUFFER(posStaticTaskMem_g, sizeof(struct POSTASK), POSCFG_MAX_TASKS);
#endif


#if POSCFG_FEATURE_SOFTINTS != 0

static struct {
  UVAR_t         intno;
  UVAR_t         param;
} softintqueue_g[POSCFG_SOFTINTQUEUELEN + 1];
static POSINTFUNC_t softIntHandlers_g[POSCFG_SOFTINTERRUPTS];
static UVAR_t    sintIdxIn_g;
static UVAR_t    sintIdxOut_g;

#endif /* POSCFG_FEATURE_SOFTINTS */


#if MVAR_BITS == 8
UVAR_t posShift1lTab_g[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
#endif



/*-------------------------------------------------------------------------
 *  ARGUMENT CHECKING (3 different levels possible)
 *-------------------------------------------------------------------------*/

#if MVAR_BITS == 8
#define POSMAGIC_TASK   0x4E
#define POSMAGIC_EVENTU 0x53
#define POSMAGIC_MSGBUF 0x7F
#define POSMAGIC_TIMER  0x14
#elif MVAR_BITS == 16
#define POSMAGIC_TASK   0x4E56
#define POSMAGIC_EVENTU 0x538E
#define POSMAGIC_MSGBUF 0x7FC4
#define POSMAGIC_TIMER  0x1455
#else
#define POSMAGIC_TASK   0x4E56A3FC
#define POSMAGIC_EVENTU 0x538EC75B
#define POSMAGIC_MSGBUF 0x7FC45AA2
#define POSMAGIC_TIMER  0x14552384
#endif
#define POSMAGIC_EVENTF  (~POSMAGIC_EVENTU)

#if POSCFG_ARGCHECK == 0
#define POS_ARGCHECK_RET(ptr, pmagic, magic, ret) \
  do { } while(0)
#define POS_ARGCHECK(ptr, pmagic, magic) \
  do { } while(0)
#elif POSCFG_ARGCHECK == 1
#define POS_ARGCHECK_RET(ptr, pmagic, magic, ret) \
  if ((ptr) == NULL) return (ret)
#define POS_ARGCHECK(ptr, pmagic, magic) \
  if ((ptr) == NULL) return
#else
#define POS_ARGCHECK_RET(ptr, pmagic, magic, ret) \
  if (((ptr) == NULL) || (pmagic != magic)) return (ret)
#define POS_ARGCHECK(ptr, pmagic, magic) \
  if (((ptr) == NULL) || (pmagic != magic)) return
#endif



/*---------------------------------------------------------------------------
 * ROUND ROBIN
 *-------------------------------------------------------------------------*/

#if POSCFG_ROUNDROBIN != 0

static UVAR_t  posNextRoundRobin_g[SYS_TASKTABSIZE_Y];
#define POS_NEXTROUNDROBIN(idx)  posNextRoundRobin_g[idx]

#else  /* ROUNDROBIN */

#define POS_NEXTROUNDROBIN(idx)  0

#endif /* ROUNDROBIN */



/*---------------------------------------------------------------------------
 * PROTOTYPES OF PRIVATE FUNCTIONS
 *-------------------------------------------------------------------------*/

static void      pos_schedule(void);
static void      pos_idletask(void *arg);
#if SYS_FEATURE_EVENTS != 0
static VAR_t     pos_sched_event(EVENT_t ev);
#endif
#if (POSCFG_FEATURE_MSGBOXES != 0) && (POSCFG_MSG_MEMORY == 0)
static MSGBUF_t* pos_msgAlloc(void);
static void      pos_msgFree(MSGBUF_t *mbuf);
#endif
#if POSCFG_FEATURE_SOFTINTS != 0
static void      pos_execSoftIntQueue(void);
#endif
#if POSCFG_FEATURE_LISTS != 0
#if POSCFG_FEATURE_LISTJOIN != 0
static void      pos_listJoin(POSLIST_t *prev, POSLIST_t *next,
                              POSLIST_t *newlist);
#endif
static void      pos_listRemove(POSLIST_t *listelem);
#endif



/*---------------------------------------------------------------------------
 * MACROS
 *-------------------------------------------------------------------------*/

#ifndef POS_IRQ_DISABLE_ALL
#define POS_IRQ_DISABLE_ALL  POS_SCHED_LOCK
#define POS_IRQ_ENABLE_ALL   POS_SCHED_UNLOCK
#else
#define HAVE_IRQ_DISABLE_ALL
#endif

#ifdef POS_DEBUGHELP
#define tasktimerticks(task)  (task)->deb.timeout
#define cleartimerticks(task) (task)->deb.timeout = 0
#else
#define tasktimerticks(task)  (task)->ticks
#define cleartimerticks(task) do { } while(0)
#endif

#if (POSCFG_FEATURE_YIELD != 0) && \
    (POSCFG_ROUNDROBIN != 0) && (SYS_TASKTABSIZE_Y != 1)
#if (MVAR_BITS == 8)
static UVAR_t posZeroMask_g[7] = {0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80};
#define pos_zmask(x)   posZeroMask_g[(UVAR_t)(x)]
#else
#define pos_zmask(x)   (~((pos_shift1l((x) + 1)) - 1))
#endif
#endif


#if SYS_TASKTABSIZE_Y > 1

#define pos_setTableBit(table, task) do { \
    (table)->ymask |= (task)->bit_y; \
    (table)->xtable[(task)->idx_y] |= (task)->bit_x; } while(0)

#define pos_delTableBit(table, task) do { \
    UVAR_t tbt; \
    tbt  = (table)->xtable[(task)->idx_y] & ~(task)->bit_x; \
    (table)->xtable[(task)->idx_y] = tbt; \
    if (tbt == 0) (table)->ymask &= ~(task)->bit_y; } while(0)

#define pos_isTableBitSet(table, task) \
    (((table)->xtable[(task)->idx_y] & (task)->bit_x) != 0)

#else

#define pos_setTableBit(table, task) do { \
    (table)->xtable[0] |= (task)->bit_x; } while(0)

#define pos_delTableBit(table, task) do { \
    (table)->xtable[0] &= ~(task)->bit_x;} while(0)

#define pos_isTableBitSet(table, task) \
    (((table)->xtable[0] & (task)->bit_x) != 0)

#endif

#define pos_addToList(list, elem) do { \
    (elem)->prev = NULL; \
    (elem)->next = list; \
    if (list != NULL) list->prev = elem; \
    list = elem; } while(0)

#define pos_removeFromList(list, elem) do { \
    if ((elem)->next != NULL) (elem)->next->prev = (elem)->prev; \
    if ((elem)->prev != NULL) (elem)->prev->next = (elem)->next; \
    else list = (elem)->next; } while(0)

#if POSCFG_FEATURE_SOFTINTS != 0
#define softIntsPending()  (sintIdxIn_g != sintIdxOut_g)
#define pos_doSoftInts() \
  if (softIntsPending())  pos_execSoftIntQueue();
#else
#define pos_doSoftInts() do { } while(0);
#endif /* POSCFG_FEATURE_SOFTINTS */

#ifndef HOOK_IDLETASK
#define HOOK_IDLETASK
#endif

#ifdef POS_DEBUGHELP
#define pos_taskHistory(debtask) do { \
    picodeb_taskhistory[2] = picodeb_taskhistory[1]; \
    picodeb_taskhistory[1] = picodeb_taskhistory[0]; \
    picodeb_taskhistory[0] = debtask; \
  } while(0)
#else
#define pos_taskHistory(debtask) do { } while(0);
#endif



/*---------------------------------------------------------------------------
 * some HELPER FUNCTIONS  (can be inlined)
 *-------------------------------------------------------------------------*/

#if SYS_TASKDOUBLELINK == 0
#define pos_addToSleepList(task) do { \
    (task)->next = posSleepingTasks_g; \
    posSleepingTasks_g = task; } while(0)
#endif


#if SYS_FEATURE_EVENTS != 0
#if ((POSCFG_FASTCODE==0) || defined(POS_DEBUGHELP)) && (SYS_EVENTS_USED!=0)

static void pos_eventAddTask(EVENT_t ev, POSTASK_t task);
static void pos_eventAddTask(EVENT_t ev, POSTASK_t task)
{
#ifdef POS_DEBUGHELP
  task->deb.event = &ev->e.deb;
#endif
  pos_setTableBit(&ev->e.pend, task);
}

static void pos_eventRemoveTask(EVENT_t ev, POSTASK_t task);
static void pos_eventRemoveTask(EVENT_t ev, POSTASK_t task)
{
#ifdef POS_DEBUGHELP
  task->deb.event = NULL;
#endif
  pos_delTableBit(&ev->e.pend, task);
}

#else
#define pos_eventAddTask(event, curtask) \
          pos_setTableBit(&((event)->e.pend), curtask)
#define pos_eventRemoveTask(event, curtask) \
          pos_delTableBit(&((event)->e.pend), curtask)
#endif
#endif  /* SYS_FEATURE_EVENTS */


#if POSCFG_FASTCODE != 0

#define pos_enableTask(task)    pos_setTableBit(&posReadyTasks_g, task)
#define pos_disableTask(task)   pos_delTableBit(&posReadyTasks_g, task)

#if SYS_TASKDOUBLELINK != 0
#define pos_addToSleepList(task) \
          pos_addToList(posSleepingTasks_g, task)
#define pos_removeFromSleepList(task) \
          pos_removeFromList(posSleepingTasks_g, task)
#endif  /* SYS_TASKDOUBLELINK */

#if POSCFG_FEATURE_TIMER != 0
#define pos_addToTimerList(timer) \
          pos_addToList(posActiveTimers_g, timer)
#define pos_removeFromTimerList(timer) do { \
          pos_removeFromList(posActiveTimers_g, timer); \
          timer->prev = timer; } while (0)
#endif  /* POSCFG_FEATURE_TIMER */

#else /* POSCFG_FASTCODE */

static void pos_disableTask(POSTASK_t task);
static void pos_disableTask(POSTASK_t task)
{
  pos_delTableBit(&posReadyTasks_g, task);
}

static void pos_enableTask(POSTASK_t task);
static void pos_enableTask(POSTASK_t task)
{
  pos_setTableBit(&posReadyTasks_g, task);
}

#if SYS_TASKDOUBLELINK != 0
static void pos_addToSleepList(POSTASK_t task);
static void pos_addToSleepList(POSTASK_t task)
{
  pos_addToList(posSleepingTasks_g, task);
}

static void pos_removeFromSleepList(POSTASK_t task);
static void pos_removeFromSleepList(POSTASK_t task)
{
  pos_removeFromList(posSleepingTasks_g, task);
}
#endif  /* SYS_TASKDOUBLELINK */

#if POSCFG_FEATURE_TIMER != 0
static void pos_addToTimerList(TIMER_t *timer);
static void pos_addToTimerList(TIMER_t *timer)
{
  pos_addToList(posActiveTimers_g, timer);
}

static void pos_removeFromTimerList(TIMER_t *timer);
static void pos_removeFromTimerList(TIMER_t *timer)
{
  pos_removeFromList(posActiveTimers_g, timer);
  timer->prev = timer;
}
#endif  /* POSCFG_FEATURE_TIMER */

#endif  /* POSCFG_FASTCODE */



/*---------------------------------------------------------------------------
 * PRIVATE FUNCTIONS
 *-------------------------------------------------------------------------*/

#ifdef POS_DEBUGHELP
void posdeb_setEventName(void *event, const char *name)
{
  EVENT_t ev = (EVENT_t) event;
  if (ev != NULL) ev->e.deb.name = name;
}
#endif

#if POSCFG_FEATURE_LISTS != 0
#if POSCFG_FEATURE_LISTJOIN != 0
static void pos_listJoin(POSLIST_t *prev, POSLIST_t *next,
                         POSLIST_t *newlist)
{

⌨️ 快捷键说明

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