22
33package machine
44
5+ import (
6+ "device/arm"
7+ "device/nxp"
8+ "runtime/volatile"
9+ "strconv"
10+ "sync/atomic"
11+ "unsafe"
12+ )
13+
14+ // F_CPU = 180 MHz
15+ // F_PLL = 180 MHz
16+ // F_BUS = 60 MHz
17+ // clock = 16 MHz
18+ // F_MEM = 25714286 Hz
19+
520// CPUFrequency returns the frequency of the ARM core clock (180MHz)
621func CPUFrequency () uint32 { return 180000000 }
722
@@ -11,6 +26,37 @@ func ClockFrequency() uint32 { return 16000000 }
1126// LED on the Teensy
1227const LED = PC05
1328
29+ const (
30+ usb_STRING_MANUFACTURER = "Teensy"
31+ usb_STRING_PRODUCT = "Teensy 3.6 USB Serial"
32+
33+ usb_DEVICE_CLASS = 0x02
34+ usb_DEVICE_SUBCLASS = 0
35+ usb_DEVICE_PROTOCOL = 0
36+
37+ usb_EP0_SIZE = 64
38+ usb_BUFFER_SIZE = usb_EP0_SIZE
39+
40+ usb_VID = 0x16C0
41+ usb_PID = 0x0483 // teensy usb serial
42+ usb_BCD_DEVICE = 0x0277 // teensy 3.6
43+
44+ // rev should appear as 0x0277
45+
46+ usb_InterfaceID_CDC_Status = 0
47+ usb_InterfaceID_CDC_Data = 1
48+ usb_InterfaceCount = 2
49+
50+ usb_EndpointID_CDC_ACM = 2
51+ usb_EndpointID_CDC_RX = 3
52+ usb_EndpointID_CDC_TX = 4
53+ usb_EndpointCount_CDC_Status = 1
54+ usb_EndpointCount_CDC_Data = 2
55+ usb_EndpointCount = 4
56+ )
57+
58+ var usb_STRING_SERIAL string
59+
1460// Port E is unavailable pending resolution of
1561// https://github.com/tinygo-org/tinygo/issues/1190
1662
@@ -105,3 +151,189 @@ const (
105151 defaultUART4TX = NoPin // D33
106152)
107153
154+ func EnterBootloader () {
155+ arm .Asm ("bkpt" )
156+ }
157+
158+ //go:linkname sleepTicks runtime.sleepTicks
159+ func sleepTicks (int64 )
160+
161+ var initted int32
162+
163+ func init () {
164+ atomic .StoreInt32 (& initted , 0 )
165+ }
166+
167+ func InitPlatform () {
168+ if ! atomic .CompareAndSwapInt32 (& initted , 0 , 1 ) {
169+ return
170+ }
171+
172+ // for background about this startup delay, please see these conversations
173+ // https://forum.pjrc.com/threads/36606-startup-time-(400ms)?p=113980&viewfull=1#post113980
174+ // https://forum.pjrc.com/threads/31290-Teensey-3-2-Teensey-Loader-1-24-Issues?p=87273&viewfull=1#post87273
175+ const millis = 1000
176+ sleepTicks (25 * millis ) // 50 for TeensyDuino < 142
177+ usb_STRING_SERIAL = readSerialNumber ()
178+ setupUSB ()
179+ sleepTicks (275 * millis ) // 350 for TeensyDuino < 142
180+ }
181+
182+ func getUSBDescriptor (value , index uint16 ) ([]byte , bool ) {
183+ // from: usb_desc.c, usb_desc.h
184+
185+ if value == 0x0100 && index == 0x0000 {
186+ return NewDeviceDescriptor (
187+ usb_DEVICE_CLASS , usb_DEVICE_SUBCLASS , usb_DEVICE_PROTOCOL ,
188+ usb_EP0_SIZE ,
189+ usb_VID , usb_PID , usb_BCD_DEVICE ,
190+ usb_IMANUFACTURER , usb_IPRODUCT , usb_ISERIAL ,
191+ 1 ,
192+ ).Bytes (), true
193+ }
194+
195+ if value == 0x0200 && index == 0x0000 {
196+ const cdcACMSize = 16
197+ const cdcRXSize = 64
198+ const cdcTXSize = 64
199+
200+ b := []byte {
201+ configDescriptorSize , // bLength
202+ usb_CONFIGURATION_DESCRIPTOR_TYPE , // bDescriptorType
203+ 0 , // wTotalLength LSB
204+ 0 , // MSB
205+ usb_InterfaceCount , // bNumInterfaces
206+ 1 , // bConfigurationValue
207+ 0 , // iConfiguration
208+ 0xC0 , // bmAttributes
209+ 50 , // bMaxPower
210+
211+ // Interface Descriptor, USB spec 9.6.5, page 267-269, Table 9-12
212+ interfaceDescriptorSize , // bLength
213+ usb_INTERFACE_DESCRIPTOR_TYPE , // bDescriptorType
214+ usb_InterfaceID_CDC_Status , // bInterfaceNumber
215+ 0 , // bAlternateSetting
216+ usb_EndpointCount_CDC_Status , // bNumEndpoints
217+ usb_CDC_COMMUNICATION_INTERFACE_CLASS , // bInterfaceClass
218+ usb_CDC_ABSTRACT_CONTROL_MODEL , // bInterfaceSubClass
219+ 0x01 , // bInterfaceProtocol
220+ 0 , // iInterface
221+
222+ // CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26
223+ 5 , // bFunctionLength
224+ 0x24 , // bDescriptorType
225+ 0x00 , // bDescriptorSubtype
226+ 0x10 , 0x01 , // bcdCDC
227+
228+ // Call Management Functional Descriptor, CDC Spec 5.2.3.2, Table 27
229+ 5 , // bFunctionLength
230+ 0x24 , // bDescriptorType
231+ 0x01 , // bDescriptorSubtype
232+ 0x01 , // bmCapabilities
233+ 1 , // bDataInterface
234+
235+ // Abstract Control Management Functional Descriptor, CDC Spec 5.2.3.3, Table 28
236+ 4 , // bFunctionLength
237+ 0x24 , // bDescriptorType
238+ 0x02 , // bDescriptorSubtype
239+ 0x06 , // bmCapabilities
240+
241+ // Union Functional Descriptor, CDC Spec 5.2.3.8, Table 33
242+ 5 , // bFunctionLength
243+ 0x24 , // bDescriptorType
244+ 0x06 , // bDescriptorSubtype
245+ usb_InterfaceID_CDC_Status , // bMasterInterface
246+ usb_InterfaceID_CDC_Data , // bSlaveInterface0
247+
248+ // Endpoint Descriptor, USB spec 9.6.6, page 269-271, Table 9-13
249+ endpointDescriptorSize , // bLength
250+ usb_ENDPOINT_DESCRIPTOR_TYPE , // bDescriptorType
251+ usb_EndpointID_CDC_ACM | 0x80 , // bEndpointAddress
252+ 0x03 , // bmAttributes (0x03=intr)
253+ cdcACMSize , // wMaxPacketSize LSB
254+ 0 , // MSB
255+ 64 , // bInterval
256+
257+ // Interface Descriptor, USB spec 9.6.5, page 267-269, Table 9-12
258+ interfaceDescriptorSize , // bLength
259+ usb_INTERFACE_DESCRIPTOR_TYPE , // bDescriptorType
260+ usb_InterfaceID_CDC_Data , // bInterfaceNumber
261+ 0 , // bAlternateSetting
262+ usb_EndpointCount_CDC_Data , // bNumEndpoints
263+ usb_CDC_DATA_INTERFACE_CLASS , // bInterfaceClass
264+ 0x00 , // bInterfaceSubClass
265+ 0x00 , // bInterfaceProtocol
266+ 0 , // iInterface
267+
268+ // Endpoint Descriptor, USB spec 9.6.6, page 269-271, Table 9-13
269+ endpointDescriptorSize , // bLength
270+ usb_ENDPOINT_DESCRIPTOR_TYPE , // bDescriptorType
271+ usb_EndpointID_CDC_RX , // bEndpointAddress
272+ 0x02 , // bmAttributes (0x02=bulk)
273+ cdcRXSize , // wMaxPacketSize LSB
274+ 0 , // MSB
275+ 0 , // bInterval
276+
277+ // Endpoint Descriptor, USB spec 9.6.6, page 269-271, Table 9-13
278+ endpointDescriptorSize , // bLength
279+ usb_ENDPOINT_DESCRIPTOR_TYPE , // bDescriptorType
280+ usb_EndpointID_CDC_TX | 0x80 , // bEndpointAddress
281+ 0x02 , // bmAttributes (0x02=bulk)
282+ cdcTXSize , // wMaxPacketSize LSB
283+ 0 , // MSB
284+ 0 , // bInterval
285+ }
286+
287+ b [2 ] = byte (len (b )) // wTotalLength LSB
288+ b [3 ] = byte (len (b ) >> 8 ) // MSB
289+ return b , true
290+ }
291+
292+ if value == 0x0300 && index == 0x0000 {
293+ return []byte {4 , 3 , 0x04 , 0x09 }, true
294+ }
295+
296+ if value == 0x0301 && index == 0x0409 {
297+ return newStringDescriptor (usb_STRING_MANUFACTURER ), true
298+ }
299+
300+ if value == 0x0302 && index == 0x0409 {
301+ return newStringDescriptor (usb_STRING_PRODUCT ), true
302+ }
303+
304+ if value == 0x0303 && index == 0x0409 {
305+ return newStringDescriptor (usb_STRING_SERIAL ), true
306+ }
307+
308+ return nil , false
309+ }
310+
311+ var usbEndpointConfigTable = [usb_EndpointCount ]uint8 {
312+ 0 : 0 ,
313+ 1 : nxp .USB0_ENDPT_EPCTLDIS | nxp .USB0_ENDPT_EPTXEN | nxp .USB0_ENDPT_EPHSHK ,
314+ 2 : nxp .USB0_ENDPT_EPCTLDIS | nxp .USB0_ENDPT_EPRXEN | nxp .USB0_ENDPT_EPHSHK ,
315+ 3 : nxp .USB0_ENDPT_EPCTLDIS | nxp .USB0_ENDPT_EPTXEN | nxp .USB0_ENDPT_EPHSHK ,
316+ }
317+
318+ func readSerialNumber () string {
319+ // from: usb_init_serialnumber
320+
321+ flags := arm .DisableInterrupts ()
322+ nxp .KinetisHSRunDisable ()
323+ nxp .FTFE .FSTAT .Set (nxp .FTFE_FSTAT_RDCOLERR | nxp .FTFE_FSTAT_ACCERR | nxp .FTFE_FSTAT_FPVIOL )
324+ ((* volatile .Register32 )(unsafe .Pointer (& nxp .FTFE .FCCOB3 ))).Set (0x41070000 )
325+ nxp .FTFE .FSTAT .Set (nxp .FTFE_FSTAT_CCIF )
326+ for ! nxp .FTFE .FSTAT .HasBits (nxp .FTFE_FSTAT_CCIF ) {
327+ } // wait
328+ num := ((* volatile .Register32 )(unsafe .Pointer (& nxp .FTFE .FCCOBB ))).Get ()
329+ nxp .KinetisHSRunEnable ()
330+ arm .EnableInterrupts (flags )
331+
332+ // add extra zero to work around OS-X CDC-ACM driver bug
333+ if num < 10000000 {
334+ num *= 10
335+ }
336+
337+ // can't allocate during startup
338+ return strconv .FormatInt (int64 (num ), 10 )
339+ }
0 commit comments