From c06299aa53df9eb9d0cb0d78487b2a459d5c5e38 Mon Sep 17 00:00:00 2001 From: Trent Gill Date: Sun, 9 Jun 2024 13:00:16 -0700 Subject: [PATCH] usb host working with crow --- Makefile | 16 ++- lib/mhost.c | 63 ++++++++++ lib/mhost.h | 22 ++++ ll/system.c | 4 + main.c | 57 ++++++++- stm32f7xx_hal_conf.h | 2 +- usbd/usbd_conf.c | 8 ++ usbd/usbd_conf.h | 9 +- usbd/usbd_main.c | 3 +- usbh/usbh_conf.c | 267 +++++++++++++++++++++++++++++++++++++++++++ usbh/usbh_conf.h | 48 ++++++++ usbh/usbh_main.c | 161 ++++++++++++++++++++++++++ usbh/usbh_main.h | 10 ++ 13 files changed, 661 insertions(+), 9 deletions(-) create mode 100644 lib/mhost.c create mode 100644 lib/mhost.h create mode 100755 usbh/usbh_conf.c create mode 100755 usbh/usbh_conf.h create mode 100755 usbh/usbh_main.c create mode 100755 usbh/usbh_main.h diff --git a/Makefile b/Makefile index bda3ac52..a101fc55 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,7 @@ GIT_VERSION := $(shell git describe --tags) CUBE=submodules/STM32CubeF7_Drivers HALS=$(CUBE)/STM32F7xx_HAL_Driver/Src USBD=submodules/STM32CubeF7_USB/STM32_USB_Device_Library +USBH=submodules/STM32CubeF7_USB/STM32_USB_Host_Library WRLIB=submodules/wrLib WRDSP=submodules/wrDsp LUAS=submodules/lua/src @@ -43,6 +44,9 @@ STM32_INCLUDES = \ -Iusbd/ \ -I$(USBD)/Class/CDC/Inc/ \ -I$(USBD)/Core/Inc/ \ + -Iusbh/ \ + -I$(USBH)/Class/CDC/Inc/ \ + -I$(USBH)/Core/Inc/ \ OPTIMIZE = -O2 @@ -72,7 +76,9 @@ ifeq ($(R), 1) #CFLAGS += -flto # broken in debug mode. provides a small LTO binary size reduction endif -LDFLAGS = -Wl,-T,stm32_flash.ld,-flto,-gc-sections +# LDFLAGS = -Wl,-T,stm32_flash.ld,-flto,-gc-sections + +LDFLAGS = -Wl,-T,stm32_flash.ld,-gc-sections LIBS = -lm -lc -lnosys SRC = main.c \ @@ -91,6 +97,7 @@ SRC = main.c \ $(HALS)/stm32f7xx_hal_dma2d.c \ $(HALS)/stm32f7xx_hal_pcd.c \ $(HALS)/stm32f7xx_hal_pcd_ex.c \ + $(HALS)/stm32f7xx_hal_hcd.c \ $(HALS)/stm32f7xx_hal_pwr.c \ $(HALS)/stm32f7xx_hal_pwr_ex.c \ $(HALS)/stm32f7xx_hal_rng.c \ @@ -115,12 +122,19 @@ SRC = main.c \ lib/shapes.c \ lib/slopes.c \ lib/midi.c \ + lib/mhost.c \ $(wildcard ll/*.c) \ $(wildcard usbd/*.c) \ $(USBD)/Core/Src/usbd_core.c \ $(USBD)/Core/Src/usbd_ctlreq.c \ $(USBD)/Core/Src/usbd_ioreq.c \ $(USBD)/Class/CDC/Src/usbd_cdc.c \ + $(wildcard usbh/*.c) \ + $(USBH)/Core/Src/usbh_core.c \ + $(USBH)/Core/Src/usbh_ctlreq.c \ + $(USBH)/Core/Src/usbh_ioreq.c \ + $(USBH)/Core/Src/usbh_pipes.c \ + $(USBH)/Class/CDC/Src/usbh_cdc.c \ $(WRLIB)/str_buffer.c \ $(WRLIB)/wrConvert.c \ $(WRLIB)/wrMath.c \ diff --git a/lib/mhost.c b/lib/mhost.c new file mode 100644 index 00000000..14cfd037 --- /dev/null +++ b/lib/mhost.c @@ -0,0 +1,63 @@ +#include "mhost.h" + +#include + +// #include "usb_device.h" + +void MHost_Init(void){ + // __HAL_RCC_GPIOB_CLK_ENABLE(); + + // GPIO_InitTypeDef g; + // g.Pin = GPIO_PIN_12; + // g.Mode = GPIO_MODE_OUTPUT_PP; + // g.Pull = GPIO_NOPULL; + // g.Speed = GPIO_SPEED_FAST; + // HAL_GPIO_Init(GPIOB, &g); + // HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, 0); // immediately turn off power + + + + + // from https://github.com/Hypnotriod/midi-box-stm32 + // MX_USB_DEVICE_Init(); + + + +} + +void MHost_Task(void){ + // MIDI_ProcessUSBData(); // see /midi_router.c +} + +void MHost_Power(int status){ // enable/disable +5v to connected device + // handled by the LL usbh driver + // HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, !!status); +} + +// TODO support power error flag from usb switch + +/* +void USB_LP_CAN1_RX0_IRQHandler(void) +{ + HAL_PCD_IRQHandler(&hpcd_USB_FS); +} + +USBD_HandleTypeDef hUsbDeviceFS; + +void MX_USB_DEVICE_Init(void) +{ + // Init Device Library, add supported class and start the library. + if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK) + { + Error_Handler(); + } + if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_MIDI) != USBD_OK) + { + Error_Handler(); + } + if (USBD_Start(&hUsbDeviceFS) != USBD_OK) + { + Error_Handler(); + } +} +*/ diff --git a/lib/mhost.h b/lib/mhost.h new file mode 100644 index 00000000..f6fef81f --- /dev/null +++ b/lib/mhost.h @@ -0,0 +1,22 @@ +#pragma once + +void MHost_Init(void); +void MHost_Power(int status); // enable +5v to connected device + +/* +// for the low-level driver +// B12: PWR_ENABLE: set high to engage power to the connected device +// B13: PWR_nERROR: set pullup. PSU pulls low if error occurs (need IRQ) + // set PWR_ENABLE low if this occurs (TODO retry?) +// B14: USB_D- +// B15: USB_D+ + +#define MIDI_IN_PORTS_NUM 0x01 +#define MIDI_OUT_PORTS_NUM 0x03 + +void USB_LP_CAN1_RX0_IRQHandler(void); + +extern PCD_HandleTypeDef hpcd_USB_FS; + +void MX_USB_DEVICE_Init(void); +*/ diff --git a/ll/system.c b/ll/system.c index 6eefa2a7..d568079e 100644 --- a/ll/system.c +++ b/ll/system.c @@ -47,6 +47,10 @@ static void Sys_Clk_Config(void) __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2); +// USE CUBE MX Clock Configuration to set all of this! +// Currently using 168MHz core clock to reduce power dissipation in +3v3 regulator +// Will need to adjust PLLQ (for USB clock) when increasing clock with a better reg. + static RCC_OscInitTypeDef osc; osc.OscillatorType = RCC_OSCILLATORTYPE_HSE; osc.HSEState = RCC_HSE_ON; diff --git a/main.c b/main.c index eea0a932..b637f96f 100755 --- a/main.c +++ b/main.c @@ -15,11 +15,13 @@ #include "lib/lualink.h" // #include "lib/repl.h" #include "usbd/usbd_cdc_interface.h" // CDC_main_init() +#include "usbh/usbh_main.h" #include "lib/bootloader.h" // bootloader_enter(), bootloader_restart() #include "lib/flash.h" // Flash_clear_user_script() #include "stm32f7xx_it.h" // CPU_count; #include "lib/midi.h" +// #include "lib/mhost.h" #include "ll/uart.h" static Uart uart_rx; @@ -59,6 +61,10 @@ int main(void) Caw_Init( max_timers-1 ); // use last timer CDC_clear_buffers(); + // MIDI Host + // MHost_Init(); + USBHost_Init(); + // i2c_hw_pullups_init(); // enable GPIO for v1.1 hardware pullups // ii_init( II_CROW ); // Random_Init(); @@ -68,22 +74,48 @@ int main(void) // REPL_print_script_name(); // Lua_crowbegin(); +// TODO startup animation + // here we run the power sequence to spread out current spikes when enabling + // setup the leds first so we can draw a nice animation while things get going + // mostly just doing this to get a predictable state before enabling USB Host + // HAL_Delay(1000); + + // Enable USB Host power + // MHost_Power(1); + + + uint32_t last_tick = HAL_GetTick(); int saw = 0; int g_state = 0; int counter = 0; + int once = 1; while(1){ CPU_count++; saw++; - saw &= 0xfffff; - if(saw == 0x7ffff){ + saw &= 0x3ffff; + if(saw == 0x1ffff){ Debug_Pin_Set(1, g_state); g_state ^= 1; - // Caw_printf("hi\n\r"); - // Caw_printf("%i\n\r",counter++); + uint8_t midi_msg[3] = {0x90, 0x3c, 0x64}; MIDI_transmit(&midi, midi_msg, 3); + + if(once){ + once = 0; + + // char crow_msg[32]; + // sprintf(crow_msg, "output[1].volts = %i\n\r", counter++); + // sprintf(crow_msg, "^^v\n\r", counter++); + // if(counter > 10) counter = 0; + // USBHost_Send(crow_msg, strlen(crow_msg)+1); + } + // char crow_msg[64]; + // snprintf(crow_msg, 64, "print(time())\n\r"); + // char* crow_msg = "^^v\n\r"; + char* crow_msg = "print('hi')\n\r"; + USBHost_Send((unsigned char*)crow_msg, strlen(crow_msg)); } // U_PrintNow(); @@ -119,5 +151,22 @@ int main(void) // event_next(); // check/execute single event // ii_leader_process(); Caw_send_queued(); + + if( USBHost_BG_Task() ){ // data is ready to be used + uint8_t* buf; + size_t len = USBHost_Get_Received(&buf); + len = len > 100 ? 100 : len; + char crow_msg[100]; + /* + for(int i=0; ipData); + +/* + if (hpcd->Init.low_power_enable) + { + // Set SLEEPDEEP bit and SleepOnExit of Cortex System Control Register. + SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); + } + */ } /** diff --git a/usbd/usbd_conf.h b/usbd/usbd_conf.h index 0e47ec1d..7cec2aff 100755 --- a/usbd/usbd_conf.h +++ b/usbd/usbd_conf.h @@ -60,17 +60,24 @@ /* Common Config */ #define USBD_MAX_NUM_INTERFACES 1 #define USBD_MAX_NUM_CONFIGURATION 1 -#define USBD_MAX_STR_DESC_SIZ 0x100 +#define USBD_MAX_STR_DESC_SIZ 0x100 // could be 512 (0x200) #define USBD_SELF_POWERED 1 #define USBD_DEBUG_LEVEL 0 /* Exported macro ------------------------------------------------------------*/ /* Memory management macros */ void* malloc1( size_t size ); // like calloc, but sets to ones (??!?!?!) +//#define USBD_malloc (uint32_t *)USBD_static_malloc #define USBD_malloc malloc1 +// #define USBD_free USBD_static_free #define USBD_free free #define USBD_memset memset #define USBD_memcpy memcpy + +/* For footprint reasons and since only one allocation is handled in the MIDI class + driver, the malloc/free is changed into a static allocation method */ +// void *USBD_static_malloc(uint32_t size); +// void USBD_static_free(void *p); /* DEBUG macros */ #if (USBD_DEBUG_LEVEL > 0U) diff --git a/usbd/usbd_main.c b/usbd/usbd_main.c index a05d8a4d..f3804e71 100755 --- a/usbd/usbd_main.c +++ b/usbd/usbd_main.c @@ -34,7 +34,6 @@ void USB_CDC_DeInit(void) extern PCD_HandleTypeDef hpcd; -void OTG_FS_IRQHandler(void) -{ +void OTG_FS_IRQHandler(void){ HAL_PCD_IRQHandler(&hpcd); } diff --git a/usbh/usbh_conf.c b/usbh/usbh_conf.c new file mode 100755 index 00000000..8409af79 --- /dev/null +++ b/usbh/usbh_conf.c @@ -0,0 +1,267 @@ +#include "stm32f7xx_hal.h" +#include "usbh_core.h" +// #include "stm32f769i_eval_io.h" + +HCD_HandleTypeDef hhcd; + +void HAL_HCD_MspInit(HCD_HandleTypeDef* hhcd){ + __HAL_RCC_GPIOB_CLK_ENABLE(); + + GPIO_InitTypeDef g; + // power enable pin + g.Pin = GPIO_PIN_12; + g.Mode = GPIO_MODE_OUTPUT_PP; + g.Pull = GPIO_NOPULL; + g.Speed = GPIO_SPEED_HIGH; + HAL_GPIO_Init(GPIOB, &g); + + // d+/d- signal pins + g.Pin = GPIO_PIN_14 | GPIO_PIN_15; + g.Mode = GPIO_MODE_AF_PP; + g.Alternate = GPIO_AF12_OTG_HS_FS; + HAL_GPIO_Init(GPIOB, &g); + + // TODO B13 is over-current-sense for usb switch + + __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); + HAL_NVIC_SetPriority(OTG_HS_IRQn, 6, 0); + HAL_NVIC_EnableIRQ(OTG_HS_IRQn); +} + +void HAL_HCD_MspDeInit(HCD_HandleTypeDef* hhcd){ + __HAL_RCC_USB_OTG_HS_CLK_DISABLE(); + __HAL_RCC_USB_OTG_HS_ULPI_CLK_DISABLE(); +} + +/////////////////////////////////////////////////////////// +// LL Driver Callbacks (HCD -> USB Host Library) + +void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd){ + USBH_LL_IncTimer (hhcd->pData); +} + +void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd){ + USBH_LL_Connect(hhcd->pData); +} + +void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd){ + USBH_LL_Disconnect(hhcd->pData); +} + +void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd){ + USBH_LL_PortEnabled(hhcd->pData); +} + +void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd){ + USBH_LL_PortDisabled(hhcd->pData); +} + +void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state){ + // USBH_LL_NotifyURBChange(hhcd->pData); +} + + +/////////////////////////////////////////////////////////// +// LL Driver Interface (USB Host Library --> HCD) +USBH_StatusTypeDef USBH_LL_Init(USBH_HandleTypeDef* phost){ + hhcd.Instance = USB_OTG_HS; + hhcd.Init.Host_channels = 11; + hhcd.Init.dma_enable = 0; + hhcd.Init.low_power_enable = 0; + hhcd.Init.phy_itface = HCD_PHY_EMBEDDED; + hhcd.Init.Sof_enable = 0; + hhcd.Init.speed = HCD_SPEED_HIGH; + hhcd.Init.vbus_sensing_enable = 0; + hhcd.Init.use_external_vbus = 1; + hhcd.Init.lpm_enable = 0; + + // Link the driver to the stack + hhcd.pData = phost; + phost->pData = &hhcd; + + // Initialize the LL driver + HAL_HCD_Init(&hhcd); + + USBH_LL_SetTimer(phost, HAL_HCD_GetCurrentFrame(&hhcd)); + + return USBH_OK; +} + +USBH_StatusTypeDef USBH_LL_DeInit(USBH_HandleTypeDef *phost){ + HAL_HCD_DeInit(phost->pData); + return USBH_OK; +} + +USBH_StatusTypeDef USBH_LL_Start(USBH_HandleTypeDef *phost){ + HAL_HCD_Start(phost->pData); + return USBH_OK; +} + +USBH_StatusTypeDef USBH_LL_Stop(USBH_HandleTypeDef *phost){ + HAL_HCD_Stop(phost->pData); + return USBH_OK; +} + +USBH_SpeedTypeDef USBH_LL_GetSpeed(USBH_HandleTypeDef *phost){ + USBH_SpeedTypeDef speed = USBH_SPEED_FULL; + + switch (HAL_HCD_GetCurrentSpeed(phost->pData)){ + case 0: speed = USBH_SPEED_HIGH; break; + case 1: speed = USBH_SPEED_FULL; break; + case 2: speed = USBH_SPEED_LOW; break; + default: speed = USBH_SPEED_FULL; break; + } + return speed; +} + +USBH_StatusTypeDef USBH_LL_ResetPort (USBH_HandleTypeDef *phost){ + HAL_HCD_ResetPort(phost->pData); + return USBH_OK; +} + +uint32_t USBH_LL_GetLastXferSize(USBH_HandleTypeDef *phost, uint8_t pipe){ + return HAL_HCD_HC_GetXferCount(phost->pData, pipe); +} + +/** + * @brief Opens a pipe of the Low Level Driver. + * @param phost: Host handle + * @param pipe: Pipe index + * @param epnum: Endpoint Number + * @param dev_address: Device USB address + * @param speed: Device Speed + * @param ep_type: Endpoint Type + * @param mps: Endpoint Max Packet Size + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_OpenPipe(USBH_HandleTypeDef *phost, + uint8_t pipe, + uint8_t epnum, + uint8_t dev_address, + uint8_t speed, + uint8_t ep_type, + uint16_t mps){ + HAL_HCD_HC_Init(phost->pData, + pipe, + epnum, + dev_address, + speed, + ep_type, + mps); + return USBH_OK; +} + +/** + * @brief Closes a pipe of the Low Level Driver. + * @param phost: Host handle + * @param pipe: Pipe index + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_ClosePipe(USBH_HandleTypeDef *phost, uint8_t pipe) +{ + HAL_HCD_HC_Halt(phost->pData, pipe); + return USBH_OK; +} + +/** + * @brief Submits a new URB to the low level driver. + * @param phost: Host handle + * @param pipe: Pipe index + * This parameter can be a value from 1 to 15 + * @param direction: Channel number + * This parameter can be one of these values: + * 0: Output + * 1: Input + * @param ep_type: Endpoint Type + * This parameter can be one of these values: + * @arg EP_TYPE_CTRL: Control type + * @arg EP_TYPE_ISOC: Isochronous type + * @arg EP_TYPE_BULK: Bulk type + * @arg EP_TYPE_INTR: Interrupt type + * @param token: Endpoint Type + * This parameter can be one of these values: + * @arg 0: PID_SETUP + * @arg 1: PID_DATA + * @param pbuff: pointer to URB data + * @param length: length of URB data + * @param do_ping: activate do ping protocol (for high speed only) + * This parameter can be one of these values: + * 0: do ping inactive + * 1: do ping active + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_SubmitURB(USBH_HandleTypeDef *phost, + uint8_t pipe, + uint8_t direction, + uint8_t ep_type, + uint8_t token, + uint8_t* pbuff, + uint16_t length, + uint8_t do_ping){ + HAL_HCD_HC_SubmitRequest(phost->pData, + pipe, + direction, + ep_type, + token, + pbuff, + length, + do_ping); + return USBH_OK; +} + +/** + * @brief Gets a URB state from the low level driver. + * @param phost: Host handle + * @param pipe: Pipe index + * This parameter can be a value from 1 to 15 + * @retval URB state + * This parameter can be one of these values: + * @arg URB_IDLE + * @arg URB_DONE + * @arg URB_NOTREADY + * @arg URB_NYET + * @arg URB_ERROR + * @arg URB_STALL + */ +USBH_URBStateTypeDef USBH_LL_GetURBState(USBH_HandleTypeDef *phost, uint8_t pipe){ + return (USBH_URBStateTypeDef)HAL_HCD_HC_GetURBState (phost->pData, pipe); +} + +/** + * @brief Drives VBUS. + * @param phost: Host handle + * @param state: VBUS state + * This parameter can be one of these values: + * 0: VBUS Active + * 1: VBUS Inactive + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_LL_DriverVBUS(USBH_HandleTypeDef *phost, uint8_t state){ + HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, !!state); + HAL_Delay(200); + return USBH_OK; +} + +USBH_StatusTypeDef USBH_LL_SetToggle(USBH_HandleTypeDef *phost, uint8_t pipe, uint8_t toggle){ + if(hhcd.hc[pipe].ep_is_in){ + hhcd.hc[pipe].toggle_in = toggle; + }else{ + hhcd.hc[pipe].toggle_out = toggle; + } + return USBH_OK; +} + +uint8_t USBH_LL_GetToggle(USBH_HandleTypeDef *phost, uint8_t pipe){ + uint8_t toggle = 0; + + if(hhcd.hc[pipe].ep_is_in){ + toggle = hhcd.hc[pipe].toggle_in; + }else{ + toggle = hhcd.hc[pipe].toggle_out; + } +return toggle; +} + +void USBH_Delay(uint32_t Delay){ + HAL_Delay(Delay); +} diff --git a/usbh/usbh_conf.h b/usbh/usbh_conf.h new file mode 100755 index 00000000..c90864fb --- /dev/null +++ b/usbh/usbh_conf.h @@ -0,0 +1,48 @@ +#pragma once + +#include "stm32f7xx.h" +#include +#include +#include +#include "../lib/caw.h" + +#define USBH_MAX_NUM_ENDPOINTS 2 +#define USBH_MAX_NUM_INTERFACES 2 +#define USBH_MAX_NUM_CONFIGURATION 1 +#define USBH_MAX_NUM_SUPPORTED_CLASS 1 +#define USBH_KEEP_CFG_DESCRIPTOR 0 +#define USBH_MAX_SIZE_CONFIGURATION 0x200 +#define USBH_MAX_DATA_BUFFER 0x200 +#define USBH_DEBUG_LEVEL 3 +#define USBH_USE_OS 0 + +/* Memory management macros */ +#define USBH_malloc malloc +#define USBH_free free +#define USBH_memset memset +#define USBH_memcpy memcpy + +/* DEBUG macros */ +#if (USBH_DEBUG_LEVEL > 0) +#define USBH_UsrLog(...) Caw_printf(__VA_ARGS__);\ + Caw_printf("\n"); +#else +#define USBH_UsrLog(...) +#endif + + +#if (USBH_DEBUG_LEVEL > 1) +#define USBH_ErrLog(...) Caw_printf("ERROR: ") ;\ + Caw_printf(__VA_ARGS__);\ + Caw_printf("\n"); +#else +#define USBH_ErrLog(...) +#endif + +#if (USBH_DEBUG_LEVEL > 2) +#define USBH_DbgLog(...) Caw_printf("DEBUG : ") ;\ + Caw_printf(__VA_ARGS__);\ + Caw_printf("\n"); +#else +#define USBH_DbgLog(...) +#endif diff --git a/usbh/usbh_main.c b/usbh/usbh_main.c new file mode 100755 index 00000000..2888e196 --- /dev/null +++ b/usbh/usbh_main.c @@ -0,0 +1,161 @@ +#include "usbh_main.h" // USBH_CDC_CLASS + +/* +USBH_ClassTypeDef CDC_Class = +{ + "CDC", + USB_CDC_CLASS, + USBH_CDC_InterfaceInit, + USBH_CDC_InterfaceDeInit, + USBH_CDC_ClassRequest, + USBH_CDC_Process, + USBH_CDC_SOFProcess, + NULL, +}; +*/ + +static USBH_HandleTypeDef hUSBHost; +// CDC_ApplicationTypeDef Appli_state = APPLICATION_IDLE; + + +#define TX_BUFF_SIZE 0x400 // 1kB +static uint8_t CDC_TX_Buffer[TX_BUFF_SIZE]; +static size_t CDC_TX_Buffer_Count = 0; + +#define RX_BUFF_SIZE 0x400 // 1kB +static uint8_t CDC_RX_Buffer[RX_BUFF_SIZE]; +static uint8_t CDC_RX_Buffer_TMP[RX_BUFF_SIZE]; +static size_t CDC_RX_Buffer_Count = 0; + +static int is_connected = 0; + + +static void USBH_UserProcess(USBH_HandleTypeDef *phost, uint8_t id); +static void USBHost_Start_Reception(void); +void GetDefaultConfiguration(void); + +void USBHost_Init(void){ + USBH_Init(&hUSBHost, USBH_UserProcess, 0); // library function + USBH_RegisterClass(&hUSBHost, USBH_CDC_CLASS); // library function + USBH_Start(&hUSBHost); // library function + + // then run usbh_bg_task in the application's main loop +} + +// run this in the main loop +int USBHost_BG_Task(void){ + USBH_Process(&hUSBHost); // bg task, lib function + return CDC_RX_Buffer_Count; +} + +// handler called by the system to process state machine of usbh +// this should raise all the useful events for us to handle state changes. +// currently we just use Log prints, but this will allow application level display +static void USBH_UserProcess(USBH_HandleTypeDef *phost, uint8_t id){ + switch(id){ + case HOST_USER_SELECT_CONFIGURATION: + // Caw_printf("h_user_select_config\n\r"); + // triggered once enumeration is complete & device is ready + break; + + case HOST_USER_DISCONNECTION: + // Caw_printf("h_user_disconnection\n\r"); + // device disconnection has been detected + // will attempt to reconnect + // Appli_state = APPLICATION_DISCONNECT; + is_connected = 0; + break; + + case HOST_USER_CONNECTION: + // Caw_printf("h_user_connection\n\r"); + // triggered when the port opening is triggered + // immediately after this we wait 100ms, then open the control pipes for i/o & enumerate + // Appli_state = APPLICATION_START; + + // Debug prints VID, PID, mfg, product name etc.. + // next is HOST_USER_CLASS_SELECTED -> + break; + + case HOST_USER_CLASS_SELECTED: + // Caw_printf("h_user_class_selected\n\r"); + // a class has been activated + // next is HOST_USER_CLASS_ACTIVE -> + break; + + case HOST_USER_CLASS_ACTIVE: + // Caw_printf("h_user_class_active\n\r"); + GetDefaultConfiguration(); + USBHost_Start_Reception(); // FIXME confirm this is the correct place to start RX + is_connected = 1; + // Appli_state = APPLICATION_READY; + break; + + default: + break; + } +} + + +///////////////////////////////////////////////// +// user facing functions + +void USBHost_Send(uint8_t* data, size_t len){ + if(is_connected){ + CDC_TX_Buffer_Count = (len > TX_BUFF_SIZE) ? TX_BUFF_SIZE : len; // FIXME just truncating long strings + memcpy(CDC_TX_Buffer, data, CDC_TX_Buffer_Count); + USBH_CDC_Transmit(&hUSBHost, CDC_TX_Buffer, CDC_TX_Buffer_Count); + } +} + +#include "../lib/caw.h" +void USBH_CDC_TransmitCallback(USBH_HandleTypeDef* phost){ + // uint32_t bytesread; + // Caw_printf(">> Data sent\n"); +} + +void USBH_CDC_LineCodingChanged(USBH_HandleTypeDef *phost){ + Caw_printf("line coding changed\n"); +} + +static void USBHost_Start_Reception(void){ + USBH_CDC_Receive(&hUSBHost, CDC_RX_Buffer, RX_BUFF_SIZE); +} + +void USBH_CDC_ReceiveCallback(USBH_HandleTypeDef* phost){ + // TODO use a circular buffer to reduce overflow concerns + // right now we just memcpy into a 2nd buffer + // this is safe if we call USBHost_Get_Received() every frame (USBHost_BG_Task()) + + // copy received data into 2nd buffer + CDC_RX_Buffer_Count = USBH_CDC_GetLastReceivedDataSize(phost); + // Caw_printf("%i, %s\n\r",CDC_RX_Buffer_Count, CDC_RX_Buffer); + memcpy(CDC_RX_Buffer_TMP, CDC_RX_Buffer, CDC_RX_Buffer_Count); + CDC_RX_Buffer_TMP[CDC_RX_Buffer_Count] = '\0'; // add null? + + // receive the next usb packet + USBH_CDC_Receive(&hUSBHost, CDC_RX_Buffer, RX_BUFF_SIZE); +} + +// data buffer must be at least RX_BUFF_SIZE large to avoid memory errors +// data is only guaranteed until the next USB frame, so be quick! +size_t USBHost_Get_Received(uint8_t** data){ + size_t len = CDC_RX_Buffer_Count; + CDC_RX_Buffer_Count = 0; // zero out buffer length to mark it as claimed + *data = CDC_RX_Buffer_TMP; + return len; +} + +///////////////////////////////////////////////// +// backend handling + +extern HCD_HandleTypeDef hhcd; + +void OTG_HS_IRQHandler(void){ + HAL_HCD_IRQHandler(&hhcd); +} + +void GetDefaultConfiguration(void){ + Caw_printf("GetDefaultConfiguration\n\r"); + // USBH_CDC_GetLineCoding(&hUSBHost, &LineCoding); + // DefaultLineCoding = LineCoding; +} diff --git a/usbh/usbh_main.h b/usbh/usbh_main.h new file mode 100755 index 00000000..1b766459 --- /dev/null +++ b/usbh/usbh_main.h @@ -0,0 +1,10 @@ +#pragma once + +#include "usbh_cdc.h" // USBH_CDC_CLASS + +void USBHost_Init(void); +// return length of data available +int USBHost_BG_Task(void); + +void USBHost_Send(uint8_t* data, size_t len); +size_t USBHost_Get_Received(uint8_t** data);