Files
discoverpixy/discovery/src/usb_bsp.c

469 lines
14 KiB
C

/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: discovery/src/usb_bsp.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-03 timolang@gmail.com 21dd1e2 Starting to integrate usb branch. Optimized Makefiles
*
**************************************************************************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "usb_bsp.h"
#include "stm32f4_discovery.h"
#define USE_ACCURATE_TIME
#define TIM_MSEC_DELAY 0x01
#define TIM_USEC_DELAY 0x02
#define HOST_OVRCURR_PORT GPIOD
#define HOST_OVRCURR_LINE GPIO_Pin_5
#define HOST_OVRCURR_PORT_SOURCE GPIO_PortSourceGPIOD
#define HOST_OVRCURR_PIN_SOURCE GPIO_PinSourceD
#define HOST_OVRCURR_PORT_RCC RCC_APB2Periph_GPIOD
#define HOST_OVRCURR_EXTI_LINE EXTI_Line5
#define HOST_OVRCURR_IRQn EXTI9_5_IRQn
#define HOST_POWERSW_PORT_RCC RCC_AHB1Periph_GPIOC
#define HOST_POWERSW_PORT GPIOC
#define HOST_POWERSW_VBUS GPIO_Pin_0
/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
ErrorStatus HSEStartUpStatus;
#ifdef USE_ACCURATE_TIME
__IO uint32_t BSP_delay = 0;
#endif
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
#ifdef USE_ACCURATE_TIME
static void BSP_SetTime(uint8_t Unit);
static void BSP_Delay(uint32_t nTime, uint8_t Unit);
static void USB_OTG_BSP_TimeInit(void);
#endif
/**
* @brief BSP_Init
* board user initializations
* @param None
* @retval None
*/
void BSP_Init(void)
{
/* Configure PA0 pin: User Key pin */
}
/**
* @brief USB_OTG_BSP_Init
* Initilizes BSP configurations
* @param None
* @retval None
*/
void USB_OTG_BSP_Init(USB_OTG_CORE_HANDLE* pdev)
{
/* Note: On STM32F4-Discovery board only USB OTG FS core is supported. */
GPIO_InitTypeDef GPIO_InitStructure;
#ifdef USE_USB_OTG_FS
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA , ENABLE);
/* Configure SOF VBUS ID DM DP Pins */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 |
GPIO_Pin_11 |
GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_OTG1_FS) ;
GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_OTG1_FS) ;
GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_OTG1_FS) ;
/* this for ID line debug */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_OTG1_FS) ;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_OTG_FS, ENABLE) ;
#else // USE_USB_OTG_HS
#ifdef USE_ULPI_PHY // ULPI
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB |
RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOH |
RCC_AHB1Periph_GPIOI, ENABLE);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_OTG2_HS) ; // D0
GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_OTG2_HS) ; // CLK
GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, GPIO_AF_OTG2_HS) ; // D1
GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF_OTG2_HS) ; // D2
GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_OTG2_HS) ; // D7
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_OTG2_HS) ; // D3
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_OTG2_HS) ; // D4
GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_OTG2_HS) ; // D5
GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_OTG2_HS) ; // D6
GPIO_PinAFConfig(GPIOH, GPIO_PinSource4, GPIO_AF_OTG2_HS) ; // NXT
GPIO_PinAFConfig(GPIOI, GPIO_PinSource11, GPIO_AF_OTG2_HS) ; // DIR
GPIO_PinAFConfig(GPIOC, GPIO_PinSource0, GPIO_AF_OTG2_HS) ; // STP
// CLK
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// D0
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// D1 D2 D3 D4 D5 D6 D7
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 |
GPIO_Pin_5 | GPIO_Pin_10 |
GPIO_Pin_11 | GPIO_Pin_12 |
GPIO_Pin_13 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// STP
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_Init(GPIOC, &GPIO_InitStructure);
//NXT
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_Init(GPIOH, &GPIO_InitStructure);
//DIR
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_Init(GPIOI, &GPIO_InitStructure);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_OTG_HS |
RCC_AHB1Periph_OTG_HS_ULPI, ENABLE) ;
#else
#ifdef USE_I2C_PHY
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB , ENABLE);
/* Configure RESET INTN SCL SDA (Phy/I2C) Pins */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 |
GPIO_Pin_1 |
GPIO_Pin_10 |
GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, GPIO_AF_OTG2_FS) ;
GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF_OTG2_FS) ;
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_OTG2_FS) ;
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_OTG2_FS);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_OTG_HS, ENABLE) ;
#else
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 |
GPIO_Pin_13 |
GPIO_Pin_14 |
GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_OTG2_FS) ;
GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_OTG2_FS) ;
GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_OTG2_FS) ;
GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_OTG2_FS) ;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_OTG_HS, ENABLE) ;
#endif
#endif
#endif //USB_OTG_HS
/* Intialize Timer for delay function */
USB_OTG_BSP_TimeInit();
}
/**
* @brief USB_OTG_BSP_EnableInterrupt
* Configures USB Global interrupt
* @param None
* @retval None
*/
void USB_OTG_BSP_EnableInterrupt(USB_OTG_CORE_HANDLE* pdev)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable USB Interrupt */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = OTG_FS_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Enable the Overcurrent Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = HOST_OVRCURR_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/**
* @brief BSP_Drive_VBUS
* Drives the Vbus signal through IO
* @param state : VBUS states
* @retval None
*/
void USB_OTG_BSP_DriveVBUS(USB_OTG_CORE_HANDLE* pdev, uint8_t state)
{
/*
On-chip 5 V VBUS generation is not supported. For this reason, a charge pump
or, if 5 V are available on the application board, a basic power switch, must
be added externally to drive the 5 V VBUS line. The external charge pump can
be driven by any GPIO output. When the application decides to power on VBUS
using the chosen GPIO, it must also set the port power bit in the host port
control and status register (PPWR bit in OTG_FS_HPRT).
Bit 12 PPWR: Port power
The application uses this field to control power to this port, and the core
clears this bit on an overcurrent condition.
*/
if (0 == state) {
/* DISABLE is needed on output of the Power Switch */
GPIO_SetBits(HOST_POWERSW_PORT, HOST_POWERSW_VBUS);
} else {
/*ENABLE the Power Switch by driving the Enable LOW */
GPIO_ResetBits(HOST_POWERSW_PORT, HOST_POWERSW_VBUS);
}
}
/**
* @brief USB_OTG_BSP_ConfigVBUS
* Configures the IO for the Vbus and OverCurrent
* @param None
* @retval None
*/
void USB_OTG_BSP_ConfigVBUS(USB_OTG_CORE_HANDLE* pdev)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(HOST_POWERSW_PORT_RCC, ENABLE);
/* Configure Power Switch Vbus Pin */
GPIO_InitStructure.GPIO_Pin = HOST_POWERSW_VBUS;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(HOST_POWERSW_PORT, &GPIO_InitStructure);
/* By Default, DISABLE is needed on output of the Power Switch */
GPIO_SetBits(HOST_POWERSW_PORT, HOST_POWERSW_VBUS);
USB_OTG_BSP_mDelay(200); /* Delay is need for stabilising the Vbus Low
in Reset Condition, when Vbus=1 and Reset-button is pressed by user */
}
/**
* @brief USB_OTG_BSP_TimeInit
* Initializes delay unit using Timer2
* @param None
* @retval None
*/
static void USB_OTG_BSP_TimeInit(void)
{
#ifdef USE_ACCURATE_TIME
NVIC_InitTypeDef NVIC_InitStructure;
/* Set the Vector Table base address at 0x08000000 */
// NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x00);
/* Configure the Priority Group to 2 bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* Enable the TIM2 gloabal Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
#endif
}
/**
* @brief USB_OTG_BSP_uDelay
* This function provides delay time in micro sec
* @param usec : Value of delay required in micro sec
* @retval None
*/
void USB_OTG_BSP_uDelay(const uint32_t usec)
{
#ifdef USE_ACCURATE_TIME
BSP_Delay(usec, TIM_USEC_DELAY);
#else
__IO uint32_t count = 0;
const uint32_t utime = (120 * usec / 7);
do {
if (++count > utime) {
return ;
}
} while (1);
#endif
}
/**
* @brief USB_OTG_BSP_mDelay
* This function provides delay time in milli sec
* @param msec : Value of delay required in milli sec
* @retval None
*/
void USB_OTG_BSP_mDelay(const uint32_t msec)
{
#ifdef USE_ACCURATE_TIME
BSP_Delay(msec, TIM_MSEC_DELAY);
#else
USB_OTG_BSP_uDelay(msec * 1000);
#endif
}
/**
* @brief USB_OTG_BSP_TimerIRQ
* Time base IRQ
* @param None
* @retval None
*/
void USB_OTG_BSP_TimerIRQ(void)
{
#ifdef USE_ACCURATE_TIME
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
if (BSP_delay > 0x00) {
BSP_delay--;
} else {
TIM_Cmd(TIM2, DISABLE);
}
}
#endif
}
#ifdef USE_ACCURATE_TIME
/**
* @brief BSP_Delay
* Delay routine based on TIM2
* @param nTime : Delay Time
* @param unit : Delay Time unit : mili sec / micro sec
* @retval None
*/
static void BSP_Delay(uint32_t nTime, uint8_t unit)
{
BSP_delay = nTime;
BSP_SetTime(unit);
while (BSP_delay != 0);
TIM_Cmd(TIM2, DISABLE);
}
/**
* @brief BSP_SetTime
* Configures TIM2 for delay routine based on TIM2
* @param unit : msec /usec
* @retval None
*/
static void BSP_SetTime(uint8_t unit)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_Cmd(TIM2, DISABLE);
TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);
if (unit == TIM_USEC_DELAY) {
TIM_TimeBaseStructure.TIM_Period = 11;
} else if (unit == TIM_MSEC_DELAY) {
TIM_TimeBaseStructure.TIM_Period = 11999;
}
TIM_TimeBaseStructure.TIM_Prescaler = 5;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
TIM_ARRPreloadConfig(TIM2, ENABLE);
/* TIM IT enable */
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
/* TIM2 enable counter */
TIM_Cmd(TIM2, ENABLE);
}
#endif
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/