⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sys_arch.c

📁 该工程源码是基于EasyARM2200开发平台开发的嵌入式TCP/IP协议栈
💻 C
字号:
/*
*********************************************************************************************************
*                                              ModbusTCP
*                                   programmable human machine interface
*
*                         (c) Copyright 2007, 浙大中自集成控制股份有限公司开发二部
*                                          All Rights Reserved
*
* File : LcdDriver.c
* By   : lb
*********************************************************************************************************
*/
/***********************************************
系统的驱动,移植了ucosii的一些功能,但是memmange不是用ucos的而是lwip自己的。
************************************************/

#include "sys_arch.h"
#include "def.h"
#include "sys.h"

//////////////////////////////////////////////////
/*#define ARCH_OK 2
#if  ARCH_OK == 1
#define MAX_QUEUES		10
#define MAX_QUEUE_ENTRIES		20

#define SYS_MBOX_NULL   (void*)0
#define SYS_SEM_NULL    (void*)0

typedef struct
{
	OS_EVENT * pQ;	//ucosii中指向事件控制块的指针
	void * pvQEntries[MAX_QUEUE_ENTRIES];		//MAX_QUEUE_ENTRIES消息队列中对多的消息数
}  Q_DESCR, *Q_DESCRPt;

typedef Q_DESCRPt	sys_mbox_t;
typedef INT8U		sys_sem_t;
typedef INT8U    	sys_thread_t;
#endif*/
//////////////////////////////////////////////////

struct sys_timeouts NullTimeouts;
struct sys_timeouts LwipTimeouts[LWIP_TASK_MAX];

static INT8U QueueMemoryPool[MAX_QUEUES][sizeof(Q_DESCR)];	//在内存中建立一个能容纳MAX_QUEUES个队列的内存池
OS_MEM * QueueMemPt;

static INT8U ModbusTcpBuf[MAX_MODBUSTCP_BUF_NUM][272];
OS_MEM * ModbusTcpBufPt;

/*定义关于协议栈任务的一些变量和常量*/
//#define LWIP_TASK_MAX  5
#define LWIP_TASK_STK_SIZE	1024
INT8U lwip_task_prio_offset[LWIP_TASK_MAX];	//这个主要是避免了写程序的时候分配的优先级混乱,我把它叫做优先级对号入座。
OS_STK	LwipTaskStack[LWIP_TASK_MAX][LWIP_TASK_STK_SIZE];
OS_STK	LwipTreadStack[2048];
unsigned char LwipTreadHasCreated=0;
//这个任务的堆栈主要是为了创建多个lwip线程所设置的,它所用的堆栈也是随着任务的创建的先后而区分的。

/*sys_init()--系统初始化函数,应用在一切开始之前,所以,这个可以对应于ucosii的 OSinit()初始化μC/OS-Ⅱ,
对这个函数的调用必须在调用OSStart()函数之前,而OSStart()函数真正开始运行多任务。sys_init既然可以用OSinit代替,
那么它做的东西可以更加有针对性,例如初始化信号量和邮箱以及消息队列,那么它的伪代码可以写成如下状态*/
void sys_init(void)
{
	//初始化了一个内存缓冲池,用于放MAX_QUEUES个ucosii的消息队列。
	unsigned char err;
	QueueMemPt = OSMemCreate((void *)QueueMemoryPool, MAX_QUEUES, sizeof(Q_DESCR), &err);
	ModbusTcpBufPt = OSMemCreate((void *)ModbusTcpBuf, MAX_MODBUSTCP_BUF_NUM, 272, &err);
}

void *sys_mem_get(INT8U *err)
{
	void * userbuf;
	userbuf = OSMemGet(ModbusTcpBufPt, err);
	return userbuf;
}

void sys_mem_free(void *Pblk)
{
	OSMemPut(ModbusTcpBufPt, Pblk);
}

/*sys_thread_new()-- 系统的线程创建函数,它相当于ucosii中的taskcreate,因此将其封装出taskcreate的功能即可*/
sys_thread_t  sys_thread_new(void (*function)(void *arg), void *arg, int prio)	//后面两个参数形同虚设
{
	INT8U CreatState;
	if((!prio) && (!LwipTreadHasCreated))
	//if((prio) && (!LwipTreadHasCreated))
	{
		CreatState = OSTaskCreate(function, (void *)0x5555,  &LwipTreadStack[2048-1],\
					(LWIP_TASK_START_PRIO+(unsigned char)prio));	
		LwipTreadHasCreated = 1;
		if(!CreatState){
			lwip_task_prio_offset[prio]=1;	//成功创建了一个任务后,将其加1,以便下一个创建的任务使用。
			return 1;
		}
		else{
			return 0;
		}		
	}
	else if(LwipTreadHasCreated)
	{
		if(prio>(LWIP_TASK_MAX-1))
			return 0;
		if(lwip_task_prio_offset[prio])
			return 0;
			
		CreatState = OSTaskCreate(function, (void *)0x5555,  &LwipTaskStack[prio][LWIP_TASK_STK_SIZE-1],\
					(LWIP_TASK_START_PRIO+(unsigned char)prio));
		
		if(!CreatState){
			lwip_task_prio_offset[prio]=1;	//成功创建了一个任务后,将其加1,以便下一个创建的任务使用。
			return 1;
		}
		else{
			return 0;
		}
	}
	else
		return 0;
}

