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();
}
答案 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位启用了成功的连接握手。