STM32F7 Discovery - USB FS主机/设备模式检测

时间:2017-11-03 03:04:48

标签: c usb stm32 stm32f4 stm32f7

STM32F723IEK6 Discovery板具有全速USB接口。我试图将它初始化是徒劳的。从不从主机接收复位信号,并且未设置适当的中断标志。

FS接口是OTG。它应该检测VBUS电压和ID引脚的状态,以确定它是作为主机还是作为器件连接。在器件模式下,VBUS应由主机提供,ID引脚应断开并拉高。当设备检测到连接时,应拉动DP引脚以指示与主机的连接。然后主机通过拉低数据线来发送RESET信号。这是理论。

看起来电路板没有拉高DP线。在启用VBUS检测的默认OTG配置(如下面的程序中)中,只在GINTSTS寄存器中设置了CIDSCHG(ID更改),SRQINT(会话)和SOF位。 CMOD位为零,表示器件模式。即使没有连接电缆,ID线似乎也很低。

我在AF 10模式(OTG FS)中配置了相应的引脚(A9,A10,A11,A12)。但是,这可能是不必要的,因为FS PHY似乎直接连接到引脚,绕过GPIO多路复用器(不确定)。

我尝试强制设备模式并禁用VBUS检测,但这不会产生任何影响,也不会从GPIO上拉ID线。

我之前在STM32F4板上运行的代码相同,并且没有这样的问题。

我想了解为什么连接检测不起作用。

代码如下,对不起,它有时钟,GPIO和USB初始化代码,省略了一些辅助功能。

STM32F72x参考手册(15MB!)http://www.st.com/resource/en/reference_manual/dm00305990.pdf

数据表http://www.st.com/resource/en/datasheet/DM00330506.pdf

董事会手册http://www.st.com/resource/en/user_manual/dm00342318.pdf

#include "stm32f7xx.h"

#define PLL_M 25
#define PLL_N 336
#define PLL_P 0
#define PLL_Q 7
#define SYS_FREQ 168000000

void rcc_config(void)
{
    RCC->APB1ENR |= RCC_APB1ENR_PWREN;
    PWR->CR1 = (PWR->CR1 & ~PWR_CR1_VOS_Msk)
            | PWR_CR1_VOS_1;
    RCC->CR |= RCC_CR_HSEON;
    while ((RCC->CR & RCC_CR_HSERDY) == 0);
    RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (PLL_P << 16) | RCC_PLLCFGR_PLLSRC_HSE | (PLL_Q << 24);
    RCC->CR |= RCC_CR_PLLON;
    RCC->CFGR = (RCC->CFGR & ~(RCC_CFGR_HPRE_Msk | RCC_CFGR_PPRE1_Msk | RCC_CFGR_PPRE2_Msk))
            | RCC_CFGR_HPRE_DIV1
            | RCC_CFGR_PPRE2_DIV2
            | RCC_CFGR_PPRE1_DIV4;
    FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ARTEN | FLASH_ACR_LATENCY_5WS;
    while ((RCC->CR & RCC_CR_PLLRDY) == 0);
    while ((PWR->CSR1 & PWR_CSR1_VOSRDY) == 0);
    RCC->CFGR &= RCC_CFGR_SW;
    RCC->CFGR |= RCC_CFGR_SW_PLL;
    while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
}

#define GPIO_OTYPE_PP 0
#define GPIO_OTYPE_OD 1
#define GPIO_PULLUP   1

void gpio_config_mode(GPIO_TypeDef* gpio, unsigned pin, unsigned mode)
{
    gpio->MODER = (gpio->MODER & ~(3u << (2 * pin))) | (mode << (2 * pin));
}
void gpio_config_in(GPIO_TypeDef* gpio, unsigned pin)
{
    gpio_config_mode(gpio, pin, 0);
}
void gpio_config_out(GPIO_TypeDef* gpio, unsigned pin, unsigned otype, unsigned ospeed)
{
    gpio_config_mode(gpio, pin, 1);
    gpio->OTYPER  = (gpio->OTYPER  & ~(1u << (1 * pin))) | (otype  << (1 * pin));
    gpio->OSPEEDR = (gpio->OSPEEDR & ~(3u << (2 * pin))) | (ospeed << (2 * pin));
}
void gpio_config_af(GPIO_TypeDef* gpio, unsigned pin, unsigned af)
{
    gpio_config_mode(gpio, pin, 2);
    unsigned pin_group = pin >> 3;
    unsigned pin_offset = pin & 7;
    gpio->AFR[pin_group] = (gpio->AFR[pin_group] & ~(0xf << (pin_offset * 4)))
            | (af << (pin_offset * 4));
}
void gpio_config_pullup(GPIO_TypeDef* gpio, unsigned pin, unsigned pupd)
{
    gpio->PUPDR = (gpio->PUPDR   & ~(3u << (2 * pin))) | (pupd   << (2 * pin));
}

