浏览代码

Improved reliability of USB config interface (port from V5 branch)

Michael McMaster 4 年之前
父节点
当前提交
4fca010c48

+ 5 - 0
lib/SCSI2SD/include/hidpacket.h

@@ -54,6 +54,11 @@ void hidPacket_send(const uint8_t* bytes, size_t len);
 // NULL if there's nothing to send.
 // NULL if there's nothing to send.
 const uint8_t* hidPacket_getHIDBytes(uint8_t* hidBuffer);
 const uint8_t* hidPacket_getHIDBytes(uint8_t* hidBuffer);
 
 
+// Returns 1 if hidPacket_getHIDBytes will return non-null
+int hidPacket_getHIDBytesReady();
+
+void hidPacket_reset();
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 } // extern "C"
 } // extern "C"
 #endif
 #endif

+ 27 - 11
lib/SCSI2SD/src/firmware/config.c

@@ -331,26 +331,33 @@ void s2s_configPoll()
 	if (!USBD_Composite_IsConfigured(&configUsbDev))
 	if (!USBD_Composite_IsConfigured(&configUsbDev))
 	{
 	{
 		usbInEpState = USB_IDLE;
 		usbInEpState = USB_IDLE;
+		hidPacket_reset();
 		goto out;
 		goto out;
 	}
 	}
 
 
 	if (USBD_HID_IsReportReady(&configUsbDev))
 	if (USBD_HID_IsReportReady(&configUsbDev))
 	{
 	{
-		s2s_ledOn();
-
-		// The host sent us some data!
-		uint8_t hidBuffer[USBHID_LEN];
-		int byteCount = USBD_HID_GetReport(&configUsbDev, hidBuffer, sizeof(hidBuffer));
-		hidPacket_recv(hidBuffer, byteCount);
+		// Check if we have a previous command outstanding
+		// before accepting another
+		size_t cmdSize;
+		if (hidPacket_peekPacket(&cmdSize) == NULL)
+		{
+			uint8_t hidBuffer[USBHID_LEN];
+			int byteCount = USBD_HID_GetReport(&configUsbDev, hidBuffer, sizeof(hidBuffer));
+			hidPacket_recv(hidBuffer, byteCount);
+		}
+	}
 
 
+	if (hidPacket_getHIDBytesReady() == 0) // Nothing queued to send
+	{
 		size_t cmdSize;
 		size_t cmdSize;
 		const uint8_t* cmd = hidPacket_getPacket(&cmdSize);
 		const uint8_t* cmd = hidPacket_getPacket(&cmdSize);
 		if (cmd && (cmdSize > 0))
 		if (cmd && (cmdSize > 0))
 		{
 		{
+			s2s_ledOn();
 			processCommand(cmd, cmdSize);
 			processCommand(cmd, cmdSize);
+			s2s_ledOff();
 		}
 		}
-
-		s2s_ledOff();
 	}
 	}
 
 
 	switch (usbInEpState)
 	switch (usbInEpState)
@@ -391,10 +398,19 @@ void s2s_debugTimer()
 
 
 	if (USBD_HID_IsReportReady(&configUsbDev))
 	if (USBD_HID_IsReportReady(&configUsbDev))
 	{
 	{
-		uint8_t hidBuffer[USBHID_LEN];
-		int byteCount = USBD_HID_GetReport(&configUsbDev, hidBuffer, sizeof(hidBuffer));
-		hidPacket_recv(hidBuffer, byteCount);
+		// Check if we have a previous command outstanding
+		// before accepting another
+		size_t cmdSize;
+		if (hidPacket_peekPacket(&cmdSize) == NULL)
+		{
+			uint8_t hidBuffer[USBHID_LEN];
+			int byteCount = USBD_HID_GetReport(&configUsbDev, hidBuffer, sizeof(hidBuffer));
+			hidPacket_recv(hidBuffer, byteCount);
+		}
+	}
 
 
+	if (hidPacket_getHIDBytesReady() == 0) // Nothing queued to send
+	{
 		size_t cmdSize;
 		size_t cmdSize;
 		const uint8_t* cmd = hidPacket_peekPacket(&cmdSize);
 		const uint8_t* cmd = hidPacket_peekPacket(&cmdSize);
 		// This is called from an ISR, only process simple commands.
 		// This is called from an ISR, only process simple commands.

+ 17 - 0
lib/SCSI2SD/src/firmware/hidpacket.c

@@ -46,6 +46,12 @@ txReset()
 	tx.offset = 0;
 	tx.offset = 0;
 }
 }
 
 
+void hidPacket_reset()
+{
+    rxReset();
+    txReset();
+}
+
 void hidPacket_recv(const uint8_t* bytes, size_t len)
 void hidPacket_recv(const uint8_t* bytes, size_t len)
 {
 {
 	if (len < 2)
 	if (len < 2)
@@ -141,6 +147,17 @@ void hidPacket_send(const uint8_t* bytes, size_t len)
 	}
 	}
 }
 }
 
 
+int
+hidPacket_getHIDBytesReady()
+{
+       if ((tx.state != PARTIAL) || (tx.offset <= 0))
+       {
+               return 0;
+       }
+
+       return 1;
+}
+
 const uint8_t*
 const uint8_t*
 hidPacket_getHIDBytes(uint8_t* hidBuffer)
 hidPacket_getHIDBytes(uint8_t* hidBuffer)
 {
 {

+ 0 - 23
lib/SCSI2SD/src/firmware/main.c

@@ -139,29 +139,6 @@ void mainLoop()
 			}
 			}
 
 
 		}
 		}
-		else
-		{
-			// TODO this hurts performance significantly! Work out why __WFI()
-			// doesn't wake up immediately !
-#if 0
-			// Wait for our 1ms timer to save some power.
-			// There's an interrupt on the SEL signal to ensure we respond
-			// quickly to any SCSI commands. The selection abort time is
-			// only 250us, and new SCSI-3 controllers time-out very
-			// not long after that, so we need to ensure we wake up quickly.
-			uint32_t interruptState = __get_PRIMASK();
-			__disable_irq();
-
-			if (!*SCSI_STS_SELECTED)
-			{
-				//__WFI(); // Will wake on interrupt, regardless of mask
-			}
-			if (!interruptState)
-			{
-				__enable_irq();
-			}
-#endif
-		}
 	}
 	}
 	else if ((scsiDev.phase >= 0) && (blockDev.state & DISK_PRESENT))
 	else if ((scsiDev.phase >= 0) && (blockDev.state & DISK_PRESENT))
 	{
 	{