AtomVM icon indicating copy to clipboard operation
AtomVM copied to clipboard

Use on-chip usb interface for console I/O for the esp32 s2

Open schnef opened this issue 1 year ago • 6 comments

The esp32 s2 has an on-chip usb interface used for flashing applications, among other things. For console I/O, UART0 is used. It would be very convenient if the USB interface is also used for console I/O because firstly it makes an external connection much easier and secondly because on development boards such as the wemos lolin s2 mini and pico, UART0 is not implemented on the pin headers. As far as I understood it should use softserial for the usb interface? The wemos s2 mini board uses the USB interface as described here

It concerns the development board wemos S2 mini Chip ESP32-S2FN4R2 Board schematics:

schnef avatar Jun 11 '24 13:06 schnef

can you share any log (such as the bootloader log) or some more details about what are you doing and it is not working?

bettio avatar Jun 14 '24 21:06 bettio

I eventually got hold of this board. It is indeed very different from the other ESP32 boards I have. The USB device appears after RST and 0 buttons are pressed and released. This allows to flash AtomVM or use rebar atomvm esp32_flash. However, after the tool is used, the following message is printed:

WARNING: ESP32-S2FNR2 (revision v1.0) chip was placed into download mode using GPIO0.
esptool.py can not exit the download mode over USB. To run the app, reset the chip manually.
To suppress this note, set --after option to 'no_reset'.

(including when using rebar plugin).

I confirm it works as I was able to run blinky with onboard LED on GPIO 15. But when AtomVM is running, the device doesn't appear on the USB bus.

Based on the documentation and an esp-idf example, the following patch enables serial interface on the board:

diff --git a/src/platforms/esp32/main/main.c b/src/platforms/esp32/main/main.c
index 4f651b8b..5d206843 100644
--- a/src/platforms/esp32/main/main.c
+++ b/src/platforms/esp32/main/main.c
@@ -37,6 +37,10 @@
 #include <term.h>
 #include <utils.h>
 
+#include "tinyusb.h"
+#include "tusb_cdc_acm.h"
+#include "tusb_console.h"
+
 #include "esp32_sys.h"
 
 #define TAG "AtomVM"
@@ -60,6 +64,31 @@ void app_main()
 {
     esp32_sys_queue_init();
 
+    /* Setting TinyUSB up */
+    ESP_LOGI(TAG, "USB initialization");
+
+    const tinyusb_config_t tusb_cfg = {
+        .device_descriptor = NULL,
+        .string_descriptor = NULL,
+        .external_phy = false, // In the most cases you need to use a `false` value
+#if (TUD_OPT_HIGH_SPEED)
+        .fs_configuration_descriptor = NULL,
+        .hs_configuration_descriptor = NULL,
+        .qualifier_descriptor = NULL,
+#else
+        .configuration_descriptor = NULL,
+#endif // TUD_OPT_HIGH_SPEED
+    };
+
+    ESP_ERROR_CHECK(tinyusb_driver_install(&tusb_cfg));
+
+    tinyusb_config_cdcacm_t acm_cfg = { 0 }; // the configuration uses default values
+    ESP_ERROR_CHECK(tusb_cdc_acm_init(&acm_cfg));
+
+    ESP_LOGI(TAG, "USB initialization DONE");
+
+    esp_tusb_init_console(TINYUSB_CDC_ACM_0); // log to usb
+
     fprintf(stdout, "%s", ATOMVM_BANNER);
     ESP_LOGI(TAG, "Starting AtomVM revision " ATOMVM_VERSION);
 

It requires esp_tinyusb (idf.py add-dependency esp_tinyusb) and also to enable CDC in menu config. With this, I can get the output of blinky. However, there is no monitor and minicom doesn't connect fast enough to see AtomVM banner. The port appears as /dev/cu.usbmodem1234561 as opposed to /dev/cu.usbmodem01 for flashing.

@bettio I'm not sure what we should do with this board, though.

pguyot avatar Jun 16 '24 19:06 pguyot

Is there a way to delay the startup to allow serial connections like we do for the rp2040 port? Maybe we just add a cmake build option for usb-serial. There are bound to be other boards in the future that rely on or support serial usb.

UncleGrumpy avatar Jun 16 '24 20:06 UncleGrumpy

I don't think we necessarily need to add this to the release matrix, we should just support the option and refer this to the build instructions as a special circumstance.

UncleGrumpy avatar Jun 16 '24 20:06 UncleGrumpy

That's fast! I really appreciate your efforts! This is uncharted territory for me and I am very happy that a solution has been found.

schnef avatar Jun 17 '24 07:06 schnef

Is there any more clarity on whether and how the problem can be solved? Many of the esp32 s2 boards, especially the cheaper ones, use the on-chip usb interface. I (we) would be greatly helped if I can use the existing usb interface.

schnef avatar Jun 24 '24 07:06 schnef

I think we can add support for it, if we make that code conditional with some #if #endif. That entire code block can be moved together to a dedicated function surrounded with a #if block and we make also conditional the includes. Last but not least, an entry to the menuconfig must be added and instructions as well. I suggest this for main branch.

bettio avatar Jul 02 '24 22:07 bettio

That would be great, thanks in advance

schnef avatar Jul 03 '24 05:07 schnef

Got it working. Some notes:

  • on configuring the platform target, do select esp32s2 (idf.py set-target esp32s2)
  • added in AtomVM/src/platforms/esp32/main/nain.c a forward declaration void init_usb_serial(); in the #ifdef USE_USB_SERIAL block to prevent error during build.
  • the USB device is /dev/ttyACM0 under Debian 12

Thanks for the help.

schnef avatar Aug 18 '24 13:08 schnef