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

📄 cxver5.c

📁 CMEX source code RTOS for atmel atmega128
💻 C
📖 第 1 页 / 共 4 页
字号:
			}
		}
	K_I_Func_Return();	/* release task block. */
	return(K_OK);	/* always return good status */
}

/********************************************************************
		CYCLIC TIMER FUNCTIONS
*********************************************************************/
/* tproc_start states:
	0 = stopped
	1 = started
*/

/********************************************************************
 This function sets up the cyclic timer's event parameters.
********************************************************************/
byte K_Timer_Create(byte timed_num,byte mode,byte tskid_pri,word16 event_num)
{
	struct _tcproc *tpptr;

	if (timed_num >= MAX_CYCLIC_TIMERS)	/* have we exceeded the maximum number */
		{
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in2(CXCTCRE_K_ERROR,timed_num);
			}
#endif
		return(K_ERROR);	/* yes, return error status */
		}
	K_I_Disable_Sched();	/* set task block */
	tpptr = &tcproc[timed_num];	/* get address of cyclic timer handler */
	tpptr->mode = mode;	/* load K_Event_Signal MODE */ 
	tpptr->tskid_pri = tskid_pri;	/* load in the tasks slot number
												or priority. May not be used. */
	tpptr->event_num = event_num;	/* load in the event to be set. */
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in2(CXCTCRE_K_OK,timed_num);
			}
#endif
	K_I_Func_Return();	/* release task block */
	return(K_OK);	/* return good status */
}

/******************************************************************
 This is the common routine that the most of the cyclic timer functions
 will call. This function starts, or restarts a cyclic timer and possibly
 also changes the cyclic timer's time parameters.

mode:
= 0: = just restart timer if not started 
= 1: = change only initial time and start 
= 2: = change only cyclic time and start 
= 3: = change both initial time and cyclic time and start
**************************************************************************/
byte K_I_Cyclic_Common(byte timed_num,word16 timecnt, word16 cyclic,byte mode)
{
	struct _tcproc *tpptr;

	if (timed_num >= MAX_CYCLIC_TIMERS)	/* have we exceeded the maximum number */
		{
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in2(CXCTCOM_K_ERROR,timed_num);
			}
#endif
		return(K_ERROR);
		}
	K_I_Disable_Sched();	/* set task block */
	tpptr = &tcproc[timed_num];	/* get the CMX handler for this cyclic timer. */
	if (mode & 0x01)	/* see if mode bit 0 set. */
		{
		tpptr->tproc_timer = timecnt;	/* load time period into counter */
		}
	if (mode & 0x02)	/* see if mode bit 1 set. */
		{
		tpptr->reload_time = cyclic;	/* load cyclic time into counter */
		}
	if (!(tpptr->tproc_start))	/* see if 0 */
		{
		tpptr->tproc_start = 1;	/* start the timed procedure */
		/* add to the cyclic timers doubly linked list. */
		if (cyclic_lnk->ftlink != (struct _tcproc *)cyclic_lnk)	
			{
			tpptr->ftlink = cyclic_lnk->btlink->ftlink;
			cyclic_lnk->btlink->ftlink = tpptr;
			tpptr->btlink = cyclic_lnk->btlink;
			}
		else
			{
			tpptr->ftlink = tpptr->btlink = (struct _tcproc *)cyclic_lnk;
			cyclic_lnk->ftlink = tpptr;
			}
		cyclic_lnk->btlink = tpptr;
		}
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			if (mode == 3)
				{
				cmxtracker_in2(CXCTSTT_K_OK,timed_num);
				}
			else if (mode == 2)
				{
				cmxtracker_in2(CXCTRSTC_K_OK,timed_num);
				}
			else if (mode == 1)
				{
				cmxtracker_in2(CXCTRSTI_K_OK,timed_num);
				}
			else
				{
				cmxtracker_in2(CXCTRSTT_K_OK,timed_num);
				}
			}
#endif
	K_I_Func_Return();	/* release task block */
	return(K_OK);	/* return good status */
}