/*创建一个邮箱,但是这个邮箱相当于ucosii中的消息队列*/
sys_mbox_t sys_mbox_new(void)
{
	unsigned char err;
	Q_DESCRPt	QDescPt;

	QDescPt = OSMemGet(QueueMemPt, &err);	//在内存池中分配出一个队列结构的空间,并将此空间赋成这个结构。
	if(err == OS_NO_ERR){	
		QDescPt->pQ = OSQCreate(&(QDescPt->pvQEntries[0]), MAX_QUEUE_ENTRIES);	//创建队列,但是队列只是lwip队列结构的一个成员。
		if(QDescPt->pQ != NULL){
			return QDescPt;
		}
	}
	return SYS_MBOX_NULL;
}

/*释放并删除一个邮箱,相当于ucosii中的消息队列的清空、删除和释放*/
void sys_mbox_free(sys_mbox_t mbox)
{
	unsigned char err;
	OSQDel((OS_EVENT *)(&(mbox->pvQEntries[0])), 0, &err);
	//具体怎样保证安全性还需要再考虑
    
    OSQFlush( mbox->pQ );	//清除队列事件
	OSQDel( mbox->pQ, OS_DEL_NO_PEND, &err);	//删除队列
    err = OSMemPut( QueueMemPt, mbox);	//把队列所占内存放入内存池
}

/*向一个邮箱发送消息,相当于osii中向队列发送消息*/
void sys_mbox_post(sys_mbox_t mbox, void *data)	//由于lwip会发空消息,而ucosii对空消息会当错处理,所以我们把lwip的空做成ucosii的一个特定值。
{
	unsigned char err;
	if(!data)
		data = (void *)0xffffffff;
	err = OSQPost(mbox->pQ, data);
}

unsigned long sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, unsigned long timeout)
{
	unsigned char err;
	unsigned short ucos_timeout = 0;
	
	/*由于lwip中的timeout时间是ms,而ucosii的是timer tick,所以要转换,将timeout转换成ucos_timeout*/
	//首先确保输入参数的合理性
	if(timeout){
		ucos_timeout = (timeout * OS_TICKS_PER_SEC)/1000;
		if(ucos_timeout < 1)
			ucos_timeout = 1;
		else if(ucos_timeout > 65535)
			ucos_timeout = 65535;
	}
	
	if(!mbox)
		return SYS_ARCH_TIMEOUT;
	//因为OSQPend()有返回值,则看有没有可返回的地址,有则返回,无则不返回。
	if(msg != NULL){
		*msg = OSQPend(mbox->pQ, (unsigned short)ucos_timeout, &err);
	}
	else{
		OSQPend(mbox->pQ, (unsigned short)ucos_timeout, &err);
	}

	if(err == OS_TIMEOUT){
		timeout = SYS_ARCH_TIMEOUT;
	}
	else{
		if(*msg == (void *)0xffffffff)
			*msg = NULL;
		timeout = (ucos_timeout - err) * (1000/OS_TICKS_PER_SEC);
	}
	return timeout;
}




/*创建信号量*/
sys_sem_t sys_sem_new(unsigned char count)
{
	sys_sem_t SemPt;
	SemPt = OSSemCreate(count);
	if(SemPt != NULL)
		return SemPt;
	return SYS_SEM_NULL;
}

/*释放并删除一个信号量*/
void sys_sem_free(sys_sem_t sem)
{
    unsigned char	err;
    OSSemDel((OS_EVENT *)sem, OS_DEL_NO_PEND, &err );
}

/*发送一个信号量*/
void sys_sem_signal(sys_sem_t sem)
{
	OSSemPost((OS_EVENT *)sem);
}


unsigned long  sys_arch_sem_wait(sys_sem_t sem, unsigned long  timeout)	//同队列
{
	unsigned char err;
	unsigned short ucos_timeout = 0;
	
	/*由于lwip中的timeout时间是ms,而ucosii的是timer tick,所以要转换,将timeout转换成ucos_timeout*/
	//首先确保输入参数的合理性
	if(timeout){
		ucos_timeout = (timeout * OS_TICKS_PER_SEC)/1000;
		if(ucos_timeout < 1)
			ucos_timeout = 1;
		else if(ucos_timeout > 65535)
			ucos_timeout = 65535;
	}

	OSSemPend ((OS_EVENT *)sem,(u16_t)ucos_timeout, (u8_t *)&err);

	if(err == OS_TIMEOUT){
		return 0;
	}
	else{
		return 1;
	}
}

/*设置一个超时事件*/
struct sys_timeouts *sys_arch_timeouts(void)
{
	unsigned char CurrPrio;
	signed short err, offset;
	OS_TCB	CurrTaskPcb;
	
	NullTimeouts.next = NULL;
	
	err = OSTaskQuery(OS_PRIO_SELF, &CurrTaskPcb);
	
	CurrPrio = CurrTaskPcb.OSTCBPrio;
	
	offset = CurrPrio - LWIP_TASK_START_PRIO;
	
	if(offset<0 || offset >= LWIP_TASK_MAX){
		return &NullTimeouts;
	}
	return &LwipTimeouts[offset];
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -