teensy40: enable hardware UART reconfiguration, fix receive watermark interrupt
Этот коммит содержится в:
родитель
3eb9dca695
коммит
1e92e5f6c6
4 изменённых файлов: 82 добавлений и 93 удалений
|
@ -2,6 +2,7 @@
|
||||||
// Type definitions, fields, and constants associated with the MPU peripheral
|
// Type definitions, fields, and constants associated with the MPU peripheral
|
||||||
// of the NXP MIMXRT1062.
|
// of the NXP MIMXRT1062.
|
||||||
|
|
||||||
|
//go:build nxp && mimxrt1062
|
||||||
// +build nxp,mimxrt1062
|
// +build nxp,mimxrt1062
|
||||||
|
|
||||||
package nxp
|
package nxp
|
||||||
|
@ -216,6 +217,12 @@ func enableIcache(enable bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
dcacheCcsidr volatile.Register32
|
||||||
|
dcacheSets volatile.Register32
|
||||||
|
dcacheWays volatile.Register32
|
||||||
|
)
|
||||||
|
|
||||||
func enableDcache(enable bool) {
|
func enableDcache(enable bool) {
|
||||||
if enable != SystemControl.CCR.HasBits(SCB_CCR_DC_Msk) {
|
if enable != SystemControl.CCR.HasBits(SCB_CCR_DC_Msk) {
|
||||||
if enable {
|
if enable {
|
||||||
|
@ -244,11 +251,6 @@ func enableDcache(enable bool) {
|
||||||
isb 0xF
|
isb 0xF
|
||||||
`, nil)
|
`, nil)
|
||||||
} else {
|
} else {
|
||||||
var (
|
|
||||||
ccsidr volatile.Register32
|
|
||||||
sets volatile.Register32
|
|
||||||
ways volatile.Register32
|
|
||||||
)
|
|
||||||
SystemControl.CSSELR.Set(0)
|
SystemControl.CSSELR.Set(0)
|
||||||
arm.AsmFull(`
|
arm.AsmFull(`
|
||||||
dsb 0xF
|
dsb 0xF
|
||||||
|
@ -257,17 +259,17 @@ func enableDcache(enable bool) {
|
||||||
arm.AsmFull(`
|
arm.AsmFull(`
|
||||||
dsb 0xF
|
dsb 0xF
|
||||||
`, nil)
|
`, nil)
|
||||||
ccsidr.Set(SystemControl.CCSIDR.Get())
|
dcacheCcsidr.Set(SystemControl.CCSIDR.Get())
|
||||||
sets.Set((ccsidr.Get() & SCB_CCSIDR_NUMSETS_Msk) >> SCB_CCSIDR_NUMSETS_Pos)
|
dcacheSets.Set((dcacheCcsidr.Get() & SCB_CCSIDR_NUMSETS_Msk) >> SCB_CCSIDR_NUMSETS_Pos)
|
||||||
for sets.Get() != 0 {
|
for dcacheSets.Get() != 0 {
|
||||||
ways.Set((ccsidr.Get() & SCB_CCSIDR_ASSOCIATIVITY_Msk) >> SCB_CCSIDR_ASSOCIATIVITY_Pos)
|
dcacheWays.Set((dcacheCcsidr.Get() & SCB_CCSIDR_ASSOCIATIVITY_Msk) >> SCB_CCSIDR_ASSOCIATIVITY_Pos)
|
||||||
for ways.Get() != 0 {
|
for dcacheWays.Get() != 0 {
|
||||||
SystemControl.DCCISW.Set(
|
SystemControl.DCCISW.Set(
|
||||||
((sets.Get() << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) |
|
((dcacheSets.Get() << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) |
|
||||||
((ways.Get() << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk))
|
((dcacheWays.Get() << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk))
|
||||||
ways.Set(ways.Get() - 1)
|
dcacheWays.Set(dcacheWays.Get() - 1)
|
||||||
}
|
}
|
||||||
sets.Set(sets.Get() - 1)
|
dcacheSets.Set(dcacheSets.Get() - 1)
|
||||||
}
|
}
|
||||||
arm.AsmFull(`
|
arm.AsmFull(`
|
||||||
dsb 0xF
|
dsb 0xF
|
||||||
|
|
|
@ -88,15 +88,20 @@ const (
|
||||||
I2C_SCL_PIN = I2C1_SCL_PIN // D19/A5
|
I2C_SCL_PIN = I2C1_SCL_PIN // D19/A5
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Default peripherals
|
||||||
|
var (
|
||||||
|
DefaultUART = UART1
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// register any interrupt handlers for this board's peripherals
|
// register any interrupt handlers for this board's peripherals
|
||||||
UART1.Interrupt = interrupt.New(nxp.IRQ_LPUART6, _UART1.handleInterrupt)
|
_UART1.Interrupt = interrupt.New(nxp.IRQ_LPUART6, _UART1.handleInterrupt)
|
||||||
UART2.Interrupt = interrupt.New(nxp.IRQ_LPUART4, _UART2.handleInterrupt)
|
_UART2.Interrupt = interrupt.New(nxp.IRQ_LPUART4, _UART2.handleInterrupt)
|
||||||
UART3.Interrupt = interrupt.New(nxp.IRQ_LPUART2, _UART3.handleInterrupt)
|
_UART3.Interrupt = interrupt.New(nxp.IRQ_LPUART2, _UART3.handleInterrupt)
|
||||||
UART4.Interrupt = interrupt.New(nxp.IRQ_LPUART3, _UART4.handleInterrupt)
|
_UART4.Interrupt = interrupt.New(nxp.IRQ_LPUART3, _UART4.handleInterrupt)
|
||||||
UART5.Interrupt = interrupt.New(nxp.IRQ_LPUART8, _UART5.handleInterrupt)
|
_UART5.Interrupt = interrupt.New(nxp.IRQ_LPUART8, _UART5.handleInterrupt)
|
||||||
UART6.Interrupt = interrupt.New(nxp.IRQ_LPUART1, _UART6.handleInterrupt)
|
_UART6.Interrupt = interrupt.New(nxp.IRQ_LPUART1, _UART6.handleInterrupt)
|
||||||
UART7.Interrupt = interrupt.New(nxp.IRQ_LPUART7, _UART7.handleInterrupt)
|
_UART7.Interrupt = interrupt.New(nxp.IRQ_LPUART7, _UART7.handleInterrupt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// #=====================================================#
|
// #=====================================================#
|
||||||
|
@ -136,9 +141,8 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
DefaultUART = UART1
|
UART1 = &_UART1
|
||||||
UART1 = &_UART1
|
_UART1 = UART{
|
||||||
_UART1 = UART{
|
|
||||||
Bus: nxp.LPUART6,
|
Bus: nxp.LPUART6,
|
||||||
Buffer: NewRingBuffer(),
|
Buffer: NewRingBuffer(),
|
||||||
txBuffer: NewRingBuffer(),
|
txBuffer: NewRingBuffer(),
|
||||||
|
|
|
@ -33,7 +33,6 @@ type UART struct {
|
||||||
|
|
||||||
// auxiliary state data used internally
|
// auxiliary state data used internally
|
||||||
configured bool
|
configured bool
|
||||||
msbFirst bool
|
|
||||||
transmitting volatile.Register32
|
transmitting volatile.Register32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +45,11 @@ func (uart *UART) resetTransmitting() {
|
||||||
uart.Bus.GLOBAL.ClearBits(nxp.LPUART_GLOBAL_RST)
|
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
|
// Configure initializes a UART with the given UARTConfig and other default
|
||||||
// settings.
|
// settings.
|
||||||
func (uart *UART) Configure(config UARTConfig) {
|
func (uart *UART) Configure(config UARTConfig) {
|
||||||
|
@ -56,13 +60,19 @@ func (uart *UART) Configure(config UARTConfig) {
|
||||||
if config.BaudRate == 0 {
|
if config.BaudRate == 0 {
|
||||||
config.BaudRate = defaultUartFreq
|
config.BaudRate = defaultUartFreq
|
||||||
}
|
}
|
||||||
uart.baud = config.BaudRate
|
|
||||||
|
|
||||||
// use default UART pins if not specified
|
// use default UART pins if not specified
|
||||||
if config.RX == 0 && config.TX == 0 {
|
if config.RX == 0 && config.TX == 0 {
|
||||||
config.RX = UART_RX_PIN
|
config.RX = UART_RX_PIN
|
||||||
config.TX = UART_TX_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.rx = config.RX
|
||||||
uart.tx = config.TX
|
uart.tx = config.TX
|
||||||
|
|
||||||
|
@ -77,9 +87,38 @@ func (uart *UART) Configure(config UARTConfig) {
|
||||||
// reset all internal logic and registers
|
// reset all internal logic and registers
|
||||||
uart.resetTransmitting()
|
uart.resetTransmitting()
|
||||||
|
|
||||||
|
// disable until we have finished configuring registers
|
||||||
|
uart.Bus.CTRL.Set(0)
|
||||||
|
|
||||||
// determine the baud rate and over-sample divisors
|
// determine the baud rate and over-sample divisors
|
||||||
sbr, osr := uart.getBaudRateDivisor(uart.baud)
|
sbr, osr := uart.getBaudRateDivisor(uart.baud)
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
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
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
|
||||||
// for now we assume some configuration. in particular:
|
// for now we assume some configuration. in particular:
|
||||||
// Data bits -> 8-bit
|
// Data bits -> 8-bit
|
||||||
// Parity bit -> None (parity bit generation disabled)
|
// Parity bit -> None (parity bit generation disabled)
|
||||||
|
@ -90,71 +129,16 @@ func (uart *UART) Configure(config UARTConfig) {
|
||||||
// RX RTS enabled -> false
|
// RX RTS enabled -> false
|
||||||
// TX CTS enabled -> false
|
// TX CTS enabled -> false
|
||||||
|
|
||||||
// set the baud rate, over-sample configuration, stop bits
|
// enable transmitter, receiver functions
|
||||||
baudBits := (((osr - 1) << nxp.LPUART_BAUD_OSR_Pos) & nxp.LPUART_BAUD_OSR_Msk) |
|
uart.Bus.CTRL.Set(nxp.LPUART_CTRL_TE | nxp.LPUART_CTRL_RE |
|
||||||
((sbr << nxp.LPUART_BAUD_SBR_Pos) & nxp.LPUART_BAUD_SBR_Msk) |
|
// enable receiver, idle line interrupts
|
||||||
((nxp.LPUART_BAUD_SBNS_SBNS_0 << nxp.LPUART_BAUD_SBNS_Pos) & nxp.LPUART_BAUD_SBNS_Msk)
|
nxp.LPUART_CTRL_RIE | nxp.LPUART_CTRL_ILIE)
|
||||||
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)
|
|
||||||
|
|
||||||
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))
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
|
|
||||||
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))
|
|
||||||
|
|
||||||
// clear all status flags
|
// clear all status flags
|
||||||
stat := uint32(nxp.LPUART_STAT_RXEDGIF_Msk | nxp.LPUART_STAT_IDLE_Msk | nxp.LPUART_STAT_OR_Msk |
|
uart.Bus.STAT.Set(uart.Bus.STAT.Get())
|
||||||
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
|
// enable RX interrupt
|
||||||
if uart.msbFirst {
|
uart.Interrupt.SetPriority(0xC0)
|
||||||
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)
|
|
||||||
|
|
||||||
// enable RX IRQ
|
|
||||||
uart.Interrupt.SetPriority(0xc0)
|
|
||||||
uart.Interrupt.Enable()
|
uart.Interrupt.Enable()
|
||||||
|
|
||||||
uart.configured = true
|
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
|
// corresponding baud rate divisor (1..8191) that best partition a given baud
|
||||||
// rate into equal intervals.
|
// 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:
|
// beginning of:
|
||||||
// void HardwareSerial::begin(uint32_t baud, uint16_t format)
|
// void HardwareSerial::begin(uint32_t baud, uint16_t format)
|
||||||
// (from Teensyduino: `cores/teensy4/HardwareSerial.cpp`)
|
// (from Teensyduino: `cores/teensy4/HardwareSerial.cpp`)
|
||||||
//
|
//
|
||||||
// We don't want to risk using floating point here in the machine package in
|
// We don't want to use floating point here in case it gets called from an ISR
|
||||||
// case it gets called before the FPU or interrupts are ready (e.g., init()).
|
// or very early during system init.
|
||||||
func (uart *UART) getBaudRateDivisor(baudRate uint32) (sbr uint32, osr uint32) {
|
func (uart *UART) getBaudRateDivisor(baudRate uint32) (sbr uint32, osr uint32) {
|
||||||
const clock = 24000000 // UART is muxed to 24 MHz OSC
|
const clock = 24000000 // UART is muxed to 24 MHz OSC
|
||||||
err := uint32(0xFFFFFFFF)
|
err := uint32(0xFFFFFFFF)
|
||||||
|
|
|
@ -8,8 +8,7 @@ MEMORY
|
||||||
|
|
||||||
ENTRY(Reset_Handler);
|
ENTRY(Reset_Handler);
|
||||||
|
|
||||||
_stack_size = 128K;
|
_stack_size = 4K;
|
||||||
_heap_size = 512K;
|
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче