Skip to content

Commit 69aaea4

Browse files
deadprogramaykevl
authored andcommitted
machine/atsamd21: Add support for bootloader reset/programming and correct error in receiving endpoint 0 data for CDC Set Line Coding changes, implementing system reset on switch to 1200 baud connection speed with DTR false.
Signed-off-by: Ron Evans <[email protected]>
1 parent 6c1abfe commit 69aaea4

File tree

2 files changed

+45
-39
lines changed

2 files changed

+45
-39
lines changed

src/device/arm/arm.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,4 +164,8 @@ func SystemReset() {
164164
// SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) |
165165
// SCB_AIRCR_SYSRESETREQ_Msk);
166166
SCB.AIRCR.Set((0x5FA << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_SYSRESETREQ_Msk)
167+
168+
for {
169+
Asm("wfi")
170+
}
167171
}

src/machine/machine_atsamd21.go

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1401,15 +1401,15 @@ func handleUSB() {
14011401
for i = 1; i < uint32(len(endPoints)); i++ {
14021402
// Check if endpoint has a pending interrupt
14031403
epFlags := getEPINTFLAG(i)
1404-
if epFlags > 0 {
1404+
if (epFlags&sam.USB_DEVICE_EPINTFLAG_TRCPT0) > 0 ||
1405+
(epFlags&sam.USB_DEVICE_EPINTFLAG_TRCPT1) > 0 {
14051406
switch i {
14061407
case usb_CDC_ENDPOINT_OUT:
1407-
if (epFlags & sam.USB_DEVICE_EPINTFLAG_TRCPT0) > 0 {
1408-
handleEndpoint(i)
1409-
}
1410-
setEPINTFLAG(i, epFlags)
1411-
case usb_CDC_ENDPOINT_ACM:
1408+
handleEndpoint(i)
14121409
setEPINTFLAG(i, epFlags)
1410+
case usb_CDC_ENDPOINT_IN, usb_CDC_ENDPOINT_ACM:
1411+
setEPSTATUSCLR(i, sam.USB_DEVICE_EPSTATUSCLR_BK1RDY)
1412+
setEPINTFLAG(i, sam.USB_DEVICE_EPINTFLAG_TRCPT1)
14131413
}
14141414
}
14151415
}
@@ -1631,17 +1631,19 @@ func cdcSetup(setup usbSetup) bool {
16311631

16321632
if setup.bRequest == usb_CDC_SET_LINE_CODING || setup.bRequest == usb_CDC_SET_CONTROL_LINE_STATE {
16331633
// auto-reset into the bootloader
1634-
if usbLineInfo.dwDTERate == 1200 && (usbLineInfo.lineState&0x01) == 0 {
1635-
// TODO: system reset
1634+
if usbLineInfo.dwDTERate == 1200 && usbLineInfo.lineState&usb_CDC_LINESTATE_DTR == 0 {
1635+
ResetProcessor()
16361636
} else {
16371637
// TODO: cancel any reset
16381638
}
1639+
sendZlp(0)
16391640
}
16401641

16411642
if setup.bRequest == usb_CDC_SEND_BREAK {
16421643
// TODO: something with this value?
16431644
// breakValue = ((uint16_t)setup.wValueH << 8) | setup.wValueL;
16441645
// return false;
1646+
sendZlp(0)
16451647
}
16461648
return true
16471649
}
@@ -1662,53 +1664,41 @@ func sendUSBPacket(ep uint32, data []byte) {
16621664
}
16631665

16641666
func receiveUSBControlPacket() []byte {
1665-
// set ready to receive data
1666-
setEPSTATUSCLR(0, sam.USB_DEVICE_EPSTATUSCLR_BK0RDY)
1667-
1668-
// read the data
1669-
bytesread := armRecvCtrlOUT(0)
1670-
1671-
// return the data
1672-
data := make([]byte, 0, bytesread)
1673-
copy(data, udd_ep_out_cache_buffer[0][:bytesread])
1674-
return data
1675-
}
1676-
1677-
func armRecvCtrlOUT(ep uint32) uint32 {
1678-
// Set output address to receive data
1679-
usbEndpointDescriptors[ep].DeviceDescBank[0].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[ep]))))
1667+
// address
1668+
usbEndpointDescriptors[0].DeviceDescBank[0].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[0]))))
16801669

1681-
// set multi-packet size which is total expected number of bytes to receive.
1682-
usbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.SetBits((8 << usb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Pos) |
1683-
uint32(epPacketSize(64)<<usb_DEVICE_PCKSIZE_SIZE_Pos))
1684-
1685-
// clear byte count of bytes received so far.
1686-
usbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)
1670+
// set byte count to zero
1671+
usbEndpointDescriptors[0].DeviceDescBank[0].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)
16871672

1688-
// clear ready state to start transfer
1689-
setEPSTATUSCLR(ep, sam.USB_DEVICE_EPSTATUSCLR_BK0RDY)
1673+
// set ready for next data
1674+
setEPSTATUSCLR(0, sam.USB_DEVICE_EPSTATUSCLR_BK0RDY)
16901675

16911676
// Wait until OUT transfer is ready.
16921677
timeout := 3000
1693-
for (getEPSTATUS(ep) & sam.USB_DEVICE_EPSTATUS_BK0RDY) == 0 {
1678+
for (getEPSTATUS(0) & sam.USB_DEVICE_EPSTATUS_BK0RDY) == 0 {
16941679
timeout--
16951680
if timeout == 0 {
1696-
return 0
1681+
return []byte{}
16971682
}
16981683
}
16991684

17001685
// Wait until OUT transfer is completed.
1701-
timeout = 3000
1702-
for (getEPINTFLAG(ep) & sam.USB_DEVICE_EPINTFLAG_TRCPT0) == 0 {
1686+
timeout = 300000
1687+
for (getEPINTFLAG(0) & sam.USB_DEVICE_EPINTFLAG_TRCPT0) == 0 {
17031688
timeout--
17041689
if timeout == 0 {
1705-
return 0
1690+
return []byte{}
17061691
}
17071692
}
17081693

1709-
// return number of bytes received
1710-
return (usbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.Get() >>
1711-
usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos) & usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask
1694+
// get data
1695+
bytesread := uint32((usbEndpointDescriptors[0].DeviceDescBank[0].PCKSIZE.Get() >>
1696+
usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos) & usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask)
1697+
1698+
data := make([]byte, bytesread)
1699+
copy(data, udd_ep_out_cache_buffer[0][:])
1700+
1701+
return data
17121702
}
17131703

17141704
// sendDescriptor creates and sends the various USB descriptor types that
@@ -2083,3 +2073,15 @@ func setEPINTENSET(ep uint32, val uint8) {
20832073
return
20842074
}
20852075
}
2076+
2077+
// ResetProcessor should perform a system reset in preperation
2078+
// to switch to the bootloader to flash new firmware.
2079+
func ResetProcessor() {
2080+
arm.DisableInterrupts()
2081+
2082+
// Perform magic reset into bootloader, as mentioned in
2083+
// https://github.com/arduino/ArduinoCore-samd/issues/197
2084+
*(*uint32)(unsafe.Pointer(uintptr(0x20007FFC))) = 0x07738135
2085+
2086+
arm.SystemReset()
2087+
}

0 commit comments

Comments
 (0)