diff --git a/docs/tulip_api.md b/docs/tulip_api.md index 12dc14bbc..87a1b66ba 100644 --- a/docs/tulip_api.md +++ b/docs/tulip_api.md @@ -335,16 +335,6 @@ def touch_callback(up): print("up %d points x1 %d y1 %d" % (up, t[0], t[1])) tulip.touch_callback(cb) - -# Make your own elements on the BG with your own styling and set up your own callbacks to process them -tulip.bg_rect(200,200,50,50,23,1) -tulip.bg_touch_register(12, 200, 200, 50, 50) # 12 is an ID -- from 0-254 -def bgt(id): - print("Got a click on id %d. up was %d" % (id, tulip.bg_touch_up(id)) # bg_touch_up returns 1 for touch up - -tulip.bg_touch_callback(bgt) -tulip.bg_touch_callback() # turns off -tulip.bg_touch_del(12) # removes ``` ## I2C / Grove / Mabee diff --git a/tulip/esp32s3/boards/MATOUCH7/mpconfigboard.cmake b/tulip/esp32s3/boards/MATOUCH7/mpconfigboard.cmake index bccb7309e..0f5ad427e 100644 --- a/tulip/esp32s3/boards/MATOUCH7/mpconfigboard.cmake +++ b/tulip/esp32s3/boards/MATOUCH7/mpconfigboard.cmake @@ -1,5 +1,7 @@ set(IDF_TARGET esp32s3) +set(MICROPY_PY_TINYUSB OFF) + set(BOARD_DEFINITION1 MATOUCH7) set(BOARD_DEFINITION2 MAKERFABS) diff --git a/tulip/esp32s3/boards/N16R8/mpconfigboard.cmake b/tulip/esp32s3/boards/N16R8/mpconfigboard.cmake index 166397c8e..65b2cbccb 100644 --- a/tulip/esp32s3/boards/N16R8/mpconfigboard.cmake +++ b/tulip/esp32s3/boards/N16R8/mpconfigboard.cmake @@ -1,5 +1,6 @@ set(IDF_TARGET esp32s3) +set(MICROPY_PY_TINYUSB ON) set(BOARD_DEFINITION1 N16R8) set(BOARD_DEFINITION2 TULIP_DIY) diff --git a/tulip/esp32s3/boards/N32R8/mpconfigboard.cmake b/tulip/esp32s3/boards/N32R8/mpconfigboard.cmake index 36b543628..ee9d1dc6d 100644 --- a/tulip/esp32s3/boards/N32R8/mpconfigboard.cmake +++ b/tulip/esp32s3/boards/N32R8/mpconfigboard.cmake @@ -1,5 +1,7 @@ set(IDF_TARGET esp32s3) +set(MICROPY_PY_TINYUSB ON) + set(BOARD_DEFINITION1 N32R8) set(BOARD_DEFINITION2 TULIP_DIY) diff --git a/tulip/esp32s3/boards/TDECK/mpconfigboard.cmake b/tulip/esp32s3/boards/TDECK/mpconfigboard.cmake index e4fcda43f..2cddbb178 100644 --- a/tulip/esp32s3/boards/TDECK/mpconfigboard.cmake +++ b/tulip/esp32s3/boards/TDECK/mpconfigboard.cmake @@ -1,5 +1,6 @@ set(IDF_TARGET esp32s3) +set(MICROPY_PY_TINYUSB OFF) set(BOARD_DEFINITION1 N16R8) set(BOARD_DEFINITION2 TDECK) diff --git a/tulip/esp32s3/boards/TDECK/mpconfigboard.h b/tulip/esp32s3/boards/TDECK/mpconfigboard.h index 617f36f9b..9e3a17532 100644 --- a/tulip/esp32s3/boards/TDECK/mpconfigboard.h +++ b/tulip/esp32s3/boards/TDECK/mpconfigboard.h @@ -5,7 +5,7 @@ #define MICROPY_PY_MACHINE_DAC (0) // Enable UART REPL for modules that have an external USB-UART and don't use native USB. -#define MICROPY_HW_ENABLE_UART_REPL (1) +#define MICROPY_HW_ENABLE_UART_REPL (0) #define USB_SERIAL_JTAG_PACKET_SZ_BYTES 64 diff --git a/tulip/esp32s3/boards/TULIP4_R11/mpconfigboard.cmake b/tulip/esp32s3/boards/TULIP4_R11/mpconfigboard.cmake index 68afc458b..33bb2af95 100644 --- a/tulip/esp32s3/boards/TULIP4_R11/mpconfigboard.cmake +++ b/tulip/esp32s3/boards/TULIP4_R11/mpconfigboard.cmake @@ -1,5 +1,6 @@ set(IDF_TARGET esp32s3) +set(MICROPY_PY_TINYUSB ON) set(BOARD_DEFINITION1 TULIP4_R11) diff --git a/tulip/esp32s3/boards/TULIP4_R11_DEBUG/mpconfigboard.cmake b/tulip/esp32s3/boards/TULIP4_R11_DEBUG/mpconfigboard.cmake index ae5739c01..98c632221 100644 --- a/tulip/esp32s3/boards/TULIP4_R11_DEBUG/mpconfigboard.cmake +++ b/tulip/esp32s3/boards/TULIP4_R11_DEBUG/mpconfigboard.cmake @@ -1,5 +1,6 @@ set(IDF_TARGET esp32s3) +set(MICROPY_PY_TINYUSB ON) set(BOARD_DEFINITION1 TULIP4_R11) diff --git a/tulip/esp32s3/esp32_common.cmake b/tulip/esp32s3/esp32_common.cmake index 868bba462..2092ce128 100644 --- a/tulip/esp32s3/esp32_common.cmake +++ b/tulip/esp32s3/esp32_common.cmake @@ -88,7 +88,6 @@ list(APPEND MICROPY_SOURCE_DRIVERS ) - string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/tinyusb) if(MICROPY_PY_TINYUSB) set(TINYUSB_SRC "${MICROPY_DIR}/lib/tinyusb/src") @@ -128,12 +127,14 @@ list(APPEND MICROPY_SOURCE_PORT ${MICROPY_PORT_DIR}/build/lv_mpy.c ${MICROPY_PORT_DIR}/network_common.c ${MICROPY_PORT_DIR}/esp_lcd_touch.c - ${MICROPY_PORT_DIR}/uart.c ${MICROPY_PORT_DIR}/modsocket.c + ${MICROPY_PORT_DIR}/mphalport.c + ${MICROPY_PORT_DIR}/usb.c + ${MICROPY_ESP32_DIR}/panichandler.c ${MICROPY_ESP32_DIR}/adc.c - ${MICROPY_ESP32_DIR}/mphalport.c - #${MICROPY_ESP32_DIR}/usb_serial_jtag.c + ${MICROPY_ESP32_DIR}/uart.c + ${MICROPY_ESP32_DIR}/usb_serial_jtag.c ${MICROPY_ESP32_DIR}/gccollect.c ${MICROPY_ESP32_DIR}/fatfs_port.c ${MICROPY_ESP32_DIR}/machine_bitstream.c @@ -156,7 +157,6 @@ list(APPEND MICROPY_SOURCE_PORT ${MICROPY_ESP32_DIR}/machine_rtc.c ${MICROPY_ESP32_DIR}/machine_sdcard.c ${MICROPY_ESP32_DIR}/modespnow.c - ${MICROPY_ESP32_DIR}/usb.c ) list(TRANSFORM MICROPY_SOURCE_BOARD PREPEND ${MICROPY_PORT_DIR}/) diff --git a/tulip/esp32s3/main.c b/tulip/esp32s3/main.c index 4bc624f7a..d2e505dea 100644 --- a/tulip/esp32s3/main.c +++ b/tulip/esp32s3/main.c @@ -222,16 +222,21 @@ void mp_task(void *pvParameter) { #if MICROPY_PY_THREAD mp_thread_init(pxTaskGetStackStart(NULL), TULIP_MP_TASK_STACK_SIZE / sizeof(uintptr_t)); #endif + #if CONFIG_USB_ENABLED - //usb_init(); + usb_init(); #elif CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG #ifdef TDECK - //usb_serial_jtag_init(); + fprintf(stderr, "init jtag\n"); + usb_serial_jtag_init(); #endif #endif + #if MICROPY_HW_ENABLE_UART_REPL + fprintf(stderr, "init uart repl\n"); uart_stdout_init(); #endif + machine_init(); //esp_err_t err = esp_event_loop_create_default(); diff --git a/tulip/esp32s3/main/CMakeLists.txt b/tulip/esp32s3/main/CMakeLists.txt index b69c3a473..beede3bbf 100644 --- a/tulip/esp32s3/main/CMakeLists.txt +++ b/tulip/esp32s3/main/CMakeLists.txt @@ -1,6 +1,5 @@ # Set location of base MicroPython directory. # Set location of base MicroPython directory. -set(MICROPY_PY_TINYUSB ON) include(../esp32_common.cmake) diff --git a/tulip/esp32s3/mpconfigport.h b/tulip/esp32s3/mpconfigport.h index fec73072b..fc19d5fbc 100644 --- a/tulip/esp32s3/mpconfigport.h +++ b/tulip/esp32s3/mpconfigport.h @@ -22,9 +22,14 @@ #define MICROPY_PY_MACHINE_I2S (0) #define MICROPY_PY_BLUETOOTH (0) #define MICROPY_BLUETOOTH_NIMBLE (0) +#ifdef TDECK +#define MICROPY_HW_USB_CDC (0) +#define MICROPY_HW_ESP_USB_SERIAL_JTAG (1) +#else #define MICROPY_HW_USB_CDC (1) -#define MICROPY_HW_ENABLE_USBDEV (1) #define MICROPY_HW_ESP_USB_SERIAL_JTAG (0) +#endif +#define MICROPY_HW_ENABLE_USBDEV (1) #define MICROPY_ENABLE_SCHEDULER (1) #define MICROPY_SCHEDULER_DEPTH (128) diff --git a/tulip/esp32s3/mphalport.c b/tulip/esp32s3/mphalport.c new file mode 100644 index 000000000..8a6687946 --- /dev/null +++ b/tulip/esp32s3/mphalport.c @@ -0,0 +1,275 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * Development of the code in this file was sponsored by Microbric Pty Ltd + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_timer.h" + +#include "py/obj.h" +#include "py/objstr.h" +#include "py/stream.h" +#include "py/mpstate.h" +#include "py/mphal.h" +#include "extmod/misc.h" +#include "shared/timeutils/timeutils.h" +#include "shared/runtime/pyexec.h" +#ifndef TDECK +#include "shared/tinyusb/mp_usbd.h" +#include "shared/tinyusb/mp_usbd_cdc.h" +#else +#include "usb_serial_jtag.h" +#endif +#include "usb.h" +#include "uart.h" +#include "display.h" +#if MICROPY_PY_STRING_TX_GIL_THRESHOLD < 0 +#error "MICROPY_PY_STRING_TX_GIL_THRESHOLD must be positive" +#endif + +TaskHandle_t mp_main_task_handle; + +static uint8_t stdin_ringbuf_array[260]; +ringbuf_t stdin_ringbuf = {stdin_ringbuf_array, sizeof(stdin_ringbuf_array), 0, 0}; + +portMUX_TYPE mp_atomic_mux = portMUX_INITIALIZER_UNLOCKED; + +// Check the ESP-IDF error code and raise an OSError if it's not ESP_OK. +#if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_NORMAL +void check_esp_err_(esp_err_t code) +#else +void check_esp_err_(esp_err_t code, const char *func, const int line, const char *file) +#endif +{ + if (code != ESP_OK) { + // map esp-idf error code to posix error code + uint32_t pcode = -code; + switch (code) { + case ESP_ERR_NO_MEM: + pcode = MP_ENOMEM; + break; + case ESP_ERR_TIMEOUT: + pcode = MP_ETIMEDOUT; + break; + case ESP_ERR_NOT_SUPPORTED: + pcode = MP_EOPNOTSUPP; + break; + } + // construct string object + mp_obj_str_t *o_str = m_new_obj_maybe(mp_obj_str_t); + if (o_str == NULL) { + mp_raise_OSError(pcode); + return; + } + o_str->base.type = &mp_type_str; + #if MICROPY_ERROR_REPORTING > MICROPY_ERROR_REPORTING_NORMAL + char err_msg[64]; + esp_err_to_name_r(code, err_msg, sizeof(err_msg)); + vstr_t vstr; + vstr_init(&vstr, 80); + vstr_printf(&vstr, "0x%04X %s in function '%s' at line %d in file '%s'", code, err_msg, func, line, file); + o_str->data = (const byte *)vstr_null_terminated_str(&vstr); + #else + o_str->data = (const byte *)esp_err_to_name(code); // esp_err_to_name ret's ptr to const str + #endif + o_str->len = strlen((char *)o_str->data); + o_str->hash = qstr_compute_hash(o_str->data, o_str->len); + // raise + mp_obj_t args[2] = { MP_OBJ_NEW_SMALL_INT(pcode), MP_OBJ_FROM_PTR(o_str)}; + nlr_raise(mp_obj_exception_make_new(&mp_type_OSError, 2, 0, args)); + } +} + +uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { + uintptr_t ret = 0; + #if MICROPY_HW_ESP_USB_SERIAL_JTAG + usb_serial_jtag_poll_rx(); + if ((poll_flags & MP_STREAM_POLL_RD) && ringbuf_peek(&stdin_ringbuf) != -1) { + ret |= MP_STREAM_POLL_RD; + } + if (poll_flags & MP_STREAM_POLL_WR) { + ret |= MP_STREAM_POLL_WR; + } + #endif + #if MICROPY_HW_USB_CDC + ret |= mp_usbd_cdc_poll_interfaces(poll_flags); + #endif + #if MICROPY_PY_OS_DUPTERM + ret |= mp_os_dupterm_poll(poll_flags); + #endif + return ret; +} + +int mp_hal_stdin_rx_chr(void) { + for (;;) { + #if MICROPY_HW_ESP_USB_SERIAL_JTAG + usb_serial_jtag_poll_rx(); + #endif + #if MICROPY_HW_USB_CDC + mp_usbd_cdc_poll_interfaces(0); + #endif + int c = ringbuf_get(&stdin_ringbuf); + if (c != -1) { + return c; + } + MICROPY_EVENT_POLL_HOOK + } +} + +mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) { + if(len) { + display_tfb_str((unsigned char*)str, len, 0, tfb_fg_pal_color, tfb_bg_pal_color); + } + // Only release the GIL if many characters are being sent + mp_uint_t ret = len; + bool did_write = false; + #if MICROPY_HW_ENABLE_UART_REPL || CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED + bool release_gil = len > MICROPY_PY_STRING_TX_GIL_THRESHOLD; + #if MICROPY_DEBUG_PRINTERS && MICROPY_DEBUG_VERBOSE && MICROPY_PY_THREAD_GIL + // If verbose debug output is enabled some strings are printed before the + // GIL mutex is set up. When that happens, no Python code is running and + // therefore the interpreter doesn't care about the GIL not being ready. + release_gil = release_gil && (MP_STATE_VM(gil_mutex).handle != NULL); + #endif + if (release_gil) { + MP_THREAD_GIL_EXIT(); + } + #if MICROPY_HW_ESP_USB_SERIAL_JTAG + usb_serial_jtag_tx_strn(str, len); + did_write = true; + #endif + #if MICROPY_HW_ENABLE_UART_REPL + uart_stdout_tx_strn(str, len); + did_write = true; + #endif + if (release_gil) { + MP_THREAD_GIL_ENTER(); + } + #endif // MICROPY_HW_ENABLE_UART_REPL || CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED + #if MICROPY_HW_USB_CDC + mp_uint_t cdc_res = mp_usbd_cdc_tx_strn(str, len); + if (cdc_res > 0) { + did_write = true; + ret = MIN(cdc_res, ret); + } + #endif + int dupterm_res = mp_os_dupterm_tx_strn(str, len); + if (dupterm_res >= 0) { + did_write = true; + ret = MIN((mp_uint_t)dupterm_res, ret); + } + return did_write ? ret : 0; +} + +uint32_t mp_hal_ticks_ms(void) { + return esp_timer_get_time() / 1000; +} + +uint32_t mp_hal_ticks_us(void) { + return esp_timer_get_time(); +} + +void mp_hal_delay_ms(uint32_t ms) { + uint64_t us = (uint64_t)ms * 1000ULL; + uint64_t dt; + uint64_t t0 = esp_timer_get_time(); + for (;;) { + mp_handle_pending(true); + MICROPY_PY_SOCKET_EVENTS_HANDLER + MP_THREAD_GIL_EXIT(); + uint64_t t1 = esp_timer_get_time(); + dt = t1 - t0; + if (dt + portTICK_PERIOD_MS * 1000ULL >= us) { + // doing a vTaskDelay would take us beyond requested delay time + taskYIELD(); + MP_THREAD_GIL_ENTER(); + t1 = esp_timer_get_time(); + dt = t1 - t0; + break; + } else { + ulTaskNotifyTake(pdFALSE, 1); + MP_THREAD_GIL_ENTER(); + } + } + if (dt < us) { + // do the remaining delay accurately + mp_hal_delay_us(us - dt); + } +} + +void mp_hal_delay_us(uint32_t us) { + // these constants are tested for a 240MHz clock + const uint32_t this_overhead = 5; + const uint32_t pend_overhead = 150; + + // return if requested delay is less than calling overhead + if (us < this_overhead) { + return; + } + us -= this_overhead; + + uint64_t t0 = esp_timer_get_time(); + for (;;) { + uint64_t dt = esp_timer_get_time() - t0; + if (dt >= us) { + return; + } + if (dt + pend_overhead < us) { + // we have enough time to service pending events + // (don't use MICROPY_EVENT_POLL_HOOK because it also yields) + mp_handle_pending(true); + } + } +} + +uint64_t mp_hal_time_ns(void) { + struct timeval tv; + gettimeofday(&tv, NULL); + uint64_t ns = tv.tv_sec * 1000000000ULL; + ns += (uint64_t)tv.tv_usec * 1000ULL; + return ns; +} + +// Wake up the main task if it is sleeping. +void mp_hal_wake_main_task(void) { + xTaskNotifyGive(mp_main_task_handle); +} + +// Wake up the main task if it is sleeping, to be called from an ISR. +void mp_hal_wake_main_task_from_isr(void) { + /* + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + vTaskNotifyGiveFromISR(mp_main_task_handle, &xHigherPriorityTaskWoken); + if (xHigherPriorityTaskWoken == pdTRUE) { + portYIELD_FROM_ISR(); + } + */ +} diff --git a/tulip/esp32s3/uart.c b/tulip/esp32s3/uart.c deleted file mode 100644 index d32b50948..000000000 --- a/tulip/esp32s3/uart.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * Development of the code in this file was sponsored by Microbric Pty Ltd - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - - -#include "py/runtime.h" -#include "py/mphal.h" -#include "uart.h" - -#if MICROPY_HW_ENABLE_UART_REPL - -#include -#include "driver/uart.h" // For uart_get_sclk_freq() -#include "hal/uart_hal.h" -#include "soc/uart_periph.h" -#include "display.h" - -static void uart_irq_handler(void *arg); - -// Declaring the HAL structure on the stack saves a tiny amount of static RAM -#define REPL_HAL_DEFN() { .dev = UART_LL_GET_HW(MICROPY_HW_UART_REPL) } - -// RXFIFO Full interrupt threshold. Set the same as the ESP-IDF UART driver -#define RXFIFO_FULL_THR (SOC_UART_FIFO_LEN - 8) - -// RXFIFO RX timeout threshold. This is in bit periods, so 10==one byte. Same as ESP-IDF UART driver. -#define RXFIFO_RX_TIMEOUT (10) - -void uart_stdout_init(void) { - uart_hal_context_t repl_hal = REPL_HAL_DEFN(); - #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 2, 0) - uart_sclk_t sclk; - #else - soc_module_clk_t sclk; - #endif - uint32_t sclk_freq; - - uart_hal_get_sclk(&repl_hal, &sclk); // To restore SCLK after uart_hal_init() resets it - ESP_ERROR_CHECK(uart_get_sclk_freq(sclk, &sclk_freq)); - - uart_hal_init(&repl_hal, MICROPY_HW_UART_REPL); // Sets defaults: 8n1, no flow control - uart_hal_set_sclk(&repl_hal, sclk); - uart_hal_set_baudrate(&repl_hal, MICROPY_HW_UART_REPL_BAUD, sclk_freq); - uart_hal_rxfifo_rst(&repl_hal); - uart_hal_txfifo_rst(&repl_hal); - - ESP_ERROR_CHECK( - esp_intr_alloc(uart_periph_signal[MICROPY_HW_UART_REPL].irq, - ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM, - uart_irq_handler, - NULL, - NULL) - ); - - // Enable RX interrupts - uart_hal_set_rxfifo_full_thr(&repl_hal, RXFIFO_FULL_THR); - uart_hal_set_rx_timeout(&repl_hal, RXFIFO_RX_TIMEOUT); - uart_hal_ena_intr_mask(&repl_hal, UART_INTR_RXFIFO_FULL | UART_INTR_RXFIFO_TOUT); -} - - -int uart_stdout_tx_strn(const char *str, size_t len) { - if(len) { - display_tfb_str((unsigned char*)str, len, 0, tfb_fg_pal_color, tfb_bg_pal_color); - } - uart_hal_context_t repl_hal = REPL_HAL_DEFN(); - size_t remaining = len; - uint32_t written = 0; - // TODO add a timeout - for (;;) { - uart_hal_write_txfifo(&repl_hal, (const void *)str, remaining, &written); - - if (written >= remaining) { - break; - } - remaining -= written; - str += written; - ulTaskNotifyTake(pdFALSE, 1); - } - //if(len) { - // display_tfb_str((unsigned char*)str, len, 0, tfb_fg_pal_color, tfb_bg_pal_color); - //} - return len; -} - - -// all code executed in ISR must be in IRAM, and any const data must be in DRAM -static void IRAM_ATTR uart_irq_handler(void *arg) { - uint8_t rbuf[SOC_UART_FIFO_LEN]; - int len; - uart_hal_context_t repl_hal = REPL_HAL_DEFN(); - - uart_hal_clr_intsts_mask(&repl_hal, UART_INTR_RXFIFO_FULL | UART_INTR_RXFIFO_TOUT | UART_INTR_FRAM_ERR); - - len = uart_hal_get_rxfifo_len(&repl_hal); - - uart_hal_read_rxfifo(&repl_hal, rbuf, &len); - - for (int i = 0; i < len; i++) { - if (rbuf[i] == mp_interrupt_char) { - mp_sched_keyboard_interrupt(); - } else { - // this is an inline function so will be in IRAM - ringbuf_put(&stdin_ringbuf, rbuf[i]); - } - } -} - -#endif // MICROPY_HW_ENABLE_UART_REPL - - - diff --git a/tulip/esp32s3/uart.h b/tulip/esp32s3/uart.h deleted file mode 100644 index 6410db24c..000000000 --- a/tulip/esp32s3/uart.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * Development of the code in this file was sponsored by Microbric Pty Ltd - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef MICROPY_INCLUDED_ESP32_UART_H -#define MICROPY_INCLUDED_ESP32_UART_H - -// Whether to enable the REPL on a UART. -#ifndef MICROPY_HW_ENABLE_UART_REPL -#define MICROPY_HW_ENABLE_UART_REPL (!CONFIG_USB_OTG_SUPPORTED && !CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG) -#endif - -#ifndef MICROPY_HW_UART_REPL -#define MICROPY_HW_UART_REPL (0) -#endif - -#ifndef MICROPY_HW_UART_REPL_BAUD -#define MICROPY_HW_UART_REPL_BAUD (115200) -#endif - -void uart_stdout_init(void); -int uart_stdout_tx_strn(const char *str, size_t len); - -#endif // MICROPY_INCLUDED_ESP32_UART_H diff --git a/tulip/esp32s3/usb.c b/tulip/esp32s3/usb.c new file mode 100644 index 000000000..ddc557f3d --- /dev/null +++ b/tulip/esp32s3/usb.c @@ -0,0 +1,88 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" +#include "py/mphal.h" +#include "usb.h" + +#include "esp_rom_gpio.h" +#include "esp_mac.h" + + +#if MICROPY_HW_USB_CDC +#include "shared/tinyusb/mp_usbd.h" +#include "esp_private/usb_phy.h" +static usb_phy_handle_t phy_hdl; + + + +void usb_init(void) { + // ref: https://github.com/espressif/esp-usb/blob/4b6a798d0bed444fff48147c8dcdbbd038e92892/device/esp_tinyusb/tinyusb.c + + // Configure USB PHY + usb_phy_config_t phy_conf = { + .controller = USB_PHY_CTRL_OTG, + .otg_mode = USB_OTG_MODE_DEVICE, + }; + // Internal USB PHY + phy_conf.target = USB_PHY_TARGET_INT; + + // Init ESP USB Phy + usb_new_phy(&phy_conf, &phy_hdl); + + // Init MicroPython / TinyUSB + mp_usbd_init(); + +} + +void mp_usbd_port_get_serial_number(char *serial_buf) { + // use factory default MAC as serial ID + uint8_t mac[8]; + esp_efuse_mac_get_default(mac); + MP_STATIC_ASSERT(sizeof(mac) * 2 <= MICROPY_HW_USB_DESC_STR_MAX); + mp_usbd_hex_str(serial_buf, mac, sizeof(mac)); +} + +#endif + +#if CONFIG_IDF_TARGET_ESP32S3 + +#if !MICROPY_HW_USB_CDC +#include "esp_private/usb_phy.h" +static usb_phy_handle_t phy_hdl; +#endif + +void usb_usj_mode(void) { + // Switch the USB PHY back to Serial/Jtag mode, disabling OTG support + // This should be run before jumping to bootloader. + usb_del_phy(phy_hdl); + usb_phy_config_t phy_conf = { + .controller = USB_PHY_CTRL_SERIAL_JTAG, + }; + usb_new_phy(&phy_conf, &phy_hdl); +} +#endif +