RT-Thread 学习笔记(十) --- 开启基于LWIP协议的网络功能

软件环境:Win7,Keil MDK 4.72a, IAR EWARM 7.2, GCC 4.2,Python 2.7 ,SCons 2.3.2

硬件环境:Armfly STM32F103ZE-EK v3.0开发板

参考文章:RT-Thread编程指南

RT-Thread_1.2.0+lwip+rtgui0.8.0 移植心得

【1】修改配置文件rtconfig.h

定位到112行,开启LWIP编译选项并加入RT_USING_LWIP141,我们要使用的LwIP版本是v1.4.1修改如下:

/* SECTION: lwip, a lighwight TCP/IP protocol stack */
#define RT_USING_LWIP 

#define RT_USING_LWIP141
... ...
/* the number of simulatenously active TCP connections*/
#define RT_LWIP_TCP_PCB_NUM 5
/* Using DHCP */
/* #define RT_LWIP_DHCP */

/* ip address of target*/
#define RT_LWIP_IPADDR0 192
#define RT_LWIP_IPADDR1 168
#define RT_LWIP_IPADDR2 1
#define RT_LWIP_IPADDR3 133

/* gateway address of target*/
#define RT_LWIP_GWADDR0 192
#define RT_LWIP_GWADDR1 168
#define RT_LWIP_GWADDR2 1
#define RT_LWIP_GWADDR3 1
... ...

开发板网卡地址,网关地址,开发主机地址在一个网段内即可。

【2】注释掉drivers组的rt_spi_device.c文件不使用的头文件

将drivers目录下dma9000.c文件加入工程的drivers组中,然后打开drivers组的rt_spi_device.c文件,定位到第5行,将#include "stm32_eth.h"注释掉,修改如下:

#ifdef RT_USING_LWIP
//#include "stm32_eth.h"
#endif /* RT_USING_LWIP */

修改完成后保存,并在命令行中使用scons命令编译,应能够编译通过。

【3】修改DM9000A芯片和MCU之间硬件接口

(1) FSMC配置

开发板原理图DM9000A硬件接口电路如下图:

RT-Thread 学习笔记(十) --- 开启基于LWIP协议的网络功能_第1张图片


STM32F103参考手册2009年12月中文版第327页给出如下说明:

RT-Thread 学习笔记(十) --- 开启基于LWIP协议的网络功能_第2张图片

 DM9000地址计算方法:

A,正如上图所示,对于16位宽度的外部存储器,stm32f103的FSMC将在内部使用HADDR[25:1]产生外部存储器的地址FSMC_A[24:0],而HADDR[0]未接;

B,DM9000的CS引脚决定它的起始地址,STM32的CPU仅引出了4个片选信号,也就是CPU硬件最多只能外接4个总线型设备。安富莱开发板(V3)具有5个FSMC外设,所以开发板外扩一个地址译码器电路,如下图:

RT-Thread 学习笔记(十) --- 开启基于LWIP协议的网络功能_第3张图片RT-Thread 学习笔记(十) --- 开启基于LWIP协议的网络功能_第4张图片

将NE4空间分为4部分,第1份给LCD,第2份给LAN,即当FSMC_A19=1、FSMC_NE4=0时选通DM9000。STM32的NE4的起始地址是0x6c000000,FSMC_A19对应于HADDR[20],所以安富莱开发板(V3)的DM9000的网卡起始地址为0x6c100000;

C,DM9000的基地址计算是由TXD[3:0]和SA4~9组成,安富莱开发板(V3)上这几位都为0;

D,DM9000的CMD引脚决定传送的是地址还是数据,安富莱开发板(V3)上连接的是FSMC_A[2]即HADDR[3],所以安富莱开发板(V3)的IO_ADDR = 0x6c100000,IO_DATA = 0x6c100008。

(1)打开drivers目录下的DM9000a.c,定位到646行开始,逐项检查,可原理图对照。数据线[D15:0]容易检查,关键看地址线,按下图原理图所示,

RT-Thread 学习笔记(十) --- 开启基于LWIP协议的网络功能_第5张图片

定位到680行附近,在FSMC_A16 ~ FSMC_A18定义的代码块下面,加入如FSMC_A19 ~ FSMC_A22的定义,代码如下:

        /* FSMC_A16 ~ FSMC_A18  PD11 ~ PD13 */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13;
        GPIO_Init(GPIOD,&GPIO_InitStructure);

        /* FSMC_A19 ~ FSMC_A22  PE3~PE6 */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;
        GPIO_Init(GPIOE,&GPIO_InitStructure);
下面的替换虽然不是必须的,但看起来规范些, 找到 FSMC_Configuration()开始的位置, 定位到633行附近,和709行附近,修改如下:

