cdc_usbserial

This commit is contained in:
2022-10-15 18:48:02 +02:00
parent b624664f52
commit 7441c5a4b2
21 changed files with 1865 additions and 3 deletions
@@ -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. <BOARD>-<DIR_NAME>)
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})
+12
View File
@@ -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
+1
View File
@@ -0,0 +1 @@
/home/user/tinyusb/hw/bsp/samd21/
+33
View File
@@ -0,0 +1,33 @@
#include <stdbool.h>
#include <stdalign.h>
#include <string.h>
#include <stdio.h>
#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");
}
}
@@ -0,0 +1,7 @@
#ifndef DEBUG_H_
#define DEBUG_H_
void debug_puts(char *s);
void debug_putb(bool b);
#endif /* DEBUG_H_ */
+129
View File
@@ -0,0 +1,129 @@
/*
* Copyright (c) 2021, Alex Taradov <alex@taradov.com>
* 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_
+126
View File
@@ -0,0 +1,126 @@
/*
* Copyright (c) 2014-2016, Alex Taradov <alex@taradov.com>
* 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_
+129
View File
@@ -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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#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;
}
@@ -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_ */
+287
View File
@@ -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
+84
View File
@@ -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),
};
*/
@@ -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<chr_count; i++)
{
_desc_str[1+i] = str[i];
}
}
// first byte is length (including header), second byte is string type
_desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8 ) | (2*chr_count + 2));
return _desc_str;
}
+236
View File
@@ -0,0 +1,236 @@
/*
* usbcdc_app.c
*
* Created: 25/01/2022 18:08:18
* Author: jesus
*/
/*- Includes ----------------------------------------------------------------*/
#include <stdbool.h>
#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;
}
}
}
+28
View File
@@ -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_ */
+203
View File
@@ -0,0 +1,203 @@
/*
* usbserial.c
*
* Created: 31/07/2021 17:42:38
* Author: jesus
*/
#include <stdbool.h>
#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);
}
}
+26
View File
@@ -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_ */
+3 -3
View File
@@ -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
+51
View File
@@ -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_ */
+11
View File
@@ -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
+146
View File
@@ -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 = . ;
}
+30
View File
@@ -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)