/******************************************************************
 stop a cyclic timer function
******************************************************************/
byte K_Timer_Stop(byte timed_num)
{
	struct _tcproc *tpptr;

	if (timed_num >= MAX_CYCLIC_TIMERS)	/* have we exceeded the maximum number */
		{
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in2(CXCTSTP_K_ERROR,timed_num);
			}
#endif
		return(K_ERROR);
		}
	K_I_Disable_Sched();	/* set task block */
	tpptr = &tcproc[timed_num];	/* address of cyclic timer structure. */
	if (tpptr->tproc_start)	/* see if non 0 */
		{
		tpptr->tproc_start = 0;	/* stop cyclic timer. */
		/* the following removes the cyclic timer from
			the doubly linked list of started cyclic timers. */
		tpptr->ftlink->btlink = tpptr->btlink;
		tpptr->btlink->ftlink = tpptr->ftlink;
		}
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in2(CXCTSTP_K_OK,timed_num);
			}
#endif
	K_I_Func_Return();	/* release task block */
	return(K_OK);	/* return good status */
}


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

		memory manager

**********************************************************************/
/* here's what a memory partition will look like
	ptr head;	 ptr to head of free list_ptr
	byte body;	 body of memory partition starts here
	does not test to ensure size of array is large enough for
	block size times the number of blocks */

/****************************************************************
 This function creates a fixed memory block according to the
 parameters passed. Make note, that the memory address supplied
 as the beginning of this fixed memory block is not tested as
 to legal CPU boundries and that the size of this memory block
 is free to be used.
****************************************************************/
void K_Mem_FB_Create(void *part,word16 bsize,word16 nblocks)
{
	byte *link;		/* scratch pointer */

#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in5(CXBFCRE_K_OK,0,part);
			}
#endif
	link = (byte *)part + sizeof(byte *); /* address of 1st block */
	*(byte **) part = link;	/* point head at 1st block */

	while (nblocks--)
	{
		part = link;		/* skip to next block */
		/* compute addr of next block */
		link += bsize;		/* compute addr of next block */
		*(byte **) part = link;	/* create link to it */
	}
	*(word16 **) part = 0;	/* last link in chain is null */
}

/****************************************************************
 this function passes a pointer of a free fixed memory block
 if one is available, to the caller.
****************************************************************/
byte K_Mem_FB_Get(void *part,byte **addr)
{
	byte *link;	/* scratch pointer */

	K_I_Disable_Sched();	/* prevent interruption by another task */
	link = *(byte **) part;	/* get head of free memory block */
	if (link != NULL)	/*  exhausted if link is null */
		{
		*(byte **) part = *(byte **) link; /* update head */
		*addr = link;	/* load address of memory block to user pointer */
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in5(CXBFGET_K_OK,0,link);
			}
#endif
		K_I_Func_Return();	/* release task block. */
		return(K_OK);	/* return good status. */
		}
	else
		{
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in5(CXBFGET_K_ERROR,0,part);
			}
#endif
		K_I_Func_Return();	/* release task block. */
		return(K_ERROR);		/* Error: no more memory blocks available */
		}
}	


/****************************************************************
 this function releases fixed memory block, back into the fixed block
 memory pool.
****************************************************************/
void K_Mem_FB_Release(void *part,byte *addr)
{
	byte *link;	/* scratch pointer */

	K_I_Disable_Sched();	/* set task block. */
	link = *(byte **) part;	/* save old head of free memory */
	*(byte **) addr = link;	/* point released block at old head */
	*(byte **) part = addr;	/* point head at released block */
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in5(CXBFREL_K_OK,0,addr);
			}
#endif
	K_I_Func_Return();	/* release task block. */

}

void K_OS_Start(void)
{
	PROC_DISABLE_INT;	/* disable interrupts. */
	PREEMPTED;	/* set preempted K_I_Scheduler flag. */
	CMX_ACTIVE;	/* identify that were CMX OS active. */
	K_I_Scheduler();			/* invoke K_I_Scheduler */
}

/*******************************************************************
 The following is the CMX timer task. This will see if any tasks
 need their time counters decremented (because they have specified
 a time period, and thier waiting). If so then this will use the doubly
 linked list of tasks that need their time counters decremented. Once a
 task has it's time counter decrement to 0, then the task will be place
 into the RESUME state, and remove from the linked list.

 Also the cyclic timers linked list will be tested to see if any cyclic
 timers need thier respective time counters decremented. If so then this
 will use the doubly	linked list of cyclic timers that need their time
 counters decremented. Once a cyclic timer has it's time counter decrement
 to 0, then the cyclic timer will have its K_Event_Signal parameters executed
 and also the cyclic time will be reloaded, if non zero.
****************************************************************/
 
