Skip to content

Commit b37f0e2

Browse files
committed
Saving work on USB
1 parent 3eee51d commit b37f0e2

File tree

10 files changed

+1451
-405
lines changed

10 files changed

+1451
-405
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ src/device/nrf/*.go
77
src/device/nrf/*.s
88
src/device/nxp/*.go
99
src/device/nxp/*.s
10+
!src/device/nxp/nxp.go
1011
src/device/sam/*.go
1112
src/device/sam/*.s
1213
src/device/sifive/*.go

src/device/nxp/nxp.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Derivative work of Teensyduino Core Library
2+
// http://www.pjrc.com/teensy/
3+
// Copyright (c) 2017 PJRC.COM, LLC.
4+
//
5+
// Permission is hereby granted, free of charge, to any person obtaining
6+
// a copy of this software and associated documentation files (the
7+
// "Software"), to deal in the Software without restriction, including
8+
// without limitation the rights to use, copy, modify, merge, publish,
9+
// distribute, sublicense, and/or sell copies of the Software, and to
10+
// permit persons to whom the Software is furnished to do so, subject to
11+
// the following conditions:
12+
//
13+
// 1. The above copyright notice and this permission notice shall be
14+
// included in all copies or substantial portions of the Software.
15+
//
16+
// 2. If the Software is incorporated into a build system that allows
17+
// selection among a list of target devices, then similar target
18+
// devices manufactured by PJRC.COM must be included in the list of
19+
// target devices and selectable in the same manner.
20+
//
21+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24+
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
25+
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
26+
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27+
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28+
// SOFTWARE.
29+
30+
// +build nxp
31+
32+
package nxp
33+
34+
const (
35+
_SMC_PMCTRL_RUN = 0 << SMC_PMCTRL_RUNM_Pos
36+
_SMC_PMCTRL_HSRUN = 3 << SMC_PMCTRL_RUNM_Pos
37+
_SMC_PMSTAT_RUN = 0x01 << SMC_PMSTAT_PMSTAT_Pos
38+
_SMC_PMSTAT_HSRUN = 0x80 << SMC_PMSTAT_PMSTAT_Pos
39+
)
40+
41+
func KinetisHSRunDisable() bool {
42+
// from: kinetis_hsrun_disable
43+
44+
if SMC.PMSTAT.Get() != _SMC_PMSTAT_HSRUN {
45+
return false
46+
}
47+
48+
// First, reduce the CPU clock speed, but do not change
49+
// the peripheral speed (F_BUS). Serial1 & Serial2 baud
50+
// rates will be impacted, but most other peripherals
51+
// will continue functioning at the same speed.
52+
SIM.CLKDIV1.Set((2 << SIM_CLKDIV1_OUTDIV1_Pos) | (2 << SIM_CLKDIV1_OUTDIV2_Pos) | (2 << SIM_CLKDIV1_OUTDIV1_Pos) | (8 << SIM_CLKDIV1_OUTDIV4_Pos))
53+
54+
// Then turn off HSRUN mode
55+
SMC.PMCTRL.Set(_SMC_PMCTRL_RUN)
56+
57+
// Wait for HSRUN to end
58+
for SMC.PMSTAT.Get() == _SMC_PMSTAT_HSRUN {
59+
}
60+
61+
return false
62+
}
63+
64+
func KinetisHSRunEnable() bool {
65+
// from: kinetis_hsrun_enable
66+
67+
if SMC.PMSTAT.Get() != _SMC_PMSTAT_RUN {
68+
return false
69+
}
70+
71+
// Turn HSRUN mode on
72+
SMC.PMCTRL.Set(_SMC_PMCTRL_HSRUN)
73+
74+
// Wait for HSRUN to start
75+
for SMC.PMSTAT.Get() != _SMC_PMSTAT_HSRUN {
76+
}
77+
78+
// Then configure clock for full speed
79+
SIM.CLKDIV1.Set((0 << SIM_CLKDIV1_OUTDIV1_Pos) | (2 << SIM_CLKDIV1_OUTDIV2_Pos) | (0 << SIM_CLKDIV1_OUTDIV1_Pos) | (6 << SIM_CLKDIV1_OUTDIV4_Pos))
80+
81+
return true
82+
}

src/machine/board_teensy36.go

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,21 @@
22

33
package 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)
621
func CPUFrequency() uint32 { return 180000000 }
722

@@ -11,6 +26,37 @@ func ClockFrequency() uint32 { return 16000000 }
1126
// LED on the Teensy
1227
const 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+
}

src/machine/machine_nxpmk66f18.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,3 +284,17 @@ func (p FastPin) Clear() { p.PCOR.Set(true) }
284284
func (p FastPin) Toggle() { p.PTOR.Set(true) }
285285
func (p FastPin) Write(v bool) { p.PDOR.Set(v) }
286286
func (p FastPin) Read() bool { return p.PDIR.Get() }
287+
288+
// SysTick is configured in runtime_nxpmk66f18.go
289+
290+
// number of systick irqs (milliseconds) since boot
291+
var systickCount volatile.Register32
292+
293+
//go:export SysTick_Handler
294+
func tick() {
295+
systickCount.Set(systickCount.Get() + 1)
296+
}
297+
298+
func MillisSinceBoot() uint32 {
299+
return systickCount.Get()
300+
}

0 commit comments

Comments
 (0)