USB_OTG_GlobalTypeDef *usb = USB_OTG_FS;
USB_OTG_DeviceTypeDef *usb_dev = (USB_OTG_DeviceTypeDef *)(USB_OTG_FS_PERIPH_BASE + USB_OTG_DEVICE_BASE);

void usb_config(void)
{
    /* The application must program this register before starting any transactions
     * on either the AHB or the USB. Do not make changes to this register after
     * the initial programming. */
    usb->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL; // TODO: no effect for F7, read-only bit
//  usb->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD;
    /* After setting the force bit, the application must wait at least * 25 ms
     * before the change takes effect. */
    delay_ms(25);

    // USB core reset
    while ((usb->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0);
    usb->GRSTCTL |= USB_OTG_GRSTCTL_CSRST;
    while ((usb->GRSTCTL & USB_OTG_GRSTCTL_CSRST) != 0);
    delay_us(1); // actually, 3 PHY clocks

    usb_dev->DCFG = USB_OTG_DCFG_DSPD_0 | USB_OTG_DCFG_DSPD_1; // full speed
//  usb->GAHBCFG = 0;
//  usb->PCGCTL = 0;
    usb->GCCFG |= USB_OTG_GCCFG_VBDEN; // VBUS detection
    usb->GCCFG |= USB_OTG_GCCFG_PWRDWN; // enable PHY

/// usb->GINTSTS= 0xFFFFFFFF;
//  usb->GINTMSK = 0;
//  usb->GINTSTS = 0xFFFFFFFF;
//  usb->GAHBCFG |= USB_OTG_GAHBCFG_GINT;
}

void usb_poll(void)
{
    uint32_t intsts = usb->GINTSTS;
    if (intsts & USB_OTG_GINTSTS_USBRST)
        usb->GINTSTS = USB_OTG_GINTSTS_USBRST;
    if (intsts & USB_OTG_GINTSTS_RSTDET)
        usb->GINTSTS = USB_OTG_GINTSTS_RSTDET;
    if (intsts & USB_OTG_GINTSTS_ENUMDNE)
        usb->GINTSTS = USB_OTG_GINTSTS_ENUMDNE;
    if (intsts & USB_OTG_GINTSTS_CIDSCHG)
        usb->GINTSTS = USB_OTG_GINTSTS_CIDSCHG;
    if (intsts & USB_OTG_GINTSTS_SRQINT)
        usb->GINTSTS = USB_OTG_GINTSTS_SRQINT;
}

#define LED_PIN 5
#define USB_AF 10

int main()
{
    rcc_config();

    SysTick->LOAD = 0xffffffu;
    SysTick->VAL = 0;
    SysTick->CTRL = 5;

    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
    gpio_config_out(GPIOA, LED_PIN, GPIO_OTYPE_PP, 0);
    gpio_config_af(GPIOA,  9, USB_AF); // VBUS_DET
    gpio_config_af(GPIOA, 10, USB_AF); // ID
    gpio_config_af(GPIOA, 11, USB_AF); // DM
    gpio_config_af(GPIOA, 12, USB_AF); // DP

    RCC->AHB2ENR |= RCC_AHB2ENR_OTGFSEN;
    usb_config();
    while (1)
        usb_poll();
}

1 个答案:

答案 0 :(得分:1)

当然。

OTG_FS_DCTL注册:

  

第1位

     

SDIS:

     

软断开应用程序使用此位发出信号   USB OTG内核执行软断开。只要这一点   设置,主机没有看到设备已连接,并且   设备不接收USB上的信号。核心留在了   断开连接状态,直到应用程序清除此位。 0:正常   操作。软断开后,该位清零时,核心   生成设备连接事件到USB主机。当设备是   重新连接后,USB主机重启设备枚举。 1:核心   生成USB主机的设备断开事件。

从STM32F411手册:

  

重置值:0x0000 0000

从STM32F723手册:

  

重置值:0x0000 0002

除非应用程序修改了复位值,否则STM32F7 USB模块将在“软断开”状态下启动,而STM32F4会在检测到VBUS时立即尝试连接。文件(例如第32.6.2节外围国家)根本没有提到这个事实。

就我而言,清除SDIS位启用了成功的连接握手。