DWORD WINAPI OSTaskW32( LPVOID lpParameter ) { OS_TCB *ptcb; OS_EMU_STK *stack; ptcb = (OS_TCB*) lpParameter; stack = (OS_EMU_STK*) ptcb->OSTCBStkPtr; #ifdef DISABLE_PRIORITY_BOOST if( SetThreadPriorityBoost( stack->Handle, TRUE ) == 0 ) { #ifdef OS_CPU_TRACE OS_Printf("Error: SetThreadPriorityBoost\n"); #endif } #endif OS_INIT_CRITICAL(); stack->Task(stack->pData); stack->Exit = 1; OSTaskDel(ptcb->OSTCBPrio); return 0; }
/** * @brief Parse and then process the command * @author R.Lillback * @date 1-Sep-2015 * * @details This message calls functions to: * 1.) Split the command into parts * 2.) Look to find the command in the command constant list * 3.) Jump to a multiplexer to validate the command & then execute it * 4.) Look to see if the command worked * * @param <none> * * @returns <void> * */ void ProcessCmd(char* strCommand) { char strMainCmd[MAX_INPUT_LINE_LEN]; // Main command char strSubCmdOne[MAX_INPUT_LINE_LEN]; // First sub-command int iSubCmdOne; // Sub-command One is going to be a number int i; // Loop integer int iFound = FALSE; // Did we find the command? int lastCommand = FALSE; // Used to terminate the loop at the last command (defined as '\0') DWORD iResult; // Result of executing the command iSubCmdOne = ParseCommands(strCommand, strMainCmd, strSubCmdOne); // Split the commands apart into multiples i=-1; while ( (FALSE == lastCommand) && (FALSE == iFound) && (i < MAX_COMMANDS) ){ i++; if ( CLI_COMMANDS[i].strCmd == '\0' ) { lastCommand = TRUE; } else { iFound = IsEqual(CLI_COMMANDS[i].strCmd,strMainCmd); } } // while if ( lastCommand ) { // we parsed through all the commands and hit the end OS_Printf("Error....command not found.\n"); } else { // we found a command if ( iFound ) { iResult = ExecuteCommand (CLI_COMMANDS[i].iIndex, iSubCmdOne); // so execute it if (iResult != (DWORD)0) { OS_Printf("%s command failed.", CLI_COMMANDS[i].strCmd); // it failed! } } } // lastCommand PRINT_PROMPT; OS_Fflush(stdout); return; } // ProcessCmd
void OSTCBInitHook(OS_TCB *ptcb) { OS_EMU_STK *stack; stack = (OS_EMU_STK*) ptcb->OSTCBStkPtr; stack->Handle = CreateThread( NULL, 0, OSTaskW32, ptcb, CREATE_SUSPENDED, &stack->Id ); #ifdef SET_AFFINITY_MASK if( SetThreadAffinityMask( stack->Handle, 1 ) == 0 ) { #ifdef OS_CPU_TRACE OS_Printf("Error: SetThreadAffinityMask\n"); #endif } #endif }
DWORD WINAPI OSTickW32( LPVOID lpParameter ) { OS_INIT_CRITICAL(); while(!OSTerminateTickW32) { OSTickISR(); #ifdef WIN_MM_TICK if( WaitForSingleObject(OSTickEventHandle, 5000) == WAIT_TIMEOUT) { #ifdef OS_CPU_TRACE OS_Printf("Error: MM OSTick Timeout!\n"); #endif } ResetEvent(OSTickEventHandle); #else Sleep(1000/OS_TICKS_PER_SEC); #endif } return 0; }
void OS_EXIT_CRITICAL() { #ifdef USE_CRITICAL_SECTION LeaveCriticalSection(&OSCriticalSection); #else #ifdef ALLOW_CS_RECURSION if( Recursion > 0 ) { if(--Recursion == 0 ) { ThreadID = 0; ReleaseSemaphore( OSSemaphore, 1, NULL ); } } else { #ifdef OS_CPU_TRACE OS_Printf("Error: OS_EXIT_CRITICAL\n"); #endif } #else ReleaseSemaphore( OSSemaphore, 1, NULL ); #endif #endif }
void OSStartHighRdy() { DWORD dwID; OSInitTrace(100000); OS_ENTER_CRITICAL(); OSTaskSwHook(); ++OSRunning; OSCtxSwW32Event = CreateEvent(NULL,FALSE,FALSE,NULL); OSCtxSwW32Handle = CreateThread( NULL, 0, OSCtxSwW32, 0, 0, &dwID ); SetPriorityClass(OSCtxSwW32Handle,THREAD_PRIORITY_HIGHEST); #ifdef SET_AFFINITY_MASK if( SetThreadAffinityMask( OSCtxSwW32Handle, 1 ) == 0 ) { #ifdef OS_CPU_TRACE OS_Printf("Error: SetThreadAffinityMask\n"); #endif } #endif SetThreadPriority(OSCtxSwW32Handle,THREAD_PRIORITY_TIME_CRITICAL); OSTick32Handle = CreateThread( NULL, 0, OSTickW32, 0, 0, &dwID ); SetPriorityClass(OSTick32Handle,THREAD_PRIORITY_HIGHEST); #ifdef SET_AFFINITY_MASK if( SetThreadAffinityMask( OSTick32Handle, 1 ) == 0 ) { #ifdef OS_CPU_TRACE OS_Printf("Error: SetThreadAffinityMask\n"); #endif } #endif SetThreadPriority(OSTick32Handle,THREAD_PRIORITY_HIGHEST); #ifdef WIN_MM_TICK timeGetDevCaps(&OSTimeCap, sizeof(OSTimeCap)); if( OSTimeCap.wPeriodMin < WIN_MM_MIN_RES ) OSTimeCap.wPeriodMin = WIN_MM_MIN_RES; timeBeginPeriod(OSTimeCap.wPeriodMin); OSTickEventHandle = CreateEvent(NULL, FALSE, FALSE, NULL); OSTickTimer = timeSetEvent((1000/OS_TICKS_PER_SEC),OSTimeCap.wPeriodMin,(LPTIMECALLBACK)OSTickEventHandle, dwID,TIME_PERIODIC|TIME_CALLBACK_EVENT_SET); #endif SS_SP = (OS_EMU_STK*) OSTCBHighRdy->OSTCBStkPtr; /* OSTCBCur = OSTCBHighRdy; */ /* OSPrioCur = OSPrioHighRdy; */ ResumeThread(SS_SP->Handle); OS_EXIT_CRITICAL(); WaitForSingleObject(OSCtxSwW32Handle,INFINITE); #ifdef WIN_MM_TICK timeKillEvent(OSTickTimer); timeEndPeriod(OSTimeCap.wPeriodMin); CloseHandle(OSTickEventHandle); #endif CloseHandle(OSTick32Handle); CloseHandle(OSCtxSwW32Event); }
/** * @brief Create a copy of the object dictionary located at iNode * @author R.Lillback * @date 4-Sep-2015 * * @details * * @param <none> * * @returns 0=success, anything else = failure. * */ DWORD PopulateObjectDictionary(void) { ECI_RESULT result = ECI_OK; DWORD loopVar = 0; DWORD outerLoopVar= 0; DWORD myIndex = 0x0000; BYTE mySubIndex = 0x00; BYTE maxIndex = 0x00; BYTE returnedByte[8]; DWORD remoteSZ = 0x00000000; // Remote Object Dictionary Data Size DWORD localSZ = 0x00000000; // Local Object Dictionary Data Size DWORD localDT = 0x00000000; // Local Object Dictionary Data Type DWORD localData = 0x00000000; WORD indicies[] = { 0x2000, 0x2001, 0x3001, 0x5000, 0x5001, 0x5002, 0x5003, 0xFFFF }; for (loopVar = 0; loopVar<8; loopVar++) returnedByte[loopVar] = 0x00; loopVar = 0x00; outerLoopVar= 0x00; myIndex = indicies[outerLoopVar]; mySubIndex = 0x00; while (0xFFFF != myIndex) { /* Figure out the best way to retrieve the index */ remoteSZ = sizeof(BYTE); localSZ = 0x00000000; localDT = 0x00000000; result = GetDTValues(myIndex, mySubIndex, &localData, &localDT, &localSZ); result = SDO_Upload(iNode, myIndex, mySubIndex, returnedByte); if (localSZ == remoteSZ) // if the sizes match, then continue on { if (returnedByte[0] <= 0x03) // Do a standard set of transfers if we are 3 elements or less { maxIndex = returnedByte[0]; loopVar = 0x01; while (loopVar <= maxIndex) { result = GetDTValues(myIndex, loopVar, &localData, &localDT, &localSZ); // get the local copy of the table result = SDO_Upload(iNode, myIndex, loopVar, returnedByte); // get the entry from the remote server node if (ECI_OK == result) { switch (localSZ) // reconstruct the data & store into local copy of Object Dictionary { case 1: // BYTE { BYTE byteData = 0x00; byteData = returnedByte[0]; result = SetDTValues(myIndex, loopVar, &byteData, &localDT, &remoteSZ); OS_Printf("\nByte Data set index 0x%04X subindex 0x%02X to 0x%02X.\n",myIndex,loopVar,byteData); break; } case 2: // WORD { WORD wordData = 0x0000; wordData = ((WORD)returnedByte[1] << 8) + (WORD)returnedByte[0]; result = SetDTValues(myIndex, loopVar, &wordData, &localDT, &remoteSZ); OS_Printf("\nWord Data set index 0x%04X subindex 0x%02X to 0x%04X.\n",myIndex,loopVar,wordData); break; } case 4: // DWORD { DWORD dwordData = 0x00000000; dwordData = ((DWORD)returnedByte[3] << 24) + ((DWORD)returnedByte[2] << 16) + ((DWORD)returnedByte[1] << 8) + ((DWORD)returnedByte[0]); result = SetDTValues(myIndex,loopVar,&dwordData,&localDT,&remoteSZ); OS_Printf("\nDword data set index 0x%04X subindex 0x%02X to 0x%08X.\n",myIndex,loopVar,dwordData); break; } } // switch on data size loopVar++; // go onto next one } // if SDO_Upload result was good } // while loopVar < index size } // do a standard set of transfers else // do a block transfer { BYTE blockData[896]; // Right now, I am limiting the block download to 896 bytes or 128 blocks of 7-byte data... DWORD i = 0; // Yeah, my 'generic' loop counter for (i = 0;i < 896; i++) // Initialize blockData blockData[i] = 0; BYTE subIndex = 0x01; WORD bytesOfDataNeeded = 0; // How many data bytes does the LOCAL data table index need? WORD remoteBytesSending = 0; // How many data bytes are being sent? BYTE subIndexSz = 0; DWORD dummy = 0; DWORD dummy2 = 0; DWORD dummy3 = 0; WORD indexSize = 0; WORD tempWord = 0; bytesOfDataNeeded = CalculateDataTableBytes(myIndex); result = InitiateBlockUpload(iNode, // Which node myIndex, // Which index subIndex, // Starting sub index number returnedByte[0], // # of sub indexes &remoteBytesSending); // Get the number of bytes we are sending if (ECI_OK != result) { OS_Printf("Initiate block upload failed.\n"); return result; } if (bytesOfDataNeeded < remoteBytesSending) { OS_Printf("Error! Too few bytes are going to be sent via a block transfer.\n"); return ~ECI_OK; } result = GetBlockUploadData(iNode, blockData); // Put the block data into a buffer /* Now let's decode the results & put them into order */ dummy = GetDTValues(myIndex, 0x00, &subIndexSz, &dummy2, &dummy3); // Get the index count i = 0; for (subIndex = 0x01; subIndex <= subIndexSz; subIndex++) { dummy = GetDTValues(myIndex, subIndex, &dummy3, &dummy2, &indexSize); localDT = 0; switch (indexSize) { case 1: // BYTE { result = SetDTValues(myIndex, subIndex, &returnedByte[i], &localDT, &indexSize); OS_Printf("\nByte Data set index 0x%04X subindex 0x%02X to 0x%02X.\n",myIndex,subIndex,returnedByte[i]); i += 1; break; } // BYTE case 2: // WORD { tempWord = (WORD)returnedByte[i]; tempWord += (WORD)(returnedByte[i+1]) << 8; result = SetDTValues(myIndex, subIndex, &tempWord, &localDT, &indexSize); OS_Printf("\nWord Data set index 0x%04X subindex 0x%02X to 0x%04X.\n",myIndex,subIndex,tempWord); i += 2; break; } // WORD case 4: // DWORD { dummy = (DWORD)returnedByte[i]; dummy += (DWORD)(returnedByte[i+1]) << 8; dummy += (DWORD)(returnedByte[i+2]) << 16; dummy += (DWORD)(returnedByte[i+3]) << 24; result = SetDTValues(myIndex, subIndex, &dummy, &localDT, &indexSize); OS_Printf("\nDWord Data set index 0x%04X subindex 0x%02X to 0x%08X.\n",myIndex,subIndex,dummy); i += 4; break; } // DWORD } // switch indexSize } // for } // do a block transfer } // if sizes match outerLoopVar++; myIndex = indicies[outerLoopVar]; } return (DWORD)result; } // PopulateObjectDictionary
/** * @brief Perform a change in operating modes on the target node * @author R.Lillback * @date 3-Sep-2015 * * @details This function: * 1.) Validates the command & data * 2.) Sends an NMT message out on the CAN bus to change modes * 3.) Waits for a NODE_STATUS message from the target node. * 4.) Validates that the status has updated to what we expect. * * This function will send the request up to 5 times, and then fail. * It does this: * 1.) Send the message * 2.) Listen for up to 12 seconds for a correct response. * 3.) Resend the message * 4.) Listen for up to 12 seconds.... * 5.) Rinse & repeat for a total of 5 messages sent. * * @param subcommand (as in integer), which is the mode you want to change to. * * @returns 0=success, anything else = failure * */ DWORD DoModeChange(DWORD subCommand) { BYTE tries = 1; // Count the number of tries DWORD finished = FALSE; // Did we get back what we expected? DWORD dwCOB_ID; // a cob_id to filter for s_MESSAGE msg = {0}; // Give us a message BYTE cntr; // just a loop variable e_MODES mode = (e_MODES)subCommand; ECI_RESULT result; if ( ((BYTE)subCommand >= 0) && ((BYTE)subCommand <= (BYTE)MODE_TESTHW) ) { if ( (iNode > 0) && (iNode < 1024) ) { // Check node OS_Printf("Asking Node %u to changed to mode %u - %s\n", iNode, mode, MODE_DESCRIPTION[(e_MODES)subCommand].strDescr); dwCOB_ID = (COB_NODE_STATUS << 7); // Looking for a node status message dwCOB_ID += iNode; // from this node while ( (tries <= MAX_TRIES) && (finished == FALSE) ) { mode = (e_MODES)subCommand; result = ChangeMode( iNode, mode ); // Request the change /* Wait for the node status to change coming back */ OS_Printf("Waiting."); OS_Fflush(stdout); result = ~ECI_OK; // Start looping cntr = 0; // clear the loop variable while ( (ECI_OK != result) && (cntr<48)) { // 48 loops at 1/4 second a loop = 12 seconds to wait OS_Sleep(QUARTER_SECOND); result = LookForMessage(&msg); // Look for a message on the FIFO queue if (ECI_OK == result) { // yes, message on the queue, now is it the one we were looking for? if ( (dwCOB_ID == msg.cob_id) && (mode == msg.data[0]) ) { // YAY, it is our message result = ECI_OK; // yeah, let's leave this while loop finished = TRUE; // and the outer while loop eMode = (e_MODES)mode; // Make sure we set the global mode status, too. } else { // it's not our message result = ~ECI_OK; // yeah, don't leave this loop } } // there was a message on the queue OS_Printf("."); OS_Fflush(stdout); cntr++; } // while not ECI_OK tries++; OS_Printf("\n"); OS_Fflush(stdout); } // while we are not finished & we haven't reached our maximum try limit } // if Targeted node was ok else { OS_Printf("Targeted Node - %u - out of range 1..1023\n", (WORD)subCommand); OS_Printf("Mode **NOT** changed. Please change node number from %u\n",iNode); } // Check node } // if subCommand is ok else { OS_Printf("Mode change is out of range. Needs to be from 0..%u\n",(BYTE)MODE_TESTHW); OS_Printf("Mode **NOT** changed."); } if (TRUE == finished) { // only if we found the result we wanted do we return OK result = ECI_OK; } else { result = ~ECI_OK; } return result; } // DoModeChange
/** * @brief Validate and execute the command(s) requested * @author R.Lillback * @date 1-Sep-2015 * * @details This is the main multiplexer to figure out which function(s) get called. * * @param command = the command index to run see CLI_COMMANDS[].iIndex * subcommand = the integer value of the subcommand * * @returns the integer value of the sub command, if any. If none, it returns 0. * */ DWORD ExecuteCommand (int command, int subCommand) { DWORD result = TRUE; int i = 0; int loopDone = FALSE; switch(command) { /****************************************************************************************/ case 0: // HELP { loopDone = FALSE; i=0; while (!loopDone) { if (CLI_COMMANDS[i].strCmd == '\0') { loopDone = TRUE; // Loop until you hit the empty command } else { OS_Printf("%s\n",CLI_COMMANDS[i].strDescr); } i++; } // while break; } // HELP /****************************************************************************************/ case 1: // NODE xxx { if ( ((WORD)subCommand > 0) && ((WORD)subCommand < 1024) ) { iNode = (WORD)subCommand; // Change the targeted node OS_Printf("Targeted Node Changed to: %u\n", iNode); return ECI_OK; } else { OS_Printf("Targeted Node - %u - out of range 1..1023\n", (WORD)subCommand); OS_Printf("Targeted Node **NOT** changed.\n"); return ~ECI_OK; } break; } // NODE /****************************************************************************************/ case 2: // MODE x { result = DoModeChange(subCommand); // Call a subroutine to change modes if (ECI_OK == result) { OS_Printf("Mode change successful.\n"); } break; } // MODE /****************************************************************************************/ case 3: // READALL - Read entire OD { //TODO: Create the ReadBlock SDO command result = PopulateObjectDictionary(); // Call a subroutine to do this break; } // READALL /****************************************************************************************/ case 4: // OUTON X - Turn on output X { //TODO: Validity check that we are in hardware test mode //TODO: Validity check the Output is in 1..14 //TODO: Create the read (both expedited and not) SDO Download //TODO: Be sure to get the complete transaction & await the handshake OS_Printf("Command %s not implemented yet.\n",CLI_COMMANDS[command+1].strCmd); break; } // OUTOFF /****************************************************************************************/ case 5: // OUTOFF - Turn off output X { //TODO: Validity check that we are in hardware test mode //TODO: Validity check the Output is in 1..14 //TODO: Do OUTON first! OS_Printf("Command %s not implemented yet.\n",CLI_COMMANDS[command+1].strCmd); break; } // OUTOFF /****************************************************************************************/ case 6: // INSTAT - Read and show the status of all inputs { //TODO: Create the UPLOAD request OS_Printf("Command %s not implemented yet.\n",CLI_COMMANDS[command+1].strCmd); break; } // INSTAT /****************************************************************************************/ case 7: // OUTSTAT - Read and show the status of all outputs { //TODO: Create the UPLOAD request OS_Printf("Command %s not implemented yet.\n",CLI_COMMANDS[command+1].strCmd); break; } // OUTSTAT /****************************************************************************************/ case 254: // EXIT { iQuit = TRUE; break; } // EXIT /****************************************************************************************/ default: { OS_Printf("How did I get this far in the command switch statement of cmdMultiplex.c ExecuteCommand() o.O?\n"); break; } /****************************************************************************************/ } // switch return result; } //ExecuteCommand