diff options
author | ardnew <[email protected]> | 2021-09-11 01:53:30 -0500 |
---|---|---|
committer | Ron Evans <[email protected]> | 2021-09-13 09:29:20 +0200 |
commit | 1e92e5f6c6e1e56baf4c695032ab275a9bdd7eb4 (patch) | |
tree | 6fdcd017a73671b39d1ad8b117923f4e00b21724 | |
parent | 3eb9dca695254b9d59f30597ea6c409e1b65e7ee (diff) | |
download | tinygo-1e92e5f6c6e1e56baf4c695032ab275a9bdd7eb4.tar.gz tinygo-1e92e5f6c6e1e56baf4c695032ab275a9bdd7eb4.zip |
teensy40: enable hardware UART reconfiguration, fix receive watermark interrupt
-rw-r--r-- | src/device/nxp/mimxrt1062_mpu.go | 30 | ||||
-rw-r--r-- | src/machine/board_teensy40.go | 24 | ||||
-rw-r--r-- | src/machine/machine_mimxrt1062_uart.go | 92 | ||||
-rw-r--r-- | targets/mimxrt1062-teensy40.ld | 3 |
4 files changed, 69 insertions, 80 deletions
diff --git a/src/device/nxp/mimxrt1062_mpu.go b/src/device/nxp/mimxrt1062_mpu.go index 8483b7561..f69dfc3fa 100644 --- a/src/device/nxp/mimxrt1062_mpu.go +++ b/src/device/nxp/mimxrt1062_mpu.go @@ -2,6 +2,7 @@ // Type definitions, fields, and constants associated with the MPU peripheral // of the NXP MIMXRT1062. +//go:build nxp && mimxrt1062 // +build nxp,mimxrt1062 package nxp @@ -216,6 +217,12 @@ func enableIcache(enable bool) { } } +var ( + dcacheCcsidr volatile.Register32 + dcacheSets volatile.Register32 + dcacheWays volatile.Register32 +) + func enableDcache(enable bool) { if enable != SystemControl.CCR.HasBits(SCB_CCR_DC_Msk) { if enable { @@ -244,11 +251,6 @@ func enableDcache(enable bool) { isb 0xF `, nil) } else { - var ( - ccsidr volatile.Register32 - sets volatile.Register32 - ways volatile.Register32 - ) SystemControl.CSSELR.Set(0) arm.AsmFull(` dsb 0xF @@ -257,17 +259,17 @@ func enableDcache(enable bool) { arm.AsmFull(` dsb 0xF `, nil) - ccsidr.Set(SystemControl.CCSIDR.Get()) - sets.Set((ccsidr.Get() & SCB_CCSIDR_NUMSETS_Msk) >> SCB_CCSIDR_NUMSETS_Pos) - for sets.Get() != 0 { - ways.Set((ccsidr.Get() & SCB_CCSIDR_ASSOCIATIVITY_Msk) >> SCB_CCSIDR_ASSOCIATIVITY_Pos) - for ways.Get() != 0 { + dcacheCcsidr.Set(SystemControl.CCSIDR.Get()) + dcacheSets.Set((dcacheCcsidr.Get() & SCB_CCSIDR_NUMSETS_Msk) >> SCB_CCSIDR_NUMSETS_Pos) + for dcacheSets.Get() != 0 { + dcacheWays.Set((dcacheCcsidr.Get() & SCB_CCSIDR_ASSOCIATIVITY_Msk) >> SCB_CCSIDR_ASSOCIATIVITY_Pos) + for dcacheWays.Get() != 0 { SystemControl.DCCISW.Set( - ((sets.Get() << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) | - ((ways.Get() << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk)) - ways.Set(ways.Get() - 1) + ((dcacheSets.Get() << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) | + ((dcacheWays.Get() << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk)) + dcacheWays.Set(dcacheWays.Get() - 1) } - sets.Set(sets.Get() - 1) + dcacheSets.Set(dcacheSets.Get() - 1) } arm.AsmFull(` dsb 0xF diff --git a/src/machine/board_teensy40.go b/src/machine/board_teensy40.go index 289edadd8..f96f63de7 100644 --- a/src/machine/board_teensy40.go +++ b/src/machine/board_teensy40.go @@ -88,15 +88,20 @@ const ( I2C_SCL_PIN = I2C1_SCL_PIN // D19/A5 ) +// Default peripherals +var ( + DefaultUART = UART1 +) + func init() { // register any interrupt handlers for this board's peripherals - UART1.Interrupt = interrupt.New(nxp.IRQ_LPUART6, _UART1.handleInterrupt) - UART2.Interrupt = interrupt.New(nxp.IRQ_LPUART4, _UART2.handleInterrupt) - UART3.Interrupt = interrupt.New(nxp.IRQ_LPUART2, _UART3.handleInterrupt) - UART4.Interrupt = interrupt.New(nxp.IRQ_LPUART3, _UART4.handleInterrupt) - UART5.Interrupt = interrupt.New(nxp.IRQ_LPUART8, _UART5.handleInterrupt) - UART6.Interrupt = interrupt.New(nxp.IRQ_LPUART1, _UART6.handleInterrupt) - UART7.Interrupt = interrupt.New(nxp.IRQ_LPUART7, _UART7.handleInterrupt) + _UART1.Interrupt = interrupt.New(nxp.IRQ_LPUART6, _UART1.handleInterrupt) + _UART2.Interrupt = interrupt.New(nxp.IRQ_LPUART4, _UART2.handleInterrupt) + _UART3.Interrupt = interrupt.New(nxp.IRQ_LPUART2, _UART3.handleInterrupt) + _UART4.Interrupt = interrupt.New(nxp.IRQ_LPUART3, _UART4.handleInterrupt) + _UART5.Interrupt = interrupt.New(nxp.IRQ_LPUART8, _UART5.handleInterrupt) + _UART6.Interrupt = interrupt.New(nxp.IRQ_LPUART1, _UART6.handleInterrupt) + _UART7.Interrupt = interrupt.New(nxp.IRQ_LPUART7, _UART7.handleInterrupt) } // #=====================================================# @@ -136,9 +141,8 @@ const ( ) var ( - DefaultUART = UART1 - UART1 = &_UART1 - _UART1 = UART{ + UART1 = &_UART1 + _UART1 = UART{ Bus: nxp.LPUART6, Buffer: NewRingBuffer(), txBuffer: NewRingBuffer(), diff --git a/src/machine/machine_mimxrt1062_uart.go b/src/machine/machine_mimxrt1062_uart.go index ade7c1706..bb43f4be5 100644 --- a/src/machine/machine_mimxrt1062_uart.go +++ b/src/machine/machine_mimxrt1062_uart.go @@ -33,7 +33,6 @@ type UART struct { // auxiliary state data used internally configured bool - msbFirst bool transmitting volatile.Register32 } @@ -46,6 +45,11 @@ func (uart *UART) resetTransmitting() { uart.Bus.GLOBAL.ClearBits(nxp.LPUART_GLOBAL_RST) } +func (uart *UART) usesConfig(c UARTConfig) bool { + return uart.configured && uart.baud == c.BaudRate && + uart.rx == c.RX && uart.tx == c.TX +} + // Configure initializes a UART with the given UARTConfig and other default // settings. func (uart *UART) Configure(config UARTConfig) { @@ -56,13 +60,19 @@ func (uart *UART) Configure(config UARTConfig) { if config.BaudRate == 0 { config.BaudRate = defaultUartFreq } - uart.baud = config.BaudRate // use default UART pins if not specified if config.RX == 0 && config.TX == 0 { config.RX = UART_RX_PIN config.TX = UART_TX_PIN } + + // Do not reconfigure pins and device buffers if duplicate config provided. + if uart.usesConfig(config) { + return + } + + uart.baud = config.BaudRate uart.rx = config.RX uart.tx = config.TX @@ -77,84 +87,58 @@ func (uart *UART) Configure(config UARTConfig) { // reset all internal logic and registers uart.resetTransmitting() + // disable until we have finished configuring registers + uart.Bus.CTRL.Set(0) + // determine the baud rate and over-sample divisors sbr, osr := uart.getBaudRateDivisor(uart.baud) - // for now we assume some configuration. in particular: - // Data bits -> 8-bit - // Parity bit -> None (parity bit generation disabled) - // Stop bits -> 1 stop bit - // MSB first -> false - // RX idle type -> idle count starts after start bit - // RX idle config -> 1 idle character - // RX RTS enabled -> false - // TX CTS enabled -> false - // set the baud rate, over-sample configuration, stop bits baudBits := (((osr - 1) << nxp.LPUART_BAUD_OSR_Pos) & nxp.LPUART_BAUD_OSR_Msk) | - ((sbr << nxp.LPUART_BAUD_SBR_Pos) & nxp.LPUART_BAUD_SBR_Msk) | - ((nxp.LPUART_BAUD_SBNS_SBNS_0 << nxp.LPUART_BAUD_SBNS_Pos) & nxp.LPUART_BAUD_SBNS_Msk) + ((sbr << nxp.LPUART_BAUD_SBR_Pos) & nxp.LPUART_BAUD_SBR_Msk) if osr <= 8 { // if OSR less than or equal to 8, we must enable sampling on both edges baudBits |= nxp.LPUART_BAUD_BOTHEDGE } uart.Bus.BAUD.Set(baudBits) - uart.Bus.PINCFG.Set(0) // disable triggers - // use 8 data bits, disable parity, use 1 idle char, and idle count starts - // after start bit - ctrlBits := uint32(((nxp.LPUART_CTRL_M_M_0 << nxp.LPUART_CTRL_M_Pos) & nxp.LPUART_CTRL_M_Msk) | - ((nxp.LPUART_CTRL_PE_PE_0 << nxp.LPUART_CTRL_PE_Pos) & nxp.LPUART_CTRL_PE_Msk) | - ((nxp.LPUART_CTRL_ILT_ILT_0 << nxp.LPUART_CTRL_ILT_Pos) & nxp.LPUART_CTRL_ILT_Msk) | - ((nxp.LPUART_CTRL_IDLECFG_IDLECFG_0 << nxp.LPUART_CTRL_IDLECFG_Pos) & nxp.LPUART_CTRL_IDLECFG_Msk)) - uart.Bus.CTRL.Set(ctrlBits) - + // configure watermarks, flush and enable TX/RX FIFOs rxSize, txSize := uart.getFIFOSize() - rxWater := rxSize >> 1 if rxWater > uint32(nxp.LPUART_FIFO_RXFIFOSIZE_Msk>>nxp.LPUART_FIFO_RXFIFOSIZE_Pos) { rxWater = uint32(nxp.LPUART_FIFO_RXFIFOSIZE_Msk >> nxp.LPUART_FIFO_RXFIFOSIZE_Pos) } - txWater := txSize >> 1 if txWater > uint32(nxp.LPUART_FIFO_TXFIFOSIZE_Msk>>nxp.LPUART_FIFO_TXFIFOSIZE_Pos) { txWater = uint32(nxp.LPUART_FIFO_TXFIFOSIZE_Msk >> nxp.LPUART_FIFO_TXFIFOSIZE_Pos) } - uart.Bus.WATER.Set( ((rxWater << nxp.LPUART_WATER_RXWATER_Pos) & nxp.LPUART_WATER_RXWATER_Msk) | ((txWater << nxp.LPUART_WATER_TXWATER_Pos) & nxp.LPUART_WATER_TXWATER_Msk)) + uart.Bus.FIFO.SetBits(nxp.LPUART_FIFO_RXFE | nxp.LPUART_FIFO_TXFE | + nxp.LPUART_FIFO_RXFLUSH | nxp.LPUART_FIFO_TXFLUSH) - // enable TX/RX FIFOs - uart.Bus.FIFO.SetBits(nxp.LPUART_FIFO_RXFE | nxp.LPUART_FIFO_TXFE) - - // flush TX/RX FIFOs - uart.Bus.FIFO.SetBits(nxp.LPUART_FIFO_RXFLUSH | nxp.LPUART_FIFO_TXFLUSH) + // for now we assume some configuration. in particular: + // Data bits -> 8-bit + // Parity bit -> None (parity bit generation disabled) + // Stop bits -> 1 stop bit + // MSB first -> false + // RX idle type -> idle count starts after start bit + // RX idle config -> 1 idle character + // RX RTS enabled -> false + // TX CTS enabled -> false - uart.Bus.MODIR.SetBits( // set the CTS configuration/TX CTS source - ((nxp.LPUART_MODIR_TXCTSC_TXCTSC_0 << nxp.LPUART_MODIR_TXCTSC_Pos) & nxp.LPUART_MODIR_TXCTSC_Msk) | - ((nxp.LPUART_MODIR_TXCTSSRC_TXCTSSRC_0 << nxp.LPUART_MODIR_TXCTSSRC_Pos) & nxp.LPUART_MODIR_TXCTSSRC_Msk)) + // enable transmitter, receiver functions + uart.Bus.CTRL.Set(nxp.LPUART_CTRL_TE | nxp.LPUART_CTRL_RE | + // enable receiver, idle line interrupts + nxp.LPUART_CTRL_RIE | nxp.LPUART_CTRL_ILIE) // clear all status flags - stat := uint32(nxp.LPUART_STAT_RXEDGIF_Msk | nxp.LPUART_STAT_IDLE_Msk | nxp.LPUART_STAT_OR_Msk | - nxp.LPUART_STAT_NF_Msk | nxp.LPUART_STAT_FE_Msk | nxp.LPUART_STAT_PF_Msk | - nxp.LPUART_STAT_LBKDIF_Msk | nxp.LPUART_STAT_MA1F_Msk | nxp.LPUART_STAT_MA2F_Msk) - - // set data bits order - if uart.msbFirst { - stat |= nxp.LPUART_STAT_MSBF - } else { - stat &^= nxp.LPUART_STAT_MSBF - } - - uart.Bus.STAT.SetBits(stat) - - // enable RX/TX functions - uart.Bus.CTRL.SetBits(nxp.LPUART_CTRL_TE | nxp.LPUART_CTRL_RE) + uart.Bus.STAT.Set(uart.Bus.STAT.Get()) - // enable RX IRQ - uart.Interrupt.SetPriority(0xc0) + // enable RX interrupt + uart.Interrupt.SetPriority(0xC0) uart.Interrupt.Enable() uart.configured = true @@ -211,13 +195,13 @@ func (uart *UART) WriteByte(c byte) error { // corresponding baud rate divisor (1..8191) that best partition a given baud // rate into equal intervals. // -// This is an integral (i.e. non-floating point) port of the logic at the +// This is an integral (non-floating point) translation of the logic at the // beginning of: // void HardwareSerial::begin(uint32_t baud, uint16_t format) // (from Teensyduino: `cores/teensy4/HardwareSerial.cpp`) // -// We don't want to risk using floating point here in the machine package in -// case it gets called before the FPU or interrupts are ready (e.g., init()). +// We don't want to use floating point here in case it gets called from an ISR +// or very early during system init. func (uart *UART) getBaudRateDivisor(baudRate uint32) (sbr uint32, osr uint32) { const clock = 24000000 // UART is muxed to 24 MHz OSC err := uint32(0xFFFFFFFF) diff --git a/targets/mimxrt1062-teensy40.ld b/targets/mimxrt1062-teensy40.ld index 312b1078c..70a717b72 100644 --- a/targets/mimxrt1062-teensy40.ld +++ b/targets/mimxrt1062-teensy40.ld @@ -8,8 +8,7 @@ MEMORY ENTRY(Reset_Handler); -_stack_size = 128K; -_heap_size = 512K; +_stack_size = 4K; SECTIONS { |