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

📄 sys_arch.c

📁 picoos源码。The RTOS and the TCP/IP stack will be built automatically.
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *  Copyright (c) 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.
 *
 */

#include <sys_cfg.h>
#include "lwip/debug.h"
#include "lwip/sys.h"
#include "lwip/opt.h"
#include "lwip/stats.h"

#include <picoos.h>

#define LWIPNAME    "lwIP"
#define SYS_DBLVL   SYS_DEBUG | DBG_LEVEL_WARNING

/*
#ifdef _DBG
#define SYSDEBUG
#endif
*/

/*-----------------------------------------------------------------------------------*/

/* check pico]OS configuration */
#if POS_VER_N < 0x0094
#error Need a newer version of pico]OS.
#endif
#if POSCFG_ROUNDROBIN == 0
#error POSCFG_ROUNDROBIN: You should enable round robin scheduling!
#endif
#if POSCFG_FEATURE_JIFFIES == 0
#error POSCFG_FEATURE_JIFFIES not enabled
#endif
#if POSCFG_FEATURE_SEMAPHORES == 0
#error POSCFG_FEATURE_SEMAPHORES not enabled
#endif
#if POSCFG_FEATURE_SEMADESTROY == 0
#error POSCFG_FEATURE_SEMADESTROY not enabled
#endif
#if POSCFG_FEATURE_SEMAWAIT == 0
#error POSCFG_FEATURE_SEMAWAIT not enabled
#endif
#if POSCFG_FEATURE_INHIBITSCHED == 0
#error POSCFG_FEATURE_INHIBITSCHED not enabled
#endif
#if POSCFG_FEATURE_LISTS == 0
#error POSCFG_FEATURE_LISTS not enabled
#endif
#if POSCFG_TASKCB_USERSPACE == 0
#error POSCFG_TASKCB_USERSPACE not enabled
#endif
#if POSCFG_TASKCB_USERSPACE < (SYS_USRSPACE_OFS + 16)
#error POSCFG_TASKCB_USERSPACE configured too small
#endif
#if (POSCFG_FEATURE_MUTEXES == 0) && (POSCFG_FEATURE_GETTASK == 0)
#error Either POSCFG_FEATURE_MUTEXES or POSCFG_FEATURE_GETTASK must be enabled!
#endif

/* check lwIP configuration */
#if SYS_LIGHTWEIGHT_PROT == 0
#error SYS_LIGHTWEIGHT_PROT must be set to 1 in lwipopts.h !!
#endif

/*-----------------------------------------------------------------------------------*/

#define BUF_MAX_SEM   2
#define BUF_MAX_MBOX  2

#if SYS_MSG_MAX < 16
#define SYS_MAX_MAIL  16
#else
#define SYS_MAX_MAIL  SYS_MSG_MAX
#endif
#if SYS_MAX_MAIL < (8*4)
#define MAIL_THRESHOLD  (SYS_MAX_MAIL - (SYS_MAX_MAIL/4))
#else
#define MAIL_THRESHOLD  (SYS_MAX_MAIL - 8)
#endif
#ifndef SYS_TCPIPMBOXFIX
#define SYS_TCPIPMBOXFIX  0
#endif
#if SYS_TCPIPMBOXFIX
#include "lwip/tcpip.h"
#endif

#define SYS_MAX_MAILBOX (SYS_MBOX_MAX + BUF_MAX_MBOX)

/*-----------------------------------------------------------------------------------*/

struct sys_mbox {
  union {
    struct sys_mbox  *next;
    POSLISTHEAD_t listhead;
  } m;
  JIF_t lasttime;
#ifdef SYSDEBUG
  u32_t magic;
  POSTASK_t  task;
#endif
};
#define MMAGIC 0x45634219

#if SYS_TCPIPMBOXFIX
struct sys_tcpipmbox {
  struct sys_mbox  m;
  POSLISTHEAD_t highPrioList;
};
#endif

struct mail {
  POSLIST_t list;
  union {
    struct mail *next;
    void        *payload;
  } l;
#ifdef SYSDEBUG
 struct sys_mbox* volatile mbox;
#endif
#if SYS_TCPIPMBOXFIX
  POSLIST_t list2;
#endif
};

