STM32F1两个USB中断入口详解

发布时间:2023-08-23  

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路径进行处理。


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>