Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: F401RE-USBHostMIDI_RecieveExample
Fork of F401RE-USBHost by
USBHost/USBHALHost_F401RE.cpp
- Committer:
- va009039
- Date:
- 2014-06-10
- Revision:
- 13:8774c07f12a5
- Parent:
- 11:61843badd06e
- Child:
- 14:b167f2b97cb7
File content as of revision 13:8774c07f12a5:
// Simple USBHost for Nucleo F401RE
#if defined(TARGET_NUCLEO_F401RE)
#include "USBHALHost_F401RE.h"
template <bool>struct CtAssert;
template <>struct CtAssert<true> {};
#define CTASSERT(A) CtAssert<A>();
#ifdef _USB_DBG
extern RawSerial pc;
#include "mydebug.h"
#define USB_DBG(...) do{pc.printf("[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);pc.printf(__VA_ARGS__);pc.puts("\n");} while(0);
#define USB_DBG_HEX(A,B) debug_hex<RawSerial>(pc,A,B)
#else
#define USB_DBG(...) while(0)
#define USB_DBG_HEX(A,B) while(0)
#endif
#ifdef _USB_TEST
#define USB_TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
#define USB_TEST_ASSERT_FALSE(A) USB_TEST_ASSERT(!(A))
#else
#define USB_TEST_ASSERT(A) while(0)
#define USB_TEST_ASSERT_FALSE(A) while(0)
#endif
#ifdef _USB_TRACE
#define USB_TRACE() while(0)
#define USB_TRACE1(A) while(0)
#define USB_TRACE_VIEW() while(0)
#define USB_TRACE_CLEAR() while(0)
#else
#define USB_TRACE() while(0)
#define USB_TRACE1(A) while(0)
#define USB_TRACE_VIEW() while(0)
#define USB_TRACE_CLEAR() while(0)
#endif
#define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");}while(0);
__IO bool attach_done = false;
__IO bool token_done = false;
__IO HCD_URBStateTypeDef g_urb_state = URB_IDLE;
void delay_ms(uint32_t t)
{
HAL_Delay(t);
}
// from usbh_conf.c
extern HCD_HandleTypeDef hhcd_USB_OTG_FS;
void HAL_HCD_MspInit(HCD_HandleTypeDef* hhcd)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(hhcd->Instance==USB_OTG_FS)
{
/* Peripheral clock enable */
__USB_OTG_FS_CLK_ENABLE();
/**USB_OTG_FS GPIO Configuration
PA11 ------> USB_OTG_FS_DM
PA12 ------> USB_OTG_FS_DP
*/
GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Peripheral interrupt init*/
/* Sets the priority grouping field */
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0);
HAL_NVIC_SetPriority(OTG_FS_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
}
}
// from stm32f4xx_it.c
extern "C" {
void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
{
USB_TRACE();
attach_done = true;
}
void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd)
{
USB_TRACE();
}
void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state)
{
USB_TRACE1(chnum);
USB_TRACE1(urb_state);
g_urb_state = urb_state;
token_done = true;
}
} // extern "C"
const int CH_CTL_IN = 0;
const int CH_CTL_OUT = 1;
const int CH_INT_IN = 2;
const int CH_INT_OUT = 3;
const int CH_BLK_IN = 4;
const int CH_BLK_OUT = 5;
const int CH_ISO_IN = 6;
const int DIR_IN = 1;
const int DIR_OUT = 0;
USBHALHost* USBHALHost::instHost;
USBHALHost::USBHALHost() {
instHost = this;
}
void USBHALHost::init() {
hhcd_USB_OTG_FS.Instance = USB_OTG_FS;
hhcd_USB_OTG_FS.Init.Host_channels = 8;
hhcd_USB_OTG_FS.Init.speed = HCD_SPEED_FULL;
hhcd_USB_OTG_FS.Init.dma_enable = DISABLE;
hhcd_USB_OTG_FS.Init.phy_itface = HCD_PHY_EMBEDDED;
hhcd_USB_OTG_FS.Init.Sof_enable = DISABLE;
hhcd_USB_OTG_FS.Init.low_power_enable = ENABLE;
hhcd_USB_OTG_FS.Init.vbus_sensing_enable = DISABLE;
hhcd_USB_OTG_FS.Init.use_external_vbus = DISABLE;
HAL_HCD_Init(&hhcd_USB_OTG_FS);
HAL_HCD_Start(&hhcd_USB_OTG_FS);
bool lowSpeed = wait_attach();
delay_ms(200);
HAL_HCD_ResetPort(&hhcd_USB_OTG_FS);
delay_ms(100); // Wait for 100 ms after Reset
addDevice(NULL, 0, lowSpeed);
}
bool USBHALHost::wait_attach() {
Timer t;
t.reset();
t.start();
while(!attach_done) {
if (t.read_ms() > 5*1000) {
t.reset();
USB_INFO("Please attach USB device.");
}
}
wait_ms(100);
return HAL_HCD_GetCurrentSpeed(&hhcd_USB_OTG_FS) == USB_OTG_SPEED_LOW;
}
int USBHALHost::token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength) {
USBDeviceConnected* dev = ep->getDevice();
HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_CTL_OUT, 0x00,
dev->getAddress(),
dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
EP_TYPE_CTRL, ep->getSize());
setup->wLength = wLength;
HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, CH_CTL_OUT, DIR_OUT, EP_TYPE_CTRL, 0, (uint8_t*)setup, 8, 0);
while(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_CTL_OUT) == URB_IDLE);
switch(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_CTL_OUT)) {
case URB_DONE:
LastStatus = ACK;
break;
default:
LastStatus = 0xff;
break;
}
ep->setData01(DATA1);
return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_CTL_OUT);
}
HAL_StatusTypeDef HAL_HCD_HC_SubmitRequest2(HCD_HandleTypeDef *hhcd,
uint8_t ch_num,
uint8_t direction ,
uint8_t ep_type,
uint8_t token,
uint8_t* pbuff,
uint16_t length,
uint8_t do_ping)
{
HCD_HCTypeDef* hc = &(hhcd->hc[ch_num]);
hc->ep_is_in = direction;
hc->ep_type = ep_type;
if (hc->toggle_in == 0) {
hc->data_pid = HC_PID_DATA0;
} else {
hc->data_pid = HC_PID_DATA1;
}
hc->xfer_buff = pbuff;
hc->xfer_len = length;
hc->urb_state = URB_IDLE;
hc->xfer_count = 0 ;
hc->ch_num = ch_num;
hc->state = HC_IDLE;
return USB_HC_StartXfer(hhcd->Instance, hc, hhcd->Init.dma_enable);
}
int USBHALHost::token_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) {
switch(ep->getType()) {
case CONTROL_ENDPOINT:
return token_ctl_in(ep, data, size, retryLimit);
case INTERRUPT_ENDPOINT:
return token_int_in(ep, data, size);
case BULK_ENDPOINT:
return token_blk_in(ep, data, size, retryLimit);
}
return -1;
}
int USBHALHost::token_ctl_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) {
USBDeviceConnected* dev = ep->getDevice();
HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_CTL_IN, 0x80,
dev->getAddress(),
dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
EP_TYPE_CTRL, ep->getSize());
hhcd_USB_OTG_FS.hc[CH_CTL_IN].toggle_in = (ep->getData01() == DATA0) ? 0 : 1;
HAL_HCD_HC_SubmitRequest2(&hhcd_USB_OTG_FS, CH_CTL_IN, DIR_IN, EP_TYPE_CTRL, 1, data, size, 0);
while(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_CTL_IN) == URB_IDLE);
switch(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_CTL_IN)) {
case URB_DONE:
LastStatus = ACK;
break;
default:
LastStatus = 0xff;
return -1;
}
ep->toggleData01();
return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_CTL_IN);
}
int USBHALHost::token_int_in(USBEndpoint* ep, uint8_t* data, int size) {
USBDeviceConnected* dev = ep->getDevice();
HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_INT_IN,
ep->getAddress(),
dev->getAddress(),
dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
EP_TYPE_INTR, ep->getSize());
hhcd_USB_OTG_FS.hc[CH_INT_IN].toggle_in = (ep->getData01() == DATA0) ? 0 : 1;
HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, CH_INT_IN, DIR_IN, EP_TYPE_INTR, 1, data, size, 0);
while(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_INT_IN) == URB_IDLE);
switch(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_INT_IN)) {
case URB_DONE:
switch(HAL_HCD_HC_GetState(&hhcd_USB_OTG_FS, CH_INT_IN)) {
case HC_XFRC:
LastStatus = ep->getData01();
ep->toggleData01();
return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_INT_IN);
case HC_NAK:
LastStatus = NAK;
return -1;
}
break;
}
LastStatus = STALL;
return -1;
}
int USBHALHost::token_blk_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) {
USBDeviceConnected* dev = ep->getDevice();
int retry = 0;
do {
HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_BLK_IN,
ep->getAddress(),
dev->getAddress(),
HCD_SPEED_FULL,
EP_TYPE_BULK, ep->getSize());
hhcd_USB_OTG_FS.hc[CH_BLK_IN].toggle_in = (ep->getData01() == DATA0) ? 0 : 1;
HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, CH_BLK_IN, DIR_IN, EP_TYPE_BULK, 1, data, size, 0);
while(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_BLK_IN) == URB_IDLE);
switch(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_BLK_IN)) {
case URB_DONE:
switch(HAL_HCD_HC_GetState(&hhcd_USB_OTG_FS, CH_BLK_IN)) {
case HC_XFRC:
LastStatus = ep->getData01();
ep->toggleData01();
return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_BLK_IN);
case HC_NAK:
LastStatus = NAK;
if (retryLimit > 0) {
delay_ms(1 + 10 * retry);
}
break;
default:
break;
}
break;
case URB_STALL:
LastStatus = STALL;
return -1;
default:
LastStatus = STALL;
delay_ms(500 + 100 * retry);
break;
}
}while(retry++ < retryLimit);
return -1;
}
int USBHALHost::token_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) {
switch(ep->getType()) {
case CONTROL_ENDPOINT:
return token_ctl_out(ep, data, size, retryLimit);
case INTERRUPT_ENDPOINT:
return token_int_out(ep, data, size);
case BULK_ENDPOINT:
return token_blk_out(ep, data, size, retryLimit);
}
return -1;
}
int USBHALHost::token_ctl_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) {
USBDeviceConnected* dev = ep->getDevice();
HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_CTL_OUT, 0x00,
dev->getAddress(),
dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
EP_TYPE_CTRL, ep->getSize());
hhcd_USB_OTG_FS.hc[CH_CTL_OUT].toggle_out = (ep->getData01() == DATA0) ? 0 : 1;
do {
HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, CH_CTL_OUT, DIR_OUT, EP_TYPE_CTRL, 1, (uint8_t*)data, size, 0);
while(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_CTL_OUT) == URB_IDLE);
switch(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_CTL_OUT)) {
case URB_DONE:
LastStatus = ACK;
ep->toggleData01();
return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_CTL_OUT);
default:
break;
}
delay_ms(1);
}while(retryLimit-- > 0);
return -1;
}
int USBHALHost::token_int_out(USBEndpoint* ep, const uint8_t* data, int size) {
USBDeviceConnected* dev = ep->getDevice();
HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_INT_OUT,
ep->getAddress(),
dev->getAddress(),
dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
EP_TYPE_INTR, ep->getSize());
hhcd_USB_OTG_FS.hc[CH_INT_OUT].toggle_out = (ep->getData01() == DATA0) ? 0 : 1;
token_done = false;
HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, CH_INT_OUT, DIR_OUT, EP_TYPE_INTR, 1, (uint8_t*)data, size, 0);
while(!token_done);
if (HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_INT_OUT) != URB_DONE) {
return -1;
}
ep->toggleData01();
return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_INT_OUT);
}
int USBHALHost::token_blk_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) {
USBDeviceConnected* dev = ep->getDevice();
int retry = 0;
do {
HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_BLK_OUT,
ep->getAddress(), dev->getAddress(),
HCD_SPEED_FULL, EP_TYPE_BULK, ep->getSize());
hhcd_USB_OTG_FS.hc[CH_BLK_OUT].toggle_out = (ep->getData01() == DATA0) ? 0 : 1;
HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, CH_BLK_OUT, DIR_OUT, EP_TYPE_BULK, 1, (uint8_t*)data, size, 0);
while(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_BLK_OUT) == URB_IDLE);
switch(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_BLK_OUT)) {
case URB_DONE:
switch(HAL_HCD_HC_GetState(&hhcd_USB_OTG_FS, CH_BLK_OUT)) {
case HC_XFRC: // ACK
LastStatus = ep->getData01();
ep->toggleData01();
return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_BLK_OUT);
default:
break;
}
break;
case URB_NOTREADY: // HC_NAK
LastStatus = NAK;
delay_ms(100 * retry);
break;
default:
LastStatus = STALL;
return -1;
}
} while(retry++ < retryLimit);
return -1;
}
int USBHALHost::token_iso_in(USBEndpoint* ep, uint8_t* data, int size) {
static bool init = false;
if (!init) {
init = true;
USBDeviceConnected* dev = ep->getDevice();
HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_ISO_IN,
ep->getAddress(), dev->getAddress(),
HCD_SPEED_FULL, EP_TYPE_ISOC, ep->getSize());
}
HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, CH_ISO_IN, DIR_IN, EP_TYPE_ISOC, 1, data, size, 0);
while(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_ISO_IN) == URB_IDLE);
return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_ISO_IN);
}
#endif
