diff --git a/src/machine/machine_esp32c3.go b/src/machine/machine_esp32c3.go index e447e4fe..1ad30998 100644 --- a/src/machine/machine_esp32c3.go +++ b/src/machine/machine_esp32c3.go @@ -504,3 +504,95 @@ func (uart *UART) writeByte(b byte) error { } func (uart *UART) flush() {} + +type Serialer interface { + WriteByte(c byte) error + Write(data []byte) (n int, err error) + Configure(config UARTConfig) error + Buffered() int + ReadByte() (byte, error) + DTR() bool + RTS() bool +} + +// USB Serial/JTAG Controller +// See esp32-c3_technical_reference_manual_en.pdf +// pg. 736 +type USB_DEVICE struct { + Bus *esp.USB_DEVICE_Type +} + +var ( + _USBCDC = &USB_DEVICE{ + Bus: esp.USB_DEVICE, + } + + USBCDC Serialer = _USBCDC +) + +var ( + errUSBWrongSize = errors.New("USB: invalid write size") + errUSBCouldNotWriteAllData = errors.New("USB: could not write all data") + errUSBBufferEmpty = errors.New("USB: read buffer empty") +) + +func (usbdev *USB_DEVICE) Configure(config UARTConfig) error { + return nil +} + +func (usbdev *USB_DEVICE) WriteByte(c byte) error { + if usbdev.Bus.GetEP1_CONF_SERIAL_IN_EP_DATA_FREE() == 0 { + return errUSBCouldNotWriteAllData + } + + usbdev.Bus.SetEP1_RDWR_BYTE(uint32(c)) + usbdev.flush() + + return nil +} + +func (usbdev *USB_DEVICE) Write(data []byte) (n int, err error) { + if len(data) == 0 || len(data) > 64 { + return 0, errUSBWrongSize + } + + for i, c := range data { + if usbdev.Bus.GetEP1_CONF_SERIAL_IN_EP_DATA_FREE() == 0 { + if i > 0 { + usbdev.flush() + } + + return i, errUSBCouldNotWriteAllData + } + usbdev.Bus.SetEP1_RDWR_BYTE(uint32(c)) + } + + usbdev.flush() + return len(data), nil +} + +func (usbdev *USB_DEVICE) Buffered() int { + return int(usbdev.Bus.GetEP1_CONF_SERIAL_OUT_EP_DATA_AVAIL()) +} + +func (usbdev *USB_DEVICE) ReadByte() (byte, error) { + if usbdev.Bus.GetEP1_CONF_SERIAL_OUT_EP_DATA_AVAIL() != 0 { + return byte(usbdev.Bus.GetEP1_RDWR_BYTE()), nil + } + + return 0, nil +} + +func (usbdev *USB_DEVICE) DTR() bool { + return false +} + +func (usbdev *USB_DEVICE) RTS() bool { + return false +} + +func (usbdev *USB_DEVICE) flush() { + usbdev.Bus.SetEP1_CONF_WR_DONE(1) + for usbdev.Bus.GetEP1_CONF_SERIAL_IN_EP_DATA_FREE() == 0 { + } +} diff --git a/src/machine/usb.go b/src/machine/usb.go index c114e709..2f775569 100644 --- a/src/machine/usb.go +++ b/src/machine/usb.go @@ -88,8 +88,9 @@ func strToUTF16LEDescriptor(in string, out []byte) { const cdcLineInfoSize = 7 var ( - ErrUSBReadTimeout = errors.New("USB read timeout") - ErrUSBBytesRead = errors.New("USB invalid number of bytes read") + ErrUSBReadTimeout = errors.New("USB read timeout") + ErrUSBBytesRead = errors.New("USB invalid number of bytes read") + ErrUSBBytesWritten = errors.New("USB invalid number of bytes written") ) var ( diff --git a/src/runtime/runtime_esp32c3.go b/src/runtime/runtime_esp32c3.go index 8a4c40df..9ac4edbc 100644 --- a/src/runtime/runtime_esp32c3.go +++ b/src/runtime/runtime_esp32c3.go @@ -5,6 +5,7 @@ package runtime import ( "device/esp" "device/riscv" + "machine" "runtime/volatile" "unsafe" ) @@ -53,6 +54,10 @@ func main() { // Configure interrupt handler interruptInit() + // Initialize UART. + machine.USBCDC.Configure(machine.UARTConfig{}) + machine.InitSerial() + // Initialize main system timer used for time.Now. initTimer() diff --git a/src/runtime/runtime_esp32xx.go b/src/runtime/runtime_esp32xx.go index b2a16f87..409c46de 100644 --- a/src/runtime/runtime_esp32xx.go +++ b/src/runtime/runtime_esp32xx.go @@ -10,22 +10,6 @@ import ( type timeUnit int64 -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() { @@ -84,3 +68,19 @@ func sleepTicks(d timeUnit) { func exit(code int) { abort() } + +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/targets/esp32c3.json b/targets/esp32c3.json index 2795c37f..8cdb278f 100644 --- a/targets/esp32c3.json +++ b/targets/esp32c3.json @@ -2,7 +2,7 @@ "inherits": ["riscv32"], "features": "+32bit,+c,+m,-64bit,-a,-d,-e,-experimental-zawrs,-experimental-zca,-experimental-zcd,-experimental-zcf,-experimental-zihintntl,-experimental-ztso,-experimental-zvfh,-f,-h,-relax,-save-restore,-svinval,-svnapot,-svpbmt,-v,-xtheadvdot,-xventanacondops,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zdinx,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zicbom,-zicbop,-zicboz,-zihintpause,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-zmmul,-zve32f,-zve32x,-zve64d,-zve64f,-zve64x,-zvl1024b,-zvl128b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl32b,-zvl4096b,-zvl512b,-zvl64b,-zvl65536b,-zvl8192b", "build-tags": ["esp32c3", "esp"], - "serial": "uart", + "serial": "usb", "rtlib": "compiler-rt", "libc": "picolibc", "cflags": [