硬汉嵌入式论坛

 找回密码
 立即注册
查看: 3219|回复: 3
收起左侧

[STM32CubeF4] 移植stm32F107问题

[复制链接]
回帖奖励 35 个金币 回复本帖可获得 5 个金币奖励! 每人限 3 次

11

主题

8

回帖

41

积分

新手上路

积分
41
发表于 2019-5-20 23:03:15 | 显示全部楼层 |阅读模式
本帖最后由 几迟 于 2019-5-20 23:35 编辑

硬汉哥,将F429的RL-TCPnet代码移植到stm32F107,上需要修改那些,以太网芯片DP83848CV,用的HAL库
  1. //这是f107上修改了一部分代码
  2. /*
  3. *********************************************************************************************************
  4. *
  5. *        模块名称 : STM32F4XX的MAC驱动
  6. *        文件名称 : ETH_STM32F4XX.C
  7. *        版    本 : V2.0
  8. *        说    明 : 由官方的驱动修改而来。
  9. *              1. 原始驱动支持DP83848C 和ST802RT1,修改为仅支持DM9161/9162,方便驱动的规范化。
  10. *              2. 增加PHY的中断触发功能,主要用于检测网线的连接状态。
  11. *              3. 变量g_ucEthLinkStatus用于表示连接状态。
  12. *                        
  13. *        修改记录 :
  14. *                版本号    日期         作者            说明
  15. *       V1.0    2015-12-22    Eric2013         首发
  16. *       V2.0    2017-04-17    Eric2013         整理,并使其规范化
  17. *
  18. *        Copyright (C), 2015-2020, 安富莱电子 www.armfly.com
  19. *
  20. *********************************************************************************************************
  21. */
  22. #include "stdio.h"
  23. #include <stm32f1xx.h>
  24. #include <Net_Config.h>
  25. #include "stm32f107xc.h"
  26. #include "ETH_STM32F1xx.h"

  27. /*
  28. *********************************************************************************************************
  29. *                                  STM32-107vc的是RMII接口,PHY芯片是DM8232                           
  30. *********************************************************************************************************
  31. */

  32. /*
  33.         PA1/ETH_RMII_RX_CLK
  34.         PA2/ETH_MDIO
  35.         PA7/RMII_CRS_DV
  36.         PC1/ETH_MDC
  37.         PC4/ETH_RMII_RX_D0
  38.         PC5/ETH_RMII_RX_D1
  39.         PG11/ETH_RMII_TX_EN
  40.         PG13/FSMC_A24/ETH_RMII_TXD0
  41.         PB13/ETH_RMII_TXD1
  42.         PH6/MII_INT ----- 中断引脚,这里将其用于网线断开或者连接的状态触发
  43. */


  44. /*
  45. *********************************************************************************************************
  46. *                                          用于本文件的调试
  47. *********************************************************************************************************
  48. */
  49. #if 1
  50.         #define printf_eth printf
  51. #else
  52.         #define printf_eth(...)
  53. #endif


  54. /*
  55. *********************************************************************************************************
  56. *                                             宏定义
  57. *********************************************************************************************************
  58. */
  59. /*
  60.   默认情况下,我们选择是自动识别,即使用PHY芯片支持的Auto-Negotiation实现自适应10Mbps网络或者100Mbps网络
  61.   但是这种时间稍长,如果用户确定了使用的网络是10Mbps还是100Mbps,直接通过下面的宏定义选择即可,如果使用的
  62.   自适应,两个都不需要选择。
  63. */
  64. //#define  _10MBIT_
  65. //#define  _100MBIT_


  66. /*
  67. *********************************************************************************************************
  68. *                                             变量
  69. *********************************************************************************************************
  70. */
  71. __IO uint8_t  g_ucEthLinkStatus = 0;  /* 以太网连接状态,0 表示未连接,1 表示连接 */

  72. extern U8 own_hw_adr[];  /* 在文件Net_Config.c里面定义 */

  73. static U8 TxBufIndex;
  74. static U8 RxBufIndex;

  75. static RX_Desc Rx_Desc[NUM_RX_BUF];  /* DMA接收描述符 */
  76. static TX_Desc Tx_Desc[NUM_TX_BUF];  /* DMA发送描述符 */

  77. static U32 rx_buf[NUM_RX_BUF][ETH_BUF_SIZE>>2]; /* DMA接收描述符缓冲 */
  78. static U32 tx_buf[NUM_TX_BUF][ETH_BUF_SIZE>>2]; /* DMA发送描述符缓冲 */


  79. /*
  80. *********************************************************************************************************
  81. *                                             变量
  82. *********************************************************************************************************
  83. */
  84. /*
  85.   底层驱动有两种方式,一种是查询的,一种是中断的,我们这里是采用的中断方式。
  86.   a. 查询方式需要的函数: - void init_ethernet ()
  87.                          - void send_frame (OS_FRAME *frame)
  88.                          - void poll_ethernet (void)
  89.   b. 中断方式需要的函数: - void init_ethernet ()
  90.                          - void send_frame (OS_FRAME *frame)
  91.                          - void int_enable_eth ()
  92.                          - void int_disable_eth ()
  93.                          - interrupt function
  94. */

  95. static void rx_descr_init (void);
  96. static void tx_descr_init (void);
  97. static void write_PHY (U32 PhyReg, U16 Value);
  98. static U16  read_PHY (U32 PhyReg);
  99. static void Eth_Link_EXTIConfig(void);


  100. /*
  101.   默认情况下,我们选择是自动识别,即使用PHY芯片支持的Auto-Negotiation实现自适应10Mbps网络或者100Mbps网络
  102.   但是这种时间稍长,如果用户确定了使用的网络是10Mbps还是100Mbps,直接通过下面的宏定义选择即可,如果使用的
  103.   自适应,两个都不需要选择。
  104. */
  105. //#define  _10MBIT_
  106. //#define  _100MBIT_

  107. /*
  108. *********************************************************************************************************
  109. *        函 数 名: init_ethernet
  110. *        功能说明: 初始化以太网RMII方式引脚,驱动PHY,配置MAC及其DMA方式。
  111. *        形    参: 无
  112. *        返 回 值: 无
  113. *********************************************************************************************************
  114. */

  115. void init_ethernet (void)
  116. {
  117.         U32 regv,tout,conn;

  118.         /* 关闭PHY中断触发引脚 */
  119.          HAL_NVIC_DisableIRQ(ETH_IRQn);

  120.         /* 使能系统配置控制器时钟 */
  121.          __HAL_RCC_ETH_CLK_ENABLE();

  122.         /* 复位以太网MAC */
  123.         RCC->AHBRSTR |= (1 << 14);

  124.         /* 选择RMII接口,必须在 MAC 处于复位状态且在使能 MAC 时钟之前完成此配置 */
  125.         AFIO->MAPR |=  (1 << 23);

  126.         /* 停止复位以太网MAC */
  127.           RCC->AHBRSTR &= ~(1 << 14);
  128.         
  129.            /**ETH GPIO Configuration   
  130.     PC1     ------> ETH_MDC
  131.     PA1     ------> ETH_REF_CLK
  132.     PA2     ------> ETH_MDIO
  133.     PB11     ------> ETH_TX_EN
  134.     PB12     ------> ETH_TXD0
  135.     PB13     ------> ETH_TXD1
  136.     PD8     ------> ETH_CRS_DV
  137.     PD9     ------> ETH_RXD0
  138.     PD10     ------> ETH_RXD1
  139.     */
  140.     GPIO_InitTypeDef GPIO_InitStruct;
  141.           GPIO_InitStruct.Pin = GPIO_PIN_1;
  142.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  143.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  144.     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  145.     GPIO_InitStruct.Pin = GPIO_PIN_1;
  146.     GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  147.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  148.     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  149.     GPIO_InitStruct.Pin = GPIO_PIN_2;
  150.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  151.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  152.     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  153.     GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13;
  154.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  155.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  156.     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  157.     GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10;
  158.     GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  159.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  160.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

  161.     __HAL_AFIO_REMAP_ETH_ENABLE();

  162.         /*
  163.           寄存器ETH->DMABMR的SR位置1后,MAC DMA控制器会复位所有MAC子系统的内部寄存器和逻辑。在所有内
  164.           核时钟域完成复位操作后,该位自动清零。重新编程任何内核寄存器之前,在该位中读取0 值。
  165.         */
  166.         ETH->DMABMR  |= DBMR_SR;
  167.         while (ETH->DMABMR & DBMR_SR);
  168.         conn = 0;

  169.         /*
  170.            HCLK的时钟是72MHz,这里选项CR位为72,CR占用寄存器ETH->MACMIIAR的bit4,bit3和bit2。
  171.            CR 时钟范围选项可确定 HCLK 频率并用于决定 MDC 时钟频率:
  172.             选项     HCLK        MDC 时钟
  173.             000     60~72 MHz     HCLK/42
  174.                   001            保留                                   HCLK/62
  175.                    010    20-35MHz      HCLK/16
  176.                   011    35-60MHz      HCLK/26
  177.                   101、110、111 保留
  178.     */
  179.         ETH->MACMIIAR = 0x00000000;

  180.         /*
  181.           注意事项:DM9161可以上电后就读取其ID寄存器,但是DM9162不行,需要延迟一段时间这里为了方便起见,
  182.           直接将其复位,发送复位指令可以立即执行。
  183.         */

  184.         /* 发送复位命令 */
  185.         write_PHY (PHY_REG_BMCR, 0x8000);

  186.         /* 等待复位完成 */
  187.         for (tout = 0; tout < 0x10000; tout++)
  188.         {
  189.                 regv = read_PHY (PHY_REG_BMCR);
  190.                 if (!(regv & 0x8800))
  191.                 {
  192.                         /* 复位完成 */
  193.                         break;
  194.                 }
  195.         }

  196.         /* 第2步:配置DP83843 ***********************************************************/
  197. #if defined (_10MBIT_)
  198.         write_PHY (PHY_REG_BMCR, PHY_FULLD_10M);  /* 连接到10Mbps的网络 */
  199. #elif defined (_100MBIT_)
  200.         write_PHY (PHY_REG_BMCR, PHY_FULLD_100M); /* 连接到100Mbps的网络 */
  201. #else
  202.         /* 通过Auto-Negotiation实现自适应10Mbps网络或者100Mbps网络 */
  203.         write_PHY (PHY_REG_BMCR, PHY_AUTO_NEG);
  204.         
  205.         /* 等待完成Auto-Negotiation */
  206.         for (tout = 0; tout < 0x100000; tout++)
  207.         {
  208.                 regv = read_PHY (PHY_REG_BMSR);
  209.                 if (regv & 0x0020)
  210.                 {
  211.                         /* 完成Auto-Negotiation */
  212.                         break;
  213.                 }
  214.         }
  215. #endif
  216.         
  217.         /* 第3步:检测连接状态 ***********************************************************/
  218.         for (tout = 0; tout < 0x10000; tout++)
  219.         {
  220.                 regv = read_PHY (PHY_REG_BMSR);
  221.                 if (regv & (1 << 2))
  222.                 {
  223.                         /* PHY已经连接上网络 */
  224.                         g_ucEthLinkStatus = 1;
  225.                         
  226.                         /* 获取连接信息 */
  227.                         regv = read_PHY (PHY_REG_DSCSR);
  228.                         
  229.                         if ((regv & (1 << 15))|(regv & (1 << 13)))
  230.                         {
  231.                                 /* 全双工 */
  232.                                 printf_eth("5. Full-duplex connection\r\n");
  233.                                 conn |= PHY_CON_SET_FULLD;
  234.                         }
  235.                         
  236.                         if ((regv & (1 << 15))|(regv & (1 << 14)))
  237.                         {
  238.                                 /* 速度100Mbps的网络 */
  239.                                 conn |= PHY_CON_SET_100M;
  240.                         }
  241.                         break;
  242.                 }
  243.                 else
  244.                 {
  245.                         /* 未连接上 */
  246.                         g_ucEthLinkStatus = 0;
  247.                 }
  248.         }

  249.         /* 第4步:使能DP83843中断 ***********************************************************/
  250.         /* 使能DP83843的连接中断 */
  251.         write_PHY (PHY_REG_INTERRUPT, 1<<12);

  252.         /* 配置引脚PA0来接收中断信号 */
  253.         Eth_Link_EXTIConfig();

  254.         /* 第5步:使能DP83843中断 ***********************************************************/        
  255.         /*
  256.            初始化MAC配置寄存器
  257.            (1)当该位MCR_ROD置1时,MAC禁止在半双工模式下接收帧。
  258.            (2)当该位MCR_ROD清0时,MAC接收PHY发送的所有数据包。
  259.            (3)如果MAC在全双工模式下工作,该位不适用。
  260.         */
  261.         ETH->MACCR  = MCR_ROD;

  262.         /* 设置MAC工作在全双工模式 */
  263.         if (conn & PHY_CON_SET_FULLD)
  264.         {
  265.                 /* 使能全双工 */
  266.                 ETH->MACCR |= MCR_DM;
  267.         }

  268.         /*
  269.                 通过位MCR_FES配置MAC通信速度
  270.                 (1)0表示10Mbps
  271.                 (2)1表示100Mbps
  272.         */
  273.         if (conn & PHY_CON_SET_100M)
  274.         {
  275.                 /* 配置为100Mbps */
  276.                 ETH->MACCR |= MCR_FES;
  277.         }

  278.         /* MACFFR 以太网帧过滤寄存器,配置可接收所有MAC组播包,即MAC地址第一个字节的bit0 = 1 */
  279.         ETH->MACFFR = MFFR_HPF | MFFR_PAM;
  280.         
  281.         /* MACFCR 以太网流控制寄存器,ZQPD零时间片暂停禁止 */
  282.         ETH->MACFCR = MFCR_ZQPD;

  283.         /* 设置以太网MAC地址寄存器 */
  284.         ETH->MACA0HR = ((U32)own_hw_adr[5] <<  8) | (U32)own_hw_adr[4];
  285.         ETH->MACA0LR = ((U32)own_hw_adr[3] << 24) | (U32)own_hw_adr[2] << 16 |
  286.                                    ((U32)own_hw_adr[1] <<  8) | (U32)own_hw_adr[0];

  287.         /* 初始化DMA发送和接收描述符 */
  288.         rx_descr_init ();
  289.         tx_descr_init ();

  290.         /*
  291.             刷新FIFO,启动DMA发送和接收功能
  292.                 DMAOMR 工作模式寄存器
  293.                 位20 DOMR_FTF:刷新发送 FIFO (Flush transmit FIFO):
  294.                                该位置1时,发送FIFO控制器逻辑会复位为默认值,因此,TX FIFO中的所有数据均会
  295.                                    丢失/刷新。刷新操作结束时该位在内部清零。此位清零之前不得对工作模式寄存器执
  296.                                    行写操作。
  297.                 位13 DOMR_ST:启动/停止发送 (Start/stop transmission)
  298.                               该位置1时,启动发送,DMA会检查当前位置的发送列表来查找待发送的帧。
  299.                 位1  DOMR_SR:启动/停止接收 (Start/stop receive)
  300.                               该位置1时,启动接收,DMA尝试从接收列表中获取描述符并处理传入帧。
  301.         */
  302.         ETH->DMAOMR = DOMR_FTF | DOMR_ST | DOMR_SR;

  303.         /* 使能发送和接收 */
  304.         ETH->MACCR |= MCR_TE | MCR_RE;

  305.         /* 复位所有MAC中断 */
  306.         ETH->DMASR  = 0xFFFFFFFF;

  307.         /*  
  308.             使能发送和接收中断
  309.                 DMAIER 中断使能寄存器
  310.                 位16 NISE:使能所有正常中断(Normal interrupt summary enable)
  311.                 位15 AISE:使能所有异常中断(Abnormal interrupt summary enable)
  312.                 位7 RBUIE:接收缓冲区不可用中断使能(Receive buffer unavailable interrupt enable)
  313.                            当该位和AISE位都置1后,可使能接收缓冲区不可用中断。该位清零时,会禁止接
  314.                                    收缓冲区不可用中断。
  315.                 位6   RIE:接收中断使能 (Receive interrupt enable)
  316.                            当该位和AISE都置1后,可使能接收中断。该位清零时,会禁止接收中断。
  317.         */
  318.         ETH->DMAIER = ETH_DMAIER_NISE | ETH_DMAIER_AISE | ETH_DMAIER_RBUIE | ETH_DMAIER_RIE;

  319.         /* 设置为最高优先级,仅调用NVIC->ISER设置的默认优先级也是最高优先级0 */
  320.         NVIC_SetPriority(ETH_IRQn, 0);
  321.         
  322. }

  323. /*
  324. *********************************************************************************************************
  325. *        函 数 名: int_enable_eth
  326. *        功能说明: 使能以太网中断
  327. *        形    参: 无
  328. *        返 回 值: 无
  329. *********************************************************************************************************
  330. */
  331. void int_enable_eth (void)
  332. {
  333.         NVIC->ISER[1] = 1 << 29;
  334. }

  335. /*
  336. *********************************************************************************************************
  337. *        函 数 名: int_disable_eth
  338. *        功能说明: 使能以太网中断
  339. *        形    参: 无
  340. *        返 回 值: 无
  341. *********************************************************************************************************
  342. */
  343. void int_disable_eth (void)
  344. {
  345.         NVIC->ICER[1] = 1 << 29;
  346. }

  347. /*
  348. *********************************************************************************************************
  349. *        函 数 名: send_frame
  350. *        功能说明: 传递数据帧给MAC DMA发送描述符,并使能发送。
  351. *        形    参: 无
  352. *        返 回 值: 无
  353. *********************************************************************************************************
  354. */
  355. void send_frame (OS_FRAME *frame)
  356. {
  357.         U32 *sp,*dp;
  358.         U32 i,j;

  359.         j = TxBufIndex;
  360.         
  361.         /* 等待上一帧数据发送完成 */
  362.         while (Tx_Desc[j].CtrlStat & DMA_TX_OWN);

  363.         sp = (U32 *)&frame->data[0];
  364.         dp = (U32 *)(Tx_Desc[j].Addr & ~3);

  365.         /* 复制要发送的数据到DMA发送描述符中 */
  366.         for (i = (frame->length + 3) >> 2; i; i--)
  367.         {
  368.                 *dp++ = *sp++;
  369.         }
  370.         
  371.         /* 设置数据帧大小 */
  372.         Tx_Desc[j].Size      = frame->length;
  373.         
  374.         /* 发送描述符由DMA控制发送 */
  375.         Tx_Desc[j].CtrlStat |= DMA_TX_OWN;
  376.         
  377.         if (++j == NUM_TX_BUF) j = 0;
  378.         TxBufIndex = j;
  379.         
  380.         /* 开始帧传输 */
  381.         /*
  382.            DMASR 以太网 DMA 状态寄存器
  383.            向ETH_DMASR寄存器[16:0]中的(未保留)位写入1会将其清零,写入 0 则不起作用。
  384.            位1 TPSS:发送过程停止状态 (Transmit process stopped status)
  385.                  当发送停止时,此位置 1。
  386.         */
  387.         ETH->DMASR   = DSR_TPSS;
  388.         
  389.         /*
  390.            DMATPDR 以太网DMA发送轮询请求寄存器
  391.        应用程序使用此寄存器来指示DMA轮询发送描述符列表。
  392.        位 31:0 TPD:发送轮询请求(Transmit poll demand)
  393.                     向这些位写入任何值时,DMA都会读取ETH_DMACHTDR寄存器指向的当前描述符。如果
  394.                     该描述符不可用(由CPU所有),则发送会返回到挂起状态,并将ETH_DMASR寄存器位2
  395.                     进行置位。如果该描述符可用,则发送会继续进行。           
  396.         */
  397.         ETH->DMATPDR = 0;
  398. }

  399. /*
  400. *********************************************************************************************************
  401. *        函 数 名: ETH_IRQHandler
  402. *        功能说明: 以太网中断,主要处理从MAC DMA接收描述符接收到的数据帧以及错误标志的处理。
  403. *        形    参: 无
  404. *        返 回 值: 无
  405. *********************************************************************************************************
  406. */
  407. void ETH_IRQHandler (void)
  408. {
  409.         OS_FRAME *frame;
  410.         U32 i, RxLen;
  411.         U32 *sp,*dp;

  412.         i = RxBufIndex;
  413.         
  414.         /* 循环所有接受描述符列表,遇到未接收到数据的退出循环 */
  415.         do
  416.         {
  417.                 /*
  418.                         #define DMA_RX_ERROR_MASK   (DMA_RX_ES | DMA_RX_LE | DMA_RX_RWT | \
  419.                                                                          DMA_RX_RE | DMA_RX_CE)
  420.                         
  421.                         有错误,放弃此帧数据,错误类型包含如下:
  422.                         位15 DMA_RX_ES:错误汇总(Error summary),即CRC错误,接收错误,看门狗超时,延迟冲突等。
  423.                     位12 DMA_RX_LE:长度错误(Length error)
  424.                                     该位置1时,指示接收帧的实际长度与长度/类型字段的值不符。该字段仅在帧类
  425.                                     型位(RDES0[5])复位后有效。
  426.                         位4 DMA_RX_RWT:接收看门狗超时 (Receive watchdog timeout)
  427.                                     该位置1时,表示接收看门狗计时器在接收当前帧时超时,且当前帧在看门狗超
  428.                                     时后被截断了
  429.                         位3 DMA_RX_RE: 接收错误 (Receive error)
  430.                             该位置1时,表示在帧接收期间,当发出RX_DV信号时,会发出RX_ERR信号。
  431.                         位1 DMA_RX_CE: CRC 错误(CRC error)
  432.                             该位置1时,表示接收的帧发生循环冗余校验(CRC)错误。只有最后一个描述符
  433.                                     (RDES0[8])置1时,该字段才有效
  434.                 */
  435.                 if (Rx_Desc[i].Stat & DMA_RX_ERROR_MASK)
  436.                 {
  437.                         goto rel;
  438.                 }
  439.                
  440.                 /*
  441.                         #define DMA_RX_SEG_MASK   (DMA_RX_FS | DMA_RX_LS)
  442.                     位9 FS:第一个描述符 (First descriptor)
  443.                     该位置1时,指示此描述符包含帧的第一个缓冲区。如果第一个缓冲区的大小为0,则第二
  444.                     个缓冲区将包含帧的帧头。如果第二个缓冲区的大小为0,则下一个描述符将包含帧的帧头。
  445.                
  446.                     位8 LS:最后一个描述符 (Last descriptor)
  447.                     该位置1时,指示此描述符指向的缓冲区为帧的最后一个缓冲区。
  448.                
  449.                     下面的函数用于判断此帧数据是否只有一个缓冲,初始化接收描述符列表的时候,每个描述符仅设置了
  450.                     一个缓冲。
  451.                 */
  452.                 if ((Rx_Desc[i].Stat & DMA_RX_SEG_MASK) != DMA_RX_SEG_MASK)
  453.                 {
  454.                         goto rel;
  455.                 }
  456.                
  457.                 RxLen = ((Rx_Desc[i].Stat >> 16) & 0x3FFF) - 4;
  458.                 if (RxLen > ETH_MTU)
  459.                 {
  460.                         /* 数据包太大,直接放弃 */
  461.                         goto rel;
  462.                 }
  463.                
  464.                 /* 申请动态内存,RxLen或上0x80000000表示动态内存不足了不会调用函数sys_error() */
  465.                 frame = alloc_mem (RxLen | 0x80000000);
  466.                
  467.                 /* 如果动态内存申请失败了,放弃此帧数据;成功了,通过函数put_in_queue存入队列中 */
  468.                 if (frame != NULL)
  469.                 {
  470.                         sp = (U32 *)(Rx_Desc[i].Addr & ~3);
  471.                         dp = (U32 *)&frame->data[0];
  472.                         for (RxLen = (RxLen + 3) >> 2; RxLen; RxLen--)
  473.                         {
  474.                                 *dp++ = *sp++;
  475.                         }
  476.                         put_in_queue (frame);
  477.                 }
  478.                
  479.                 /* 设置此接收描述符继续接收新的数据 */
  480.                 rel: Rx_Desc[i].Stat = DMA_RX_OWN;

  481.                 if (++i == NUM_RX_BUF) i = 0;
  482.         }
  483.         while (!(Rx_Desc[i].Stat & DMA_RX_OWN));
  484.         
  485.         RxBufIndex = i;

  486.         /*
  487.            DMASR DMA的状态寄存器(DMA status register)
  488.            位7 RBUS:接收缓冲区不可用状态 (Receive buffer unavailable status)
  489.                  此位指示接收列表中的下一个描述符由CPU所拥有,DMA无法获取。接收过程进入挂起状态。
  490.                      要恢复处理接收描述符,CPU应更改描述符的拥有关系,然后发出接收轮询请求命令。如果
  491.                      未发出接收轮询请求命令,则当接收到下一个识别的传入帧时,接收过程会恢复。仅当上一
  492.                      接收描述符由DMA所拥有时,才能将ETH_DMASR[7]置1。
  493.         
  494.            DMAIER的接收缓冲区不可用中断RBUIE是bit7,对于的接收缓冲区不可用状态在DMA状态寄存器中也是bit7。
  495.         */
  496.         if (ETH->DMASR & INT_RBUIE)
  497.         {
  498.                 /* 接收缓冲区不可用,重新恢复DMA传输 */
  499.                 ETH->DMASR = ETH_DMASR_RBUS;
  500.                 ETH->DMARPDR = 0;
  501.         }
  502.         
  503.         /*
  504.            DMASR DMA的状态寄存器(DMA status register)
  505.            这里实现清除中断挂起标志
  506.            位16 ETH_DMASR_NIS:所有正常中断 (Normal interrupt summary)
  507.            位15 ETH_DMASR_AIS:所有异常中断 (Abnormal interrupt summary)
  508.            位6  ETH_DMASR_RS :接收状态 (Receive status)
  509.                                此位指示帧接收已完成,具体的帧状态信息已经包含在描述符中,接收仍保持运行状态。
  510.         */
  511.         ETH->DMASR = ETH_DMASR_NIS | ETH_DMASR_AIS | ETH_DMASR_RS;
  512. }

  513. /*
  514. *********************************************************************************************************
  515. *        函 数 名: rx_descr_init
  516. *        功能说明: MAC DMA接收描述符初始化。
  517. *        形    参: 无
  518. *        返 回 值: 无
  519. *********************************************************************************************************
  520. */
  521. static void rx_descr_init (void)
  522. {
  523.         U32 i,next;

  524.         /*
  525.            1. RDES0:接收描述符字0,对应Rx_Desc[i].Stat
  526.               位31 OWN:所有关系位 (Own bit)
  527.                                         该位置1时,指示描述符由MAC子系统的DMA所拥有。
  528.                         该位清零时,指示描述符由主机所拥有,即CPU。
  529.                         DMA在帧接收完成或此描述符的关联缓冲区已满时将该位清零。
  530.         
  531.            2. RDES1:接收描述符字1,对应Rx_Desc[i].Ctrl
  532.               位14   RCH: 链接的第二个地址 (Second address chained)
  533.                                            该位置1时,表示描述符中的第二个地址是下一个描述符地址,而非第二个缓冲区地址。该
  534.                        位置1时,RBS2(RDES1[28:16])为无关值。RDES1[15]比RDES1[14]优先处理。
  535.               位12:0 RBS1:接收缓冲区1大小 (Receive buffer 1 size)
  536.                        第一个数据缓冲区的大小以字节为单位。即使RDES2(缓冲区1地址指针)的值未对齐,缓
  537.                            冲区大小也必须为4、8或16的倍数,具体取决于总线宽度32、64或128。如果缓冲区大小不
  538.                            是4、8或16的倍数,这种情况的结果是未定义。如果该字段为0,则DMA会忽略该缓冲区并
  539.                            使用缓冲区2或下一个描述符,具体取决于RCH(位14)的值。
  540.         
  541.            3. RDES2:接收描述符字2,对应Rx_Desc[i].Addr
  542.               位31:0 RBAP1/RTSL:接收缓冲区1地址指针/接收帧时间戳低位
  543.                                      Receive buffer 1 address pointer
  544.                              Receive frame time stamp low
  545.         
  546.            4. RDES3:接收描述符字3,对应Rx_Desc[i].Next
  547.               位31:0 RBAP2/RTSH:接收缓冲区2地址指针(下一个描述符地址)/ 接收帧时间戳高位
  548.                                      Receive buffer 2 address pointer (next descriptor address)
  549.                                      Receive frame time stamp high
  550.         */
  551.         RxBufIndex = 0;
  552.         
  553.         for (i = 0, next = 0; i < NUM_RX_BUF; i++)
  554.         {
  555.                 if (++next == NUM_RX_BUF) next = 0;
  556.                 Rx_Desc[i].Stat = DMA_RX_OWN;
  557.                 Rx_Desc[i].Ctrl = DMA_RX_RCH | ETH_BUF_SIZE;
  558.                 Rx_Desc[i].Addr = (U32)&rx_buf[i];
  559.                 Rx_Desc[i].Next = (U32)&Rx_Desc[next];
  560.         }
  561.         
  562.         /* 接收描述符列表地址寄存器指向接收描述符列表的起始处 */
  563.         ETH->DMARDLAR = (U32)&Rx_Desc[0];
  564. }

  565. /*
  566. *********************************************************************************************************
  567. *        函 数 名: tx_descr_init
  568. *        功能说明: MAC DMA发送描述符初始化
  569. *        形    参: 无
  570. *        返 回 值: 无
  571. *********************************************************************************************************
  572. */
  573. static void tx_descr_init (void)
  574. {
  575.         U32 i,next;

  576.         /*
  577.            1. TDES0:发送描述符字0,对应Tx_Desc[i].CtrlStat
  578.               位29 LS :末段 (Last segment)
  579.                     该位置1时,指示缓冲区中包含帧的末段。
  580.               位28 FS :首段 (First segment)
  581.                     该位置1时,指示缓冲区中包含帧的首段
  582.           位20 TCH:链接的第二个地址 (Second address chained)
  583.                     该位置1时,表示描述符中的第二个地址是下一个描述符地址,而非第二个缓冲区地址。
  584.                     TDES0[20]置1时,TBS2(TDES1[28:16])为无关值。TDES0[21]比TDES0[20]优先处理。
  585.         
  586.            2. TDES1:发送描述符字1,对应Tx_Desc[i].Size
  587.         
  588.            3. TDES2:发送描述符字2,对应Tx_Desc[i].Addr
  589.               位31:0 TBAP1:发送缓冲区1地址指针/发送帧时间戳低位
  590.                             Transmit buffer 1 address pointer / Transmitframe time stamp low
  591.         
  592.            4. TDES3:发送描述符字3,对应Tx_Desc[i].Next
  593.               位 1:0 TBAP2:发送缓冲区2地址指针(下一个描述符地址)/ 发送帧时间戳高位
  594.                                  Transmit buffer 2 address pointer (Next descriptor address)
  595.                                                 Transmit frame time stamp high
  596.         */
  597.         TxBufIndex = 0;
  598.         for (i = 0, next = 0; i < NUM_TX_BUF; i++)
  599.         {
  600.                 if (++next == NUM_TX_BUF) next = 0;
  601.                 Tx_Desc[i].CtrlStat = DMA_TX_TCH | DMA_TX_LS | DMA_TX_FS;
  602.                 Tx_Desc[i].Addr     = (U32)&tx_buf[i];
  603.                 Tx_Desc[i].Next     = (U32)&Tx_Desc[next];
  604.         }
  605.         
  606.         /* 发送描述符列表地址寄存器指向发送描述符列表的起始处 */
  607.         ETH->DMATDLAR = (U32)&Tx_Desc[0];
  608. }


  609. /*
  610. *********************************************************************************************************
  611. *        函 数 名: write_PHY
  612. *        功能说明: 写数据到PHY寄存器
  613. *        形    参: PhyReg  PHY寄存器地址
  614. *             Value   写入的数据
  615. *        返 回 值: 无
  616. *********************************************************************************************************
  617. */
  618. static void write_PHY (U32 PhyReg, U16 Value)
  619. {
  620.         U32 tout;

  621.         /* 数据寄存器,存入要写入PHY的16位数据 */
  622.         ETH->MACMIIDR = Value;

  623.         /*
  624.            MACMIIAR 以太网MAC MII 地址寄存器
  625.        位 15:11 PA:PHY 地址 (PHY address),对应这里的PHY_DEF_ADDR
  626.                                         该字段指示正在访问32个可能的PHY器件中的哪一个。        
  627.            
  628.            位 10:6  MR:MII寄存器 (MII register),对应这里的PhyReg
  629.                                         这些位在所选的PHY器件中选择要访问的MII寄存器。
  630.            位 1     MW:MII写(MII write),对应这里的MMAR_MW
  631.                         此位置1是在告知PHY,将要启动一个使用MII数据寄存器的写操作。
  632.                         如果此位未置,则表示会启动一个读操作,将数据放入MII数据寄存器。
  633.            位 0     MB:MII忙碌 (MII busy),对应这里的MMAR_MB
  634.                         向ETH_MACMIIAR和ETH_MACMIIDR写入前,此位应读取逻辑0。向ETH_MACMIIAR写入过程中,此
  635.                         位也必须复位为0。在PHY寄存器访问过程中,此位由应用程序置1,指示读或写访问正在进行中。
  636.                         在对PHY进行写操作过程中,ETH_MACMIIDR(MII数据)应始终保持有效,直到MAC将此位清零。
  637.                         在对PHY进行读操作过程中,ETH_MACMIIDR始终无效,直到MAC将此位清零。在此位清零后,才
  638.                                         可以向ETH_MACMIIAR(MII地址)写入。
  639.         */
  640.         ETH->MACMIIAR = PHY_DEF_ADDR << 11 | PhyReg << 6 | MMAR_MW | MMAR_MB;

  641.         /* 等待操作完成,即等待MMAR_MB位被清零 */
  642.         tout = 0;
  643.         for (tout = 0; tout < MII_WR_TOUT; tout++)
  644.         {
  645.                 if ((ETH->MACMIIAR & MMAR_MB) == 0)
  646.                 {
  647.                         break;
  648.                 }
  649.         }
  650. }

  651. /*
  652. *********************************************************************************************************
  653. *        函 数 名: read_PHY
  654. *        功能说明: 从PHY芯片中读取寄存器数据
  655. *        形    参: PhyReg  寄存器地址
  656. *        返 回 值: 无
  657. *********************************************************************************************************
  658. */
  659. static U16 read_PHY (U32 PhyReg)
  660. {
  661.         U32 tout;

  662.         /*
  663.            MACMIIAR 以太网MAC MII 地址寄存器
  664.        位 15:11 PA:PHY 地址 (PHY address),对应这里的PHY_DEF_ADDR
  665.                                         该字段指示正在访问32个可能的PHY器件中的哪一个。        
  666.            
  667.            位 10:6  MR:MII寄存器 (MII register),对应这里的PhyReg
  668.                                         这些位在所选的PHY器件中选择要访问的MII寄存器。
  669.            位 1     MW:MII写(MII write),对应这里的MMAR_MW
  670.                         此位置1是在告知PHY,将要启动一个使用MII数据寄存器的写操作。
  671.                         如果此位未置,则表示会启动一个读操作,将数据放入MII数据寄存器。
  672.            位 0     MB:MII忙碌 (MII busy),对应这里的MMAR_MB
  673.                         向ETH_MACMIIAR和ETH_MACMIIDR写入前,此位应读取逻辑0。向ETH_MACMIIAR写入过程中,此
  674.                         位也必须复位为0。在PHY寄存器访问过程中,此位由应用程序置1,指示读或写访问正在进行中。
  675.                         在对PHY进行写操作过程中,ETH_MACMIIDR(MII数据)应始终保持有效,直到MAC将此位清零。
  676.                         在对PHY进行读操作过程中,ETH_MACMIIDR始终无效,直到MAC将此位清零。在此位清零后,才
  677.                                         可以向ETH_MACMIIAR(MII地址)写入。
  678.         */
  679.         ETH->MACMIIAR = PHY_DEF_ADDR << 11 | PhyReg << 6 | MMAR_MB;

  680.         /* 等待操作完成,即等待MMAR_MB位被清零 */
  681.         tout = 0;
  682.         for (tout = 0; tout < MII_RD_TOUT; tout++)
  683.         {
  684.                 if ((ETH->MACMIIAR & MMAR_MB) == 0)
  685.                 {
  686.                         break;
  687.                 }
  688.         }
  689.         
  690.         /* 从 PHY 中读取16bit的数据值 */
  691.         return (ETH->MACMIIDR & MMDR_MD);
  692. }

  693. /*
  694. *********************************************************************************************************
  695. *        函 数 名: Eth_Link_EXTIConfig
  696. *        功能说明: PHY的中断触发使用STM32的PA0引脚识别,此功能主要用于检测网线的连接状态判别。
  697. *        形    参: 无
  698. *        返 回 值: 无
  699. *********************************************************************************************************
  700. */
  701. static void Eth_Link_EXTIConfig(void)
  702. {
  703.         GPIO_InitTypeDef GPIO_InitStruct;
  704. //        EXTI_InitTypeDef EXTI_InitStructure;
  705. //        NVIC_InitTypeDef NVIC_InitStructure;

  706.         /* 使用PA0作为中断输入口, 下降沿表示中断信号 */

  707.          __HAL_RCC_GPIOA_CLK_ENABLE();
  708. __HAL_RCC_AFIO_IS_CLK_ENABLED();
  709.         
  710.         /* 配置中断引脚是输入PA0 */
  711.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
  712.         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  713.         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  714.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0
  715.         GPIO_Init(GPIOA, &GPIO_InitStructure);

  716. //    HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 0);
  717. //    HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);


  718. }

  719. /*
  720. *********************************************************************************************************
  721. *        函 数 名: EXTI9_5_IRQHandler
  722. *        功能说明: PA0引脚的中断处理
  723. *        形    参: 无
  724. *        返 回 值: 无
  725. *********************************************************************************************************
  726. */
  727. #define ETH_CONSTATUS
  728. #define ETH_CONNECT    "ETH_LINK Connect\r\n"
  729. #define ETH_DISCONNECT "ETH_LINK Disconnect\r\n"
  730. void EXTI9_5_IRQHandler(void)
  731. {
  732.         U32 regv, tout;
  733.         
  734.         if (EXTI_GetITStatus(EXTI_Line6) != RESET)
  735.         {
  736.                 /* 可以考虑在此处加入延迟,有时连接状态变了,但是寄存器没有及时更新*/
  737.                 regv = read_PHY(PHY_REG_INTERRUPT);
  738.                 if(regv & (1 << 2))
  739.                 {
  740.                         /* 重新插入后要多读几次,保证寄存器BMSR被更新 */
  741.                         for(tout = 0; tout < 10; tout++)
  742.                         {
  743.                                 regv = read_PHY (PHY_REG_BMSR);
  744.                                 if (regv & (1 << 2))
  745.                                 {
  746.                                         break;
  747.                                 }
  748.                         }

  749.                         /* 连接上网线 */
  750.                         if(regv & (1 << 2))
  751.                         {
  752.                                 #ifdef ETH_CONSTATUS
  753.                                         const char *pError = ETH_CONNECT;
  754.                                         uint8_t i;
  755.                                 #endif
  756.                                 
  757.                                 g_ucEthLinkStatus = 1;
  758.                                 
  759.                                 #ifdef ETH_CONSTATUS
  760.                                         for (i = 0; i < sizeof(ETH_CONNECT); i++)
  761.                                         {
  762.                                                 USART1->DR = pError[i];
  763.                                                 /* 等待发送结束 */
  764.                                                 while ((USART1->SR & USART_FLAG_TC) == (uint16_t)RESET);
  765.                                         }
  766.                                 #endif
  767.                         }
  768.                         /* 网线断开 */
  769.                         else
  770.                         {
  771.                                 #ifdef ETH_CONSTATUS
  772.                                         const char *pError = ETH_DISCONNECT;
  773.                                         uint8_t i;
  774.                                 #endif
  775.                                 
  776.                                 g_ucEthLinkStatus = 0;
  777.                                 
  778.                                 #ifdef ETH_CONSTATUS
  779.                                         for (i = 0; i < sizeof(ETH_DISCONNECT); i++)
  780.                                         {
  781.                                                 USART1->DR = pError[i];
  782.                                                 /* 等待发送结束 */
  783.                                                 while ((USART1->SR & USART_FLAG_TC) == (uint16_t)RESET);
  784.                                         }
  785.                                 #endif
  786.                                 
  787.                         }
  788.                         
  789.                 }
  790.                 /* 清中断挂起位 */
  791.                 EXTI_ClearITPendingBit(EXTI_Line6);
  792.         }
  793. }

  794. ///***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
复制代码


以太网硬件原理图

以太网硬件原理图
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106754
QQ
发表于 2019-5-21 00:05:31 | 显示全部楼层

回帖奖励 +5 个金币

MDK安装目录里面有F107的驱动。不过也是标准库的,仅需修改一小部分为HAL即可。
回复

使用道具 举报

1

主题

16

回帖

19

积分

新手上路

积分
19
发表于 2019-5-22 10:51:59 | 显示全部楼层

回帖奖励 +5 个金币

这个不用自己动手,通过MDK的RTE组件点几下就行了,昨天跑了一下7.X版本,感觉很爽,107这种64KB的RAM跑lwip资源占用感人,RL-TCPnet资源占用小,用起来也比较方便
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106754
QQ
发表于 2019-5-22 14:04:08 | 显示全部楼层

回帖奖励 +5 个金币

1328616904 发表于 2019-5-22 10:51
这个不用自己动手,通过MDK的RTE组件点几下就行了,昨天跑了一下7.X版本,感觉很爽,107这种64KB的RAM跑lwi ...

对,使用7.x用HAL方便些。
回复

使用道具 举报

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

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-4 11:03 , Processed in 0.250437 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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