基于DM9161的RL-TCPnet实现

来源:互联网 发布:24周胎儿发育标准数据 编辑:程序博客网 时间:2024/04/30 18:01

RL-ARM版本:4.22
以太网PHY:DM9161
处理器:STR912FAW4x
软件平台:裸奔
编译环境:MDK-ARM Professional Version: 4.23
目标:固定IP,ping通

如果Keil提供了处理器的MAC驱动,并且驱动与PHY匹配的话,那么RL-TCPnet的实现超简单。Keil提供了STR9的驱动,不过那是为STE100P写的,而我用的是DM9161,驱动不能直接用,因此费了一些脑筋。
RL-TCPnet可独立于RTX内核运行,为了降低调试难度,我采用了裸奔的方式。
1. 添加并修改Net_Config.c
从Keil\ARM\RL\TCPnet\Config复制Net_Config.c,并修改如下:

去掉不用的模块。UDP要选上,因为ping的ICMP包要用到。
2. 添加函数库
从\Keil\ARM\RV31\LIB复制TCP_ARM_L.lib,并添加到MDK。
3. 添加并修改驱动
从\Keil\ARM\RL\TCPnet\Drivers复制STR9_ENET.c和STR9_ENET.h。
对比STE100P和DM9161的手册,发现两个芯片的寄存器0~6内容基本相同(业内标准??),于是我将STE100P特有的寄存器定义去掉,只保留相同的内容(STR9_ENET.h文件):

/* PHY Registers */#define PHY_REG_XCR         0           /* XCVR Control Register             */#define PHY_REG_XSR         1           /* XCVR Status Register              */#define PHY_REG_PID1        2           /* PHY Identifier 1                  */#define PHY_REG_PID2        3           /* PHY Identifier 2                  */#define PHY_REG_ANA         4           /* Auto-Negotiation Advertisement    */#define PHY_REG_ANLPA       5           /* Auto-Neg. Link Partner Abitily    */#define PHY_REG_ANE         6           /* Auto-Neg. Expansion Register      *///#define PHY_REG_XCIIS       17          /* XCVR Config. and Interrupt Status *///#define PHY_REG_XIE         18          /* XCVR Interrupt Enable Register    *///#define PHY_REG_100CTR      19          /* 100Base-TX PHY Control/Status     *///#define PHY_REG_XMC         20          /* XCVE Mode Control Register        */


编译,提示PHY_REG_XCIIS未定义,代码在STR9_ENET.c的此处:

  regv = read_PHY (PHY_REG_XCIIS);  if (regv & 0x0100) {


这两行的作用是判断是否全双工,可以通过读取寄存器0来实现:

  regv = read_PHY (PHY_REG_XSR);  if (regv & 0x5000) {


根据DM9161的PHY ID和PHYAD[0~4]管脚的复位电平,将STR9_ENET.h这两行

#define STE100P_DEF_ADR     0x0000      /* Default PHY device address        */#define STE100P_ID          0x1C040010  /* PHY Identifier                    */


改为:

#define PHY_DEV_ADDR     1           /* PHY device address                */#define PHY_ID        0x0181B8A0  /* PHY Identifier                    */


同时修改STR9_ENET.c相关内容。
init_ethernet函数:

  if (((id1 << 16) | (id2 & 0xFFF0)) == PHY_ID) {


write_PHY函数:

  ENET_MAC->MIIA = (PHY_DEV_ADDR << 11) | (PhyReg << 6) | MIIA_WR | MIIA_BUSY;


read_PHY函数:

  ENET_MAC->MIIA = (PHY_DEV_ADDR << 11) | (PhyReg << 6) | MIIA_BUSY;


最后,由于带__irq关键字的中断函数在裸奔时无法正常运行,将STR9_ENET.c文件中的所有__irq关键字去掉。

顺便说一下,这个驱动采用的是中断方式。根据Keil的手册,RL-TCPnet的以太网驱动有两种方式:轮询方式和中断方式。这里我没有看到poll_ethernet函数,而init_ethernet函数配置了中断入口,因此是中断方式。
4. 编写main.c
代码如下:

#include <rtl.h>bool g_100mstimeout = FALSE;    //这个标志在100ms定时中断置为TRUEvoid timer_poll () {  if (g_100mstimeout) {    timer_tick (); // RL-TCPnet function    g_100mstimeout = FALSE;  }}int main (void) {  //此处初始化100ms定时器和外围时钟等  init_TcpNet ();  while (1) {    timer_poll ();    main_TcpNet ();  }}

 

5. 注意事项
(1)如果PHY的时钟信号使用独立晶振,不使用STR9的P5.2,那么需要修改STR9_ENET.c中init_ethernet函数的IO初始化代码,禁止P5.2输出。不这样做的话,P5.2高频率悬空,对板子的EMC性能有影响。
(2)采用2008版STR91x.s在裸奔的时候无法正常运行,我采用的是2006版的文件。
(3)裸奔的时候STR91x.s中的Setup Library Exception Handlers选项必须打开,否则中断函数不正常。
有意思的是,以上(2)(3)两点以及__irq关键字都是与使用RTX的情况相反。原因不清楚,暂时没有去研究。

6. 参考资料
http://download.csdn.net/detail/zoogar/4003823 -- DM9161手册
http://download.csdn.net/detail/zoogar/4003811 -- STE100P手册
http://download.csdn.net/detail/zoogar/3983092 -- RL-ARM User's Guide
http://download.csdn.net/detail/zoogar/3983085 -- Building Applications with RL-ARM - Getting Started
http://bbs.eeworld.com.cn/thread-192539-1-3.html -- 云*飞扬写的网络开发笔记
http://bbs.eeworld.com.cn/thread-285929-1-1.html -- shilaike写的Realtime库学习心得