diff riviera/rvf/rvf_task.c @ 0:75a11d740a02

initial import of gsm-fw from freecalypso-sw rev 1033:5ab737ac3ad7
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 09 Jun 2016 00:02:41 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/riviera/rvf/rvf_task.c	Thu Jun 09 00:02:41 2016 +0000
@@ -0,0 +1,1177 @@
+/****************************************************************************/
+/*                                                                          */
+/*  Name        rvf_task.c                                                  */
+/*                                                                          */
+/*  Function    this file contains \rvf task related functions               */
+/*                                                                          */
+/*  Version		0.1															*/
+/*																			*/
+/* 	Date       	Modification												*/
+/*  ------------------------------------									*/
+/*  3/12/99		Create														*/
+/*	10/27/99	remove all non-nucleus sections (#ifdef)					*/
+/*				change tasks priority and time_slicing						*/	
+/*  11/17/1999	change RVF_create_task and RVF_get_taskid functions         */
+/*	30/11/99	compliant to RV coding guidelines							*/
+/*  28/08/2000	add mutex related functions.								*/
+/*																			*/
+/*	Author		David Lamy-Charrier (dlamy@tif.ti.com)						*/
+/*																			*/
+/* (C) Copyright 1999 by Texas Instruments Incorporated, All Rights Reserved*/
+/****************************************************************************/
+
+#include "../../include/config.h"
+
+#include "../rv/rv_general.h"
+#include "rvf_api.h"
+#include "rvf_i.h"			
+#include "../rvm/rvm_i.h"	 /* ONLY for Task Codes */
+#include "../rvm/rvm_use_id_list.h"
+
+#include "../../nucleus/nucleus.h"
+
+#include <stdio.h>
+#include <string.h>
+
+/* include the rvtool_trace.h file only in the RivieraTool */
+#ifdef	_WINDOWS
+#ifndef	_CONSOLE
+//		#include "rvtool_trace.h"
+	#endif
+	#include <windows.h>
+#endif
+
+#define RVF_STATIC_ALLOC_NB	1
+
+/**********************************************************************
+** Nucleus specific definitions
+*/
+
+typedef void (*NU_TASK_ENTRY)(UNSIGNED, VOID *);  //
+
+/* array of tasks */
+/**********************************************************************
+* Note: if dynamic mem alloc of "pOSTCB" creates too much fragentation
+* The origianl way me be utilised and pointed to by a addr_id table 
+* structure, which is proposed for type 2 support.
+***********************************************************************/
+
+#define _RALLOC_TASK_CNTRL_BLK(tb)		rvf_get_buf(rvm_sys_mem_bank, sizeof(NU_TASK), tb)
+#define	_RALLOC_TASK_EVT_GRP(tb)		rvf_get_buf(rvm_sys_mem_bank, sizeof(NU_EVENT_GROUP), tb)
+#define _RALLOC_TASK_RT_ADDR_DATA(tb)	rvf_get_buf(rvm_sys_mem_bank, sizeof(T_RVF_RT_ADDR_ID_DATA), tb)
+//#define _RALLOC_TASK_RT_TM(tb)			rvf_get_buf(rvm_sys_mem_bank, sizeof(T_RVF_TIMER_LIST_Q), tb)
+
+/*static NU_TASK			bOSTCB[RVF_STATIC_ALLOC_NB];			 
+static NU_EVENT_GROUP	bOSEvtGrp[RVF_STATIC_ALLOC_NB];			 
+static UINT8			*bOSStack;
+static UINT16			bOSStackSize;
+static char				bOSTName[RVF_STATIC_ALLOC_NB][RVF_STATIC_ALLOC_NB];
+*/
+
+static UINT8	task_counter = 0;	
+static INT16	OSDisableNesting = 0;
+static BOOL		OSInterruptAlreadyMasked = FALSE;
+static INT32    OSLastIntLevel;
+static T_RVF_G_ADDR_ID _RDV=RVF_INVALID_ADDR_ID;
+
+T_RVF_RET		_initSysRtData(void);
+
+
+/*******************************************************************************
+**
+** Function         rvf_AllocTaskXyz()
+**
+** Description      
+**                  
+**
+** Returns          T_RVF_MB_STATUS
+**
+*******************************************************************************/
+T_RVF_RET _initSysRtData(void) {    /*A-M-E-N-D-E-D!*/
+	int i=0;
+
+	for (i=0; i < MAX_RVF_G_ADDR_ID; i++) pRtAddrIdTable[i]=NULL;
+
+	//	pOSTCB[0]=&OSTCB[0];
+	return RVF_OK;
+}
+
+/*******************************************************************************
+**
+** Function         rvf_init
+**
+** Description      This function is called once at startup to initialize
+**                  all the rvf (timer, buffer...).
+**
+** Returns          void
+**
+*******************************************************************************/
+void rvf_init(void) {
+	/* UINT8   i;	*/
+
+    /* Initialize RVF variables */
+    /*for (i = 0; i < MAX_RVF_TASKS; i++) {
+        OSStack[i] = 0;
+        OSStackSize[i] = 0;
+        OSTName[i][0] = 0;
+		memset( &OSTCB[i],		0, sizeof(NU_TASK) );
+		memset( &OSEvtGrp[i],	0, sizeof(NU_EVENT_GROUP) );
+    }
+	//	for (i = 0; i < 1; i++) memset( &OSTCB[i], 0, sizeof(NU_TASK) );
+	*/
+	_initSysRtData();
+	_rvf_buffer_init();
+	_rvf_timers_init();
+}
+
+/*******************************************************************************
+**
+** Function         _rvf_name_cpy
+**
+** Description      Internal function which copy a string in a buffer.
+**                  The string may be null-terminated or length bytes long.
+**
+** Returns          void
+**
+*******************************************************************************/
+void _rvf_name_cpy(char * dest, char * source, UINT8 length) {	
+	UINT8 cpt;
+	for( cpt = 0; cpt < length ; cpt++) {
+		dest[cpt] = source[cpt];
+		if (source[cpt] == 0) {	return;}
+	}
+}
+
+T_RVF_G_ADDR_ID rvf_get_context() {
+	T_RVF_G_ADDR_ID gid=rvf_get_taskid();
+	if(pRtAddrIdTable[gid]->type_code==ET2_HOST_TASK) {
+		return pRtAddrIdTable[gid]->virtualContext;
+	} else {
+		return pRtAddrIdTable[gid]->host_addr_id;
+	}
+}
+
+void rvf_setRDV(T_RVF_G_ADDR_ID tid,T_RVF_G_ADDR_ID vid) { 	
+	if(pRtAddrIdTable[tid])	pRtAddrIdTable[tid]->virtualContext=vid;
+}
+
+
+/**************************************************************
+*	Function         _rvf_name_cpy
+*
+***************************************************************/
+T_RVF_G_ADDR_ID rvf_allocate_task_id(UINT8 isRealTask) {
+	T_RVF_G_ADDR_ID i=0;
+	UINT8 isTask=1;
+
+	/* Note: differentiation is made between REAL and VIRTUAL IDs
+	 * to provide for backwards compatabible LEGACY timer implementations
+	 * The Real task ids should be in sync with:
+	 * "static rvf_Timer[MAX_RVF_TASKS][RVF_NUM_TASK_TIMERS]",
+	 * defined in "rvf_time.c". In the future, one NU_Timer blk will
+	 * be pointed to in the rt global addr table. Hence, eliminating 
+	 * the large resource of "rvf_Timer[][]"
+	 */
+	if(!pRtAddrIdTable[i]) return RVF_INVALID_ADDR_ID;
+
+	if(isRealTask) {
+		/* REAL TASK									*/
+		for(i=0; pRtAddrIdTable[i]!=NULL && i<MAX_RVF_TASKS; i++);
+
+		if (i < MAX_RVF_TASKS)	{ /* alloc. and init. */ 
+			if(_RALLOC_TASK_RT_ADDR_DATA((T_RVF_BUFFER**)&pRtAddrIdTable[i])) return RVF_INVALID_TASK;
+			memset( pRtAddrIdTable[i], 0, sizeof(T_RVF_RT_ADDR_ID_DATA) );
+			rvf_mbox_buffer_init(pRtAddrIdTable[i]);
+
+		} else	return RVF_INVALID_ADDR_ID;
+	} else {
+		/* VIRTUAL TASK				*/
+		for(i=MAX_RVF_TASKS; pRtAddrIdTable[i]!=NULL && i<MAX_RVF_G_ADDR_ID; i++);
+
+		if (i < MAX_RVF_G_ADDR_ID)	{ /* alloc. and init. */ 
+			if(_RALLOC_TASK_RT_ADDR_DATA((T_RVF_BUFFER**)&pRtAddrIdTable[i])) return RVF_INVALID_TASK;
+			memset( pRtAddrIdTable[i], 0, sizeof(T_RVF_RT_ADDR_ID_DATA) );
+			rvf_mbox_buffer_init(pRtAddrIdTable[i]);
+
+		} else	return RVF_INVALID_ADDR_ID;
+	}
+	
+	return  i;
+}
+
+/* MUST RESOLVE ERROR CODES '1' is just for P of C */
+T_RVF_RET rvf_setRtAddrSweIndex(T_RVF_G_ADDR_ID id, UINT8 sweIndex) {
+	if(id>=MAX_RVF_G_ADDR_ID) return 1;
+	pRtAddrIdTable[id]->swe_db_index=sweIndex;
+//	pRtAddrIdTable[id]->type_code=tcode; /* allows type to be set if not in swe */
+	return RVF_OK;
+}
+
+T_RVF_RET rvf_setHostTaskStackPtr(T_RVF_G_ADDR_ID id, UINT8* pStack) { /* deprecated ! */
+	if(id>=MAX_RVF_TASKS) return 1;
+	pRtAddrIdTable[id]->p_os_stack=pStack;
+
+	return RVF_OK;
+}
+
+T_RVF_RET rvf_isHostingTaskIdle(T_RVF_G_ADDR_ID id, UINT8* status) { /* deprecated ! */
+	if(id>=MAX_RVF_TASKS)	return RVF_INVALID_PARAMETER;
+	if(!pRtAddrIdTable[id])	return RVF_INVALID_PARAMETER;
+	if(pRtAddrIdTable[id]->type_code!=ET2_HOST_TASK) return RVF_INVALID_PARAMETER;
+
+	if(pRtAddrIdTable[id]->hosting_count==0) *status=1;
+	return RVF_OK;
+}
+
+/* convenience/helper fnc. */
+T_RVF_G_ADDR_ID resolveHostAddrId(T_RVF_G_ADDR_ID id) { 
+	if(!pRtAddrIdTable[id]) return RVF_INVALID_ADDR_ID;
+	return pRtAddrIdTable[id]->host_addr_id;
+}
+
+/* HostingCounter enables one to deduce if task can be terminated	*/
+/* ERROR return val must be revised									*/
+T_RVF_RET rvf_registerToHost(T_RVF_G_ADDR_ID host_id, T_RVF_G_ADDR_ID eid) {
+	UINT8 i;
+
+	if (host_id >= MAX_RVF_TASKS || eid >= MAX_RVF_G_ADDR_ID )  return RV_INVALID_PARAMETER;; 
+
+	for(i=0;pRtAddrIdTable[host_id]->parasites[i]!=0 && i < MAX_PARASITES; i++);
+
+		pRtAddrIdTable[host_id]->parasites[i]=eid;
+		pRtAddrIdTable[host_id]->hosting_count++;
+
+	return RVF_OK;
+}
+
+T_RVF_RET rvf_unregisterFromHost(T_RVF_G_ADDR_ID host_id, T_RVF_G_ADDR_ID pid) {
+	UINT8 i=0;
+	if (pRtAddrIdTable[host_id]->hosting_count !=0) {
+		for(i=0; i<MAX_PARASITES || pRtAddrIdTable[host_id]->parasites[i]==pid; i++);
+			pRtAddrIdTable[host_id]->parasites[i]=0;
+
+		pRtAddrIdTable[host_id]->hosting_count--;
+	} else return RV_INVALID_PARAMETER;
+
+	return RVF_OK;
+}
+
+T_RVF_RET rvf_associateGrpToHost(T_RVF_G_ADDR_ID host_id, T_RVF_GD_ID gd_id) {
+
+	if (host_id >= MAX_RVF_TASKS )  return RV_INVALID_PARAMETER; 
+
+	pRtAddrIdTable[host_id]->gdHost=gd_id;
+		
+	return RVF_OK;
+}
+
+/*T_RVF_RET rvf_unregisterGrpFromHost(T_RVF_G_ADDR_ID host_id, T_RVF_G_ADDR_ID pid) {
+	if (pRtAddrIdTable[host_id]->hosting_count !=0) {
+		pRtAddrIdTable[host_id]->parasites[pid]=0;
+		pRtAddrIdTable[host_id]->hosting_count--;
+	} else return RV_INVALID_PARAMETER;
+
+	return RVF_OK;
+}*/
+
+T_RVF_G_ADDR_ID rvf_resolveHostingAddrId(T_RVM_GROUP_DIRECTIVE gd) {
+	int i=0;
+
+	for(i=1; i<MAX_RVF_TASKS; i++) {		// i=1 by-pass RVM task 
+		if(pRtAddrIdTable[i]!=NULL) {
+			if( pRtAddrIdTable[i]->type_code==ET2_HOST_TASK &&
+//				pRtAddrIdTable[i]->priority==priority &&	// to do ...
+//				pRtAddrIdTable[i]->os_stack_size>=stack_size
+				pRtAddrIdTable[i]->gdHost==gd.group_directive &&
+				pRtAddrIdTable[i]->hosting_count<MAX_PARASITES ) return i; // def. 10 A+ .
+		}
+	}
+
+	return RVF_INVALID_ADDR_ID; /* nothing found ret. param must be invalid*/
+}
+
+/*********************************************************************
+ * start() and stop() should be added to params, due to defered calling 
+ * Allow for parasites to be added at RT and their start to be called.
+ *********************************************************************/
+T_RVF_RET rvf_create_virtual_task (T_RV_RET (* handle_message)(T_RV_HDR * msg),
+								   T_RV_RET (* handle_timer)(T_RV_HDR * msg),
+								   T_RVF_G_ADDR_ID task_id, T_RVF_G_ADDR_ID host_task_id, char *taskname,
+								   UINT8 priority, UINT8 tcode) {
+
+	if(!pRtAddrIdTable[task_id]) {  /* allow for static init. or previous dyn init, eg. idle*/	
+		if(_RALLOC_TASK_RT_ADDR_DATA((T_RVF_BUFFER**)&pRtAddrIdTable[task_id])) return RVF_INTERNAL_ERR;
+		memset( pRtAddrIdTable[task_id], 0, sizeof(T_RVF_RT_ADDR_ID_DATA) );
+
+		rvf_mbox_buffer_init(pRtAddrIdTable[task_id]);
+	} /*else printf("RVF: task rt addr %d already alloc'ed\n", task_id); */
+
+	pRtAddrIdTable[task_id]->host_addr_id=host_task_id;
+	pRtAddrIdTable[task_id]->symbolic_name=taskname;
+	pRtAddrIdTable[task_id]->handle_message=handle_message;
+	pRtAddrIdTable[task_id]->handle_timer=handle_timer;
+	pRtAddrIdTable[task_id]->type_code=tcode;
+
+	pRtAddrIdTable[task_id]->pOSTCB=NULL;		/* init to NULL for res.'free' */ 
+	pRtAddrIdTable[task_id]->pOSEvtGrp=NULL;
+	pRtAddrIdTable[task_id]->p_os_stack=NULL;
+//	pRtAddrIdTable[task_id]->p_tm_q=NULL;
+
+//	rvf_registerToHost(host_task_id, task_id);
+	
+	return RVF_OK;
+}
+
+T_RVF_RET rvf_register_t3_handlers (T_RVF_G_ADDR_ID task_id,
+								   T_RV_RET (* handle_message)(T_RV_HDR * msg),
+								   T_RV_RET (* handle_timer)(T_RV_HDR * msg) ) {
+
+	pRtAddrIdTable[task_id]->handle_message=handle_message;
+	pRtAddrIdTable[task_id]->handle_timer=handle_timer;
+
+	return RVF_OK;
+}
+
+/* RVM must create a stack with its MB and pass as params to task create */
+/*T_RVF_RET rvf_create_host_task (T_RV_RET (* proxy)(void), T_RVF_G_ADDR_ID task_id,
+								   char *taskname, UINT8 *stack, UINT16 stacksize, 
+								   UINT8 priority, UINT8 tcode, UINT8 time_slicing, T_RVF_TASK_STATE suspend) {
+
+	return rvf_create_task(	(TASKPTR)proxy, task_id, taskname, stack, stacksize,\
+							priority, tcode, time_slicing,	suspend ) ;
+									
+}*/
+
+/*******************************************************************************
+**
+** Function         rvf_create_task
+**
+** Description      This function is called to create a new rvf task.
+**                  time_slice represents the number of Nucleus ticks before a task is interrupted.
+**					0 for no time-slicing.
+**
+** Returns          RVF_OK if successful, else an error code
+**
+*******************************************************************************/
+T_RVF_RET rvf_create_legacy_task (TASKPTR task_entry, UINT8 task_id, char *taskname, UINT8 *stack, UINT16 stacksize, UINT8 priority, UINT8 time_slicing, T_RVF_TASK_STATE is_suspend) {
+
+	return rvf_create_task(task_entry,task_id,taskname,stack,stacksize,priority,ET4_TASK,time_slicing,is_suspend);
+}
+
+T_RVF_RET rvf_create_task (TASKPTR task_entry, T_RVF_G_ADDR_ID task_id, char *taskname, UINT8 *stack, UINT16 stacksize,
+						   UINT8 priority, UINT8 tcode, UINT8 time_slicing, T_RVF_TASK_STATE suspend) {
+
+	/*if (task_id >= MAX_RVF_TASKS) { return 1; } */
+	if (task_counter >= MAX_RVF_TASKS) { return 1; }
+
+	/* fill the task stack with a 0xFE pattern to allow use with stack monitoring tool */
+	memset( stack, 0xFE, stacksize );
+
+	/* allow for immediate task creation, eg. no alloc taskId(), but #defined task No. Dangerous!*/	
+	if(!pRtAddrIdTable[task_id]) {  
+		if(_RALLOC_TASK_RT_ADDR_DATA((T_RVF_BUFFER**)&pRtAddrIdTable[task_id])) return RVF_INTERNAL_ERR;
+		memset( pRtAddrIdTable[task_id], 0, sizeof(T_RVF_RT_ADDR_ID_DATA) );
+
+		rvf_mbox_buffer_init(pRtAddrIdTable[task_id]);
+	} /*else printf("RVF: task rt addr %d already alloc'ed\n", task_id); */
+
+	/*if(_RALLOC_TASK_RT_TM((T_RVF_BUFFER**)&pRtAddrIdTable[task_id]->p_tm_q)) {
+		rvf_free_buf(pRtAddrIdTable[task_id]);
+		pRtAddrIdTable[task_id]=NULL;
+		return RVF_INTERNAL_ERR;
+	} else pRtAddrIdTable[task_id]->p_tm_q->timerCnt=0;*/
+	
+	pRtAddrIdTable[task_id]->hosting_count=0;
+	pRtAddrIdTable[task_id]->host_addr_id=task_id;
+	pRtAddrIdTable[task_id]->symbolic_name=taskname;
+	pRtAddrIdTable[task_id]->priority=priority;
+	pRtAddrIdTable[task_id]->type_code=tcode;
+
+	memset(&pRtAddrIdTable[task_id]->parasites, 0, (sizeof(T_RVF_G_ADDR_ID)*MAX_PARASITES));
+
+	if (stack) {
+	    pRtAddrIdTable[task_id]->p_os_stack     = (UINT8 *)stack;// - stacksize;
+	    pRtAddrIdTable[task_id]->os_stack_size	= stacksize;
+    } else {
+//		rvf_free_buf(pRtAddrIdTable[task_id]->p_tm_q);
+		rvf_free_buf(pRtAddrIdTable[task_id]);
+		pRtAddrIdTable[task_id]=NULL;
+		return RVF_INTERNAL_ERR;
+	}
+
+	if(_RALLOC_TASK_CNTRL_BLK((T_RVF_BUFFER**)&pRtAddrIdTable[task_id]->pOSTCB)) {
+		rvf_free_buf(stack);
+//		rvf_free_buf(pRtAddrIdTable[task_id]->p_tm_q);
+		rvf_free_buf(pRtAddrIdTable[task_id]);
+		pRtAddrIdTable[task_id]=NULL;
+		return RVF_INTERNAL_ERR;
+	}
+	memset( pRtAddrIdTable[task_id]->pOSTCB, 0, sizeof(NU_TASK) );
+
+	if(_RALLOC_TASK_EVT_GRP((T_RVF_BUFFER**)&pRtAddrIdTable[task_id]->pOSEvtGrp)) {
+		rvf_free_buf(pRtAddrIdTable[task_id]->pOSTCB);
+		rvf_free_buf(stack);
+//		rvf_free_buf(pRtAddrIdTable[task_id]->p_tm_q);
+		rvf_free_buf(pRtAddrIdTable[task_id]);
+		pRtAddrIdTable[task_id]=NULL;
+		return RVF_INTERNAL_ERR;
+	}
+	memset( pRtAddrIdTable[task_id]->pOSEvtGrp, 0, sizeof(NU_EVENT_GROUP) );
+
+	/* Create one Event Group for this task */
+	if( NU_SUCCESS != \
+		NU_Create_Event_Group (pRtAddrIdTable[task_id]->pOSEvtGrp,\
+		taskname) ) {
+		return RVF_INTERNAL_ERR;
+	}
+
+	//}
+    /* Create Task */
+	if ( NU_SUCCESS != 
+	NU_Create_Task (pRtAddrIdTable[task_id]->pOSTCB,            /* Task Control Block */
+		            taskname,     /*taskname,*/					/* Task Name */
+		            (NU_TASK_ENTRY )task_entry,					/* Task Entry Function */
+		            0,            /* why prev. task_id ???  */	/* ARGC  A-M-E-N-D-E-D! */
+		            NULL,										/* ARGV */
+		            pRtAddrIdTable[task_id]->p_os_stack,        /* Begining of Stack */
+		            pRtAddrIdTable[task_id]->os_stack_size,		/* Stack size */
+		            priority,									/* Priority */
+		            time_slicing,								/* Time Slicing Period*/
+		            NU_PREEMPT,									/* Preemption allowed */
+					(OPTION)(suspend == RUNNING ? NU_START : NU_NO_START) )/* Start the task or suspend it */
+		)	{	
+		return RVF_INTERNAL_ERR;
+	}
+	task_counter++;   /* MUST 'DEC' ON TASK TERMINATION	*/
+	
+	return RVF_OK;
+}
+
+/* to be called from func. 'create_tasks()' of module "create_RVtasks.c" 
+ * utilises static alloated system variables								*/
+/*T_RVF_RET rvf_create_boot_task (TASKPTR task_entry, UINT8 task_id, char *taskname, UINT8 *stack, UINT16 stacksize, UINT8 priority, UINT8 time_slicing, T_RVF_TASK_STATE suspend) {
+	if (task_id >= MAX_RVF_TASKS)	{		return 1;}
+
+    if (stack)    {
+	    bOSStack     = (UINT8 *)stack;// - stacksize;
+	    bOSStackSize = stacksize;
+    }
+	// copy the task name into an internal buffer 
+	_rvf_name_cpy( &(bOSTName[0][0]), taskname, RVF_MAX_TASK_LEN);
+
+	// fill the task stack with a 0xFE pattern to allow use with stack monitoring tool 
+	memset( stack, 0xFE, stacksize );
+
+	// Create one Event Group for this task 
+	if( NU_SUCCESS != NU_Create_Event_Group (&bOSEvtGrp[0], taskname) ){
+		return RVF_INTERNAL_ERR;
+	}
+
+    // Create Task 
+	if ( NU_SUCCESS != 
+	NU_Create_Task (&bOSTCB[0],                 // (reserved)Task Control Block 
+		            taskname,	                // Task Name 
+		            (NU_TASK_ENTRY )task_entry,	// Task Entry Function 
+		            task_id,		            // ARGC 
+		            NULL,		                // ARGV 
+		            bOSStack,					// Begining of Stack 
+		            stacksize,	                // Stack size 
+		            priority,					// Priority 
+		            time_slicing,			    // Time Slicing Period
+		            NU_PREEMPT,                 // Preemption allowed 
+					(OPTION)(suspend == RUNNING ? NU_START : NU_NO_START) )// Start the task or suspend it 
+		)
+	{	return RVF_INTERNAL_ERR;
+	}
+	task_counter++;
+	return RVF_OK;
+}*/
+
+/* Later timer blk must be added, once made dynamic   */ 
+T_RVF_RET rvf_free_sys_resources(T_RVF_G_ADDR_ID gid, UINT8 rm) {
+
+	if(!pRtAddrIdTable[gid]) return RVF_INTERNAL_ERR;
+
+	if(rm==1 || rm==2) {
+		if(pRtAddrIdTable[gid]->pOSTCB)rvf_free_buf(pRtAddrIdTable[gid]->pOSTCB);
+		if(pRtAddrIdTable[gid]->pOSEvtGrp)rvf_free_buf(pRtAddrIdTable[gid]->pOSEvtGrp);
+		if(pRtAddrIdTable[gid]->p_os_stack)rvf_free_buf(pRtAddrIdTable[gid]->p_os_stack);
+
+		task_counter--;
+	}
+	if(rm==0 || rm==2) {
+		if(pRtAddrIdTable[gid])rvf_free_buf(pRtAddrIdTable[gid]);
+		pRtAddrIdTable[gid]=NULL;
+	}
+
+	return RVF_OK;
+}
+
+/*******************************************************************************
+**
+** Function         rvf_exit_task
+**
+** Description      This function is called to stop a rvf task.
+**					A task can kill another task or itself.
+**
+** Returns          void
+**
+*******************************************************************************/
+void rvf_exit_task (T_RVF_G_ADDR_ID task_id)
+{
+	if(!pRtAddrIdTable[task_id]) return;
+	/*
+	** Empty task's mail box
+	*/
+	_rvf_empty_mailboxes(task_id);
+
+	/*
+	** Terminate task
+	*/
+	NU_Terminate_Task(pRtAddrIdTable[task_id]->pOSTCB); /*&OSTCB[task_id]);*/
+	NU_Delete_Task(pRtAddrIdTable[task_id]->pOSTCB);
+
+	/*
+	** Delete related event group
+	*/
+	NU_Delete_Event_Group (pRtAddrIdTable[task_id]->pOSEvtGrp);
+
+	pRtAddrIdTable[task_id]->p_os_stack=0;
+    //OSStack[task_id]     = 0;
+}
+
+
+/*******************************************************************************
+**
+** Function         rvf_suspend_task
+**
+** Description      This function is called to suspend a rvf task.
+**					A task can suspend another task or itself.
+**
+** Returns          void
+**
+*******************************************************************************/
+T_RVF_RET rvf_suspend_task (T_RVF_G_ADDR_ID task_id)
+{
+	if(!pRtAddrIdTable[task_id]) return RVF_INVALID_PARAMETER;
+	NU_Suspend_Task(pRtAddrIdTable[task_id]->pOSTCB); // A-M-E-N-D-E-D! 
+
+	return RVF_OK;
+}
+
+
+/*******************************************************************************
+**
+** Function         rvf_wait
+**
+** Description      This function is called by tasks to wait for a specific
+**                  event or set of events. The task may specify the duration
+**                  that it wants to wait for, or 0 if infinite.
+**
+** Returns          the event mask of received events or zero if timeout
+**
+*******************************************************************************/
+UINT16 rvf_wait (UINT16 flag, UINT32 timeout) {
+	T_RVF_G_ADDR_ID     rtask = rvf_get_taskid();
+
+	if (!timeout) timeout = 0xFFFFFFFFL;
+	
+	return rvf_evt_wait(rtask, flag, timeout);
+}
+
+UINT16 rvf_evt_wait(T_RVF_G_ADDR_ID rtask, UINT16 flag, UINT32 timeout) {
+
+#define RVF_RET_TIME_OUT	0
+
+	UINT16		mbxEvt = 0;
+	UNSIGNED    evt   = 0;
+	UNSIGNED	clear = 0;
+	STATUS		status_ret; 
+
+    /* Check if anything in any of the mailboxes. Possible race condition. */
+   
+	if (rtask>=MAX_RVF_TASKS || !pRtAddrIdTable[rtask]) {
+		RVM_TRACE_WARNING_PARAM("RVF: Illegal MBOX or MBOX not ready!", rtask);
+		return (UINT16) RVF_RET_TIME_OUT; 
+	}
+
+	if (pRtAddrIdTable[rtask] && pRtAddrIdTable[rtask]->OSTaskQFirst[0])
+        mbxEvt |= RVF_TASK_MBOX_0_EVT_MASK;
+    if (pRtAddrIdTable[rtask] && pRtAddrIdTable[rtask]->OSTaskQFirst[1])
+        mbxEvt |= RVF_TASK_MBOX_1_EVT_MASK;
+    if (pRtAddrIdTable[rtask] && pRtAddrIdTable[rtask]->OSTaskQFirst[2])
+        mbxEvt |= RVF_TASK_MBOX_2_EVT_MASK;
+    if (pRtAddrIdTable[rtask] && pRtAddrIdTable[rtask]->OSTaskQFirst[3])
+        mbxEvt |= RVF_TASK_MBOX_3_EVT_MASK;
+
+    /* If any valid event if pending, return immediately */
+    if (mbxEvt & flag)
+    {
+       /* Return only those bits which user wants... */
+       evt = (UINT16) (mbxEvt & flag);
+
+	   /* clear the nucleus event(s) for mailboxes */
+	   if ( mbxEvt & 0x000F ) /* a mailbox event is signaled*/
+	   {   NU_Retrieve_Events (pRtAddrIdTable[rtask]->pOSEvtGrp, (UNSIGNED) mbxEvt & 0x000F, NU_AND_CONSUME,
+                        (UNSIGNED *)&clear, NU_NO_SUSPEND);
+	   }
+
+       	   
+        return ((UINT16) evt);
+    }
+
+
+    if(pRtAddrIdTable[rtask]) {
+		status_ret = NU_Retrieve_Events (pRtAddrIdTable[rtask]->pOSEvtGrp,
+										 (UNSIGNED) flag, NU_OR_CONSUME,
+										 (UNSIGNED *)&evt, timeout );
+		if ( status_ret == NU_SUCCESS) {
+			return (UINT16) evt;
+		} else { /* timeout or error case */
+			return (UINT16) RVF_RET_TIME_OUT;
+		}
+	} return (UINT16) RVF_RET_TIME_OUT;
+}
+
+/*******************************************************************************
+**
+** Function         rvf_wait_for_specific_msg
+**
+** Description      This function is called by tasks to wait for a specific
+**                  message in the specified mailbox. The task may specify the duration
+**                  that it wants to wait for, or 0 if infinite.
+**
+** Returns          A pointer to the message, NULL in case of time-out.
+**
+*******************************************************************************/
+T_RVF_BUFFER * rvf_wait_for_specific_msg(UINT16 msg_code, UINT8 mbox, UINT32 timeout)
+{
+	T_RVF_G_ADDR_ID task_id = rvf_get_taskid();
+	T_RVF_BUFFER * p_buf = NULL;
+	T_RVF_INTERNAL_BUF * p_hdr;
+	UNSIGNED clear = 0;
+	STATUS status_ret;
+	UINT32 wait_time;
+	UINT32 init_time = rvf_get_tick_count();
+
+	
+	/* check input parameter */
+	if ( mbox >= RVF_NUM_TASK_MBOX)  /* NOTE: must be def to 2 max */
+	{	rvf_send_trace( "RVF: rvf_wait_for_specific_msg(): invalid mailbox id", 52, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID);
+		return p_buf;
+	}
+
+	if(!timeout)
+		timeout = 0xFFFFFFFFL;
+	wait_time = timeout;
+
+	while( (rvf_get_tick_count() - init_time) < timeout  )
+	{
+		/* test all messages in the mailbox */
+		if( pRtAddrIdTable[task_id]->OSTaskQFirst[mbox] )
+		{
+			rvf_disable(9);
+			p_hdr = pRtAddrIdTable[task_id]->OSTaskQFirst[mbox];
+			p_buf = MEM2USER(p_hdr);
+			/* test the first one */
+			if ( ((T_RV_HDR *)p_buf)->msg_id == msg_code )
+			{	/* message found, return it */
+				pRtAddrIdTable[task_id]->OSTaskQFirst[mbox] = p_hdr->p_next;
+				p_hdr->p_next				= NULL;
+
+#if RVF_ENABLE_BUF_LINKAGE_CHECK
+				RVF_SET_BUF_UNLINKED(p_hdr);
+#endif
+				/* clear the Nucleus Event for this mailbox */
+				NU_Retrieve_Events( pRtAddrIdTable[task_id]->pOSEvtGrp, EVENT_MASK(mbox), NU_AND_CONSUME, 
+								(UNSIGNED *)&clear, NU_NO_SUSPEND);
+				rvf_enable();
+				return p_buf;
+			}
+
+			while(p_hdr->p_next != NULL)
+			{
+				p_buf = MEM2USER(p_hdr->p_next);
+				if ( ((T_RV_HDR *)p_buf)->msg_id == msg_code )
+				{	/* remove it from the list */
+					p_hdr->p_next = ( (T_RVF_INTERNAL_BUF *) USER2MEM(p_buf))->p_next;
+					/* check if it the last one */
+					if ( pRtAddrIdTable[task_id]->OSTaskQLast[mbox]  == USER2MEM(p_buf) )
+					{	pRtAddrIdTable[task_id]->OSTaskQLast[mbox]  = p_hdr;
+					}
+					((T_RVF_INTERNAL_BUF *) USER2MEM(p_buf))->p_next = NULL;
+
+	#if RVF_ENABLE_BUF_LINKAGE_CHECK
+					RVF_SET_BUF_UNLINKED(USER2MEM(p_buf));
+	#endif
+					rvf_enable();
+					return p_buf;
+				}
+				p_hdr = p_hdr->p_next;
+			}
+
+			rvf_enable();
+		}
+		
+		/* here, the message has not been found, so wait for a new message */
+		
+		if ((wait_time != 0xFFFFFFFFL) &&
+			(timeout > rvf_get_tick_count() - init_time))
+		{
+			/* NU_Retrieve_Events bug: cannot call function with a parameter with F in MSB */
+			wait_time = (timeout - (rvf_get_tick_count() - init_time)) & 0x0FFFFFFFL;
+		}
+
+		status_ret = NU_Retrieve_Events( pRtAddrIdTable[task_id]->pOSEvtGrp, EVENT_MASK(mbox), NU_OR_CONSUME,
+										(UNSIGNED *)&clear, wait_time);
+
+		if( status_ret != NU_SUCCESS) /* time out */
+		{	return NULL;
+		}
+		
+	}
+	return NULL;
+}
+
+
+/*******************************************************************************
+**
+** Function         rvf_delay
+**
+** Description      This function is called by tasks to sleep unconditionally
+**                  for a specified amount of time.
+**
+** Returns          void
+**
+*******************************************************************************/
+void rvf_delay (UINT32 timeout)
+{
+	if (timeout == 0)
+	{	timeout = 1;
+	}
+
+	NU_Sleep(timeout);
+
+}
+
+
+/*******************************************************************************
+**
+** Function         rvf_send_event
+**
+** Description      This function is called by tasks to send events to other
+**                  tasks. Tasks can also send events to themselves.
+**
+** Returns          0 if all OK, else 1
+**
+*******************************************************************************/
+UINT8 rvf_send_event (T_RVF_G_ADDR_ID task_id, UINT16 event) {	
+
+	if (task_id >= MAX_RVF_TASKS || !pRtAddrIdTable[task_id] ) return 1;
+
+	NU_Set_Events (pRtAddrIdTable[task_id]->pOSEvtGrp, (UNSIGNED)event, NU_OR);
+
+	return 0;
+}
+
+/*******************************************************************************
+**
+** Function         rvf_get_taskid
+**
+** Description      This function gets the currently running task ID.
+**
+** Returns          task ID
+**
+*******************************************************************************/
+T_RVF_G_ADDR_ID rvf_get_taskid(void) {	/* Retrieve the taskid using index of the task pointer in the OSTCB array */
+	NU_TASK * currTask=0;
+	T_RVF_G_ADDR_ID taskId=RVF_INVALID_ADDR_ID;
+
+	currTask = NU_Current_Task_Pointer();
+
+	if( currTask != NU_NULL) {
+		/* find the task pointer in the OSTCB array */
+		for ( taskId = 0; taskId < MAX_RVF_TASKS; taskId++) {
+			if( (pRtAddrIdTable[taskId]!= NULL) && 
+				((pRtAddrIdTable[taskId]->pOSTCB)) == currTask) return taskId;
+		}
+		return RVF_INVALID_ADDR_ID;
+	} else {
+		return RVF_INVALID_ADDR_ID; /* error case, must return an error code */
+	}
+}
+
+
+/*******************************************************************************
+**
+** Function         rvf_get_taskname
+**
+** Description      This function gets the currently running task name.
+**
+** Returns          pointer to task name or NULL if error
+**
+*******************************************************************************/
+char* rvf_get_taskname(void)
+{	T_RVF_G_ADDR_ID id = rvf_get_taskid();
+	
+	if (id == 0xFF) return NULL; /* return NULL if rvf_get_taskid returns 0xFF */
+
+    return pRtAddrIdTable[id]->symbolic_name; /*(OSTName[ id ]);*/
+}
+
+/*******************************************************************************
+**
+** Function         rvf_enable
+**
+** Description      This function enables interrupts.
+**
+** Returns          void
+**
+*******************************************************************************/
+void rvf_enable(void)
+{
+
+	if( --OSDisableNesting == 0)	/* Control nesting interrupt */
+	{	
+		if( OSInterruptAlreadyMasked == TRUE) /*	check if interrupts have been disabled outside RVF, 
+													in that case, do not enable interrupts */
+		{	OSInterruptAlreadyMasked = FALSE;
+		}
+		else
+		{	NU_Control_Interrupts(OSLastIntLevel);
+		}
+	}
+
+}
+
+#ifdef _WINDOWS
+
+/*******************************************************************************
+**
+** Function         INT_Check_IRQ_Mask()
+**
+** Description      This function checks if the IRQ are disabled (outside RVF).
+**
+** Returns          IRQ mask
+**
+*******************************************************************************/
+UINT32 INT_Check_IRQ_Mask(void)
+{
+	return 0;
+}
+#else
+
+/*-------------------------------------------------------*/ 
+/* INT_Check_IRQ_Mask()                                  */
+/*-------------------------------------------------------*/
+/*                                                       */
+/* Description: check in the CPSR register if the IRQ	 */
+/*              are masked out or not.                   */
+/* ------------                                          */
+/*												         */
+/*-------------------------------------------------------*/
+/* Declaration of ASM INT_Check_IRQ_Mask function */
+UINT32 INT_Check_IRQ_Mask(void);
+
+/*
+ * FreeCalypso: this assembly function will be moved out into
+ * its own source file, or maybe added to nucleus/tct.S.
+ */
+#if 0
+asm("           .def	$INT_Check_IRQ_Mask");
+asm("$INT_Check_IRQ_Mask  ");			    
+asm("           .ref _INT_32_Check_IRQ_Mask");
+asm(".state16");
+asm("	ADR	r0,_INT_32_Check_IRQ_Mask  ");
+asm("	BX r0  ");
+
+asm("	.align");
+asm("	.state32");
+asm("           .def _INT_32_Check_IRQ_Mask");
+asm("_INT_32_Check_IRQ_Mask  ");
+
+asm("	MRS	r0,CPSR  ");   // pick up CPSR 
+asm("	BX	lr  ");        // return to caller
+#endif
+#endif
+
+
+/*******************************************************************************
+**
+** Function         rvf_disable
+**
+** Description      This function disables interrupts.
+**
+** Returns          void
+**
+*******************************************************************************/
+
+#define RVF_IRQ_DISABLED_MASK 0x00000080
+
+void rvf_disable(UINT8 who)
+{
+
+	/* Control interrupt nesting ourselves */
+	if (OSDisableNesting == 0)
+	{
+		if ( INT_Check_IRQ_Mask() & RVF_IRQ_DISABLED_MASK)	/* if IRQ are disabled (outside RVF) */
+		{	OSInterruptAlreadyMasked = TRUE;
+		}
+		else
+		{	OSLastIntLevel = NU_Control_Interrupts(NU_DISABLE_INTERRUPTS);
+		}
+	}
+	OSDisableNesting++;
+
+}
+
+
+/*******************************************************************************
+**
+** Function         rvf_used_stack
+**
+** Description      This function tries to calculate the amount of
+**                  stack used by looking for a zero.
+**
+** Returns          the number of non-zero bytes on the stack
+**
+*******************************************************************************/
+UINT16 rvf_used_stack(T_RVF_G_ADDR_ID task)
+{
+	UINT16 j, stacksize;
+	UINT8 *p;
+
+	if(!pRtAddrIdTable[task]) return 0;
+
+	stacksize = pRtAddrIdTable[task]->os_stack_size; /*OSStackSize[task];*/
+	p = pRtAddrIdTable[task]->p_os_stack; /*OSStack[task];*/
+	for(j = 0; (j < stacksize) && (*p++ == 0xFE); j++);
+
+	return ((UINT16)(stacksize - j));
+}
+
+
+/*******************************************************************************
+**
+** Function         rvf_dump_tasks
+**
+** Description      This function dump all the rvf tasks.
+**
+** Returns          void
+**
+*******************************************************************************/
+void rvf_dump_tasks()
+{	UINT8 num_task;
+	char task_info[100];
+
+	rvf_send_trace("*** START DUMPING TASKS ***", 27, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID);
+	
+	/* for each task, display its name, its id, its stack size*/
+	rvf_send_trace("*TASK_NAME Id Stack_size Used_stack", 35, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID);
+		
+	for ( num_task = 0; num_task < MAX_RVF_G_ADDR_ID; num_task++ )
+	{	
+		/* trace the task if it has been created*/
+		if (pRtAddrIdTable[num_task] != 0 ) {	
+			sprintf( task_info, "%10.10s %2d      %5d      %5d",
+				pRtAddrIdTable[num_task]->symbolic_name /*OSTName[num_task]*/, 
+				num_task, 
+				pRtAddrIdTable[num_task]->os_stack_size, 
+				rvf_used_stack( num_task) );
+			rvf_send_trace( task_info, 35, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID);		
+		}
+	}
+	/* find a way to track task stack usage and display it */
+	/* using NU_Check_Stack, NU_Task_Information or finding the first non-zero value in the stack */
+}
+
+
+/****************************************************************************/
+/* For Big Endian Processors swap the bytes                                 */
+#if defined(__BIG_ENDIAN)
+UINT16 ntohs(UINT16 n)
+{
+	register UINT8  tmp;
+	register UINT8  *p=(UINT8 *)&n;
+
+	tmp  = p[0];
+	p[0] = p[1];
+	p[1] = tmp;
+
+	return n;
+}
+
+UINT32 ntohl(UINT32 n)
+{
+	register UINT8 tmp;
+	register UINT8 *p=(UINT8 *)&n;
+
+	tmp  = p[0];
+	p[0] = p[3];
+	p[3] = tmp;
+
+	tmp  = p[1];
+	p[1] = p[2];
+	p[2] = tmp;
+
+	return n;
+}
+
+#endif /* __BIG_ENDIAN*/
+
+
+
+
+/******************************************************************************
+**
+** Function			rvf_send_trace
+**
+** Description		This function displays a message essentially for debug purposes.
+**					It displays the msg_length characters of the string pointed by msg
+**					and the value of val.		
+**
+** Returns			void
+**
+******************************************************************************/
+#ifdef  _WINDOWS 
+#ifndef _CONSOLE
+void rvf_send_trace1( INT8 * msg, UINT8 msg_length, UINT32 val, UINT8 TRACE_LEVEL, UINT32 swe_use_id)
+{
+/* Function to display trace message for Tool */
+
+	UINT32 trace_type = swe_use_id;
+	
+	Trace( msg, msg_length, val, TRACE_LEVEL, trace_type);
+}
+#endif	
+#endif	
+
+#ifdef _CONSOLE  /* CONSOLE */
+void rvf_send_trace1( INT8 * msg, UINT8 msg_length, UINT32 val, UINT8 TRACE_LEVEL, UINT32 swe_use_id) {
+	const	int MAX		= 1000; 
+	static	int l		= 0;
+	char	buf[100];
+	HANDLE	out			= 0;
+    int nb;
+
+	if(!out)out=GetStdHandle(STD_OUTPUT_HANDLE); 
+
+	rvf_disable(25);
+	
+	sprintf(buf,"%s %d\n", msg, val);
+	WriteConsole(out, buf, strlen(buf), &nb, NULL);
+	
+	if(l>=MAX) {
+		system("cls");
+		l=0;
+	} else l++;
+
+	rvf_enable();
+}
+#endif			/* CONSOLE */
+
+/*******************************************************************************
+**
+** Function         rvf_resume_task
+**
+** Description      This function is called to resume a rvf task which is in a suspend state.
+**
+** Returns          RVF_OK if successful, else an error code
+**
+*******************************************************************************/
+T_RVF_RET rvf_resume_task( T_RVF_G_ADDR_ID taskid)
+{
+	if(!pRtAddrIdTable[taskid]) return RVF_INVALID_PARAMETER;
+	if(!pRtAddrIdTable[taskid]->pOSTCB) return RVF_INVALID_PARAMETER;
+	/* resume the task */
+	if ( NU_INVALID_TASK == NU_Resume_Task( pRtAddrIdTable[taskid]->pOSTCB) ) {// A-M-E-N-D-E-D!
+		return RVF_INTERNAL_ERR; //RVF_INVALID_PARAMETER;
+	}
+	return RVF_OK;
+}
+
+/*******************************************************************************
+**
+** Function         rvf_initialize_mutex
+**
+** Description      This function initialize a mutex structure, which will be used 
+**					to protect shared variables against simultaneous access.
+**
+** Returns          RVF_OK if successful, else an error code
+**
+*******************************************************************************/
+T_RVF_RET		rvf_initialize_mutex( T_RVF_MUTEX * mutex)
+{
+
+	/* initializes the mutex structure */
+	
+	if( NU_Create_Semaphore( (NU_SEMAPHORE *)mutex, "RVF", 1, NU_PRIORITY ) != NU_SUCCESS)
+	{	return RVF_INTERNAL_ERR;
+	}
+	
+	return RVF_OK;
+}
+
+/*******************************************************************************
+**
+** Function         rvf_lock_mutex
+**
+** Description      This function locks a mutex to avoid simultaneous access.
+**					If the mutex is already locked, the task is suspended 
+**					until the mutex is unlocked.
+**
+** Returns          RVF_OK if successful, else an error code
+**
+*******************************************************************************/
+T_RVF_RET		rvf_lock_mutex( T_RVF_MUTEX * mutex)
+{
+	if( NU_Obtain_Semaphore( (NU_SEMAPHORE *)mutex, NU_SUSPEND ) != NU_SUCCESS)
+	{	return RVF_INTERNAL_ERR;
+	}
+
+	return RVF_OK;
+}
+
+/*******************************************************************************
+**
+** Function         rvf_unlock_mutex
+**
+** Description      This function unlocks a mutex to avoid simultaneous access.
+**
+** Returns          RVF_OK if successful, else an error code
+**
+*******************************************************************************/
+T_RVF_RET		rvf_unlock_mutex( T_RVF_MUTEX * mutex)
+{
+	if( NU_Release_Semaphore( (NU_SEMAPHORE *)mutex ) != NU_SUCCESS)
+	{	return RVF_INTERNAL_ERR;
+	}
+
+	return RVF_OK;
+}
+
+/*******************************************************************************
+**
+** Function         rvf_delete_mutex
+**
+** Description      This function deletes a previously created mutex.
+**
+** Returns          RVF_OK if successful, else an error code
+**
+*******************************************************************************/
+T_RVF_RET		rvf_delete_mutex( T_RVF_MUTEX * mutex)
+{
+	if( NU_Delete_Semaphore( (NU_SEMAPHORE *)mutex ) != NU_SUCCESS)
+	{	return RVF_INTERNAL_ERR;
+	}
+
+	return RVF_OK;
+}
+
+void rvf_yield() { NU_Relinquish(); }
+
+/* convenience function    */ 
+UINT8 rvf_isType2() {
+	if(pRtAddrIdTable[rvf_get_taskid()]->type_code==ET2_HOST_TASK) return 1;
+	else return 0;
+}