nios2 ucos lwip enc28j60

环境:

quartus11.0sp1,NIOSII 11.0IDE sp1(win7)

fpga开发板采用的是黑金开发板cyclone四代

nios2 eds自带ucos v286

lwip1.4.1

硬件部分:

ucos基本tmer:1ms interrupt

enc28j60相关设置:

spi设置:(10Mhz)

nios2 ucos lwip enc28j60_第1张图片

gpio:

LAN_nINT

nios2 ucos lwip enc28j60_第2张图片

LAN_nCS :简单output

LAN_nRST:简单output

软件部分:

enc28j60驱动参照linux内核驱动移植修改,这部分改动较多不一一描述:

enc28j60的初始化并使能接口函数 

int enc28j60_net_open(void);//注意 开中断后调用此函数 不然有可能无法正常使用enc28j60

enc28j60中断处理函数

void enc28j60_irq_work_handler(void);// 注意 不要包含在中断函数中 需要退出中断后处理

enc28j60数据包发送函数

void enc28j60_packet_write(int len, const u8 *data);


spi驱动提供gpio驱动和spi驱动两种选择:

#define USE_SPICORE 1 // 1使用spicore , 0使用gpio

提供给enc28j60驱动调用函数:

int spi_write(unsigned char *buf, unsigned int len);
unsigned char spi_write_then_read(unsigned char *txbuf, int n_tx, unsigned char *rxbuf, int n_rx);


lwip移植参考焦海波移植手册,以及自带sys_arch.txt文档;

sys_arch.h:

/*
 * sys_arch.h
 *
 *  Created on: 2015-1-17
 *      Author: xw
 */
#ifndef SYS_ARCH_H_
#define SYS_ARCH_H_

/*********************************************************************************************************

*                                              UCOS-II Port

*

*                Target           : Anyprocessor

*                Put together by : Michael Anburaj

*                URL             : http://geocities.com/michaelanburaj/    Email : [email protected]

*

*********************************************************************************************************

*/
#include    "os_cpu.h"
#include    "os_cfg.h"
#ifndef OS_VERSION
#include "ucos_ii.h"
#endif /* OS_VERSION */
#include "system.h"
#define LWIP_MAX_TASKS OS_LOWEST_PRIO /* Number of LwIPtasks */
#define LWIP_START_PRIO 3          /* Defined the lowestLwIP task priority */
#ifndef LWIP_STACK_SIZE
#define LWIP_STACK_SIZE 2048
#endif /* LWIP_STACK_SIZE */
#define LWIP_COMPAT_MUTEX     1
/*#define LWIP_STACK_SIZE2048        Stack size for LwIP tasks */

/* Note:

   Task priorities, LWIP_START_PRIO through(LWIP_START_PRIO+LWIP_MAX_TASKS-1) must be reserved

   for LwIP and must not used by otherapplications outside. */

#define LWIP_Q_SIZE 10             /* LwIP queue size */

#define LWIP_MAX_QS 50             /* Max. LwIP queues */

#define SYS_MBOX_NULL   NULL

#define SYS_SEM_NULL    NULL

typedef struct {

    OS_EVENT*   pQ;
    OS_EVENT*   hMBox;
   void*       pvQEntries[LWIP_Q_SIZE];

} TQ_DESCR, *PQ_DESCR;
typedef OS_EVENT* sys_sem_t;

typedef PQ_DESCR sys_mbox_t;

typedef INT8U     sys_thread_t;

#define T_LWIP_THREAD_START_PRIO  7
#define T_LWIP_THREAD_MAX_NB   1
#define T_LWIP_THREAD_STKSIZE   512
#endif /* __SYS_ARCH__H__ */

根据sys_arch.txt中需要实现的函数
sys_arch.c:

/*
 * sys_arch.c
 *
 *  Created on: 2015-1-17
 *      Author: xw
 */
#include "arch/cc.h"
#include "arch/sys_arch.h"
#include "lwip/err.h"
#include "lwip/sys.h"
#include "ucos_ii.h"
OS_STK T_LWIP_THREAD_STK[T_LWIP_THREAD_MAX_NB][T_LWIP_THREAD_STKSIZE];

