0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

使用MM32F0270 USB从Suspend模式唤醒

jf_pJlTbmA9 来源:灵动MM32MCU 作者:灵动MM32MCU 2023-09-26 16:39 次阅读

在许多的PC的USB应用中,越来越多的需要使用低功耗功能,PC可结合USB提供一定的供电能力,使得外设在1.5W以内,可以不用其他单独的外部供电;更巧妙的是PC可以进入Sleep,驱使USB外设也进入Suspend状态,达到只提供2.5mA的供电需求,以达到低功耗的目的。灵动微电子推出的MM32F0270系列,支持多种灵活的低功耗模式,支持Suspend模式的USB Device模块。USB外设支持 USB挂起 /恢复操作,可以通过停止MCU时钟来实现降低功耗。

当USB设备处于挂起状态时,它仍然为其D+或D-及上拉电阻器供电,以保持空闲状态并保持其内部状态,包括地址和配置。当它被USB总线上的恢复信号唤醒时,它不需要经历重新枚举过程。

USB总线上的恢复信号可以由主机和设备发送。远程唤醒功能使USB设备能够唤醒挂起的主机;例如,将鼠标连接到笔记本电脑时,您可以通过单击鼠标来唤醒已经进入睡眠状态的笔记本电脑(PC端需要配置为支持远程唤醒)。远程唤醒功能在枚举阶段在配置描述符中报告,并且可以使用标准 USB 请求启用(或禁用)。

本文介绍了如何使用 MM32F0270的USB来实现通过接收USB的D+/D-信号在实现Suspend/Resume的状态转换。

1、MM32F0270 USB的简要介绍

符合 USB 2.0全速设备的技术规范;

支持全速模式(12M)

包含四个独立的通用端点和一个控制传输端点用于中断传输和批量传输

控制、批量 、 中断传输 最大可传输 64字节的包

CRC生成 /校验, NRZI编码 /解码和位填充

支持 USB挂起 /恢复操作

支持 DMA传输

poYBAGIPK7yAVVvyAACZ9vN0WK4582.png 图1 USB的功能框图

2、USB的功能特性

2.1、MM32的USB具有以下特性

USB模块可以为PC主机和微控制器提供一种符合USB规范的通信连接,用于两者所实现的功能之间的连接。PC主机和微控制器之间通过数据缓冲区完成数据传输,USB模块与PC主机通信,根据USB规范完成对令牌分组的检测,对数据发送/接收和握手分组的处理。由硬件完成对包括CRC的生成和校验等整个传输的格式。每一个端点都有一个64字节缓冲区描述块,且该缓冲区是在USB模块内部,不能直接被CPU访问的。一个有效的功能/端点的令牌分组被USB模块识别,当端点已配置完成后发生相关的数据传输。USB模块与专用数据缓冲区的数据交换通过内部寄存器完成。在所有的数据传输完成后,根据需要的传输方向,发送或接收适当的握手分组。

数据传输完成时,USB模块会触发端点相关的中断,通过读取状态寄存器或利用不同的中断处理程序,可以确定:

主机请求的传输类型

哪个端点需要得到服务

正在进行的是哪种类型的服务

端点的应答

传输是否完成

USB模块在不工作时,可以通过配置USB_POWER寄存器使 USB模块处于SUSPEND模式(低功耗模式)。USB模块在低功耗模式下,USB时钟会减慢或停止且USB模块不产生静态电流功耗。USB模块在低功耗模式下,可以通过USB线上数据传输将其唤醒,也可以通过软件直接将其唤醒。或者通过将特定的中断输入源连接到唤醒引脚上,使系统立即恢复正常的时钟,可以直接启动或停止时钟系统。

2.2、MM32F0270 USB用于挂起和恢复的USB总线状态

USB 规范定义了与 USB 总线上的信号电压相对应的总线状态。

下图为连接到D+的1.5 kΩ上拉电阻的全速总线。

poYBAGIPLAqAYYFmAAAwxsQ2EXY306.jpg

MM32F0270系列芯片内置1.5K上拉电阻。

下面介绍USB 总线如何定义挂起、恢复和空闲状态的总线状态。

设备的挂起

在USB系统中,正常状态下PC,Hub或Root Hub会一直周期性地发送SOF包(Start Of Frame,全速USB每1ms发送一个,高速USB则是125µs发送一个)。根据USB协议,如果USB线上一直处于空闲(Idle)状态超过3ms,设备应该把它当作一个挂起(Suspended)信号,要求设备在10ms内进入挂起状态,并把设备所需的电流大小降到规定的值;对于low-power设备,要求是500µA,而对于high-power或支持远程唤醒(remote wakeup)功能的设备是2.5mA。在挂起状态中,设备必须继续向数据项D+/D-的上拉电阻提供电压以维持Idle状态。

poYBAGIPLq2AVXeHAAASZhVC_-c413.jpg

设备的唤醒

设备处于挂起状态时,任何总线上的活动(非空闲信号)都可以把设备唤醒/恢复,从而退出低功耗模式。同样,设备也可以换醒host,比如电脑待机时通过USB键盘来换醒主机,这种功能称之为“远程唤醒”(remote wakeup),不在本文的讨论范围内。

因为设备挂起时处于全速信号,在当host需要把将设备退出suspend状态时,需要先发送一个持续时间超过20ms的Fulll Speed K状态。设备看到K状态结束的1.3us内醒过来,而host需要在3ms内发送SOF信号以维持正常的高速信号模式,否则设备又将进入suspend。如下图所示:

poYBAGIPLs6AM1zmAAAnTq4v-SQ493.jpg

下面是USB的数据状态与信号的说明:

数据 J 和 K 状态Data J and K states

对于全速总线段,J 状态与差分 1 相同,即 D+ 为逻辑高电平时和 D- 为逻辑低电平,而 K 状态与差分 0 相同,即当 D+ 为逻辑低电平且D- 是逻辑高电平。

空闲状态Idle state

在空闲状态下,对于全速总线段,D+ 比 D- 的电平高。

挂起状态Suspend signal

由于当USB总线处于空闲状态超过3 ms时进入挂起状态,因此挂起状态与空闲状态相同或与全速总线段中的J状态相同。

恢复信号Resume signal

当设备处于挂起状态时,设备端口上的数据K状态表示从挂起状态恢复。这意味着恢复信号是全速段中从数据J状态到数据K状态的变化。

2.3、MM32F0270 USB支持从Suspend模式下唤醒

MM32F0270 可通过EXTI线 18连接到 USB总线挂起中断实现USB从挂起状态唤醒。

需要使用唤醒时,需要使能相应的USB中断外,还需配置EXTI 18以使能相关的功能。

相关的寄存器与控制状态位的控制与查询,可以参考MM32F0270的用户手册。

3、USB进入Suspend与Res ume的软硬件设计

3.1、在库函数版本的样例中可以通过如下顺序初始化USB

a.配置系统时钟为48MHz或96Mhz,使能GPIOA时钟,使能USB时钟

void USB_ClockConfig(void)
{
    USB_HSI48M_Config();
    Set_CRS();      // The calibration of vibration
    // Select USBCLK source
//    RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div2); //if SYSCLK is 96MHz
    // Enable USB clock
    RCC_APB1PeriphClockCmd(RCC_APB1ENR_USB, ENABLE);
}

b.配置USB D+和D-所需用到的GPIO引脚,使用GPIO_Configuration函数

void GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_StructInit( GPIO_InitStruct);
    RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE);

    // USB_DISCONNECT used as USB pull-up
    GPIO_InitStruct.GPIO_Pin = USB_DISCONNECT_PIN;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_FLOATING;
    GPIO_Init(USB_DISCONNECT,  GPIO_InitStruct);
}

c.配置USB的中断,调用USB_NVIC_Config函数

void USB_NVIC_Config(void)
{
    NVIC_InitTypeDef NVIC_InitStruct;

    NVIC_InitStruct.NVIC_IRQChannel = USB_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPriority = 0;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init( NVIC_InitStruct);
}

d.设置USB的时钟,调用USB_ClockConfig

void USB_ClockConfig(void)
{
    USB_HSI48M_Config();
    Set_CRS();      // The calibration of vibration
    // Select USBCLK source
//    RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div2);
    // Enable USB clock
    RCC_APB1PeriphClockCmd(RCC_APB1ENR_USB, ENABLE);
}

e.设置USB 初始化

