From 39805bca4598e3a3ad312a388a008c8d9f989eb2 Mon Sep 17 00:00:00 2001 From: sago35 Date: Tue, 29 Mar 2022 08:25:04 +0900 Subject: [PATCH] os, runtime: enable os.Stdin for baremetal target --- Makefile | 2 ++ src/examples/echo2/echo2.go | 31 +++++++++++++++++++++++++ src/os/file_other.go | 30 ++++++++++++++++++++++-- src/runtime/runtime_arm7tdmi.go | 10 ++++++++ src/runtime/runtime_atmega.go | 12 ++++++++++ src/runtime/runtime_atsamd21.go | 12 ++++++++++ src/runtime/runtime_atsamd51.go | 12 ++++++++++ src/runtime/runtime_attiny.go | 10 ++++++++ src/runtime/runtime_cortexm_qemu.go | 10 ++++++++ src/runtime/runtime_esp32xx.go | 12 ++++++++++ src/runtime/runtime_esp8266.go | 12 ++++++++++ src/runtime/runtime_fe310.go | 12 ++++++++++ src/runtime/runtime_k210.go | 12 ++++++++++ src/runtime/runtime_mimxrt1062.go | 12 ++++++++++ src/runtime/runtime_nrf.go | 12 ++++++++++ src/runtime/runtime_nxpmk66f18.go | 10 ++++++++ src/runtime/runtime_rp2040.go | 12 ++++++++++ src/runtime/runtime_stm32f103.go | 12 ++++++++++ src/runtime/runtime_stm32f4.go | 12 ++++++++++ src/runtime/runtime_stm32f405.go | 12 ++++++++++ src/runtime/runtime_stm32f7x2.go | 12 ++++++++++ src/runtime/runtime_stm32l0.go | 12 ++++++++++ src/runtime/runtime_stm32l4.go | 12 ++++++++++ src/runtime/runtime_stm32l5x2.go | 12 ++++++++++ src/runtime/runtime_stm32wlx.go | 12 ++++++++++ src/runtime/runtime_tinygoriscv_qemu.go | 10 ++++++++ 26 files changed, 327 insertions(+), 2 deletions(-) create mode 100644 src/examples/echo2/echo2.go diff --git a/Makefile b/Makefile index b23cc069..c5afd2bb 100644 --- a/Makefile +++ b/Makefile @@ -396,6 +396,8 @@ smoketest: @$(MD5SUM) test.hex $(TINYGO) build -size short -o test.hex -target=pca10040 examples/echo @$(MD5SUM) test.hex + $(TINYGO) build -size short -o test.hex -target=pca10040 examples/echo2 + @$(MD5SUM) test.hex $(TINYGO) build -size short -o test.hex -target=circuitplay-express examples/i2s @$(MD5SUM) test.hex $(TINYGO) build -size short -o test.hex -target=pca10040 examples/mcp3008 diff --git a/src/examples/echo2/echo2.go b/src/examples/echo2/echo2.go new file mode 100644 index 00000000..6b4c1528 --- /dev/null +++ b/src/examples/echo2/echo2.go @@ -0,0 +1,31 @@ +// This is a echo console running on the os.Stdin and os.Stdout. +// Stdin and os.Stdout are connected to machine.Serial in the baremetal target. +// +// Serial can be switched with the -serial option as follows +// 1. tinygo flash -target wioterminal -serial usb examples/echo2 +// 2. tinygo flash -target wioterminal -serial uart examples/echo2 +// +// This example will also work with standard Go. +package main + +import ( + "bufio" + "fmt" + "os" +) + +func main() { + fmt.Printf("Echo console enabled. Type something then press enter:\r\n") + + scanner := bufio.NewScanner(os.Stdin) + + for { + msg := "" + fmt.Scanf("%s\n", &msg) + fmt.Printf("You typed (scanf) : %s\r\n", msg) + + if scanner.Scan() { + fmt.Printf("You typed (scanner) : %s\r\n", scanner.Text()) + } + } +} diff --git a/src/os/file_other.go b/src/os/file_other.go index 036ddf69..82c84e95 100644 --- a/src/os/file_other.go +++ b/src/os/file_other.go @@ -38,9 +38,26 @@ func NewFile(fd uintptr, name string) *File { return &File{&file{stdioFileHandle(fd), name}} } -// Read is unsupported on this system. +// Read reads up to len(b) bytes from machine.Serial. +// It returns the number of bytes read and any error encountered. func (f stdioFileHandle) Read(b []byte) (n int, err error) { - return 0, ErrUnsupported + if len(b) == 0 { + return 0, nil + } + + size := buffered() + for size == 0 { + gosched() + size = buffered() + } + + if size > len(b) { + size = len(b) + } + for i := 0; i < size; i++ { + b[i] = getchar() + } + return size, nil } func (f stdioFileHandle) ReadAt(b []byte, off int64) (n int, err error) { @@ -78,6 +95,15 @@ func (f stdioFileHandle) Fd() uintptr { //go:linkname putchar runtime.putchar func putchar(c byte) +//go:linkname getchar runtime.getchar +func getchar() byte + +//go:linkname buffered runtime.buffered +func buffered() int + +//go:linkname gosched runtime.Gosched +func gosched() int + func Pipe() (r *File, w *File, err error) { return nil, nil, ErrNotImplemented } diff --git a/src/runtime/runtime_arm7tdmi.go b/src/runtime/runtime_arm7tdmi.go index 61b67264..10baa671 100644 --- a/src/runtime/runtime_arm7tdmi.go +++ b/src/runtime/runtime_arm7tdmi.go @@ -14,6 +14,16 @@ func putchar(c byte) { // dummy, TODO } +func getchar() byte { + // dummy, TODO + return 0 +} + +func buffered() int { + // dummy, TODO + return 0 +} + //go:extern _sbss var _sbss [0]byte diff --git a/src/runtime/runtime_atmega.go b/src/runtime/runtime_atmega.go index b62a50a0..f4391ead 100644 --- a/src/runtime/runtime_atmega.go +++ b/src/runtime/runtime_atmega.go @@ -16,6 +16,18 @@ func putchar(c byte) { machine.Serial.WriteByte(c) } +func getchar() byte { + for machine.Serial.Buffered() == 0 { + Gosched() + } + v, _ := machine.Serial.ReadByte() + return v +} + +func buffered() int { + return machine.Serial.Buffered() +} + // Sleep for a given period. The period is defined by the WDT peripheral, and is // on most chips (at least) 3 bits wide, in powers of two from 16ms to 2s // (0=16ms, 1=32ms, 2=64ms...). Note that the WDT is not very accurate: it can diff --git a/src/runtime/runtime_atsamd21.go b/src/runtime/runtime_atsamd21.go index 8888a711..69468655 100644 --- a/src/runtime/runtime_atsamd21.go +++ b/src/runtime/runtime_atsamd21.go @@ -39,6 +39,18 @@ func putchar(c byte) { machine.Serial.WriteByte(c) } +func getchar() byte { + for machine.Serial.Buffered() == 0 { + Gosched() + } + v, _ := machine.Serial.ReadByte() + return v +} + +func buffered() int { + return machine.Serial.Buffered() +} + func initClocks() { // Set 1 Flash Wait State for 48MHz, required for 3.3V operation according to SAMD21 Datasheet sam.NVMCTRL.CTRLB.SetBits(sam.NVMCTRL_CTRLB_RWS_HALF << sam.NVMCTRL_CTRLB_RWS_Pos) diff --git a/src/runtime/runtime_atsamd51.go b/src/runtime/runtime_atsamd51.go index a2438bac..8c7282fa 100644 --- a/src/runtime/runtime_atsamd51.go +++ b/src/runtime/runtime_atsamd51.go @@ -39,6 +39,18 @@ func putchar(c byte) { machine.Serial.WriteByte(c) } +func getchar() byte { + for machine.Serial.Buffered() == 0 { + Gosched() + } + v, _ := machine.Serial.ReadByte() + return v +} + +func buffered() int { + return machine.Serial.Buffered() +} + func initClocks() { // set flash wait state sam.NVMCTRL.CTRLA.SetBits(0 << sam.NVMCTRL_CTRLA_RWS_Pos) diff --git a/src/runtime/runtime_attiny.go b/src/runtime/runtime_attiny.go index 7683fcac..bb196840 100644 --- a/src/runtime/runtime_attiny.go +++ b/src/runtime/runtime_attiny.go @@ -14,6 +14,16 @@ func putchar(c byte) { // UART is not supported. } +func getchar() byte { + // UART is not supported. + return 0 +} + +func buffered() int { + // UART is not supported. + return 0 +} + func sleepWDT(period uint8) { // TODO: use the watchdog timer instead of a busy loop. for i := 0x45; i != 0; i-- { diff --git a/src/runtime/runtime_cortexm_qemu.go b/src/runtime/runtime_cortexm_qemu.go index 5f37b062..458b9764 100644 --- a/src/runtime/runtime_cortexm_qemu.go +++ b/src/runtime/runtime_cortexm_qemu.go @@ -49,6 +49,16 @@ func putchar(c byte) { stdoutWrite.Set(uint8(c)) } +func getchar() byte { + // dummy, TODO + return 0 +} + +func buffered() int { + // dummy, TODO + return 0 +} + func waitForEvents() { arm.Asm("wfe") } diff --git a/src/runtime/runtime_esp32xx.go b/src/runtime/runtime_esp32xx.go index 79507a51..08370f72 100644 --- a/src/runtime/runtime_esp32xx.go +++ b/src/runtime/runtime_esp32xx.go @@ -15,6 +15,18 @@ func putchar(c byte) { machine.Serial.WriteByte(c) } +func getchar() byte { + for machine.Serial.Buffered() == 0 { + Gosched() + } + v, _ := machine.Serial.ReadByte() + return v +} + +func buffered() int { + return machine.Serial.Buffered() +} + // Initialize .bss: zero-initialized global variables. // The .data section has already been loaded by the ROM bootloader. func clearbss() { diff --git a/src/runtime/runtime_esp8266.go b/src/runtime/runtime_esp8266.go index 7ec75c82..57a76bd5 100644 --- a/src/runtime/runtime_esp8266.go +++ b/src/runtime/runtime_esp8266.go @@ -18,6 +18,18 @@ func putchar(c byte) { machine.Serial.WriteByte(c) } +func getchar() byte { + for machine.Serial.Buffered() == 0 { + Gosched() + } + v, _ := machine.Serial.ReadByte() + return v +} + +func buffered() int { + return machine.Serial.Buffered() +} + // Write to the internal control bus (using I2C?). // Signature found here: // https://github.com/espressif/ESP8266_RTOS_SDK/blob/14171de0/components/esp8266/include/esp8266/rom_functions.h#L54 diff --git a/src/runtime/runtime_fe310.go b/src/runtime/runtime_fe310.go index 5999396b..15dfe093 100644 --- a/src/runtime/runtime_fe310.go +++ b/src/runtime/runtime_fe310.go @@ -99,6 +99,18 @@ func putchar(c byte) { machine.Serial.WriteByte(c) } +func getchar() byte { + for machine.Serial.Buffered() == 0 { + Gosched() + } + v, _ := machine.Serial.ReadByte() + return v +} + +func buffered() int { + return machine.Serial.Buffered() +} + var timerWakeup volatile.Register8 func ticks() timeUnit { diff --git a/src/runtime/runtime_k210.go b/src/runtime/runtime_k210.go index 6cdea759..a49867bb 100644 --- a/src/runtime/runtime_k210.go +++ b/src/runtime/runtime_k210.go @@ -111,6 +111,18 @@ func putchar(c byte) { machine.Serial.WriteByte(c) } +func getchar() byte { + for machine.Serial.Buffered() == 0 { + Gosched() + } + v, _ := machine.Serial.ReadByte() + return v +} + +func buffered() int { + return machine.Serial.Buffered() +} + var timerWakeup volatile.Register8 func ticks() timeUnit { diff --git a/src/runtime/runtime_mimxrt1062.go b/src/runtime/runtime_mimxrt1062.go index fc0ec353..d777a65c 100644 --- a/src/runtime/runtime_mimxrt1062.go +++ b/src/runtime/runtime_mimxrt1062.go @@ -126,6 +126,18 @@ func putchar(c byte) { machine.Serial.WriteByte(c) } +func getchar() byte { + for machine.UART1.Buffered() == 0 { + Gosched() + } + v, _ := machine.UART1.ReadByte() + return v +} + +func buffered() int { + return machine.UART1.Buffered() +} + func exit(code int) { abort() } diff --git a/src/runtime/runtime_nrf.go b/src/runtime/runtime_nrf.go index 9da4caf3..7ee34f8b 100644 --- a/src/runtime/runtime_nrf.go +++ b/src/runtime/runtime_nrf.go @@ -66,6 +66,18 @@ func putchar(c byte) { machine.Serial.WriteByte(c) } +func getchar() byte { + for machine.Serial.Buffered() == 0 { + Gosched() + } + v, _ := machine.Serial.ReadByte() + return v +} + +func buffered() int { + return machine.Serial.Buffered() +} + func sleepTicks(d timeUnit) { for d != 0 { ticks := uint32(d) & 0x7fffff // 23 bits (to be on the safe side) diff --git a/src/runtime/runtime_nxpmk66f18.go b/src/runtime/runtime_nxpmk66f18.go index 05643d71..28c019e5 100644 --- a/src/runtime/runtime_nxpmk66f18.go +++ b/src/runtime/runtime_nxpmk66f18.go @@ -231,6 +231,16 @@ func putchar(c byte) { machine.PutcharUART(machine.UART0, c) } +func getchar() byte { + // dummy, TODO + return 0 +} + +func buffered() int { + // dummy, TODO + return 0 +} + func exit(code int) { abort() } diff --git a/src/runtime/runtime_rp2040.go b/src/runtime/runtime_rp2040.go index 0d4db365..c6bc0d79 100644 --- a/src/runtime/runtime_rp2040.go +++ b/src/runtime/runtime_rp2040.go @@ -58,6 +58,18 @@ func putchar(c byte) { machine.Serial.WriteByte(c) } +func getchar() byte { + for machine.Serial.Buffered() == 0 { + Gosched() + } + v, _ := machine.Serial.ReadByte() + return v +} + +func buffered() int { + return machine.Serial.Buffered() +} + // machineInit is provided by package machine. func machineInit() diff --git a/src/runtime/runtime_stm32f103.go b/src/runtime/runtime_stm32f103.go index c0cd7fa4..89eb3ad6 100644 --- a/src/runtime/runtime_stm32f103.go +++ b/src/runtime/runtime_stm32f103.go @@ -20,6 +20,18 @@ func putchar(c byte) { machine.Serial.WriteByte(c) } +func getchar() byte { + for machine.Serial.Buffered() == 0 { + Gosched() + } + v, _ := machine.Serial.ReadByte() + return v +} + +func buffered() int { + return machine.Serial.Buffered() +} + // initCLK sets clock to 72MHz using HSE 8MHz crystal w/ PLL X 9 (8MHz x 9 = 72MHz). func initCLK() { stm32.FLASH.ACR.SetBits(stm32.FLASH_ACR_LATENCY_WS2) // Two wait states, per datasheet diff --git a/src/runtime/runtime_stm32f4.go b/src/runtime/runtime_stm32f4.go index 6ce44303..9b26ce97 100644 --- a/src/runtime/runtime_stm32f4.go +++ b/src/runtime/runtime_stm32f4.go @@ -21,6 +21,18 @@ func putchar(c byte) { machine.Serial.WriteByte(c) } +func getchar() byte { + for machine.Serial.Buffered() == 0 { + Gosched() + } + v, _ := machine.Serial.ReadByte() + return v +} + +func buffered() int { + return machine.Serial.Buffered() +} + func initCLK() { // Reset clock registers // Set HSION diff --git a/src/runtime/runtime_stm32f405.go b/src/runtime/runtime_stm32f405.go index ce8e9ef5..c42ee48a 100644 --- a/src/runtime/runtime_stm32f405.go +++ b/src/runtime/runtime_stm32f405.go @@ -163,3 +163,15 @@ func initCOM() { func putchar(c byte) { machine.Serial.WriteByte(c) } + +func getchar() byte { + for machine.Serial.Buffered() == 0 { + Gosched() + } + v, _ := machine.Serial.ReadByte() + return v +} + +func buffered() int { + return machine.Serial.Buffered() +} diff --git a/src/runtime/runtime_stm32f7x2.go b/src/runtime/runtime_stm32f7x2.go index 29fe173c..7158d14f 100644 --- a/src/runtime/runtime_stm32f7x2.go +++ b/src/runtime/runtime_stm32f7x2.go @@ -38,6 +38,18 @@ func putchar(c byte) { machine.Serial.WriteByte(c) } +func getchar() byte { + for machine.Serial.Buffered() == 0 { + Gosched() + } + v, _ := machine.Serial.ReadByte() + return v +} + +func buffered() int { + return machine.Serial.Buffered() +} + func initCLK() { // PWR_CLK_ENABLE stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN) diff --git a/src/runtime/runtime_stm32l0.go b/src/runtime/runtime_stm32l0.go index bee860ab..0caf95ec 100644 --- a/src/runtime/runtime_stm32l0.go +++ b/src/runtime/runtime_stm32l0.go @@ -16,6 +16,18 @@ func putchar(c byte) { machine.Serial.WriteByte(c) } +func getchar() byte { + for machine.Serial.Buffered() == 0 { + Gosched() + } + v, _ := machine.Serial.ReadByte() + return v +} + +func buffered() int { + return machine.Serial.Buffered() +} + func initCLK() { // Set Power Regulator to enable max performance (1.8V) stm32.PWR.CR.ReplaceBits(1<