sys_arch.c

来自「NXPl788上lwip的无操作系统移植,基于Embest开发板」· C语言 代码 · 共 598 行 · 第 1/2 页

C
598
字号
/* @(#)sys_arch.c
 * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
 * 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.
 *
 * This file is part of the lwIP TCP/IP stack.
 * 
 * Author: David Haas   <dhaas@alum.rpi.edu>
 *
 */

#include "lwip/debug.h"

#include "lwip/sys.h"
#include "lwip/opt.h"
#include "lwip/stats.h"

#include "nucleus.h"
#include "config.h"
#include <stdlib.h>
#include <string.h>

struct sys_thread {
    struct sys_thread *next;
    struct sys_timeouts timeouts;
    int errno_i;
    NU_TASK *pthread;
    void (*function)(void *arg);
    void *arg;
};

struct sys_hisr 
{
    struct sys_hisr *next;
    NU_HISR *hisr;
    void (*disablefun) (void);
    u32_t vector;
};

static int num_sem = 0;                 // Number of semaphores created
static int num_mbox = 0;                // Number of mailboxes created
static int num_thread = 0;              // Number of threads created
static int num_hisr = 0;                // Number of hisrs created
static struct sys_thread *threads = NULL;
static struct sys_hisr *hisrs = NULL;

#define TICKS_PER_SECOND 10000
#define MS_TO_TICKS(MS) (MS * (TICKS_PER_SECOND / 1000))
#define TICKS_TO_MS(TICKS) ((unsigned long)((1000ULL * TICKS) / TICKS_PER_SECOND))
#define TICKS_TO_HUNDMICROSEC(TICKS) TICKS

#define SYS_MBOX_SIZE 128               // Number of elements in mbox queue
#define SYS_STACK_SIZE 2048             // A minimum Nucleus stack for coldfire
#define SYS_HISR_STACK_SIZE 2048             // A minimum Nucleus stack for coldfire

/*---------------------------------------------------------------------------------*/
void
sys_init(void)
{
    return;
}

/*---------------------------------------------------------------------------------*/
static void
sys_thread_entry(UNSIGNED argc, VOID *argv)
{
    /* argv is passed as a pointer to our thread structure */
    struct sys_thread *p_thread = (struct sys_thread *)argv;

    p_thread->function(p_thread->arg);
}

/*---------------------------------------------------------------------------------*/
static struct sys_thread * 
introduce_thread(NU_TASK *id, void (*function)(void *arg), void *arg)
{
  struct sys_thread *thread;
  sys_prot_t old_level;
  
  thread = (struct sys_thread *) calloc(1,sizeof(struct sys_thread));
    
  if (thread) {
      old_level = sys_arch_protect();
      thread->next = threads;
      thread->timeouts.next = NULL;
      thread->pthread = id;
      thread->function = function;
      thread->arg = arg;
      threads = thread;
      sys_arch_unprotect(old_level);
  }
    
  return thread;
}

/*---------------------------------------------------------------------------------*/
/* We use Nucleus task as thread. Create one with a standard size stack at a standard
 * priority. */
sys_thread_t
sys_thread_new(char *name, void (* function)(void *arg), void *arg, int stacksize, int prio)
{
    NU_TASK *p_thread;
    u8_t *p_stack;
    STATUS status;
    char thread_name[8] = "        ";
    struct sys_thread *st;
    
    /** @todo Replace SYS_STACK_SIZE by "stacksize" parameter, perhaps use "name" if it is prefered */
    
    p_stack = (u8_t *) malloc(SYS_STACK_SIZE);
    if (p_stack)
    {
        p_thread = (NU_TASK *) calloc(1,sizeof(NU_TASK));
        if (p_thread)
        {
            /* get a new thread structure */
            st = introduce_thread(p_thread, function, arg);
            if (st)
            {
                num_thread = (num_thread +1) % 100; // Only count to 99
                sprintf(thread_name, "lwip%02d", num_thread);
                thread_name[strlen(thread_name)] = ' ';
                
                status = NU_Create_Task(p_thread,
                                        thread_name,
                                        sys_thread_entry,
                                        0,
                                        st,
                                        p_stack,
                                        SYS_STACK_SIZE,
                                        prio,
                                        0,                          //Disable timeslicing
                                        NU_PREEMPT,
                                        NU_START);
                if (status == NU_SUCCESS)
                    return p_thread;
            }
            
        }
    }
    abort();
}

/*-----------------------------------------------------------------------------------*/
static struct sys_thread *
current_thread(void)
{
    struct sys_thread *st;
    sys_prot_t old_level;
    NU_TASK *pt;
    
    pt = NU_Current_Task_Pointer();
    old_level = sys_arch_protect();
    
    for(st = threads; st != NULL; st = st->next)
    {    
        if (st->pthread == pt)
        {
            sys_arch_unprotect(old_level);
            return st;
        }
    }

    sys_arch_unprotect(old_level);
    st = introduce_thread(pt, 0, 0);
    
    if (!st) {
        abort();
    }

    return st;
}


/*---------------------------------------------------------------------------------*/
struct sys_timeouts *
sys_arch_timeouts(void)
{
    struct sys_thread *thread;

    thread = current_thread();
    return &thread->timeouts;
}
/*---------------------------------------------------------------------------------*/
int *
sys_arch_errno(void)
{
    struct sys_thread *thread;

    thread = current_thread();
    return &thread->errno_i;
}

/*---------------------------------------------------------------------------------*/
sys_sem_t
sys_sem_new(u8_t count)
{
    STATUS status;
    NU_SEMAPHORE *sem;
    char sem_name[8] = "        ";

#ifdef SYS_STATS
    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;
    }
#endif /* SYS_STATS */
    
    /* Get memory for new semaphore */
    sem = (NU_SEMAPHORE *) calloc(1,sizeof(NU_SEMAPHORE));

    if (sem)
    {
        /* Create a unique name for semaphore based on number created */
        num_sem = (num_sem + 1) % 100;  // Only count to 99
        sprintf(sem_name, "lwip%02d", num_sem);
        sem_name[strlen(sem_name)] = ' ';

        /* Ask nucleus to create semaphore */
        NU_Create_Semaphore(sem,
                            sem_name,
                            count,
                            NU_FIFO);
    }
    return sem;
}

/*---------------------------------------------------------------------------------*/
void
sys_sem_free(sys_sem_t sem)
{
    if (sem != SYS_SEM_NULL)
    {
#ifdef SYS_STATS
        lwip_stats.sys.sem.used--;
#endif /* SYS_STATS */
        NU_Delete_Semaphore(sem);
        free(sem);
    }
}

/*---------------------------------------------------------------------------------*/
void
sys_sem_signal(sys_sem_t sem)
{
    NU_Release_Semaphore(sem);
}

/*---------------------------------------------------------------------------------*/
u32_t
sys_arch_sem_wait(sys_sem_t sem, u32_t timeout)
{
    UNSIGNED timestart, timespent;
    STATUS status;

    /* Get the current time */
    timestart = NU_Retrieve_Clock();
    /* Wait for the semaphore */
    status = NU_Obtain_Semaphore(sem,
                                 timeout ? MS_TO_TICKS(timeout) : NU_SUSPEND);
    /* This next statement takes wraparound into account. It works. Really! */
    timespent = TICKS_TO_HUNDMICROSEC(((s32_t) ((s32_t) NU_Retrieve_Clock() - (s32_t) timestart)));
    
    if (status == NU_TIMEOUT)
        return SYS_ARCH_TIMEOUT;
    else
        /* Round off to milliseconds */
        return (timespent+5)/10;
}

/*---------------------------------------------------------------------------------*/
sys_mbox_t
sys_mbox_new(void)
{
    u32_t *p_queue_mem;
    NU_QUEUE *p_queue;
    char queue_name[8] = "        ";

⌨️ 快捷键说明

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