void USB_Init(void)
{
    pInformation =  Device_Info;
    pInformation->ControlState = 2;
    pProperty =  Device_Property;
    pUser_Standard_Requests =  User_Standard_Requests;
    // Initialize devices one by one
    pProperty->Init();
}

f.设定USB对应唤醒的EXTI参数

void USB1_WKUP_Init(void)
{
    EXTI_InitTypeDef EXTI_InitStructure;

    EXTI_InitStructure.EXTI_Line = EXTI_Line18;            
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;    
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init( EXTI_InitStructure);                        
}

g.中断相应处理函数

void USB_Istr(void)
{
    __IO u16 wIstr;
    wIstr = _GetUSB_INT_STA();
    //USB->INT_STATE = wIstr;

    // fSuspendEnabled = 0;
    if(wIstr   USB_INT_STATE_RSTF) {
        _ClrUSB_INT_STA(USB_INT_STATE_RSTF) ;
        Device_Property.Reset();
    }
//…
    EXTI_ClearITPendingBit(EXTI_Line22);
}

3.2、实现main Demo功能的主要函数代码

s32 main(void)
{
    GPIO_Configuration();
    USB_NVIC_Config();
    USB_ClockConfig();
    USB_Init();
    while(1) {
        if(bDeviceState == CONFIGURED) {
            if(!(_GetUSB_CTRL1() EP1_CTRL_TRANEN)) {
                UserToPMABufferCopy(gTableData, ENDP1, BUFF_SIZE);
                _SetUSB_CTRL1(EP1_CTRL_TRANEN | BUFF_SIZE) ; //Loop IN transmission
            }
        }
    }
}

配置好初始化USB收发的初始化操作后,PC端会发现USB HID枚举成功;此时PC端进入待机模式,

poYBAGIPLwmANDGFAAAhuVnmhYE253.png

MCU的USB收到Suspend的命令后,执行:

void Suspend(void)
{

    if(bDeviceState == CONFIGURED) {
        //Frequency the bus clock 512
        USB->POWER  = ~USB_POWER_SUSP;

        bDeviceState = SUSPENDED;
        fSuspendEnabled = true;

        RCC->CFGR  = ~RCC_CFGR_HPRE;
        RCC->CFGR |=  RCC_CFGR_HPRE_DIV512;
        RCC->CR  = ~(0x1f << 26);

        RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div4);

        UART_DeInit(UART1);

    }

}

USB唤醒机制

USB设备进入挂起状态之后,将由Resume信号进行唤醒。Resume信号可以由USB主机发起,也可以由USB设备本身触发,但是只有USB主机可以结束Resume信号。

主机在挂起设备后可通过翻转数据线上的极性并保持20ms来唤醒设备,并以低速EOP信号结尾。

如果设备支持远程唤醒,设备可向主机发起远程唤醒请求,前提是设备已进入idle状态至少5ms,设备会驱动总线进入K状态,如下图,K状态必须维持1ms-15ms之内,此信号会在1ms内被主机接管,主机会继续驱动唤醒信号直到20ms,并以低速EOP信号结尾。

主机复位设备或者设备对自己强行复位,设备也会从挂起状态切换到默认状态。

MM32F0270 设备被唤醒后,如果唤醒中断使能(比如使用PA0的EXTI0),则会进入唤醒中断,退出低功耗模式,然后清除USB_POWER寄存器的SUSPEND位,退出强制挂起操作。

操作上体现为PC Host主机同按主机KeyBoard或鼠标按键实现退出睡眠状态,从而唤醒MM32F0270的挂起状态。

通过上述的步骤,简单的演示了MM32F0270的USB 接收数据,通过数据帧中的Start Bit唤醒MCU的功能。

Demo程序可登录MindMotion的官网下载MM32F0270 lib_Samples

工程路径如下:

~ MM32F0270_SamplesLibSamplesUSB

来源:灵动MM32MCU

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • mcu
    mcu
    +关注

    关注

    146

    文章

    16019

    浏览量

    343673
  • usb
    usb
    +关注

    关注

    59

    文章

    7437

    浏览量

    258234
  • 总线
    +关注

    关注

    10

    文章

    2712

    浏览量

    87223
  • 低功耗
    +关注

    关注

    10

    文章

    2227

    浏览量

    102692
