Merge branch 'master' into msp430f5529

This commit is contained in:
hathach 2019-11-10 20:12:23 +07:00 committed by GitHub
commit 620fa572bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 326 additions and 241 deletions

View File

@ -82,11 +82,16 @@ CFLAGS += \
# Debugging/Optimization # Debugging/Optimization
ifeq ($(DEBUG), 1) ifeq ($(DEBUG), 1)
CFLAGS += -Og -ggdb -DCFG_TUSB_DEBUG=2 CFLAGS += -Og -ggdb
else else
ifneq ($(BOARD), spresense) ifneq ($(BOARD),spresense)
CFLAGS += -flto -Os CFLAGS += -flto -Os
else else
CFLAGS += -Os CFLAGS += -Os
endif
endif endif
# TUSB Logging option
ifneq ($(LOG),)
CFLAGS += -DCFG_TUSB_DEBUG=$(LOG)
endif endif

View File

@ -24,8 +24,8 @@ SRC_C += \
$(ST_HAL_DRIVER)/Src/stm32f0xx_hal_cortex.c \ $(ST_HAL_DRIVER)/Src/stm32f0xx_hal_cortex.c \
$(ST_HAL_DRIVER)/Src/stm32f0xx_hal_rcc.c \ $(ST_HAL_DRIVER)/Src/stm32f0xx_hal_rcc.c \
$(ST_HAL_DRIVER)/Src/stm32f0xx_hal_rcc_ex.c \ $(ST_HAL_DRIVER)/Src/stm32f0xx_hal_rcc_ex.c \
$(ST_HAL_DRIVER)/Src/stm32f0xx_hal_gpio.c $(ST_HAL_DRIVER)/Src/stm32f0xx_hal_gpio.c \
$(ST_HAL_DRIVER)/Src/stm32f0xx_hal_uart.c
SRC_S += \ SRC_S += \
$(ST_CMSIS)/Source/Templates/gcc/startup_stm32f070xb.s $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f070xb.s

View File

@ -37,6 +37,24 @@
#define BUTTON_PIN GPIO_PIN_13 #define BUTTON_PIN GPIO_PIN_13
#define BUTTON_STATE_ACTIVE 0 #define BUTTON_STATE_ACTIVE 0
#define UARTx USART2
#define UART_GPIO_PORT GPIOA
#define UART_GPIO_AF GPIO_AF1_USART2
#define UART_TX_PIN GPIO_PIN_2
#define UART_RX_PIN GPIO_PIN_3
UART_HandleTypeDef UartHandle;
// enable all LED, Button, Uart, USB clock
static void all_rcc_clk_enable(void)
{
__HAL_RCC_GPIOA_CLK_ENABLE(); // USB D+, D-
__HAL_RCC_GPIOC_CLK_ENABLE(); // LED
//__HAL_RCC_GPIOA_CLK_ENABLE(); // Button
//__HAL_RCC_GPIOA_CLK_ENABLE(); // Uart tx, rx
__HAL_RCC_USART2_CLK_ENABLE(); // Uart module
}
void board_init(void) void board_init(void)
{ {
#if CFG_TUSB_OS == OPT_OS_NONE #if CFG_TUSB_OS == OPT_OS_NONE
@ -74,8 +92,9 @@ void board_init(void)
// Notify runtime of frequency change. // Notify runtime of frequency change.
SystemCoreClockUpdate(); SystemCoreClockUpdate();
all_rcc_clk_enable();
// LED // LED
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = LED_PIN; GPIO_InitStruct.Pin = LED_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
@ -84,13 +103,30 @@ void board_init(void)
HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct); HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct);
// Button // Button
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_InitStruct.Pin = BUTTON_PIN; GPIO_InitStruct.Pin = BUTTON_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN; GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct); HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct);
// Uart
GPIO_InitStruct.Pin = UART_TX_PIN | UART_RX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = UART_GPIO_AF;
HAL_GPIO_Init(UART_GPIO_PORT, &GPIO_InitStruct);
UartHandle.Instance = UARTx;
UartHandle.Init.BaudRate = CFG_BOARD_UART_BAUDRATE;
UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
UartHandle.Init.StopBits = UART_STOPBITS_1;
UartHandle.Init.Parity = UART_PARITY_NONE;
UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
UartHandle.Init.Mode = UART_MODE_TX_RX;
UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&UartHandle);
// Start USB clock // Start USB clock
__HAL_RCC_USB_CLK_ENABLE(); __HAL_RCC_USB_CLK_ENABLE();
} }
@ -117,8 +153,8 @@ int board_uart_read(uint8_t* buf, int len)
int board_uart_write(void const * buf, int len) int board_uart_write(void const * buf, int len)
{ {
(void) buf; (void) len; HAL_UART_Transmit(&UartHandle, (uint8_t*) buf, len, 0xffff);
return 0; return len;
} }
#if CFG_TUSB_OS == OPT_OS_NONE #if CFG_TUSB_OS == OPT_OS_NONE

