teensy40: refactor to remove unnecessary code and constants

This commit is contained in:
ardnew
2020-10-31 21:02:27 -05:00
committed by Ron Evans
parent 47410a4b54
commit 19a0270303
9 changed files with 581 additions and 831 deletions
+66 -77
View File
@@ -2,11 +2,6 @@
package machine
const (
NUM_DIGITAL_IO_PINS = 40
NUM_ANALOG_IO_PINS = 14
)
// Digital pins
const (
// = Pin // [Pad]: Alt Func 0 Alt Func 1 Alt Func 2 Alt Func 3 Alt Func 4 Alt Func 5 Alt Func 6 Alt Func 7 Alt Func 8 Alt Func 9
@@ -55,57 +50,53 @@ const (
// Analog pins
const (
// = Pin // Dig | [Pad] {Ch}
A0 = PA18 // D14 | [AD_B1_02] {7}
A1 = PA19 // D15 | [AD_B1_03] {8}
A2 = PA23 // D16 | [AD_B1_07] {12}
A3 = PA22 // D17 | [AD_B1_06] {11}
A4 = PA17 // D18 | [AD_B1_01] {6}
A5 = PA16 // D19 | [AD_B1_00] {5}
A6 = PA26 // D20 | [AD_B1_10] {15}
A7 = PA27 // D21 | [AD_B1_11] {0}
A8 = PA24 // D22 | [AD_B1_08] {13}
A9 = PA25 // D23 | [AD_B1_09] {14}
A10 = PA12 // D24 | [AD_B0_12] {1}
A11 = PA13 // D25 | [AD_B0_13] {2}
A12 = PA30 // D26 | [AD_B1_14] {128+3}
A13 = PA31 // D27 | [AD_B1_15] {128+4}
// = Pin // Dig | [Pad] {ADC1/ADC2}
A0 = PA18 // D14 | [AD_B1_02] { 7 / 7 }
A1 = PA19 // D15 | [AD_B1_03] { 8 / 8 }
A2 = PA23 // D16 | [AD_B1_07] { 12 / 12 }
A3 = PA22 // D17 | [AD_B1_06] { 11 / 11 }
A4 = PA17 // D18 | [AD_B1_01] { 6 / 6 }
A5 = PA16 // D19 | [AD_B1_00] { 5 / 5 }
A6 = PA26 // D20 | [AD_B1_10] { 15 / 15 }
A7 = PA27 // D21 | [AD_B1_11] { 0 / 0 }
A8 = PA24 // D22 | [AD_B1_08] { 13 / 13 }
A9 = PA25 // D23 | [AD_B1_09] { 14 / 14 }
A10 = PA12 // D24 | [AD_B0_12] { 1 / - }
A11 = PA13 // D25 | [AD_B0_13] { 2 / - }
A12 = PA30 // D26 | [AD_B1_14] { - / 3 }
A13 = PA31 // D27 | [AD_B1_15] { - / 4 }
)
func init() {
initLED()
initUART()
initSPI()
initI2C()
}
// -- LEDs ---------------------------------------------------------------------
// Default peripheral pins
const (
NUM_BOARD_LED = 1
LED = D13
LED_BUILTIN = D13
LED = LED_BUILTIN
UART_RX_PIN = UART1_RX_PIN // D0
UART_TX_PIN = UART1_TX_PIN // D1
SPI_SDI_PIN = SPI1_SDI_PIN // D12
SPI_SDO_PIN = SPI1_SDO_PIN // D11
SPI_SCK_PIN = SPI1_SCK_PIN // D13
SPI_CS_PIN = SPI1_CS_PIN // D10
I2C_SDA_PIN = I2C1_SDA_PIN // D18/A4
I2C_SCL_PIN = I2C1_SCL_PIN // D19/A5
)
func initLED() {}
// -- UART ---------------------------------------------------------------------
// #=====================================================#
// | UART |
// #===========#===========#=============#===============#
// | Interface | Hardware | Clock(Freq) | RX/TX : Alt |
// #===========#===========#=============#=========-=====#
// | UART1 | LPUART6 | OSC(24 MHz) | D0/D1 : 2/2 |
// | UART2 | LPUART4 | OSC(24 MHz) | D7/D8 : 2/2 |
// | UART3 | LPUART2 | OSC(24 MHz) | D15/D14 : 2/2 |
// | UART4 | LPUART3 | OSC(24 MHz) | D16/D17 : 2/2 |
// | UART5 | LPUART8 | OSC(24 MHz) | D21/D20 : 2/2 |
// | UART6 | LPUART1 | OSC(24 MHz) | D25/D24 : 2/2 |
// | UART7 | LPUART7 | OSC(24 MHz) | D28/D29 : 2/2 |
// #===========#===========#=============#=========-=====#
const (
// #===========#===========#=============#===========#=============#
// | Interface | Hardware | Clock(Freq) | RX/TX Pin | RX/TX AltFn |
// #===========#===========#=============#===========#=============#
// | UART1 | LPUART6 | OSC(24 MHz) | D0/D1 | 2/2 |
// | UART2 | LPUART4 | OSC(24 MHz) | D7/D8 | 2/2 |
// | UART3 | LPUART2 | OSC(24 MHz) | D15/D14 | 2/2 |
// | UART4 | LPUART3 | OSC(24 MHz) | D16/D17 | 2/2 |
// | UART5 | LPUART8 | OSC(24 MHz) | D21/D20 | 2/2 |
// | UART6 | LPUART1 | OSC(24 MHz) | D25/D24 | 2/2 |
// | UART7 | LPUART7 | OSC(24 MHz) | D28/D29 | 2/2 |
// #===========#===========#=============#===========#=============#
NUM_UART_INTERFACES = 7
UART1_RX_PIN = D0
UART1_TX_PIN = D1
@@ -126,25 +117,18 @@ const (
UART7_RX_PIN = D28
UART7_TX_PIN = D29
UART_RX_PIN = UART1_RX_PIN
UART_TX_PIN = UART1_TX_PIN
)
func initUART() {}
// -- SPI ----------------------------------------------------------------------
// #==================================================================#
// | SPI |
// #===========#==========#===============#===========================#
// | Interface | Hardware | Clock(Freq) | SDI/SDO/SCK/CS : Alt |
// #===========#==========#===============#=================-=========#
// | SPI1 | LPSPI4 | PLL2(132 MHz) | D12/D11/D13/D10 : 3/3/3/3 |
// | SPI2 | LPSPI3 | PLL2(132 MHz) | D1/D26/D27/D0 : 7/2/2/7 |
// | SPI3 | LPSPI1 | PLL2(132 MHz) | D34/D35/D37/D36 : 4/4/4/4 |
// #===========#==========#===============#=================-=========#
const (
// #===========#==========#===================#===========================#
// | Interface | Hardware | Clock(Freq) | SDI/SDO/SCK/CS : Alt |
// #===========#==========#===================#=================-=========#
// | SPI1 | LPSPI4 | PLL3PFD1(130 MHz) | D12/D11/D13/D10 : 3/3/3/3 |
// | SPI2 | LPSPI3 | PLL3PFD1(130 MHz) | D1/D26/D27/D0 : 7/2/2/7 |
// | SPI3 | LPSPI1 | PLL3PFD1(130 MHz) | D34/D35/D37/D36 : 4/4/4/4 |
// #===========#==========#===================#=================-=========#
NUM_SPI_INTERFACES = 3
SPI1_SDI_PIN = D12
SPI1_SDO_PIN = D11
SPI1_SCK_PIN = D13
@@ -159,19 +143,24 @@ const (
SPI3_SDO_PIN = D35
SPI3_SCK_PIN = D37
SPI3_CS_PIN = D36
SPI_SDI_PIN = SPI1_SDI_PIN
SPI_SDO_PIN = SPI1_SDO_PIN
SPI_SCK_PIN = SPI1_SCK_PIN
SPI_CS_PIN = SPI1_CS_PIN
)
func initSPI() {}
// -- I2C ----------------------------------------------------------------------
// #====================================================#
// | I2C |
// #===========#==========#=============#===============#
// | Interface | Hardware | Clock(Freq) | SDA/SCL : Alt |
// #===========#==========#=============#=========-=====#
// | I2C1 | LPI2C1 | OSC(24 MHz) | D18/D19 : 3/3 |
// | I2C2 | LPI2C3 | OSC(24 MHz) | D17/D16 : 1/1 |
// | I2C3 | LPI2C4 | OSC(24 MHz) | D25/D24 : 0/0 |
// #===========#==========#=============#=========-=====#
const (
NUM_I2C_INTERFACES = 3
)
I2C1_SDA_PIN = D18
I2C1_SCL_PIN = D19
func initI2C() {}
I2C2_SDA_PIN = D17
I2C2_SCL_PIN = D16
I2C3_SDA_PIN = D25
I2C3_SCL_PIN = D24
)
+283 -117
View File
@@ -15,28 +15,6 @@ func CPUFrequency() uint32 {
type PinMode uint8
// muxSelect is yet another level of indirection required to connect pins in an
// alternate function state to a desired peripheral (since more than one pin can
// provide a given alternate function).
//
// Once a pin is configured with a given alternate function mode, the IOMUXC
// device must then be configured to select which alternate function pin to
// route to the desired peripheral.
//
// The reference manual refers to this functionality as a "Daisy Chain". The
// associated docs are found in the i.MX RT1060 Processor Reference Manual:
// "Chapter 11.3.3 Daisy chain - multi pads driving same module input pin"
type muxSelect struct {
mux uint8 // AF mux selection (NOT a Pin type)
sel *volatile.Register32 // AF selection register
}
// connect configures the IOMUXC controller to route a given pin with alternate
// function to a desired peripheral (see godoc comments on type muxSelect).
func (s muxSelect) connect() {
s.sel.Set(uint32(s.mux))
}
const (
// GPIO
PinInput PinMode = iota
@@ -45,93 +23,25 @@ const (
PinOutput
PinOutputOpenDrain
PinDisable
// ADC
PinInputAnalog
// UART
PinModeUARTTX
PinModeUARTRX
// SPI
PinModeSPISDI
PinModeSPISDO
PinModeSPICLK
PinModeSPICS
// I2C
PinModeI2CSDA
PinModeI2CSCL
)
// Configure sets the GPIO pad and pin properties, and selects the appropriate
// alternate function, for a given Pin and PinConfig.
func (p Pin) Configure(config PinConfig) {
var (
// padSRE = uint32(0x01 << 0)
padDSE = func(n uint32) uint32 { return (n & 0x07) << 3 }
// padSPD = func(n uint32) uint32 { return (n & 0x03) << 6 }
padODE = uint32(0x01 << 11)
padPKE = uint32(0x01 << 12)
padPUE = uint32(0x01 << 13)
padPUP = func(n uint32) uint32 { return (n & 0x03) << 14 }
padHYS = uint32(0x01 << 16)
)
_, gpio := p.getGPIO() // use fast GPIO for all pins
pad, mux := p.getPad()
// first configure the pad characteristics
switch config.Mode {
case PinInput:
gpio.GDIR.ClearBits(p.getMask())
pad.Set(padDSE(7))
case PinInputPullUp:
gpio.GDIR.ClearBits(p.getMask())
pad.Set(padDSE(7) | padPKE | padPUE | padPUP(3) | padHYS)
case PinInputPullDown:
gpio.GDIR.ClearBits(p.getMask())
pad.Set(padDSE(7) | padPKE | padPUE | padHYS)
case PinOutput:
gpio.GDIR.SetBits(p.getMask())
pad.Set(padDSE(7))
case PinOutputOpenDrain:
gpio.GDIR.SetBits(p.getMask())
pad.Set(padDSE(7) | padODE)
case PinDisable:
gpio.GDIR.ClearBits(p.getMask())
pad.Set(padDSE(7) | padHYS)
}
// then configure the alternate function mux
mux.Set(p.getMuxMode(config))
}
// getMuxMode acts as a callback from the `(Pin).Configure(PinMode)` routine to
// determine the alternate function setting for a given Pin and PinConfig.
// This value is used in the IOMUXC device's SW_MUX_CTL_PAD_GPIO_* registers.
func (p Pin) getMuxMode(config PinConfig) uint32 {
const forcePath = true // TODO: should be input parameter?
switch config.Mode {
// GPIO
case PinInput, PinInputPullUp, PinInputPullDown,
PinOutput, PinOutputOpenDrain, PinDisable:
mode := uint32(0x5) // GPIO is always alternate function 5
if forcePath {
mode |= 0x10 // SION bit
}
return mode
default:
panic("machine: invalid pin mode")
}
}
// Set changes the value of the GPIO pin. The pin must be configured as output.
func (p Pin) Set(value bool) {
_, gpio := p.getGPIO() // use fast GPIO for all pins
if value {
gpio.DR_SET.Set(p.getMask())
} else {
gpio.DR_CLEAR.Set(p.getMask())
}
}
// Get returns the current value of a GPIO pin.
func (p Pin) Get() bool {
_, gpio := p.getGPIO() // use fast GPIO for all pins
return gpio.PSR.HasBits(p.getMask())
}
// From the i.MXRT1062 Processor Reference Manual (Chapter 12 - GPIO):
//
// | High-speed GPIOs exist in this device:
@@ -149,17 +59,13 @@ func (p Pin) Get() bool {
// We cannot declare 32 pins for all available ports (GPIO1-9) anyway, since Pin
// is only uint8, and 9*32=288 > 256, so something has to be sacrificed.
const numPorts, pinsPerPort = 4, 32
const (
portA Pin = iota * pinsPerPort // GPIO1(6)
portB // GPIO2(7)
portC // GPIO3(8)
portD // GPIO4(9)
portA Pin = iota * 32 // GPIO1(6)
portB // GPIO2(7)
portC // GPIO3(8)
portD // GPIO4(9)
)
const numPins = numPorts * pinsPerPort
const (
// [Pad]: Alt Func 0 Alt Func 1 Alt Func 2 Alt Func 3 Alt Func 4 Alt Func 5 Alt Func 6 Alt Func 7 Alt Func 8 Alt Func 9
// ---------- --------------- --------------- ------------------- -------------------- -------------------- ----------- -------------------- -------------------- --------------------- ----------------
@@ -296,9 +202,104 @@ const (
PD31 = portD + 31 // [EMC_31]: SEMC_DATA09 FLEXPWM3_PWMA01 LPUART7_TX LPSPI1_PCS1 CSI_DATA22 GPIO4_IO31 ENET2_TDATA01 ~ ~ ~
)
func (p Pin) getPos() uint8 { return uint8(p % pinsPerPort) }
func (p Pin) getPos() uint8 { return uint8(p % 32) }
func (p Pin) getMask() uint32 { return uint32(1) << p.getPos() }
func (p Pin) getPort() Pin { return Pin(p/pinsPerPort) * pinsPerPort }
func (p Pin) getPort() Pin { return Pin(p/32) * 32 }
// Configure sets the GPIO pad and pin properties, and selects the appropriate
// alternate function, for a given Pin and PinConfig.
func (p Pin) Configure(config PinConfig) {
var (
sre = uint32(0x01 << 0)
dse = func(n uint32) uint32 { return (n & 0x07) << 3 }
spd = func(n uint32) uint32 { return (n & 0x03) << 6 }
ode = uint32(0x01 << 11)
pke = uint32(0x01 << 12)
pue = uint32(0x01 << 13)
pup = func(n uint32) uint32 { return (n & 0x03) << 14 }
hys = uint32(0x01 << 16)
)
_, gpio := p.getGPIO() // use fast GPIO for all pins
pad, mux := p.getPad()
// first configure the pad characteristics
switch config.Mode {
case PinInput:
gpio.GDIR.ClearBits(p.getMask())
pad.Set(dse(7))
case PinInputPullUp:
gpio.GDIR.ClearBits(p.getMask())
pad.Set(dse(7) | pke | pue | pup(3) | hys)
case PinInputPullDown:
gpio.GDIR.ClearBits(p.getMask())
pad.Set(dse(7) | pke | pue | hys)
case PinOutput:
gpio.GDIR.SetBits(p.getMask())
pad.Set(dse(7))
case PinOutputOpenDrain:
gpio.GDIR.SetBits(p.getMask())
pad.Set(dse(7) | ode)
case PinDisable:
gpio.GDIR.ClearBits(p.getMask())
pad.Set(dse(7) | hys)
case PinInputAnalog:
gpio.GDIR.ClearBits(p.getMask())
pad.Set(dse(7))
case PinModeUARTTX:
pad.Set(sre | dse(3) | spd(3))
case PinModeUARTRX:
pad.Set(dse(7) | pke | pue | pup(3) | hys)
case PinModeSPISDI:
pad.Set(dse(7) | spd(2))
case PinModeSPISDO:
pad.Set(dse(7) | spd(2))
case PinModeSPICLK:
pad.Set(dse(7) | spd(2))
case PinModeSPICS:
pad.Set(dse(7))
case PinModeI2CSDA, PinModeI2CSCL:
pad.Set(ode | sre | dse(4) | spd(1) | pke | pue | pup(3))
}
// then configure the alternate function mux
mux.Set(p.getMuxMode(config))
}
// Get returns the current value of a GPIO pin.
func (p Pin) Get() bool {
_, gpio := p.getGPIO() // use fast GPIO for all pins
return gpio.PSR.HasBits(p.getMask())
}
// Set changes the value of the GPIO pin. The pin must be configured as output.
func (p Pin) Set(value bool) {
_, gpio := p.getGPIO() // use fast GPIO for all pins
if value {
gpio.DR_SET.Set(p.getMask())
} else {
gpio.DR_CLEAR.Set(p.getMask())
}
}
// Toggle switches an output pin from low to high or from high to low.
func (p Pin) Toggle() {
_, gpio := p.getGPIO() // use fast GPIO for all pins
gpio.DR_TOGGLE.Set(p.getMask())
}
// getGPIO returns both the normal (IPG_CLK_ROOT) and high-speed (AHB_CLK_ROOT)
// GPIO peripherals to which a given Pin is connected.
@@ -589,3 +590,168 @@ func (p Pin) getPad() (pad *volatile.Register32, mux *volatile.Register32) {
}
panic("machine: invalid pin")
}
// muxSelect is yet another level of indirection required to connect pins in an
// alternate function state to a desired peripheral (since more than one pin can
// provide a given alternate function).
//
// Once a pin is configured with a given alternate function mode, the IOMUXC
// device must then be configured to select which alternate function pin to
// route to the desired peripheral.
//
// The reference manual refers to this functionality as a "Daisy Chain". The
// associated docs are found in the i.MX RT1060 Processor Reference Manual:
// "Chapter 11.3.3 Daisy chain - multi pads driving same module input pin"
type muxSelect struct {
mux uint8 // AF mux selection (NOT a Pin type)
sel *volatile.Register32 // AF selection register
}
// connect configures the IOMUXC controller to route a given pin with alternate
// function to a desired peripheral (see godoc comments on type muxSelect).
func (s muxSelect) connect() {
s.sel.Set(uint32(s.mux))
}
// getMuxMode acts as a callback from the `(Pin).Configure(PinMode)` routine to
// determine the alternate function setting for a given Pin and PinConfig.
// This value is used in the IOMUXC device's SW_MUX_CTL_PAD_GPIO_* registers.
func (p Pin) getMuxMode(config PinConfig) uint32 {
const forcePath = true // TODO: should be input parameter?
switch config.Mode {
// GPIO
case PinInput, PinInputPullUp, PinInputPullDown,
PinOutput, PinOutputOpenDrain, PinDisable:
mode := uint32(0x5) // GPIO is always alternate function 5
if forcePath {
mode |= 0x10 // SION bit
}
return mode
// ADC
case PinInputAnalog:
mode := uint32(0x5) // use alternate function 5 (GPIO)
if forcePath {
mode |= 0x10 // SION bit
}
return mode
// UART RX/TX
case PinModeUARTRX, PinModeUARTTX:
mode := uint32(0x2) // UART is always alternate function 2 on Teensy 4.0
// TODO: Teensy 4.1 has a UART (LPUART5) with alternate function 1
return mode
// SPI SDI
case PinModeSPISDI:
var mode uint32
switch p {
case PC15: // LPSPI1 SDI on PC15 alternate function 4
mode = uint32(0x4)
case PA2: // LPSPI3 SDI on PA2 alternate function 7
mode = uint32(0x7)
case PB1: // LPSPI4 SDI on PB1 alternate function 3
mode = uint32(0x3)
default:
panic("machine: invalid SPI SDI pin")
}
if forcePath {
mode |= 0x10 // SION bit
}
return mode
// SPI SDO
case PinModeSPISDO:
var mode uint32
switch p {
case PC14: // LPSPI1 SDO on PC14 alternate function 4
mode = uint32(0x4)
case PA30: // LPSPI3 SDO on PA30 alternate function 2
mode = uint32(0x2)
case PB2: // LPSPI4 SDO on PB2 alternate function 3
mode = uint32(0x3)
default:
panic("machine: invalid SPI SDO pin")
}
if forcePath {
mode |= 0x10 // SION bit
}
return mode
// SPI SCK
case PinModeSPICLK:
var mode uint32
switch p {
case PC12: // LPSPI1 SCK on PC12 alternate function 4
mode = uint32(0x4)
case PA31: // LPSPI3 SCK on PA31 alternate function 2
mode = uint32(0x2)
case PB3: // LPSPI4 SCK on PB3 alternate function 3
mode = uint32(0x3)
default:
panic("machine: invalid SPI CLK pin")
}
if forcePath {
mode |= 0x10 // SION bit
}
return mode
// SPI CS
case PinModeSPICS:
var mode uint32
switch p {
case PC13: // LPSPI1 CS on PC13 alternate function 4
mode = uint32(0x4)
case PA3: // LPSPI3 CS on PA3 alternate function 7
mode = uint32(0x7)
case PB0: // LPSPI4 CS on PB0 alternate function 3
mode = uint32(0x3)
default: // use alternate function 5 (GPIO) if non-CS pin selected
mode = uint32(0x5)
}
if forcePath {
mode |= 0x10 // SION bit
}
return mode
// I2C SDA
case PinModeI2CSDA:
var mode uint32
switch p {
case PA13: // LPI2C4 SDA on PA13 alternate function 0
mode = uint32(0)
case PA17: // LPI2C1 SDA on PA17 alternate function 3
mode = uint32(3)
case PA22: // LPI2C3 SDA on PA22 alternate function 1
mode = uint32(1)
default:
panic("machine: invalid I2C SDA pin")
}
if forcePath {
mode |= 0x10 // SION bit
}
return mode
// I2C SCL
case PinModeI2CSCL:
var mode uint32
switch p {
case PA12: // LPI2C4 SCL on PA12 alternate function 0
mode = uint32(0)
case PA16: // LPI2C1 SCL on PA16 alternate function 3
mode = uint32(3)
case PA23: // LPI2C3 SCL on PA23 alternate function 1
mode = uint32(1)
default:
panic("machine: invalid I2C SCL pin")
}
if forcePath {
mode |= 0x10 // SION bit
}
return mode
default:
panic("machine: invalid pin mode")
}
}