收藏 人收藏

    评论

    相关推荐

    [实战经验] STM32F767 的 USB 工作在 HOST 模式下的远程唤醒问题

    1 前言 本文将针对 STM32F767 的 USB_OTG_FS 模块工作在 Host 模式下的挂起与恢复以及远程唤醒方面的问题进行讨论。 2 问题描述 客户使用 STM32
    发表于 03-27 13:49

    灵动微课堂 (第196讲) | 使用MM32F0270 LPTIMSTOP模式唤醒

    了如何使用 MM32F0270的LPTIM来实现定时1sSTOP方式的低功耗模式唤醒。实现使用LPTIM1,在低功耗stop模式下定时1
    发表于 01-10 11:38

    灵动微课堂 (第197讲) | MM32F0270 UART空闲中断 + DMA接收不定长数据

    ,一旦接收的数据断流,没有接收到数据,即产生空闲中断。MM32F0270系列的UART支持空闲中断功能。相关的寄存器包括UART中断状态寄存器(UART_ISR)、 UART中断使能寄存器
    发表于 01-10 11:42

    灵动微课堂 (第198讲) | 使用MM32F0270 LPUART从低功耗模式唤醒

    了如何使用 MM32F0270的LPUART来实现通过接收外部UART的信号,触发MCUSleep/DeepSleep低功耗模式唤醒。1MM32
    发表于 01-17 13:24

    灵动微课堂 (第199讲) | 使用MM32F0270 USBSuspend模式唤醒

    时,设备端口上的数据K状态表示挂起状态恢复。这意味着恢复信号是全速段中数据J状态到数据K状态的变化。2.3MM32F0270 USB支持
    发表于 02-18 13:32

    灵动微课堂 (第200讲) | 使用MM32F0270 定时器DMA方式输出PWM

    MM32F0270的定时器TIM1、TIM2、TIM3、TIM15、TIM16/17有DMA模式,能够在发生单个事件时生成多个DMA 请求。主要目的是在没有软件开销的情况下,多次重新编程定时器的一部分
    发表于 02-18 13:36

    灵动微课堂 (第200讲) | 使用MM32F0270 定时器DMA方式输出PWM

    MM32F0270的定时器TIM1、TIM2、TIM3、TIM15、TIM16/17有DMA模式,能够在发生单个事件时生成多个DMA 请求。主要目的是在没有软件开销的情况下,多次重新编程定时器的一部分
    发表于 03-17 17:26

    MM32F0270 产品手册(中文版)

    MM32F0270 产品手册(中文版)
    发表于 02-23 18:36 0次下载
    <b class='flag-5'>MM32F0270</b> 产品手册(中文版)

    MM32F0270 产品手册(英文版)

    MM32F0270 产品手册(英文版)
    发表于 02-23 18:37 0次下载
    <b class='flag-5'>MM32F0270</b> 产品手册(英文版)

    MM32F0270 用户手册(中文版)

    MM32F0270 用户手册(中文版)
    发表于 02-23 18:37 0次下载
    <b class='flag-5'>MM32F0270</b> 用户手册(中文版)

    MM32F0270 用户手册(英文版)

    MM32F0270 用户手册(英文版)
    发表于 02-23 18:38 0次下载
    <b class='flag-5'>MM32F0270</b> 用户手册(英文版)

    MM32F0270 勘误表(中文版)

    MM32F0270 勘误表(中文版)
    发表于 02-23 18:38 0次下载
    <b class='flag-5'>MM32F0270</b> 勘误表(中文版)

    MM32F0270 勘误表(英文版)

    MM32F0270 勘误表(英文版)
    发表于 02-23 18:39 0次下载
    <b class='flag-5'>MM32F0270</b> 勘误表(英文版)

    使用MM32F0270 定时器DMA方式输出PWM

    使用MM32F0270 定时器DMA方式输出PWM
    的头像 发表于 10-17 14:47 532次阅读
    使用<b class='flag-5'>MM32F0270</b> 定时器DMA方式输出PWM

    使用MM32F0270 LPTIM从STOP模式唤醒

    使用MM32F0270 LPTIM从STOP模式唤醒
    的头像 发表于 10-26 16:46 561次阅读
    使用<b class='flag-5'>MM32F0270</b> LPTIM从STOP<b class='flag-5'>模式</b><b class='flag-5'>唤醒</b>