static void FSMC_Configuration()
{
FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
FSMC_NORSRAMTimingInitTypeDef FSMC_NORSRAMTimingInitStructure;

... ...

/*-- FSMC Configuration ------------------------------------------------------*/
/*----------------------- SRAM Bank 4 ----------------------------------------*/
/* FSMC_Bank1_NORSRAM4 configuration */
FSMC_NORSRAMTimingInitStructure
.FSMC_AddressSetupTime = 0;
FSMC_NORSRAMTimingInitStructure.FSMC_AddressHoldTime = 0;
FSMC_NORSRAMTimingInitStructure.FSMC_DataSetupTime = 2;
FSMC_NORSRAMTimingInitStructure.FSMC_BusTurnAroundDuration = 0;
FSMC_NORSRAMTimingInitStructure.FSMC_CLKDivision = 0;
FSMC_NORSRAMTimingInitStructure.FSMC_DataLatency = 0;
FSMC_NORSRAMTimingInitStructure.FSMC_AccessMode = FSMC_AccessMode_A;

... ...

FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &FSMC_NORSRAMTimingInitStructure;
FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &FSMC_NORSRAMTimingInitStructure;

(2)中断线配置

A,原理图中给出的中断线接口是PA1,而DM9000中配置的中断线是PE4,需要改过来,我们先定位到文件的597行,GPIO_Configuration()函数开头部分,

static void GPIO_Configuration()
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;

/* configure PE5 as eth RST */
//GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
//GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//GPIO_Init(GPIOE,&GPIO_InitStructure);
//GPIO_SetBits(GPIOE,GPIO_Pin_5);

//RST_1();

/* configure PA1 as external interrupt */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//IO内部上拉
GPIO_Init(GPIOA, &GPIO_InitStructure);

/* Connect DM9000 EXTI Line to GPIOE Pin 1 */
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);

/* Configure DM9000 EXTI Line to generate an interrupt on falling edge */
EXTI_InitStructure.EXTI_Line = EXTI_Line1;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);

/* Clear DM9000A EXTI line pending bit */
EXTI_ClearITPendingBit(EXTI_Line1);
}

B,然后再定位到585行附近,配置NVIC,改成EXTI1,代码修改如下:

static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;

/* Enable the EXTI1 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}

【4】修改DM9000a.h文件中定义的基地址

<1>根据原理图中给出的IO地址和Data地址,打开DM9000a.h,定位到18行,修改如下:
#define DM9000_IO_BASE 0x6C100000
#define DM9000_DATA_BASE 0x6C100008

#define DM9000_IO (*((volatile rt_uint16_t *) 0x6C100000)) // CMD = 0
#define DM9000_DATA (*((volatile rt_uint16_t *) 0x6C100008)) // CMD = 1

修改完后保存。

<2>打开DM9000a.c,定位到742行附近,加入条件编译,代码修改如下:

#ifdef RT_USING_LWIP
int rt_hw_dm9000_init(void)
{

... ...

return 0;
}
INIT_DEVICE_EXPORT(rt_hw_dm9000_init);
#endif /* RT_USING_LWIP */

... ...

修改完成后保存。

【5】修改中断接口文件

打开drivers目录下的stm32f10x_it.c,定位到130行附近,修改如下:

#ifdef RT_USING_LWIP
/*******************************************************************************
* Function Name : EXTI1_IRQHandler
* Description : This function handles External lines 9 to 5 interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void EXTI1_IRQHandler(void)
{
extern void rt_dm9000_isr(void);

/* enter interrupt */
rt_interrupt_enter();

/* Clear the DM9000A EXTI line pending bit */
EXTI_ClearITPendingBit(EXTI_Line1);

rt_dm9000_isr();

/* leave interrupt */
rt_interrupt_leave();
}
#endif /* RT_USING_LWIP */

修改完成后保存。

【6】编译测试

编译,下载,在终端显示如下:

\ | /
- RT - Thread Operating System
/ | \ 1.2.2 build Apr 2 2015
2006 - 2013 Copyright by rt-thread team
found part[0], begin: 219152384, size: 1.690GB
dm9000 id: 0x90000a46
finsh />operating at 100M full duplex mode
lwIP-1.4.1 initialized!

W25Q64BV or W25Q64CV detection
flash0 mount to /.
sd0 mount to /dev.

finsh />

然后再命令终端里ping 开发板地址 192.168.1.133,结果如下:

RT-Thread 学习笔记(十) --- 开启基于LWIP协议的网络功能_第6张图片

可以看到,已经可以正常ping通。



你可能感兴趣的:(RT-Thread 学习笔记(十) --- 开启基于LWIP协议的网络功能)