mirror of https://github.com/ARMmbed/mbed-os.git
Update the STM32 USB driver to the new API
Take the code from mbed-os\features\unsupported\USBDevice\targets\TARGET_STM as a starting point and use it to fill in the USBPhy template for STM32 devices.pull/9768/head
parent
67498e384a
commit
a47c383233
|
@ -2222,7 +2222,8 @@
|
||||||
"SERIAL_ASYNCH",
|
"SERIAL_ASYNCH",
|
||||||
"FLASH",
|
"FLASH",
|
||||||
"TRNG",
|
"TRNG",
|
||||||
"MPU"
|
"MPU",
|
||||||
|
"USBDEVICE"
|
||||||
],
|
],
|
||||||
"device_has_remove": ["LPTICKER"],
|
"device_has_remove": ["LPTICKER"],
|
||||||
"release_versions": ["2", "5"],
|
"release_versions": ["2", "5"],
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
/* mbed Microcontroller Library
|
||||||
|
* Copyright (c) 2018-2018 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NUMBER_OF_LOGICAL_ENDPOINTS (4)
|
||||||
|
#define NUMBER_OF_PHYSICAL_ENDPOINTS (NUMBER_OF_LOGICAL_ENDPOINTS * 2)
|
||||||
|
|
||||||
|
/* Define physical endpoint numbers */
|
||||||
|
|
||||||
|
/* Endpoint No. Type(s) MaxPacket DoubleBuffer */
|
||||||
|
/* ---------------- ------------ ---------- --- */
|
||||||
|
#define EP0OUT (0x00) /* Control 64 No */
|
||||||
|
#define EP0IN (0x80) /* Control 64 No */
|
||||||
|
#define EP1OUT (0x01) /* Int/Bulk/Iso 64/64/1023 Yes */
|
||||||
|
#define EP1IN (0x81) /* Int/Bulk/Iso 64/64/1023 Yes */
|
||||||
|
#define EP2OUT (0x02) /* Int/Bulk/Iso 64/64/1023 Yes */
|
||||||
|
#define EP2IN (0x82) /* Int/Bulk/Iso 64/64/1023 Yes */
|
||||||
|
#define EP3OUT (0x03) /* Int/Bulk/Iso 64/64/1023 Yes */
|
||||||
|
#define EP3IN (0x83) /* Int/Bulk/Iso 64/64/1023 Yes */
|
||||||
|
|
||||||
|
/* Maximum Packet sizes */
|
||||||
|
#define MAX_PACKET_SIZE_SETUP (48)
|
||||||
|
#define MAX_PACKET_SIZE_EP0 (64)
|
||||||
|
#define MAX_PACKET_SIZE_EP1 (64) /* Int/Bulk */
|
||||||
|
#define MAX_PACKET_SIZE_EP2 (64) /* Int/Bulk */
|
||||||
|
#define MAX_PACKET_SIZE_EP3 (200) /* Int/Bulk/iso (44100 stereo 16 bits) */
|
||||||
|
|
||||||
|
#define MAX_PACKET_SIZE_EP1_ISO (1023) /* Isochronous */
|
||||||
|
#define MAX_PACKET_SIZE_EP2_ISO (1023) /* Isochronous */
|
||||||
|
#define MAX_PACKET_SIZE_EP3_ISO (1023) /* Isochronous */
|
||||||
|
|
||||||
|
/* Generic endpoints - intended to be portable accross devices */
|
||||||
|
/* and be suitable for simple USB devices. */
|
||||||
|
|
||||||
|
/* Bulk endpoint */
|
||||||
|
#define EPBULK_OUT (EP2OUT)
|
||||||
|
#define EPBULK_IN (EP2IN)
|
||||||
|
#define EPBULK_OUT_callback EP2_OUT_callback
|
||||||
|
#define EPBULK_IN_callback EP2_IN_callback
|
||||||
|
/* Interrupt endpoint */
|
||||||
|
#define EPINT_OUT (EP1OUT)
|
||||||
|
#define EPINT_IN (EP1IN)
|
||||||
|
#define EPINT_OUT_callback EP1_OUT_callback
|
||||||
|
#define EPINT_IN_callback EP1_IN_callback
|
||||||
|
/* Isochronous endpoint */
|
||||||
|
#define EPISO_OUT (EP3OUT)
|
||||||
|
#define EPISO_IN (EP3IN)
|
||||||
|
#define EPISO_OUT_callback EP3_OUT_callback
|
||||||
|
#define EPISO_IN_callback EP3_IN_callback
|
||||||
|
|
||||||
|
#define MAX_PACKET_SIZE_EPBULK (MAX_PACKET_SIZE_EP2)
|
||||||
|
#define MAX_PACKET_SIZE_EPINT (MAX_PACKET_SIZE_EP1)
|
||||||
|
#define MAX_PACKET_SIZE_EPISO (MAX_PACKET_SIZE_EP3_ISO)
|
|
@ -0,0 +1,102 @@
|
||||||
|
/* mbed Microcontroller Library
|
||||||
|
* Copyright (c) 2018-2018 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 USBPHYHW_H
|
||||||
|
#define USBPHYHW_H
|
||||||
|
|
||||||
|
#include "mbed.h"
|
||||||
|
#include "USBPhy.h"
|
||||||
|
|
||||||
|
#if defined(TARGET_DISCO_F746NG)
|
||||||
|
#if (MBED_CONF_TARGET_USB_SPEED == 1) // Defined in json configuration file
|
||||||
|
#define TARGET_DISCO_F746NG_OTG_HS
|
||||||
|
#else
|
||||||
|
#define TARGET_DISCO_F746NG_OTG_FS
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TARGET_DISCO_F429ZI) || \
|
||||||
|
defined(TARGET_DISCO_F769NI) || \
|
||||||
|
defined(TARGET_DISCO_F746NG_OTG_HS)
|
||||||
|
#define USBHAL_IRQn OTG_HS_IRQn
|
||||||
|
#else
|
||||||
|
#define USBHAL_IRQn OTG_FS_IRQn
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "USBEndpoints_STM32.h"
|
||||||
|
|
||||||
|
#define NB_ENDPOINT 4 // Must be a multiple of 4 bytes
|
||||||
|
|
||||||
|
#define MAXTRANSFER_SIZE 0x200
|
||||||
|
|
||||||
|
#define FIFO_USB_RAM_SIZE (MAXTRANSFER_SIZE + MAX_PACKET_SIZE_EP0 + MAX_PACKET_SIZE_EP1 + MAX_PACKET_SIZE_EP2 + MAX_PACKET_SIZE_EP3)
|
||||||
|
|
||||||
|
#if (FIFO_USB_RAM_SIZE > 0x500)
|
||||||
|
#error "FIFO dimensioning incorrect"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class USBPhyHw : public USBPhy {
|
||||||
|
public:
|
||||||
|
USBPhyHw();
|
||||||
|
virtual ~USBPhyHw();
|
||||||
|
virtual void init(USBPhyEvents *events);
|
||||||
|
virtual void deinit();
|
||||||
|
virtual bool powered();
|
||||||
|
virtual void connect();
|
||||||
|
virtual void disconnect();
|
||||||
|
virtual void configure();
|
||||||
|
virtual void unconfigure();
|
||||||
|
virtual void sof_enable();
|
||||||
|
virtual void sof_disable();
|
||||||
|
virtual void set_address(uint8_t address);
|
||||||
|
virtual void remote_wakeup();
|
||||||
|
virtual const usb_ep_table_t* endpoint_table();
|
||||||
|
|
||||||
|
virtual uint32_t ep0_set_max_packet(uint32_t max_packet);
|
||||||
|
virtual void ep0_setup_read_result(uint8_t *buffer, uint32_t size);
|
||||||
|
virtual void ep0_read(uint8_t *data, uint32_t size);
|
||||||
|
virtual uint32_t ep0_read_result();
|
||||||
|
virtual void ep0_write(uint8_t *buffer, uint32_t size);
|
||||||
|
virtual void ep0_stall();
|
||||||
|
|
||||||
|
virtual bool endpoint_add(usb_ep_t endpoint, uint32_t max_packet, usb_ep_type_t type);
|
||||||
|
virtual void endpoint_remove(usb_ep_t endpoint);
|
||||||
|
virtual void endpoint_stall(usb_ep_t endpoint);
|
||||||
|
virtual void endpoint_unstall(usb_ep_t endpoint);
|
||||||
|
|
||||||
|
virtual bool endpoint_read(usb_ep_t endpoint, uint8_t *data, uint32_t size);
|
||||||
|
virtual uint32_t endpoint_read_result(usb_ep_t endpoint);
|
||||||
|
virtual bool endpoint_write(usb_ep_t endpoint, uint8_t *data, uint32_t size);
|
||||||
|
virtual void endpoint_abort(usb_ep_t endpoint);
|
||||||
|
|
||||||
|
virtual void process();
|
||||||
|
|
||||||
|
USBPhyEvents *events;
|
||||||
|
bool sof_enabled;
|
||||||
|
|
||||||
|
uint8_t epComplete[2 * NB_ENDPOINT];
|
||||||
|
uint32_t pBufRx[MAXTRANSFER_SIZE >> 2];
|
||||||
|
uint32_t pBufRx0[MAX_PACKET_SIZE_EP0 >> 2];
|
||||||
|
PCD_HandleTypeDef hpcd;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t _read_size[16];
|
||||||
|
uint8_t *_read_buf[16];
|
||||||
|
|
||||||
|
static void _usbisr(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,522 @@
|
||||||
|
/* mbed Microcontroller Library
|
||||||
|
* Copyright (c) 2018-2018 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* TARGET NOT STM does not support this HAL */
|
||||||
|
#ifndef TARGET_STM
|
||||||
|
#define USBSTM_HAL_UNSUPPORTED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* STM32F4 family without USB_STM_HAL use another HAL */
|
||||||
|
#if defined(TARGET_STM) && defined(TARGET_STM32F4) && !defined(USB_STM_HAL)
|
||||||
|
#define USBSTM_HAL_UNSUPPORTED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef USBSTM_HAL_UNSUPPORTED
|
||||||
|
#include "USBPhyHw.h"
|
||||||
|
#include "pinmap.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* endpoint conversion macros */
|
||||||
|
#define EP_TO_LOG(ep) ((ep) & 0x7F)
|
||||||
|
#define EP_TO_IDX(ep) (((ep) << 1) | ((ep) & 0x80 ? 1 : 0))
|
||||||
|
#define LOG_IN_TO_EP(ep) ((ep) | 0x80)
|
||||||
|
#define LOG_OUT_TO_EP(ep) ((ep) | 0x00)
|
||||||
|
#define IDX_TO_EP(ep) (((ep) >> 1)|((ep) & 1) << 7)
|
||||||
|
|
||||||
|
uint32_t HAL_PCDEx_GetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo)
|
||||||
|
{
|
||||||
|
uint32_t len;
|
||||||
|
if (fifo == 0) {
|
||||||
|
len = hpcd->Instance->DIEPTXF0_HNPTXFSIZ >> 16;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
len = hpcd->Instance->DIEPTXF[fifo - 1] >> 16;
|
||||||
|
}
|
||||||
|
return len * 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
|
||||||
|
{
|
||||||
|
USBPhyHw *priv=((USBPhyHw *)(hpcd->pData));
|
||||||
|
USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
|
||||||
|
if (priv->sof_enabled) {
|
||||||
|
priv->events->sof((USBx_DEVICE->DSTS & USB_OTG_DSTS_FNSOF) >> 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this call at device reception completion on a Out Enpoint */
|
||||||
|
void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
|
||||||
|
{
|
||||||
|
USBPhyHw *priv=((USBPhyHw *)(hpcd->pData));
|
||||||
|
uint8_t endpoint = LOG_OUT_TO_EP(epnum);
|
||||||
|
priv->epComplete[EP_TO_IDX(endpoint)] = 1;
|
||||||
|
/* -2 endpoint 0 In out are not in call back list */
|
||||||
|
if (epnum) {
|
||||||
|
priv->events->out(endpoint);
|
||||||
|
} else {
|
||||||
|
priv->events->ep0_out();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this is call at device transmission completion on In endpoint */
|
||||||
|
void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
|
||||||
|
{
|
||||||
|
USBPhyHw *priv=((USBPhyHw *)(hpcd->pData));
|
||||||
|
uint8_t endpoint = LOG_IN_TO_EP(epnum);
|
||||||
|
priv->epComplete[EP_TO_IDX(endpoint)] = 1;
|
||||||
|
/* -2 endpoint 0 In out are not in call back list */
|
||||||
|
if (epnum) {
|
||||||
|
priv->events->in(endpoint);
|
||||||
|
} else {
|
||||||
|
priv->events->ep0_in();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* This is call at device set up reception */
|
||||||
|
void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
|
||||||
|
{
|
||||||
|
USBPhyHw *priv=((USBPhyHw *)(hpcd->pData));
|
||||||
|
priv->events->ep0_setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
|
||||||
|
{
|
||||||
|
USBPhyHw *priv=((USBPhyHw *)(hpcd->pData));
|
||||||
|
priv->events->suspend(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
|
||||||
|
{
|
||||||
|
USBPhyHw *priv=((USBPhyHw *)(hpcd->pData));
|
||||||
|
priv->events->suspend(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
|
||||||
|
{
|
||||||
|
// Nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
|
||||||
|
{
|
||||||
|
// Nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
|
||||||
|
{
|
||||||
|
USBPhyHw *obj=((USBPhyHw *)(hpcd->pData));
|
||||||
|
unsigned int i;
|
||||||
|
for(i=0;i<hpcd->Init.dev_endpoints;i++) {
|
||||||
|
obj->epComplete[2*i]=0;
|
||||||
|
HAL_PCD_EP_Close(hpcd,IDX_TO_EP(2*i));
|
||||||
|
HAL_PCD_EP_Flush(hpcd,IDX_TO_EP(2*i));
|
||||||
|
obj->epComplete[2*i+1]=0;
|
||||||
|
HAL_PCD_EP_Close(hpcd,IDX_TO_EP(2*i+1));
|
||||||
|
HAL_PCD_EP_Flush(hpcd,IDX_TO_EP(2*i+1));
|
||||||
|
|
||||||
|
}
|
||||||
|
obj->endpoint_add(EP0IN, MAX_PACKET_SIZE_EP0, USB_EP_TYPE_CTRL);
|
||||||
|
obj->endpoint_add(EP0OUT, MAX_PACKET_SIZE_EP0, USB_EP_TYPE_CTRL);
|
||||||
|
obj->events->reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* hal pcd handler , used for STM32 HAL PCD Layer */
|
||||||
|
|
||||||
|
static USBPhyHw *instance;
|
||||||
|
|
||||||
|
USBPhy *get_usb_phy()
|
||||||
|
{
|
||||||
|
static USBPhyHw usbphy;
|
||||||
|
return &usbphy;
|
||||||
|
}
|
||||||
|
|
||||||
|
USBPhyHw::USBPhyHw(): events(NULL), sof_enabled(false)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
USBPhyHw::~USBPhyHw()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBPhyHw::init(USBPhyEvents *events)
|
||||||
|
{
|
||||||
|
NVIC_DisableIRQ(USBHAL_IRQn);
|
||||||
|
|
||||||
|
this->events = events;
|
||||||
|
sof_enabled = false;
|
||||||
|
memset(epComplete, 0, sizeof(epComplete));
|
||||||
|
memset(pBufRx, 0, sizeof(pBufRx));
|
||||||
|
memset(pBufRx0, 0, sizeof(pBufRx0));
|
||||||
|
memset(&hpcd.Init, 0, sizeof(hpcd.Init));
|
||||||
|
memset(_read_size, 0, sizeof(_read_size));
|
||||||
|
memset(_read_buf, 0, sizeof(_read_buf));
|
||||||
|
|
||||||
|
#if defined(TARGET_DISCO_F769NI) || \
|
||||||
|
defined(TARGET_DISCO_F746NG_OTG_HS)
|
||||||
|
hpcd.Instance = USB_OTG_HS;
|
||||||
|
hpcd.Init.phy_itface = PCD_PHY_ULPI;
|
||||||
|
hpcd.Init.Sof_enable = 1;
|
||||||
|
hpcd.Init.speed = PCD_SPEED_HIGH;
|
||||||
|
#elif defined(TARGET_DISCO_F429ZI)
|
||||||
|
hpcd.Instance = USB_OTG_HS;
|
||||||
|
hpcd.Init.phy_itface = PCD_PHY_EMBEDDED;
|
||||||
|
hpcd.Init.Sof_enable = 1;
|
||||||
|
hpcd.Init.speed = PCD_SPEED_HIGH;
|
||||||
|
#else
|
||||||
|
hpcd.Instance = USB_OTG_FS;
|
||||||
|
hpcd.Init.phy_itface = PCD_PHY_EMBEDDED;
|
||||||
|
hpcd.Init.Sof_enable = 1;
|
||||||
|
hpcd.Init.speed = PCD_SPEED_FULL;
|
||||||
|
#endif
|
||||||
|
hpcd.Init.dev_endpoints = NB_ENDPOINT;
|
||||||
|
hpcd.Init.ep0_mps = MAX_PACKET_SIZE_EP0;
|
||||||
|
|
||||||
|
// Pass instance for usage inside call back
|
||||||
|
instance = this;
|
||||||
|
|
||||||
|
// Configure USB pins and other clocks
|
||||||
|
|
||||||
|
#if defined(TARGET_NUCLEO_F207ZG) || \
|
||||||
|
defined(TARGET_NUCLEO_F401RE) || \
|
||||||
|
defined(TARGET_NUCLEO_F411RE) || \
|
||||||
|
defined(TARGET_NUCLEO_F412ZG) || \
|
||||||
|
defined(TARGET_NUCLEO_F413ZH) || \
|
||||||
|
defined(TARGET_NUCLEO_F429ZI) || \
|
||||||
|
defined(TARGET_NUCLEO_F446RE) || \
|
||||||
|
defined(TARGET_NUCLEO_F446ZE) || \
|
||||||
|
defined(TARGET_NUCLEO_F767ZI) || \
|
||||||
|
defined(TARGET_NUCLEO_F746ZG) || \
|
||||||
|
defined(TARGET_DISCO_F407VG) || \
|
||||||
|
defined(TARGET_DISCO_F413ZH) || \
|
||||||
|
defined(TARGET_DISCO_F469NI) || \
|
||||||
|
defined(TARGET_DISCO_F746NG_OTG_FS)
|
||||||
|
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||||
|
pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); // DM
|
||||||
|
pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); // DP
|
||||||
|
pin_function(PA_9, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, GPIO_AF10_OTG_FS)); // VBUS
|
||||||
|
pin_function(PA_10, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_PULLUP, GPIO_AF10_OTG_FS)); // ID
|
||||||
|
pin_function(PA_8, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); // SOF
|
||||||
|
__HAL_RCC_USB_OTG_FS_CLK_ENABLE();
|
||||||
|
|
||||||
|
#elif defined(TARGET_DISCO_F429ZI)
|
||||||
|
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||||
|
pin_function(PB_14, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF12_OTG_HS_FS)); // DM
|
||||||
|
pin_function(PB_15, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF12_OTG_HS_FS)); // DP
|
||||||
|
pin_function(PB_13, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); // VBUS
|
||||||
|
__HAL_RCC_USB_OTG_HS_CLK_ENABLE();
|
||||||
|
|
||||||
|
#elif defined(TARGET_DISCO_L475VG_IOT01A) || \
|
||||||
|
defined(TARGET_DISCO_L476VG)
|
||||||
|
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||||
|
pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); // DM
|
||||||
|
pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); // DP
|
||||||
|
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||||
|
pin_function(PC_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); // VBUS
|
||||||
|
__HAL_RCC_PWR_CLK_ENABLE();
|
||||||
|
HAL_PWREx_EnableVddUSB();
|
||||||
|
__HAL_RCC_USB_OTG_FS_CLK_ENABLE();
|
||||||
|
|
||||||
|
#elif defined(TARGET_DISCO_F769NI) || \
|
||||||
|
defined(TARGET_DISCO_F746NG_OTG_HS)
|
||||||
|
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||||
|
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||||
|
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||||
|
__HAL_RCC_GPIOH_CLK_ENABLE();
|
||||||
|
__HAL_RCC_GPIOI_CLK_ENABLE();
|
||||||
|
pin_function(PA_5, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // CLK
|
||||||
|
pin_function(PA_3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // D0
|
||||||
|
pin_function(PB_0, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // D1
|
||||||
|
pin_function(PB_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // D2
|
||||||
|
pin_function(PB_5, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // D3
|
||||||
|
pin_function(PB_10, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // D4
|
||||||
|
pin_function(PB_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // D5
|
||||||
|
pin_function(PB_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // D6
|
||||||
|
pin_function(PB_13, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // D7
|
||||||
|
pin_function(PC_0, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // STP
|
||||||
|
pin_function(PH_4, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // NXT
|
||||||
|
#if defined(TARGET_DISCO_F769NI)
|
||||||
|
pin_function(PI_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // DIR
|
||||||
|
#else // TARGET_DISCO_F746NG
|
||||||
|
pin_function(PC_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_HS)); // DIR
|
||||||
|
#endif
|
||||||
|
__HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE();
|
||||||
|
__HAL_RCC_USB_OTG_HS_CLK_ENABLE();
|
||||||
|
|
||||||
|
#elif defined(TARGET_STEVAL_3DP001V1)
|
||||||
|
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||||
|
pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); // DM
|
||||||
|
pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); // DP
|
||||||
|
__HAL_RCC_USB_OTG_FS_CLK_ENABLE();
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error "USB pins are not configured !"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
__HAL_RCC_SYSCFG_CLK_ENABLE();
|
||||||
|
|
||||||
|
// Configure PCD and FIFOs
|
||||||
|
hpcd.pData = (void*)this;
|
||||||
|
hpcd.State = HAL_PCD_STATE_RESET;
|
||||||
|
HAL_PCD_Init(&hpcd);
|
||||||
|
|
||||||
|
/* 1.25 kbytes */
|
||||||
|
/* min value 16 (= 16 x 4 bytes) */
|
||||||
|
/* max value 256 (= 1K bytes ) */
|
||||||
|
/* maximum sum is 0x140 */
|
||||||
|
HAL_PCDEx_SetRxFiFo(&hpcd, (MAXTRANSFER_SIZE / 4));
|
||||||
|
|
||||||
|
// Configure interrupt vector
|
||||||
|
NVIC_SetVector(USBHAL_IRQn, (uint32_t)&_usbisr);
|
||||||
|
NVIC_SetPriority(USBHAL_IRQn, 1);
|
||||||
|
NVIC_EnableIRQ(USBHAL_IRQn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBPhyHw::deinit()
|
||||||
|
{
|
||||||
|
HAL_PCD_DeInit(&hpcd);
|
||||||
|
NVIC_DisableIRQ(USBHAL_IRQn);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool USBPhyHw::powered()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBPhyHw::connect()
|
||||||
|
{
|
||||||
|
HAL_PCD_Start(&hpcd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBPhyHw::disconnect()
|
||||||
|
{
|
||||||
|
HAL_PCD_Stop(&hpcd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBPhyHw::configure()
|
||||||
|
{
|
||||||
|
// Not needed
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBPhyHw::unconfigure()
|
||||||
|
{
|
||||||
|
// Not needed
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBPhyHw::sof_enable()
|
||||||
|
{
|
||||||
|
sof_enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBPhyHw::sof_disable()
|
||||||
|
{
|
||||||
|
sof_enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBPhyHw::set_address(uint8_t address)
|
||||||
|
{
|
||||||
|
HAL_PCD_SetAddress(&hpcd, address);
|
||||||
|
ep0_write(NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBPhyHw::remote_wakeup()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const usb_ep_table_t *USBPhyHw::endpoint_table()
|
||||||
|
{
|
||||||
|
static const usb_ep_table_t table = {
|
||||||
|
1280, // 1.25K for endpoint buffers
|
||||||
|
{
|
||||||
|
{USB_EP_ATTR_ALLOW_CTRL | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 80},
|
||||||
|
{USB_EP_ATTR_ALLOW_ALL | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 4},
|
||||||
|
{USB_EP_ATTR_ALLOW_ALL | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 4},
|
||||||
|
{USB_EP_ATTR_ALLOW_ALL | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 4},
|
||||||
|
{USB_EP_ATTR_ALLOW_ALL | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 4},
|
||||||
|
{0 | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 4},
|
||||||
|
{0 | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 4},
|
||||||
|
{0 | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 4},
|
||||||
|
{0 | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 4},
|
||||||
|
{0 | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 4},
|
||||||
|
{0 | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 4},
|
||||||
|
{0 | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 4},
|
||||||
|
{0 | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 4},
|
||||||
|
{0 | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 4},
|
||||||
|
{0 | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 4},
|
||||||
|
{0 | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 4}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return &table;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t USBPhyHw::ep0_set_max_packet(uint32_t max_packet)
|
||||||
|
{
|
||||||
|
// FUTURE - set endpoint 0 size and return this size
|
||||||
|
return MAX_PACKET_SIZE_EP0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read setup packet
|
||||||
|
void USBPhyHw::ep0_setup_read_result(uint8_t *buffer, uint32_t size)
|
||||||
|
{
|
||||||
|
if (size > MAX_PACKET_SIZE_SETUP) {
|
||||||
|
size = MAX_PACKET_SIZE_SETUP;
|
||||||
|
}
|
||||||
|
memcpy(buffer, hpcd.Setup, size);
|
||||||
|
memset(hpcd.Setup,0,MAX_PACKET_SIZE_SETUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBPhyHw::ep0_read(uint8_t *data, uint32_t size)
|
||||||
|
{
|
||||||
|
_read_buf[0] = data;
|
||||||
|
_read_size[0] = size;
|
||||||
|
|
||||||
|
uint8_t *pBuf = (uint8_t *)pBufRx0;
|
||||||
|
HAL_StatusTypeDef ret;
|
||||||
|
epComplete[EP_TO_IDX(EP0OUT)] = 2;
|
||||||
|
ret = HAL_PCD_EP_Receive(&hpcd, EP0OUT, pBuf, MAX_PACKET_SIZE_EP0 );
|
||||||
|
MBED_ASSERT(ret!=HAL_BUSY);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t USBPhyHw::ep0_read_result()
|
||||||
|
{
|
||||||
|
uint32_t length = (uint32_t) HAL_PCD_EP_GetRxCount(&hpcd, 0);
|
||||||
|
epComplete[EP_TO_IDX(EP0OUT)] = 0;
|
||||||
|
if (length) {
|
||||||
|
uint8_t *buff = (uint8_t *)pBufRx0;
|
||||||
|
memcpy(_read_buf[0], buff, _read_size[0] > length ? length : _read_size[0]);
|
||||||
|
}
|
||||||
|
_read_buf[0] = 0;
|
||||||
|
_read_size[0] = 0;
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBPhyHw::ep0_write(uint8_t *buffer, uint32_t size)
|
||||||
|
{
|
||||||
|
/* check that endpoint maximum size is not exceeding TX fifo */
|
||||||
|
MBED_ASSERT(hpcd.IN_ep[0].maxpacket >= size);
|
||||||
|
endpoint_write(EP0IN, buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBPhyHw::ep0_stall()
|
||||||
|
{
|
||||||
|
endpoint_stall(EP0IN);
|
||||||
|
endpoint_stall(EP0OUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool USBPhyHw::endpoint_add(usb_ep_t endpoint, uint32_t max_packet, usb_ep_type_t type)
|
||||||
|
{
|
||||||
|
uint32_t len;
|
||||||
|
if (max_packet > MAXTRANSFER_SIZE) return false;
|
||||||
|
if (endpoint & 0x80) {
|
||||||
|
HAL_PCDEx_SetTxFiFo(&hpcd, endpoint & 0x7f, (max_packet / 4) + 1);
|
||||||
|
len = HAL_PCDEx_GetTxFiFo(&hpcd,endpoint & 0x7f);
|
||||||
|
MBED_ASSERT(len >= max_packet);
|
||||||
|
}
|
||||||
|
HAL_StatusTypeDef ret = HAL_PCD_EP_Open(&hpcd, endpoint, max_packet, type);
|
||||||
|
MBED_ASSERT(ret!=HAL_BUSY);
|
||||||
|
return (ret == HAL_OK) ? true:false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBPhyHw::endpoint_remove(usb_ep_t endpoint)
|
||||||
|
{
|
||||||
|
HAL_StatusTypeDef ret = HAL_PCD_EP_Close(&hpcd, endpoint);
|
||||||
|
MBED_ASSERT(ret == HAL_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBPhyHw::endpoint_stall(usb_ep_t endpoint)
|
||||||
|
{
|
||||||
|
HAL_StatusTypeDef ret;
|
||||||
|
ret = HAL_PCD_EP_SetStall(&hpcd, endpoint);
|
||||||
|
MBED_ASSERT(ret!=HAL_BUSY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBPhyHw::endpoint_unstall(usb_ep_t endpoint)
|
||||||
|
{
|
||||||
|
HAL_StatusTypeDef ret;
|
||||||
|
ret = HAL_PCD_EP_ClrStall(&hpcd, endpoint);
|
||||||
|
MBED_ASSERT(ret!=HAL_BUSY);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool USBPhyHw::endpoint_read(usb_ep_t endpoint, uint8_t *data, uint32_t size)
|
||||||
|
{
|
||||||
|
_read_buf[EP_TO_LOG(endpoint)] = data;
|
||||||
|
_read_size[EP_TO_LOG(endpoint)] = size;
|
||||||
|
|
||||||
|
uint8_t* pBuf = (uint8_t *)pBufRx; //TODO - this buffer shouldn't be shared for multiple endpoints
|
||||||
|
HAL_StatusTypeDef ret;
|
||||||
|
// clean reception end flag before requesting reception
|
||||||
|
ret = HAL_PCD_EP_Receive(&hpcd, endpoint, pBuf, size);
|
||||||
|
MBED_ASSERT(ret!=HAL_BUSY);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t USBPhyHw::endpoint_read_result(usb_ep_t endpoint)
|
||||||
|
{
|
||||||
|
uint8_t *buffer =_read_buf[EP_TO_LOG(endpoint)];
|
||||||
|
uint8_t max_size = _read_size[EP_TO_LOG(endpoint)];
|
||||||
|
|
||||||
|
if (epComplete[EP_TO_IDX(endpoint)]==0) {
|
||||||
|
/* no reception possible !!! */
|
||||||
|
return 0;
|
||||||
|
} else if ((epComplete[EP_TO_IDX(endpoint)]!=1)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint8_t *buff = (uint8_t *)pBufRx;
|
||||||
|
uint32_t length = (uint32_t) HAL_PCD_EP_GetRxCount(&hpcd, endpoint);
|
||||||
|
memcpy(buffer, buff, length > max_size ? max_size : length);
|
||||||
|
epComplete[EP_TO_IDX(endpoint)]= 0;
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool USBPhyHw::endpoint_write(usb_ep_t endpoint, uint8_t *data, uint32_t size)
|
||||||
|
{
|
||||||
|
HAL_StatusTypeDef ret;
|
||||||
|
// clean transmission end flag before requesting transmission
|
||||||
|
epComplete[EP_TO_IDX(endpoint)] = 2;
|
||||||
|
ret = HAL_PCD_EP_Transmit(&hpcd, endpoint, data, size);
|
||||||
|
MBED_ASSERT(ret!=HAL_BUSY);
|
||||||
|
// update the status
|
||||||
|
if (ret != HAL_OK) return false;
|
||||||
|
// fix me return is too simple
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBPhyHw::endpoint_abort(usb_ep_t endpoint)
|
||||||
|
{
|
||||||
|
// TODO - stop the current transfer on this endpoint and don't call the IN or OUT callback
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBPhyHw::process()
|
||||||
|
{
|
||||||
|
HAL_PCD_IRQHandler(&instance->hpcd);
|
||||||
|
// Re-enable interrupt
|
||||||
|
NVIC_ClearPendingIRQ(USBHAL_IRQn);
|
||||||
|
NVIC_EnableIRQ(USBHAL_IRQn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBPhyHw::_usbisr(void) {
|
||||||
|
NVIC_DisableIRQ(USBHAL_IRQn);
|
||||||
|
instance->events->start_process();
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO - remove this hack which allows HAL_Delay to work when interrupts are disabled
|
||||||
|
extern "C" uint32_t HAL_GetTick()
|
||||||
|
{
|
||||||
|
return ticker_read_us(get_us_ticker_data()) / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue