sys_arch.c
来自「NXPl788上lwip的无操作系统移植,基于Embest开发板」· C语言 代码 · 共 598 行 · 第 1/2 页
C
598 行
/* Allocate memory for queue */
p_queue_mem = (u32_t *) calloc(1,(SYS_MBOX_SIZE * sizeof(u32_t)));
if (p_queue_mem)
{
/* Allocate memory for queue control block */
p_queue = (NU_QUEUE *) calloc(1,sizeof(NU_QUEUE));
if (p_queue)
{
/* Create a unique name for mbox based on number created */
num_mbox = (num_mbox + 1) % 100;
sprintf(queue_name, "lwip%02d", num_mbox);
queue_name[strlen(queue_name)] = ' ';
NU_Create_Queue(p_queue,
queue_name,
p_queue_mem,
SYS_MBOX_SIZE,
NU_FIXED_SIZE,
1,
NU_FIFO);
#ifdef SYS_STATS
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;
}
#endif /* SYS_STATS */
return p_queue;
}
else
free(p_queue_mem);
}
return SYS_MBOX_NULL;
}
/*---------------------------------------------------------------------------------*/
void
sys_mbox_free(sys_mbox_t mbox)
{
VOID *p_queue_mem;
CHAR name[8];
UNSIGNED queue_size;
UNSIGNED available;
UNSIGNED messages;
OPTION message_type;
UNSIGNED message_size;
OPTION suspend_type;
UNSIGNED tasks_waiting;
NU_TASK *first_task;
STATUS status;
if (mbox != SYS_MBOX_NULL)
{
/* First we need to get address of queue memory. Ask Nucleus
for information about the queue */
status = NU_Queue_Information(mbox,
name,
&p_queue_mem,
&queue_size,
&available,
&messages,
&message_type,
&message_size,
&suspend_type,
&tasks_waiting,
&first_task);
if (status == NU_SUCCESS)
free(p_queue_mem);
NU_Delete_Queue(mbox);
free(mbox);
#ifdef SYS_STATS
lwip_stats.sys.mbox.used--;
#endif /* SYS_STATS */
}
}
/*---------------------------------------------------------------------------------
This function sends a message to a mailbox. It is unusual in that no error
return is made. This is because the caller is responsible for ensuring that
the mailbox queue will not fail. The caller does this by limiting the number
of msg structures which exist for a given mailbox.
---------------------------------------------------------------------------------*/
void
sys_mbox_post(sys_mbox_t mbox, void *msg)
{
UNSIGNED status;
LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_post: mbox %p msg %p\n", mbox, msg));
status = NU_Send_To_Queue(mbox,
&msg,
1,
NU_NO_SUSPEND);
LWIP_ASSERT("sys_mbox_post: mbx post failed", status == NU_SUCCESS);
}
/*---------------------------------------------------------------------------------*/
u32_t
sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout)
{
UNSIGNED timestart, timespent;
STATUS status;
void *ret_msg;
UNSIGNED actual_size;
/* Get the current time */
timestart = NU_Retrieve_Clock();
/* Wait for message */
status = NU_Receive_From_Queue(mbox,
&ret_msg,
1,
&actual_size,
timeout ? MS_TO_TICKS(timeout) : NU_SUSPEND);
if (status == NU_SUCCESS)
{
if (msg)
*msg = ret_msg;
LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p msg %p\n", mbox, ret_msg));
} else {
if (msg)
*msg = 0;
if (status == NU_TIMEOUT)
LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: timeout on mbox %p\n", mbox));
else
LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: Queue Error %i on mbox %p\n", status, mbox));
}
/* 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;
}
/*---------------------------------------------------------------------------------*/
static void
sys_arch_lisr(INT vector_number)
{
struct sys_hisr *p_hisr = hisrs;
/* Determine which HISR to activate */
while (p_hisr != NULL)
{
if (vector_number == p_hisr->vector)
{
if (p_hisr->disablefun)
(*p_hisr->disablefun)();
NU_Activate_HISR(p_hisr->hisr);
break;
}
p_hisr = p_hisr->next;
}
return;
}
/*---------------------------------------------------------------------------------*/
void
sys_setvect(u32_t vector, void (*isr_function)(void), void (*dis_funct)(void))
{
/* The passed function is called as a high level ISR on the selected vector.
It is assumed that all the functions in this module can be called by the
isr_function.
*/
struct sys_hisr *p_hisr = hisrs;
INT old_level;
NU_HISR *nucleus_hisr;
u8_t *p_stack;
STATUS status;
char hisr_name[8] = " ";
void (*old_lisr)(INT);
/* In this case a Nucleus HISR is created for the isr_function. This
* requires it's own stack. Also get memory for Nucleus HISR. */
nucleus_hisr = (NU_HISR *) calloc(1,sizeof(NU_HISR));
if (nucleus_hisr)
{
p_stack = (u8_t *) malloc(SYS_HISR_STACK_SIZE);
if (p_stack)
{
/* It is most efficient to disable interrupts for Nucleus for a short
time. Chances are we are doing this while interrupts are disabled
already during system initialization.
*/
old_level = NU_Control_Interrupts(NU_DISABLE_INTERRUPTS);
/* It is a simplification here that once an HISR is set up for a particular
* vector it will never be set up again. This way if the init code is called
* more than once it is harmless (no memory leaks)
*/
while (p_hisr != NULL)
{
if (vector == p_hisr->vector)
{
NU_Control_Interrupts(old_level);
free(p_stack);
free(nucleus_hisr);
return;
}
p_hisr = p_hisr->next;
}
/* Get a sys_hisr structure */
p_hisr = (struct sys_hisr *) calloc(1,sizeof(struct sys_hisr));
if (p_hisr)
{
p_hisr->next = hisrs;
p_hisr->vector = vector;
p_hisr->hisr = nucleus_hisr;
p_hisr->disablefun = dis_funct;
hisrs = p_hisr;
NU_Control_Interrupts(old_level);
num_hisr = (num_hisr + 1) % 100;
sprintf(hisr_name, "lwip%02d", num_hisr);
hisr_name[strlen(hisr_name)] = ' ';
/* Ask Nucleus to create the HISR */
status = NU_Create_HISR(p_hisr->hisr,
hisr_name,
isr_function,
1, //Priority 0-2
p_stack,
SYS_HISR_STACK_SIZE);
if (status == NU_SUCCESS)
{
/* Plug vector with system lisr now */
NU_Register_LISR(vector, sys_arch_lisr, &old_lisr);
return; //Success
}
}
NU_Control_Interrupts(old_level);
}
}
/* Errors should be logged here */
abort();
}
/*---------------------------------------------------------------------------------*/
/** sys_prot_t sys_arch_protect(void)
This optional function does a "fast" critical region protection and returns
the previous protection level. This function is only called during very short
critical regions. An embedded system which supports ISR-based drivers might
want to implement this function by disabling interrupts. Task-based systems
might want to implement this by using a mutex or disabling tasking. This
function should support recursive calls from the same task or interrupt. In
other words, sys_arch_protect() could be called while already protected. In
that case the return value indicates that it is already protected.
sys_arch_protect() is only required if your port is supporting an operating
system.
*/
sys_prot_t
sys_arch_protect(void)
{
return NU_Control_Interrupts(NU_DISABLE_INTERRUPTS);
}
/*---------------------------------------------------------------------------------*/
/** void sys_arch_unprotect(sys_prot_t pval)
This optional function does a "fast" set of critical region protection to the
value specified by pval. See the documentation for sys_arch_protect() for
more information. This function is only required if your port is supporting
an operating system.
*/
void
sys_arch_unprotect(sys_prot_t pval)
{
NU_Control_Interrupts(pval);
}
/*********************************************************************
* void sys_get_eth_addr(struct eth_addr *eth_addr)
*
* Get configured ethernet address from nvram and return it
* in a eth_addr structure.
*********************************************************************/
void
sys_get_eth_addr(struct eth_addr *eth_addr)
{
Cfg_lan *p_lan = config_get_lan_setup();
eth_addr->addr[0] = (u8_t) ((p_lan->etheraddrhi >> 16) & 0xff);
eth_addr->addr[1] = (u8_t) ((p_lan->etheraddrhi >> 8) & 0xff);
eth_addr->addr[2] = (u8_t) ((p_lan->etheraddrhi) & 0xff);
eth_addr->addr[3] = (u8_t) ((p_lan->etheraddrlo >> 16) & 0xff);
eth_addr->addr[4] = (u8_t) ((p_lan->etheraddrlo >> 8) & 0xff);
eth_addr->addr[5] = (u8_t) ((p_lan->etheraddrlo) & 0xff);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?