FreeCalypso > hg > fc-magnetite
view src/cs/riviera/rvf/rvf_task.c @ 475:3860b9e50692
.../drv_app/ffs/board/dev.c: FC hardware comment update
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 30 Mar 2018 06:39:13 +0000 |
parents | 945cf7f506b2 |
children |
line wrap: on
line source
/****************************************************************************/ /* */ /* 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*/ /****************************************************************************/ #ifndef _WINDOWS #include "config/rv.cfg" #endif #include "nucleus.h" #include "rv/rv_general.h" #include "rvf/rvf_api.h" #include "rvf/rvf_i.h" #include "rvm/rvm_i.h" /* ONLY for Task Codes */ #include "rvm/rvm_use_id_list.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); 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 /******************************************************************************* ** ** 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; }