View File

@ -66,8 +66,8 @@
/*#define HAL_RTC_MODULE_ENABLED */ /*#define HAL_RTC_MODULE_ENABLED */
/*#define HAL_SPI_MODULE_ENABLED */ /*#define HAL_SPI_MODULE_ENABLED */
/*#define HAL_TIM_MODULE_ENABLED */ /*#define HAL_TIM_MODULE_ENABLED */
/*#define HAL_UART_MODULE_ENABLED */ #define HAL_UART_MODULE_ENABLED
#define HAL_USART_MODULE_ENABLED /*#define HAL_USART_MODULE_ENABLED */
/*#define HAL_IRDA_MODULE_ENABLED */ /*#define HAL_IRDA_MODULE_ENABLED */
/*#define HAL_SMARTCARD_MODULE_ENABLED */ /*#define HAL_SMARTCARD_MODULE_ENABLED */
/*#define HAL_SMBUS_MODULE_ENABLED */ /*#define HAL_SMBUS_MODULE_ENABLED */

View File

@ -24,7 +24,8 @@ SRC_C += \
$(ST_HAL_DRIVER)/Src/stm32f0xx_hal_cortex.c \ $(ST_HAL_DRIVER)/Src/stm32f0xx_hal_cortex.c \
$(ST_HAL_DRIVER)/Src/stm32f0xx_hal_rcc.c \ $(ST_HAL_DRIVER)/Src/stm32f0xx_hal_rcc.c \
$(ST_HAL_DRIVER)/Src/stm32f0xx_hal_rcc_ex.c \ $(ST_HAL_DRIVER)/Src/stm32f0xx_hal_rcc_ex.c \
$(ST_HAL_DRIVER)/Src/stm32f0xx_hal_gpio.c $(ST_HAL_DRIVER)/Src/stm32f0xx_hal_gpio.c \
$(ST_HAL_DRIVER)/Src/stm32f0xx_hal_uart.c
SRC_S += \ SRC_S += \
$(ST_CMSIS)/Source/Templates/gcc/startup_stm32f072xb.s $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f072xb.s

View File

