tEplKernel EdrvCyclicSetNextTxBufferList(tEdrvTxBuffer** apTxBuffer_p, unsigned int uiTxBufferCount_p) { tEplKernel Ret = kEplSuccessful; unsigned int uiNextTxBufferList; uiNextTxBufferList = EdrvCyclicInstance_l.m_uiCurTxBufferList ^ EdrvCyclicInstance_l.m_uiMaxTxBufferCount; // check if next list is free if (EdrvCyclicInstance_l.m_paTxBufferList[uiNextTxBufferList] != NULL) { Ret = kEplEdrvNextTxListNotEmpty; goto Exit; } if ((uiTxBufferCount_p == 0) || (uiTxBufferCount_p > EdrvCyclicInstance_l.m_uiMaxTxBufferCount)) { Ret = kEplEdrvInvalidParam; goto Exit; } // check if last entry in list equals a NULL pointer if (apTxBuffer_p[uiTxBufferCount_p - 1] != NULL) { Ret = kEplEdrvInvalidParam; goto Exit; } EPL_MEMCPY(&EdrvCyclicInstance_l.m_paTxBufferList[uiNextTxBufferList], apTxBuffer_p, sizeof (*apTxBuffer_p) * uiTxBufferCount_p); Exit: return Ret; }
tEplKernel PUBLIC EplEventkPostError(tEplEventSource EventSource_p, tEplKernel EplError_p, unsigned int uiArgSize_p, void* pArg_p) { tEplKernel Ret; tEplEventError EventError; tEplEvent EplEvent; Ret = kEplSuccessful; // create argument EventError.m_EventSource = EventSource_p; EventError.m_EplError = EplError_p; uiArgSize_p = (unsigned int) min ((size_t) uiArgSize_p, sizeof (EventError.m_Arg)); EPL_MEMCPY(&EventError.m_Arg, pArg_p, uiArgSize_p); // create event EplEvent.m_EventType = kEplEventTypeError; EplEvent.m_EventSink = kEplEventSinkApi; EPL_MEMSET(&EplEvent.m_NetTime, 0x00, sizeof(EplEvent.m_NetTime)); EplEvent.m_uiSize = (memberoffs (tEplEventError, m_Arg) + uiArgSize_p); EplEvent.m_pArg = &EventError; // post errorevent Ret = EplEventkPost(&EplEvent); return Ret; }
//--------------------------------------------------------------------------- // // Function: EplTimeruModifyTimerMs // // Description: function change a timer and return a handle to the pointer // // // // Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle // ulTime_p = time for timer in ms // Argument_p = argument for timer // // // Returns: tEplKernel = errorcode // // // State: // //--------------------------------------------------------------------------- tEplKernel PUBLIC EplTimeruModifyTimerMs(tEplTimerHdl * pTimerHdl_p, unsigned long ulTime_p, tEplTimerArg Argument_p) { tEplKernel Ret; HANDLE DeleteHandle; HANDLE ThreadHandle; DWORD ThreadId; Ret = kEplSuccessful; // check parameter if (pTimerHdl_p == NULL) { Ret = kEplTimerInvalidHandle; goto Exit; } DeleteHandle = (HANDLE) (*pTimerHdl_p); // set event to end timer task for this timer SetEvent(DeleteHandle); // create new timer // first create event to delete timer DeleteHandle = CreateEvent(NULL, FALSE, FALSE, NULL); if (DeleteHandle == NULL) { Ret = kEplTimerNoTimerCreated; goto Exit; } // set handle for caller *pTimerHdl_p = (tEplTimerHdl) DeleteHandle; // enter critical section EnterCriticalSection(EplTimeruInstance_g.m_pCriticalSection); // fill data for thread ThreadData_l.DelteHandle = DeleteHandle; EPL_MEMCPY(&ThreadData_l.TimerArgument, &Argument_p, sizeof(tEplTimerArg)); ThreadData_l.ulTimeout = ulTime_p; // create thread to create waitable timer and wait for timer ThreadHandle = CreateThread(NULL, 0, EplSdoTimeruThreadms, &ThreadData_l, 0, &ThreadId); if (ThreadHandle == NULL) { // leave critical section LeaveCriticalSection(EplTimeruInstance_g.m_pCriticalSection); // delte handle Ret = kEplTimerNoTimerCreated; goto Exit; } Exit: return Ret; }
static tEplKernel EplIdentuCbIdentResponse(tEplFrameInfo *pFrameInfo_p) { tEplKernel Ret = kEplSuccessful; unsigned int uiNodeId; unsigned int uiIndex; tEplIdentuCbResponse pfnCbResponse; uiNodeId = AmiGetByteFromLe(&pFrameInfo_p->m_pFrame->m_le_bSrcNodeId); uiIndex = uiNodeId - 1; if (uiIndex < tabentries(EplIdentuInstance_g.m_apfnCbResponse)) { // memorize pointer to callback function pfnCbResponse = EplIdentuInstance_g.m_apfnCbResponse[uiIndex]; // reset callback function pointer so that caller may issue next request immediately EplIdentuInstance_g.m_apfnCbResponse[uiIndex] = NULL; if (pFrameInfo_p->m_uiFrameSize < EPL_C_DLL_MINSIZE_IDENTRES) { // IdentResponse not received or it has invalid size if (pfnCbResponse == NULL) { // response was not requested goto Exit; } Ret = pfnCbResponse(uiNodeId, NULL); } else { // IdentResponse received if (EplIdentuInstance_g.m_apIdentResponse[uiIndex] == NULL) { // memory for IdentResponse must be allocated EplIdentuInstance_g.m_apIdentResponse[uiIndex] = EPL_MALLOC(sizeof(tEplIdentResponse)); if (EplIdentuInstance_g.m_apIdentResponse[uiIndex] == NULL) { // malloc failed if (pfnCbResponse == NULL) { // response was not requested goto Exit; } Ret = pfnCbResponse(uiNodeId, &pFrameInfo_p-> m_pFrame->m_Data. m_Asnd.m_Payload. m_IdentResponse); goto Exit; } } // copy IdentResponse to instance structure EPL_MEMCPY(EplIdentuInstance_g. m_apIdentResponse[uiIndex], &pFrameInfo_p->m_pFrame->m_Data.m_Asnd. m_Payload.m_IdentResponse, sizeof(tEplIdentResponse)); if (pfnCbResponse == NULL) { // response was not requested goto Exit; } Ret = pfnCbResponse(uiNodeId, EplIdentuInstance_g. m_apIdentResponse[uiIndex]); } } Exit: return Ret; }
tEplKernel PUBLIC EplApiInitialize(tEplApiInitParam * pInitParam_p) { tEplKernel Ret = kEplSuccessful; const char* pszDrvName; // driver name int iRet; // reset instance structure EPL_MEMSET(&EplApiInstance_g, 0, sizeof (EplApiInstance_g)); EPL_MEMCPY(&EplApiInstance_g.m_InitParam, pInitParam_p, (sizeof (tEplApiInitParam) < pInitParam_p->m_uiSizeOfStruct) ? sizeof (tEplApiInitParam) : pInitParam_p->m_uiSizeOfStruct); // check event callback function pointer if (EplApiInstance_g.m_InitParam.m_pfnCbEvent == NULL) { // application must always have an event callback function Ret = kEplApiInvalidParam; goto Exit; } pszDrvName = "/dev/"EPLLIN_DEV_NAME; EplApiInstance_g.m_hDrvInst = -1; // open driver TRACE1("EPL: Try to open driver '%s'\n", pszDrvName); EplApiInstance_g.m_hDrvInst = open (pszDrvName, O_RDWR); if (EplApiInstance_g.m_hDrvInst > -1) { TRACE2("EPL: open '%s' successful -> hDrvInst=%d\n", pszDrvName, EplApiInstance_g.m_hDrvInst); } else { TRACE1("EPL: ERROR: Can't open '%s'\n", pszDrvName); Ret = kEplNoResource; goto Exit; } // initialize hardware iRet = ioctl (EplApiInstance_g.m_hDrvInst, EPLLIN_CMD_INITIALIZE, (unsigned long)&EplApiInstance_g.m_InitParam); if (iRet < 0) { Ret = kEplNoResource; goto Exit; } else { Ret = (tEplKernel)iRet; } // the application must start NMT state machine // via EplApiExecNmtCommand(kEplNmtEventSwReset) // and thereby the whole EPL stack :-) /*#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0) Ret = EplNmtuNmtEvent(kEplNmtEventSwReset); #endif*/ Exit: return Ret; }
tEplKernel PUBLIC EplTimeruProcess(void) { tTimerEntry* pTimerEntry; DWORD dwTimeoutMs; tEplEvent EplEvent; tEplTimerEventArg TimerEventArg; tEplKernel Ret; Ret = kEplSuccessful; EplTimeruEnterCriticalSection(TIMERU_TIMER_LIST); // calculate elapsed time since start time dwTimeoutMs = EplTimeruGetTickCountMs() - EplTimeruInstance_g.m_dwStartTimeMs; // observe first timer entry in timer list pTimerEntry = EplTimeruInstance_g.m_pTimerListFirst; if (pTimerEntry != NULL) { if (dwTimeoutMs >= pTimerEntry->m_dwTimeoutMs) { // timeout elapsed // remove entry from timer list EplTimeruInstance_g.m_pTimerListFirst = pTimerEntry->m_pNext; // adjust start time EplTimeruInstance_g.m_dwStartTimeMs += pTimerEntry->m_dwTimeoutMs; } else { pTimerEntry = NULL; } } EplTimeruLeaveCriticalSection(TIMERU_TIMER_LIST); if (pTimerEntry != NULL) { // call event function TimerEventArg.m_TimerHdl = (tEplTimerHdl) pTimerEntry; EPL_MEMCPY(&TimerEventArg.m_Arg, &pTimerEntry->m_TimerArg.m_Arg, sizeof (TimerEventArg.m_Arg)); EplEvent.m_EventSink = pTimerEntry->m_TimerArg.m_EventSink; EplEvent.m_EventType = kEplEventTypeTimer; EPL_MEMSET(&EplEvent.m_NetTime, 0x00, sizeof(tEplNetTime)); EplEvent.m_pArg = &TimerEventArg; EplEvent.m_uiSize = sizeof(TimerEventArg); Ret = EplEventuPost(&EplEvent); } return Ret; }
//--------------------------------------------------------------------------- // // Function: VEthAddInstance // // Description: Add a VEth instance // // Parameters: abSrcMac_p = The MAC Address to set // // Returns: tEplKernel = error code // // // State: // //--------------------------------------------------------------------------- tEplKernel PUBLIC VEthAddInstance(const BYTE abSrcMac_p[6]) { tEplKernel Ret = kEplSuccessful; EPL_MEMSET(&VEthInstance_g, 0 , sizeof(VEthInstance_g)); EPL_MEMCPY(VEthInstance_g.m_abEthMac, abSrcMac_p, sizeof(VEthInstance_g.m_abEthMac) ); Ret = VEthOpen(); if(Ret != kEplSuccessful) { EPL_DBGLVL_VETH_TRACE("VEthOpen: returned 0x%02X\n", Ret); } return Ret; }
tEplKernel PUBLIC EplApiProcessImageExchangeOut(tEplApiProcessImage* pPI_p) { tEplKernel Ret = kEplSuccessful; #if EPL_API_PROCESS_IMAGE_SIZE_OUT > 0 #if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) copy_from_user(EplApiProcessImageInstance_g.m_abProcessImageOutput, pPI_p->m_pImage, min(pPI_p->m_uiSize, sizeof (EplApiProcessImageInstance_g.m_abProcessImageOutput))); #else EPL_MEMCPY(EplApiProcessImageInstance_g.m_abProcessImageOutput, pPI_p->m_pImage, min(pPI_p->m_uiSize, sizeof (EplApiProcessImageInstance_g.m_abProcessImageOutput))); #endif #endif return Ret; }
tEplKernel EplTimeruModifyTimerMs(tEplTimerHdl *pTimerHdl_p, unsigned long ulTime_p, tEplTimerArg Argument_p) { tEplKernel Ret = kEplSuccessful; tEplTimeruData *pData; // check pointer to handle if (pTimerHdl_p == NULL) { Ret = kEplTimerInvalidHandle; goto Exit; } // check handle itself, i.e. was the handle initialized before if (*pTimerHdl_p == 0) { Ret = EplTimeruSetTimerMs(pTimerHdl_p, ulTime_p, Argument_p); goto Exit; } pData = (tEplTimeruData *) * pTimerHdl_p; if ((tEplTimeruData *) pData->m_Timer.data != pData) { Ret = kEplTimerInvalidHandle; goto Exit; } mod_timer(&pData->m_Timer, (jiffies + ulTime_p * HZ / 1000)); // copy the TimerArg after the timer is restarted, // so that a timer occured immediately before mod_timer // won't use the new TimerArg and // therefore the old timer cannot be distinguished from the new one. // But if the new timer is too fast, it may get lost. EPL_MEMCPY(&pData->TimerArgument, &Argument_p, sizeof(tEplTimerArg)); // check if timer is really running if (timer_pending(&pData->m_Timer) == 0) { // timer is not running // retry starting it add_timer(&pData->m_Timer); } // set handle to pointer of tEplTimeruData // *pTimerHdl_p = (tEplTimerHdl) pData; Exit: return Ret; }
/*----------------------------------------------------------------------------*\ Init method for the Powerlink module \*----------------------------------------------------------------------------*/ static pwr_tStatus IoAgentInit (io_tCtx ctx, io_sAgent *ap) { io_sLocalEpl_MN *local; int sts; pwr_sClass_Epl_MN *op = (pwr_sClass_Epl_MN *)ap->op; local = (io_sLocalEpl_MN *) calloc( 1, sizeof(io_sLocalEpl_MN)); ap->Local = local; local->inputResetEnabled = 0; op->NumberOfSlaves = 0; static tEplApiInitParam EplApiInitParam; tEplKernel EplRet = kEplSuccessful; pwr_tFileName cdc_file; char* sHostname = malloc(1023); if ( strchr(op->CDCfile, '/') != 0) strcpy( cdc_file, op->CDCfile); else { strcpy( cdc_file, "$pwrp_load/"); strcat( cdc_file, op->CDCfile); } dcli_translate_filename( cdc_file, cdc_file); gethostname(sHostname, 1023); if( op->StallAction == pwr_eStallActionEnum_ResetInputs) local->inputResetEnabled = 1; // Init the I/O area unsigned int input_area_offset = 0; unsigned int input_area_chansize = 0; unsigned int output_area_offset = 0; unsigned int output_area_chansize = 0; io_sRack *rp; io_sCard *cp; pwr_tCid cid; for ( rp = ap->racklist; rp; rp = rp->next) { rp->Local = calloc( 1, sizeof(io_sLocalEpl_CN)); rp->MethodDisabled = 1; op->NumberOfSlaves++; if( ((pwr_sClass_Epl_CN *)rp->op)->StallAction == pwr_eStallActionEnum_ResetInputs) local->inputResetEnabled = 1; // Show device offset and size if ( rp->Class == pwr_cClass_Epl_CN && rp->op) { ((pwr_sClass_Epl_CN *)rp->op)->InputAreaOffset = input_area_offset + input_area_chansize; ((pwr_sClass_Epl_CN *)rp->op)->OutputAreaOffset = output_area_offset + output_area_chansize; } // Get byte ordering pwr_tAName name; pwr_tEnum byte_ordering; strcpy( name, rp->Name); strcat( name, ".ByteOrdering"); sts = gdh_GetObjectInfo( name, &byte_ordering, sizeof(byte_ordering)); if ( ODD(sts)) ((io_sLocalEpl_CN *)rp->Local)->byte_ordering = byte_ordering; else ((io_sLocalEpl_CN *)rp->Local)->byte_ordering = pwr_eByteOrderingEnum_LittleEndian; for ( cp = rp->cardlist; cp; cp = cp->next) { cid = cp->Class; while ( ODD( gdh_GetSuperClass( cid, &cid, cp->Objid))) ; cp->MethodDisabled = 1; // Show module offset and size if ( cid == pwr_cClass_Epl_Module && cp->op) { ((pwr_sClass_Epl_Module *)cp->op)->InputAreaOffset = input_area_offset + input_area_chansize; ((pwr_sClass_Epl_Module *)cp->op)->OutputAreaOffset = output_area_offset + output_area_chansize; } io_bus_card_init( ctx, cp, &input_area_offset, &input_area_chansize, &output_area_offset, &output_area_chansize, byte_ordering, io_eAlignment_Powerlink); // Show module offset and size if ( cid == pwr_cClass_Epl_Module && cp->op) { ((pwr_sClass_Epl_Module *)cp->op)->InputAreaSize = input_area_offset + input_area_chansize - ((pwr_sClass_Epl_Module *)cp->op)->InputAreaOffset; ((pwr_sClass_Epl_Module *)cp->op)->OutputAreaSize = output_area_offset + output_area_chansize - ((pwr_sClass_Epl_Module *)cp->op)->OutputAreaOffset; } if(rp->next == NULL) { if(cp->next == NULL) { ((pwr_sClass_Epl_Module *)cp->op)->InputAreaSize += pwr_Align(input_area_offset + input_area_chansize, 4) - (input_area_offset + input_area_chansize); ((pwr_sClass_Epl_Module *)cp->op)->OutputAreaSize += pwr_Align(output_area_offset + output_area_chansize, 4) - (output_area_offset + output_area_chansize); } } } // Show slave offset and size if ( rp->Class == pwr_cClass_Epl_CN && rp->op) { ((pwr_sClass_Epl_CN *)rp->op)->InputAreaSize = input_area_offset + input_area_chansize - ((pwr_sClass_Epl_CN *)rp->op)->InputAreaOffset; ((pwr_sClass_Epl_CN *)rp->op)->OutputAreaSize = output_area_offset + output_area_chansize - ((pwr_sClass_Epl_CN *)rp->op)->OutputAreaOffset; if(rp->next == NULL) { ((pwr_sClass_Epl_CN *)rp->op)->InputAreaSize += pwr_Align(input_area_offset + input_area_chansize, 4) - (input_area_offset + input_area_chansize); ((pwr_sClass_Epl_CN *)rp->op)->OutputAreaSize += pwr_Align(output_area_offset + output_area_chansize, 4) - (output_area_offset + output_area_chansize); } } } // This is the calculated in- and outputarea size local->input_area_size = pwr_Align(input_area_offset + input_area_chansize, 4); local->output_area_size = pwr_Align(output_area_offset + output_area_chansize, 4); // Show agent in- and output area size op->InputAreaSize = local->input_area_size; op->OutputAreaSize = local->output_area_size; struct sched_param schedParam; // adjust process priority // push nice level in case we have no RTPreempt if (nice (-20) == -1) { errh_Error("%s() couldn't set nice value! (%s)", __func__, strerror(errno)); } //schedParam.sched_priority = MIN(sched_get_priority_max(SCHED_FIFO), // sched_get_priority_min(SCHED_FIFO) + op->Priority); schedParam.__sched_priority = op->Priority; if (pthread_setschedparam(pthread_self(), SCHED_RR, &schedParam) != 0) { errh_Error("%s() couldn't set thread scheduling parameters! %d", __func__, schedParam.__sched_priority); } // binds all openPOWERLINK threads to the second CPU core cpu_set_t affinity; CPU_ZERO(&affinity); CPU_SET(1, &affinity); sched_setaffinity(0, sizeof(cpu_set_t), &affinity); // Initialize target specific stuff EplTgtInit(); EPL_MEMSET(&EplApiInitParam, 0, sizeof (EplApiInitParam)); EplApiInitParam.m_uiSizeOfStruct = sizeof (EplApiInitParam); EplApiInitParam.m_pEventUserArg = ap; // Get devicename from attribute in agent EplApiInitParam.m_HwParam.m_pszDevName = op->Device; // Get nodeid from attribute in agent EplApiInitParam.m_uiNodeId = op->NodeId; EplApiInitParam.m_dwIpAddress = ntohl( inet_addr( op->IpAddress)); // write 00:00:00:00:00:00 to MAC address, so that the driver uses the real hardware address EPL_MEMCPY(EplApiInitParam.m_abMacAddress, abMacAddr, sizeof (EplApiInitParam.m_abMacAddress)); EplApiInitParam.m_fAsyncOnly = FALSE; EplApiInitParam.m_dwFeatureFlags = -1; // required for error detection EplApiInitParam.m_dwCycleLen = uiCycleLen_g; // const EplApiInitParam.m_uiIsochrTxMaxPayload = 256; // const EplApiInitParam.m_uiIsochrRxMaxPayload = 256; // const; only required for IdentRes EplApiInitParam.m_dwPresMaxLatency = 50000; // required for initialisation (+28 bytes) EplApiInitParam.m_uiPreqActPayloadLimit = 36; // required for initialisation of Pres frame (+28 bytes) EplApiInitParam.m_uiPresActPayloadLimit = 36; // const; only required for IdentRes EplApiInitParam.m_dwAsndMaxLatency = 150000; // required for error detection EplApiInitParam.m_uiMultiplCycleCnt = 0; // required to set up max frame size EplApiInitParam.m_uiAsyncMtu = 1500; // required for sync EplApiInitParam.m_uiPrescaler = 2; EplApiInitParam.m_dwLossOfFrameTolerance = 500000; EplApiInitParam.m_dwAsyncSlotTimeout = 3000000; EplApiInitParam.m_dwWaitSocPreq = 150000; // NMT_DeviceType_U32 EplApiInitParam.m_dwDeviceType = -1; // NMT_IdentityObject_REC.VendorId_U32 EplApiInitParam.m_dwVendorId = -1; // NMT_IdentityObject_REC.ProductCode_U32 EplApiInitParam.m_dwProductCode = -1; // NMT_IdentityObject_REC.RevisionNo_U32 EplApiInitParam.m_dwRevisionNumber = -1; // NMT_IdentityObject_REC.SerialNo_U32 EplApiInitParam.m_dwSerialNumber = -1; EplApiInitParam.m_dwSubnetMask = ntohl( inet_addr( op->IpNetmask)); EplApiInitParam.m_dwDefaultGateway = 0; EPL_MEMCPY(EplApiInitParam.m_sHostname, sHostname, sizeof(EplApiInitParam.m_sHostname)); EplApiInitParam.m_uiSyncNodeId = EPL_C_ADR_SYNC_ON_SOA; EplApiInitParam.m_fSyncOnPrcNode = FALSE; // set callback functions EplApiInitParam.m_pfnCbEvent = (tEplApiCbEvent)AppCbEvent; EplApiInitParam.m_pfnObdInitRam = EplObdInitRam; EplApiInitParam.m_pfnCbSync = AppCbSync; // initialize POWERLINK stack EplRet = EplApiInitialize(&EplApiInitParam); if(EplRet != kEplSuccessful) { errh_Error("EplApiInitialize() failed (Error:0x%x!", EplRet); goto Exit; } EplRet = EplApiSetCdcFilename(cdc_file); if(EplRet != kEplSuccessful) { goto Exit; } // Allocate memory for the in- and outputareas if( local->output_area_size > 0) AppProcessImageIn_g = malloc(local->output_area_size); if( local->input_area_size > 0) { AppProcessImageOut_g = malloc(local->input_area_size); } // Save pointer to in- and outputareas in THIS agent object local->input_area = AppProcessImageOut_g; local->output_area = AppProcessImageIn_g; if( local->inputResetEnabled && local->input_area_size > 0) local->tmp_area = malloc(local->input_area_size); else local->tmp_area = local->input_area; AppProcessImageCopyJob_g.m_fNonBlocking = FALSE; AppProcessImageCopyJob_g.m_uiPriority = 0; AppProcessImageCopyJob_g.m_In.m_pPart = AppProcessImageIn_g; AppProcessImageCopyJob_g.m_In.m_uiOffset = 0; AppProcessImageCopyJob_g.m_In.m_uiSize = local->output_area_size; AppProcessImageCopyJob_g.m_Out.m_pPart = AppProcessImageOut_g; AppProcessImageCopyJob_g.m_Out.m_uiOffset = 0; AppProcessImageCopyJob_g.m_Out.m_uiSize = local->input_area_size; EplRet = EplApiProcessImageAlloc(local->output_area_size, local->input_area_size, 2, 2); if (EplRet != kEplSuccessful) { goto Exit; } EplRet = EplApiProcessImageSetup(); if (EplRet != kEplSuccessful) { goto Exit; } // start processing EplRet = EplApiExecNmtCommand(kEplNmtEventSwReset); if (EplRet != kEplSuccessful) { IoAgentClose(NULL, NULL); goto Exit; } errh_Success ("Powerlink init successfull"); return IO__SUCCESS; Exit: errh_Error("IoCardInit: returns 0x%X", EplRet); return IO__SUCCESS; }
static tEplKernel EplApiProcessImageExchangeIntUserPages( tEplApiProcessImageCopyJobInt* pCopyJob_p) { tEplKernel Ret = kEplSuccessful; unsigned int nIndex; struct page** ppPage; unsigned long ulOffset; unsigned long ulLength; unsigned long ulSize; void* pPIVar; tEplApiProcessImagePart* pPart; void* pVirtUserPart; // copy input image ppPage = pCopyJob_p->m_Event.m_pCompletion->m_apPageIn; pPart = &pCopyJob_p->m_CopyJob.m_In; if ((pPart->m_uiSize > 0) && (pPart->m_pPart != NULL) && (EplApiProcessImageInstance_g.m_In.m_pImage != NULL) && ((pPart->m_uiOffset + pPart->m_uiSize) <= EplApiProcessImageInstance_g.m_In.m_uiSize)) { pPIVar = ((BYTE*) EplApiProcessImageInstance_g.m_In.m_pImage) + pPart->m_uiOffset; ulOffset = ((unsigned long)pPart->m_pPart) & (PAGE_SIZE - 1); ulLength = 0; for (nIndex = 0; nIndex < EPL_API_PI_PAGE_COUNT; nIndex++) { if (ppPage[nIndex] == NULL) { break; } ulSize = min ((PAGE_SIZE - ulOffset), pPart->m_uiSize - ulLength); #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) pVirtUserPart = kmap_atomic(ppPage[nIndex], KM_USER0); #else pVirtUserPart = kmap_atomic(ppPage[nIndex]); #endif EPL_MEMCPY(pPIVar, pVirtUserPart + ulOffset, ulSize); #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) kunmap_atomic(pVirtUserPart, KM_USER0); #else kunmap_atomic(pVirtUserPart); #endif pPIVar += ulSize; ulLength += ulSize; ulOffset = 0; if (ulLength >= pPart->m_uiSize) { break; } } } // copy output image ppPage = pCopyJob_p->m_Event.m_pCompletion->m_apPageOut; pPart = &pCopyJob_p->m_CopyJob.m_Out; if ((pPart->m_uiSize > 0) && (pPart->m_pPart != NULL) && (EplApiProcessImageInstance_g.m_Out.m_pImage != NULL) && ((pPart->m_uiOffset + pPart->m_uiSize) <= EplApiProcessImageInstance_g.m_Out.m_uiSize)) { pPIVar = ((BYTE*) EplApiProcessImageInstance_g.m_Out.m_pImage) + pPart->m_uiOffset; ulOffset = ((unsigned long)pPart->m_pPart) & (PAGE_SIZE - 1); ulLength = 0; for (nIndex = 0; nIndex < EPL_API_PI_PAGE_COUNT; nIndex++) { if (ppPage[nIndex] == NULL) { break; } ulSize = min ((PAGE_SIZE - ulOffset), pPart->m_uiSize - ulLength); #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) pVirtUserPart = kmap_atomic(ppPage[nIndex], KM_USER0); #else pVirtUserPart = kmap_atomic(ppPage[nIndex]); #endif EPL_MEMCPY(pVirtUserPart + ulOffset, pPIVar, ulSize); #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) kunmap_atomic(pVirtUserPart, KM_USER0); #else kunmap_atomic(pVirtUserPart); #endif pPIVar += ulSize; ulLength += ulSize; ulOffset = 0; if (ulLength >= pPart->m_uiSize) { break; } } } return Ret; }
static tEplKernel EplApiProcessImageExchangeInt( tEplApiProcessImageCopyJob* pCopyJob_p) { tEplKernel Ret = kEplSuccessful; if (pCopyJob_p->m_In.m_uiSize > 0) { if ((pCopyJob_p->m_In.m_pPart != NULL) && (EplApiProcessImageInstance_g.m_In.m_pImage != NULL) && ((pCopyJob_p->m_In.m_uiOffset + pCopyJob_p->m_In.m_uiSize) <= EplApiProcessImageInstance_g.m_In.m_uiSize)) { void* pPIVar = ((BYTE*) EplApiProcessImageInstance_g.m_In.m_pImage) + pCopyJob_p->m_In.m_uiOffset; #if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) int iErr; iErr = copy_from_user(pPIVar, pCopyJob_p->m_In.m_pPart, pCopyJob_p->m_In.m_uiSize); if (iErr != 0) { PRINTF("%s: copy_from_user(%p, %p, %u) returned %i\n", __func__, pPIVar, pCopyJob_p->m_In.m_pPart, pCopyJob_p->m_In.m_uiSize, iErr); Ret = kEplApiPIInvalidPIPointer; goto Exit; } #else EPL_MEMCPY(pPIVar, pCopyJob_p->m_In.m_pPart, pCopyJob_p->m_In.m_uiSize); #endif } } if (pCopyJob_p->m_Out.m_uiSize > 0) { if ((pCopyJob_p->m_Out.m_pPart != NULL) && (EplApiProcessImageInstance_g.m_Out.m_pImage != NULL) && ((pCopyJob_p->m_Out.m_uiOffset + pCopyJob_p->m_Out.m_uiSize) <= EplApiProcessImageInstance_g.m_Out.m_uiSize)) { void* pPIVar = ((BYTE*) EplApiProcessImageInstance_g.m_Out.m_pImage) + pCopyJob_p->m_Out.m_uiOffset; #if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) int iErr; iErr = copy_to_user(pCopyJob_p->m_Out.m_pPart, pPIVar, pCopyJob_p->m_Out.m_uiSize); if (iErr != 0) { PRINTF("%s: copy_to_user(%p, %p, %u) returned %i\n", __func__, pCopyJob_p->m_Out.m_pPart, pPIVar, pCopyJob_p->m_Out.m_uiSize, iErr); Ret = kEplApiPIInvalidPIPointer; goto Exit; } #else EPL_MEMCPY(pCopyJob_p->m_Out.m_pPart, pPIVar, pCopyJob_p->m_Out.m_uiSize); #endif } } #if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) Exit: #endif return Ret; }
//--------------------------------------------------------------------------- // // Function: EplLinInit // // Description: Entry point of kernel module //// // // Parameters: N/A // // // Returns: Return code // //--------------------------------------------------------------------------- static int __init EplLinInit (void) { tEplKernel EplRet; static tEplApiInitParam EplApiInitParam = {0}; char* sHostname = HOSTNAME; BOOL fApiInit = FALSE; BOOL fLinProcInit =FALSE; atomic_set(&AtomicShutdown_g, TRUE); // open character device from debugfs to disable tracing when necessary hAppFdTracingEnabled_g = open("/sys/kernel/debug/tracing/tracing_enabled", O_WRONLY, 0666); // get node ID from insmod command line EplApiInitParam.m_uiNodeId = uiNodeId_g; if (EplApiInitParam.m_uiNodeId == EPL_C_ADR_INVALID) { // invalid node ID set // set default node ID EplApiInitParam.m_uiNodeId = NODEID; } uiNodeId_g = EplApiInitParam.m_uiNodeId; // calculate IP address EplApiInitParam.m_dwIpAddress = (0xFFFFFF00 & IP_ADDR) | EplApiInitParam.m_uiNodeId; EplApiInitParam.m_fAsyncOnly = FALSE; EplApiInitParam.m_uiSizeOfStruct = sizeof (EplApiInitParam); EPL_MEMCPY(EplApiInitParam.m_abMacAddress, abMacAddr, sizeof (EplApiInitParam.m_abMacAddress)); EplApiInitParam.m_dwFeatureFlags = (DWORD) ~0UL; EplApiInitParam.m_dwCycleLen = uiCycleLen_g; // required for error detection EplApiInitParam.m_uiIsochrTxMaxPayload = 100; // const EplApiInitParam.m_uiIsochrRxMaxPayload = 100; // const EplApiInitParam.m_dwPresMaxLatency = 50000; // const; only required for IdentRes EplApiInitParam.m_uiPreqActPayloadLimit = 36; // required for initialisation (+28 bytes) EplApiInitParam.m_uiPresActPayloadLimit = 36; // required for initialisation of Pres frame (+28 bytes) EplApiInitParam.m_dwAsndMaxLatency = 150000; // const; only required for IdentRes EplApiInitParam.m_uiMultiplCycleCnt = 0; // required for error detection EplApiInitParam.m_uiAsyncMtu = 1500; // required to set up max frame size EplApiInitParam.m_uiPrescaler = 2; // required for sync EplApiInitParam.m_dwLossOfFrameTolerance = 500000; EplApiInitParam.m_dwAsyncSlotTimeout = 3000000; EplApiInitParam.m_dwWaitSocPreq = 150000; EplApiInitParam.m_dwDeviceType = (DWORD) ~0UL; // NMT_DeviceType_U32 EplApiInitParam.m_dwVendorId = (DWORD) ~0UL; // NMT_IdentityObject_REC.VendorId_U32 EplApiInitParam.m_dwProductCode = (DWORD) ~0UL; // NMT_IdentityObject_REC.ProductCode_U32 EplApiInitParam.m_dwRevisionNumber = (DWORD) ~0UL; // NMT_IdentityObject_REC.RevisionNo_U32 EplApiInitParam.m_dwSerialNumber = (DWORD) ~0UL; // NMT_IdentityObject_REC.SerialNo_U32 EplApiInitParam.m_dwSubnetMask = SUBNET_MASK; EplApiInitParam.m_dwDefaultGateway = 0; EPL_MEMCPY(EplApiInitParam.m_sHostname, sHostname, sizeof(EplApiInitParam.m_sHostname)); EplApiInitParam.m_uiSyncNodeId = EPL_C_ADR_SYNC_ON_SOA; EplApiInitParam.m_fSyncOnPrcNode = FALSE; // set callback functions EplApiInitParam.m_pfnCbEvent = AppCbEvent; EplApiInitParam.m_pfnCbSync = AppCbSync; EplApiInitParam.m_pfnObdInitRam = EplObdInitRam; printk("\n\n Hello, I'm a simple POWERLINK node running as %s!\n (build: %s / %s)\n\n", (uiNodeId_g == EPL_C_ADR_MN_DEF_NODE_ID ? "Managing Node" : "Controlled Node"), __DATE__, __TIME__); // initialize the Linux a wait queue for shutdown of this module init_waitqueue_head(&WaitQueueShutdown_g); // initialize the procfs device EplRet = EplLinProcInit(); if (EplRet != kEplSuccessful) { PRINTF("EplLinProcInit failed!\n"); goto Exit; } fLinProcInit = TRUE; // initialize POWERLINK stack EplRet = EplApiInitialize(&EplApiInitParam); if(EplRet != kEplSuccessful) { PRINTF("EplApiInitialize failed!\n"); goto Exit; } fApiInit = TRUE; EplRet = EplApiSetCdcFilename(pszCdcFilename_g); if(EplRet != kEplSuccessful) { goto Exit; } PRINTF("Initializing process image...\n"); PRINTF("Size of input process image: %ld\n", sizeof(AppProcessImageIn_g)); PRINTF("Size of output process image: %ld\n", sizeof (AppProcessImageOut_g)); AppProcessImageCopyJob_g.m_fNonBlocking = FALSE; AppProcessImageCopyJob_g.m_uiPriority = 0; AppProcessImageCopyJob_g.m_In.m_pPart = &AppProcessImageIn_g; AppProcessImageCopyJob_g.m_In.m_uiOffset = 0; AppProcessImageCopyJob_g.m_In.m_uiSize = sizeof (AppProcessImageIn_g); AppProcessImageCopyJob_g.m_Out.m_pPart = &AppProcessImageOut_g; AppProcessImageCopyJob_g.m_Out.m_uiOffset = 0; AppProcessImageCopyJob_g.m_Out.m_uiSize = sizeof (AppProcessImageOut_g); EplRet = EplApiProcessImageAlloc(sizeof (AppProcessImageIn_g), sizeof (AppProcessImageOut_g), 2, 2); if (EplRet != kEplSuccessful) { goto Exit; } EplRet = EplApiProcessImageSetup(); if (EplRet != kEplSuccessful) { goto Exit; } // start the NMT state machine EplRet = EplApiExecNmtCommand(kEplNmtEventSwReset); atomic_set(&AtomicShutdown_g, FALSE); Exit: PRINTF("EplLinInit(): returns 0x%X\n", EplRet); if (EplRet != kEplSuccessful) { if (fApiInit != FALSE) { EplApiShutdown(); } if (fLinProcInit != FALSE) { EplLinProcFree(); } return -ENODEV; } else { return 0; } }
tEplKernel EplDllkCalAsyncSend(tEplFrameInfo * pFrameInfo_p, tEplDllAsyncReqPriority Priority_p) { tEplKernel Ret = kEplSuccessful; tEplEvent Event; #if EPL_USE_SHAREDBUFF != FALSE tShbError ShbError; switch (Priority_p) { case kEplDllAsyncReqPrioNmt: // NMT request priority ShbError = ShbCirWriteDataBlock (EplDllkCalInstance_g.m_ShbInstanceTxNmt, pFrameInfo_p->m_pFrame, pFrameInfo_p->m_uiFrameSize); // returns kShbOk, kShbExceedDataSizeLimit, kShbBufferFull, kShbInvalidArg break; default: // generic priority ShbError = ShbCirWriteDataBlock (EplDllkCalInstance_g.m_ShbInstanceTxGen, pFrameInfo_p->m_pFrame, pFrameInfo_p->m_uiFrameSize); // returns kShbOk, kShbExceedDataSizeLimit, kShbBufferFull, kShbInvalidArg break; } // error handling switch (ShbError) { case kShbOk: break; case kShbExceedDataSizeLimit: Ret = kEplDllAsyncTxBufferFull; break; case kShbBufferFull: Ret = kEplDllAsyncTxBufferFull; break; case kShbInvalidArg: default: Ret = kEplNoResource; break; } #else switch (Priority_p) { case kEplDllAsyncReqPrioNmt: // NMT request priority if (EplDllkCalInstance_g.m_uiFrameSizeNmt == 0) { EPL_MEMCPY(EplDllkCalInstance_g.m_abFrameNmt, pFrameInfo_p->m_pFrame, pFrameInfo_p->m_uiFrameSize); EplDllkCalInstance_g.m_uiFrameSizeNmt = pFrameInfo_p->m_uiFrameSize; } else { Ret = kEplDllAsyncTxBufferFull; goto Exit; } break; default: // generic priority if (EplDllkCalInstance_g.m_uiFrameSizeGen == 0) { EPL_MEMCPY(EplDllkCalInstance_g.m_abFrameGen, pFrameInfo_p->m_pFrame, pFrameInfo_p->m_uiFrameSize); EplDllkCalInstance_g.m_uiFrameSizeGen = pFrameInfo_p->m_uiFrameSize; } else { Ret = kEplDllAsyncTxBufferFull; goto Exit; } break; } #endif // post event to DLL Event.m_EventSink = kEplEventSinkDllk; Event.m_EventType = kEplEventTypeDllkFillTx; EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime)); Event.m_pArg = &Priority_p; Event.m_uiSize = sizeof(Priority_p); Ret = EplEventkPost(&Event); #if EPL_USE_SHAREDBUFF == FALSE Exit: #endif return Ret; }
int openPowerlink(void) { const BYTE abMacAddr[] = {MAC_ADDR}; static tEplApiInitParam EplApiInitParam = {0}; // needed for process var tEplObdSize ObdSize; tEplKernel EplRet; unsigned int uiVarEntries; fShutdown_l = FALSE; //////////////////////// // setup th EPL Stack // //////////////////////// // set EPL init parameters EplApiInitParam.m_uiSizeOfStruct = sizeof (EplApiInitParam); #ifdef NODESWITCH_SPI_BASE // read node-ID from hex switch on baseboard, which is connected via SPI shift register IOWR_ALTERA_AVALON_SPI_TXDATA(NODESWITCH_SPI_BASE, 0xFF); // generate pulse for latching inputs while ((IORD_ALTERA_AVALON_SPI_STATUS(NODESWITCH_SPI_BASE) & ALTERA_AVALON_SPI_STATUS_RRDY_MSK) == 0) { // wait } EplApiInitParam.m_uiNodeId = IORD_ALTERA_AVALON_SPI_RXDATA(NODESWITCH_SPI_BASE); #endif #ifdef NODESWITCH_PIO_BASE EplApiInitParam.m_uiNodeId = IORD_ALTERA_AVALON_PIO_DATA(NODESWITCH_PIO_BASE); #endif if (EplApiInitParam.m_uiNodeId == EPL_C_ADR_INVALID) { EplApiInitParam.m_uiNodeId = NODEID; // defined at the top of this file! } EPL_MEMCPY(EplApiInitParam.m_abMacAddress, abMacAddr, sizeof(EplApiInitParam.m_abMacAddress)); EplApiInitParam.m_abMacAddress[5] = (BYTE) EplApiInitParam.m_uiNodeId; // calculate IP address EplApiInitParam.m_dwIpAddress = (0xFFFFFF00 & IP_ADDR) | EplApiInitParam.m_uiNodeId; EplApiInitParam.m_uiIsochrTxMaxPayload = 256; EplApiInitParam.m_uiIsochrRxMaxPayload = 256; EplApiInitParam.m_dwPresMaxLatency = 2000; EplApiInitParam.m_dwAsndMaxLatency = 2000; EplApiInitParam.m_fAsyncOnly = FALSE; EplApiInitParam.m_dwFeatureFlags = -1; EplApiInitParam.m_dwCycleLen = CYCLE_LEN; EplApiInitParam.m_uiPreqActPayloadLimit = 36; EplApiInitParam.m_uiPresActPayloadLimit = 36; EplApiInitParam.m_uiMultiplCycleCnt = 0; EplApiInitParam.m_uiAsyncMtu = 1500; EplApiInitParam.m_uiPrescaler = 2; EplApiInitParam.m_dwLossOfFrameTolerance = 500000; EplApiInitParam.m_dwAsyncSlotTimeout = 3000000; EplApiInitParam.m_dwWaitSocPreq = 0; EplApiInitParam.m_dwDeviceType = -1; EplApiInitParam.m_dwVendorId = -1; EplApiInitParam.m_dwProductCode = -1; EplApiInitParam.m_dwRevisionNumber = -1; EplApiInitParam.m_dwSerialNumber = -1; EplApiInitParam.m_dwSubnetMask = SUBNET_MASK; EplApiInitParam.m_dwDefaultGateway = 0; EplApiInitParam.m_dwApplicationSwDate = 1; // PDL_LocVerApplSw_REC.ApplSwDate_U32 on programmable device or date portion of NMT_ManufactSwVers_VS on non-programmable device EplApiInitParam.m_pfnCbEvent = AppCbEvent; EplApiInitParam.m_pfnCbSync = AppCbSync; EplApiInitParam.m_pfnObdInitRam = EplObdInitRam; EplApiInitParam.m_dwSyncResLatency = EPL_C_DLL_T_IFG; // initialize EPL stack printf("init EPL Stack with node-ID 0x%02X:\n", EplApiInitParam.m_uiNodeId); EplRet = EplApiInitialize(&EplApiInitParam); if(EplRet != kEplSuccessful) { printf("init EPL Stack... error %X\n\n", EplRet); goto Exit; } printf("init EPL Stack...ok\n\n"); // link process variables used by CN to object dictionary printf("linking process vars:\n"); ObdSize = sizeof(bButtonInputs_l); uiVarEntries = 1; EplRet = EplApiLinkObject(0x6000, &bButtonInputs_l, &uiVarEntries, &ObdSize, 0x01); if (EplRet != kEplSuccessful) { printf("linking process vars... error\n\n"); goto ExitShutdown; } ObdSize = sizeof(abVirtualInputs_l[0]); uiVarEntries = 17; EplRet = EplApiLinkObject(0x2000, abVirtualInputs_l, &uiVarEntries, &ObdSize, 0x01); if (EplRet != kEplSuccessful) { printf("linking process vars... error\n\n"); goto ExitShutdown; } ObdSize = sizeof(adwVirtualInputs_l[0]); uiVarEntries = 8; EplRet = EplApiLinkObject(0x2001, adwVirtualInputs_l, &uiVarEntries, &ObdSize, 0x01); if (EplRet != kEplSuccessful) { printf("linking process vars... error\n\n"); goto ExitShutdown; } ObdSize = sizeof(wDigitalOutputs_l); uiVarEntries = 1; EplRet = EplApiLinkObject(0x6300, &wDigitalOutputs_l, &uiVarEntries, &ObdSize, 0x01); if (EplRet != kEplSuccessful) { printf("linking process vars... error\n\n"); goto ExitShutdown; } ObdSize = sizeof(bLedOutputs_l); uiVarEntries = 1; EplRet = EplApiLinkObject(0x6200, &bLedOutputs_l, &uiVarEntries, &ObdSize, 0x01); if (EplRet != kEplSuccessful) { printf("linking process vars... error\n\n"); goto ExitShutdown; } ObdSize = sizeof(abVirtualOutputs_l[0]); uiVarEntries = 15; EplRet = EplApiLinkObject(0x2200, abVirtualOutputs_l, &uiVarEntries, &ObdSize, 0x01); if (EplRet != kEplSuccessful) { printf("linking process vars... error\n\n"); goto ExitShutdown; } ObdSize = sizeof(adwVirtualOutputs_l[0]); uiVarEntries = 8; EplRet = EplApiLinkObject(0x2201, adwVirtualOutputs_l, &uiVarEntries, &ObdSize, 0x01); if (EplRet != kEplSuccessful) { printf("linking process vars... error\n\n"); goto ExitShutdown; } printf("linking process vars... ok\n\n"); // start the EPL stack printf("start EPL Stack...\n"); EplRet = EplApiExecNmtCommand(kEplNmtEventSwReset); if (EplRet != kEplSuccessful) { printf("start EPL Stack... error\n\n"); goto ExitShutdown; } printf("start EPL Stack... ok\n\n"); printf("NIOS II with openPowerlink is ready!\n\n"); #ifdef LED_PIO_BASE IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, 0xFF); #endif while(1) { EplApiProcess(); if (fShutdown_l == TRUE) break; } ExitShutdown: printf("Shutdown EPL Stack\n"); EplApiShutdown(); //shutdown node Exit: return EplRet; }
//--------------------------------------------------------------------------- // // Function: main // // Description: main function of demo application // // Parameters: // // Returns: //--------------------------------------------------------------------------- int main (int argc, char **argv) { tEplKernel EplRet = kEplSuccessful; static tEplApiInitParam EplApiInitParam; char* sHostname = HOSTNAME; char cKey = 0; #ifdef CONFIG_POWERLINK_USERSTACK // variables for Pcap char sErr_Msg[ PCAP_ERRBUF_SIZE ]; char devName[128]; pcap_if_t * alldevs; pcap_if_t * seldev; int i = 0; int inum; #endif int opt; #if (TARGET_SYSTEM == _LINUX_) /* get command line parameters */ while ((opt = getopt(argc, argv, "c:l:")) != -1) { switch (opt) { case 'c': uiCycleLen_g = strtoul(optarg, NULL, 10); break; case 'l': pLogFile_g = optarg; break; default: /* '?' */ fprintf (stderr, "Usage: %s [-c CYCLE_TIME] [-l LOGFILE]\n", argv[0]); goto Exit; } } #endif #ifdef CONFIG_POWERLINK_USERSTACK #if (TARGET_SYSTEM == _LINUX_) struct sched_param schedParam; /* adjust process priority */ if (nice (-20) == -1) // push nice level in case we have no RTPreempt { EPL_DBGLVL_ERROR_TRACE("%s() couldn't set nice value! (%s)\n", __func__, strerror(errno)); } schedParam.__sched_priority = MAIN_THREAD_PRIORITY; if (pthread_setschedparam(pthread_self(), SCHED_RR, &schedParam) != 0) { EPL_DBGLVL_ERROR_TRACE("%s() couldn't set thread scheduling parameters! %d\n", __func__, schedParam.__sched_priority); } /* Initialize target specific stuff */ EplTgtInit(); #elif (TARGET_SYSTEM == _WIN32_) // activate realtime priority class SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS); // lower the priority of this thread SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE); #endif // (TARGET_SYSTEM == _WIN32_) #endif // CONFIG_POWERLINK_USERSTACK #if (TARGET_SYSTEM == _LINUX_) #ifdef SET_CPU_AFFINITY { /* binds all openPOWERLINK threads to the second CPU core */ cpu_set_t affinity; CPU_ZERO(&affinity); CPU_SET(1, &affinity); sched_setaffinity(0, sizeof(cpu_set_t), &affinity); } #endif #endif /* Enabling ftrace for debugging */ FTRACE_OPEN(); FTRACE_ENABLE(TRUE); /* EPL_DBGLVL_ALWAYS_TRACE("%s(): Main Thread Id:%ld\n", __func__, syscall(SYS_gettid)); */ printf("----------------------------------------------------\n"); printf("openPOWERLINK console MN DEMO application\n"); printf("----------------------------------------------------\n"); EPL_MEMSET(&EplApiInitParam, 0, sizeof (EplApiInitParam)); EplApiInitParam.m_uiSizeOfStruct = sizeof (EplApiInitParam); #ifdef CONFIG_POWERLINK_USERSTACK /* Retrieve the device list on the local machine */ if (pcap_findalldevs(&alldevs, sErr_Msg) == -1) { fprintf(stderr, "Error in pcap_findalldevs: %s\n", sErr_Msg); EplRet = kEplNoResource; goto Exit; } PRINTF("--------------------------------------------------\n"); PRINTF("List of Ethernet Cards Found in this System: \n"); PRINTF("--------------------------------------------------\n"); /* Print the list */ for (seldev = alldevs; seldev != NULL; seldev = seldev->next) { PRINTF("%d. ", ++i); if (seldev->description) { PRINTF("%s\n %s\n", seldev->description, seldev->name); } else { PRINTF("%s\n", seldev->name); } } if (i == 0) { PRINTF("\nNo interfaces found! Make sure pcap library is installed.\n"); EplRet = kEplNoResource; goto Exit; } PRINTF("--------------------------------------------------\n"); PRINTF("Select the interface to be used for POWERLINK (1-%d):",i); if (scanf("%d", &inum) == EOF) { pcap_freealldevs(alldevs); EplRet = kEplNoResource; goto Exit; } PRINTF("--------------------------------------------------\n"); if ((inum < 1) || (inum > i)) { PRINTF("\nInterface number out of range.\n"); /* Free the device list */ pcap_freealldevs(alldevs); EplRet = kEplNoResource; goto Exit; } /* Jump to the selected adapter */ for (seldev = alldevs, i = 0; i < (inum - 1); seldev = seldev->next, i++) { // do nothing } strncpy(devName, seldev->name, 127); // pass selected device name to Edrv EplApiInitParam.m_HwParam.m_pszDevName = devName; #endif EplApiInitParam.m_uiNodeId = uiNodeId_g = NODEID; EplApiInitParam.m_dwIpAddress = (0xFFFFFF00 & IP_ADDR) | EplApiInitParam.m_uiNodeId; /* write 00:00:00:00:00:00 to MAC address, so that the driver uses the real hardware address */ EPL_MEMCPY(EplApiInitParam.m_abMacAddress, abMacAddr, sizeof (EplApiInitParam.m_abMacAddress)); EplApiInitParam.m_fAsyncOnly = FALSE; EplApiInitParam.m_dwFeatureFlags = -1; EplApiInitParam.m_dwCycleLen = uiCycleLen_g; // required for error detection EplApiInitParam.m_uiIsochrTxMaxPayload = 256; // const EplApiInitParam.m_uiIsochrRxMaxPayload = 256; // const EplApiInitParam.m_dwPresMaxLatency = 50000; // const; only required for IdentRes EplApiInitParam.m_uiPreqActPayloadLimit = 36; // required for initialisation (+28 bytes) EplApiInitParam.m_uiPresActPayloadLimit = 36; // required for initialisation of Pres frame (+28 bytes) EplApiInitParam.m_dwAsndMaxLatency = 150000; // const; only required for IdentRes EplApiInitParam.m_uiMultiplCycleCnt = 0; // required for error detection EplApiInitParam.m_uiAsyncMtu = 1500; // required to set up max frame size EplApiInitParam.m_uiPrescaler = 2; // required for sync EplApiInitParam.m_dwLossOfFrameTolerance = 500000; EplApiInitParam.m_dwAsyncSlotTimeout = 3000000; EplApiInitParam.m_dwWaitSocPreq = 150000; EplApiInitParam.m_dwDeviceType = -1; // NMT_DeviceType_U32 EplApiInitParam.m_dwVendorId = -1; // NMT_IdentityObject_REC.VendorId_U32 EplApiInitParam.m_dwProductCode = -1; // NMT_IdentityObject_REC.ProductCode_U32 EplApiInitParam.m_dwRevisionNumber = -1; // NMT_IdentityObject_REC.RevisionNo_U32 EplApiInitParam.m_dwSerialNumber = -1; // NMT_IdentityObject_REC.SerialNo_U32 EplApiInitParam.m_dwSubnetMask = SUBNET_MASK; EplApiInitParam.m_dwDefaultGateway = 0; EPL_MEMCPY(EplApiInitParam.m_sHostname, sHostname, sizeof(EplApiInitParam.m_sHostname)); EplApiInitParam.m_uiSyncNodeId = EPL_C_ADR_SYNC_ON_SOA; EplApiInitParam.m_fSyncOnPrcNode = FALSE; // set callback functions EplApiInitParam.m_pfnCbEvent = AppCbEvent; #ifdef CONFIG_POWERLINK_USERSTACK EplApiInitParam.m_pfnObdInitRam = EplObdInitRam; EplApiInitParam.m_pfnCbSync = AppCbSync; #else EplApiInitParam.m_pfnCbSync = NULL; #endif printf("\n\nHello, I'm a Userspace POWERLINK node running as %s!\n (build: %s / %s)\n\n", (uiNodeId_g == EPL_C_ADR_MN_DEF_NODE_ID ? "Managing Node" : "Controlled Node"), __DATE__, __TIME__); // initialize POWERLINK stack printf ("Initializing openPOWERLINK stack...\n"); EplRet = EplApiInitialize(&EplApiInitParam); if(EplRet != kEplSuccessful) { printf("EplApiInitialize() failed (Error:0x%x!\n", EplRet); goto Exit; } // initialize application printf ("Initializing openPOWERLINK application...\n"); EplRet = AppInit(); if(EplRet != kEplSuccessful) { printf("ApiInit() failed!\n"); goto Exit; } #ifdef CONFIG_POWERLINK_USERSTACK /* At this point, we don't need any more the device list. Free it */ pcap_freealldevs(alldevs); EplRet = EplApiSetCdcFilename(pszCdcFilename_g); if(EplRet != kEplSuccessful) { goto Exit; } #else // create event thread if (pthread_create(&eventThreadId, NULL, &powerlinkEventThread, NULL) != 0) { goto Exit; } // create sync thread if (pthread_create(&syncThreadId, NULL, &powerlinkSyncThread, NULL) != 0) { goto Exit; } #endif printf("Initializing process image...\n"); printf("Size of input process image: %ld\n", sizeof(AppProcessImageIn_g)); printf("Size of output process image: %ld\n", sizeof (AppProcessImageOut_g)); AppProcessImageCopyJob_g.m_fNonBlocking = FALSE; AppProcessImageCopyJob_g.m_uiPriority = 0; AppProcessImageCopyJob_g.m_In.m_pPart = &AppProcessImageIn_g; AppProcessImageCopyJob_g.m_In.m_uiOffset = 0; AppProcessImageCopyJob_g.m_In.m_uiSize = sizeof (AppProcessImageIn_g); AppProcessImageCopyJob_g.m_Out.m_pPart = &AppProcessImageOut_g; AppProcessImageCopyJob_g.m_Out.m_uiOffset = 0; AppProcessImageCopyJob_g.m_Out.m_uiSize = sizeof (AppProcessImageOut_g); EplRet = EplApiProcessImageAlloc(sizeof (AppProcessImageIn_g), sizeof (AppProcessImageOut_g), 2, 2); if (EplRet != kEplSuccessful) { goto Exit; } EplRet = EplApiProcessImageSetup(); if (EplRet != kEplSuccessful) { goto Exit; } // start processing EplRet = EplApiExecNmtCommand(kEplNmtEventSwReset); if (EplRet != kEplSuccessful) { goto ExitShutdown; } printf("\n-------------------------------\n"); printf("Press Esc to leave the program\n"); printf("Press r to reset the node\n"); printf("-------------------------------\n\n"); // wait for key hit while (cKey != 0x1B) { if( EplTgtKbhit() ) { cKey = (BYTE) EplTgtGetch(); switch (cKey) { case 'r': { EplRet = EplApiExecNmtCommand(kEplNmtEventSwReset); if (EplRet != kEplSuccessful) { goto ExitShutdown; } break; } case 'c': { EplRet = EplApiExecNmtCommand(kEplNmtEventNmtCycleError); if (EplRet != kEplSuccessful) { goto ExitShutdown; } break; } default: { break; } } } EplTgtMilliSleep( 1500 ); } FTRACE_ENABLE(FALSE); ExitShutdown: // halt the NMT state machine // so the processing of POWERLINK frames stops EplRet = EplApiExecNmtCommand(kEplNmtEventSwitchOff); // delete process image EplRet = EplApiProcessImageFree(); // delete instance for all modules EplRet = EplApiShutdown(); Exit: PRINTF("main(): returns 0x%X\n", EplRet); #if (TARGET_SYSTEM == _WIN32_) PRINTF("Press Enter to quit!\n"); EplTgtGetch(); #endif return EplRet; }
tEplKernel EplPdokConfigureChannel(tEplPdoChannelConf* pChannelConf_p) { tEplKernel Ret = kEplSuccessful; tEplPdoChannel* pDestPdoChannel; if (pChannelConf_p->m_fTx == FALSE) { // RPDO #if EPL_NMT_MAX_NODE_ID > 0 tEplDllNodeOpParam NodeOpParam; NodeOpParam.m_OpNodeType = kEplDllNodeOpTypeFilterPdo; #endif if (pChannelConf_p->m_uiChannelId >= EplPdokInstance_g.m_Allocation.m_uiRxPdoChannelCount) { Ret = kEplPdoNotExist; goto Exit; } if (pChannelConf_p->m_PdoChannel.m_uiMappObjectCount > tabentries(*EplPdokInstance_g.m_paRxObject)) { Ret = kEplPdoErrorMapp; goto Exit; } pDestPdoChannel = &EplPdokInstance_g.m_pRxPdoChannel[pChannelConf_p->m_uiChannelId]; #if EPL_NMT_MAX_NODE_ID > 0 if ((pDestPdoChannel->m_uiNodeId != EPL_PDO_INVALID_NODE_ID) && (pDestPdoChannel->m_uiNodeId != EPL_PDO_PREQ_NODE_ID)) { // disable old PRes filter in DLL NodeOpParam.m_uiNodeId = pDestPdoChannel->m_uiNodeId; Ret = EplDllkDeleteNode(&NodeOpParam); if (Ret != kEplSuccessful) { goto Exit; } } #endif // EPL_NMT_MAX_NODE_ID > 0 // copy channel configuration to local structure EPL_MEMCPY(pDestPdoChannel, &pChannelConf_p->m_PdoChannel, sizeof (pChannelConf_p->m_PdoChannel)); EPL_MEMCPY(&EplPdokInstance_g.m_paRxObject[pChannelConf_p->m_uiChannelId], &pChannelConf_p->m_aMappObject[0], (pChannelConf_p->m_PdoChannel.m_uiMappObjectCount * sizeof (pChannelConf_p->m_aMappObject[0]))); #if EPL_NMT_MAX_NODE_ID > 0 if ((pDestPdoChannel->m_uiNodeId != EPL_PDO_INVALID_NODE_ID) && (pDestPdoChannel->m_uiNodeId != EPL_PDO_PREQ_NODE_ID)) { // enable new PRes filter in DLL NodeOpParam.m_uiNodeId = pDestPdoChannel->m_uiNodeId; Ret = EplDllkAddNode(&NodeOpParam); if (Ret != kEplSuccessful) { goto Exit; } } #endif // EPL_NMT_MAX_NODE_ID > 0 } else { // TPDO if (pChannelConf_p->m_uiChannelId >= EplPdokInstance_g.m_Allocation.m_uiTxPdoChannelCount) { Ret = kEplPdoNotExist; goto Exit; } if (pChannelConf_p->m_PdoChannel.m_uiMappObjectCount > tabentries(*EplPdokInstance_g.m_paTxObject)) { Ret = kEplPdoErrorMapp; goto Exit; } // copy channel configuration to local structure EPL_MEMCPY(&EplPdokInstance_g.m_pTxPdoChannel[pChannelConf_p->m_uiChannelId], &pChannelConf_p->m_PdoChannel, sizeof (pChannelConf_p->m_PdoChannel)); EPL_MEMCPY(&EplPdokInstance_g.m_paTxObject[pChannelConf_p->m_uiChannelId], &pChannelConf_p->m_aMappObject[0], (pChannelConf_p->m_PdoChannel.m_uiMappObjectCount * sizeof (pChannelConf_p->m_aMappObject[0]))); } Exit: return Ret; }
tEplKernel PUBLIC EplTimeruSetTimerMs( tEplTimerHdl* pTimerHdl_p, unsigned long ulTimeMs_p, tEplTimerArg Argument_p) { tTimerEntry* pNewEntry; tTimerEntry** ppEntry; tEplKernel Ret; Ret = kEplSuccessful; // check pointer to handle if(pTimerHdl_p == NULL) { Ret = kEplTimerInvalidHandle; goto Exit; } // fetch entry from free timer list EplTimeruEnterCriticalSection(TIMERU_FREE_LIST); pNewEntry = EplTimeruInstance_g.m_pFreeListFirst; if (pNewEntry != NULL) { EplTimeruInstance_g.m_pFreeListFirst = pNewEntry->m_pNext; EplTimeruInstance_g.m_uiFreeEntries--; if (EplTimeruInstance_g.m_uiMinFreeEntries > EplTimeruInstance_g.m_uiFreeEntries) { EplTimeruInstance_g.m_uiMinFreeEntries = EplTimeruInstance_g.m_uiFreeEntries; } } EplTimeruLeaveCriticalSection(TIMERU_FREE_LIST); if (pNewEntry == NULL) { // sorry, no free entry Ret = kEplTimerNoTimerCreated; goto Exit; } *pTimerHdl_p = (tEplTimerHdl) pNewEntry; EPL_MEMCPY(&pNewEntry->m_TimerArg, &Argument_p, sizeof(tEplTimerArg)); // insert timer entry in timer list EplTimeruEnterCriticalSection(TIMERU_TIMER_LIST); // calculate timeout based on start time pNewEntry->m_dwTimeoutMs = (EplTimeruGetTickCountMs() - EplTimeruInstance_g.m_dwStartTimeMs) + ulTimeMs_p; ppEntry = &EplTimeruInstance_g.m_pTimerListFirst; while (*ppEntry != NULL) { if ((*ppEntry)->m_dwTimeoutMs > pNewEntry->m_dwTimeoutMs) { (*ppEntry)->m_dwTimeoutMs -= pNewEntry->m_dwTimeoutMs; break; } pNewEntry->m_dwTimeoutMs -= (*ppEntry)->m_dwTimeoutMs; ppEntry = &(*ppEntry)->m_pNext; } // insert before **ppEntry pNewEntry->m_pNext = *ppEntry; *ppEntry = pNewEntry; EplTimeruLeaveCriticalSection(TIMERU_TIMER_LIST); #if (TARGET_SYSTEM == _WIN32_) if (ppEntry == &EplTimeruInstance_g.m_pTimerListFirst) { SetEvent( EplTimeruInstance_g.m_ahEvents[TIMERU_EVENT_WAKEUP] ); } #endif Exit: return Ret; }
//--------------------------------------------------------------------------- // // Function: EplSdoTimeruThreadms // // Description: function to process timer as thread // // // // Parameters: lpParameter = pointer to structur of type tEplTimeruThread // // // Returns: DWORD = Errorcode // // // State: // //--------------------------------------------------------------------------- DWORD PUBLIC EplSdoTimeruThreadms(LPVOID lpParameter) { tEplKernel Ret; tEplTimeruThread *pThreadData; HANDLE aHandles[2]; BOOL fReturn; LARGE_INTEGER TimeoutTime; unsigned long ulEvent; tEplEvent EplEvent; tEplTimeruThread ThreadData; tEplTimerEventArg TimerEventArg; Ret = kEplSuccessful; // get pointer to data pThreadData = (tEplTimeruThread *) lpParameter; // copy thread data EPL_MEMCPY(&ThreadData, pThreadData, sizeof(ThreadData)); pThreadData = &ThreadData; // leave critical section LeaveCriticalSection(EplTimeruInstance_g.m_pCriticalSection); // create waitable timer aHandles[1] = CreateWaitableTimer(NULL, FALSE, NULL); if (aHandles[1] == NULL) { Ret = kEplTimerNoTimerCreated; goto Exit; } // set timer // set timeout interval -> needed to be negativ // -> because relative timeout // -> multiply by 10000 for 100 ns timebase of function TimeoutTime.QuadPart = (((long long)pThreadData->ulTimeout) * -10000); fReturn = SetWaitableTimer(aHandles[1], &TimeoutTime, 0, NULL, NULL, FALSE); if (fReturn == 0) { Ret = kEplTimerNoTimerCreated; goto Exit; } // save delte event handle in handle array aHandles[0] = pThreadData->DelteHandle; // wait for one of the events ulEvent = WaitForMultipleObjects(2, &aHandles[0], FALSE, INFINITE); if (ulEvent == WAIT_OBJECT_0) { // delte event // close handels CloseHandle(aHandles[1]); // terminate thread goto Exit; } else if (ulEvent == (WAIT_OBJECT_0 + 1)) { // timer event // call event function TimerEventArg.m_TimerHdl = (tEplTimerHdl) pThreadData->DelteHandle; TimerEventArg.m_ulArg = pThreadData->TimerArgument.m_ulArg; EplEvent.m_EventSink = pThreadData->TimerArgument.m_EventSink; EplEvent.m_EventType = kEplEventTypeTimer; EPL_MEMSET(&EplEvent.m_NetTime, 0x00, sizeof(tEplNetTime)); EplEvent.m_pArg = &TimerEventArg; EplEvent.m_uiSize = sizeof(TimerEventArg); Ret = EplEventuPost(&EplEvent); // close handels CloseHandle(aHandles[1]); // terminate thread goto Exit; } else { // error ulEvent = GetLastError(); TRACE1("Error in WaitForMultipleObjects Errorcode: 0x%x\n", ulEvent); // terminate thread goto Exit; } Exit: return Ret; }
/** ******************************************************************************** \brief Constructor Constructs a POWERLINK object. \param pMainWindow_p pointer to main window \param uiNodeId_p node ID of the POWERLINK node \param devName_p device name of the network interface *******************************************************************************/ EplApi::EplApi(MainWindow *pMainWindow_p, unsigned int uiNodeId_p, QString devName_p) { const char* sHostname = HOSTNAME; tEplKernel EplRet; EplState* pEplState; EplOutput* pEplOutput; EplInput* pEplInput; EplCnState* pEplCnState; char devName[256]; pEplState = pMainWindow_p->getEplStateWidget(); pEplOutput = pMainWindow_p->getEplOutputWidget(); pEplInput = pMainWindow_p->getEplInputWidget(); pEplCnState = pMainWindow_p->getEplCnStateWidget(); pEplProcessThread = new EplProcessThread; QObject::connect(pEplProcessThread, SIGNAL(eplStatusChanged(int)), pEplState, SLOT(setEplStatusLed(int))); QObject::connect(pEplProcessThread, SIGNAL(nmtStateChanged(const QString&)), pEplState, SLOT(setNmtStateText(const QString &))); QObject::connect(pEplProcessThread, SIGNAL(nodeAppeared(int)), pEplInput, SLOT(addNode(int))); QObject::connect(pEplProcessThread, SIGNAL(allNodesRemoved()), pEplInput, SLOT(removeAllNodes())); QObject::connect(pEplProcessThread, SIGNAL(nodeDisappeared(int)), pEplInput, SLOT(removeNode(int))); QObject::connect(pEplProcessThread, SIGNAL(nodeAppeared(int)), pEplOutput, SLOT(addNode(int))); QObject::connect(pEplProcessThread, SIGNAL(nodeDisappeared(int)), pEplOutput, SLOT(removeNode(int))); QObject::connect(pEplProcessThread, SIGNAL(allNodesRemoved()), pEplOutput, SLOT(removeAllNodes())); QObject::connect(pEplProcessThread, SIGNAL(nodeAppeared(int)), pEplCnState, SLOT(addNode(int))); QObject::connect(pEplProcessThread, SIGNAL(nodeDisappeared(int)), pEplCnState, SLOT(removeNode(int))); QObject::connect(pEplProcessThread, SIGNAL(allNodesRemoved()), pEplCnState, SLOT(removeAllNodes())); QObject::connect(pEplProcessThread, SIGNAL(nodeStatusChanged(int, int)), pEplCnState, SLOT(setState(int, int))); pEplDataInOutThread = new EplDataInOutThread; QObject::connect(pEplDataInOutThread, SIGNAL(processImageOutChanged(unsigned int, unsigned int)), pEplOutput, SLOT(setValue(unsigned int, unsigned int))); QObject::connect(pEplDataInOutThread, SIGNAL(processImageInChanged(unsigned int, unsigned int)), pEplInput, SLOT(setLeds(unsigned int, unsigned int))); EPL_MEMSET(&EplApiInitParam, 0, sizeof (EplApiInitParam)); EplApiInitParam.m_uiSizeOfStruct = sizeof (EplApiInitParam); EplApiInitParam.m_uiNodeId = uiNodeId_p; EplApiInitParam.m_dwIpAddress = (IP_ADDR & 0xFFFFFF00) | EplApiInitParam.m_uiNodeId; EplApiInitParam.m_fAsyncOnly = FALSE; EplApiInitParam.m_dwFeatureFlags = -1; EplApiInitParam.m_dwCycleLen = CYCLE_LEN; // required for error detection EplApiInitParam.m_uiIsochrTxMaxPayload = 256; // const EplApiInitParam.m_uiIsochrRxMaxPayload = 256; // const EplApiInitParam.m_dwPresMaxLatency = 50000; // const; only required for IdentRes EplApiInitParam.m_uiPreqActPayloadLimit = 36; // required for initialisation (+28 bytes) EplApiInitParam.m_uiPresActPayloadLimit = 36; // required for initialisation of Pres frame (+28 bytes) EplApiInitParam.m_dwAsndMaxLatency = 150000; // const; only required for IdentRes EplApiInitParam.m_uiMultiplCycleCnt = 0; // required for error detection EplApiInitParam.m_uiAsyncMtu = 1500; // required to set up max frame size EplApiInitParam.m_uiPrescaler = 2; // required for sync EplApiInitParam.m_dwLossOfFrameTolerance = 500000; EplApiInitParam.m_dwAsyncSlotTimeout = 3000000; EplApiInitParam.m_dwWaitSocPreq = 150000; EplApiInitParam.m_dwDeviceType = -1; // NMT_DeviceType_U32 EplApiInitParam.m_dwVendorId = -1; // NMT_IdentityObject_REC.VendorId_U32 EplApiInitParam.m_dwProductCode = -1; // NMT_IdentityObject_REC.ProductCode_U32 EplApiInitParam.m_dwRevisionNumber = -1; // NMT_IdentityObject_REC.RevisionNo_U32 EplApiInitParam.m_dwSerialNumber = -1; // NMT_IdentityObject_REC.SerialNo_U32 EplApiInitParam.m_dwSubnetMask = SUBNET_MASK; EplApiInitParam.m_dwDefaultGateway = 0; EPL_MEMCPY(EplApiInitParam.m_sHostname, sHostname, sizeof(EplApiInitParam.m_sHostname)); EplApiInitParam.m_uiSyncNodeId = EPL_C_ADR_SYNC_ON_SOA; EplApiInitParam.m_fSyncOnPrcNode = FALSE; // set callback functions EplApiInitParam.m_pfnCbEvent = pEplProcessThread->getEventCbFunc(); /* write 00:00:00:00:00:00 to MAC address, so that the driver uses the real hardware address */ EPL_MEMCPY(EplApiInitParam.m_abMacAddress, abMacAddr, sizeof (EplApiInitParam.m_abMacAddress)); #ifdef CONFIG_POWERLINK_USERSTACK EplApiInitParam.m_HwParam.m_pszDevName = devName_p.toAscii().data(); EplApiInitParam.m_pfnObdInitRam = EplObdInitRam; EplApiInitParam.m_pfnCbSync = pEplDataInOutThread->getSyncCbFunc(); #else // Sync call back function not required for init from user space EplApiInitParam.m_pfnCbSync = NULL; #endif // init EPL EplRet = EplApiInitialize(&EplApiInitParam); if(EplRet != kEplSuccessful) { printf("%s: EplApiInitialize() failed\n", __FUNCTION__); QMessageBox::critical(0, "POWERLINK demo", QString("Initialization of openPOWERLINK Stack failed.\n") + "Error code: 0x"+ QString::number(EplRet, 16) + "\nThe most common error source are an unsupported Ethernet controller or the kernel module is not loaded." "\nFor further information please consult the manual."); goto Exit; } #ifdef CONFIG_POWERLINK_USERSTACK EplRet = EplApiSetCdcFilename(pszCdcFilename_g); if(EplRet != kEplSuccessful) { goto Exit; } #endif EplRet = pEplDataInOutThread->SetupProcessImage(); if (EplRet != kEplSuccessful) { printf("%s: pEplDataInOutThread->SetupProcessImage() failed\n", __FUNCTION__); goto Exit; } printf("Setup Process Image Successfull\n"); // start the EPL stack EplRet = EplApiExecNmtCommand(kEplNmtEventSwReset); // start process thread pEplProcessThread->start(); #ifndef CONFIG_POWERLINK_USERSTACK // start data in out thread pEplDataInOutThread->start(); #endif Exit: printf("%s: returns 0x%X\n", __FUNCTION__, EplRet); }
//--------------------------------------------------------------------------- // // Function: openPowerlinkInit // // Description: // Initialize and start the openPOWERLINK demo application // // Parameters: // pszEthName = pointer to string with name of network interface to use // // Returns: int // //--------------------------------------------------------------------------- int openPowerlinkInit (char *pszEthName, unsigned int uiDevNumber) { tEplKernel EplRet; static tEplApiInitParam EplApiInitParam = {0}; char* sHostname = HOSTNAME; BOOL fApiInit = FALSE; int tid; // Adjust task priorities of system tasks /* shell task is normally set to priority 1 which could disturb * openPOWERLINK if long-running commands are entered. Therefore * we lower the performance to 20 */ tid = taskIdSelf(); printf ("Task ID: %d\n", tid); taskPrioritySet(tid, 20); /* The priority of the network stack task has to be increased (default:50) * in order to get network packets in time! */ if ((tid = taskNameToId("tNet0")) != -1 ) { taskPrioritySet(tid, 5); } // Initialize high-resolution timer library hrtimer_init(EPL_TASK_PRIORITY_HRTIMER, EPL_TASK_STACK_SIZE); // get node ID from insmod command line EplApiInitParam.m_uiNodeId = uiNodeId_g; if (EplApiInitParam.m_uiNodeId == EPL_C_ADR_INVALID) { // invalid node ID set // set default node ID EplApiInitParam.m_uiNodeId = NODEID; } uiNodeId_g = EplApiInitParam.m_uiNodeId; // calculate IP address EplApiInitParam.m_dwIpAddress = (0xFFFFFF00 & IP_ADDR) | EplApiInitParam.m_uiNodeId; EplApiInitParam.m_fAsyncOnly = FALSE; // store the specified device name EplApiInitParam.m_HwParam.m_pszDevName = pszEthName; EplApiInitParam.m_HwParam.m_uiDevNumber = uiDevNumber; EplApiInitParam.m_uiSizeOfStruct = sizeof (EplApiInitParam); EPL_MEMCPY(EplApiInitParam.m_abMacAddress, abMacAddr, sizeof (EplApiInitParam.m_abMacAddress)); EplApiInitParam.m_dwFeatureFlags = (DWORD) ~0UL; EplApiInitParam.m_dwCycleLen = uiCycleLen_g; // required for error detection EplApiInitParam.m_uiIsochrTxMaxPayload = 100; // const EplApiInitParam.m_uiIsochrRxMaxPayload = 100; // const EplApiInitParam.m_dwPresMaxLatency = 50000; // const; only required for IdentRes EplApiInitParam.m_uiPreqActPayloadLimit = 36; // required for initialisation (+28 bytes) EplApiInitParam.m_uiPresActPayloadLimit = 36; // required for initialisation of Pres frame (+28 bytes) EplApiInitParam.m_dwAsndMaxLatency = 150000; // const; only required for IdentRes EplApiInitParam.m_uiMultiplCycleCnt = 0; // required for error detection EplApiInitParam.m_uiAsyncMtu = 1500; // required to set up max frame size EplApiInitParam.m_uiPrescaler = 2; // required for sync EplApiInitParam.m_dwLossOfFrameTolerance = 500000; EplApiInitParam.m_dwAsyncSlotTimeout = 3000000; EplApiInitParam.m_dwWaitSocPreq = 0; EplApiInitParam.m_dwDeviceType = (DWORD) ~0UL; // NMT_DeviceType_U32 EplApiInitParam.m_dwVendorId = (DWORD) ~0UL; // NMT_IdentityObject_REC.VendorId_U32 EplApiInitParam.m_dwProductCode = (DWORD) ~0UL; // NMT_IdentityObject_REC.ProductCode_U32 EplApiInitParam.m_dwRevisionNumber = (DWORD) ~0UL; // NMT_IdentityObject_REC.RevisionNo_U32 EplApiInitParam.m_dwSerialNumber = (DWORD) ~0UL; // NMT_IdentityObject_REC.SerialNo_U32 EplApiInitParam.m_dwSubnetMask = SUBNET_MASK; EplApiInitParam.m_dwDefaultGateway = 0; EPL_MEMCPY(EplApiInitParam.m_sHostname, sHostname, sizeof(EplApiInitParam.m_sHostname)); EplApiInitParam.m_uiSyncNodeId = EPL_C_ADR_SYNC_ON_SOA; // for fSyncOnPrcNode==TRUE, this means last PRC node EplApiInitParam.m_fSyncOnPrcNode = TRUE; // set callback functions EplApiInitParam.m_pfnCbEvent = AppCbEvent; EplApiInitParam.m_pfnCbSync = AppCbSync; EplApiInitParam.m_pfnObdInitRam = EplObdInitRam; printf("\n\n Hello, I'm a VxWorks POWERLINK node running as %s!\n" "(build: %s / %s)\n\n", (uiNodeId_g == EPL_C_ADR_MN_DEF_NODE_ID ? "Managing Node" : "Controlled Node"), __DATE__, __TIME__); // initialize POWERLINK stack EplRet = EplApiInitialize(&EplApiInitParam); if(EplRet != kEplSuccessful) { goto Exit; } fApiInit = TRUE; // set CDC filename EplRet = EplApiSetCdcFilename(pszCdcFilename_g); if(EplRet != kEplSuccessful) { printf ("Error set cdc filename!\n"); goto Exit; } // initialize application printf ("Initializing openPOWERLINK application...\n"); EplRet = AppInit(); if(EplRet != kEplSuccessful) { printf("ApiInit() failed!\n"); goto Exit; } // initialize process image printf("Initializing process image...\n"); printf("Size of input process image: %ld\n", sizeof(AppProcessImageIn_g)); printf("Size of output process image: %ld\n", sizeof (AppProcessImageOut_g)); AppProcessImageCopyJob_g.m_fNonBlocking = FALSE; AppProcessImageCopyJob_g.m_uiPriority = 0; AppProcessImageCopyJob_g.m_In.m_pPart = &AppProcessImageIn_g; AppProcessImageCopyJob_g.m_In.m_uiOffset = 0; AppProcessImageCopyJob_g.m_In.m_uiSize = sizeof (AppProcessImageIn_g); AppProcessImageCopyJob_g.m_Out.m_pPart = &AppProcessImageOut_g; AppProcessImageCopyJob_g.m_Out.m_uiOffset = 0; AppProcessImageCopyJob_g.m_Out.m_uiSize = sizeof (AppProcessImageOut_g); EplRet = EplApiProcessImageAlloc(sizeof (AppProcessImageIn_g), sizeof (AppProcessImageOut_g), 2, 2); if (EplRet != kEplSuccessful) { goto Exit; } EplRet = EplApiProcessImageSetup(); if (EplRet != kEplSuccessful) { goto Exit; } // start the NMT state machine EplRet = EplApiExecNmtCommand(kEplNmtEventSwReset); Exit: PRINTF("%s(): returns 0x%X\n", __func__, EplRet); if (EplRet != kEplSuccessful) { if (fApiInit != FALSE) { EplApiShutdown(); } // Shutdown high-resolution timer library hrtimer_shutdown(); fOpenPowerlinkIsRunning_g = FALSE; return -ENODEV; } else { fOpenPowerlinkIsRunning_g = TRUE; return 0; } }