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 + -
显示快捷键?