@ -37,6 +37,24 @@
#define BUTTON_PIN GPIO_PIN_0 #define BUTTON_PIN GPIO_PIN_0
#define BUTTON_STATE_ACTIVE 1 #define BUTTON_STATE_ACTIVE 1
#define UARTx USART1
#define UART_GPIO_PORT GPIOA
#define UART_GPIO_AF GPIO_AF1_USART1
#define UART_TX_PIN GPIO_PIN_9
#define UART_RX_PIN GPIO_PIN_10
UART_HandleTypeDef UartHandle;
// enable all LED, Button, Uart, USB clock
static void all_rcc_clk_enable(void)
{
__HAL_RCC_GPIOA_CLK_ENABLE(); // USB D+, D-
__HAL_RCC_GPIOC_CLK_ENABLE(); // LED
//__HAL_RCC_GPIOA_CLK_ENABLE(); // Button
//__HAL_RCC_GPIOA_CLK_ENABLE(); // Uart tx, rx
__HAL_RCC_USART1_CLK_ENABLE(); // Uart module
}
/** /**
* @brief System Clock Configuration * @brief System Clock Configuration
@ -83,12 +101,11 @@ void board_init(void)
#endif #endif
SystemClock_Config(); SystemClock_Config();
// Notify runtime of frequency change.
SystemCoreClockUpdate(); SystemCoreClockUpdate();
all_rcc_clk_enable();
// LED // LED
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = LED_PIN; GPIO_InitStruct.Pin = LED_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
@ -97,16 +114,32 @@ void board_init(void)
HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct); HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct);
// Button // Button
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = BUTTON_PIN; GPIO_InitStruct.Pin = BUTTON_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN; GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct); HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct);
// Uart
GPIO_InitStruct.Pin = UART_TX_PIN | UART_RX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = UART_GPIO_AF;
HAL_GPIO_Init(UART_GPIO_PORT, &GPIO_InitStruct);
UartHandle.Instance = UARTx;
UartHandle.Init.BaudRate = CFG_BOARD_UART_BAUDRATE;
UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
UartHandle.Init.StopBits = UART_STOPBITS_1;
UartHandle.Init.Parity = UART_PARITY_NONE;
UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
UartHandle.Init.Mode = UART_MODE_TX_RX;
UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&UartHandle);
// USB Pins // USB Pins
// Configure USB DM and DP pins. This is optional, and maintained only for user guidance. // Configure USB DM and DP pins. This is optional, and maintained only for user guidance.
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12); GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12);
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Pull = GPIO_NOPULL;
@ -139,8 +172,8 @@ int board_uart_read(uint8_t* buf, int len)
int board_uart_write(void const * buf, int len) int board_uart_write(void const * buf, int len)
{ {
(void) buf; (void) len; HAL_UART_Transmit(&UartHandle, (uint8_t*) buf, len, 0xffff);
return 0; return len;
} }
#if CFG_TUSB_OS == OPT_OS_NONE #if CFG_TUSB_OS == OPT_OS_NONE
@ -170,7 +203,8 @@ void HardFault_Handler (void)
* @retval None * @retval None
*/ */
void assert_failed(char *file, uint32_t line) void assert_failed(char *file, uint32_t line)
{ {
(void) file; (void) line;
/* USER CODE BEGIN 6 */ /* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number, /* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

View File

@ -66,8 +66,8 @@
/*#define HAL_RTC_MODULE_ENABLED */ /*#define HAL_RTC_MODULE_ENABLED */
/*#define HAL_SPI_MODULE_ENABLED */ /*#define HAL_SPI_MODULE_ENABLED */
/*#define HAL_TIM_MODULE_ENABLED */ /*#define HAL_TIM_MODULE_ENABLED */
/*#define HAL_UART_MODULE_ENABLED */ #define HAL_UART_MODULE_ENABLED
#define HAL_USART_MODULE_ENABLED //#define HAL_USART_MODULE_ENABLED
/*#define HAL_IRDA_MODULE_ENABLED */ /*#define HAL_IRDA_MODULE_ENABLED */
/*#define HAL_SMARTCARD_MODULE_ENABLED */ /*#define HAL_SMARTCARD_MODULE_ENABLED */
/*#define HAL_SMBUS_MODULE_ENABLED */ /*#define HAL_SMBUS_MODULE_ENABLED */

View File

@ -656,7 +656,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r
TU_VERIFY(request->wLength == sizeof(rsp)); TU_VERIFY(request->wLength == sizeof(rsp));
TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out);
TU_VERIFY(tud_usbtmc_check_abort_bulk_out_cb(&rsp)); TU_VERIFY(tud_usbtmc_check_abort_bulk_out_cb(&rsp));
TU_VERIFY(usbd_edpt_xfer(rhport, 0u, (void*)&rsp,sizeof(rsp))); TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp)));
return true; return true;
} }

View File

@ -124,50 +124,20 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr);
void dcd_control_status_complete(uint8_t rhport) TU_ATTR_WEAK; void dcd_control_status_complete(uint8_t rhport) TU_ATTR_WEAK;
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// Event API // Event API (Implemented by device stack)
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// Called by DCD to notify device stack // Called by DCD to notify device stack
extern void dcd_event_handler(dcd_event_t const * event, bool in_isr); extern void dcd_event_handler(dcd_event_t const * event, bool in_isr);
// helper to send bus signal event // helper to send bus signal event
static inline void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr); extern void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr);
// helper to send setup received // helper to send setup received
static inline void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr); extern void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr);
// helper to send transfer complete event // helper to send transfer complete event
static inline void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr); extern void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr);
//--------------------------------------------------------------------+
// Inline helper
//--------------------------------------------------------------------+
static inline void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr)
{
dcd_event_t event = { .rhport = rhport, .event_id = eid, };
dcd_event_handler(&event, in_isr);
}
static inline void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr)
{
dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_SETUP_RECEIVED };
memcpy(&event.setup_received, setup, 8);
dcd_event_handler(&event, in_isr);
}
static inline void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr)
{
dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_XFER_COMPLETE };
event.xfer_complete.ep_addr = ep_addr;
event.xfer_complete.len = xferred_bytes;
event.xfer_complete.result = result;
dcd_event_handler(&event, in_isr);
}
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -377,7 +377,7 @@ void tud_task (void)
case DCD_EVENT_SETUP_RECEIVED: case DCD_EVENT_SETUP_RECEIVED:
TU_LOG2(" "); TU_LOG2(" ");
TU_LOG2_MEM(&event.setup_received, 1, 8); TU_LOG1_MEM(&event.setup_received, 1, 8);
// Mark as connected after receiving 1st setup packet. // Mark as connected after receiving 1st setup packet.
// But it is easier to set it every time instead of wasting time to check then set // But it is easier to set it every time instead of wasting time to check then set
@ -386,6 +386,7 @@ void tud_task (void)
// Process control request // Process control request
if ( !process_control_request(event.rhport, &event.setup_received) ) if ( !process_control_request(event.rhport, &event.setup_received) )
{ {
TU_LOG1(" Stall EP0\r\n");
// Failed -> stall both control endpoint IN and OUT // Failed -> stall both control endpoint IN and OUT
dcd_edpt_stall(event.rhport, 0); dcd_edpt_stall(event.rhport, 0);
dcd_edpt_stall(event.rhport, 0 | TUSB_DIR_IN_MASK); dcd_edpt_stall(event.rhport, 0 | TUSB_DIR_IN_MASK);
@ -405,6 +406,7 @@ void tud_task (void)
if ( 0 == epnum ) if ( 0 == epnum )
{ {
TU_LOG1(" EP Addr = 0x%02X, len = %ld\r\n", ep_addr, event.xfer_complete.len);
usbd_control_xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); usbd_control_xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len);
} }
else else
@ -589,7 +591,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
// stall control endpoint if driver return false // stall control endpoint if driver return false
usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_complete); usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_complete);
TU_LOG2(" %s control request\r\n", _usbd_driver_str[drvid]); TU_LOG2(" %s control request\r\n", _usbd_driver_str[drvid]);
TU_ASSERT(usbd_class_drivers[drvid].control_request != NULL && TU_VERIFY(usbd_class_drivers[drvid].control_request != NULL &&
usbd_class_drivers[drvid].control_request(rhport, p_request)); usbd_class_drivers[drvid].control_request(rhport, p_request));
break; break;
} }
@ -599,7 +601,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
// stall control endpoint if driver return false // stall control endpoint if driver return false
usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_complete); usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_complete);
TU_LOG2(" %s control request\r\n", _usbd_driver_str[drvid]); TU_LOG2(" %s control request\r\n", _usbd_driver_str[drvid]);
TU_ASSERT(usbd_class_drivers[drvid].control_request != NULL && TU_VERIFY(usbd_class_drivers[drvid].control_request != NULL &&
usbd_class_drivers[drvid].control_request(rhport, p_request)); usbd_class_drivers[drvid].control_request(rhport, p_request));
} }
} }
@ -898,6 +900,31 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr)
} }
} }
void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr)
{
dcd_event_t event = { .rhport = rhport, .event_id = eid, };
dcd_event_handler(&event, in_isr);
}
void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr)
{
dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_SETUP_RECEIVED };
memcpy(&event.setup_received, setup, 8);
dcd_event_handler(&event, in_isr);
}
void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr)
{
dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_XFER_COMPLETE };
event.xfer_complete.ep_addr = ep_addr;
event.xfer_complete.len = xferred_bytes;
event.xfer_complete.result = result;
dcd_event_handler(&event, in_isr);
}
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// Helper // Helper
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+

View File

