Skip to content

Target STM USBHOST support #3432

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jan 9, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 139 additions & 0 deletions features/unsupported/USBHost/USBHost/TARGET_STM/USBEndpoint_STM.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/* mbed USBHost Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if defined(TARGET_STM) && defined(USBHOST_OTHER)

#include "dbg.h"
#include "USBEndpoint.h"
extern uint32_t HAL_HCD_HC_GetMaxPacket(HCD_HandleTypeDef *hhcd, uint8_t chn_num);
extern uint32_t HAL_HCD_HC_GetType(HCD_HandleTypeDef *hhcd, uint8_t chn_num);


void USBEndpoint::init(HCED * hced_, ENDPOINT_TYPE type_, ENDPOINT_DIRECTION dir_, uint32_t size, uint8_t ep_number, HCTD* td_list_[2])
{
hced = hced_;
type = type_;
dir = dir_;
setup = (type == CONTROL_ENDPOINT) ? true : false;

//TDs have been allocated by the host
memcpy((HCTD**)td_list, td_list_, sizeof(HCTD*)*2); //TODO: Maybe should add a param for td_list size... at least a define
memset(td_list_[0], 0, sizeof(HCTD));
memset(td_list_[1], 0, sizeof(HCTD));

td_list[0]->ep = this;
td_list[1]->ep = this;

address = (ep_number & 0x7F) | ((dir - 1) << 7);
this->size = size;
this->ep_number = ep_number;
transfer_len = 0;
transferred = 0;
buf_start = 0;
nextEp = NULL;

td_current = td_list[0];
td_next = td_list[1];

intf_nb = 0;

state = USB_TYPE_IDLE;
}
void USBEndpoint::setSize(uint32_t size)
{
this->size = size;
}


void USBEndpoint::setDeviceAddress(uint8_t addr)
{
this->device_address = addr;
HAL_HCD_HC_Init((HCD_HandleTypeDef*)hced->hhcd,hced->ch_num, address, addr, HCD_SPEED_FULL, type, size);
}

void USBEndpoint::setSpeed(uint8_t speed)
{
this->speed = speed;
}



void USBEndpoint::setState(uint8_t st) {
if (st > 18)
return;
if (state == USB_TYPE_FREE) HAL_HCD_HC_Halt((HCD_HandleTypeDef*)hced->hhcd, hced->ch_num);

state = (USB_TYPE)st;
}


extern uint32_t HAL_HCD_HC_GetMaxPacket(HCD_HandleTypeDef *hhcd, uint8_t chn_num);
extern uint32_t HAL_HCD_HC_GetType(HCD_HandleTypeDef *hhcd, uint8_t chn_num);


USB_TYPE USBEndpoint::queueTransfer()
{
HCD_HandleTypeDef *hhcd = (HCD_HandleTypeDef*)hced->hhcd;
uint32_t *addr = &((uint32_t *)hhcd->pData)[hced->ch_num];
uint32_t type = HAL_HCD_HC_GetType(hhcd, hced->ch_num);
uint32_t max_size = HAL_HCD_HC_GetMaxPacket(hhcd, hced->ch_num);
/* if a packet is queue on disconnected ; no solution for now */
if(*addr == (uint32_t) -1) {
/* set td as disconnected */
td_current->state = USB_TYPE_DISCONNECTED;
return USB_TYPE_DISCONNECTED;
}
MBED_ASSERT(*addr ==0);
if ((type == EP_TYPE_BULK) || (type== EP_TYPE_CTRL)) {
transfer_len = td_current->size <= max_size ? td_current->size : max_size;
transferred = td_current->size;
} else {
transfer_len = td_current->size;
transferred = td_current->size;
MBED_ASSERT(transferred <= (int)max_size);
}
buf_start = (uint8_t *)td_current->currBufPtr;

//Now add this free TD at this end of the queue
state = USB_TYPE_PROCESSING;
/* one request */
td_current->nextTD = (hcTd*)0;

*addr = (uint32_t)td_current;
/* dir /setup is inverted for ST */
/* token is useful only ctrl endpoint */
/* last parameter is ping ? */
MBED_ASSERT(HAL_HCD_HC_SubmitRequest((HCD_HandleTypeDef*)hced->hhcd, hced->ch_num, dir-1, type,!setup,(uint8_t*) td_current->currBufPtr, transfer_len, 0)==HAL_OK);
return USB_TYPE_PROCESSING;
}

