mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-07-26 06:38:42 +00:00
usb/msc: wait for interrupt instead of polling a flag
This should make usb/msc a whole lot more efficient by pausing the worker goroutine and waiting for an interrupt to unpause it instead of waiting in a loop and sleeping for 0.1ms each cycle. In other words, this should make it both faster (no unnecessary delay due to the time.Sleep) and more efficient (no polling).
This commit is contained in:
+22
-22
@@ -1,12 +1,12 @@
|
||||
package msc
|
||||
|
||||
import (
|
||||
"internal/task"
|
||||
"machine"
|
||||
"machine/usb"
|
||||
"machine/usb/descriptor"
|
||||
"machine/usb/msc/csw"
|
||||
"machine/usb/msc/scsi"
|
||||
"time"
|
||||
)
|
||||
|
||||
type mscState uint8
|
||||
@@ -26,14 +26,14 @@ const (
|
||||
var MSC *msc
|
||||
|
||||
type msc struct {
|
||||
buf []byte // Buffer for incoming/outgoing data
|
||||
blockCache []byte // Buffer for block read/write data
|
||||
taskQueued bool // Flag to indicate if the buffer has a task queued
|
||||
rxStalled bool // Flag to indicate if the RX endpoint is stalled
|
||||
txStalled bool // Flag to indicate if the TX endpoint is stalled
|
||||
maxPacketSize uint32 // Maximum packet size for the IN endpoint
|
||||
respStatus csw.Status // Response status for the last command
|
||||
sendZLP bool // Flag to indicate if a zero-length packet should be sent before sending CSW
|
||||
buf []byte // Buffer for incoming/outgoing data
|
||||
blockCache []byte // Buffer for block read/write data
|
||||
taskWaiter task.Waiter // Waiter for events outside interrupt context
|
||||
rxStalled bool // Flag to indicate if the RX endpoint is stalled
|
||||
txStalled bool // Flag to indicate if the TX endpoint is stalled
|
||||
maxPacketSize uint32 // Maximum packet size for the IN endpoint
|
||||
respStatus csw.Status // Response status for the last command
|
||||
sendZLP bool // Flag to indicate if a zero-length packet should be sent before sending CSW
|
||||
|
||||
cbw *CBW // Last received Command Block Wrapper
|
||||
queuedBytes uint32 // Number of bytes queued for sending
|
||||
@@ -120,21 +120,21 @@ func newMSC(dev machine.BlockDevice) *msc {
|
||||
func (m *msc) processTasks() {
|
||||
// Process tasks that cannot be done in an interrupt context
|
||||
for {
|
||||
if m.taskQueued {
|
||||
cmd := m.cbw.SCSICmd()
|
||||
switch cmd.CmdType() {
|
||||
case scsi.CmdWrite:
|
||||
m.scsiWrite(cmd, m.buf)
|
||||
case scsi.CmdUnmap:
|
||||
m.scsiUnmap(m.buf)
|
||||
}
|
||||
// Wait for the next task to arrive.
|
||||
m.taskWaiter.Wait()
|
||||
|
||||
// Acknowledge the received data from the host
|
||||
m.queuedBytes = 0
|
||||
m.taskQueued = false
|
||||
machine.AckUsbOutTransfer(usb.MSC_ENDPOINT_OUT)
|
||||
cmd := m.cbw.SCSICmd()
|
||||
switch cmd.CmdType() {
|
||||
case scsi.CmdWrite:
|
||||
m.scsiWrite(cmd, m.buf)
|
||||
case scsi.CmdUnmap:
|
||||
m.scsiUnmap(m.buf)
|
||||
}
|
||||
time.Sleep(100 * time.Microsecond)
|
||||
|
||||
// Acknowledge the received data from the host
|
||||
m.queuedBytes = 0
|
||||
m.taskWaiter.Done()
|
||||
machine.AckUsbOutTransfer(usb.MSC_ENDPOINT_OUT)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -251,7 +251,7 @@ func (m *msc) scsiQueueTask(cmdType scsi.CmdType, b []byte) bool {
|
||||
}
|
||||
|
||||
// Save the incoming data in our buffer for processing outside of interrupt context.
|
||||
if m.taskQueued {
|
||||
if m.taskWaiter.Working() {
|
||||
// If we already have a full task queue we can't accept this data
|
||||
m.sendScsiError(csw.StatusFailed, scsi.SenseAbortedCommand, scsi.SenseCodeMsgReject)
|
||||
return true
|
||||
@@ -268,14 +268,14 @@ func (m *msc) scsiQueueTask(cmdType scsi.CmdType, b []byte) bool {
|
||||
case scsi.CmdWrite:
|
||||
// If we're writing data wait until we have a full write block of data that can be processed.
|
||||
if m.queuedBytes == uint32(cap(m.blockCache)) || (m.sentBytes+m.queuedBytes >= m.transferBytes) {
|
||||
m.taskQueued = true
|
||||
m.taskWaiter.Resume()
|
||||
}
|
||||
case scsi.CmdUnmap:
|
||||
m.taskQueued = true
|
||||
m.taskWaiter.Resume()
|
||||
}
|
||||
|
||||
// Don't acknowledge the incoming data until we can process it.
|
||||
return !m.taskQueued
|
||||
return !m.taskWaiter.Working()
|
||||
}
|
||||
|
||||
func (m *msc) sendScsiError(status csw.Status, key scsi.Sense, code scsi.SenseCode) {
|
||||
|
||||
Reference in New Issue
Block a user