OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 1275|回复: 0

STM32L4R5板子模拟用户自定义的USB设备的问题

[复制链接]

74

主题

182

帖子

0

精华

高级会员

Rank: 4

积分
588
金钱
588
注册时间
2014-10-15
在线时间
137 小时
发表于 2023-6-22 19:45:04 | 显示全部楼层 |阅读模式
1金钱
我仿照圈圈的书,写了个模拟用户自定义的USB设备。
可以识别了,发送按键没有问题。
只是点灯不行。
中断处理函数如下:
  1. #if defined (USB_OTG_FS)
  2. /**
  3.   * @brief  Handles PCD interrupt request.
  4.   * [url=home.php?mod=space&uid=271674]@param[/url]  hpcd PCD handle
  5.   * @retval HAL status
  6.   */
  7. void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
  8. {
  9.   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
  10.   uint32_t USBx_BASE = (uint32_t)USBx;
  11.   USB_OTG_EPTypeDef *ep;
  12.   uint32_t i;
  13.   uint32_t ep_intr;
  14.   uint32_t epint;
  15.   uint32_t epnum;
  16.   uint32_t fifoemptymsk;
  17.   uint32_t RegVal;

  18.        
  19.   /* ensure that we are in device mode */
  20.   if (USB_GetMode(hpcd->Instance) == USB_OTG_MODE_DEVICE)
  21.   {
  22.     /* avoid spurious interrupt */
  23.     if (__HAL_PCD_IS_INVALID_INTERRUPT(hpcd))
  24.     {
  25.       return;
  26.     }

  27.     /* store current frame number */
  28.     hpcd->FrameNumber = (USBx_DEVICE->DSTS & USB_OTG_DSTS_FNSOF_Msk) >> USB_OTG_DSTS_FNSOF_Pos;

  29.     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_MMIS))
  30.     {
  31.       /* incorrect mode, acknowledge the interrupt */
  32.       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_MMIS);
  33.     }

  34.     /* Handle RxQLevel Interrupt */
  35.     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL))
  36.     {
  37.       USB_MASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);

  38.       RegVal = USBx->GRXSTSP;

  39.       ep = &hpcd->OUT_ep[RegVal & USB_OTG_GRXSTSP_EPNUM];

  40.       if (((RegVal & USB_OTG_GRXSTSP_PKTSTS) >> 17) ==  STS_DATA_UPDT)
  41.       {
  42.         if ((RegVal & USB_OTG_GRXSTSP_BCNT) != 0U)
  43.         {
  44.           (void)USB_ReadPacket(USBx, ep->xfer_buff,
  45.                                (uint16_t)((RegVal & USB_OTG_GRXSTSP_BCNT) >> 4));
  46.                        
  47.                                        
  48.                                        
  49.           ep->xfer_buff += (RegVal & USB_OTG_GRXSTSP_BCNT) >> 4;
  50.           ep->xfer_count += (RegVal & USB_OTG_GRXSTSP_BCNT) >> 4;
  51.                                        
  52.                                         //HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, GPIO_PIN_SET);

  53.         }
  54.       }
  55.       else if (((RegVal & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_SETUP_UPDT)
  56.       {
  57.         (void)USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8U);
  58.         ep->xfer_count += (RegVal & USB_OTG_GRXSTSP_BCNT) >> 4;

  59.       }
  60.       else
  61.       {
  62.         /* ... */
  63.                                 //HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, GPIO_PIN_SET);
  64.       }

  65.       USB_UNMASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
  66.     }

  67.     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OEPINT))
  68.     {
  69.       epnum = 0U;

  70.       /* Read in the device interrupt bits */
  71.       ep_intr = USB_ReadDevAllOutEpInterrupt(hpcd->Instance);

  72.       while (ep_intr != 0U)
  73.       {
  74.         if ((ep_intr & 0x1U) != 0U)
  75.         {
  76.           epint = USB_ReadDevOutEPInterrupt(hpcd->Instance, (uint8_t)epnum);
  77.                                        
  78.                                         //////////////////////////////////////////////////////////////////
  79.        
  80.           if ((epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC)
  81.           {
  82.             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_XFRC);
  83.             (void)PCD_EP_OutXfrComplete_int(hpcd, epnum);
  84.           }

  85.           if ((epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP)
  86.           {
  87.             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STUP);
  88.             /* Class B setup phase done for previous decoded setup */
  89.             (void)PCD_EP_OutSetupPacket_int(hpcd, epnum);
  90.           }

  91.           if ((epint & USB_OTG_DOEPINT_OTEPDIS) == USB_OTG_DOEPINT_OTEPDIS)
  92.           {
  93.             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPDIS);
  94.           }

  95.           /* Clear OUT Endpoint disable interrupt */
  96.           if ((epint & USB_OTG_DOEPINT_EPDISD) == USB_OTG_DOEPINT_EPDISD)
  97.           {
  98.             if ((USBx->GINTSTS & USB_OTG_GINTSTS_BOUTNAKEFF) == USB_OTG_GINTSTS_BOUTNAKEFF)
  99.             {
  100.               USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGONAK;
  101.             }

  102.             ep = &hpcd->OUT_ep[epnum];

  103.             if (ep->is_iso_incomplete == 1U)
  104.             {
  105.               ep->is_iso_incomplete = 0U;

  106. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  107.               hpcd->ISOOUTIncompleteCallback(hpcd, (uint8_t)epnum);
  108. #else
  109.               HAL_PCD_ISOOUTIncompleteCallback(hpcd, (uint8_t)epnum);
  110. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  111.             }

  112.             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_EPDISD);
  113.           }

  114.           /* Clear Status Phase Received interrupt */
  115.           if ((epint & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR)
  116.           {
  117.             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
  118.           }

  119.           /* Clear OUT NAK interrupt */
  120.           if ((epint & USB_OTG_DOEPINT_NAK) == USB_OTG_DOEPINT_NAK)
  121.           {
  122.             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_NAK);
  123.           }
  124.         }
  125.         epnum++;
  126.         ep_intr >>= 1U;
  127.       }
  128.     }

  129.     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IEPINT))
  130.     {
  131.       /* Read in the device interrupt bits */
  132.       ep_intr = USB_ReadDevAllInEpInterrupt(hpcd->Instance);

  133.       epnum = 0U;

  134.       while (ep_intr != 0U)
  135.       {
  136.         if ((ep_intr & 0x1U) != 0U) /* In ITR */
  137.         {
  138.           epint = USB_ReadDevInEPInterrupt(hpcd->Instance, (uint8_t)epnum);

  139.           if ((epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC)
  140.           {
  141.             fifoemptymsk = (uint32_t)(0x1UL << (epnum & EP_ADDR_MSK));
  142.             USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;

  143.             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_XFRC);

  144. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  145.             hpcd->DataInStageCallback(hpcd, (uint8_t)epnum);
  146. #else
  147.             HAL_PCD_DataInStageCallback(hpcd, (uint8_t)epnum);
  148. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  149.           }
  150.           if ((epint & USB_OTG_DIEPINT_TOC) == USB_OTG_DIEPINT_TOC)
  151.           {
  152.             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_TOC);
  153.           }
  154.           if ((epint & USB_OTG_DIEPINT_ITTXFE) == USB_OTG_DIEPINT_ITTXFE)
  155.           {
  156.             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_ITTXFE);
  157.           }
  158.           if ((epint & USB_OTG_DIEPINT_INEPNE) == USB_OTG_DIEPINT_INEPNE)
  159.           {
  160.             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_INEPNE);
  161.           }
  162.           if ((epint & USB_OTG_DIEPINT_EPDISD) == USB_OTG_DIEPINT_EPDISD)
  163.           {
  164.             (void)USB_FlushTxFifo(USBx, epnum);

  165.             ep = &hpcd->IN_ep[epnum];

  166.             if (ep->is_iso_incomplete == 1U)
  167.             {
  168.               ep->is_iso_incomplete = 0U;

  169. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  170.               hpcd->ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
  171. #else
  172.               HAL_PCD_ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
  173. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  174.             }

  175.             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_EPDISD);
  176.           }
  177.           if ((epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE)
  178.           {
  179.             (void)PCD_WriteEmptyTxFifo(hpcd, epnum);
  180.           }
  181.         }
  182.         epnum++;
  183.         ep_intr >>= 1U;
  184.       }
  185.     }

  186.     /* Handle Resume Interrupt */
  187.     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT))
  188.     {
  189.       /* Clear the Remote Wake-up Signaling */
  190.       USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;

  191.       if (hpcd->LPM_State == LPM_L1)
  192.       {
  193.         hpcd->LPM_State = LPM_L0;

  194. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  195.         hpcd->LPMCallback(hpcd, PCD_LPM_L0_ACTIVE);
  196. #else
  197.         HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L0_ACTIVE);
  198. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  199.       }
  200.       else
  201.       {
  202. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  203.         hpcd->ResumeCallback(hpcd);
  204. #else
  205.         HAL_PCD_ResumeCallback(hpcd);
  206. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  207.       }

  208.       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT);
  209.     }

  210.     /* Handle Suspend Interrupt */
  211.     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP))
  212.     {
  213.       if ((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS)
  214.       {
  215. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  216.         hpcd->SuspendCallback(hpcd);
  217. #else
  218.         HAL_PCD_SuspendCallback(hpcd);
  219. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  220.       }
  221.       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP);
  222.     }

  223.     /* Handle LPM Interrupt */
  224.     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT))
  225.     {
  226.       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT);

  227.       if (hpcd->LPM_State == LPM_L0)
  228.       {
  229.         hpcd->LPM_State = LPM_L1;
  230.         hpcd->BESL = (hpcd->Instance->GLPMCFG & USB_OTG_GLPMCFG_BESL) >> 2U;

  231. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  232.         hpcd->LPMCallback(hpcd, PCD_LPM_L1_ACTIVE);
  233. #else
  234.         HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L1_ACTIVE);
  235. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  236.       }
  237.       else
  238.       {
  239. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  240.         hpcd->SuspendCallback(hpcd);
  241. #else
  242.         HAL_PCD_SuspendCallback(hpcd);
  243. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  244.       }
  245.     }

  246.     /* Handle Reset Interrupt */
  247.     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBRST))
  248.     {
  249.       USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
  250.       (void)USB_FlushTxFifo(hpcd->Instance, 0x10U);

  251.       for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
  252.       {
  253.         USBx_INEP(i)->DIEPINT = 0xFB7FU;
  254.         USBx_INEP(i)->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL;
  255.         USBx_OUTEP(i)->DOEPINT = 0xFB7FU;
  256.         USBx_OUTEP(i)->DOEPCTL &= ~USB_OTG_DOEPCTL_STALL;
  257.         USBx_OUTEP(i)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK;
  258.       }
  259.       USBx_DEVICE->DAINTMSK |= 0x10001U;

  260.       if (hpcd->Init.use_dedicated_ep1 != 0U)
  261.       {
  262.         USBx_DEVICE->DOUTEP1MSK |= USB_OTG_DOEPMSK_STUPM |
  263.                                    USB_OTG_DOEPMSK_XFRCM |
  264.                                    USB_OTG_DOEPMSK_EPDM;

  265.         USBx_DEVICE->DINEP1MSK |= USB_OTG_DIEPMSK_TOM |
  266.                                   USB_OTG_DIEPMSK_XFRCM |
  267.                                   USB_OTG_DIEPMSK_EPDM;
  268.                                
  269.        

  270.       }
  271.       else
  272.       {
  273.         USBx_DEVICE->DOEPMSK |= USB_OTG_DOEPMSK_STUPM |
  274.                                 USB_OTG_DOEPMSK_XFRCM |
  275.                                 USB_OTG_DOEPMSK_EPDM |
  276.                                 USB_OTG_DOEPMSK_OTEPSPRM |
  277.                                 USB_OTG_DOEPMSK_NAKM;

  278.         USBx_DEVICE->DIEPMSK |= USB_OTG_DIEPMSK_TOM |
  279.                                 USB_OTG_DIEPMSK_XFRCM |
  280.                                 USB_OTG_DIEPMSK_EPDM;
  281.       }

  282.       /* Set Default Address to 0 */
  283.       USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD;

  284.       /* setup EP0 to receive SETUP packets */
  285.       (void)USB_EP0_OutStart(hpcd->Instance, (uint8_t *)hpcd->Setup);

  286.       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBRST);
  287.     }

  288.     /* Handle Enumeration done Interrupt */
  289.     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE))
  290.     {
  291.       (void)USB_ActivateSetup(hpcd->Instance);
  292.       hpcd->Init.speed = USB_GetDevSpeed(hpcd->Instance);

  293.       /* Set USB Turnaround time */
  294.       (void)USB_SetTurnaroundTime(hpcd->Instance,
  295.                                   HAL_RCC_GetHCLKFreq(),
  296.                                   (uint8_t)hpcd->Init.speed);

  297. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  298.       hpcd->ResetCallback(hpcd);
  299. #else
  300.       HAL_PCD_ResetCallback(hpcd);
  301. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */

  302.       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE);
  303.     }

  304.     /* Handle SOF Interrupt */
  305.     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SOF))
  306.     {
  307. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  308.       hpcd->SOFCallback(hpcd);
  309. #else
  310.       HAL_PCD_SOFCallback(hpcd);
  311. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */

  312.       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SOF);
  313.     }

  314.     /* Handle Global OUT NAK effective Interrupt */
  315.     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_BOUTNAKEFF))
  316.     {
  317.       USBx->GINTMSK &= ~USB_OTG_GINTMSK_GONAKEFFM;

  318.       for (epnum = 1U; epnum < hpcd->Init.dev_endpoints; epnum++)
  319.       {
  320.         if (hpcd->OUT_ep[epnum].is_iso_incomplete == 1U)
  321.         {
  322.           /* Abort current transaction and disable the EP */
  323.           (void)HAL_PCD_EP_Abort(hpcd, (uint8_t)epnum);
  324.         }
  325.       }
  326.     }

  327.     /* Handle Incomplete ISO IN Interrupt */
  328.     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR))
  329.     {
  330.       for (epnum = 1U; epnum < hpcd->Init.dev_endpoints; epnum++)
  331.       {
  332.         RegVal = USBx_INEP(epnum)->DIEPCTL;

  333.         if ((hpcd->IN_ep[epnum].type == EP_TYPE_ISOC) &&
  334.             ((RegVal & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA))
  335.         {
  336.           hpcd->IN_ep[epnum].is_iso_incomplete = 1U;

  337.           /* Abort current transaction and disable the EP */
  338.           (void)HAL_PCD_EP_Abort(hpcd, (uint8_t)(epnum | 0x80U));
  339.         }
  340.       }

  341.       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR);
  342.     }

  343.     /* Handle Incomplete ISO OUT Interrupt */
  344.     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
  345.     {
  346.       for (epnum = 1U; epnum < hpcd->Init.dev_endpoints; epnum++)
  347.       {
  348.         RegVal = USBx_OUTEP(epnum)->DOEPCTL;

  349.         if ((hpcd->OUT_ep[epnum].type == EP_TYPE_ISOC) &&
  350.             ((RegVal & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA) &&
  351.             ((RegVal & (0x1U << 16)) == (hpcd->FrameNumber & 0x1U)))
  352.         {
  353.           hpcd->OUT_ep[epnum].is_iso_incomplete = 1U;

  354.           USBx->GINTMSK |= USB_OTG_GINTMSK_GONAKEFFM;

  355.           if ((USBx->GINTSTS & USB_OTG_GINTSTS_BOUTNAKEFF) == 0U)
  356.           {
  357.             USBx_DEVICE->DCTL |= USB_OTG_DCTL_SGONAK;
  358.             break;
  359.           }
  360.         }
  361.       }

  362.       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
  363.     }

  364.     /* Handle Connection event Interrupt */
  365.     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT))
  366.     {
  367. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  368.       hpcd->ConnectCallback(hpcd);
  369. #else
  370.       HAL_PCD_ConnectCallback(hpcd);
  371. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */

  372.       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT);
  373.     }

  374.     /* Handle Disconnection event Interrupt */
  375.     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OTGINT))
  376.     {
  377.       RegVal = hpcd->Instance->GOTGINT;

  378.       if ((RegVal & USB_OTG_GOTGINT_SEDET) == USB_OTG_GOTGINT_SEDET)
  379.       {
  380. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  381.         hpcd->DisconnectCallback(hpcd);
  382. #else
  383.         HAL_PCD_DisconnectCallback(hpcd);
  384. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  385.       }
  386.       hpcd->Instance->GOTGINT |= RegVal;
  387.     }
  388.   }
  389. }
  390. #endif /* defined (USB_OTG_FS) */
复制代码
我不知道该怎么接收数据,用bus hound也发不出数据来。
还有一点,圈圈的书上写着要用端点1输出。
hpcd_USB_OTG_FS.Init.use_dedicated_ep1 = DISABLE;
这个把端点一禁止了。可是我一使能它,设备就不识别。
高手支招,谢谢!

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-4-18 06:38

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表