Skip to content

Commit 1e92e5f

Browse files
ardnewdeadprogram
authored andcommitted
teensy40: enable hardware UART reconfiguration, fix receive watermark interrupt
1 parent 3eb9dca commit 1e92e5f

File tree

4 files changed

+69
-80
lines changed

4 files changed

+69
-80
lines changed

src/device/nxp/mimxrt1062_mpu.go

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Type definitions, fields, and constants associated with the MPU peripheral
33
// of the NXP MIMXRT1062.
44

5+
//go:build nxp && mimxrt1062
56
// +build nxp,mimxrt1062
67

78
package nxp
@@ -216,6 +217,12 @@ func enableIcache(enable bool) {
216217
}
217218
}
218219

220+
var (
221+
dcacheCcsidr volatile.Register32
222+
dcacheSets volatile.Register32
223+
dcacheWays volatile.Register32
224+
)
225+
219226
func enableDcache(enable bool) {
220227
if enable != SystemControl.CCR.HasBits(SCB_CCR_DC_Msk) {
221228
if enable {
@@ -244,11 +251,6 @@ func enableDcache(enable bool) {
244251
isb 0xF
245252
`, nil)
246253
} else {
247-
var (
248-
ccsidr volatile.Register32
249-
sets volatile.Register32
250-
ways volatile.Register32
251-
)
252254
SystemControl.CSSELR.Set(0)
253255
arm.AsmFull(`
254256
dsb 0xF
@@ -257,17 +259,17 @@ func enableDcache(enable bool) {
257259
arm.AsmFull(`
258260
dsb 0xF
259261
`, nil)
260-
ccsidr.Set(SystemControl.CCSIDR.Get())
261-
sets.Set((ccsidr.Get() & SCB_CCSIDR_NUMSETS_Msk) >> SCB_CCSIDR_NUMSETS_Pos)
262-
for sets.Get() != 0 {
263-
ways.Set((ccsidr.Get() & SCB_CCSIDR_ASSOCIATIVITY_Msk) >> SCB_CCSIDR_ASSOCIATIVITY_Pos)
264-
for ways.Get() != 0 {
262+
dcacheCcsidr.Set(SystemControl.CCSIDR.Get())
263+
dcacheSets.Set((dcacheCcsidr.Get() & SCB_CCSIDR_NUMSETS_Msk) >> SCB_CCSIDR_NUMSETS_Pos)
264+
for dcacheSets.Get() != 0 {
265+
dcacheWays.Set((dcacheCcsidr.Get() & SCB_CCSIDR_ASSOCIATIVITY_Msk) >> SCB_CCSIDR_ASSOCIATIVITY_Pos)
266+
for dcacheWays.Get() != 0 {
265267
SystemControl.DCCISW.Set(
266-
((sets.Get() << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) |
267-
((ways.Get() << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk))
268-
ways.Set(ways.Get() - 1)
268+
((dcacheSets.Get() << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) |
269+
((dcacheWays.Get() << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk))
270+
dcacheWays.Set(dcacheWays.Get() - 1)
269271
}
270-
sets.Set(sets.Get() - 1)
272+
dcacheSets.Set(dcacheSets.Get() - 1)
271273
}
272274
arm.AsmFull(`
273275
dsb 0xF

src/machine/board_teensy40.go

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -88,15 +88,20 @@ const (
8888
I2C_SCL_PIN = I2C1_SCL_PIN // D19/A5
8989
)
9090

91+
// Default peripherals
92+
var (
93+
DefaultUART = UART1
94+
)
95+
9196
func init() {
9297
// register any interrupt handlers for this board's peripherals
93-
UART1.Interrupt = interrupt.New(nxp.IRQ_LPUART6, _UART1.handleInterrupt)
94-
UART2.Interrupt = interrupt.New(nxp.IRQ_LPUART4, _UART2.handleInterrupt)
95-
UART3.Interrupt = interrupt.New(nxp.IRQ_LPUART2, _UART3.handleInterrupt)
96-
UART4.Interrupt = interrupt.New(nxp.IRQ_LPUART3, _UART4.handleInterrupt)
97-
UART5.Interrupt = interrupt.New(nxp.IRQ_LPUART8, _UART5.handleInterrupt)
98-
UART6.Interrupt = interrupt.New(nxp.IRQ_LPUART1, _UART6.handleInterrupt)
99-
UART7.Interrupt = interrupt.New(nxp.IRQ_LPUART7, _UART7.handleInterrupt)
98+
_UART1.Interrupt = interrupt.New(nxp.IRQ_LPUART6, _UART1.handleInterrupt)
99+
_UART2.Interrupt = interrupt.New(nxp.IRQ_LPUART4, _UART2.handleInterrupt)
100+
_UART3.Interrupt = interrupt.New(nxp.IRQ_LPUART2, _UART3.handleInterrupt)
101+
_UART4.Interrupt = interrupt.New(nxp.IRQ_LPUART3, _UART4.handleInterrupt)
102+
_UART5.Interrupt = interrupt.New(nxp.IRQ_LPUART8, _UART5.handleInterrupt)
103+
_UART6.Interrupt = interrupt.New(nxp.IRQ_LPUART1, _UART6.handleInterrupt)
104+
_UART7.Interrupt = interrupt.New(nxp.IRQ_LPUART7, _UART7.handleInterrupt)
100105
}
101106

102107
// #=====================================================#
@@ -136,9 +141,8 @@ const (
136141
)
137142

138143
var (
139-
DefaultUART = UART1
140-
UART1 = &_UART1
141-
_UART1 = UART{
144+
UART1 = &_UART1
145+
_UART1 = UART{
142146
Bus: nxp.LPUART6,
143147
Buffer: NewRingBuffer(),
144148
txBuffer: NewRingBuffer(),

src/machine/machine_mimxrt1062_uart.go

Lines changed: 38 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ type UART struct {
3333

3434
// auxiliary state data used internally
3535
configured bool
36-
msbFirst bool
3736
transmitting volatile.Register32
3837
}
3938

@@ -46,6 +45,11 @@ func (uart *UART) resetTransmitting() {
4645
uart.Bus.GLOBAL.ClearBits(nxp.LPUART_GLOBAL_RST)
4746
}
4847

48+
func (uart *UART) usesConfig(c UARTConfig) bool {
49+
return uart.configured && uart.baud == c.BaudRate &&
50+
uart.rx == c.RX && uart.tx == c.TX
51+
}
52+
4953
// Configure initializes a UART with the given UARTConfig and other default
5054
// settings.
5155
func (uart *UART) Configure(config UARTConfig) {
@@ -56,13 +60,19 @@ func (uart *UART) Configure(config UARTConfig) {
5660
if config.BaudRate == 0 {
5761
config.BaudRate = defaultUartFreq
5862
}
59-
uart.baud = config.BaudRate
6063

6164
// use default UART pins if not specified
6265
if config.RX == 0 && config.TX == 0 {
6366
config.RX = UART_RX_PIN
6467
config.TX = UART_TX_PIN
6568
}
69+
70+
// Do not reconfigure pins and device buffers if duplicate config provided.
71+
if uart.usesConfig(config) {
72+
return
73+
}
74+
75+
uart.baud = config.BaudRate
6676
uart.rx = config.RX
6777
uart.tx = config.TX
6878

@@ -77,84 +87,58 @@ func (uart *UART) Configure(config UARTConfig) {
7787
// reset all internal logic and registers
7888
uart.resetTransmitting()
7989

90+
// disable until we have finished configuring registers
91+
uart.Bus.CTRL.Set(0)
92+
8093
// determine the baud rate and over-sample divisors
8194
sbr, osr := uart.getBaudRateDivisor(uart.baud)
8295

83-
// for now we assume some configuration. in particular:
84-
// Data bits -> 8-bit
85-
// Parity bit -> None (parity bit generation disabled)
86-
// Stop bits -> 1 stop bit
87-
// MSB first -> false
88-
// RX idle type -> idle count starts after start bit
89-
// RX idle config -> 1 idle character
90-
// RX RTS enabled -> false
91-
// TX CTS enabled -> false
92-
9396
// set the baud rate, over-sample configuration, stop bits
9497
baudBits := (((osr - 1) << nxp.LPUART_BAUD_OSR_Pos) & nxp.LPUART_BAUD_OSR_Msk) |
95-
((sbr << nxp.LPUART_BAUD_SBR_Pos) & nxp.LPUART_BAUD_SBR_Msk) |
96-
((nxp.LPUART_BAUD_SBNS_SBNS_0 << nxp.LPUART_BAUD_SBNS_Pos) & nxp.LPUART_BAUD_SBNS_Msk)
98+
((sbr << nxp.LPUART_BAUD_SBR_Pos) & nxp.LPUART_BAUD_SBR_Msk)
9799
if osr <= 8 {
98100
// if OSR less than or equal to 8, we must enable sampling on both edges
99101
baudBits |= nxp.LPUART_BAUD_BOTHEDGE
100102
}
101103
uart.Bus.BAUD.Set(baudBits)
102-
103104
uart.Bus.PINCFG.Set(0) // disable triggers
104105

105-
// use 8 data bits, disable parity, use 1 idle char, and idle count starts
106-
// after start bit
107-
ctrlBits := uint32(((nxp.LPUART_CTRL_M_M_0 << nxp.LPUART_CTRL_M_Pos) & nxp.LPUART_CTRL_M_Msk) |
108-
((nxp.LPUART_CTRL_PE_PE_0 << nxp.LPUART_CTRL_PE_Pos) & nxp.LPUART_CTRL_PE_Msk) |
109-
((nxp.LPUART_CTRL_ILT_ILT_0 << nxp.LPUART_CTRL_ILT_Pos) & nxp.LPUART_CTRL_ILT_Msk) |
110-
((nxp.LPUART_CTRL_IDLECFG_IDLECFG_0 << nxp.LPUART_CTRL_IDLECFG_Pos) & nxp.LPUART_CTRL_IDLECFG_Msk))
111-
uart.Bus.CTRL.Set(ctrlBits)
112-
106+
// configure watermarks, flush and enable TX/RX FIFOs
113107
rxSize, txSize := uart.getFIFOSize()
114-
115108
rxWater := rxSize >> 1
116109
if rxWater > uint32(nxp.LPUART_FIFO_RXFIFOSIZE_Msk>>nxp.LPUART_FIFO_RXFIFOSIZE_Pos) {
117110
rxWater = uint32(nxp.LPUART_FIFO_RXFIFOSIZE_Msk >> nxp.LPUART_FIFO_RXFIFOSIZE_Pos)
118111
}
119-
120112
txWater := txSize >> 1
121113
if txWater > uint32(nxp.LPUART_FIFO_TXFIFOSIZE_Msk>>nxp.LPUART_FIFO_TXFIFOSIZE_Pos) {
122114
txWater = uint32(nxp.LPUART_FIFO_TXFIFOSIZE_Msk >> nxp.LPUART_FIFO_TXFIFOSIZE_Pos)
123115
}
124-
125116
uart.Bus.WATER.Set(
126117
((rxWater << nxp.LPUART_WATER_RXWATER_Pos) & nxp.LPUART_WATER_RXWATER_Msk) |
127118
((txWater << nxp.LPUART_WATER_TXWATER_Pos) & nxp.LPUART_WATER_TXWATER_Msk))
119+
uart.Bus.FIFO.SetBits(nxp.LPUART_FIFO_RXFE | nxp.LPUART_FIFO_TXFE |
120+
nxp.LPUART_FIFO_RXFLUSH | nxp.LPUART_FIFO_TXFLUSH)
128121

129-
// enable TX/RX FIFOs
130-
uart.Bus.FIFO.SetBits(nxp.LPUART_FIFO_RXFE | nxp.LPUART_FIFO_TXFE)
131-
132-
// flush TX/RX FIFOs
133-
uart.Bus.FIFO.SetBits(nxp.LPUART_FIFO_RXFLUSH | nxp.LPUART_FIFO_TXFLUSH)
122+
// for now we assume some configuration. in particular:
123+
// Data bits -> 8-bit
124+
// Parity bit -> None (parity bit generation disabled)
125+
// Stop bits -> 1 stop bit
126+
// MSB first -> false
127+
// RX idle type -> idle count starts after start bit
128+
// RX idle config -> 1 idle character
129+
// RX RTS enabled -> false
130+
// TX CTS enabled -> false
134131

135-
uart.Bus.MODIR.SetBits( // set the CTS configuration/TX CTS source
136-
((nxp.LPUART_MODIR_TXCTSC_TXCTSC_0 << nxp.LPUART_MODIR_TXCTSC_Pos) & nxp.LPUART_MODIR_TXCTSC_Msk) |
137-
((nxp.LPUART_MODIR_TXCTSSRC_TXCTSSRC_0 << nxp.LPUART_MODIR_TXCTSSRC_Pos) & nxp.LPUART_MODIR_TXCTSSRC_Msk))
132+
// enable transmitter, receiver functions
133+
uart.Bus.CTRL.Set(nxp.LPUART_CTRL_TE | nxp.LPUART_CTRL_RE |
134+
// enable receiver, idle line interrupts
135+
nxp.LPUART_CTRL_RIE | nxp.LPUART_CTRL_ILIE)
138136

139137
// clear all status flags
140-
stat := uint32(nxp.LPUART_STAT_RXEDGIF_Msk | nxp.LPUART_STAT_IDLE_Msk | nxp.LPUART_STAT_OR_Msk |
141-
nxp.LPUART_STAT_NF_Msk | nxp.LPUART_STAT_FE_Msk | nxp.LPUART_STAT_PF_Msk |
142-
nxp.LPUART_STAT_LBKDIF_Msk | nxp.LPUART_STAT_MA1F_Msk | nxp.LPUART_STAT_MA2F_Msk)
143-
144-
// set data bits order
145-
if uart.msbFirst {
146-
stat |= nxp.LPUART_STAT_MSBF
147-
} else {
148-
stat &^= nxp.LPUART_STAT_MSBF
149-
}
150-
151-
uart.Bus.STAT.SetBits(stat)
152-
153-
// enable RX/TX functions
154-
uart.Bus.CTRL.SetBits(nxp.LPUART_CTRL_TE | nxp.LPUART_CTRL_RE)
138+
uart.Bus.STAT.Set(uart.Bus.STAT.Get())
155139

156-
// enable RX IRQ
157-
uart.Interrupt.SetPriority(0xc0)
140+
// enable RX interrupt
141+
uart.Interrupt.SetPriority(0xC0)
158142
uart.Interrupt.Enable()
159143

160144
uart.configured = true
@@ -211,13 +195,13 @@ func (uart *UART) WriteByte(c byte) error {
211195
// corresponding baud rate divisor (1..8191) that best partition a given baud
212196
// rate into equal intervals.
213197
//
214-
// This is an integral (i.e. non-floating point) port of the logic at the
198+
// This is an integral (non-floating point) translation of the logic at the
215199
// beginning of:
216200
// void HardwareSerial::begin(uint32_t baud, uint16_t format)
217201
// (from Teensyduino: `cores/teensy4/HardwareSerial.cpp`)
218202
//
219-
// We don't want to risk using floating point here in the machine package in
220-
// case it gets called before the FPU or interrupts are ready (e.g., init()).
203+
// We don't want to use floating point here in case it gets called from an ISR
204+
// or very early during system init.
221205
func (uart *UART) getBaudRateDivisor(baudRate uint32) (sbr uint32, osr uint32) {
222206
const clock = 24000000 // UART is muxed to 24 MHz OSC
223207
err := uint32(0xFFFFFFFF)

targets/mimxrt1062-teensy40.ld

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ MEMORY
88

99
ENTRY(Reset_Handler);
1010

11-
_stack_size = 128K;
12-
_heap_size = 512K;
11+
_stack_size = 4K;
1312

1413
SECTIONS
1514
{

0 commit comments

Comments
 (0)