Beispiel #1
0
// OK, a bit of explanation here:
// The only operation that can be in progress is Job-Handling.
// We can do one thing however, make sure that the job is not active...
// We must read the ASIC periodically until we have some response.
void MCU_Main_Loop()
{
	// Commands received from PC is 3 bytes in length
	// and will look like 'Z' + [COMMAND] + 'X'.
	//
	// Once we receive a packet like this, we must respond with 'OK'
	// and call the corresponding function.
	// The function will take it from there...
	// (PC Will send the rest of the data after that...)

	// First things first, we must clear the FTDI chip
	// Read all that you can..
	volatile int i = 10000;
	unsigned int intercepted_command_length = 0;
	
	while (USB_inbound_USB_data() && i-- > 1) USB_read_byte();

	// OK, now the memory on FTDI is empty,
	// wait for standard packet size
	char sz_cmd[2048];
	volatile unsigned int umx;
	volatile unsigned int  i_count = 0;
	
	char bTimeoutDetectedOnXLINK = 0;
	char bDeviceNotRespondedOnXLINK = 0;			
	
	for (umx = 0; umx < 1024; umx++) sz_cmd[umx] = 0;
	
	// Clear logg buffer if needed
	#if defined(__SHOW_DECOMMISSIONED_ENGINES_LOG)
		strcpy(szDecommLog,"");	
	#endif
	
	//////////////////////////////////////////
	// Turn the LED on
	//////////////////////////////////////////
	MCU_MainLED_Set();
	
	while (1)
	{
		// HighLevel Functions Spin
		Microkernel_Spin();

		//////////////////////////////////////////
		// If we are master, we'll listen to the USB
		//////////////////////////////////////////
		if (XLINK_ARE_WE_MASTER)
		{
			// We listen to USB
			i = 3;
			while (!USB_inbound_USB_data() && i-- > 1);
			
			// Check, if 'i' equals zero, we discard the actual command buffer
			if (i <= 1)
			{
				// Clear buffer, something is wrong...
				i_count = 0;
				sz_cmd[0] = 0;
				sz_cmd[1] = 0;
				sz_cmd[2] = 0;
			}

			// We've reduced timeout counter to 5000, so we can run this function periodically
			// Flush the job (should they exist)
			// This must be called on a timer running 
			// Management_flush_p2p_buffer_into_engines();

			// Check if there is data, or we just had
			// an overflow?
			if (!USB_inbound_USB_data()) continue;
			
			// Was EndOfStream detected?
			intercepted_command_length = 0;
			
			volatile unsigned int bEOSDetected = FALSE;
			volatile unsigned int iExpectedPacketLength = 0;
			volatile unsigned int bInterceptingChainForwardReq = FALSE;
			volatile unsigned char bSingleStageJobIssueCommand = FALSE;
			volatile unsigned char bSingleStageMultiJobIssueCommand = FALSE;
			volatile unsigned char __expected_singlestage_multijob_length = 0xFF;

			// Read all the data that has arrived
			while (USB_inbound_USB_data() && i_count < 2048)
			{
				// Read byte
				sz_cmd[i_count] = USB_read_byte();
				
				// Are we a single-cycle job issue?
				bSingleStageJobIssueCommand = ((sz_cmd[0] == 'S') && (sz_cmd[1] == 48)) ? TRUE : FALSE;
				bSingleStageMultiJobIssueCommand = ((sz_cmd[0] == 'W') && (sz_cmd[1] == 'X')) ? TRUE : FALSE;
				
				// Are we expecting 
				bInterceptingChainForwardReq = (sz_cmd[0] == 64) ? TRUE : FALSE;
				
				if (bInterceptingChainForwardReq) 
				{
					 intercepted_command_length = (i_count + 1) - 3; // First three characters are @XY (X = Packet Size, Y = Forware Number)
					 if (i_count > 1) iExpectedPacketLength = sz_cmd[1] & 0x0FF;
				}	
				
				// Increase Count				 
				i_count++;
				
				// Determine single-stage multi-job command length
				if (i_count >= 3)
				{
					__expected_singlestage_multijob_length = sz_cmd[2] + 1 + 2; // +1 because this length does not include the stream-length byte itself
																				// +2 because it doesn't include the initial 'WX' either
				}
								
				
				// Check if 3-byte packet is done
				if ((i_count == 3) && (bInterceptingChainForwardReq == FALSE) && 
					(bSingleStageJobIssueCommand == FALSE) && 
					(bSingleStageMultiJobIssueCommand == FALSE))
				{
					bEOSDetected = TRUE;
					break;
				}					 
				
				if (bInterceptingChainForwardReq && (intercepted_command_length == iExpectedPacketLength))
				{
					bEOSDetected = TRUE;
					break;
				}
				
				if ((bSingleStageJobIssueCommand == TRUE) && (i_count == 48))
				{
					bEOSDetected = TRUE;
					break;
				}
				
				if ((bSingleStageMultiJobIssueCommand == TRUE) && (i_count == __expected_singlestage_multijob_length))
				{
					bEOSDetected = TRUE;
					// Set the correct intercepted_Command_length
					intercepted_command_length = i_count - 2; // Minus 2 because you need to include Field
					break;
				}				
				
				// Check if we've overlapped
				if (i_count > 256)							
				{
					// Clear buffer, something is wrong...
					i_count = 0;
					__expected_singlestage_multijob_length = 0xFF;
					sz_cmd[0] = 0;
					sz_cmd[1] = 0;
					sz_cmd[2] = 0;
					continue;
				}
				
			}	
			
			// Check for length and signature
			// If we've received less than three characters, continue waiting
			if (i_count < 3)
			{
				if (bEOSDetected == TRUE)
				{
					// Clear buffer, something is wrong...
					i_count = 0;
					__expected_singlestage_multijob_length = 0xFF;
					sz_cmd[0] = 0;
					sz_cmd[1] = 0;
					sz_cmd[2] = 0;
					continue;
				}
				else 
				{
					continue; // We'll continue...			
				}					
			}
			

		}
		else 
		{
			///////////////////////////////////////////////
			// We listen to XLINK, as we are a chain-slave
			///////////////////////////////////////////////
						
			// Wait for incoming transactions
			bTimeoutDetectedOnXLINK = FALSE;
			
			// Run the procedure
			XLINK_SLAVE_wait_transact(sz_cmd, 
									  &i_count, 
									  2048, 
									  __XLINK_TRANSACTION_TIMEOUT__,  // 1000us, or 1ms
									  &bTimeoutDetectedOnXLINK, 
									  FALSE, TRUE); // Note: WE ARE WAITING FOR COMMAND
			
			// Check for sz_cmd, if it's PUSH then we have an invalid command
			if ((sz_cmd[0] == 'P') && (sz_cmd[1] == 'U') && (sz_cmd[2] == 'S') && (sz_cmd[3] == 'H'))
			{
				MACRO_XLINK_send_packet(XLINK_get_cpld_id(), "INVA", 4, TRUE, FALSE);
				continue;
			}
			
			// Is it a RIMA packet verification call?
			if ((sz_cmd[0] == 'R') && (sz_cmd[1] == 'I') && (sz_cmd[2] == 'M') && (sz_cmd[3] == 'A'))
			{
				DEBUG_TotalRIMA_Count++;
				continue;				
			}
			
			// Check for sz_cmd, AA BB C4 <ID>, then we set CPLD ID and enable pass-through
			if ((sz_cmd[0] == 0xAA) && (sz_cmd[1] == 0xBB) && (sz_cmd[2] == 0xC4) && (i_count == 4))
			{
				// We respond with 'ACK' and then change the address
				XLINK_SLAVE_respond_transact("ACK", 
											 3,
											 __XLINK_TRANSACTION_TIMEOUT__, 
											 &bTimeoutDetectedOnXLINK, 
											 FALSE); // Note: We'll used XLINK general dispatch address for this specific operation!

				// Set the new address
				XLINK_set_cpld_id(sz_cmd[3]);
				continue;
			}
			
			// How many bytes did we receive?
			intercepted_command_length = i_count;
			
			// Check 
			if (bTimeoutDetectedOnXLINK) continue;			
		}		
		
		// Are we a single-stage job-issue command?
		char bSingleStageJobIssueCommand = ((sz_cmd[0] == 'S') && (sz_cmd[1] == 48)) ? TRUE : FALSE; 
		char bSingleStageMultiJobIssueCommand = ((sz_cmd[0] == 'W') && (sz_cmd[1] == 'X')) ? TRUE : FALSE;
		
		// Check number of bytes received so far.
		// If they are 3, we may have a command here (4 for the AMUX Read)...
		if (TRUE)
		{
			// Reset the count anyway
			i_count = 0;

			// Check for packet integrity
			if (((sz_cmd[0] != 'Z' || sz_cmd[2] != 'X') && 
				(sz_cmd[0] != '@')) && 
				(bSingleStageJobIssueCommand == FALSE) && 
				(bSingleStageMultiJobIssueCommand == FALSE)) // @XX means forward to XX (X must be between '0' and '9')
			{
				continue;
			}
			else
			{
				// We have a command. Check for validity
				if ((sz_cmd[0] != '@') &&
					(bSingleStageJobIssueCommand == FALSE) && 
					(bSingleStageMultiJobIssueCommand == FALSE) && 
					(sz_cmd[1] != PROTOCOL_REQ_INFO_REQUEST) &&
					(sz_cmd[1] != PROTOCOL_REQ_BUF_FLUSH_EX) &&
					(sz_cmd[1] != PROTOCOL_REQ_HANDLE_JOB) &&
					(sz_cmd[1] != PROTOCOL_REQ_ID) &&
					(sz_cmd[1] != PROTOCOL_REQ_GET_FIRMWARE_VERSION) &&
					(sz_cmd[1] != PROTOCOL_REQ_BLINK) &&
					(sz_cmd[1] != PROTOCOL_REQ_TEMPERATURE) &&
					(sz_cmd[1] != PROTOCOL_REQ_BUF_PUSH_JOB_PACK) &&
					(sz_cmd[1] != PROTOCOL_REQ_BUF_PUSH_JOB) &&
					(sz_cmd[1] != PROTOCOL_REQ_BUF_STATUS) &&
					(sz_cmd[1] != PROTOCOL_REQ_BUF_FLUSH) &&
					(sz_cmd[1] != PROTOCOL_REQ_GET_VOLTAGES) &&
					(sz_cmd[1] != PROTOCOL_REQ_GET_CHAIN_LENGTH) &&
					(sz_cmd[1] != PROTOCOL_REQ_SET_FREQ_FACTOR) &&
					(sz_cmd[1] != PROTOCOL_REQ_GET_FREQ_FACTOR) &&
					(sz_cmd[1] != PROTOCOL_REQ_SET_XLINK_ADDRESS)	&&
					(sz_cmd[1] != PROTOCOL_REQ_XLINK_ALLOW_PASS) &&
					(sz_cmd[1] != PROTOCOL_REQ_XLINK_DENY_PASS) &&
					(sz_cmd[1] != PROTOCOL_REQ_PRESENCE_DETECTION) &&
					(sz_cmd[1] != PROTOCOL_REQ_ECHO) &&
					(sz_cmd[1] != PROTOCOL_REQ_TEST_COMMAND) &&
					(sz_cmd[1] != PROTOCOL_REQ_SAVE_STRING) &&
					(sz_cmd[1] != PROTOCOL_REQ_LOAD_STRING) &&
					(sz_cmd[1] != PROTOCOL_REQ_GET_STATUS))
				{					
					if (XLINK_ARE_WE_MASTER)
					{
						USB_send_string("ERR:UNKNOWN COMMAND\n");
					}						
					else
					{
						XLINK_SLAVE_respond_transact("ERR:UNKNOWN COMMAND\n", 
													 sizeof("ERR:UNKNOWN COMMAND\n"), 
													 __XLINK_TRANSACTION_TIMEOUT__, 
													 &bDeviceNotRespondedOnXLINK, 
													 FALSE);
					}
																		 
					// Continue the loop	
					continue;
				}
				
				// Do we have a Chain-Forward request?
				if ((sz_cmd[0] == '@') && (XLINK_ARE_WE_MASTER))
				{
					// Forward command to the device in chain...
					DEBUG_LastXLINKTransTook = MACRO_GetTickCountRet;
					
					Protocol_chain_forward((char)sz_cmd[2], 
										   (char*)(sz_cmd+3), 
										   intercepted_command_length); // Length is always 3	
										   
					DEBUG_LastXLINKTransTook = MACRO_GetTickCountRet - DEBUG_LastXLINKTransTook;
				}					
				else
				{
					// We have a valid command, go call its procedure...
					if (bSingleStageJobIssueCommand)
					{
						Protocol_handle_job_single_stage(sz_cmd);
					}
					else if (bSingleStageMultiJobIssueCommand)
					{
						Protocol_MultiJob_single_stage((const char*)(sz_cmd + 2), 
													   (XLINK_ARE_WE_MASTER) ? (intercepted_command_length) : (intercepted_command_length - 2)); // +2 because the first two characters are 'W','X'
					}
					else
					{
						// Job-Issuing commands
						if (sz_cmd[1] == PROTOCOL_REQ_BUF_PUSH_JOB)			Protocol_PIPE_BUF_PUSH();
						if (sz_cmd[1] == PROTOCOL_REQ_BUF_PUSH_JOB_PACK)    Protocol_PIPE_BUF_PUSH_PACK();
						if (sz_cmd[1] == PROTOCOL_REQ_HANDLE_JOB)			Protocol_handle_job();
					
						// Load String / Save String
						if (sz_cmd[1] == PROTOCOL_REQ_SAVE_STRING)			Protocol_save_string();
						if (sz_cmd[1] == PROTOCOL_REQ_LOAD_STRING)			Protocol_load_string();
					
						// The rest of the commands
						if (sz_cmd[1] == PROTOCOL_REQ_BUF_FLUSH)			Protocol_PIPE_BUF_FLUSH();
						if (sz_cmd[1] == PROTOCOL_REQ_BUF_FLUSH_EX)			Protocol_PIPE_BUF_FLUSH_EX();
						if (sz_cmd[1] == PROTOCOL_REQ_BUF_STATUS)			Protocol_PIPE_BUF_STATUS();
						if (sz_cmd[1] == PROTOCOL_REQ_INFO_REQUEST)			Protocol_info_request();
						if (sz_cmd[1] == PROTOCOL_REQ_ID)					Protocol_id();
						if (sz_cmd[1] == PROTOCOL_REQ_BLINK)				Protocol_Blink();
						if (sz_cmd[1] == PROTOCOL_REQ_TEMPERATURE)			Protocol_temperature();
						if (sz_cmd[1] == PROTOCOL_REQ_GET_STATUS)			Protocol_get_status();
						if (sz_cmd[1] == PROTOCOL_REQ_GET_VOLTAGES)			Protocol_get_voltages();
						if (sz_cmd[1] == PROTOCOL_REQ_GET_FIRMWARE_VERSION)	Protocol_get_firmware_version();
						if (sz_cmd[1] == PROTOCOL_REQ_SET_FREQ_FACTOR)		Protocol_set_freq_factor();
						if (sz_cmd[1] == PROTOCOL_REQ_GET_FREQ_FACTOR)		Protocol_get_freq_factor();
						if (sz_cmd[1] == PROTOCOL_REQ_SET_XLINK_ADDRESS)	Protocol_set_xlink_address();
						if (sz_cmd[1] == PROTOCOL_REQ_XLINK_ALLOW_PASS)		Protocol_xlink_allow_pass();
						if (sz_cmd[1] == PROTOCOL_REQ_XLINK_DENY_PASS)		Protocol_xlink_deny_pass();
						if (sz_cmd[1] == PROTOCOL_REQ_ECHO)					Protocol_Echo();
						if (sz_cmd[1] == PROTOCOL_REQ_TEST_COMMAND)			Protocol_Test_Command();
						if (sz_cmd[1] == PROTOCOL_REQ_PRESENCE_DETECTION)   Protocol_xlink_presence_detection();
					}
				}	
				
				// Once we reach here, our procedure has run and we're back to standby...
			}
		}
		else
		{
			i_count = 0;
			continue;
		}		
	}
}
void USB_wait_stream (char* data,
					  unsigned int  *length,    // output
					  unsigned int   max_len,   // input
					  unsigned int  *time_out,  // Timeout variable
					  unsigned char *invalid_data) // Invalid-Data detected
{
	char byte_received = 0;
	char EOS_detected = 0;
	char expected_length = 0;
	char length_detected = FALSE;
	// Initialize length
	*length = 0;
	*invalid_data = FALSE;

	// while we have data (indicated in status register), read it
	// there is a cap of max_len bytes
	while (USB_inbound_USB_data() == FALSE && (*time_out) > 1)
	{
		WATCHDOG_RESET;
		*time_out = *time_out - 1;
	}; // Loop until there is some data

	// Is there timeout? abort in this case
	if (*time_out == 1)
	{
		USB_send_string("exit due to timeout1\n");
		return;
	}

	  //char byte_received = 0;
	  //char EOS_detected = 0;
	  //char expected_length = 0;
	  //char length_detected = FALSE;

	// Now continue until buffer is empty
	while ((*length < max_len) && *time_out-- > 1)
	{
		// Reset WATCHDOG
		WATCHDOG_RESET;
		
		// We read as u32 as there is inbound data, and max-len was not surpassed
		while ((*length < max_len) && 
			   (USB_inbound_USB_data() != FALSE) && 
			   (!EOS_detected))
		{
			// Reset watchdog
			WATCHDOG_RESET;
			
			// Proceed
			byte_received = USB_read_byte();
			
			if (length_detected == FALSE)
			{
				// If this is the first byte we're receiving, then it's our length indicator
				expected_length = byte_received;
				length_detected = TRUE;
			}
			else
			{			
				// We take the byte as u32 as total length is less than maximum length.
				// Like this if we're in a problematic transaction, we won't encounter buffer overrun
				// and at the same time we will clear FTDI's buffer for the newer transactions
				if ((*length) < max_len) data[(*length)] = byte_received;
				*length = *length + 1;				
			}			
			
			// Check for signature
			EOS_detected = (((*length) >= max_len) || ((*length) == expected_length));			
		}

		// Ok, now we check if we have detected the sign already
		if ((*length >= max_len) || (EOS_detected))
		{
			// Read the remainder of bytes in FTDI fifo until it's empty
			while (USB_inbound_USB_data() == TRUE) 
			{ 
				WATCHDOG_RESET;
				byte_received = USB_read_byte(); 
			} 
			break;
		}			 

		// No, so we wait for more inbound data
		while ((USB_inbound_USB_data() == FALSE) && (*time_out > 1)) 
		{ 
			WATCHDOG_RESET;
			*time_out = *time_out - 1;
		} // Loop until there is some data again...
	}

	// OK, we're done at this point. Most likely we'll have our packet, unless
	// there is a timeout, or buffer is bigger than req_size (which means something must've gone wrong)
	if (!EOS_detected)
	{
		*invalid_data = TRUE;
	}	
}