From 7441c5a4b223f05eb807653db43f4e04d9c95af4 Mon Sep 17 00:00:00 2001 From: Jesus Date: Sat, 15 Oct 2022 18:48:02 +0200 Subject: [PATCH] cdc_usbserial --- examples/device/cdc_usbserial/CMakeLists.txt | 28 ++ examples/device/cdc_usbserial/Makefile | 12 + examples/device/cdc_usbserial/samd21 | 1 + examples/device/cdc_usbserial/src/debug.c | 33 ++ examples/device/cdc_usbserial/src/debug.h | 7 + .../device/cdc_usbserial/src/hal_config.h | 129 ++++++++ examples/device/cdc_usbserial/src/hal_gpio.h | 126 ++++++++ examples/device/cdc_usbserial/src/main.c | 129 ++++++++ .../device/cdc_usbserial/src/tusb_config.h | 111 +++++++ examples/device/cdc_usbserial/src/uart.c | 287 ++++++++++++++++++ examples/device/cdc_usbserial/src/uart.h | 84 +++++ .../cdc_usbserial/src/usb_descriptors.c | 184 +++++++++++ .../device/cdc_usbserial/src/usbcdc_app.c | 236 ++++++++++++++ .../device/cdc_usbserial/src/usbcdc_app.h | 28 ++ examples/device/cdc_usbserial/src/usbserial.c | 203 +++++++++++++ examples/device/cdc_usbserial/src/usbserial.h | 26 ++ examples/make.mk | 6 +- hw/bsp/samd21/boards/mini/board.h | 51 ++++ hw/bsp/samd21/boards/mini/board.mk | 11 + hw/bsp/samd21/boards/mini/mini.ld | 146 +++++++++ hw/bsp/samd21/family.c | 30 ++ 21 files changed, 1865 insertions(+), 3 deletions(-) create mode 100644 examples/device/cdc_usbserial/CMakeLists.txt create mode 100644 examples/device/cdc_usbserial/Makefile create mode 120000 examples/device/cdc_usbserial/samd21 create mode 100644 examples/device/cdc_usbserial/src/debug.c create mode 100644 examples/device/cdc_usbserial/src/debug.h create mode 100755 examples/device/cdc_usbserial/src/hal_config.h create mode 100755 examples/device/cdc_usbserial/src/hal_gpio.h create mode 100644 examples/device/cdc_usbserial/src/main.c create mode 100644 examples/device/cdc_usbserial/src/tusb_config.h create mode 100644 examples/device/cdc_usbserial/src/uart.c create mode 100644 examples/device/cdc_usbserial/src/uart.h create mode 100644 examples/device/cdc_usbserial/src/usb_descriptors.c create mode 100755 examples/device/cdc_usbserial/src/usbcdc_app.c create mode 100755 examples/device/cdc_usbserial/src/usbcdc_app.h create mode 100755 examples/device/cdc_usbserial/src/usbserial.c create mode 100755 examples/device/cdc_usbserial/src/usbserial.h create mode 100644 hw/bsp/samd21/boards/mini/board.h create mode 100644 hw/bsp/samd21/boards/mini/board.mk create mode 100644 hw/bsp/samd21/boards/mini/mini.ld diff --git a/examples/device/cdc_usbserial/CMakeLists.txt b/examples/device/cdc_usbserial/CMakeLists.txt new file mode 100644 index 00000000..abc4d91d --- /dev/null +++ b/examples/device/cdc_usbserial/CMakeLists.txt @@ -0,0 +1,28 @@ +cmake_minimum_required(VERSION 3.5) + +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) + +# gets PROJECT name for the example (e.g. -) +family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) + +project(${PROJECT}) + +# Checks this example is valid for the family and initializes the project +family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) + +add_executable(${PROJECT}) + +# Example source +target_sources(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c + ) + +# Example include +target_include_directories(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) + +# Configure compilation flags and libraries for the example... see the corresponding function +# in hw/bsp/FAMILY/family.cmake for details. +family_configure_device_example(${PROJECT}) \ No newline at end of file diff --git a/examples/device/cdc_usbserial/Makefile b/examples/device/cdc_usbserial/Makefile new file mode 100644 index 00000000..5a455078 --- /dev/null +++ b/examples/device/cdc_usbserial/Makefile @@ -0,0 +1,12 @@ +include ../../../tools/top.mk +include ../../make.mk + +INC += \ + src \ + $(TOP)/hw \ + +# Example source +EXAMPLE_SOURCE += $(wildcard src/*.c) +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) + +include ../../rules.mk diff --git a/examples/device/cdc_usbserial/samd21 b/examples/device/cdc_usbserial/samd21 new file mode 120000 index 00000000..bad2cb45 --- /dev/null +++ b/examples/device/cdc_usbserial/samd21 @@ -0,0 +1 @@ +/home/user/tinyusb/hw/bsp/samd21/ \ No newline at end of file diff --git a/examples/device/cdc_usbserial/src/debug.c b/examples/device/cdc_usbserial/src/debug.c new file mode 100644 index 00000000..9e1661e8 --- /dev/null +++ b/examples/device/cdc_usbserial/src/debug.c @@ -0,0 +1,33 @@ +#include +#include +#include +#include + +#include "sam.h" +#include "samd21.h" + +#include "uart.h" +#include "tusb.h" + +#define DEBUG_CDC_ITF 0 + + + + +void debug_puts(char *s) +{ + while (*s) { + tud_cdc_n_write_char(DEBUG_CDC_ITF, *s++); + } + tud_cdc_n_write_flush(DEBUG_CDC_ITF); +} + +void debug_putb(bool b) { + if( b ) { + debug_puts((char *)"1"); + } else { + debug_puts((char *)"0"); + } +} + + diff --git a/examples/device/cdc_usbserial/src/debug.h b/examples/device/cdc_usbserial/src/debug.h new file mode 100644 index 00000000..d12a9ef1 --- /dev/null +++ b/examples/device/cdc_usbserial/src/debug.h @@ -0,0 +1,7 @@ +#ifndef DEBUG_H_ +#define DEBUG_H_ + + +void debug_puts(char *s); +void debug_putb(bool b); +#endif /* DEBUG_H_ */ \ No newline at end of file diff --git a/examples/device/cdc_usbserial/src/hal_config.h b/examples/device/cdc_usbserial/src/hal_config.h new file mode 100755 index 00000000..9aba1000 --- /dev/null +++ b/examples/device/cdc_usbserial/src/hal_config.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2021, Alex Taradov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _HAL_CONFIG_H_ +#define _HAL_CONFIG_H_ + + +#include "hal_gpio.h" + +#define F_CPU 48000000 + + + HAL_GPIO_PIN(nRESET, A, 2); + HAL_GPIO_PIN(GPIO0, A, 4); + + HAL_GPIO_PIN(EN6, A, 2); + HAL_GPIO_PIN(EN5, A, 4); + HAL_GPIO_PIN(EN4, A, 5); + HAL_GPIO_PIN(EN3, A, 4); + HAL_GPIO_PIN(EN2, A, 5); + HAL_GPIO_PIN(EN1, A, 14); + +/* + HAL_GPIO_PIN(UART1_TX, A, 4); + HAL_GPIO_PIN(UART1_RX, A, 5); + #define UART1_SERCOM SERCOM0 + #define UART1_SERCOM_PMUX PORT_PMUX_PMUXE_C_Val + #define UART1_SERCOM_GCLK_ID SERCOM0_GCLK_ID_CORE + #define UART1_SERCOM_APBCMASK PM_APBCMASK_SERCOM0 + #define UART1_SERCOM_IRQ_INDEX SERCOM0_IRQn + #define UART1_SERCOM_IRQ_HANDLER irq_handler_sercom0 + #define UART1_SERCOM_TXPO 1 //PAD[2] + #define UART1_SERCOM_RXPO 3 //PAD[3] +*/ + +/* + HAL_GPIO_PIN(UART1_TX, A, 8); + HAL_GPIO_PIN(UART1_RX, A, 9); + #define UART1_SERCOM SERCOM0 + #define UART1_SERCOM_PMUX PORT_PMUX_PMUXE_D_Val + #define UART1_SERCOM_GCLK_ID SERCOM0_GCLK_ID_CORE + #define UART1_SERCOM_APBCMASK PM_APBCMASK_SERCOM0 + #define UART1_SERCOM_IRQ_INDEX SERCOM0_IRQn + #define UART1_SERCOM_IRQ_HANDLER irq_handler_sercom0 + #define UART1_SERCOM_TXPO 1 //PAD[2] + #define UART1_SERCOM_RXPO 3 //PAD[3] +*/ + + + HAL_GPIO_PIN(UART1_TX, A, 14); + HAL_GPIO_PIN(UART1_RX, A, 15); + #define UART0_SERCOM SERCOM2 + #define UART0_SERCOM_PMUX PORT_PMUX_PMUXE_C_Val + #define UART0_SERCOM_GCLK_ID SERCOM2_GCLK_ID_CORE + #define UART0_SERCOM_APBCMASK PM_APBCMASK_SERCOM2 + #define UART0_SERCOM_IRQ_INDEX SERCOM2_IRQn + #define UART0_SERCOM_IRQ_HANDLER irq_handler_sercom2 + #define UART0_SERCOM_TXPO 1 //PAD[2] + #define UART0_SERCOM_RXPO 3 //PAD[3] + + +/* + HAL_GPIO_PIN(UART0_TX, B, 8); + HAL_GPIO_PIN(UART0_RX, B, 9); + #define UART0_SERCOM SERCOM4 + #define UART0_SERCOM_PMUX PORT_PMUX_PMUXE_D_Val + #define UART0_SERCOM_GCLK_ID SERCOM4_GCLK_ID_CORE + #define UART0_SERCOM_APBCMASK PM_APBCMASK_SERCOM4 + #define UART0_SERCOM_IRQ_INDEX SERCOM4_IRQn + #define UART0_SERCOM_IRQ_HANDLER irq_handler_sercom4 + #define UART0_SERCOM_TXPO 0 //PAD[0] + #define UART0_SERCOM_RXPO 1 //PAD[1] +*/ + + HAL_GPIO_PIN(UART0_TX, A, 16); + HAL_GPIO_PIN(UART0_RX, A, 17); + #define UART1_SERCOM SERCOM1 + #define UART1_SERCOM_PMUX PORT_PMUX_PMUXE_C_Val + #define UART1_SERCOM_GCLK_ID SERCOM1_GCLK_ID_CORE + #define UART1_SERCOM_APBCMASK PM_APBCMASK_SERCOM1 + #define UART1_SERCOM_IRQ_INDEX SERCOM1_IRQn + #define UART1_SERCOM_IRQ_HANDLER irq_handler_sercom1 + #define UART1_SERCOM_TXPO 0 //PAD[0] + #define UART1_SERCOM_RXPO 1 //PAD[1] + + + + + + +/* SERCOM UART available pad settings +enum uart_pad_settings { + UART_RX_PAD0_TX_PAD2 = SERCOM_USART_CTRLA_RXPO(0) | SERCOM_USART_CTRLA_TXPO(1), + UART_RX_PAD1_TX_PAD2 = SERCOM_USART_CTRLA_RXPO(1) | SERCOM_USART_CTRLA_TXPO(1), + UART_RX_PAD2_TX_PAD0 = SERCOM_USART_CTRLA_RXPO(2), + UART_RX_PAD3_TX_PAD0 = SERCOM_USART_CTRLA_RXPO(3), + UART_RX_PAD1_TX_PAD0 = SERCOM_USART_CTRLA_RXPO(1), + UART_RX_PAD3_TX_PAD2 = SERCOM_USART_CTRLA_RXPO(3) | SERCOM_USART_CTRLA_TXPO(1), +}; + +*/ + +#endif // _HAL_CONFIG_H_ + diff --git a/examples/device/cdc_usbserial/src/hal_gpio.h b/examples/device/cdc_usbserial/src/hal_gpio.h new file mode 100755 index 00000000..8510d8f5 --- /dev/null +++ b/examples/device/cdc_usbserial/src/hal_gpio.h @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2014-2016, Alex Taradov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _HAL_GPIO_H_ +#define _HAL_GPIO_H_ + +/*- Definitions -------------------------------------------------------------*/ +#define HAL_GPIO_PORTA 0 +#define HAL_GPIO_PORTB 1 +#define HAL_GPIO_PORTC 2 + +#define HAL_GPIO_PMUX_A 0 +#define HAL_GPIO_PMUX_B 1 +#define HAL_GPIO_PMUX_C 2 +#define HAL_GPIO_PMUX_D 3 +#define HAL_GPIO_PMUX_E 4 +#define HAL_GPIO_PMUX_F 5 +#define HAL_GPIO_PMUX_G 6 +#define HAL_GPIO_PMUX_H 7 +#define HAL_GPIO_PMUX_I 8 + +#define HAL_GPIO_PIN(name, port, pin) \ + static inline void HAL_GPIO_##name##_set(void) \ + { \ + PORT->Group[HAL_GPIO_PORT##port].OUTSET.reg = (1 << pin); \ + (void)HAL_GPIO_##name##_set; \ + } \ + \ + static inline void HAL_GPIO_##name##_clr(void) \ + { \ + PORT->Group[HAL_GPIO_PORT##port].OUTCLR.reg = (1 << pin); \ + (void)HAL_GPIO_##name##_clr; \ + } \ + \ + static inline void HAL_GPIO_##name##_toggle(void) \ + { \ + PORT->Group[HAL_GPIO_PORT##port].OUTTGL.reg = (1 << pin); \ + (void)HAL_GPIO_##name##_toggle; \ + } \ + \ + static inline void HAL_GPIO_##name##_write(int value) \ + { \ + if (value) \ + PORT->Group[HAL_GPIO_PORT##port].OUTSET.reg = (1 << pin); \ + else \ + PORT->Group[HAL_GPIO_PORT##port].OUTCLR.reg = (1 << pin); \ + (void)HAL_GPIO_##name##_write; \ + } \ + \ + static inline void HAL_GPIO_##name##_in(void) \ + { \ + PORT->Group[HAL_GPIO_PORT##port].DIRCLR.reg = (1 << pin); \ + PORT->Group[HAL_GPIO_PORT##port].PINCFG[pin].reg |= PORT_PINCFG_INEN; \ + PORT->Group[HAL_GPIO_PORT##port].PINCFG[pin].reg &= ~PORT_PINCFG_PULLEN; \ + (void)HAL_GPIO_##name##_in; \ + } \ + \ + static inline void HAL_GPIO_##name##_out(void) \ + { \ + PORT->Group[HAL_GPIO_PORT##port].DIRSET.reg = (1 << pin); \ + PORT->Group[HAL_GPIO_PORT##port].PINCFG[pin].reg |= PORT_PINCFG_INEN; \ + (void)HAL_GPIO_##name##_out; \ + } \ + \ + static inline void HAL_GPIO_##name##_pullup(void) \ + { \ + PORT->Group[HAL_GPIO_PORT##port].OUTSET.reg = (1 << pin); \ + PORT->Group[HAL_GPIO_PORT##port].PINCFG[pin].reg |= PORT_PINCFG_PULLEN; \ + (void)HAL_GPIO_##name##_pullup; \ + } \ + \ + static inline int HAL_GPIO_##name##_read(void) \ + { \ + return (PORT->Group[HAL_GPIO_PORT##port].IN.reg & (1 << pin)) != 0; \ + (void)HAL_GPIO_##name##_read; \ + } \ + \ + static inline int HAL_GPIO_##name##_state(void) \ + { \ + return (PORT->Group[HAL_GPIO_PORT##port].DIR.reg & (1 << pin)) != 0; \ + (void)HAL_GPIO_##name##_state; \ + } \ + \ + static inline void HAL_GPIO_##name##_pmuxen(int mux) \ + { \ + PORT->Group[HAL_GPIO_PORT##port].PINCFG[pin].reg |= PORT_PINCFG_PMUXEN; \ + if (pin & 1) \ + PORT->Group[HAL_GPIO_PORT##port].PMUX[pin>>1].bit.PMUXO = mux; \ + else \ + PORT->Group[HAL_GPIO_PORT##port].PMUX[pin>>1].bit.PMUXE = mux; \ + (void)HAL_GPIO_##name##_pmuxen; \ + } \ + \ + static inline void HAL_GPIO_##name##_pmuxdis(void) \ + { \ + PORT->Group[HAL_GPIO_PORT##port].PINCFG[pin].reg &= ~PORT_PINCFG_PMUXEN; \ + (void)HAL_GPIO_##name##_pmuxdis; \ + } \ + +#endif // _HAL_GPIO_H_ + diff --git a/examples/device/cdc_usbserial/src/main.c b/examples/device/cdc_usbserial/src/main.c new file mode 100644 index 00000000..07e22472 --- /dev/null +++ b/examples/device/cdc_usbserial/src/main.c @@ -0,0 +1,129 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * 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 + +#include "sam.h" +#include "samd21.h" + +#include "bsp/board.h" +#include "tusb.h" + + +#include "uart.h" +#include "usbserial.h" +#include "usbcdc_app.h" + + +#define CDC_ITF_0 0 +#define CDC_ITF_1 1 +#define CDC_ITF_2 2 + +#define DOUBLE_TAP_MAGIC 0x07738135 //MattairTech bootloader .arduino15/packages/MattairTech_Arduino/hardware/samd/1.6.18-beta-b1/bootloaders/zero/sam_ba_Generic_x21E_SAMD21E18A.bin +#define BOOT_DOUBLE_TAP_ADDRESS (HMCRAMC0_ADDR + HMCRAMC0_SIZE - 4) +#define BOOT_DOUBLE_TAP_DATA (*((volatile uint32_t *) BOOT_DOUBLE_TAP_ADDRESS)) +#define BOOT_DOUBLE_TAP_ITF CDC_ITF_0 + + + + + +//----------------------------------------------------------------------------- + +/* +static void cdc_task_echo(int USBCDC) { + int byte; + + if ( tud_cdc_n_available(USBCDC) ) { + byte = tud_cdc_n_read_char(USBCDC); + tud_cdc_n_write_char(USBCDC, byte); + } + tud_cdc_n_write_flush(USBCDC); +} +*/ + +uint64_t reboot_status_timeout; +//----------------------------------------------------------------------------- +static void reboot_timer_task(void) +{ + if (reboot_status_timeout && (board_millis() > reboot_status_timeout) ) { + NVIC_SystemReset(); + } + +} + + + +/*------------- MAIN -------------*/ +int main(void) +{ + board_init(); + +HAL_GPIO_UART0_ESP_PIN_RESET_in(); +HAL_GPIO_UART1_ESP_PIN_RESET_in(); +HAL_GPIO_UART0_ESP_PIN_BOOT_in(); +HAL_GPIO_UART1_ESP_PIN_BOOT_in(); + + //uart_n_init(UART0, 115200); + //uart_n_init(UART1,115200); + + + tud_init(BOARD_TUD_RHPORT); // init device stack on configured roothub port + + usbcdc_app_init( CDC_ITF_0 ); + usb_serial_esp_init( USB_SERIAL_1, CDC_ITF_1, UART0, 115200, UART0_ESP_PIN_BOOT, UART0_ESP_PIN_RESET); + usb_serial_esp_init( USB_SERIAL_2, CDC_ITF_2, UART1, 115200, UART1_ESP_PIN_BOOT, UART1_ESP_PIN_RESET); + + while (1) + { + tud_task(); // tinyusb device task + + usbcdc_app_task( CDC_ITF_0 ); + usb_serial_esp_task( USB_SERIAL_1 ); + usb_serial_esp_task( USB_SERIAL_2 ); + //cdc_task_echo( CDC_ITF_2 ); + + reboot_timer_task(); + } + + + return 0; +} + +void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding) +{ + if(itf == BOOT_DOUBLE_TAP_ITF) { + if( p_line_coding->bit_rate == 1200 ) { + BOOT_DOUBLE_TAP_DATA = DOUBLE_TAP_MAGIC; + reboot_status_timeout = board_millis() + 250; + return; + } + } + usb_serial_n_line_coding( itf, p_line_coding); + return; +} diff --git a/examples/device/cdc_usbserial/src/tusb_config.h b/examples/device/cdc_usbserial/src/tusb_config.h new file mode 100644 index 00000000..578bd5b2 --- /dev/null +++ b/examples/device/cdc_usbserial/src/tusb_config.h @@ -0,0 +1,111 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * 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 _TUSB_CONFIG_H_ +#define _TUSB_CONFIG_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Board Specific Configuration +//--------------------------------------------------------------------+ + +// RHPort number used for device can be defined by board.mk, default to port 0 +#ifndef BOARD_TUD_RHPORT +#define BOARD_TUD_RHPORT 0 +#endif + +// RHPort max operational speed can defined by board.mk +#ifndef BOARD_TUD_MAX_SPEED +#define BOARD_TUD_MAX_SPEED OPT_MODE_DEFAULT_SPEED +#endif + +//-------------------------------------------------------------------- +// COMMON CONFIGURATION +//-------------------------------------------------------------------- + +// defined by board.mk +#ifndef CFG_TUSB_MCU +#error CFG_TUSB_MCU must be defined +#endif + +#ifndef CFG_TUSB_OS +#define CFG_TUSB_OS OPT_OS_NONE +#endif + +#ifndef CFG_TUSB_DEBUG +#define CFG_TUSB_DEBUG 0 +#endif + +// Enable Device stack +#define CFG_TUD_ENABLED 1 + +// Default is max speed that hardware controller could support with on-chip PHY +#define CFG_TUD_MAX_SPEED BOARD_TUD_MAX_SPEED + +/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#endif + +//-------------------------------------------------------------------- +// DEVICE CONFIGURATION +//-------------------------------------------------------------------- + +#ifndef CFG_TUD_ENDPOINT0_SIZE +#define CFG_TUD_ENDPOINT0_SIZE 64 +#endif + +//------------- CLASS -------------// +#define CFG_TUD_CDC 3 +#define CFG_TUD_MSC 0 +#define CFG_TUD_HID 0 +#define CFG_TUD_MIDI 0 +#define CFG_TUD_VENDOR 0 + +// CDC FIFO size of TX and RX +#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) +#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) + +// CDC Endpoint transfer buffer size, more is faster +#define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_CONFIG_H_ */ diff --git a/examples/device/cdc_usbserial/src/uart.c b/examples/device/cdc_usbserial/src/uart.c new file mode 100644 index 00000000..aad8a42f --- /dev/null +++ b/examples/device/cdc_usbserial/src/uart.c @@ -0,0 +1,287 @@ +#include "sam.h" +#include "bsp/board.h" +#include "samd21.h" + +#include "hal/include/hal_gpio.h" +#include "hal/include/hal_init.h" +#include "hri/hri_nvmctrl_d21.h" + +#include "hpl/gclk/hpl_gclk_base.h" +#include "hpl_pm_config.h" +#include "hpl/pm/hpl_pm_base.h" + +#include "uart.h" + +#define UART_BUF_SIZE 64 + +typedef struct +{ + int wr; + int rd; + uint8_t data[UART_BUF_SIZE]; +} fifo_buffer_t; + + +//static volatile fifo_buffer_t uart0_rx_fifo; +//static volatile fifo_buffer_t uart0_tx_fifo; + +typedef struct +{ + Sercom* module; + int8_t pmux; + uint8_t gclk_id; + int8_t apbcmask; + int8_t irq_index; + int8_t irq_handler; + int8_t tx_pad; + int8_t rx_pad; + uint32_t tx_pin; + uint32_t rx_pin; + long int tx_mux; + long int rx_mux; + + uint8_t itf_num; + + volatile int line_state; + + + //RING + volatile fifo_buffer_t rx_fifo; + volatile fifo_buffer_t tx_fifo; + + +} uart_interface_t; + + +static uart_interface_t uart_itf[]={ + { + .module = UART0_SERCOM , + .pmux = UART0_SERCOM_PMUX, + .gclk_id = UART0_SERCOM_GCLK_ID, + .apbcmask = UART0_SERCOM_APBCMASK, + .irq_index = UART0_SERCOM_IRQ_INDEX, + .tx_pad = UART0_SERCOM_PAD_TX, + .rx_pad = UART0_SERCOM_PAD_RX, + .tx_pin = UART0_SERCOM_PIN_TX, + .rx_pin = UART0_SERCOM_PIN_RX, + .tx_mux = UART0_SERCOM_PMUX_TX, + .rx_mux = UART0_SERCOM_PMUX_RX, + }, + { + .module = UART1_SERCOM , + .pmux = UART1_SERCOM_PMUX, + .gclk_id = UART1_SERCOM_GCLK_ID, + .apbcmask = UART1_SERCOM_APBCMASK, + .irq_index = UART1_SERCOM_IRQ_INDEX, + .tx_pad = UART1_SERCOM_PAD_TX, + .rx_pad = UART1_SERCOM_PAD_RX, + .tx_pin = UART1_SERCOM_PIN_TX, + .rx_pin = UART1_SERCOM_PIN_RX, + .tx_mux = UART1_SERCOM_PMUX_TX, + .rx_mux = UART1_SERCOM_PMUX_RX, + }, +}; + + + + + +void uart_n_init(int port, uint32_t dwDTERate) +{ + + uart_interface_t* UART = &uart_itf[port]; + + Sercom* SERCOM = UART->module; + + NVIC_DisableIRQ(UART->irq_index); + + gpio_set_pin_function(UART->tx_pin, UART->tx_mux); + gpio_set_pin_function(UART->rx_pin, UART->rx_mux); + + + UART->tx_fifo.wr = 0; + UART->tx_fifo.rd = 0; + UART->rx_fifo.wr = 0; + UART->rx_fifo.rd = 0; + + PM->APBCMASK.reg |= UART->apbcmask; + + // setup clock (48MHz) + _pm_enable_bus_clock(PM_BUS_APBC, SERCOM); + _gclk_enable_channel(UART->gclk_id, GCLK_CLKCTRL_GEN_GCLK0_Val); + + SERCOM->USART.CTRLA.bit.SWRST = 1; /* reset SERCOM & enable config */ + while(SERCOM->USART.SYNCBUSY.bit.SWRST); + + SERCOM->USART.CTRLA.reg = /* CMODE = 0 -> async, SAMPA = 0, FORM = 0 -> USART frame, SMPR = 0 -> arithmetic baud rate */ + SERCOM_USART_CTRLA_SAMPR(1) | /* 0 = 16x / arithmetic baud rate, 1 = 16x / fractional baud rate */ + SERCOM_USART_CTRLA_FORM(0) | /* 0 = USART Frame, 2 = LIN Master */ + SERCOM_USART_CTRLA_DORD | /* LSB first */ + SERCOM_USART_CTRLA_MODE(1) | /* 0 = Asynchronous, 1 = USART with internal clock */ + SERCOM_USART_CTRLA_RXPO(UART->rx_pad) | + SERCOM_USART_CTRLA_TXPO(UART->tx_pad) ; + + + SERCOM->USART.CTRLB.reg = + SERCOM_USART_CTRLB_TXEN | /* tx enabled */ + SERCOM_USART_CTRLB_RXEN | /* rx enabled */ + SERCOM_USART_CTRLB_CHSIZE(0) | 0 | 0; + + + + int baud = F_CPU / (16 * dwDTERate); + int fp = (F_CPU / dwDTERate - 16 * baud) / 2; + + SERCOM->USART.BAUD.reg = SERCOM_USART_BAUD_FRACFP_BAUD(baud) | SERCOM_USART_BAUD_FRACFP_FP(fp); + + SERCOM->USART.CTRLA.reg |= SERCOM_USART_CTRLA_ENABLE; + SERCOM->USART.INTENSET.reg = SERCOM_USART_INTENSET_RXC; + + + SERCOM->USART.CTRLA.bit.ENABLE = 1; /* activate SERCOM */ + while(SERCOM->USART.SYNCBUSY.bit.ENABLE); /* wait for SERCOM to be ready */ + + NVIC_EnableIRQ(UART->irq_index); + +} + + + +static inline void uart_n_send_buffer(int port, uint8_t const *text, size_t len) +{ + uart_interface_t* UART = &uart_itf[port]; + Sercom* SERCOM = UART->module; + for (size_t i = 0; i < len; ++i) { + SERCOM->USART.DATA.reg = text[i]; + while((SERCOM->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_TXC) == 0); + } +} + +static inline void uart_n_send_str(int port,const char* text) +{ + Sercom* SERCOM = uart_itf[port].module; + while (*text) { + SERCOM->USART.DATA.reg = *text++; + while((SERCOM->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_TXC) == 0); + } +} + + + + + +//----------------------------------------------------------------------------- +bool uart_n_write_byte(int port, int byte) +{ + uart_interface_t* UART = &uart_itf[port]; + Sercom* SERCOM = UART->module; + bool res = false; + + NVIC_DisableIRQ(UART->irq_index); + + int wr = (UART->tx_fifo.wr + 1) % UART_BUF_SIZE; + + if ( UART->tx_fifo.rd != wr ) + { + UART->tx_fifo.data[UART->tx_fifo.wr] = byte; + UART->tx_fifo.wr = wr; + res = true; + + SERCOM->USART.INTENSET.reg = SERCOM_USART_INTENSET_DRE; + } + + NVIC_EnableIRQ(UART->irq_index); + + return res; +} + +//----------------------------------------------------------------------------- +bool uart_n_read_byte(int port, int *byte) +{ + uart_interface_t* UART = &uart_itf[port]; + bool res = false; + + + + NVIC_DisableIRQ(UART->irq_index); + + + if ( UART->rx_fifo.wr != UART->rx_fifo.rd) + { + *byte = UART->rx_fifo.data[UART->rx_fifo.rd]; + UART->rx_fifo.rd = (UART->rx_fifo.rd + 1) % UART_BUF_SIZE; + res = true; + } + + NVIC_EnableIRQ(UART->irq_index); + + + return res; +} + + +void uart_n_serial_state_update(int port, int state) +{ + (void)port; + (void)state; + // uart_serial_state_update(0, state); +} + +//----------------------------------------------------------------------------- +void SERCOM_IRQ_HANDLER(int port) +{ + uart_interface_t* UART = &uart_itf[port]; + Sercom* SERCOM = UART->module; + + int flags = SERCOM->USART.INTFLAG.reg; + + if (flags & SERCOM_USART_INTFLAG_RXC) + { + int status = SERCOM->USART.STATUS.reg; + int byte = SERCOM->USART.DATA.reg; + + if (status & SERCOM_USART_STATUS_BUFOVF) + uart_n_serial_state_update(port,SERCOM_USART_STATUS_BUFOVF); + + int wr = (UART->rx_fifo.wr + 1) % UART_BUF_SIZE; + + + if (UART->rx_fifo.rd != wr) + { + UART->rx_fifo.data[UART->rx_fifo.wr] = byte; + UART->rx_fifo.wr = wr; + + } else { + uart_n_serial_state_update(port, SERCOM_USART_STATUS_BUFOVF); + } + } + + if (flags & SERCOM_USART_INTFLAG_DRE) + { + if ( UART->tx_fifo.rd != UART->tx_fifo.wr ) + { + SERCOM->USART.DATA.reg = UART->tx_fifo.data[UART->tx_fifo.rd]; + UART->tx_fifo.rd = (UART->tx_fifo.rd + 1) % UART_BUF_SIZE;; + } + else + { + SERCOM->USART.INTENCLR.reg = SERCOM_USART_INTENCLR_DRE; + } + } + +} + + +#ifdef UART0 +void UART0_SERCOM_IRQ_HANDLER(void) +{ + SERCOM_IRQ_HANDLER(UART0); +} +#endif + +#ifdef UART1 +void UART1_SERCOM_IRQ_HANDLER(void) +{ + SERCOM_IRQ_HANDLER(UART1); +} +#endif diff --git a/examples/device/cdc_usbserial/src/uart.h b/examples/device/cdc_usbserial/src/uart.h new file mode 100644 index 00000000..d200ed16 --- /dev/null +++ b/examples/device/cdc_usbserial/src/uart.h @@ -0,0 +1,84 @@ + +#include "hal_gpio.h" + +#define F_CPU 48000000 + + +#define UART0 0 +#define UART1 1 +#define UART_NUM 2 + + + #define UART0_SERCOM SERCOM2 + #define UART0_SERCOM_PMUX PORT_PMUX_PMUXE_C_Val + #define UART0_SERCOM_GCLK_ID SERCOM2_GCLK_ID_CORE + #define UART0_SERCOM_APBCMASK PM_APBCMASK_SERCOM2 + #define UART0_SERCOM_IRQ_INDEX SERCOM2_IRQn + #define UART0_SERCOM_IRQ_HANDLER SERCOM2_Handler + #define UART0_SERCOM_PAD_TX 1 //PAD[2] + #define UART0_SERCOM_PAD_RX 3 //PAD[3] + #define UART0_SERCOM_PIN_TX PIN_PA14 + #define UART0_SERCOM_PIN_RX PIN_PA15 + #define UART0_SERCOM_PMUX_TX PINMUX_PA14C_SERCOM2_PAD2 + #define UART0_SERCOM_PMUX_RX PINMUX_PA15C_SERCOM2_PAD3 + + #define UART0_ESP_PIN_RESET PIN_PA10 + #define UART0_ESP_PIN_BOOT PIN_PA11 + + HAL_GPIO_PIN(UART0_ESP_PIN_RESET, A, 10); + HAL_GPIO_PIN(UART0_ESP_PIN_BOOT, A, 11); + +/* + #define UART1_SERCOM SERCOM0 + #define UART1_SERCOM_PMUX PORT_PMUX_PMUXE_C_Val + #define UART1_SERCOM_GCLK_ID SERCOM0_GCLK_ID_CORE + #define UART1_SERCOM_APBCMASK PM_APBCMASK_SERCOM0 + #define UART1_SERCOM_IRQ_INDEX SERCOM0_IRQn + #define UART1_SERCOM_IRQ_HANDLER SERCOM0_Handler + #define UART1_SERCOM_PAD_TX 1 //PAD[2] + #define UART1_SERCOM_PAD_RX 3 //PAD[3] + #define UART1_SERCOM_PIN_TX PIN_PA10 + #define UART1_SERCOM_PIN_RX PIN_PA11 + #define UART1_SERCOM_PMUX_TX PINMUX_PA10C_SERCOM0_PAD2 + #define UART1_SERCOM_PMUX_RX PINMUX_PA11C_SERCOM0_PAD3 +*/ + + #define UART1_SERCOM SERCOM1 + #define UART1_SERCOM_PMUX PORT_PMUX_PMUXE_D_Val + #define UART1_SERCOM_GCLK_ID SERCOM1_GCLK_ID_CORE + #define UART1_SERCOM_APBCMASK PM_APBCMASK_SERCOM1 + #define UART1_SERCOM_IRQ_INDEX SERCOM1_IRQn + #define UART1_SERCOM_IRQ_HANDLER SERCOM1_Handler + #define UART1_SERCOM_PAD_TX 1 //PAD[2] + #define UART1_SERCOM_PAD_RX 3 //PAD[3] + #define UART1_SERCOM_PIN_TX PIN_PA30 + #define UART1_SERCOM_PIN_RX PIN_PA31 + #define UART1_SERCOM_PMUX_TX PINMUX_PA30D_SERCOM1_PAD2 + #define UART1_SERCOM_PMUX_RX PINMUX_PA31D_SERCOM1_PAD3 + + + #define UART1_ESP_PIN_RESET PIN_PA03 + #define UART1_ESP_PIN_BOOT PIN_PA02 + + HAL_GPIO_PIN(UART1_ESP_PIN_RESET, A, 3); + HAL_GPIO_PIN(UART1_ESP_PIN_BOOT, A, 2); + + + +void uart_n_init(int port, uint32_t dwDTERate); +bool uart_n_write_byte(int port, int byte); +bool uart_n_read_byte(int port, int *byte); + + + + +/* SERCOM UART available pad settings +enum uart_pad_settings { + UART_RX_PAD0_TX_PAD2 = SERCOM_USART_CTRLA_RXPO(0) | SERCOM_USART_CTRLA_TXPO(1), + UART_RX_PAD1_TX_PAD2 = SERCOM_USART_CTRLA_RXPO(1) | SERCOM_USART_CTRLA_TXPO(1), + UART_RX_PAD2_TX_PAD0 = SERCOM_USART_CTRLA_RXPO(2), + UART_RX_PAD3_TX_PAD0 = SERCOM_USART_CTRLA_RXPO(3), + UART_RX_PAD1_TX_PAD0 = SERCOM_USART_CTRLA_RXPO(1), + UART_RX_PAD3_TX_PAD2 = SERCOM_USART_CTRLA_RXPO(3) | SERCOM_USART_CTRLA_TXPO(1), +}; +*/ \ No newline at end of file diff --git a/examples/device/cdc_usbserial/src/usb_descriptors.c b/examples/device/cdc_usbserial/src/usb_descriptors.c new file mode 100644 index 00000000..5a7e213c --- /dev/null +++ b/examples/device/cdc_usbserial/src/usb_descriptors.c @@ -0,0 +1,184 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * 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 "tusb.h" + +/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. + * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. + * + * Auto ProductID layout's Bitmap: + * [MSB] MIDI | HID | MSC | CDC [LSB] + */ +#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) +#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ + _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) + +#define USB_VID 0xCafe +#define USB_BCD 0x0200 + +//--------------------------------------------------------------------+ +// Device Descriptors +//--------------------------------------------------------------------+ +tusb_desc_device_t const desc_device = +{ + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = USB_BCD, + + // Use Interface Association Descriptor (IAD) for CDC + // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + + .idVendor = USB_VID, + .idProduct = USB_PID, + .bcdDevice = 0x0100, + + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + + .bNumConfigurations = 0x01 +}; + +// Invoked when received GET DEVICE DESCRIPTOR +// Application return pointer to descriptor +uint8_t const * tud_descriptor_device_cb(void) +{ + return (uint8_t const *) &desc_device; +} + +//--------------------------------------------------------------------+ +// Configuration Descriptor +//--------------------------------------------------------------------+ +enum +{ + ITF_NUM_CDC_0 = 0, + ITF_NUM_CDC_0_DATA, + ITF_NUM_CDC_1, + ITF_NUM_CDC_1_DATA, + ITF_NUM_CDC_2, + ITF_NUM_CDC_2_DATA, + ITF_NUM_TOTAL +}; + +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_CDC * TUD_CDC_DESC_LEN) + + + #define EPNUM_CDC_0_NOTIF 0x81 + #define EPNUM_CDC_0_OUT 0x02 + #define EPNUM_CDC_0_IN 0x82 + + #define EPNUM_CDC_1_NOTIF 0x83 + #define EPNUM_CDC_1_OUT 0x04 + #define EPNUM_CDC_1_IN 0x84 + + #define EPNUM_CDC_2_NOTIF 0x85 + #define EPNUM_CDC_2_OUT 0x06 + #define EPNUM_CDC_2_IN 0x86 + +uint8_t const desc_fs_configuration[] = +{ + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), + + // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 64), + + // 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 64), + + // 3nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_2, 4, EPNUM_CDC_2_NOTIF, 8, EPNUM_CDC_2_OUT, EPNUM_CDC_2_IN, 64), +}; + + + +// Invoked when received GET CONFIGURATION DESCRIPTOR +// Application return pointer to descriptor +// Descriptor contents must exist long enough for transfer to complete +uint8_t const * tud_descriptor_configuration_cb(uint8_t index) +{ + (void) index; // for multiple configurations + + return desc_fs_configuration; + +} + +//--------------------------------------------------------------------+ +// String Descriptors +//--------------------------------------------------------------------+ + +// array of pointer to string descriptors +char const* string_desc_arr [] = +{ + (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) + "TinyUSB", // 1: Manufacturer + "TinyUSB Device", // 2: Product + "123456", // 3: Serials, should use chip ID + "TinyUSB CDC", // 4: CDC Interface +}; + +static uint16_t _desc_str[32]; + +// Invoked when received GET STRING DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) +{ + (void) langid; + + uint8_t chr_count; + + if ( index == 0) + { + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; + }else + { + // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. + // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors + + if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL; + + const char* str = string_desc_arr[index]; + + // Cap at max char + chr_count = (uint8_t) strlen(str); + if ( chr_count > 31 ) chr_count = 31; + + // Convert ASCII string into UTF-16 + for(uint8_t i=0; i +#include "samd21.h" + +#include "tusb.h" +#include "bsp/board.h" +#include "debug.h" + +#include "usbcdc_app.h" +#include "hal_gpio.h" + + +#define COMMAND_SIZE 25 + + +static char command[COMMAND_SIZE] = {0}; ; +static uint8_t command_pos = 0; + + + + +typedef struct +{ + bool usb1; + bool usb2; + bool usb3; + bool usb4; + + bool p1; + bool p2; + bool p3; + bool p4; + +} app_pins_t; + +static app_pins_t pins; + +uint64_t qhy8_timer_task_on = 0; +uint64_t qhy8_timer_task_off = 0; + +static void app_print( int USBCDC, char const* str ) { + tud_cdc_n_write_str(USBCDC, str); + tud_cdc_n_write_flush(USBCDC); +} + +static void qhy8_timer_task(int USBCDC) +{ + if (qhy8_timer_task_on && (board_millis() > qhy8_timer_task_on) ) { + qhy8_timer_task_on = 0; + HAL_GPIO_USB3_set(); //enciende usb3 + pins.usb3 = true; + app_print( USBCDC, "USB3 ON DELAY OK\r\n" ); + } + + if (qhy8_timer_task_off && (board_millis() > qhy8_timer_task_off) ) { + qhy8_timer_task_off = 0; + HAL_GPIO_P3_clr(); //apaga rele p3 + pins.p3 = false; + app_print( USBCDC, "P3 OFF DELAY OK\r\n" ); + } + +} + + +void usbcdc_app_init(int USBCDC) +{ + (void)USBCDC; + + HAL_GPIO_USB1_out(); + HAL_GPIO_USB1_set(); + pins.usb1 = true; + + HAL_GPIO_USB2_out(); + HAL_GPIO_USB2_set(); + pins.usb2 = true; + + HAL_GPIO_USB3_out(); + HAL_GPIO_USB3_set(); + pins.usb3 = true; + + HAL_GPIO_USB4_out(); + HAL_GPIO_USB4_set(); + pins.usb4 = true; + + HAL_GPIO_P1_out(); + HAL_GPIO_P1_set(); + pins.p1 = true; + + HAL_GPIO_P2_out(); + HAL_GPIO_P2_set(); + pins.p2 = true; + + HAL_GPIO_P3_out(); + HAL_GPIO_P3_set(); + pins.p3 = true; + + HAL_GPIO_P4_out(); + HAL_GPIO_P4_set(); + pins.p4 = true; + +} + + + +void usbcdc_app_task( int USBCDC ) { + qhy8_timer_task( USBCDC ); + + int byte = 0; + + if ( tud_cdc_n_available(USBCDC) ) { + byte = tud_cdc_n_read_char(USBCDC); + tud_cdc_n_write_char(USBCDC, byte); + tud_cdc_n_write_flush(USBCDC); + } else { + return; + } + + if( byte == '\r' ) { + + if( strcmp(command,"USB1 ON") == 0 ) { + HAL_GPIO_USB1_set(); + pins.usb1 = true; + app_print( USBCDC, "\r\nUSB1 ON OK" ); + } else if( strcmp(command,"USB1 OFF") == 0 ) { + HAL_GPIO_USB1_clr(); + pins.usb1 = false; + app_print( USBCDC, "\r\nUSB1 OFF OK" ); + } + + if( strcmp(command,"USB2 ON") == 0 ) { + HAL_GPIO_USB2_set(); + pins.usb2 = true; + app_print( USBCDC, "\r\nUSB2 ON OK" ); + } else if( strcmp(command,"USB2 OFF") == 0 ) { + HAL_GPIO_USB2_clr(); + pins.usb2 = false; + app_print( USBCDC, "\r\nUSB2 OFF OK" ); + } + + if( strcmp(command,"USB3 ON") == 0 ) { + HAL_GPIO_USB3_set(); + pins.usb3 = true; + app_print( USBCDC, "\r\nUSB3 ON OK" ); + } else if( strcmp(command,"USB3 OFF") == 0 ) { + HAL_GPIO_USB3_clr(); + pins.usb3 = false; + app_print( USBCDC, "\r\nUSB3 OFF OK" ); + + } + + if( strcmp(command,"USB4 ON") == 0 ) { + HAL_GPIO_USB4_set(); + pins.usb4 = true; + app_print( USBCDC, "\r\nUSB4 ON OK" ); + } else if( strcmp(command,"USB4 OFF") == 0 ) { + HAL_GPIO_USB4_clr(); + pins.usb4 = false; + app_print( USBCDC, "\r\nUSB4 OFF OK" ); + } + + if( strcmp(command,"P1 ON") == 0 ) { + HAL_GPIO_P1_set(); + pins.p1 = true; + app_print( USBCDC, "\r\nP1 ON OK" ); + } else if( strcmp(command,"P1 OFF") == 0 ) { + HAL_GPIO_P1_clr(); + pins.p1 = false; + app_print( USBCDC, "\r\nP1 OFF OK" ); + } + + if( strcmp(command,"P2 ON") == 0 ) { + HAL_GPIO_P2_set(); + pins.p2 = true; + app_print( USBCDC, "\r\nP2 ON OK" ); + } else if( strcmp(command,"P2 OFF") == 0 ) { + HAL_GPIO_P2_clr(); + pins.p2 = false; + app_print( USBCDC, "\r\nP2 OFF OK" ); + } + + if( strcmp(command,"P3 ON") == 0 ) { + HAL_GPIO_P3_set(); + pins.p3 = true; + app_print( USBCDC, "\r\nP3 ON OK" ); + } else if( strcmp(command,"P3 OFF") == 0 ) { + HAL_GPIO_P3_clr(); + pins.p3 = false; + app_print( USBCDC, "\r\nP3 OFF OK" ); + } + + if( strcmp(command,"P4 ON") == 0 ) { + HAL_GPIO_P4_set(); + pins.p4 = true; + app_print( USBCDC, "\r\nP4 ON OK" ); + } else if( strcmp(command,"P4 OFF") == 0 ) { + HAL_GPIO_P4_clr(); + pins.p4 = false; + app_print( USBCDC, "\r\nP4 OFF OK" ); + } + + if( strcmp(command,"QHY8L ON") == 0 ) { + HAL_GPIO_P3_set(); //enciende rele p3 + pins.p3 = true; + app_print( USBCDC, "\r\nQHY8L ON OK\r\nP3 ON OK" ); + qhy8_timer_task_on = board_millis() + 1000; //espera a encender usb3 + } else if( strcmp(command,"QHY8L OFF") == 0 ) { + HAL_GPIO_USB3_clr(); //apaga usb3 + pins.usb3 = false; + app_print( USBCDC, "\r\nQHY8L OFF OK\r\nUSB3 OFF OK" ); + qhy8_timer_task_off = board_millis() + 1000; //espera a apagar rele p3 + } + + + command_pos = 0; + memset(command, 0, COMMAND_SIZE*sizeof(uint8_t)); + + } else if( byte == '\n' || byte == '\r' ) { + } else { + command[command_pos] = byte; + command_pos++; + if( command_pos == COMMAND_SIZE ) { + command_pos = 0; + } + } + + + +} + diff --git a/examples/device/cdc_usbserial/src/usbcdc_app.h b/examples/device/cdc_usbserial/src/usbcdc_app.h new file mode 100755 index 00000000..3ae8acf2 --- /dev/null +++ b/examples/device/cdc_usbserial/src/usbcdc_app.h @@ -0,0 +1,28 @@ +/* + * usbcdc_app.h + * + * Created: 25/01/2022 18:08:31 + * Author: jesus + */ + + +#ifndef USBCDC_APP_H_ +#define USBCDC_APP_H_ + +#include "hal_gpio.h" + +HAL_GPIO_PIN(USB1, A, 19); +HAL_GPIO_PIN(USB2, A, 22); +HAL_GPIO_PIN(USB3, A, 16); +HAL_GPIO_PIN(USB4, A, 17); + +HAL_GPIO_PIN(P1, A, 7); +HAL_GPIO_PIN(P2, A, 6); +HAL_GPIO_PIN(P3, A, 5); +HAL_GPIO_PIN(P4, A, 4); + +void usbcdc_app_init(int USBCDC); +void usbcdc_app_task( int USBCDC ); + + +#endif /* USBCDC_APP_H_ */ \ No newline at end of file diff --git a/examples/device/cdc_usbserial/src/usbserial.c b/examples/device/cdc_usbserial/src/usbserial.c new file mode 100755 index 00000000..f8a1ef0b --- /dev/null +++ b/examples/device/cdc_usbserial/src/usbserial.c @@ -0,0 +1,203 @@ +/* + * usbserial.c + * + * Created: 31/07/2021 17:42:38 + * Author: jesus + */ + +#include +#include "samd21.h" +#include "uart.h" +#include "tusb.h" +#include "bsp/board.h" +#include "debug.h" + + +#include "usbserial.h" + +typedef struct +{ + int uart; + int itf; + uint32_t speed; + uint64_t gpio0_status_timeout; + uint64_t reset_status_timeout; + uint32_t gpio0_pin; + uint32_t reset_pin; + bool espboot; +} usb_serial_t; + +static usb_serial_t usb_serial[USB_SERIAL_NUM]; + +void usb_serial_init(int USBSERIAL, int USBCDC, int UART, uint32_t speed ) { + usb_serial_t* usbs = &usb_serial[USBSERIAL]; + usbs->itf = USBCDC; + usbs->uart = UART; + usbs->speed = speed; + usbs->espboot = false; + usbs->gpio0_pin = 0; + usbs->reset_pin = 0; + usbs->gpio0_status_timeout = 0; + usbs->reset_status_timeout = 0; + + uart_n_init(UART, speed); +} + +void usb_serial_esp_init(int USBSERIAL, int USBCDC, int UART, uint32_t speed, uint32_t gpio0_pin, uint32_t reset_pin) { + + usb_serial_init(USBSERIAL, USBCDC, UART, speed) ; + + usb_serial_t* usbs = &usb_serial[USBSERIAL]; + usbs->gpio0_pin = gpio0_pin; + usbs->reset_pin = reset_pin; + usbs->espboot = true; + +} + + + +void esp_boot_task(int USBSERIAL) { + + usb_serial_t* esp = &usb_serial[USBSERIAL]; + int UART = esp->uart; + + if (esp->reset_status_timeout && (board_millis() > esp->reset_status_timeout) ) { + esp->reset_status_timeout = 0; + if( UART == UART0 ) { + debug_puts( (char *)"UART0 nRST HIGH\r\n"); + HAL_GPIO_UART0_ESP_PIN_RESET_in(); + }else if( UART == UART1 ) { + debug_puts( (char *)"UART1 nRST HIGH\r\n"); + HAL_GPIO_UART1_ESP_PIN_RESET_in(); + } + + } + + if (esp->gpio0_status_timeout && (board_millis() > esp->gpio0_status_timeout) ) { + esp->gpio0_status_timeout = 0; + if( UART == UART0 ) { + debug_puts( (char *)"UART0 GPIO0 HIGH\r\n"); + HAL_GPIO_UART0_ESP_PIN_BOOT_in(); + }else if( UART == UART1 ) { + debug_puts( (char *)"UART1 GPIO0 HIGH\r\n"); + HAL_GPIO_UART1_ESP_PIN_BOOT_in(); + } + + } + +} + +void usb_serial_task( int USBSERIAL ) { + usb_serial_t* usbs = &usb_serial[USBSERIAL]; + int USBCDC = usbs->itf; + int UART = usbs->uart; + + int byte; + + while ( tud_cdc_n_available(USBCDC) ) { + byte = tud_cdc_n_read_char(USBCDC); + if( byte < 0){ break; } + else{ + while(!uart_n_write_byte(UART, byte )); + } + } + + + while (uart_n_read_byte(UART, &byte) ) + { + tud_cdc_n_write_char(USBCDC, byte); + } + tud_cdc_n_write_flush(USBCDC); + + +} + +void usb_serial_esp_task( int USBSERIAL ) { + + usb_serial_task( USBSERIAL); + + esp_boot_task( USBSERIAL ); +} + + + +int getUsbSerial(int itf){ + int usbs_id = -1; + + for (int u = 0; u < USB_SERIAL_NUM; u++) { + usb_serial_t* esp = &usb_serial[u]; + if( esp->itf == itf) { + usbs_id = u; + break; + } + } + return usbs_id; +} + +void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) +{ + int usbs_id = getUsbSerial(itf); + + if( usbs_id < 0 ) { return; } + + + usb_serial_t* esp = &usb_serial[usbs_id]; + int UART = esp->uart; + + + // connected + if ( dtr && rts ) + { + //debug_puts( (char *)"DR\r\n "); + } + + + if( esp->espboot ) { + if( !esp->gpio0_status_timeout && dtr ) { + esp->gpio0_status_timeout = board_millis() + 1000; + + if( UART == UART0 ) { + debug_puts( (char *)"UART0 GPIO0 LOW\r\n"); + HAL_GPIO_UART0_ESP_PIN_BOOT_out(); + HAL_GPIO_UART0_ESP_PIN_BOOT_clr(); + }else if( UART == UART1 ) { + debug_puts( (char *)"UART1 GPIO0 LOW\r\n "); + HAL_GPIO_UART1_ESP_PIN_BOOT_out(); + HAL_GPIO_UART1_ESP_PIN_BOOT_clr(); + } + } + + if( !esp->reset_status_timeout && !dtr && rts) { + esp->reset_status_timeout = board_millis() + 5; + + if( UART == UART0 ) { + debug_puts( (char *)"UART0 nRST LOW\r\n"); + HAL_GPIO_UART0_ESP_PIN_RESET_out(); + HAL_GPIO_UART0_ESP_PIN_RESET_clr(); + }else if( UART == UART1 ) { + debug_puts( (char *)"UART1 nRST LOW\r\n "); + HAL_GPIO_UART1_ESP_PIN_RESET_out(); + HAL_GPIO_UART1_ESP_PIN_RESET_clr(); + } + } + } + + +} + + + + +void usb_serial_n_line_coding(uint8_t itf, cdc_line_coding_t const* p_line_coding) { + + int usbs_id = getUsbSerial(itf); + if( usbs_id < 0 ) { return; } + + usb_serial_t* usbs = &usb_serial[usbs_id]; + int UART = usbs->uart; + if( p_line_coding->bit_rate != usbs->speed ) { + usbs->speed = p_line_coding->bit_rate; + //debug_puts( (char *)"line coding\r\n"); + uart_n_init(UART, p_line_coding->bit_rate); + } +} diff --git a/examples/device/cdc_usbserial/src/usbserial.h b/examples/device/cdc_usbserial/src/usbserial.h new file mode 100755 index 00000000..5864e0bf --- /dev/null +++ b/examples/device/cdc_usbserial/src/usbserial.h @@ -0,0 +1,26 @@ +/* + * usbserial.h + * + * Created: 31/07/2021 17:46:02 + * Author: jesus + */ + + +#ifndef USBSERIAL_H_ +#define USBSERIAL_H_ + +#define USB_SERIAL_1 0 +#define USB_SERIAL_2 1 + +#define USB_SERIAL_NUM 2 + + +void usb_serial_init(int USBSERIAL , int USBCDC, int UART, uint32_t speed ); +void usb_serial_task( int USBSERIAL ); + +void usb_serial_esp_init(int USBSERIAL, int USBCDC, int UART, uint32_t speed, uint32_t gpio0_pin, uint32_t reset_pin); +void usb_serial_esp_task( int USBSERIAL); + +void usb_serial_n_line_coding(uint8_t itf, cdc_line_coding_t const* p_line_coding); + +#endif /* USBSERIAL_H_ */ \ No newline at end of file diff --git a/examples/make.mk b/examples/make.mk index 47520d66..112bebfe 100644 --- a/examples/make.mk +++ b/examples/make.mk @@ -100,13 +100,13 @@ CFLAGS += \ -Wsign-compare \ -Wmissing-format-attribute \ -Wunreachable-code \ - -Wcast-align \ -Wcast-function-type \ - -Wcast-qual \ -Wnull-dereference \ -Wuninitialized \ - -Wunused \ -Wredundant-decls +# -Wunused \ +# -Wcast-align \ +# -Wcast-qual \ # conversion is too strict for most mcu driver, may be disable sign/int/arith-conversion # -Wconversion diff --git a/hw/bsp/samd21/boards/mini/board.h b/hw/bsp/samd21/boards/mini/board.h new file mode 100644 index 00000000..18044ef2 --- /dev/null +++ b/hw/bsp/samd21/boards/mini/board.h @@ -0,0 +1,51 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, Ha Thach (tinyusb.org) + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// LED is neopixel, leave unset for now +// // LED +#define LED_PIN 6 // PA10 +#define LED_STATE_ON 1 + + +// Button is wired to reset + +// UART +//#define UART_SERCOM 2 +//#define UART_RX_PIN 15 +//#define UART_TX_PIN 14 + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/samd21/boards/mini/board.mk b/hw/bsp/samd21/boards/mini/board.mk new file mode 100644 index 00000000..6cefa84c --- /dev/null +++ b/hw/bsp/samd21/boards/mini/board.mk @@ -0,0 +1,11 @@ +# For Adafruit QT Py board + +CFLAGS += -D__SAMD21E18A__ -DCFG_EXAMPLE_VIDEO_READONLY + +# All source paths should be relative to the top level. +LD_FILE = $(BOARD_PATH)/$(BOARD).ld + +# For flash-jlink target +JLINK_DEVICE = ATSAMD21E18 + +flash: flash-bossac diff --git a/hw/bsp/samd21/boards/mini/mini.ld b/hw/bsp/samd21/boards/mini/mini.ld new file mode 100644 index 00000000..f0c93340 --- /dev/null +++ b/hw/bsp/samd21/boards/mini/mini.ld @@ -0,0 +1,146 @@ +/** + * \file + * + * \brief Linker script for running in internal FLASH on the SAMD21G18A + * + * Copyright (c) 2017 Microchip Technology Inc. + * + * \asf_license_start + * + * \page License + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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 Licence 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. + * + * \asf_license_stop + * + */ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +SEARCH_DIR(.) + +/* Memory Spaces Definitions */ +MEMORY +{ + rom (rx) : ORIGIN = 0x00000000 + 8K, LENGTH = 0x00040000 - 8K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 +} + +/* The stack size used by the application. NOTE: you need to adjust according to your application. */ +STACK_SIZE = DEFINED(STACK_SIZE) ? STACK_SIZE : DEFINED(__stack_size__) ? __stack_size__ : 0x2000; + +ENTRY(Reset_Handler) + +/* Section Definitions */ +SECTIONS +{ + .text : + { + . = ALIGN(4); + _sfixed = .; + KEEP(*(.vectors .vectors.*)) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + *(.rodata .rodata* .gnu.linkonce.r.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + + /* Support C constructors, and C destructors in both user code + and the C library. This also provides support for C++ code. */ + . = ALIGN(4); + KEEP(*(.init)) + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + + . = ALIGN(4); + _efixed = .; /* End of text section */ + } > rom + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > rom + PROVIDE_HIDDEN (__exidx_end = .); + + . = ALIGN(4); + _etext = .; + + .relocate : AT (_etext) + { + . = ALIGN(4); + _srelocate = .; + *(.ramfunc .ramfunc.*); + *(.data .data.*); + . = ALIGN(4); + _erelocate = .; + } > ram + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = . ; + _szero = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + _ezero = .; + end = .; + } > ram + + /* stack section */ + .stack (NOLOAD): + { + . = ALIGN(8); + _sstack = .; + . = . + STACK_SIZE; + . = ALIGN(8); + _estack = .; + } > ram + + . = ALIGN(4); + _end = . ; +} diff --git a/hw/bsp/samd21/family.c b/hw/bsp/samd21/family.c index 494dc393..f3d88fe8 100644 --- a/hw/bsp/samd21/family.c +++ b/hw/bsp/samd21/family.c @@ -182,6 +182,36 @@ static void uart_init(void) SERCOM0->USART.CTRLA.bit.ENABLE = 1; /* activate SERCOM */ while(SERCOM0->USART.SYNCBUSY.bit.ENABLE); /* wait for SERCOM to be ready */ #endif + +#if UART_SERCOM == 2 + gpio_set_pin_function(PIN_PA14, PINMUX_PA14C_SERCOM2_PAD2); + gpio_set_pin_function(PIN_PA15, PINMUX_PA15C_SERCOM2_PAD3); + + // setup clock (48MHz) + _pm_enable_bus_clock(PM_BUS_APBC, SERCOM2); + _gclk_enable_channel(SERCOM2_GCLK_ID_CORE, GCLK_CLKCTRL_GEN_GCLK0_Val); + + SERCOM2->USART.CTRLA.bit.SWRST = 1; /* reset SERCOM & enable config */ + while(SERCOM2->USART.SYNCBUSY.bit.SWRST); + + SERCOM2->USART.CTRLA.reg = /* CMODE = 0 -> async, SAMPA = 0, FORM = 0 -> USART frame, SMPR = 0 -> arithmetic baud rate */ + SERCOM_USART_CTRLA_SAMPR(1) | /* 0 = 16x / arithmetic baud rate, 1 = 16x / fractional baud rate */ +// SERCOM_USART_CTRLA_FORM(0) | /* 0 = USART Frame, 2 = LIN Master */ + SERCOM_USART_CTRLA_DORD | /* LSB first */ + SERCOM_USART_CTRLA_MODE(1) | /* 0 = Asynchronous, 1 = USART with internal clock */ + SERCOM_USART_CTRLA_RXPO(3) | /* pad 3 */ + SERCOM_USART_CTRLA_TXPO(1); /* pad 2 */ + + SERCOM2->USART.CTRLB.reg = + SERCOM_USART_CTRLB_TXEN | /* tx enabled */ + SERCOM_USART_CTRLB_RXEN; /* rx enabled */ + + SERCOM2->USART.BAUD.reg = SERCOM_USART_BAUD_FRAC_FP(0) | SERCOM_USART_BAUD_FRAC_BAUD(26); + + SERCOM2->USART.CTRLA.bit.ENABLE = 1; /* activate SERCOM */ + while(SERCOM2->USART.SYNCBUSY.bit.ENABLE); /* wait for SERCOM to be ready */ +#endif + } static inline void uart_send_buffer(uint8_t const *text, size_t len)