From 5a5d4838ed91219aeea1904c989978dda1e3b564 Mon Sep 17 00:00:00 2001 From: soypat Date: Wed, 12 Jul 2023 18:11:30 -0300 Subject: [PATCH 1/8] add gosched calls to UART --- src/machine/machine_rp2040_uart.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/machine/machine_rp2040_uart.go b/src/machine/machine_rp2040_uart.go index e5e4f77de3..8f7ffc03ef 100644 --- a/src/machine/machine_rp2040_uart.go +++ b/src/machine/machine_rp2040_uart.go @@ -89,10 +89,16 @@ func (uart *UART) SetBaudRate(br uint32) { func (uart *UART) WriteByte(c byte) error { // wait until buffer is not full for uart.Bus.UARTFR.HasBits(rp.UART0_UARTFR_TXFF) { + gosched() } // write data uart.Bus.UARTDR.Set(uint32(c)) + + // wait until done transmitting. + for uart.Bus.UARTFR.HasBits(rp.UART0_UARTFR_BUSY) { + gosched() + } return nil } From c477c01c0fa35a3815ec6d92b0c9d443fd20ee6f Mon Sep 17 00:00:00 2001 From: soypat Date: Wed, 12 Jul 2023 18:27:04 -0300 Subject: [PATCH 2/8] add UART.flush() stubs for all supported architectures --- src/machine/machine_atmega.go | 2 ++ src/machine/machine_atsamd21.go | 2 ++ src/machine/machine_atsamd51.go | 2 ++ src/machine/machine_esp32.go | 2 ++ src/machine/machine_esp32c3.go | 2 ++ src/machine/machine_esp8266.go | 2 ++ src/machine/machine_k210.go | 2 ++ src/machine/machine_mimxrt1062_uart.go | 2 ++ src/machine/machine_nrf.go | 2 ++ src/machine/machine_nxpmk66f18_uart.go | 2 ++ src/machine/machine_rp2040_uart.go | 5 +++-- src/machine/machine_stm32_uart.go | 2 ++ src/machine/uart.go | 1 + 13 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/machine/machine_atmega.go b/src/machine/machine_atmega.go index 90977fb877..2c5e13033e 100644 --- a/src/machine/machine_atmega.go +++ b/src/machine/machine_atmega.go @@ -198,6 +198,8 @@ func (uart *UART) WriteByte(c byte) error { return nil } +func (uart *UART) flush() {} + // SPIConfig is used to store config info for SPI. type SPIConfig struct { Frequency uint32 diff --git a/src/machine/machine_atsamd21.go b/src/machine/machine_atsamd21.go index 59df853e5c..f18eb21415 100644 --- a/src/machine/machine_atsamd21.go +++ b/src/machine/machine_atsamd21.go @@ -634,6 +634,8 @@ func (uart *UART) WriteByte(c byte) error { return nil } +func (uart *UART) flush() {} + // handleInterrupt should be called from the appropriate interrupt handler for // this UART instance. func (uart *UART) handleInterrupt(interrupt.Interrupt) { diff --git a/src/machine/machine_atsamd51.go b/src/machine/machine_atsamd51.go index de5491c884..a1182fd8fd 100644 --- a/src/machine/machine_atsamd51.go +++ b/src/machine/machine_atsamd51.go @@ -1122,6 +1122,8 @@ func (uart *UART) WriteByte(c byte) error { return nil } +func (uart *UART) flush() {} + func (uart *UART) handleInterrupt(interrupt.Interrupt) { // should reset IRQ uart.Receive(byte((uart.Bus.DATA.Get() & 0xFF))) diff --git a/src/machine/machine_esp32.go b/src/machine/machine_esp32.go index b58cef66ae..88c5bf2906 100644 --- a/src/machine/machine_esp32.go +++ b/src/machine/machine_esp32.go @@ -324,6 +324,8 @@ func (uart *UART) WriteByte(b byte) error { return nil } +func (uart *UART) flush() {} + // Serial Peripheral Interface on the ESP32. type SPI struct { Bus *esp.SPI_Type diff --git a/src/machine/machine_esp32c3.go b/src/machine/machine_esp32c3.go index f1f646fd5e..89a64f5dba 100644 --- a/src/machine/machine_esp32c3.go +++ b/src/machine/machine_esp32c3.go @@ -502,3 +502,5 @@ func (uart *UART) WriteByte(b byte) error { uart.Bus.FIFO.Set(uint32(b)) return nil } + +func (uart *UART) flush() {} diff --git a/src/machine/machine_esp8266.go b/src/machine/machine_esp8266.go index 37ab29a17d..1173db7f48 100644 --- a/src/machine/machine_esp8266.go +++ b/src/machine/machine_esp8266.go @@ -190,3 +190,5 @@ func (uart *UART) WriteByte(c byte) error { esp.UART0.UART_FIFO.Set(uint32(c)) return nil } + +func (uart *UART) flush() {} diff --git a/src/machine/machine_k210.go b/src/machine/machine_k210.go index 9c63a8f766..63c4cce858 100644 --- a/src/machine/machine_k210.go +++ b/src/machine/machine_k210.go @@ -399,6 +399,8 @@ func (uart *UART) WriteByte(c byte) { uart.Bus.TXDATA.Set(uint32(c)) } +func (uart *UART) flush() {} + type SPI struct { Bus *kendryte.SPI_Type } diff --git a/src/machine/machine_mimxrt1062_uart.go b/src/machine/machine_mimxrt1062_uart.go index d24206dfb9..ed4539f734 100644 --- a/src/machine/machine_mimxrt1062_uart.go +++ b/src/machine/machine_mimxrt1062_uart.go @@ -181,6 +181,8 @@ func (uart *UART) WriteByte(c byte) error { return nil } +func (uart *UART) flush() {} + // getBaudRateDivisor finds the greatest over-sampling factor (4..32) and // corresponding baud rate divisor (1..8191) that best partition a given baud // rate into equal intervals. diff --git a/src/machine/machine_nrf.go b/src/machine/machine_nrf.go index 83fa57b3e9..61747f2cb2 100644 --- a/src/machine/machine_nrf.go +++ b/src/machine/machine_nrf.go @@ -194,6 +194,8 @@ func (uart *UART) WriteByte(c byte) error { return nil } +func (uart *UART) flush() {} + func (uart *UART) handleInterrupt(interrupt.Interrupt) { if nrf.UART0.EVENTS_RXDRDY.Get() != 0 { uart.Receive(byte(nrf.UART0.RXD.Get())) diff --git a/src/machine/machine_nxpmk66f18_uart.go b/src/machine/machine_nxpmk66f18_uart.go index d62fc64e01..bbd225704c 100644 --- a/src/machine/machine_nxpmk66f18_uart.go +++ b/src/machine/machine_nxpmk66f18_uart.go @@ -305,3 +305,5 @@ func (u *UART) WriteByte(c byte) error { u.C2.Set(uartC2TXActive) return nil } + +func (uart *UART) flush() {} diff --git a/src/machine/machine_rp2040_uart.go b/src/machine/machine_rp2040_uart.go index 8f7ffc03ef..378a557550 100644 --- a/src/machine/machine_rp2040_uart.go +++ b/src/machine/machine_rp2040_uart.go @@ -94,12 +94,13 @@ func (uart *UART) WriteByte(c byte) error { // write data uart.Bus.UARTDR.Set(uint32(c)) + return nil +} - // wait until done transmitting. +func (uart *UART) flush() { for uart.Bus.UARTFR.HasBits(rp.UART0_UARTFR_BUSY) { gosched() } - return nil } // SetFormat for number of data bits, stop bits, and parity for the UART. diff --git a/src/machine/machine_stm32_uart.go b/src/machine/machine_stm32_uart.go index 6ae6f0f994..ec3ff8ea6c 100644 --- a/src/machine/machine_stm32_uart.go +++ b/src/machine/machine_stm32_uart.go @@ -81,3 +81,5 @@ func (uart *UART) WriteByte(c byte) error { } return nil } + +func (uart *UART) flush() {} diff --git a/src/machine/uart.go b/src/machine/uart.go index 37d3223324..a5641cfe86 100644 --- a/src/machine/uart.go +++ b/src/machine/uart.go @@ -64,6 +64,7 @@ func (uart *UART) Write(data []byte) (n int, err error) { for _, v := range data { uart.WriteByte(v) } + uart.flush() return len(data), nil } From fc92b05ecfcf8b74d20a4c7014c048b4eb20d1a9 Mon Sep 17 00:00:00 2001 From: soypat Date: Wed, 12 Jul 2023 18:29:03 -0300 Subject: [PATCH 3/8] add comment un uart.go on flush functionality --- src/machine/uart.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/uart.go b/src/machine/uart.go index a5641cfe86..5612e02caa 100644 --- a/src/machine/uart.go +++ b/src/machine/uart.go @@ -64,7 +64,7 @@ func (uart *UART) Write(data []byte) (n int, err error) { for _, v := range data { uart.WriteByte(v) } - uart.flush() + uart.flush() // flush() blocks until all data has been transmitted. return len(data), nil } From 59640e445ce7416e31a486845d4896b5a4479e2d Mon Sep 17 00:00:00 2001 From: soypat Date: Wed, 12 Jul 2023 23:01:39 -0300 Subject: [PATCH 4/8] uart.writeByte as base of UART usage --- src/machine/machine_atmega.go | 2 +- src/machine/machine_atsamd21.go | 2 +- src/machine/machine_atsamd51.go | 2 +- src/machine/machine_esp32.go | 2 +- src/machine/machine_esp32c3.go | 2 +- src/machine/machine_esp8266.go | 4 ++-- src/machine/machine_fe310.go | 2 +- src/machine/machine_k210.go | 2 +- src/machine/machine_mimxrt1062_uart.go | 2 +- src/machine/machine_nrf.go | 2 +- src/machine/machine_rp2040_uart.go | 2 +- src/machine/machine_stm32_uart.go | 2 +- src/machine/uart.go | 12 +++++++++++- 13 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/machine/machine_atmega.go b/src/machine/machine_atmega.go index 2c5e13033e..3a73028c5d 100644 --- a/src/machine/machine_atmega.go +++ b/src/machine/machine_atmega.go @@ -190,7 +190,7 @@ func (uart *UART) handleInterrupt(intr interrupt.Interrupt) { } // WriteByte writes a byte of data to the UART. -func (uart *UART) WriteByte(c byte) error { +func (uart *UART) writeByte(c byte) error { // Wait until UART buffer is not busy. for !uart.statusRegA.HasBits(avr.UCSR0A_UDRE0) { } diff --git a/src/machine/machine_atsamd21.go b/src/machine/machine_atsamd21.go index f18eb21415..443c7af56a 100644 --- a/src/machine/machine_atsamd21.go +++ b/src/machine/machine_atsamd21.go @@ -626,7 +626,7 @@ func (uart *UART) SetBaudRate(br uint32) { } // WriteByte writes a byte of data to the UART. -func (uart *UART) WriteByte(c byte) error { +func (uart *UART) writeByte(c byte) error { // wait until ready to receive for !uart.Bus.INTFLAG.HasBits(sam.SERCOM_USART_INTFLAG_DRE) { } diff --git a/src/machine/machine_atsamd51.go b/src/machine/machine_atsamd51.go index a1182fd8fd..7c4c4d07c7 100644 --- a/src/machine/machine_atsamd51.go +++ b/src/machine/machine_atsamd51.go @@ -1114,7 +1114,7 @@ func (uart *UART) SetBaudRate(br uint32) { } // WriteByte writes a byte of data to the UART. -func (uart *UART) WriteByte(c byte) error { +func (uart *UART) writeByte(c byte) error { // wait until ready to receive for !uart.Bus.INTFLAG.HasBits(sam.SERCOM_USART_INT_INTFLAG_DRE) { } diff --git a/src/machine/machine_esp32.go b/src/machine/machine_esp32.go index 88c5bf2906..4491b3dd95 100644 --- a/src/machine/machine_esp32.go +++ b/src/machine/machine_esp32.go @@ -314,7 +314,7 @@ func (uart *UART) Configure(config UARTConfig) { uart.Bus.CLKDIV.Set(peripheralClock / config.BaudRate) } -func (uart *UART) WriteByte(b byte) error { +func (uart *UART) writeByte(b byte) error { for (uart.Bus.STATUS.Get()>>16)&0xff >= 128 { // Read UART_TXFIFO_CNT from the status register, which indicates how // many bytes there are in the transmit buffer. Wait until there are diff --git a/src/machine/machine_esp32c3.go b/src/machine/machine_esp32c3.go index 89a64f5dba..e447e4fe0d 100644 --- a/src/machine/machine_esp32c3.go +++ b/src/machine/machine_esp32c3.go @@ -493,7 +493,7 @@ func (uart *UART) enableReceiver() { uart.Bus.SetINT_ENA_RXFIFO_OVF_INT_ENA(1) } -func (uart *UART) WriteByte(b byte) error { +func (uart *UART) writeByte(b byte) error { for (uart.Bus.STATUS.Get()&esp.UART_STATUS_TXFIFO_CNT_Msk)>>esp.UART_STATUS_TXFIFO_CNT_Pos >= 128 { // Read UART_TXFIFO_CNT from the status register, which indicates how // many bytes there are in the transmit buffer. Wait until there are diff --git a/src/machine/machine_esp8266.go b/src/machine/machine_esp8266.go index 1173db7f48..4edd4a535f 100644 --- a/src/machine/machine_esp8266.go +++ b/src/machine/machine_esp8266.go @@ -181,9 +181,9 @@ func (uart *UART) Configure(config UARTConfig) { esp.UART0.UART_CLKDIV.Set(CPUFrequency() / config.BaudRate) } -// WriteByte writes a single byte to the output buffer. Note that the hardware +// writeByte writes a single byte to the output buffer. Note that the hardware // includes a buffer of 128 bytes which will be used first. -func (uart *UART) WriteByte(c byte) error { +func (uart *UART) writeByte(c byte) error { for (esp.UART0.UART_STATUS.Get()>>16)&0xff >= 128 { // Wait until the TX buffer has room. } diff --git a/src/machine/machine_fe310.go b/src/machine/machine_fe310.go index 3a0c451349..efe94cbe47 100644 --- a/src/machine/machine_fe310.go +++ b/src/machine/machine_fe310.go @@ -111,7 +111,7 @@ func (uart *UART) handleInterrupt(interrupt.Interrupt) { uart.Receive(c) } -func (uart *UART) WriteByte(c byte) { +func (uart *UART) writeByte(c byte) { for sifive.UART0.TXDATA.Get()&sifive.UART_TXDATA_FULL != 0 { } diff --git a/src/machine/machine_k210.go b/src/machine/machine_k210.go index 63c4cce858..22dc2883ef 100644 --- a/src/machine/machine_k210.go +++ b/src/machine/machine_k210.go @@ -392,7 +392,7 @@ func (uart *UART) handleInterrupt(interrupt.Interrupt) { uart.Receive(c) } -func (uart *UART) WriteByte(c byte) { +func (uart *UART) writeByte(c byte) { for uart.Bus.TXDATA.Get()&kendryte.UARTHS_TXDATA_FULL != 0 { } diff --git a/src/machine/machine_mimxrt1062_uart.go b/src/machine/machine_mimxrt1062_uart.go index ed4539f734..6265b85656 100644 --- a/src/machine/machine_mimxrt1062_uart.go +++ b/src/machine/machine_mimxrt1062_uart.go @@ -173,7 +173,7 @@ func (uart *UART) Sync() error { } // WriteByte writes a single byte of data to the UART interface. -func (uart *UART) WriteByte(c byte) error { +func (uart *UART) writeByte(c byte) error { uart.startTransmitting() for !uart.txBuffer.Put(c) { } diff --git a/src/machine/machine_nrf.go b/src/machine/machine_nrf.go index 61747f2cb2..346a0bb2e9 100644 --- a/src/machine/machine_nrf.go +++ b/src/machine/machine_nrf.go @@ -186,7 +186,7 @@ func (uart *UART) SetBaudRate(br uint32) { } // WriteByte writes a byte of data to the UART. -func (uart *UART) WriteByte(c byte) error { +func (uart *UART) writeByte(c byte) error { nrf.UART0.EVENTS_TXDRDY.Set(0) nrf.UART0.TXD.Set(uint32(c)) for nrf.UART0.EVENTS_TXDRDY.Get() == 0 { diff --git a/src/machine/machine_rp2040_uart.go b/src/machine/machine_rp2040_uart.go index 378a557550..1d927df128 100644 --- a/src/machine/machine_rp2040_uart.go +++ b/src/machine/machine_rp2040_uart.go @@ -86,7 +86,7 @@ func (uart *UART) SetBaudRate(br uint32) { } // WriteByte writes a byte of data to the UART. -func (uart *UART) WriteByte(c byte) error { +func (uart *UART) writeByte(c byte) error { // wait until buffer is not full for uart.Bus.UARTFR.HasBits(rp.UART0_UARTFR_TXFF) { gosched() diff --git a/src/machine/machine_stm32_uart.go b/src/machine/machine_stm32_uart.go index ec3ff8ea6c..6e8806c876 100644 --- a/src/machine/machine_stm32_uart.go +++ b/src/machine/machine_stm32_uart.go @@ -74,7 +74,7 @@ func (uart *UART) SetBaudRate(br uint32) { } // WriteByte writes a byte of data to the UART. -func (uart *UART) WriteByte(c byte) error { +func (uart *UART) writeByte(c byte) error { uart.txReg.Set(uint32(c)) for !uart.statusReg.HasBits(uart.txEmptyFlag) { diff --git a/src/machine/uart.go b/src/machine/uart.go index 5612e02caa..7b505700cc 100644 --- a/src/machine/uart.go +++ b/src/machine/uart.go @@ -59,10 +59,20 @@ func (uart *UART) Read(data []byte) (n int, err error) { return size, nil } +// WriteByte writes a byte of data to the UART. +func (uart *UART) WriteByte(c byte) error { + err := uart.writeByte(c) + if err != nil { + return err + } + uart.flush() // flush() blocks until all data has been transmitted. + return nil +} + // Write data to the UART. func (uart *UART) Write(data []byte) (n int, err error) { for _, v := range data { - uart.WriteByte(v) + uart.writeByte(v) } uart.flush() // flush() blocks until all data has been transmitted. return len(data), nil From e0a84caf6002647af6e2801aff3c9edadb8bd639 Mon Sep 17 00:00:00 2001 From: soypat Date: Wed, 12 Jul 2023 23:25:15 -0300 Subject: [PATCH 5/8] fix NXP having duplicate WriteByte --- src/machine/machine_nxpmk66f18_uart.go | 2 +- src/machine/uart.go | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/machine/machine_nxpmk66f18_uart.go b/src/machine/machine_nxpmk66f18_uart.go index bbd225704c..a14d18f5ef 100644 --- a/src/machine/machine_nxpmk66f18_uart.go +++ b/src/machine/machine_nxpmk66f18_uart.go @@ -292,7 +292,7 @@ func (u *UART) handleStatusInterrupt(interrupt.Interrupt) { } // WriteByte writes a byte of data to the UART. -func (u *UART) WriteByte(c byte) error { +func (u *UART) writeByte(c byte) error { if !u.Configured { return ErrNotConfigured } diff --git a/src/machine/uart.go b/src/machine/uart.go index 7b505700cc..c6307f41c8 100644 --- a/src/machine/uart.go +++ b/src/machine/uart.go @@ -59,7 +59,8 @@ func (uart *UART) Read(data []byte) (n int, err error) { return size, nil } -// WriteByte writes a byte of data to the UART. +// WriteByte writes a byte of data over the UART's Tx. +// This function blocks until the data is finished being sent. func (uart *UART) WriteByte(c byte) error { err := uart.writeByte(c) if err != nil { @@ -69,7 +70,8 @@ func (uart *UART) WriteByte(c byte) error { return nil } -// Write data to the UART. +// Write data over the UART's Tx. +// This function blocks until the data is finished being sent. func (uart *UART) Write(data []byte) (n int, err error) { for _, v := range data { uart.writeByte(v) From 1b729a10c0bfad101110ef5dff1a34162ba79292 Mon Sep 17 00:00:00 2001 From: soypat Date: Thu, 13 Jul 2023 19:28:40 -0300 Subject: [PATCH 6/8] fix writeByte not returning error on some platforms --- src/machine/machine_atmega.go | 3 ++- src/machine/machine_fe310.go | 3 ++- src/machine/machine_k210.go | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/machine/machine_atmega.go b/src/machine/machine_atmega.go index 3a73028c5d..81a47c0dfa 100644 --- a/src/machine/machine_atmega.go +++ b/src/machine/machine_atmega.go @@ -97,7 +97,7 @@ func (i2c *I2C) stop() { } // writeByte writes a single byte to the I2C bus. -func (i2c *I2C) writeByte(data byte) { +func (i2c *I2C) writeByte(data byte) error { // Write data to register. avr.TWDR.Set(data) @@ -107,6 +107,7 @@ func (i2c *I2C) writeByte(data byte) { // Wait till data is transmitted. for !avr.TWCR.HasBits(avr.TWCR_TWINT) { } + return nil } // readByte reads a single byte from the I2C bus. diff --git a/src/machine/machine_fe310.go b/src/machine/machine_fe310.go index efe94cbe47..8bd4661f4c 100644 --- a/src/machine/machine_fe310.go +++ b/src/machine/machine_fe310.go @@ -111,11 +111,12 @@ func (uart *UART) handleInterrupt(interrupt.Interrupt) { uart.Receive(c) } -func (uart *UART) writeByte(c byte) { +func (uart *UART) writeByte(c byte) error { for sifive.UART0.TXDATA.Get()&sifive.UART_TXDATA_FULL != 0 { } sifive.UART0.TXDATA.Set(uint32(c)) + return nil } // SPI on the FE310. The normal SPI0 is actually a quad-SPI meant for flash, so it is best diff --git a/src/machine/machine_k210.go b/src/machine/machine_k210.go index 22dc2883ef..e8a304c850 100644 --- a/src/machine/machine_k210.go +++ b/src/machine/machine_k210.go @@ -392,11 +392,12 @@ func (uart *UART) handleInterrupt(interrupt.Interrupt) { uart.Receive(c) } -func (uart *UART) writeByte(c byte) { +func (uart *UART) writeByte(c byte) error { for uart.Bus.TXDATA.Get()&kendryte.UARTHS_TXDATA_FULL != 0 { } uart.Bus.TXDATA.Set(uint32(c)) + return nil } func (uart *UART) flush() {} From 90cbe52f4290223174001fbf9ae9e68d3b652f90 Mon Sep 17 00:00:00 2001 From: soypat Date: Thu, 13 Jul 2023 19:53:08 -0300 Subject: [PATCH 7/8] add flush method for fe310 device --- src/machine/machine_fe310.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/machine/machine_fe310.go b/src/machine/machine_fe310.go index 8bd4661f4c..85a2c5bd37 100644 --- a/src/machine/machine_fe310.go +++ b/src/machine/machine_fe310.go @@ -119,6 +119,8 @@ func (uart *UART) writeByte(c byte) error { return nil } +func (uart *UART) flush() {} + // SPI on the FE310. The normal SPI0 is actually a quad-SPI meant for flash, so it is best // to use SPI1 or SPI2 port for most applications. type SPI struct { From c84bdd05b8b13eab98a762549aa9d6252a138590 Mon Sep 17 00:00:00 2001 From: soypat Date: Fri, 14 Jul 2023 18:58:39 -0300 Subject: [PATCH 8/8] check for error in WriteByte call to writeByte --- src/machine/uart.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/machine/uart.go b/src/machine/uart.go index c6307f41c8..eeeb7d6a0b 100644 --- a/src/machine/uart.go +++ b/src/machine/uart.go @@ -73,8 +73,11 @@ func (uart *UART) WriteByte(c byte) error { // Write data over the UART's Tx. // This function blocks until the data is finished being sent. func (uart *UART) Write(data []byte) (n int, err error) { - for _, v := range data { - uart.writeByte(v) + for i, v := range data { + err = uart.writeByte(v) + if err != nil { + return i, err + } } uart.flush() // flush() blocks until all data has been transmitted. return len(data), nil