void USBEndpoint::unqueueTransfer(volatile HCTD * td)
{

uint32_t *addr = &((uint32_t *)((HCD_HandleTypeDef*)hced->hhcd)->pData)[hced->ch_num];
td->state=0;
td->currBufPtr=0;
td->size=0;
td->nextTD=0;
*addr = 0;
td_current = td_next;
td_next = td;
}

void USBEndpoint::queueEndpoint(USBEndpoint * ed)
{
nextEp = ed;
}
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/* mbed USBHost Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef USBHALHOST_DISCOF429ZI
#define USBHALHOST_DISCOF429ZI

#define USBHAL_IRQn OTG_HS_IRQn

#define HCCA_SIZE sizeof(HCD_HandleTypeDef)
#define ED_SIZE sizeof(HCED)
#define TD_SIZE sizeof(HCTD)

#define TOTAL_SIZE (HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE) + (MAX_TD*TD_SIZE))
/* STM device FS have 11 channels (definition is for 60 channels) */
static volatile uint8_t usb_buf[TOTAL_SIZE];
typedef struct
{
/* store the request ongoing on each endpoit */
/* 1st field of structure avoid giving knowledge of all structure to
* endpoint */
volatile uint32_t addr[MAX_ENDPOINT];
USBHALHost *inst;
void (USBHALHost::*deviceConnected)(int hub, int port, bool lowSpeed, USBHostHub * hub_parent);
void (USBHALHost::*deviceDisconnected)(int hub, int port, USBHostHub * hub_parent, volatile uint32_t addr);
void (USBHALHost::*transferCompleted)(volatile uint32_t addr);
}USBHALHost_Private_t;
/* CONFIGURATION for USB_VBUS
* on 64 bits board PC_0 is used (0 VBUS on, 1 VBUS off)
* on 144 pins board PG_6 is used ( 1 VBUS on, 0 VBUS on)
*/
static gpio_t gpio_vbus;

#define VBUS_OFF 1
#define VBUS_ON 0
#define USB_VBUS_CONFIG \
do {__HAL_RCC_GPIOC_CLK_ENABLE();\
gpio_init_out_ex(&gpio_vbus, PC_4, VBUS_OFF);\
}while(0);


void usb_vbus( uint8_t state)
{
if(state == 0)
{
gpio_write(&gpio_vbus, VBUS_OFF);
}
else
{
gpio_write(&gpio_vbus, VBUS_ON);
}
wait(0.2);
}


USBHALHost::USBHALHost() {
gpio_t pin_vbus;
instHost = this;
HCD_HandleTypeDef *hhcd;
USBHALHost_Private_t *HALPriv = new(USBHALHost_Private_t);
memset(HALPriv, 0, sizeof(USBHALHost_Private_t));
memInit();
memset((void*)usb_hcca, 0, HCCA_SIZE);
hhcd = (HCD_HandleTypeDef *)usb_hcca;
hhcd->Instance = USB_OTG_HS;
hhcd->pData = (void*)HALPriv;
hhcd->Init.Host_channels = 11;
/* for now failed with dma */
hhcd->Init.dma_enable = 0;
hhcd->Init.speed = HCD_SPEED_HIGH;
hhcd->Init.phy_itface = HCD_PHY_EMBEDDED;
hhcd->Init.use_external_vbus = 1;
HALPriv->inst = this;
HALPriv->deviceConnected = &USBHALHost::deviceConnected;
HALPriv->deviceDisconnected = &USBHALHost::deviceDisconnected;
HALPriv->transferCompleted = &USBHALHost::transferCompleted;
for (int i = 0; i < MAX_ENDPOINT; i++) {
edBufAlloc[i] = false;
HALPriv->addr[i]=(uint32_t)-1;
}
for (int i = 0; i < MAX_TD; i++) {
tdBufAlloc[i] = false;
}
/* Configure USB HS GPIOs */
__HAL_RCC_GPIOB_CLK_ENABLE();

/*USB DM and DP */
pin_function(PB_14, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF12_OTG_HS_FS));
pin_function(PB_15, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF12_OTG_HS_FS));
/* Configure VBUS Pin */
gpio_init_in(&pin_vbus, PB_13);
/* Configure POWER_SWITCH IO pin */
USB_VBUS_CONFIG;
/* Enable USB HS Clocks */
__HAL_RCC_USB_OTG_HS_CLK_ENABLE();

