/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels
*
*/
#ifndef __ARCH_CC_H__
#define __ARCH_CC_H__
/* Include some files for defining library routines */
#include /* printf, fflush, FILE */
#include
#include /* abort */
//#include
#if (!defined(__CC_ARM)) && (!defined(__ARMCC_VERSION)) && (!defined(__ICCARM__))
#include
#endif
#include "FreeRTOSConfig.h"
#ifndef BYTE_ORDER
#define BYTE_ORDER LITTLE_ENDIAN
#endif
#define LWIP_PLATFORM_BYTESWAP 0
/** @todo fix some warnings: don't use #pragma if compiling with cygwin gcc */
//#ifndef __GNUC__
#if (!defined(__ICCARM__)) && (!defined(__GNUC__)) && (!defined(__CC_ARM))
#include
#pragma warning (disable: 4244) /* disable conversion warning (implicit integer promotion!) */
#pragma warning (disable: 4127) /* conditional expression is constant */
#pragma warning (disable: 4996) /* 'strncpy' was declared deprecated */
#pragma warning (disable: 4103) /* structure packing changed by including file */
#endif
#define LWIP_PROVIDE_ERRNO
#if ( configUSE_POSIX_ERRNO == 1 )
extern int FreeRTOS_errno;
#ifndef errno
#define errno FreeRTOS_errno
#endif
#endif
/* Define generic types used in lwIP */
#define LWIP_NO_STDINT_H 1
typedef unsigned char u8_t;
typedef signed char s8_t;
typedef unsigned short u16_t;
typedef signed short s16_t;
typedef unsigned long u32_t;
typedef signed long s32_t;
typedef size_t mem_ptr_t;
typedef u32_t sys_prot_t;
/* Define (sn)printf formatters for these lwIP types */
#define X8_F "02x"
#define U16_F "hu"
#define S16_F "hd"
#define X16_F "hx"
#define U32_F "lu"
#define S32_F "ld"
#define X32_F "lx"
#define SZT_F U32_F
/* Compiler hints for packing structures */
#if defined(__ICCARM__)
#define PACK_STRUCT_STRUCT __packed
#else
#define PACK_STRUCT_STRUCT __attribute__( (packed) )
#endif
#if 0
#ifndef LWIP_DEBUG_USE_PRINTF
#define LWIP_LOGE(fmt,arg...) LOG_E(lwip, "[lwip]: "fmt,##arg)
#define LWIP_LOGW(fmt,arg...) LOG_W(lwip, "[lwip]: "fmt,##arg)
#define LWIP_LOGI(fmt,arg...) LOG_I(lwip ,"[lwip]: "fmt,##arg)
#endif
#endif
#ifdef LWIP_DEBUG_USE_PRINTF
/* Plaform specific diagnostic output */
#define LWIP_PLATFORM_DIAG(x) do { printf x; } while(0)
#else
#define LWIP_PLATFORM_DIAG(x) do { printf(x) ; } while(0)
#endif
#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d in %s\n", \
x, __LINE__, __FILE__); fflush(NULL); abort();} while(0)
//#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \
// printf(("Assertion \"%s\" failed at line %d in %s\n", message, __LINE__, __FILE__)); \
// handler;} } while(0)
/* C runtime functions redefined */
//#define snprintf _snprintf //2015-07-22 Cheng Liu @132663
u32_t dns_lookup_external_hosts_file(const char *name);
#define LWIP_RAND() ((u32_t)rand())
#endif /* __ARCH_CC_H__ */
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Simon Goldschmidt
*
*/
#ifndef LWIP_HDR_LWIPOPTS_H__
#define LWIP_HDR_LWIPOPTS_H__
/* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */
/* NO_SYS=1 无操作系统,0有操作系统,这里使用FreeRTOS */
#define NO_SYS 0
#define LWIP_TIMERS 1
#define SYS_LIGHTWEIGHT_PROT 1
#define LWIP_NETCONN 0
#define LWIP_SOCKET 0
#define SYS_LIGHTWEIGHT_PROT 0
#define LWIP_IPV6 0
#define IPV6_FRAG_COPYHEADER 0
#define LWIP_IPV6_DUP_DETECT_ATTEMPTS 0
/* Enable some protocols to test them */
#define LWIP_DHCP 0
#define LWIP_AUTOIP 0
#define LWIP_IGMP 1
#define LWIP_DNS 1
#define LWIP_ALTCP 1
/* Turn off checksum verification of fuzzed data */
#define CHECKSUM_CHECK_IP 0
#define CHECKSUM_CHECK_UDP 0
#define CHECKSUM_CHECK_TCP 0
#define CHECKSUM_CHECK_ICMP 0
#define CHECKSUM_CHECK_ICMP6 0
/* Minimal changes to opt.h required for tcp unit tests: */
#define MEM_SIZE 16000
#define TCP_SND_QUEUELEN 40
#define MEMP_NUM_TCP_SEG TCP_SND_QUEUELEN
#define TCP_OVERSIZE 1
#define TCP_SND_BUF (12 * TCP_MSS)
#define TCP_WND (10 * TCP_MSS)
#define LWIP_WND_SCALE 1
#define TCP_RCV_SCALE 2
#define PBUF_POOL_SIZE 400 /* pbuf tests need ~200KByte */
/* Minimal changes to opt.h required for etharp unit tests: */
#define ETHARP_SUPPORT_STATIC_ENTRIES 1
#define LWIP_NUM_NETIF_CLIENT_DATA 1
#define LWIP_SNMP 1
#define MIB2_STATS 1
#define LWIP_MDNS_RESPONDER 1
#endif /* LWIP_HDR_LWIPOPTS_H__ */
驱动参考MDK的例程进行修改,若采用的芯片与官方提供的一致,可直接使用,仅需更改物理地址即可;
MDK下的驱动路径如下图所示,在ETH文件夹内;
也可以使用MDK官方提供的模板,在MDK安装路径下可以找到。
修改后内容如下:
/******************************************************************************
* File Name : MX_Device.h
* Date : 06/06/2019 08:02:00
* Description : STM32Cube MX parameter definitions
* Note : This file is generated by STM32CubeMX (DO NOT EDIT!)
******************************************************************************/
#ifndef __MX_DEVICE_H
#define __MX_DEVICE_H
/*---------------------------- Clock Configuration ---------------------------*/
#define MX_LSI_VALUE 32000
#define MX_LSE_VALUE 32768
#define MX_HSI_VALUE 64000000
#define MX_HSE_VALUE 25000000
#define MX_EXTERNAL_CLOCK_VALUE 12288000
#define MX_PLLDSIFreq_Value 500000000
#define MX_SYSCLKFreq_VALUE 400000000
#define MX_HCLKFreq_Value 100000000
#define MX_CortexFreq_Value 400000000
#define MX_APB1Freq_Value 25000000
#define MX_APB2Freq_Value 25000000
#define MX_CECFreq_Value 32000
#define MX_RTCFreq_Value 32000
#define MX_USBFreq_Value 400000000
#define MX_WatchDogFreq_Value 32000
#define MX_DSIFreq_Value 96000000
#define MX_DSIPHYCLKFreq_Value 96000000
#define MX_DSITXEscFreq_Value 20000000
#define MX_SPDIFRXFreq_Value 400000000
#define MX_MCO1PinFreq_Value 64000000
#define MX_MCO2PinFreq_Value 400000000
/*-------------------------------- CORTEX_M7 --------------------------------*/
#define MX_CORTEX_M7 1
/* GPIO Configuration */
/*-------------------------------- SYS --------------------------------*/
#define MX_SYS 1
/* GPIO Configuration */
/*-------------------------------- NVIC --------------------------------*/
#define MX_NVIC 1
/*-------------------------------- GPIO --------------------------------*/
#define MX_GPIO 1
/* GPIO Configuration */
#endif /* __MX_DEVICE_H */
重新编译,发现缺少定义
DMARxDscrTab 以太网 Rx DMA描述符
DMATxDscrTab 以太网 Tx DMA描述符
Rx_Buff 以太网 接收缓存
6. 在EMAC_STM32H7XX.c文件头中,我们可以找到如下说明,我们可以根据该说明新建一个ETH_Configuration.c文件,并按照说明实现即可
Configuration tab
-----------------
1. Under Connectivity open \b ETH Configuration:
- GPIO Settings: review settings, no changes required
Pin Name | Signal on Pin | GPIO mode | GPIO Pull-up/Pull..| Maximum out | User Label
:--------|:--------------|:----------|:-------------------|:------------|:----------
PA1 | ETH_REF_CLK | Alternate | No pull-up and no..| High |.
PA2 | ETH_MDIO | Alternate | No pull-up and no..| High |.
PA7 | ETH_CRS_DV | Alternate | No pull-up and no..| High |.
PC1 | ETH_MDC | Alternate | No pull-up and no..| High |.
PC4 | ETH_RXD0 | Alternate | No pull-up and no..| High |.
PC5 | ETH_RXD1 | Alternate | No pull-up and no..| High |.
PG11 | ETH_TX_EN | Alternate | No pull-up and no..| High |.
PG13 | ETH_TXD0 | Alternate | No pull-up and no..| High |.
PG14 | ETH_TXD1 | Alternate | No pull-up and no..| High |.
- NVIC Settings: enable interrupts
Interrupt Table | Enable | Preemption Priority | Sub Priority
:------------------------------------|:-------|:--------------------|:------------
Ethernet global interrupt |\b ON | 0 | 0
- Parameter Settings: configure descriptor and RX buffer memory locations
General:Ethernet Configuration | Value
:------------------------------|:-------
Ethernet MAC Address | unused
Tx Descriptor Length | \b 4
First Tx Descriptor Address | \b 0x30040060
Rx Descriptor Length | \b 4
First Rx Descriptor Address | \b 0x30040000
Rx Buffers Address | \b 0x30040200
Rx Buffers Length | \b 1524
\n\note
Add "RxDecripSection", "TxDecripSection" and "RxArraySection" sections to the Scatter file if GNU Compiler or Arm Compiler 6 is used.\n
Example:
\code{.sct}
RW_ETH_RX_DESC 0x30040000 0x00000060 {
*(.RxDecripSection)
}
RW_ETH_TX_DESC 0x30040060 0x000001A0 {
*(.TxDecripSection)
}
RW_ETH_RX_BUF 0x30040200 0x00001800 {
*(.RxArraySection)
}
\endcode
\endnote
- User Constants: not used
Click \b OK to close the ETH Configuration dialog
2. Under System open \b CORTEX_M7 Configuration
- Parameter Settings: optionally enable cache and configure MPU
Cortex Interface Settings | Value
:----------------------------|:-------
CPU ICache | Enabled (optional)
CPU DCache Length | Enabled (optional)
Cortex MPU Control Settings | Value
:----------------------------|:-------
MPU Control Mode | Background Region Privileged accesses only
Cortex MPU Region 0 Settings | Value
:----------------------------|:-------
MPU Region | \b Enabled
MPU Region Base Address | \b 0x30040000
MPU Region Size | \b 256B
MPU SubRegion Disable | \b 0x0
MPU TEX field level | \b level 0
MPU Access Permission | \b ALL ACCESS PERMITTED
MPU Instruction Access | \b ENABLE
MPU Shareability Permission | \b ENABLE
MPU Cacheable Permission | \b DISABLE
MPU Bufferable Permission | \b ENABLE
*/
GPIO初始化;
NVIC中断配置;
以太网DMA接收/发送描述符的配置;
另外需要对MPU进行配置。
#include "includes.h"
/* Ethernet Rx DMA 描述符 */
__attribute__((at(0x30040000))) ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT];
/* Ethernet Tx DMA 描述符 */
__attribute__((at(0x30040060))) ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT];
/* Ethernet 接收缓冲 */
__attribute__((at(0x30040200))) uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_MAX_PACKET_SIZE];
ETH_HandleTypeDef heth;
/*
*********************************************************************************************************
* 函 数 名: HAL_ETH_MspInit
* 功能说明: 以太网初始化调用的底层回调,用于初始化IO,时钟和中断
* 形 参: ---
* 返 回 值: 无
*********************************************************************************************************
*/
void HAL_ETH_MspInit(ETH_HandleTypeDef* heth)
{
GPIO_InitTypeDef GPIO_InitStruct;
/*
PC1 ------> ETH_MDC
PA1 ------> ETH_REF_CLK
PA2 ------> ETH_MDIO
PA7 ------> ETH_CRS_DV
PC4 ------> ETH_RXD0
PC5 ------> ETH_RXD1
PB13 ------> ETH_TXD1
PG11 ------> ETH_TX_EN
PG13 ------> ETH_TXD0
*/
if(heth->Instance==ETH)
{
/* 使能外设时钟 */
__HAL_RCC_ETH1MAC_CLK_ENABLE();
__HAL_RCC_ETH1TX_CLK_ENABLE();
__HAL_RCC_ETH1RX_CLK_ENABLE();
/* 使能时钟 */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
/* 配置PA1, PA2 , PA7 */
GPIO_InitStruct.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL ;
GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* 配置PB13 */
GPIO_InitStruct.Pin = GPIO_PIN_13;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* 配置PC1, PC4和PC5 */
GPIO_InitStruct.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* 配置PG11, PG12和PG13 */
GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_13;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
/* 设置中断优先级 */
HAL_NVIC_SetPriority(ETH_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(ETH_IRQn);
}
}
/*
*********************************************************************************************************
* 函 数 名: ETH_IRQHandler
* 功能说明: 以太网回调函数
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void ETH_IRQHandler(void)
{
HAL_ETH_IRQHandler(&heth);
}
为了便于移植,这里直接使用MDK提供的ethernetif.c文件进行移植操作,文件路径如下;
同时还需要拷贝ethif_config.h文件,路径见下图
添加lwip相关头文件
创建以太网初始化函数,代码如下
void net_init(void)
{
struct ip4_addr ipaddr;
struct ip4_addr netmask;
struct ip4_addr gw;
/* 创建协议栈线程 */
tcpip_init(NULL, NULL);
#if LWIP_DHCP
ipaddr.addr = 0;
netmask.addr = 0;
gw.addr = 0;
#else
IP4_ADDR(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1 , NETMASK_ADDR2, NETMASK_ADDR3);
IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
#endif
/* 将网络接口添加到netif_list列表 */
netif_add(&netif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, ðernet_input);
/* 注册默认网络接口 */
netif_set_default(&netif);
netif_set_up(&netif);
#if LWIP_DHCP
dhcp_start (&netif);
#endif
}
void vTaskEthCheck(void *pvParameters)
{
/* 初始化网络 */
printf("开始初始化网络.....");
net_init();
printf("初始化网络完成");
while(1)
{
vTaskDelay(300);
}
//1.添加信号量定义
xSemaphoreHandle s_xSemaphore = NULL;
//2.在下面函数增加创建任务语句,如下
static void
low_level_init(struct netif *netif)
{
.....//省略
/* 创建接收处理任务 */
s_xSemaphore = xSemaphoreCreateBinary();
sys_thread_new("ethernetif_task",
ethernetif_task, /* 任务入口函数 */
NULL, /* 任务入口函数参数 */
TCPIP_THREAD_STACKSIZE, /* 任务栈大小 */
2); /* 任务的优先级 */
}
//修改void ethernetif_poll (struct netif *netif) 函数如下
void ethernetif_poll (struct netif *netif)
{
struct ethernetif *eth = netif->state;
while(1)
{
xSemaphoreTake(s_xSemaphore, portMAX_DELAY );
taskENTER_CRITICAL();
if (!eth->phy_ok || eth->link == ARM_ETH_LINK_DOWN)
{}
if ((eth->rx_event) || (!eth->event_rx_frame))
{
eth->rx_event = false;
/* process received ethernet packet */
ethernetif_input (netif);
}
taskEXIT_CRITICAL();
}
}
修改之后可以ping通