rtthread 以太网 (LAN8720A)

查询以太网配置过程

文件路径: /drivers/board.h

/*-------------------------- ETH CONFIG BEGIN --------------------------*/

/** if you want to use eth you can use the following instructions.
 *
 * STEP 1, define macro related to the eth
 *                 such as    BSP_USING_ETH
 *
 * STEP 2, copy your eth init function from stm32xxxx_hal_msp.c generated by stm32cubemx to the end if board.c file
 *                 such as     void HAL_ETH_MspInit(ETH_HandleTypeDef* heth)
 *
 * STEP 3, modify your stm32xxxx_hal_config.h file to support eth peripherals. define macro related to the peripherals
 *                 such as     #define HAL_ETH_MODULE_ENABLED
 *
 * STEP 4, config your phy type
 *                 such as     #define PHY_USING_LAN8720A
 *                             #define PHY_USING_DM9161CEP
 *                             #define PHY_USING_DP83848C
 * STEP 5, implement your phy reset function in the end of board.c file
 *                 void phy_reset(void)
 *
 * STEP 6, config your lwip or other network stack
 *
 */

注释中详细描述了以太网配置过程,

  1. 使能rtt以太网驱动
    打开 /drivers/board.h 启用BSP_USING_ETH宏定义,根据芯片启用相应的phy,我的是lan8720,这启用PHY_USING_LAN8720A宏定义。

  2. 初始化RMII接口硬件
    通过 stm32cubemx工具使能RMII硬件,在一下路径
    \Core\Src\stm32f7xx_hal_msp.c中将HAL_ETH_MspInit拷贝到 /drivers/board.c中

    并根据硬件添加phy复位函数phy_reset

    
    
    void HAL_ETH_MspInit(ETH_HandleTypeDef* ethHandle)
    {
      GPIO_InitTypeDef GPIO_InitStruct = {0};
      if(ethHandle->Instance==ETH)
      {
        /* ETH clock enable */
        __HAL_RCC_ETH_CLK_ENABLE();
    
        __HAL_RCC_GPIOC_CLK_ENABLE();
        __HAL_RCC_GPIOA_CLK_ENABLE();
        __HAL_RCC_GPIOB_CLK_ENABLE();
        /**ETH GPIO Configuration
        PC1     ------> ETH_MDC
        PA1     ------> ETH_REF_CLK
        PA2     ------> ETH_MDIO
        PA7     ------> ETH_CRS_DV
        PC4     ------> ETH_RXD0
        PC5     ------> ETH_RXD1
        PB11     ------> ETH_TX_EN
        PB12     ------> ETH_TXD0
        PB13     ------> ETH_TXD1
        */
        GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
        GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    
        GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_7;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
        GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
        GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
        GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    
      }
    }
    #define RESET_IO GET_PIN(D, 0)
    void phy_reset(void)
    {
       rt_pin_mode(RESET_IO, PIN_MODE_OUTPUT);
       rt_pin_write(RESET_IO, PIN_HIGH);
       rt_thread_mdelay(50);
       rt_pin_write(RESET_IO, PIN_LOW);
       rt_thread_mdelay(50);
       rt_pin_write(RESET_IO, PIN_HIGH);
    }
    
  3. 打开相应的HAL库
    打开 /drivers/ stm32f7xx_hal_conf.h
    使能 #define HAL_ETH_MODULE_ENABLED

  4. 添加lwip协议栈
    打开 RT-Thread Settings->选择lwip

    使能rtt lwip协议栈
    打开 RT-Thread Settings-->跟多配置
    |组件
    |---->RT-Thrad组件
    |		|---->网络
    |			|---->轻量级TCP/IP协议栈		
    |				|---->使能LWIP堆栈			√
    
  5. 验证

    msh />list_device
    device           type         ref count
    -------- -------------------- ----------
    W25Q256  Block Device         1
    qspi10   SPI Device           0
    spi40    SPI Device           0
    e0       Network Interface    0
    
    msh />ping 192.168.1.100
    60 bytes from 192.168.1.100 icmp_seq=0 ttl=64 time=1 ms
    60 bytes from 192.168.1.100 icmp_seq=1 ttl=64 time=0 ms
    60 bytes from 192.168.1.100 icmp_seq=2 ttl=64 time=1 ms
    60 bytes from 192.168.1.100 icmp_seq=3 ttl=64 time=1 ms
    