#if SYS_TCPIPMBOXFIX
static struct sys_tcpipmbox         tcpipmbox_g;
static struct sys_tcpipmbox         *p_tcpipmbox_g;
#endif
static struct sys_mbox              mbox_memory_g[SYS_MAX_MAILBOX];
static struct mail                  mail_memory_g[SYS_MAX_MAIL];

static struct sys_sem*              mail_sem_g;
static INT_t              volatile  mail_waiting_g;

#if BUF_MAX_SEM > 0
static struct sys_sem*              semabuffer_g[BUF_MAX_SEM];
static INT_t                        semabufLast_g;
#endif

#if BUF_MAX_MBOX > 0
static struct sys_mbox*             mboxbuffer_g[BUF_MAX_MBOX];
static INT_t                        mboxbufLast_g;
#endif

static struct sys_mbox*   volatile  unused_mbox_list_g;
static struct mail*       volatile  unused_mail_list_g;
static UINT_t             volatile  max_used_mboxes_g;
static UINT_t             volatile  max_used_mails_g;
static UINT_t             volatile  cur_used_mails_g;
#ifdef SYSDEBUG
static UINT_t             volatile  cur_used_mboxes_g;
#endif

#if POSCFG_FEATURE_MUTEXES
static POSMUTEX_t                   sysprotMutex_g;
#else
static POSSEMA_t                    sysprotSemaphore_g;
static POSTASK_t                    sysprotLastTask_g;
static UINT_t                       sysprotLockCntr_g;
#endif

#if (POSCFG_ENABLE_NANO == 0) && (POSCFG_TASKSTACKTYPE == 0)
static UVAR_t volatile  no_of_tasks_g = 0;
static UVAR_t stackmem_g[SYS_THREAD_MAX * (SYS_STACK_SIZE / sizeof(UVAR_t))];
#endif

#if POSCFG_ENABLE_NANO
#define SCHED_LOCK()        nosTaskSchedLock();
#define SCHED_UNLOCK()      nosTaskSchedUnlock();
#else
#define SCHED_LOCK()        posTaskSchedLock();
#define SCHED_UNLOCK()      posTaskSchedUnlock();
#endif


