📄 xtask_rpc.c
字号:
xtask_rpc_wait_for_completion(context);#endif /* Get return args and return result */ if( (err = xtask_pull_args( pgbus, context->fifo, args )) != RM_OK ) { err = RM_ERROR; goto safe_exit; } /* get the return status */ err = xtask_rpc_get_status(context); safe_exit: /* release the semaphore */ xtask_semaphore_release( context ); return err;}/**************************************************************** Method Name ** xtask_rpc_wait_for_completion ** ** Description: ** Wait until the procedure has finished. ** ****************************************************************/RMstatus xtask_rpc_wait_for_completion_wtimeout( struct XtaskAPI* context, RMuint32 timeout_us ){ struct gbus *pgbus = context->pgbus; RMuint32 startTime = timer_start(pgbus); /* Maximum timer value is 159072861 us ( 2 ^ 32 ticks / 27,000,000 ticks/second ) * The effective range provided by the rpc call is cut in half as to prevent the * chance of an infinite loop where the timer interval is not read in time before * a rollover. So the effective maximum timeout is '159072861/2' * => 79536430 us (79 seconds) * * This is much larger than what should be needed. * */ if( timeout_us > MAX_TIMEOUT ) timeout_us = MAX_TIMEOUT; while( gbus_read_uint32( pgbus, (RMuint32)&context->fifo->procedureFd) != 0 ){ if( timer_interval_complete( pgbus, startTime, timeout_us) ) { RMDBGLOG((ENABLE,"xtask rpc operation timed out!\n")); return RM_TIMEOUT; } /* Don't read GBUS too often! */ delay_us(5); } return RM_OK;}/**************************************************************** Method Name ** xtask_rpc_wait_for_completion ** ** Description: ** Wait until the procedure has finished. ** ****************************************************************/RMstatus xtask_rpc_wait_for_completion( struct XtaskAPI* context /*RMuint32 timeout_us*/ ){ struct gbus *pgbus = context->pgbus; /* TODO: Implement Timeout, by adding (int timeout) in ms to the call list. */ while( gbus_read_uint32( pgbus, (RMuint32)&context->fifo->procedureFd) != 0 ){ /* Don't read GBUS too often! */ delay_us(5); } return RM_OK;}/**************************************************************** Method Name ** xtask_rpc_sync ** ** Description: ** This procedure prevents a race condition with the ** xtask. Basically, the xtask signals it has ended ** its initialization, and ready to go by constantly ** changing an agreed upon memory location in the PID ** rpc2xtask zone. Once this procedure sees a change ** in the memory location, it signals an ack to the ** xtask by resetting a different agreed upon memory ** location. ** ****************************************************************/RMstatus xtask_rpc_sync(struct XtaskAPI* context){ RMuint32 first, second, third; struct gbus *pgbus = context->pgbus; RMuint32 xPid; RMuint32 startTime; xPid = context->xPid; RMDBGLOG((ENABLE,"Syncing to xPid %d\n",xPid)); /* DEBUG */ RMDBGLOG((LOCALDBG, "GBUS_ADDR(xPid_FIFO_SYNC) = 0x%lx\n", (RMuint32)(&context->fifo->xtaskToCPUSignal) )); /* Get initial timer value */ startTime = timer_start(pgbus); /* Remember the first value in the agreed upon memory location */ /* Added robustness: Xtask is looping on {0:255} interval only */ while((first = gbus_read_uint32(pgbus, (RMuint32)&context->fifo->xtaskToCPUSignal)) > 255 ) { RMDBGLOG((LOCALDBG, "Waiting on first == 0x%lx\n",first)); if( timer_interval_complete(pgbus, startTime, SYNC_TIMEOUT_US) ){ RMDBGLOG((ENABLE,"Sync Timeout!\n")); return RM_TIMEOUT; } } /* Wait for this value to change */ while ( ((second = gbus_read_uint32(pgbus, (RMuint32)&context->fifo->xtaskToCPUSignal)) == first) || (second>255)) { RMDBGLOG((LOCALDBG,"Waiting on second == 0x%lx\n",second)); if( timer_interval_complete(pgbus, startTime, SYNC_TIMEOUT_US) ){ RMDBGLOG((ENABLE,"Sync Timeout!\n")); return RM_TIMEOUT; } } /* Wait for this value to change for the second time*/ while ( ((third = gbus_read_uint32(pgbus, (RMuint32)&context->fifo->xtaskToCPUSignal)) == second) || (third>255)) { RMDBGLOG((LOCALDBG,"Waiting on third == 0x%lx\n",third)); if( timer_interval_complete(pgbus, startTime, SYNC_TIMEOUT_US) ){ RMDBGLOG((ENABLE,"Sync Timeout!\n")); return RM_TIMEOUT; } } RMDBGLOG((ENABLE,"Rcvd signal from xtask.\n")); /* Signal acknowledgement to the xtask */ gbus_write_uint32(pgbus, (RMuint32)&context->fifo->cpuToXtaskSignal, 0); RMDBGLOG((ENABLE,"Sent signal to xtask\n")); return RM_OK;}/**************************************************************** Method Name ** xtask_rpc_init ** ** Description: ** Initialize the xtas_api context. This includes ** opening the gbus/llad, initializing the base * * address for communication with the xtask. ** ****************************************************************/RMstatus xtask_rpc_init( struct XtaskAPI* context, RMascii device[MAX_DEVICE_STRING], RMuint32 xrpc_base_addr, RMuint32 xrpc_size ){ /* Local Temp variables */ struct llad *pllad = 0; struct gbus *pgbus = 0; struct xrpc_block_header *pB; RMDBGLOG((ENABLE,"Open the llad with string \'%s\', xrpc_base_addr = 0x%08lx\n",device, xrpc_base_addr)); if( !xrpc_base_addr ) { RMDBGLOG((ENABLE,"xrpc_base_address is NULL ! \n")); return RM_ERROR; } if( xrpc_size < sizeof(struct xrpc_block_header) ) { RMDBGLOG((ENABLE,"memory allocated is too small. \n")); return RM_ERROR; }#ifndef USE_WIN_CE /* Open the llad */ pllad = llad_open(device); if (pllad == NULL) { RMDBGLOG((ENABLE, "unable to access device\n")); return RM_ERROR; } /* Open the gbus */ pgbus = gbus_open(pllad); if( pgbus == 0 ) { RMDBGLOG((ENABLE,"Failed to initialize the GBUS context\n")); return RM_ERROR; } #endif /* Make sure that xrpc header is on 32-byte aligment for Cache boundary issue in XOS !!! */ if( xrpc_base_addr % 16 != 0 ) { RMDBGLOG((ENABLE, "xrpc_base_addr(0x%08lx) is not on a 16 byte cache boundary!\n",xrpc_base_addr )); return RM_ERROR; } pB = (struct xrpc_block_header *)xrpc_base_addr; /* update the xtaskContext */ context->pgbus = pgbus; context->pllad = pllad; context->pB = pB; context->base_addr = xrpc_base_addr; context->size = xrpc_size; /* By default events are enabled (backwards compatability) */ context->events_enabled = TRUE; return RM_OK;}/**************************************************************** Method Name ** xtask_rpc_close ** ** Description: ** Cleanup, reclaim memory occupied by the llad/gbus. ** ****************************************************************/void xtask_rpc_close( struct XtaskAPI *context ){ RMDBGLOG((LOCALDBG,"Closing Xtask API ref!\n"));#ifndef USE_WIN_CE /* Close the gbus and the llad */ if( context->pgbus ) gbus_close(context->pgbus); if( context->pllad ) llad_close(context->pllad); #endif }/**************************************************************** Method Name ** xtask_semaphore_lock ** ** Description: ** Attempt to grab the semaphore, busy wait until it is ** available. **Not atomic ** ** ****************************************************************/RMstatus xtask_semaphore_lock( struct XtaskAPI* context /*, int timeout_ms */ ){ struct gbus *pgbus = context->pgbus; //RMDBGLOG((ENABLE,":::::::: Xtask_Semaphore_Lock() ...")); /* Busy wait for semahpore - maybe perform yeild here instead.*/ while( gbus_read_uint32( pgbus, (RMuint32)&context->fifo->semaphore) != 0 ); /* Acquire the semaphore */ gbus_write_uint32( pgbus, (RMuint32)&context->fifo->semaphore, 1 ); //RMDBGPRINT((ENABLE," locked!\n")); return RM_OK;}/**************************************************************** Method Name ** xtask_sempahore_release ** ** Description: ** Release the semaphore. ** ** ****************************************************************/RMstatus xtask_semaphore_release( struct XtaskAPI* context ){ struct gbus *pgbus = context->pgbus; gbus_write_uint32( pgbus, (RMuint32)&context->fifo->semaphore, 0 ); //RMDBGLOG((ENABLE,":::::::: Xtask_Semaphore_Released()!\n")); return RM_OK; }/**************************************************************** Method Name ** xtasl_rpc_enable_event_mode ** ** Description: ** Enable/Disable event mode. ** ** ****************************************************************/void xtask_rpc_enable_event_mode( struct XtaskAPI* context, RMbool enable){ context->events_enabled = enable;}#ifdef USE_WIN_CERMuint32 doxrpc (void *pgbus, RMuint32 XrpcBlock_PA){ RMuint32 reply; // acquire xos mutex while (gbus_read_uint32 (pgbus, REG_BASE_host_interface+host_mutex10)) { RMDBGLOG ((ENABLE, "xos mutex held ... (%d)\n", (int)gbus_read_uint32 (pgbus, REG_BASE_host_interface+host_mutex10))); } // tell xos where the xrpc header is at (physical address) gbus_write_uint32 (pgbus, CPU_LOCALRAM_STAGE, (RMuint32)XrpcBlock_PA); // signal xos that there is a valid xrpc header block gbus_write_uint32 (pgbus, REG_BASE_xpu_block + CPU_irq_softset,SOFT_IRQ_XRPC); // poll waiting for completion while ((gbus_read_uint32 (pgbus, REG_BASE_xpu_block+CPU_irq_softset) & SOFT_IRQ_XRPC) != 0); // read result code reply = gbus_read_uint32 (pgbus, CPU_LOCALRAM_STAGE); // release mutex gbus_write_uint32 (pgbus, REG_BASE_host_interface+host_mutex10, 0); return reply; // 6 == SUCCESS}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -