主机环境:Windows 7 SP1
开发环境:MDK5.18
目标板:NUVOTON NUC472
之前领了一块新唐的NUC472开发板一直没有动,吃了很久的灰,后来接触了一下新唐的M451芯片,休闲之余把NUC472开发板拿出来研究了一哈,该开发板只有两个接口以太网接口和一个USB接口,当然所有引脚是都引出来的,如下图所示:
该开发板刚好可以用来研究一下网络的开发,之前一直在使用STM32的芯片搞开发,但苦于没有领到过带网络模块的STM32开发板,因此一直没动静。。。之前的STM32 USB开发板还是花了二十多块钱在网上淘的。
NUC472开发板例程中关于网络的开发示例有两种:uip和lwip,目前来看lwip是开发网络的最佳选择,资料很多,而uip几乎是小众选择了,但这两种协议栈的作者是同一个人--Adam Dunkels,感觉他是一个很牛叉的人,写过很多开源软件,uip目前好像停止单独更新了,uip项目合并到contiki项目中了,目前uip单独的最新版本是uip1.0,lwip目前更新记录是lwip2.0 RC2,之所以先选择uip来研究是因为它比较小源代码文件较少,方便入手,但后面肯定还是要学习lwip的,而且lwip2.0的稳定版还没放出来,等放出来后再研究吧。
uip-1.0源码目录很少,如下:
uip-1.0比uip-0.9多了一些文件,相比而言uip-0.9更简洁一些。apps目录包含了一些uip应用的示例,方便用于编辑代码时可以参考,其中包含了一些常用的示例如:webserver、webclient、telnetd、smtp等,doc目录包含了参考手册方便用户学习该源码,lib目录是比uip-0.9多出的一个目录,其为uip-1.0的内存管理模块,uip目录则是协议栈的核心文件,最后的unix则是一个示例程序,方便用户移植uip-1.0协议栈到所需要的平台。我们在NUC472平台上使用该协议栈,所需要做的工作就是重写unix目录下的文件
在uip-conf.h文件中我们选择引用apps目录下的哪个示例,默认使用的是webserver示例。tapdev文件则是跟硬件相关的以太网发送和接收数据的函数,uip协议栈只是处理以太网数据包,但具体的数据包来源以及处理完之后的数据包发送还是要交由具体硬件来实现的,也就是我们的以太网驱动的编写,clock-arch文件则是由具体的硬件提供一个时钟以便于uip检测时间,这些文件说明都可以在参考手册中找到,在初始学习uip协议栈时建议由简入难,因此,这里我实现的示例是helloworld示例,先看下tapdev模块的编写,tapdev模块只需要完成三个函数即可:tapdev_init()、tapdev_send()、tapdev_read(),在NUC472中实现这三个文件还是比较简单的,如下:
/*
* Copyright (c) 2001, 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. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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.
*
* Author: Adam Dunkels <adam@sics.se>
*
* $Id: tapdev.c,v 1.8 2006/06/07 08:39:58 adam Exp $
*/
#include "NUC472_442.h"
#include "uip.h"
#include "string.h"
extern struct uip_eth_addr ethaddr;
uint32_t volatile u32PktLen = 0;//接收到的数据包长度
/*---------------------------------------------------------------------------*/
/**
* @brief EMAC Tx interrupt handler.
* @param None
* @return None
*/
void EMAC_TX_IRQHandler(void)
{
// Clean up Tx resource occupied by previous sent packet(s)
EMAC_SendPktDone();
}
/**
* @brief EMAC Rx interrupt handler.
* @param None
* @return None
*/
void EMAC_RX_IRQHandler(void)
{
while(1)
{
// Get all recv data
if(EMAC_RecvPkt(uip_buf, (uint32_t *)&u32PktLen) == 0)
break;
// Clean up Rx resource occupied by previous received packet
EMAC_RecvPktDone();
}
}
void
tapdev_init(void)
{
// Select RMII interface by default
EMAC_Open(ethaddr.addr);
NVIC_EnableIRQ(EMAC_TX_IRQn);
NVIC_EnableIRQ(EMAC_RX_IR