void K_I_Timer_Task(void)
{
	tcbpointer x;
	struct _tcproc *tpptr;

	tpptr = cyclic_lnk->ftlink;	/* set pointer to cyclic linked list. */
	while (tpptr != (struct _tcproc *)cyclic_lnk) /* test for done of list. */
		{
		if (!(--tpptr->tproc_timer))	/* decrement time counter and test. */
			{
			/* if 0, then reload time counter, with cyclic time. */
			if ((tpptr->tproc_timer = tpptr->reload_time) == 0)
				{
				/* if cyclic time period 0, then stop cyclic timer
					and remove from linked list. */
				tpptr->tproc_start = 0;
				tpptr->ftlink->btlink = tpptr->btlink;
				tpptr->btlink->ftlink = tpptr->ftlink;
				}
			/* execute the cyclic timer's K_Event_Signal function parameters. */ 
#ifdef CMXTRACKER
		if (CMXTRACKER_ON)
			{
			cmxtracker_in2(TIMER_TASK_ACTION,(byte)(tpptr - tcproc));
			}
#endif
			K_Event_Signal(tpptr->mode,tpptr->tskid_pri,tpptr->event_num);
			}
		/* adjust pointer to next linked list member. */
		tpptr = tpptr->ftlink;
		} /* while loop */
	/* set pointer to beginning of task timer link list. */
	x = tsk_timer_lnk->ftlink;
	while (x != (tcbpointer)tsk_timer_lnk)	/* if not end of linked list. */
		{
		if (x->tcbstate & TIME)	/* see if task really waiting on time out. */
			{
			if (!(--x->tcbtimer))	/* yes, go decrement the task time counter. */
				{
				/* if time expired, test to see if task waiting on resource. */
				if (x->tcbstate & (RESOURCE | SEMAPHORE))
					{
					/* yes, remove task from resource wait linked list. */
					x->fwlink->bwlink = x->bwlink;
					x->bwlink->fwlink = x->fwlink;
					}
				/* set the task into the RESUME state. */
				x->tcbstate = RESUME | TIME_EXPIRED;
				/* indicate we should remove task from link list, this
					will be done by the function that place this task
					into the wait (sleep) state. This way we do NOT
					waste time in here performing this. */
				x->tcbtimer = 1;
				if (x->priority < active_priority) 
					PREEMPTED;	/* yes, set preempted scheduling flag */
				}
			}
		x = x->ftlink;	/* point to next link. */
		}
}	/* K_I_Timer_Task */

/*****************************************************************
 Semaphore stuff
******************************************************************/
/*
 Pend on semaphore, if count 0, otherwise return with semaphore

 mode 0 : wait if semaphore not present 
 mode 1 : do NOT wait if semaphore not present, return immediatedly

*/

byte K_I_Semaphore_Get_Common(byte sem_num, word16 timecnt, byte mode)	
{
	SEM *sem_ptr;

	if (sem_num >= MAX_SEMAPHORES)
		{
		return(K_ERROR);	/* return good status to caller */
		}
	K_I_Disable_Sched();
	sem_ptr = &sem_array[sem_num];	/* CMX semaphore handler. */
	if (sem_ptr->fwlink == NULL)
		{
		K_I_Func_Return();	/* release task block */
		return(K_ERROR);	/* return good status to caller */
		}
	if (!sem_ptr->sem_count)
		{
		if (mode)
			{
			K_I_Func_Return();	/* release task block */
			return(K_SEMAPHORE_NONE);	/* return error that semaphore
											had not been posted to */
			}
		if (sem_ptr->fwlink != (tcbpointer)sem_ptr)	/* is at least one task waiting
																		on is semaphore */
			{
			activetcb->fwlink = sem_ptr->bwlink->fwlink;
			sem_ptr->bwlink->fwlink = activetcb;
			activetcb->bwlink = sem_ptr->bwlink;
			sem_ptr->bwlink = activetcb;
			}
		else
			{
			sem_ptr->fwlink = sem_ptr->bwlink = activetcb;
			activetcb->fwlink = activetcb->bwlink = (tcbpointer)sem_ptr;
			}
		if (K_I_Time_Common(timecnt,SEMAPHORE))	/* go suspend task. */
			return(K_TIMEOUT);	/* return the warning: that the time period expired */
		else
			return(K_OK);
		}
	--sem_ptr->sem_count;
	K_I_Func_Return();
	return(K_OK);
}	/* K_I_Semaphore_Get_Common */