/*-----------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
struct sys_sem *
sys_sem_new(u8_t count)
{
#if POSCFG_ENABLE_NANO
  NOSSEMA_t sem;
  sem = nosSemaCreate((INT_t) count, 0, LWIPNAME "-*");
#else
  POSSEMA_t sem;
  sem = posSemaCreate((INT_t) count);
  POS_SETEVENTNAME(sem, LWIPNAME);
#endif
  if (sem == NULL)
  {
    LWIP_DEBUGF(SYS_DBLVL, ("WARNING: sys_arch.c: out of pico]OS semaphores(1),"
                            " please increase POSCFG_MAX_EVENTS\n" ));
  }
#if SYS_STATS
  SCHED_LOCK();
  if (sem != NULL)
  {
    lwip_stats.sys.sem.used++;
    if (lwip_stats.sys.sem.used > lwip_stats.sys.sem.max)
      lwip_stats.sys.sem.max = lwip_stats.sys.sem.used;
  }
  else
  {
    lwip_stats.sys.sem.err++;
  }
  SCHED_UNLOCK();
#endif /* SYS_STATS */
  return (struct sys_sem*) sem;
}
/*-----------------------------------------------------------------------------------*/
void
sys_sem_free(struct sys_sem *sem)
{
  struct sys_sem* fsem;

  if (sem != NULL)
  {
    SCHED_LOCK();

#if BUF_MAX_SEM > 0
    /* Small work-around for some lwIP race conditions:
       We delay the freeing of the semaphore a bit. */
    fsem = semabuffer_g[semabufLast_g];
    semabuffer_g[semabufLast_g] = sem;
    if (++semabufLast_g >= BUF_MAX_SEM)
      semabufLast_g = 0;
#else
    fsem = sem;
#endif

#if SYS_STATS
    lwip_stats.sys.sem.used--;
#endif /* SYS_STATS */
    SCHED_UNLOCK();

    if (fsem != NULL)
#if POSCFG_ENABLE_NANO
      nosSemaDestroy((NOSSEMA_t) fsem);
#else
      posSemaDestroy((POSSEMA_t) fsem);
#endif
  }
}
/*-----------------------------------------------------------------------------------*/
void
sys_sem_signal(struct sys_sem *sem)
{
  if (sem != NULL)
  {
#if POSCFG_ENABLE_NANO
    nosSemaSignal((NOSSEMA_t) sem);
#else
    posSemaSignal((POSSEMA_t) sem);
#endif
  }
}
/*-----------------------------------------------------------------------------------*/
u32_t
sys_arch_sem_wait(struct sys_sem *sem, u32_t timeout)
{
  VAR_t status;
  JIF_t start;
  u32_t w;

  if (sem == NULL)
    return 0;

  start = jiffies;

#if POSCFG_ENABLE_NANO
  status = nosSemaWait( (NOSSEMA_t) sem, 
                        (timeout == 0) ? INFINITE : (UINT_t) MS(timeout) );
#else
  status = posSemaWait( (POSSEMA_t) sem, 
                        (timeout == 0) ? INFINITE : (UINT_t) MS(timeout) );
#endif
  if (status > 0)
    return SYS_ARCH_TIMEOUT;

  /* Calculate the waited time. We make sure that the calculated 
     time is never zero. Otherwise, when there is high traffic on
     this semaphore, this function may always return with zero
     and a sys.c-timer may never expire. */
  w = (u32_t) (jiffies - start) * 1000;
  w = w / HZ;
  if (w < (1000 / HZ))
    w = (HZ < 500) ? (500 / HZ) : 1;
  return (w < timeout) ? w : timeout;
}
/*-----------------------------------------------------------------------------------*/
struct sys_mbox *
sys_mbox_new()
{
  struct sys_mbox *mbox;

  SCHED_LOCK();
#if SYS_TCPIPMBOXFIX
  if (p_tcpipmbox_g == NULL)
  {
    p_tcpipmbox_g = &tcpipmbox_g;
    posListInit(&p_tcpipmbox_g->highPrioList);
    mbox = (struct sys_mbox*) p_tcpipmbox_g;
  }
  else
#endif
  {
    mbox = unused_mbox_list_g;
    if (mbox != NULL)
    {
      unused_mbox_list_g = mbox->m.next;
    }
    else
    if (max_used_mboxes_g < SYS_MAX_MAILBOX)
    {
      mbox = &mbox_memory_g[max_used_mboxes_g];
      max_used_mboxes_g++;
    }
#ifdef SYSDEBUG
    if (mbox != NULL)
    {
      cur_used_mboxes_g++;
      mbox->magic = MMAGIC;
    }
#endif
  }
  SCHED_UNLOCK();

  if (mbox != NULL)
  {
    posListInit(&mbox->m.listhead);
    mbox->lasttime = jiffies;
#ifdef SYSDEBUG
    mbox->task = posTaskGetCurrent();
#endif
#if SYS_STATS
    SCHED_LOCK();
    lwip_stats.sys.mbox.used++;
    if (lwip_stats.sys.mbox.used > lwip_stats.sys.mbox.max)
      lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used;
    SCHED_UNLOCK();
#endif /* SYS_STATS */
  }
  else
  {
    LWIP_DEBUGF(SYS_DBLVL, ("WARNING: sys_arch.c: out of mailboxes,"
                            " please increase SYS_MBOX_MAX\n" ));
#if SYS_STATS
    SCHED_LOCK();
    lwip_stats.sys.mbox.err++;
    SCHED_UNLOCK();
#endif /* SYS_STATS */
  }
  return mbox;
}
/*-----------------------------------------------------------------------------------*/
void
sys_mbox_free(struct sys_mbox *mbox)
{
  struct sys_mbox *fmb;
  struct mail *m;
  POSLIST_t   *l;

#if BUF_MAX_MBOX > 0
  /* Small work-around for some lwIP race conditions:
     We delay the freeing of the mailbox a bit. */
  SCHED_LOCK();
  fmb = mboxbuffer_g[mboxbufLast_g];
  mboxbuffer_g[mboxbufLast_g] = mbox;
  if (++mboxbufLast_g >= BUF_MAX_MBOX)
    mboxbufLast_g = 0;
  SCHED_UNLOCK();
#else
  fmb = mbox;
#endif

  if (fmb != NULL)

⌨️ 快捷键说明

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