软件环境: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硬件接口电路如下图:
STM32F103参考手册2009年12月中文版第327页给出如下说明:
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外设,所以开发板外扩一个地址译码器电路,如下图:
将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]容易检查,关键看地址线,按下图原理图所示,
定位到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,结果如下:
可以看到,已经可以正常ping通。