@ -1,179 +1,189 @@
/* /*
* The MIT License (MIT) * The MIT License (MIT)
* *
* Copyright (c) 2019 Ha Thach (tinyusb.org) * Copyright (c) 2019 Ha Thach (tinyusb.org)
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
* This file is part of the TinyUSB stack. * This file is part of the TinyUSB stack.
*/ */
#include "tusb_option.h" #include "tusb_option.h"
#if TUSB_OPT_DEVICE_ENABLED #if TUSB_OPT_DEVICE_ENABLED
#include "tusb.h" #include "tusb.h"
#include "device/usbd_pvt.h" #include "device/usbd_pvt.h"
#include "dcd.h" #include "dcd.h"
enum enum
{ {
EDPT_CTRL_OUT = 0x00, EDPT_CTRL_OUT = 0x00,
EDPT_CTRL_IN = 0x80 EDPT_CTRL_IN = 0x80
}; };
typedef struct typedef struct
{ {
tusb_control_request_t request; tusb_control_request_t request;
uint8_t* buffer; uint8_t* buffer;
uint16_t data_len; uint16_t data_len;
uint16_t total_xferred; uint16_t total_xferred;
bool (*complete_cb) (uint8_t, tusb_control_request_t const *); bool (*complete_cb) (uint8_t, tusb_control_request_t const *);
} usbd_control_xfer_t; } usbd_control_xfer_t;
static usbd_control_xfer_t _ctrl_xfer; static usbd_control_xfer_t _ctrl_xfer;
CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE];
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// Application API // Application API
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request) static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t const * request)
{ {
// status direction is reversed to one in the setup packet // status direction is reversed to one in the setup packet
return dcd_edpt_xfer(rhport, request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN, NULL, 0); return dcd_edpt_xfer(rhport, request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN, NULL, 0);
} }
// Transfer an transaction in Data Stage bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request)
// Each transaction has up to Endpoint0's max packet size. {
// This function can also transfer an zero-length packet _ctrl_xfer.request = (*request);
static bool _data_stage_xact(uint8_t rhport) _ctrl_xfer.buffer = NULL;
{ _ctrl_xfer.total_xferred = 0;
uint16_t const xact_len = tu_min16(_ctrl_xfer.data_len - _ctrl_xfer.total_xferred, CFG_TUD_ENDPOINT0_SIZE); _ctrl_xfer.data_len = 0;
uint8_t ep_addr = EDPT_CTRL_OUT; return _status_stage_xact(rhport, request);
}
if ( _ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_IN )
{ // Transfer an transaction in Data Stage
ep_addr = EDPT_CTRL_IN; // Each transaction has up to Endpoint0's max packet size.
if ( xact_len ) memcpy(_usbd_ctrl_buf, _ctrl_xfer.buffer, xact_len); // This function can also transfer an zero-length packet
} static bool _data_stage_xact(uint8_t rhport)
{
return dcd_edpt_xfer(rhport, ep_addr, xact_len ? _usbd_ctrl_buf : NULL, xact_len); uint16_t const xact_len = tu_min16(_ctrl_xfer.data_len - _ctrl_xfer.total_xferred, CFG_TUD_ENDPOINT0_SIZE);
}
uint8_t ep_addr = EDPT_CTRL_OUT;
bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, void* buffer, uint16_t len)
{ if ( _ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_IN )
_ctrl_xfer.request = (*request); {
_ctrl_xfer.buffer = (uint8_t*) buffer; ep_addr = EDPT_CTRL_IN;
_ctrl_xfer.total_xferred = 0; if ( xact_len ) memcpy(_usbd_ctrl_buf, _ctrl_xfer.buffer, xact_len);
_ctrl_xfer.data_len = tu_min16(len, request->wLength); }
if ( _ctrl_xfer.data_len ) return dcd_edpt_xfer(rhport, ep_addr, xact_len ? _usbd_ctrl_buf : NULL, xact_len);
{ }
TU_ASSERT(buffer);
bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, void* buffer, uint16_t len)
// Data stage {
TU_ASSERT( _data_stage_xact(rhport) ); _ctrl_xfer.request = (*request);
}else _ctrl_xfer.buffer = (uint8_t*) buffer;
{ _ctrl_xfer.total_xferred = 0;
// Status stage _ctrl_xfer.data_len = tu_min16(len, request->wLength);
TU_ASSERT( tud_control_status(rhport, request) );
} if ( _ctrl_xfer.data_len )
{
return true; TU_ASSERT(buffer);
}
// Data stage
//--------------------------------------------------------------------+ TU_ASSERT( _data_stage_xact(rhport) );
// USBD API }else
//--------------------------------------------------------------------+ {
// Status stage
void usbd_control_reset (uint8_t rhport) TU_ASSERT( _status_stage_xact(rhport, request) );
{ }
(void) rhport;
tu_varclr(&_ctrl_xfer); return true;
} }
// TODO may find a better way //--------------------------------------------------------------------+
void usbd_control_set_complete_callback( bool (*fp) (uint8_t, tusb_control_request_t const * ) ) // USBD API
{ //--------------------------------------------------------------------+
_ctrl_xfer.complete_cb = fp;
} void usbd_control_reset (uint8_t rhport)
{
// callback when a transaction complete on DATA stage of control endpoint (void) rhport;
bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) tu_varclr(&_ctrl_xfer);
{ }
(void) result;
// TODO may find a better way
// Endpoint Address is opposite to direction bit, this is Status Stage complete event void usbd_control_set_complete_callback( bool (*fp) (uint8_t, tusb_control_request_t const * ) )
if ( tu_edpt_dir(ep_addr) != _ctrl_xfer.request.bmRequestType_bit.direction ) {
{ _ctrl_xfer.complete_cb = fp;
TU_ASSERT(0 == xferred_bytes); }
if (dcd_control_status_complete) dcd_control_status_complete(rhport);
return true; // callback when a transaction complete on DATA stage of control endpoint
} bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
{
if ( _ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_OUT ) (void) result;
{
TU_VERIFY(_ctrl_xfer.buffer); // Endpoint Address is opposite to direction bit, this is Status Stage complete event
memcpy(_ctrl_xfer.buffer, _usbd_ctrl_buf, xferred_bytes); if ( tu_edpt_dir(ep_addr) != _ctrl_xfer.request.bmRequestType_bit.direction )
} {
TU_ASSERT(0 == xferred_bytes);
_ctrl_xfer.total_xferred += xferred_bytes; if (dcd_control_status_complete) dcd_control_status_complete(rhport);
_ctrl_xfer.buffer += xferred_bytes; return true;
}
// Data Stage is complete when all request's length are transferred or
// a short packet is sent including zero-length packet. if ( _ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_OUT )
if ( (_ctrl_xfer.request.wLength == _ctrl_xfer.total_xferred) || xferred_bytes < CFG_TUD_ENDPOINT0_SIZE ) {
{ TU_VERIFY(_ctrl_xfer.buffer);
// DATA stage is complete memcpy(_ctrl_xfer.buffer, _usbd_ctrl_buf, xferred_bytes);
bool is_ok = true; }
// invoke complete callback if set _ctrl_xfer.total_xferred += xferred_bytes;
// callback can still stall control in status phase e.g out data does not make sense _ctrl_xfer.buffer += xferred_bytes;
if ( _ctrl_xfer.complete_cb )
{ // Data Stage is complete when all request's length are transferred or
is_ok = _ctrl_xfer.complete_cb(rhport, &_ctrl_xfer.request); // a short packet is sent including zero-length packet.
} if ( (_ctrl_xfer.request.wLength == _ctrl_xfer.total_xferred) || xferred_bytes < CFG_TUD_ENDPOINT0_SIZE )
{
if ( is_ok ) // DATA stage is complete
{ bool is_ok = true;
// Send status
TU_ASSERT( tud_control_status(rhport, &_ctrl_xfer.request) ); // invoke complete callback if set
}else // callback can still stall control in status phase e.g out data does not make sense
{ if ( _ctrl_xfer.complete_cb )
// Stall both IN and OUT control endpoint {
dcd_edpt_stall(rhport, EDPT_CTRL_OUT); is_ok = _ctrl_xfer.complete_cb(rhport, &_ctrl_xfer.request);
dcd_edpt_stall(rhport, EDPT_CTRL_IN); }
}
} if ( is_ok )
else {
{ // Send status
// More data to transfer TU_ASSERT( _status_stage_xact(rhport, &_ctrl_xfer.request) );
TU_ASSERT( _data_stage_xact(rhport) ); }else
} {
// Stall both IN and OUT control endpoint
return true; dcd_edpt_stall(rhport, EDPT_CTRL_OUT);
} dcd_edpt_stall(rhport, EDPT_CTRL_IN);
}
#endif }
else
{
// More data to transfer
TU_ASSERT( _data_stage_xact(rhport) );
}
return true;
}
#endif

View File

@ -198,6 +198,8 @@ static inline bool osal_queue_send(osal_queue_t const qhdl, void const * data, b
_osal_q_unlock(qhdl); _osal_q_unlock(qhdl);
} }
TU_ASSERT(success);
return success; return success;
} }