单片机
返回首页

STM32F1两个USB中断入口详解

2023-08-23 来源:elecfans

1 STM32F1两个USB中断入口


STM32中断入口有两个,分别是USB_HP_CAN1_TX_IRQHandler和USB_LP_CAN1_RX0_IRQHandler。


其中USB_Istr函数调用了CTR_LP函数,代码如下。


/*******************************************************************************

* Function Name  : USB_HP_CAN1_TX_IRQHandler

* Description    : This function handles USB High Priority or CAN TX interrupts

*                  requests.

* Input          : None

* Output         : None

* Return         : None

*******************************************************************************/

void USB_HP_CAN1_TX_IRQHandler(void)

{

  CTR_HP();

}


/*******************************************************************************

* Function Name  : USB_LP_CAN1_RX0_IRQHandler

* Description    : This function handles USB Low Priority or CAN RX0 interrupts

*                  requests.

* Input          : None

* Output         : None

* Return         : None

*******************************************************************************/

void USB_LP_CAN1_RX0_IRQHandler(void)

{

  USB_Istr();

}

2 CTR_LP


CTR_LP为低优先级端点传输正常时的中断服务函数,控制传输只能在CTR_LP里面处理,代码如下。


/*******************************************************************************

* Function Name  : CTR_LP.

* Description    : Low priority Endpoint Correct Transfer interrupt's service

*                  routine.

* Input          : None.

* Output         : None.

* Return         : None.

*******************************************************************************/

void CTR_LP(void)

{

  uint32_t wEPVal = 0;

  /* stay in loop while pending ints */

  while (((wIstr = _GetISTR()) & ISTR_CTR) != 0)

  {

    _SetISTR((uint16_t)CLR_CTR); /* clear CTR flag */

    /* extract highest priority endpoint number */

    EPindex = (uint8_t)(wIstr & ISTR_EP_ID);

    if (EPindex == 0)

    {

      /* Decode and service control endpoint interrupt */

      /* calling related service routine */

      /* (Setup0_Process, In0_Process, Out0_Process) */


      /* save RX & TX status */

      /* and set both to NAK */

      SaveRState = _GetEPRxStatus(ENDP0);

      SaveTState = _GetEPTxStatus(ENDP0);

      _SetEPRxStatus(ENDP0, EP_RX_NAK);

      _SetEPTxStatus(ENDP0, EP_TX_NAK);



      /* DIR bit = origin of the interrupt */


      if ((wIstr & ISTR_DIR) == 0)

      {

        /* DIR = 0 */


        /* DIR = 0      = > IN  int */

        /* DIR = 0 implies that (EP_CTR_TX = 1) always  */



        _ClearEP_CTR_TX(ENDP0);

        In0_Process();


           /* before terminate set Tx & Rx status */

          _SetEPRxStatus(ENDP0, SaveRState);

          _SetEPTxStatus(ENDP0, SaveTState);

          return;

      }

      else

      {

        /* DIR = 1 */


        /* DIR = 1 & CTR_RX       = > SETUP or OUT int */

        /* DIR = 1 & (CTR_TX | CTR_RX) = > 2 int pending */


        wEPVal = _GetENDPOINT(ENDP0);

        if ((wEPVal & EP_CTR_TX) != 0)

        {

          _ClearEP_CTR_TX(ENDP0);

          In0_Process();

          /* before terminate set Tx & Rx status */

          _SetEPRxStatus(ENDP0, SaveRState);

          _SetEPTxStatus(ENDP0, SaveTState);

          return;

        }

        else if ((wEPVal &EP_SETUP) != 0)

        {

          _ClearEP_CTR_RX(ENDP0); /* SETUP bit kept frozen while CTR_RX = 1 */

          Setup0_Process();

          /* before terminate set Tx & Rx status */

          _SetEPRxStatus(ENDP0, SaveRState);

          _SetEPTxStatus(ENDP0, SaveTState);

          return;

        }


        else if ((wEPVal & EP_CTR_RX) != 0)

        {

          _ClearEP_CTR_RX(ENDP0);

          Out0_Process();

          /* before terminate set Tx & Rx status */

          _SetEPRxStatus(ENDP0, SaveRState);

          _SetEPTxStatus(ENDP0, SaveTState);

          return;

        }

      }

    }/* if(EPindex == 0) */

    else

    {

      /* Decode and service non control endpoints interrupt  */


      /* process related endpoint register */

      wEPVal = _GetENDPOINT(EPindex);

      if ((wEPVal & EP_CTR_RX) != 0)

      {

        /* clear int flag */

        _ClearEP_CTR_RX(EPindex);


        /* call OUT service function */

        (*pEpInt_OUT[EPindex-1])();


      } /* if((wEPVal & EP_CTR_RX) */


      if ((wEPVal & EP_CTR_TX) != 0)

      {

        /* clear int flag */

        _ClearEP_CTR_TX(EPindex);


        /* call IN service function */

        (*pEpInt_IN[EPindex-1])();

      } /* if((wEPVal & EP_CTR_TX) != 0) */


    }/* if(EPindex == 0) else */


  }/* while(...) */

}

3 CTR_HP


CTR_HP为高优先级端点传输正常时的中断服务函数,代码如下。


/*******************************************************************************

* Function Name  : CTR_HP.

* Description    : High Priority Endpoint Correct Transfer interrupt's service 

*                  routine.

* Input          : None.

* Output         : None.

* Return         : None.

*******************************************************************************/

void CTR_HP(void)

{

  uint32_t wEPVal = 0;


  while (((wIstr = _GetISTR()) & ISTR_CTR) != 0)

  {

    _SetISTR((uint16_t)CLR_CTR); /* clear CTR flag */

    /* extract highest priority endpoint number */

    EPindex = (uint8_t)(wIstr & ISTR_EP_ID);

    /* process related endpoint register */

    wEPVal = _GetENDPOINT(EPindex);

    if ((wEPVal & EP_CTR_RX) != 0)

    {

      /* clear int flag */

      _ClearEP_CTR_RX(EPindex);


      /* call OUT service function */

      (*pEpInt_OUT[EPindex-1])();


    } /* if((wEPVal & EP_CTR_RX) */

    else if ((wEPVal & EP_CTR_TX) != 0)

    {

      /* clear int flag */

      _ClearEP_CTR_TX(EPindex);


      /* call IN service function */

      (*pEpInt_IN[EPindex-1])();



    } /* if((wEPVal & EP_CTR_TX) != 0) */


  }/* while(...) */

}

4 CTR_LP和CTR_HP各自处理的事务类型


这两个函数定义在usb_int.c中,用法如下。


CTR_LP(低优先级中断Low-priority interrupt),用于控制传输、中断传输、批量传输( 单缓冲模式)。


CTR_HP(高优先级中断 High-priority interrupt),用于快速大数据量传输处理,比如同步传输、批量传输,但是都是处理双缓冲模式。


5 核心注意要点


如果把只初始化了USB_LP_CAN1_RX0_IRQn中断向量,则所有的正确传输中断只会进入USB_LP_CAN1_RX0_IRQHandler->CTR_LP,所以要想进入CTR_HP必须对其中断向量进行初始化,否则会使用默认的CTR_LP路径进行处理。


进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

最新器件
精选电路图
  • 如何利用ESP8266制作一个简单的四轴飞行器

  • 非常简单的150W功放电路图

  • 基于IC555的可变PWM振荡器电路

  • 一个简单的立体声平衡指示器电路

  • 使用NE555和磁簧开关的橱柜照明电路

  • 电谐波图形均衡器示意图

    相关电子头条文章