diff --git a/CMakeLists.txt b/CMakeLists.txt index cdb1f079..cd228a07 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,7 @@ set(CORE_SRCS cores/esp32/stdlib_noniso.c cores/esp32/Stream.cpp cores/esp32/StreamString.cpp + cores/esp32/HWCDC.cpp cores/esp32/USB.cpp cores/esp32/USBCDC.cpp cores/esp32/USBMSC.cpp diff --git a/boards.txt b/boards.txt index 138cbcdb..abc77f9e 100644 --- a/boards.txt +++ b/boards.txt @@ -21,12 +21,16 @@ menu.EventsCore=Events Run On ############################################################## esp32c3.name=ESP32C3 Dev Module +esp32c3.vid.0=0x303a +esp32c3.pid.0=0x1001 esp32c3.upload.tool=esptool_py esp32c3.upload.maximum_size=1310720 esp32c3.upload.maximum_data_size=327680 esp32c3.upload.flags= esp32c3.upload.extra_flags= +esp32c3.upload.use_1200bps_touch=false +esp32c3.upload.wait_for_upload_port=false esp32c3.serial.disableDTR=false esp32c3.serial.disableRTS=false @@ -48,6 +52,18 @@ esp32c3.build.boot=qio esp32c3.build.partitions=default esp32c3.build.defines= +esp32c3.menu.CDCOnBoot.default=Disabled +esp32c3.menu.CDCOnBoot.default.build.cdc_on_boot=0 +esp32c3.menu.CDCOnBoot.cdc=Enabled +esp32c3.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +esp32c3.menu.UploadMode.default=UART0 +esp32c3.menu.UploadMode.default.upload.use_1200bps_touch=false +esp32c3.menu.UploadMode.default.upload.wait_for_upload_port=false +esp32c3.menu.UploadMode.cdc=Internal USB +esp32c3.menu.UploadMode.cdc.upload.use_1200bps_touch=true +esp32c3.menu.UploadMode.cdc.upload.wait_for_upload_port=true + esp32c3.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) esp32c3.menu.PartitionScheme.default.build.partitions=default esp32c3.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) diff --git a/cores/esp32/HWCDC.cpp b/cores/esp32/HWCDC.cpp new file mode 100644 index 00000000..05cb816f --- /dev/null +++ b/cores/esp32/HWCDC.cpp @@ -0,0 +1,283 @@ +// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "USB.h" +#if CONFIG_IDF_TARGET_ESP32C3 + +#include "esp32-hal.h" +#include "HWCDC.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "freertos/queue.h" +#include "freertos/ringbuf.h" +#include "esp_intr_alloc.h" +#include "soc/periph_defs.h" +#include "hal/usb_serial_jtag_ll.h" + +static RingbufHandle_t tx_ring_buf = NULL; +static xQueueHandle rx_queue = NULL; +static uint8_t rx_data_buf[64]; +static intr_handle_t intr_handle = NULL; +static volatile bool initial_empty = false; + +static void hw_cdc_isr_handler(void *arg) { + portBASE_TYPE xTaskWoken = 0; + uint32_t usbjtag_intr_status = 0; + usbjtag_intr_status = usb_serial_jtag_ll_get_intsts_mask(); + + if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY) { + // Interrupt tells us the host picked up the data we sent. + if (usb_serial_jtag_ll_txfifo_writable() == 1) { + // We disable the interrupt here so that the interrupt won't be triggered if there is no data to send. + usb_serial_jtag_ll_disable_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY); + + if(!initial_empty){ + initial_empty = true; + //send event? + //ets_printf("CONNECTED\n"); + } + size_t queued_size; + uint8_t *queued_buff = (uint8_t *)xRingbufferReceiveUpToFromISR(tx_ring_buf, &queued_size, 64); + // If the hardware fifo is avaliable, write in it. Otherwise, do nothing. + if (queued_buff != NULL) { //Although tx_queued_bytes may be larger than 0. We may have interrupt before xRingbufferSend() was called. + //Copy the queued buffer into the TX FIFO + usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY); + usb_serial_jtag_ll_write_txfifo(queued_buff, queued_size); + usb_serial_jtag_ll_txfifo_flush(); + vRingbufferReturnItemFromISR(tx_ring_buf, queued_buff, &xTaskWoken); + usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY); + //send event? + //ets_printf("TX:%u\n", queued_size); + } + } else { + usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY); + } + } + + if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT) { + // read rx buffer(max length is 64), and send avaliable data to ringbuffer. + // Ensure the rx buffer size is larger than RX_MAX_SIZE. + usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT); + uint32_t rx_fifo_len = usb_serial_jtag_ll_read_rxfifo(rx_data_buf, 64); + uint32_t i=0; + for(i=0; i +#include "Stream.h" + +class HWCDC: public Stream +{ +public: + HWCDC(); + ~HWCDC(); + + size_t setRxBufferSize(size_t); + size_t setTxBufferSize(size_t); + void begin(unsigned long baud=0); + void end(); + + int available(void); + int availableForWrite(void); + int peek(void); + int read(void); + size_t read(uint8_t *buffer, size_t size); + size_t write(uint8_t); + size_t write(const uint8_t *buffer, size_t size); + void flush(void); + + inline size_t read(char * buffer, size_t size) + { + return read((uint8_t*) buffer, size); + } + inline size_t write(const char * buffer, size_t size) + { + return write((uint8_t*) buffer, size); + } + inline size_t write(const char * s) + { + return write((uint8_t*) s, strlen(s)); + } + inline size_t write(unsigned long n) + { + return write((uint8_t) n); + } + inline size_t write(long n) + { + return write((uint8_t) n); + } + inline size_t write(unsigned int n) + { + return write((uint8_t) n); + } + inline size_t write(int n) + { + return write((uint8_t) n); + } + operator bool() const; + void setDebugOutput(bool); + uint32_t baudRate(){return 115200;} + +}; + +#if ARDUINO_HW_CDC_ON_BOOT //Serial used for USB CDC +extern HWCDC Serial; +#else +extern HWCDC USBSerial; +#endif + +#endif /* CONFIG_IDF_TARGET_ESP32C3 */ diff --git a/cores/esp32/HardwareSerial.cpp b/cores/esp32/HardwareSerial.cpp index 32411514..064aef6f 100644 --- a/cores/esp32/HardwareSerial.cpp +++ b/cores/esp32/HardwareSerial.cpp @@ -76,6 +76,8 @@ void serialEvent2(void) {} #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL) #if ARDUINO_USB_CDC_ON_BOOT //Serial used for USB CDC HardwareSerial Serial0(0); +#elif ARDUINO_HW_CDC_ON_BOOT +HardwareSerial Serial0(0); #else HardwareSerial Serial(0); #endif @@ -91,6 +93,8 @@ void serialEventRun(void) { #if ARDUINO_USB_CDC_ON_BOOT //Serial used for USB CDC if(Serial0.available()) serialEvent(); +#elif ARDUINO_HW_CDC_ON_BOOT + if(Serial0.available()) serialEvent(); #else if(Serial.available()) serialEvent(); #endif diff --git a/cores/esp32/HardwareSerial.h b/cores/esp32/HardwareSerial.h index 04b96045..40282361 100644 --- a/cores/esp32/HardwareSerial.h +++ b/cores/esp32/HardwareSerial.h @@ -50,6 +50,7 @@ #include "Stream.h" #include "esp32-hal.h" #include "soc/soc_caps.h" +#include "HWCDC.h" class HardwareSerial: public Stream { @@ -121,6 +122,8 @@ extern void serialEventRun(void) __attribute__((weak)); #include "USB.h" #include "USBCDC.h" extern HardwareSerial Serial0; +#elif ARDUINO_HW_CDC_ON_BOOT +extern HardwareSerial Serial0; #else extern HardwareSerial Serial; #endif diff --git a/platform.txt b/platform.txt index 2fa972dc..d76c6212 100644 --- a/platform.txt +++ b/platform.txt @@ -60,7 +60,7 @@ compiler.cpp.flags.esp32c3=-march=rv32imc -ffunction-sections -fdata-sections -W compiler.S.flags.esp32c3=-ffunction-sections -fdata-sections -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=deprecated-declarations -Wno-unused-parameter -Wno-sign-compare -ggdb -Wno-error=format= -nostartfiles -Wno-format -Og -fstrict-volatile-bitfields -Wno-error=unused-but-set-variable -fno-jump-tables -fno-tree-switch-conversion -x assembler-with-cpp -MMD -c compiler.c.elf.flags.esp32c3=-T memory.ld -T sections.ld -T esp32c3.rom.ld -T esp32c3.rom.api.ld -T esp32c3.rom.libgcc.ld -T esp32c3.rom.newlib.ld -T esp32c3.rom.version.ld -T esp32c3.peripherals.ld -nostartfiles -march=rv32imc --specs=nosys.specs -Wl,--cref -Wl,--gc-sections -fno-rtti -fno-lto -u _Z5setupv -u _Z4loopv -Wl,--wrap=mbedtls_mpi_exp_mod -u esp_app_desc -u pthread_include_pthread_impl -u pthread_include_pthread_cond_impl -u pthread_include_pthread_local_storage_impl -u start_app -u __ubsan_include -u __assert_func -u vfs_include_syscalls_impl -Wl,--undefined=uxTopUsedPriority -u app_main -u newlib_include_heap_impl -u newlib_include_syscalls_impl -u newlib_include_pthread_impl -Wl,--wrap=_Unwind_SetEnableExceptionFdeSorting -Wl,--wrap=__register_frame_info_bases -Wl,--wrap=__register_frame_info -Wl,--wrap=__register_frame -Wl,--wrap=__register_frame_info_table_bases -Wl,--wrap=__register_frame_info_table -Wl,--wrap=__register_frame_table -Wl,--wrap=__deregister_frame_info_bases -Wl,--wrap=__deregister_frame_info -Wl,--wrap=_Unwind_Find_FDE -Wl,--wrap=_Unwind_GetGR -Wl,--wrap=_Unwind_GetCFA -Wl,--wrap=_Unwind_GetIP -Wl,--wrap=_Unwind_GetIPInfo -Wl,--wrap=_Unwind_GetRegionStart -Wl,--wrap=_Unwind_GetDataRelBase -Wl,--wrap=_Unwind_GetTextRelBase -Wl,--wrap=_Unwind_SetIP -Wl,--wrap=_Unwind_SetGR -Wl,--wrap=_Unwind_GetLanguageSpecificData -Wl,--wrap=_Unwind_FindEnclosingFunction -Wl,--wrap=_Unwind_Resume -Wl,--wrap=_Unwind_RaiseException -Wl,--wrap=_Unwind_DeleteException -Wl,--wrap=_Unwind_ForcedUnwind -Wl,--wrap=_Unwind_Resume_or_Rethrow -Wl,--wrap=_Unwind_Backtrace -Wl,--wrap=__cxa_call_unexpected -Wl,--wrap=__gxx_personality_v0 -u __cxa_guard_dummy -u __cxx_fatal_exception compiler.ar.flags.esp32c3=cr -build.extra_flags.esp32c3=-DARDUINO_USB_CDC_ON_BOOT=0 +build.extra_flags.esp32c3=-DARDUINO_HW_CDC_ON_BOOT={build.cdc_on_boot} # # ESP32C3 Support End #