byte K_Semaphore_Post(byte sem_num)	
{
	SEM *sem_ptr;
	tcbpointer tp;

	if (sem_num >= MAX_SEMAPHORES)
		{
		return(K_ERROR);	/* return good status to caller */
		}
	K_I_Disable_Sched();
	sem_ptr = &sem_array[sem_num];	/* CMX semaphore handler. */
	if (sem_ptr->fwlink == NULL)
		{
		K_I_Func_Return();	/* release task block */
		return(K_ERROR);	/* return good status to caller */
		}
	++sem_ptr->sem_count;
	if (sem_ptr->fwlink != (tcbpointer)sem_ptr)	/* does a task own this semaphore */
		{
		sem_ptr->fwlink->tcbstate = RESUME;	/* allow task to run again */
		if (sem_ptr->fwlink->priority < active_priority)
			PREEMPTED;	/* yes, so set the preempted scheduling flag */
		tp = sem_ptr->fwlink;
		tp->fwlink->bwlink = tp->bwlink;
		sem_ptr->fwlink = tp->fwlink;
		--sem_ptr->sem_count; /* reduce count again, because this task now
										 has semaphore */
		}
	K_I_Func_Return();	/* release task block */
	return(K_OK);	/* return good status to caller */
}	/* K_Semaphore_Post */

byte K_Semaphore_Create(byte sem_num, word16 n)	
{
	SEM *sem_ptr;

	if (sem_num >= MAX_SEMAPHORES)
		{
		return(K_ERROR);	/* return good status to caller */
		}
	K_I_Disable_Sched();
	sem_ptr = &sem_array[sem_num];	/* CMX semaphore handler. */
	sem_ptr->fwlink = (tcbpointer)sem_ptr;
	sem_ptr->bwlink = (tcbpointer)sem_ptr;
	sem_ptr->sem_n = sem_ptr->sem_count = n;
	K_I_Func_Return();	/* release task block */
	return(K_OK);	/* return good status to caller */
}

/*
mode = 0 = do not flush if task owns semaphore
mode = 1 = do flush if task owns semaphore
also reset count to original value
*/
byte K_Semaphore_Reset(byte sem_num,byte mode)	
{
	SEM *sem_ptr;

	if (sem_num >= MAX_SEMAPHORES)
		{
		return(K_ERROR);	/* return good status to caller */
		}
	K_I_Disable_Sched();
	sem_ptr = &sem_array[sem_num];	/* CMX semaphore handler. */
	if (sem_ptr->fwlink == NULL)
		{
		K_I_Func_Return();	/* release task block */
		return(K_ERROR);	/* return good status to caller */
		}
	if (sem_ptr->fwlink != (tcbpointer)sem_ptr)	/* see if another task already "owns" this semaphore. */
		{
		if (!mode)
			{
			K_I_Func_Return();	/* release task block. */
			return(K_ERROR);
			}
		else
			{
			do {
				sem_ptr->fwlink->tcbstate = RESUME | TIME_EXPIRED;	/* allow task to run again */
				if (sem_ptr->fwlink->priority < active_priority)
					PREEMPTED;	/* yes, so set the preempted scheduling flag */
				if ((sem_ptr->fwlink = sem_ptr->fwlink->fwlink) == (tcbpointer)sem_ptr)
					sem_ptr->bwlink = (tcbpointer)sem_ptr;
				}
			while(sem_ptr->fwlink != (tcbpointer)sem_ptr);
			}
		}
	sem_ptr->sem_count = sem_ptr->sem_n;
	K_I_Func_Return();	/* release task block. */
	return(K_OK);
}

⌨️ 快捷键说明

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