/* Set USBFS Interrupt priority */
HAL_NVIC_SetPriority(USBHAL_IRQn, 5, 0);
NVIC_SetVector(USBHAL_IRQn, (uint32_t)&_usbisr);
}
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/* Copyright (c) 2016 mbed.org, MIT License
*
* 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 USBHALHOST_DISCOL476VG
#define USBHALHOST_DISCOL476VG

#define USBHAL_IRQn OTG_FS_IRQn

#define HCCA_SIZE sizeof(HCD_HandleTypeDef)
#define ED_SIZE sizeof(HCED)
#define TD_SIZE sizeof(HCTD)

#define TOTAL_SIZE (HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE) + (MAX_TD*TD_SIZE))
/* STM device FS have 11 channels (definition is for 60 channels) */
static volatile uint8_t usb_buf[TOTAL_SIZE];
typedef struct
{
/* store the request ongoing on each endpoit */
/* 1st field of structure avoid giving knowledge of all structure to
* endpoint */
volatile uint32_t addr[MAX_ENDPOINT];
USBHALHost *inst;
void (USBHALHost::*deviceConnected)(int hub, int port, bool lowSpeed, USBHostHub * hub_parent);
void (USBHALHost::*deviceDisconnected)(int hub, int port, USBHostHub * hub_parent, volatile uint32_t addr);
void (USBHALHost::*transferCompleted)(volatile uint32_t addr);
}USBHALHost_Private_t;

static gpio_t gpio_vbus;

#define VBUS_OFF 1
#define VBUS_ON 0
#define USB_VBUS_CONFIG \
do {\
gpio_init_out_ex(&gpio_vbus, PC_9, VBUS_OFF);\
}while(0);


void usb_vbus( uint8_t state)
{
if(state == 0)
{
gpio_write(&gpio_vbus, VBUS_OFF);
}
else
{
gpio_write(&gpio_vbus, VBUS_ON);
}
wait(0.2);
}


USBHALHost::USBHALHost() {
instHost = this;
HCD_HandleTypeDef *hhcd;
USBHALHost_Private_t *HALPriv = new(USBHALHost_Private_t);
memset(HALPriv, 0, sizeof(USBHALHost_Private_t));
memInit();
memset((void*)usb_hcca, 0, HCCA_SIZE);
hhcd = (HCD_HandleTypeDef *)usb_hcca;
hhcd->Instance = USB_OTG_FS;
hhcd->pData = (void*)HALPriv;
hhcd->Init.Host_channels = 11;
/* for now failed with dma */
hhcd->Init.dma_enable = 0;
hhcd->Init.speed = HCD_SPEED_FULL;
hhcd->Init.phy_itface = HCD_PHY_EMBEDDED;
hhcd->Init.use_external_vbus = 1;
HALPriv->inst = this;
HALPriv->deviceConnected = &USBHALHost::deviceConnected;
HALPriv->deviceDisconnected = &USBHALHost::deviceDisconnected;
HALPriv->transferCompleted = &USBHALHost::transferCompleted;
for (int i = 0; i < MAX_ENDPOINT; i++) {
edBufAlloc[i] = false;
HALPriv->addr[i]=(uint32_t)-1;
}
for (int i = 0; i < MAX_TD; i++) {
tdBufAlloc[i] = false;
}
__HAL_RCC_PWR_CLK_ENABLE();
#ifdef TARGET_STM32L4
HAL_PWREx_EnableVddUSB();
#endif

/* Configure USB HS GPIOs */
__HAL_RCC_GPIOA_CLK_ENABLE();

/*USB DM and DP */
pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS));
pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS));

/* Configure VBUS Pin */
__HAL_RCC_GPIOC_CLK_ENABLE();
pin_function(PC_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS));
/* Configure POWER_SWITCH IO pin */
USB_VBUS_CONFIG;
__HAL_RCC_SYSCFG_CLK_ENABLE();

/* Enable USB FS Clocks */
__HAL_RCC_USB_OTG_FS_CLK_ENABLE();
/* Set USBFS Interrupt priority */
HAL_NVIC_SetPriority(USBHAL_IRQn, 5, 0);
NVIC_SetVector(USBHAL_IRQn, (uint32_t)&_usbisr);
}
#endif
Loading