添加网络接口设备

打开 RT-Thread Settings->选择lwip

使能rtt lwip协议栈
打开 RT-Thread Settings-->跟多配置
|组件
|---->RT-Thrad组件
|		|---->网络
|			|---->网络接口设备	
|				|---->使能网络接口设备		√

添加套接字抽象层

打开 RT-Thread Settings->选择lwip

使能rtt lwip协议栈
打开 RT-Thread Settings-->跟多配置
|组件
|---->RT-Thrad组件
|		|---->网络
|			|---->套接字抽象层	
|				|---->使能套接字抽象层		√

测试代码

#include 
#include 
#include 

#include 
#include 

#include 
#include 

#include 
#include 
#include 

/* RT-Thread 官网,支持 TLS 功能 */
//#define SAL_TLS_HOST    "www.rt-thread.org"
//#define SAL_TLS_PORT    443
#define SAL_TLS_HOST    "192.168.1.100"
#define SAL_TLS_PORT    8088
#define SAL_TLS_BUFSZ   1024



static const char *send_data = "GET /download/rt-thread.txt HTTP/1.1\r\n"
    "Host: www.rt-thread.org\r\n"
    "User-Agent: rtthread/4.0.1 rtt\r\n\r\n";

void sal_tls_test(void)
{
    int ret, i;
    char *recv_data;
    struct hostent *host;
    int sock = -1, bytes_received;
    struct sockaddr_in server_addr;

    /* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */
    host = gethostbyname(SAL_TLS_HOST);

    recv_data = rt_calloc(1, SAL_TLS_BUFSZ);
    if (recv_data == RT_NULL)
    {
        rt_kprintf("No memory\n");
        return;
    }

    /* 创建一个socket,类型是SOCKET_STREAM,TCP 协议, TLS 类型 */
//    if ((sock = socket(AF_INET, SOCK_STREAM, PROTOCOL_TLS)) < 0)
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        rt_kprintf("Socket error\n");
        goto __exit;
    }

    /* 初始化预连接的服务端地址 */
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SAL_TLS_PORT);
    server_addr.sin_addr = *((struct in_addr *)host->h_addr);
    rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));

    if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0)
    {
        rt_kprintf("Connect fail!\n");
        goto __exit;
    }

    /* 发送数据到 socket 连接 */
    ret = send(sock, send_data, strlen(send_data), 0);
    if (ret <= 0)
    {
        rt_kprintf("send error,close the socket.\n");
        goto __exit;
    }

    /* 接收并打印响应的数据,使用加密数据传输 */
    bytes_received = recv(sock, recv_data, SAL_TLS_BUFSZ  - 1, 0);
    if (bytes_received <= 0)
    {
        rt_kprintf("received error,close the socket.\n");
        goto __exit;
    }

    rt_kprintf("recv data:\n");
    for (i = 0; i < bytes_received; i++)
    {
        rt_kprintf("%c", recv_data[i]);
    }

__exit:
    if (recv_data)
        rt_free(recv_data);

    if (sock >= 0)
        closesocket(sock);
}

#ifdef FINSH_USING_MSH
#include 
MSH_CMD_EXPORT(sal_tls_test, SAL TLS function test);
#endif /* FINSH_USING_MSH */

服务器侧操作:

设置服务器pc IP地址位 192.168.1.100
打开网络调试助手,选择tcpserver,监听端口填写8088,打开端口

验证:
串口调试助手

msh />sal_tls_test

服务器

[2020-11-25 11:06:32.407]# RECV ASCII FROM 192.168.1.101 :49153>
GET /download/rt-thread.txt HTTP/1.1
Host: www.rt-thread.org
User-Agent: rtthread/4.0.1 rtt

串口调试助手

recv data:
http://www.cmsoft.cn

你可能感兴趣的:(rtthread,网络通信,物联网)