functioning USB-CDC class initialization

This commit is contained in:
sago35
2022-05-12 20:34:37 +09:00
parent 6e29c17a8b
commit 2f50d24fec
14 changed files with 1499 additions and 509 deletions
+1 -1
View File
@@ -8,7 +8,7 @@ import (
)
func main() {
uart := machine.UART0
uart := machine.Serial
uart.Write([]byte("Echo console enabled. Type something then press enter:\r\n"))
input := make([]byte, 4096)
+6
View File
@@ -3,6 +3,10 @@
package machine
import (
"machine/usb"
)
// Digital pins
const (
// = Pin Alt. Function SERCOM PWM Timer Interrupt
@@ -248,6 +252,8 @@ const (
RESET_MAGIC_VALUE = 0xF01669EF // Used to reset into bootloader
)
var USB = usb.UART{Port: 0}
// USB CDC pins
const (
USBCDC_HOSTEN_PIN = D77 // (PA27) host enable
+11 -11
View File
@@ -1985,10 +1985,10 @@ type USBCDC struct {
configured bool
}
var (
// USB is a USB CDC interface.
USB = &USBCDC{Buffer: NewRingBuffer()}
)
// var (
// // USB is a USB CDC interface.
// USB = &USBCDC{Buffer: NewRingBuffer()}
// )
const (
usbcdcTxSizeMask uint8 = 0x3F
@@ -2163,10 +2163,10 @@ func (usbcdc *USBCDC) Configure(config UARTConfig) {
sam.USB_DEVICE.CTRLA.SetBits(sam.USB_DEVICE_CTRLA_ENABLE)
// enable IRQ at highest priority
interrupt.New(sam.IRQ_USB_OTHER, handleUSBIRQ).Enable()
interrupt.New(sam.IRQ_USB_SOF_HSOF, handleUSBIRQ).Enable()
interrupt.New(sam.IRQ_USB_TRCPT0, handleUSBIRQ).Enable()
interrupt.New(sam.IRQ_USB_TRCPT1, handleUSBIRQ).Enable()
//interrupt.New(sam.IRQ_USB_OTHER, handleUSBIRQ).Enable()
//interrupt.New(sam.IRQ_USB_SOF_HSOF, handleUSBIRQ).Enable()
//interrupt.New(sam.IRQ_USB_TRCPT0, handleUSBIRQ).Enable()
//interrupt.New(sam.IRQ_USB_TRCPT1, handleUSBIRQ).Enable()
usbcdc.configured = true
}
@@ -2240,7 +2240,7 @@ func handleUSBIRQ(interrupt.Interrupt) {
// Start of frame
if (flags & sam.USB_DEVICE_INTFLAG_SOF) > 0 {
USB.Flush()
//USB.Flush()
// if you want to blink LED showing traffic, this would be the place...
}
@@ -2300,7 +2300,7 @@ func handleUSBIRQ(interrupt.Interrupt) {
setEPINTFLAG(i, sam.USB_DEVICE_ENDPOINT_EPINTFLAG_TRCPT1)
if i == usb_CDC_ENDPOINT_IN {
USB.waitTxc = false
//USB.waitTxc = false
}
}
}
@@ -2614,7 +2614,7 @@ func handleEndpoint(ep uint32) {
// move to ring buffer
for i := 0; i < count; i++ {
USB.Receive(byte((udd_ep_out_cache_buffer[ep][i] & 0xFF)))
//USB.Receive(byte((udd_ep_out_cache_buffer[ep][i] & 0xFF)))
}
// set byte count to zero
+8
View File
@@ -5,3 +5,11 @@ package machine
// Serial is implemented via USB (USB-CDC).
var Serial = USB
func init() {
// configure pins
USBCDC_DM_PIN.Configure(PinConfig{Mode: PinCom})
USBCDC_DP_PIN.Configure(PinConfig{Mode: PinCom})
}
+177 -79
View File
@@ -7,7 +7,10 @@ package usb
// implemented for each target, providing common/shared functionality and
// defining a standard interface with which the dhw must adhere.
import "unsafe"
import (
"runtime/volatile"
"unsafe"
)
// dcdCount defines the number of USB cores to configure for device mode. It is
// computed as the sum of all declared device configuration descriptors.
@@ -29,6 +32,8 @@ type dcd struct {
port int // USB port index
cc class // USB device class
id int // USB device controller index
st volatile.Register8 // USB device state
}
// initDCD initializes and assigns a free device controller instance to the
@@ -54,6 +59,7 @@ func initDCD(port int, speed Speed, class class) (*dcd, status) {
dcdInstance[i].port = port
dcdInstance[i].cc = class
dcdInstance[i].id = i
dcdInstance[i].setState(dcdStateNotReady)
return &dcdInstance[i], statusOK
}
}
@@ -77,24 +83,19 @@ type dcdSetup struct {
// setupFrom decodes and returns a USB standard setup packet located at the
// memory address pointed to by addr.
func setupFrom(addr uintptr) dcdSetup {
func setupFrom(addr uintptr) (s dcdSetup) {
var u uint64
for i := uintptr(0); i < 8; i++ {
for i := uintptr(0); i < dcdSetupSize; i++ {
u |= uint64(*(*uint8)(unsafe.Pointer(addr + i))) << (i << 3)
}
return dcdSetup{
bmRequestType: uint8(u & 0xFF),
bRequest: uint8((u & 0xFF00) >> 8),
wValue: uint16((u & 0xFFFF0000) >> 16),
wIndex: uint16((u & 0xFFFF00000000) >> 32),
wLength: uint16((u & 0xFFFF000000000000) >> 48),
}
s.set(u)
return
}
// setup decodes and returns a USB standard setup packet stored in the given
// byte slice b.
func setup(b []uint8) dcdSetup {
if len(b) >= 8 {
if len(b) >= int(dcdSetupSize) {
return dcdSetup{
bmRequestType: b[0],
bRequest: b[1],
@@ -106,7 +107,17 @@ func setup(b []uint8) dcdSetup {
return dcdSetup{}
}
//go:inline
func (s *dcdSetup) set(u uint64) {
s.bmRequestType = uint8(u & 0xFF)
s.bRequest = uint8((u & 0xFF00) >> 8)
s.wValue = uint16((u & 0xFFFF0000) >> 16)
s.wIndex = uint16((u & 0xFFFF00000000) >> 32)
s.wLength = uint16((u & 0xFFFF000000000000) >> 48)
}
// pack returns the receiver USB standard setup packet s encoded as uint64.
//go:inline
func (s dcdSetup) pack() uint64 {
return ((uint64(s.bmRequestType) & 0xFF) << 0) |
((uint64(s.bRequest) & 0xFF) << 8) |
@@ -115,6 +126,54 @@ func (s dcdSetup) pack() uint64 {
((uint64(s.wLength) & 0xFFFF) << 48)
}
// direction parses the direction bit from the bmRequestType field of a SETUP
// packet, returning 0 for OUT (Rx) and 1 for IN (Tx) requests.
//go:inline
func (s dcdSetup) direction() uint8 {
return (s.bmRequestType & descRequestTypeDirMsk) >> descRequestTypeDirPos
}
//go:inline
func (s dcdSetup) equals(t dcdSetup) bool {
return s.bmRequestType == t.bmRequestType && s.bRequest == t.bRequest &&
s.wValue == t.wValue && s.wIndex == t.wIndex && s.wLength == t.wLength
}
// dcdState defines the current state of the device class driver.
type dcdState uint8
const (
dcdStateNotReady dcdState = iota // initial state, before END_OF_RESET
dcdStateDefault // after END_OF_RESET, before SET_ADDRESS
dcdStateAddressed // after SET_ADDRESS, before SET_CONFIGURATION
dcdStateConfigured // after SET_CONFIGURATION, operational state
dcdStateSuspended // while operational, after SUSPEND
)
func (d *dcd) state() dcdState { return dcdState(d.st.Get()) }
func (d *dcd) setState(state dcdState) (ok bool) {
curr := d.state()
switch state {
case dcdStateNotReady:
ok = true
case dcdStateDefault:
ok = curr == dcdStateNotReady || curr == dcdStateDefault
case dcdStateAddressed:
ok = curr == dcdStateDefault
case dcdStateConfigured:
ok = curr == dcdStateAddressed || curr == dcdStateConfigured || curr == dcdStateSuspended
case dcdStateSuspended:
ok = curr == dcdStateAddressed || curr == dcdStateConfigured || curr == dcdStateSuspended
default:
ok = false
}
if ok {
d.st.Set(uint8(state))
}
return
}
// dcdEvent is used to describe virtual interrupts on the USB bus to a device
// controller.
//
@@ -132,47 +191,85 @@ type dcdEvent struct {
// Enumerated constants for all possible USB device controller interrupt codes.
const (
dcdEventInvalid uint8 = iota // Invalid interrupt
dcdEventStatusReset // USB reset received
dcdEventStatusRun // USB controller entered run state
dcdEventStatusSuspend // USB suspend received
dcdEventStatusError // USB error condition detected on bus
dcdEventControlSetup // USB setup received
dcdEventPeripheralReady // USB PHY powered and ready to _go_
dcdEventTransactComplete // USB transaction complete
dcdEventTimer // USB (system) timer
dcdEventInvalid uint8 = iota // Invalid interrupt
dcdEventStatusReset // USB RESET received
dcdEventStatusResume // USB RESUME condition
dcdEventStatusSuspend // USB SUSPEND received
dcdEventStatusError // USB error condition detected on bus
dcdEventDeviceReady // USB PHY powered and ready to _go_
dcdEventDeviceAddress // USB device SET_ADDRESS complete
dcdEventDeviceConfiguration // USB device SET_CONFIGURATION complete
dcdEventControlSetup // USB SETUP received
dcdEventControlComplete // USB control request complete
dcdEventTransferComplete // USB data transfer complete
dcdEventTimer // USB (system) timer
)
func (d *dcd) event(ev dcdEvent) {
switch ev.id {
case dcdEventInvalid:
case dcdEventStatusReset:
d.endpointMask = 0
d.setState(dcdStateNotReady)
case dcdEventPeripheralReady:
// Configure and enable control endpoint 0
d.endpointEnable(0, true, 0)
case dcdEventStatusResume:
d.setState(dcdStateConfigured)
case dcdEventStatusRun:
case dcdEventStatusSuspend:
case dcdEventStatusError:
case dcdEventControlSetup:
// On control endpoint 0 setup events, the ev.setup field will be defined
d.stage = d.controlSetup(ev.setup)
switch d.stage {
case dcdStageSetup:
case dcdStageDataIn:
case dcdStageDataOut:
case dcdStageStatusIn:
case dcdStageStatusOut:
case dcdStageStall:
d.controlStall()
d.setState(dcdStateSuspended)
case dcdEventDeviceReady:
if d.setState(dcdStateDefault) {
// Configure and enable control endpoint 0
d.endpointEnable(0, true, 0)
}
case dcdEventTransactComplete:
case dcdEventTimer:
case dcdEventDeviceAddress:
// -- ** IMPORTANT ** --
// dcdEventDeviceAddress must be triggered by the target driver, because
// different MCUs require setting the device address at different times
// during the enumeration process.
d.setState(dcdStateAddressed)
case dcdEventDeviceConfiguration:
d.setState(dcdStateConfigured)
case dcdEventControlSetup:
// On control endpoint 0 setup events, the ev.setup field will be defined.
// We overwrite the receiver's setup field, leaving it unmodified throughout
// all transactions of a control transfer. It is only cleared once the
// completion event dcdEventControlComplete has been called and finished
// processing, or if its initial processing fails due to error.
d.setup = ev.setup
d.stage = d.controlSetup(ev.setup)
switch d.stage {
case dcdStageDataIn, dcdStageDataOut:
// TBD: control endpoint data transfer
case dcdStageStatusIn, dcdStageStatusOut:
// TBD: control endpoint status transfer
case dcdStageStall:
d.controlStall(true, ev.setup.direction())
case dcdStageSetup:
fallthrough
default:
// TBD: no stage transition occurred
}
case dcdEventControlComplete:
d.controlComplete()
// clear the active SETUP packet once the control transfer completes.
d.setup = dcdSetup{}
case dcdEventTransferComplete:
// TBD: data endpoint transfer complete
case dcdEventInvalid, dcdEventStatusError, dcdEventTimer:
fallthrough
default:
// TBD: unhandled events
}
}
@@ -192,9 +289,6 @@ const (
// controlSetup handles setup messages on control endpoint 0.
func (d *dcd) controlSetup(sup dcdSetup) dcdStage {
// Reset endpoint 0 notify mask
d.controlMask = 0
// First, switch on the type of request (standard, class, or vendor)
switch sup.bmRequestType & descRequestTypeTypeMsk {
@@ -215,7 +309,7 @@ func (d *dcd) controlSetup(sup dcdSetup) dcdStage {
case descRequestStandardSetAddress:
d.setDeviceAddress(sup.wValue)
d.controlReceive(uintptr(0), 0, false)
return dcdStageSetup
return dcdStageStatusOut
// SET CONFIGURATION (0x09):
case descRequestStandardSetConfiguration:
@@ -224,6 +318,7 @@ func (d *dcd) controlSetup(sup dcdSetup) dcdStage {
// Use default if invalid index received
d.cc.config = 1
}
d.event(dcdEvent{id: dcdEventDeviceConfiguration})
// Respond based on our device class configuration
switch d.cc.id {
@@ -244,7 +339,7 @@ func (d *dcd) controlSetup(sup dcdSetup) dcdStage {
default:
// Unhandled device class
}
return dcdStageSetup
return dcdStageStatusOut
default:
// Unhandled request
@@ -258,11 +353,10 @@ func (d *dcd) controlSetup(sup dcdSetup) dcdStage {
// GET STATUS (0x00):
case descRequestStandardGetStatus:
d.controlReply[0] = 0
d.controlReply[1] = 0
d.controlTransmit(
uintptr(unsafe.Pointer(&d.controlReply[0])), 2, false)
return dcdStageSetup
d.controlStatusBuffer([]uint8{0, 0}),
2, false)
return dcdStageDataIn
// GET DESCRIPTOR (0x06):
case descRequestStandardGetDescriptor:
@@ -273,12 +367,12 @@ func (d *dcd) controlSetup(sup dcdSetup) dcdStage {
// CDC-ACM (single)
case classDeviceCDCACM:
d.controlDescriptorCDCACM(sup)
return dcdStageSetup
return dcdStageDataIn
// HID
case classDeviceHID:
d.controlDescriptorHID(sup)
return dcdStageSetup
return dcdStageDataIn
default:
// Unhandled device class
@@ -286,10 +380,12 @@ func (d *dcd) controlSetup(sup dcdSetup) dcdStage {
// GET CONFIGURATION (0x08):
case descRequestStandardGetConfiguration:
d.controlReply[0] = uint8(d.cc.config)
d.controlTransmit(
uintptr(unsafe.Pointer(&d.controlReply[0])), 1, false)
return dcdStageSetup
d.controlStatusBuffer([]uint8{
uint8(d.cc.config),
}),
1, false)
return dcdStageDataIn
default:
// Unhandled request
@@ -310,12 +406,12 @@ func (d *dcd) controlSetup(sup dcdSetup) dcdStage {
// CDC-ACM (single)
case classDeviceCDCACM:
d.controlDescriptorCDCACM(sup)
return dcdStageSetup
return dcdStageDataIn
// HID
case classDeviceHID:
d.controlDescriptorHID(sup)
return dcdStageSetup
return dcdStageDataIn
default:
// Unhandled device class
@@ -330,7 +426,7 @@ func (d *dcd) controlSetup(sup dcdSetup) dcdStage {
// HID
case classDeviceHID:
d.controlDescriptorHID(sup)
return dcdStageSetup
return dcdStageDataIn
default:
// Unhandled device class
@@ -350,13 +446,13 @@ func (d *dcd) controlSetup(sup dcdSetup) dcdStage {
case descRequestStandardClearFeature:
d.endpointClearFeature(uint8(sup.wIndex))
d.controlReceive(uintptr(0), 0, false)
return dcdStageSetup
return dcdStageStatusOut
// SET FEATURE (0x03):
case descRequestStandardSetFeature:
d.endpointSetFeature(uint8(sup.wIndex))
d.controlReceive(uintptr(0), 0, false)
return dcdStageSetup
return dcdStageStatusOut
default:
// Unhandled request
@@ -371,11 +467,13 @@ func (d *dcd) controlSetup(sup dcdSetup) dcdStage {
// GET STATUS (0x00):
case descRequestStandardGetStatus:
status := d.endpointStatus(uint8(sup.wIndex))
d.controlReply[0] = uint8(status)
d.controlReply[1] = uint8(status >> 8)
d.controlTransmit(
uintptr(unsafe.Pointer(&d.controlReply[0])), 2, false)
return dcdStageSetup
d.controlStatusBuffer([]uint8{
uint8(status),
uint8(status >> 8),
}),
2, false)
return dcdStageDataIn
default:
// Unhandled request
@@ -407,14 +505,14 @@ func (d *dcd) controlSetup(sup dcdSetup) dcdStage {
// CDC-ACM (single)
case classDeviceCDCACM:
// line coding must contain exactly 7 bytes
if descCDCACMCodingSize == sup.wLength {
if uint16(descCDCACMCodingSize) == sup.wLength {
d.setup = sup
d.controlReceive(
uintptr(unsafe.Pointer(&descCDCACM[d.cc.config-1].cx[0])),
descCDCACMCodingSize, true)
uint32(descCDCACMCodingSize), true)
// CDC Line Coding packet receipt handling occurs in method
// controlComplete().
return dcdStageSetup
return dcdStageDataOut
}
default:
@@ -438,7 +536,7 @@ func (d *dcd) controlSetup(sup dcdSetup) dcdStage {
// DTR is bit 0 (mask 0x01), RTS is bit 1 (mask 0x02)
d.uartSetLineState(0 != sup.wValue&0x01, 0 != sup.wValue&0x02)
d.controlReceive(uintptr(0), 0, false)
return dcdStageSetup
return dcdStageStatusOut
default:
// Unhandled device interface
@@ -457,7 +555,7 @@ func (d *dcd) controlSetup(sup dcdSetup) dcdStage {
// CDC-ACM (single)
case classDeviceCDCACM:
d.controlReceive(uintptr(0), 0, false)
return dcdStageSetup
return dcdStageStatusOut
default:
// Unhandled device class
@@ -471,13 +569,13 @@ func (d *dcd) controlSetup(sup dcdSetup) dcdStage {
// HID
case classDeviceHID:
if sup.wLength <= descHIDCxSize {
if sup.wLength <= descHIDSxSize {
d.setup = sup
descHID[d.cc.config-1].cx[0] = 0xE9
d.controlReceive(
uintptr(unsafe.Pointer(&descHID[d.cc.config-1].cx[0])),
uint32(sup.wLength), true)
return dcdStageSetup
return dcdStageDataOut
}
default:
@@ -493,9 +591,11 @@ func (d *dcd) controlSetup(sup dcdSetup) dcdStage {
// HID
case classDeviceHID:
idleRate := sup.wValue >> 8
// TBD: do we need to handle this request? wIndex contains the target
// interface of the request.
_ = idleRate
d.controlReceive(uintptr(0), 0, false)
return dcdStageSetup
return dcdStageStatusOut
default:
// Unhandled device class
@@ -521,12 +621,13 @@ func (d *dcd) controlSetup(sup dcdSetup) dcdStage {
case classDeviceHID:
reportType := uint8(sup.wValue >> 8)
reportID := uint8(sup.wValue)
// TBD: do we need to handle this request? wIndex contains the target
// interface of the request.
_, _ = reportType, reportID
d.controlReply[0] = 0
d.controlReply[1] = 0
d.controlTransmit(
uintptr(unsafe.Pointer(&d.controlReply[0])), 2, false)
return dcdStageSetup
d.controlStatusBuffer([]uint8{0, 0}),
2, false)
return dcdStageDataIn
default:
// Unhandled device class
@@ -551,10 +652,7 @@ func (d *dcd) controlSetup(sup dcdSetup) dcdStage {
}
// controlComplete handles the setup completion of control endpoint 0.
func (d *dcd) controlComplete(status uint32) {
// Reset endpoint 0 notify mask
d.controlMask = 0
func (d *dcd) controlComplete() {
// First, switch on the type of request (standard, class, or vendor)
switch d.setup.bmRequestType & descRequestTypeTypeMsk {
+18 -5
View File
@@ -1,8 +1,10 @@
package usb
import "unsafe"
const descUSBSpecVersion = uint16(0x0200) // USB 2.0
const descLanguageEnglish = uint16(0x0409)
const descLanguageEnglish = uint16(0x0409) // (US) English
// USB constants defined per specification.
const (
@@ -135,6 +137,11 @@ const (
descDeviceCapExtAttrBESLPos = 2
)
const (
descDirOut = descRequestTypeDirOut >> descRequestTypeDirPos
descDirIn = descRequestTypeDirIn >> descRequestTypeDirPos
)
// device returns the enumerated device descriptor value, defined per USB
// specification, for the receiver Speed s.
func (s Speed) device() uint32 {
@@ -153,7 +160,7 @@ func (s Speed) device() uint32 {
}
const (
// Attributes of all endpoint descriptor configurations.
// Common attributes for all endpoint descriptor configurations.
descEndptConfigAttr = descConfigAttrD7Msk | // Bit 7: reserved (1)
(0 << descConfigAttrSelfPoweredPos) | // Bit 6: self-powered
(0 << descConfigAttrRemoteWakeupPos) | // Bit 5: remote wakeup
@@ -161,8 +168,8 @@ const (
descEndptConfigAttrRxPos = 0
descEndptConfigAttrTxPos = 16
descEndptConfigAttrRxMsk = (descEndptConfigAttr | descEndptAttrSyncTypeMsk) << descEndptConfigAttrRxPos
descEndptConfigAttrTxMsk = (descEndptConfigAttr | descEndptAttrSyncTypeMsk) << descEndptConfigAttrTxPos
descEndptConfigAttrRxMsk = (descEndptAttrSyncTypeMsk | descEndptConfigAttr) << descEndptConfigAttrRxPos
descEndptConfigAttrTxMsk = (descEndptAttrSyncTypeMsk | descEndptConfigAttr) << descEndptConfigAttrTxPos
descEndptConfigAttrRxUnused = 0x02 << descEndptConfigAttrRxPos
descEndptConfigAttrTxUnused = 0x02 << descEndptConfigAttrTxPos
@@ -419,8 +426,11 @@ const (
// for each string) seems a good compromise.
)
// descEndpointInvalid represents an invalid endpoint address.
const descEndpointInvalid = ^uint8(descEndptAddrNumberMsk | descEndptAddrDirectionMsk)
// descCDCACMCodingSize defines the length of a CDC-ACM UART line coding buffer.
const descCDCACMCodingSize = 7
const descCDCACMCodingSize = unsafe.Sizeof(descCDCACMLineCoding{})
// descCDCACMLineCoding represents an emulated UART's line configuration.
type descCDCACMLineCoding struct {
@@ -455,6 +465,9 @@ const (
type descCDCACMClass struct {
*descCDCACMClassData // Target-defined, class-specific data
line descCDCACMLineCoding
term struct{ dtr, rts bool }
locale *[descCDCACMLanguageCount]descStringLanguage // string descriptors
device *[descLengthDevice]uint8 // device descriptor
qualif *[descLengthQualification]uint8 // device qualification descriptor
+30 -14
View File
@@ -41,7 +41,7 @@ const (
descBankOut = 0 // descriptor bank 0 holds OUT endpoints
descBankIn = 1 // descriptor bank 1 holds IN endpoints
descControlPacketSize = 16
descControlPacketSize = 64
)
// Constants for USB CDC-ACM device classes.
@@ -64,7 +64,8 @@ const (
// | than the data payload specified by PCKSIZE.SIZE minus two, both CRC
// | data bytes are written to the data buffer.
// Thus, we need to allocate 2 extra bytes for control endpoint 0 Rx (OUT).
descCDCACMCxSize = 8 + 2
descCDCACMSxSize = 8 + 2
descCDCACMCxSize = descControlPacketSize
// CDC-ACM Data Buffers
@@ -85,7 +86,7 @@ const (
// CDC-ACM Endpoint Configurations for Full-Speed Device
descCDCACMStatusFSInterval = 5 // Status
descCDCACMStatusFSPacketSize = 16 // (full-speed)
descCDCACMStatusFSPacketSize = 64 // (full-speed)
descCDCACMDataRxFSPacketSize = 64 // Data Rx (full-speed)
descCDCACMDataTxFSPacketSize = 64 // Data Tx (full-speed)
@@ -115,7 +116,8 @@ const (
// | than the data payload specified by PCKSIZE.SIZE minus two, both CRC
// | data bytes are written to the data buffer.
// Thus, we need to allocate 2 extra bytes for control endpoint 0 Rx (OUT).
descHIDCxSize = 8 + 2
descHIDSxSize = 8 + 2
descHIDCxSize = descControlPacketSize
// HID Serial Buffers
@@ -192,10 +194,15 @@ const (
// DMA controller the buffer and transfer properties for each endpoint, for the
// default CDC-ACM (single) device class configuration (index 1).
//go:align 32
var descCDCACM0ED [descCDCACMEDCount]dhwEndptAddrDesc
var descCDCACM0ED [descCDCACMEDCount]dhwEPAddrDesc
// descCDCACM0Cx is the buffer for control/status data received on endpoint 0 of
// the default CDC-ACM (single) device class configuration (index 1).
// descCDCACM0Sx is the receive (Rx) buffer for setup packets on control endpoint
// 0 of the default CDC-ACM (single) device class configuration (index 1).
//go:align 32
var descCDCACM0Sx [descCDCACMSxSize]uint8
// descCDCACM0Cx is the transmit (Tx) buffer for control/status packets on control
// endpoint 0 of the default CDC-ACM (single) device class configuration (index 1).
//go:align 32
var descCDCACM0Cx [descCDCACMCxSize]uint8
@@ -227,9 +234,10 @@ type descCDCACMClassData struct {
// CDC-ACM Control Buffers
ed *[descCDCACMEDCount]dhwEndptAddrDesc // endpoint descriptors
ed *[descCDCACMEDCount]dhwEPAddrDesc // endpoint descriptors
cx *[descCDCACMCxSize]uint8 // control endpoint 0 Rx/Tx transfer buffer
sx *[descCDCACMSxSize]uint8 // control endpoint 0 Rx (OUT) setup packets
cx *[descCDCACMCxSize]uint8 // control endpoint 0 Tx (IN) control/status packets
dx *[descCDCACMConfigSize]uint8 // control endpoint 0 Tx (IN) descriptor transfer buffer
// CDC-ACM Data Buffers
@@ -254,6 +262,7 @@ var descCDCACMData = [dcdCount]descCDCACMClassData{
ed: &descCDCACM0ED,
sx: &descCDCACM0Sx,
cx: &descCDCACM0Cx,
dx: &descCDCACM0Dx,
@@ -272,10 +281,15 @@ var descCDCACMData = [dcdCount]descCDCACMClassData{
// DMA controller the buffer and transfer properties for each endpoint, for the
// default HID device class configuration (index 1).
//go:align 32
var descHID0ED [descHIDEDCount]dhwEndptAddrDesc
var descHID0ED [descHIDEDCount]dhwEPAddrDesc
// descHID0Cx is the buffer for control/status data received on endpoint 0 of
// the default HID device class configuration (index 1).
// descHID0Sx is the receive (Rx) buffer for setup packets on control endpoint 0
// of the default HID device class configuration (index 1).
//go:align 32
var descHID0Sx [descHIDSxSize]uint8
// descHID0Cx is the transmit (Tx) buffer for control/status packets on control
// endpoint 0 of the default CDC-ACM (single) device class configuration (index 1).
//go:align 32
var descHID0Cx [descHIDCxSize]uint8
@@ -339,9 +353,10 @@ type descHIDClassData struct {
// HID Control Buffers
ed *[descHIDEDCount]dhwEndptAddrDesc // endpoint descriptors
ed *[descHIDEDCount]dhwEPAddrDesc // endpoint descriptors
cx *[descHIDCxSize]uint8 // control endpoint 0 Rx/Tx transfer buffer
sx *[descHIDSxSize]uint8 // control endpoint 0 Rx (OUT) setup packets
cx *[descHIDCxSize]uint8 // control endpoint 0 Tx (IN) control/status packets
dx *[descHIDConfigSize]uint8 // control endpoint 0 Tx (IN) descriptor transfer buffer
// HID Serial Buffers
@@ -391,6 +406,7 @@ var descHIDData = [dcdCount]descHIDClassData{
ed: &descHID0ED,
sx: &descHID0Sx,
cx: &descHID0Cx,
dx: &descHID0Dx,
+1
View File
@@ -1,3 +1,4 @@
//go:build mimxrt1062
// +build mimxrt1062
package usb
File diff suppressed because it is too large Load Diff
+13 -4
View File
@@ -1,3 +1,4 @@
//go:build mimxrt1062
// +build mimxrt1062
package usb
@@ -236,6 +237,8 @@ func (d *dhw) interrupt() {
// wait for flush to complete
for d.bus.ENDPTFLUSH.HasBits(0x00010001) {
}
// Reset notify mask for control endpoint 0
d.controlMask = 0
// Notify device controller driver
d.event(dcdEvent{
id: dcdEventControlSetup,
@@ -248,7 +251,11 @@ func (d *dhw) interrupt() {
if 0 != completeStatus {
d.bus.ENDPTCOMPLETE.Set(completeStatus)
if 0 != completeStatus&d.controlMask {
d.controlComplete(completeStatus)
// Clear notify mask for control endpoint 0
d.controlMask = 0
// Notify device controller driver, which invokes any appropriate
// callback(s) for the current device class configuration.
d.controlComplete()
}
completeStatus &= d.endpointMask
if 0 != completeStatus {
@@ -289,6 +296,7 @@ func (d *dhw) interrupt() {
}
d.bus.ENDPTFLUSH.Set(0xFFFFFFFF)
d.event(dcdEvent{id: dcdEventStatusReset})
d.endpointMask = 0
}
// General Purpose Timer Interrupt 0(GPTINT0) - R/WC
@@ -375,6 +383,7 @@ func (d *dhw) setDeviceAddress(addr uint16) {
d.bus.DEVICEADDR.Set(nxp.USB_DEVICEADDR_USBADRA |
((uint32(addr) << nxp.USB_DEVICEADDR_USBADR_Pos) &
nxp.USB_DEVICEADDR_USBADR_Msk))
d.event(dcdEvent{id: dcdEventDeviceAddress})
}
// =============================================================================
@@ -383,8 +392,8 @@ func (d *dhw) setDeviceAddress(addr uint16) {
// controlStall stalls a transfer on control endpoint 0. To stall a transfer on
// any other endpoint, use method endpointStall().
func (d *dhw) controlStall() {
d.endpointStall(0)
func (d *dhw) controlStall(stall bool) {
d.endpointStall(0, stall)
}
// controlReceive receives (Rx, OUT) data on control endpoint 0.
@@ -554,7 +563,7 @@ func (d *dhw) endpointStatus(endpoint uint8) uint16 {
}
// endpointStall stalls a transfer on the given endpoint.
func (d *dhw) endpointStall(endpoint uint8) {
func (d *dhw) endpointStall(endpoint uint8, stall bool) {
// RXS and TXS bits at same position in all endpoint control registers.
d.endpointControlRegister(endpoint).SetBits(
nxp.USB_ENDPTCTRL0_RXS | nxp.USB_ENDPTCTRL0_TXS,
+131
View File
@@ -0,0 +1,131 @@
package usb
import (
"errors"
"runtime/volatile"
)
const QueueSize = 8
type Queue struct {
fifo [QueueSize]uint8
tail volatile.Register32
head volatile.Register32
}
var (
ErrReadBuffer = errors.New("cannot copy into read buffer")
ErrWriteBuffer = errors.New("cannot copy from write buffer")
ErrQueueEmpty = errors.New("data queue empty") // Read Error
ErrQueueFull = errors.New("data queue full") // Write error
)
// Reset discards all buffered data.
//go:inline
func (q *Queue) Reset() {
for i := range q.fifo {
q.fifo[i] = 0
}
q.tail.Set(0)
q.head.Set(0)
}
//go:inline
func (q *Queue) Len() int {
return int(q.tail.Get() - q.head.Get())
}
//go:inline
func (q *Queue) Cap() int {
return cap(q.fifo)
}
func (q *Queue) Read(data []uint8) (int, error) {
less := uint32(len(data))
if less == 0 {
return 0, ErrReadBuffer
} // nothing to copy into
head := q.head.Get()
used := q.tail.Get() - head
if used == 0 {
return 0, ErrQueueEmpty
} // empty queue
if less > used {
less = used
} // only get from used space
for i := uint32(0); i < less; i++ {
data[i] = q.fifo[head%QueueSize]
head++
}
q.head.Set(head)
return int(less), nil
}
func (q *Queue) Write(data []uint8) (int, error) {
more := uint32(len(data))
if more == 0 {
return 0, ErrWriteBuffer
} // nothing to copy from
tail := q.tail.Get()
used := tail - q.head.Get()
if used == QueueSize {
return 0, ErrQueueFull
} // full queue
if used+more > QueueSize {
more = QueueSize - used
} // only put to unused space
for i := uint32(0); i < more; i++ {
q.fifo[tail%QueueSize] = data[i]
tail++
}
q.tail.Set(tail)
return int(more), nil
}
func (q *Queue) Deq() (uint8, bool) {
tail := q.head.Get()
if tail == q.tail.Get() {
return 0, false
} // empty queue
data := q.fifo[tail%QueueSize]
q.head.Set(tail + 1)
return data, true
}
func (q *Queue) Front() (uint8, bool) {
tail := q.head.Get()
if tail == q.tail.Get() {
return 0, false
} // empty queue
return q.fifo[tail%QueueSize], true
}
func (q *Queue) Enq(data uint8) bool {
head := q.tail.Get()
if head-q.head.Get() == QueueSize {
return false
} // full queue
q.fifo[head%QueueSize] = data
q.tail.Set(head + 1)
return true
}
+9 -5
View File
@@ -37,14 +37,18 @@ func (uart *UART) Configure(config UARTConfig) error {
return nil
}
func (uart *UART) Ready() bool {
return uart.core.dc.uartReady()
}
// Buffered returns the number of bytes currently stored in the RX buffer.
func (uart UART) Buffered() int {
func (uart *UART) Buffered() int {
return uart.core.dc.uartAvailable()
}
// ReadByte reads a single byte from the RX buffer.
// If there is no data in the buffer, returns an error.
func (uart UART) ReadByte() (byte, error) {
func (uart *UART) ReadByte() (byte, error) {
n, ok := uart.core.dc.uartReadByte()
if !ok {
return 0, ErrUARTEmptyBuffer
@@ -53,12 +57,12 @@ func (uart UART) ReadByte() (byte, error) {
}
// Read from the RX buffer.
func (uart UART) Read(data []byte) (n int, err error) {
func (uart *UART) Read(data []byte) (n int, err error) {
return uart.core.dc.uartRead(data), nil
}
// WriteByte writes a single byte of data to the UART interface.
func (uart UART) WriteByte(c byte) error {
func (uart *UART) WriteByte(c byte) error {
if !uart.core.dc.uartWriteByte(c) {
return ErrUARTWriteFailed
}
@@ -66,6 +70,6 @@ func (uart UART) WriteByte(c byte) error {
}
// Write data to the UART.
func (uart UART) Write(data []byte) (n int, err error) {
func (uart *UART) Write(data []byte) (n int, err error) {
return uart.core.dc.uartWrite(data), nil
}
+27 -3
View File
@@ -216,12 +216,33 @@ func cycles(microsec, cpuFreqHz uint32) uint32 {
return uint32((uint64(microsec) * uint64(cpuFreqHz)) / 1000000)
}
//go:inline
func endpointValid(address uint8) bool {
return address&descEndpointInvalid == 0
}
//go:inline
func unpackEndpoint(address uint8) (number, direction uint8) {
return (address & descEndptAddrNumberMsk) >> descEndptAddrNumberPos,
(address & descEndptAddrDirectionMsk) >> descEndptAddrDirectionPos
}
//go:inline
func packEndpoint(number, direction uint8) (address uint8) {
return ((number << descEndptAddrNumberPos) & descEndptAddrNumberMsk) |
((direction << descEndptAddrDirectionPos) & descEndptAddrDirectionMsk)
}
//go:inline
func endpointNumber(address uint8) (number uint8) {
return (address & descEndptAddrNumberMsk) >> descEndptAddrNumberPos
}
//go:inline
func endpointDirection(address uint8) (direction uint8) {
return (address & descEndptAddrDirectionMsk) >> descEndptAddrDirectionPos
}
//go:inline
func rxEndpoint(number uint8) uint8 {
return (number & descEndptAddrNumberMsk) | descEndptAddrDirectionOut
@@ -245,20 +266,23 @@ func indexEndpoint(index uint8) uint8 {
}
// wrap computes the index into a circular buffer of length mod by walking
// forward n elements if n is positive, or reverse n elements if n is negative.
// For example, both wrap(42, 10) and wrap(-308, 10) return 2.
// forward n elements if n is positive, or reverse -n elements if n is negative.
// For example, both wrap(12, 10) and wrap(-18, 10) return 2.
//go:inline
func wrap(n, mod int) int {
if mod <= 0 || n == mod {
if mod <= 0 {
// Buffer length (mod) must be positive.
return 0
}
if n < 0 {
if -n < mod {
// Do not wrap around (no underflow).
return mod + n
}
return mod - (-n % mod)
}
if n < mod {
// Do not wrap around (no overflow).
return n
}
return n % mod
+3 -3
View File
@@ -7,6 +7,7 @@ import (
"device/arm"
"device/sam"
"machine"
"machine/usb"
"runtime/interrupt"
"runtime/volatile"
)
@@ -25,13 +26,12 @@ func init() {
initClocks()
initRTC()
initSERCOMClocks()
initUSBClock()
initADCClock()
// connect to USB CDC interface
machine.Serial.Configure(machine.UARTConfig{})
machine.Serial.Configure(usb.UARTConfig{})
if !machine.USB.Configured() {
machine.USB.Configure(machine.UARTConfig{})
machine.USB.Configure(usb.UARTConfig{})
}
}