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


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

相关文章

    相应优先级状态触发器置1;(2)执行一个硬件子程序的调用,1)硬件清零相应中断请求标志(TI、RI除外)2)将当前PC内容压入堆栈——保护断点;3)将中断服务子程序入口地址送PC——转移。返回过程:(RETI......
    较为复杂。 但51单片机这个过程被大大简化了,51系列基本型单片机只有5个中断源,这5个中断源的中断程序入口地址是固定的。 2)断点保护 在处理器找到中断程序的入口地址后,就会暂停主程序的执行,转去执行终端服务子程序......
    mode bits设置为0x12,将I位置为1,屏蔽IRQ中断,将T位置为1,进入ARM状态)        保存返回地址:将下一条指令的地址(被打断程序)保存在LR(异常模式下LR_excep)中......
    执行的走向应该如图所示。 STM32F10x有一个中断向量表,这个中断向量表存放在代码开始部分的后4个字节处(即0x0800 0004),代码开始的4个字节存放的是堆栈栈顶的地址,当发生中断后程序通过查找该表得到相应的中断服务程序入口地址......
    (又称中断向量)也位于程序存储器单元。在程序存储器中,每个中断都有一个固定的入口地址,当中断发生并得到响应后,单片机就会自动跳转到相应的中断入口地址去执行程序。外部中断 0(INT0)的中断服务程序的入口地址是......
    ; 0013H单元:外部中断/INT1的矢量入口地址; 001BH单元:定时器T1的溢出中断矢量入口地址; 0023H单元:串行口接收、传送的中断矢量入口地址。 矢量入口单元:在编写中断程序时,写入......
    ; 0013H单元:外部中断/INT1的矢量入口地址; 001BH单元:定时器T1的溢出中断矢量入口地址; 0023H单元:串行口接收、传送的中断矢量入口地址。 矢量入口单元:在编写中断程序......
    须包含一张向量表,用于初始时的异常分配。 值得注意的是这里有个另类: 0号类型并不是什么入口地址,而是给出了复位后 MSP的初值,后面会具体讲解。 …… 第55行:定义一块代码段,段名字是RESET......
    服务 程序的入口地址是 0003H,定时器/计数器 0(TIMER0)中断服务程序的入口地址是 000BH,外部中断 1(INT1) 的中断服务程序的入口地址是 0013H,定时器/计数器 1......
    在Cortex-M3内核复位后,会自动从起始地址的下一个32位空间取出复位中断入口向量,跳转执行复位中断服务程序。对比ARM7/ARM9内核,Cortex-M3内核则是固定了中断向量表的位置而起始地址是......

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

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

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

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

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

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

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