static TQ_DESCR __staLwIPMBoxs[LWIP_MAX_QS];
PQ_DESCR pstCurFreeMBox;
//struct sys_timeouts {
//struct sys_timeout *next;
//};
//static struct sys_timeouts __staSysTimeouts[T_LWIP_THREAD_MAX_NB + 1];

u32_t sys_now(void){

	return OSTime;
}
void sys_sem_signal(sys_sem_t *sem){
	OSSemPost((OS_EVENT*)sem);
}
int sys_sem_valid(sys_sem_t *sem){
	return (*sem != 0 ? 1 : 0);
	//return OSSemAccept((OS_EVENT*)sem);
}
void sys_sem_free(sys_sem_t *sem){
	INT8U res;
	OSSemDel((OS_EVENT*)sem , OS_DEL_ALWAYS, &res);
}
err_t sys_sem_new(sys_sem_t *sem, u8_t count){
	  *sem = OSSemCreate (count);
	  return *sem ? 0 : -1;
}
void sys_sem_set_invalid(sys_sem_t *sem){
	*sem = 0;
}
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout){
	INT8U res;
	OSSemPend((OS_EVENT*)sem, timeout, &res);
	return res;
}

int sys_mbox_valid(sys_mbox_t *mbox){
	return 0;
}
err_t sys_mbox_new(sys_mbox_t *mbox, int size){
	mbox =(sys_mbox_t *) OSMboxCreate(&size);
	return 0;
}
void sys_mbox_free(sys_mbox_t *mbox){
	INT8U res;
	OSMboxDel((OS_EVENT*)mbox, OS_DEL_ALWAYS, &res);
}
void sys_mbox_post(sys_mbox_t *mbox, void *msg){
	OSMboxPost((OS_EVENT*)mbox, msg);
}
err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg){
	INT8U res;
	res = OSMboxPost((OS_EVENT*)mbox, msg);
	return res;
}
u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout){
	INT8U res;
	msg = OSMboxPend((OS_EVENT*)mbox, timeout, &res);
	return res;
}
void sys_mbox_set_invalid(sys_mbox_t *mbox){
	*mbox = 0;
}
u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg){
	INT8U res;
	msg = OSMboxPend((OS_EVENT*)mbox, 1, &res);
	return res;
}
sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio){
	u8_t __ubPrio = 0;
	 //* 如果优先级定义没有超出系统允许的范围
	 if(prio > 0 && prio <= T_LWIP_THREAD_MAX_NB)
	{
	  __ubPrio = T_LWIP_THREAD_START_PRIO + (prio - 1);
	  if(OS_NO_ERR ==
	 OSTaskCreate(thread,
	arg,
	&T_LWIP_THREAD_STK[prio-1][T_LWIP_THREAD_STKSIZE-1],
	__ubPrio))
	return __ubPrio;
	}
	  return __ubPrio;
}
void sys_init(void){
	u8_t i;
	INT8U ucErr;
	 //* 先把数组清 0
	 //memset(__staLwIPMBoxs, 0, sizeof(__staLwIPMBoxs));
	OSMemCreate((void*)__staLwIPMBoxs, LWIP_MAX_QS, sizeof(TQ_DESCR), &ucErr);
	 //* 建立链表和邮箱
	 for(i=0; i<(LWIP_MAX_QS-1); i++)
	{
	  //* 把数组中的各成员链接在一起
	  __staLwIPMBoxs[i].pQ = &__staLwIPMBoxs[i+1];
	  //* 建立邮箱,系统必须保证邮箱能够顺利建立,如果出现错误,那是程序 BUG,
	  //* 应该在调试阶段排除
	  __staLwIPMBoxs[i].hMBox = OSQCreate(__staLwIPMBoxs[i].pvQEntries, LWIP_Q_SIZE);
	}
	 //* 别忘了数组中最后一个元素,它还没有建立邮箱呢
	 __staLwIPMBoxs[LWIP_MAX_QS-1].hMBox = OSQCreate(__staLwIPMBoxs[LWIP_MAX_QS-1].pvQEntries, LWIP_Q_SIZE);
	 //* 保存链表首地址
	 pstCurFreeMBox = __staLwIPMBoxs;
	 //* 初始化 sys_timeouts 数组,将每个数组成员保存的链表地址设置为 NULL
	 //for(i=0; i

perf.h

/*
 * perf.h
 *
 *  Created on: 2015-1-17
 *      Author: xw
 */

#ifndef PERF_H_
#define PERF_H_

#define PERF_START
#define PERF_STOP(x)

#endif /* PERF_H_ */

cc.h

/*
 * cc.h
 *
 *  Created on: 2015-1-17
 *      Author: xw
 */

#ifndef CC_H_
#define CC_H_
  /* FPAG-NIOS platform*/


#include"errno.h"        //定义错误编码

#include "alt_types.h"    //定义NIOS数据类型

//#include "lwipopts.h"     //

#define BYTE_ORDER LITTLE_ENDIAN          //字的高低位顺序

//数据长度

typedef alt_u8    u8_t;    //一个无符号字节类型,          8bits   0~~255

typedef alt_8    s8_t;    //一个有符号字节类型,         8 bits   -127~~-127

typedef alt_u16   u16_t;   //一个无符号字(=2个字节)类型,16 bits

typedef alt_16    s16_t;   //一个有符号字(=2个字节)类型,16 bits

typedef alt_u32   u32_t;   //一个无符号字节类型,          32 bits

typedef alt_32    s32_t;   //一个有符号字节类型,          32 bits

typedef u32_t mem_ptr_t;    //

#include 

/* Plaform specific diagnostic output   与平台相关的调试输出 */

#define LWIP_PLATFORM_DIAG(x) {printf x;}

#define LWIP_PLATFORM_ASSERT(x) {printf("Assertion\"%s\" failed at line %d in %s\n", x, __LINE__, __FILE__); while(1);}

//编译器对c语言中struct结构字节对齐

#define PACK_STRUCT_FIELD(x) x __attribute__((packed))

#define PACK_STRUCT_STRUCT __attribute__((packed))

#define PACK_STRUCT_BEGIN

#define PACK_STRUCT_END


#endif /* CC_H_ */
选择nios eds程序优化选项optimization level:level 3 否则数据处理延时很长

mian.c建立任务初始化lwip:

	IP4_ADDR(&my_gw, 192,168,1,1);
	IP4_ADDR(&my_ipaddr, 192,168,1,6);
	IP4_ADDR(&my_netmask, 255,255,255,0);
	//printf("Hello LWIP!\n");
	lwip_init();
	IOWR_ALTERA_AVALON_PIO_IRQ_MASK(LAN_NINT_BASE, 1);//允许irq接受
	alt_ic_isr_register(LAN_NINT_IRQ_INTERRUPT_CONTROLLER_ID, LAN_NINT_IRQ ,(void *)enc28j60_irq,NULL,NULL);
	#if NO_SYS
	  netif_add(&my_netif, &my_ipaddr, &my_netmask, &my_gw, NULL, netif_loopif_init, ip_input);
	#else  /* NO_SYS */
	  netif_add(&my_netif, &my_ipaddr, &my_netmask, &my_gw, NULL, ethernetif_init, ethernet_input);
	#endif /* NO_SYS */
	  netif_set_default(&my_netif);
	  printf("netif_set_up!\n");
	  netif_set_up(&my_netif);

测试ping命令结果:

nios2 ucos lwip enc28j60_第3张图片

经过大概一周的努力终于可以使用lwip了,还是存在不少问题,已发现问题如下:

1、通信速度,udp包最大发送速度在15kbyte/s (不用ucos,nios裸机测试也是这个速度)

2、udp、tcp、ping 数据包大小最大500字节 如果遇到大于500字节的数据包nios死机 (这个问题应该可以通过opt.h定义修改)

3、nios持续不断的已最大速度发送udp数据包几分钟内死机

4、ping命令几个小时保持正常,但反应速度慢 最快也要2ms

quartus工程和nios工程下载:http://download.csdn.net/detail/yoeksome/8404853

你可能感兴趣的:(fpga)