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

📄 rtos.c

📁 一个完整的rtos源代码.运行在嵌入80186 cpu上.提供4个任务,信号灯,定时器,schedule等.
💻 C
📖 第 1 页 / 共 4 页
字号:
		return E_ID;
	}
	
	if( (blf == (VP)NULL) || (blf == (VP)NADR) )
	{
		error_trap( "rel_blf", E_PAR );
		return E_PAR;
	}
#endif

	SRkeep = InterruptDisable();

	blcfree( blf );

	tcb = (T_TSKCB *)(mpf.queue.next);

	if( (T_QUEUE *)tcb != (T_QUEUE *)&mpf )
	{
      a_blf = blcalloc();

		if( a_blf == NULL )
		{
			set_SR( SRkeep );
			return E_OK;
		}

		tcb->ans = (VP*)a_blf;
		wakeup_task( E_OK, tcb, TRUE );
	}

	set_SR( SRkeep );

	return E_OK;
}
#endif

#ifdef USED_GET_BLF
/*-----------------------------------------------------------------------------
; Get Fixed-Size Memory Block [E]
-----------------------------------------------------------------------------*/
ER	get_blf( VP *p_blf, ID mplid)
{
	ER ercd;
	STATUS_REG SRkeep;					/* SR(Status Register) keep area */

#ifdef DEBUG_OS
	set_dbgtrc(currentrun, "get_blf");
#endif

	*p_blf = NULL;

#ifndef NO_ERCHK
	if( mplid != 1 )
	{
		error_trap( "get_blf", E_PAR );
		return E_ID;
	}

	if( sysstat & (TSS_INDP | TSS_DDSP) )
	{
		error_trap( "get_blf", E_CTX );
		return E_CTX;
	}
#endif

	SRkeep = InterruptDisable();

   *p_blf = blcalloc();

	if( *p_blf != NULL )
	{
		set_SR( SRkeep );
		return E_OK;
	}

	ercd = wait_task( TTW_MPF, (T_QUEUE *)&mpf, TRUE );
	*p_blf = (VP*)(currentrun->ans);

	set_SR( SRkeep );

	return ercd;
}
#endif

#ifdef USED_PGET_BLF
/*-----------------------------------------------------------------------------
; Poll and Get Fixed-Size Memory Block [E]
-----------------------------------------------------------------------------*/
ER	pget_blf( VP *p_blf, ID mplid )
{
	ER ercd;
	STATUS_REG SRkeep;					/* SR(Status Register) keep area */

#ifdef DEBUG_OS
	set_dbgtrc(currentrun, "pget_blf");
#endif

	*p_blf = NULL;

#ifndef NO_ERCHK
	if( mplid != 1 )
	{
		error_trap( "pget_blf", E_ID );
		return E_ID;
	}

#endif

	SRkeep = InterruptDisable();

   *p_blf = blcalloc();

	if( *p_blf == NULL )
		ercd = E_TMOUT;
	else
		ercd = E_OK;

	set_SR( SRkeep );

	return ercd;
}
#endif

/*=============================================================================
; Interrupt Management Functions
=============================================================================*/
#ifdef USED_LOC_CPU
/*-----------------------------------------------------------------------------
; Lock CPU [R]
-----------------------------------------------------------------------------*/
ER loc_cpu( void )
{
#ifdef DEBUG_OS
	set_dbgtrc(currentrun, "loc_cpu");
#endif

#ifndef NO_ERCHK
	if( sysstat & TSS_INDP )
	{
		error_trap( "loc_cpu", E_CTX );
		return E_CTX;
	}
#endif

	InterruptDisable();

	sysstat |= TSS_LOC;

	return E_OK;
}
#endif

#ifdef USED_UNL_CPU
/*-----------------------------------------------------------------------------
; Unlock CPU [R]
-----------------------------------------------------------------------------*/
ER unl_cpu( void )
{

#ifdef DEBUG_OS
	set_dbgtrc(currentrun, "unl_cpu");
#endif

#ifndef NO_ERCHK
	if ( sysstat & TSS_INDP )
	{
		error_trap( "unl_cpu", E_CTX );
		return E_CTX;
	}
#endif

	sysstat &= ~TSS_LOC;

	if( delaydispatch )
		dispatch();

	InterruptEnable();

	return E_OK;
}
#endif

/*-----------------------------------------------------------------------------
; Entrance of interrupt
-----------------------------------------------------------------------------*/
void ent_int( void )
{
	STATUS_REG SRkeep;					/* SR(Status Register) keep area */

	SRkeep = InterruptDisable();

	intnest++;
	sysstat |= TSS_INDP;

	set_SR( SRkeep );
}

/*-----------------------------------------------------------------------------
; Return from Interrupt Handler [R]
-----------------------------------------------------------------------------*/
void ret_int( void )
{
	STATUS_REG SRkeep;					/* SR(Status Register) keep area */

	SRkeep = InterruptDisable();

	intnest--;

	if( !intnest ){
		sysstat &= ~TSS_INDP;
		if( delaydispatch ){
			dispatch();
		}
	}

	set_SR( SRkeep );
}


/*=============================================================================
; Time Management Functions
=============================================================================*/
#ifdef USED_SET_TIM
/*-----------------------------------------------------------------------------
; Set System Clock [S]
-----------------------------------------------------------------------------*/
ER set_tim( SYSTIME *pk_tim )
{

	STATUS_REG SRkeep;					/* SR(Status Register) keep area */

#ifdef DEBUG_OS
	set_dbgtrc(currentrun, "set_tim");
#endif

#ifndef NO_ERCHK
	if( pk_tim == NULL )
	{
		error_trap( "set_tim", E_PAR );
		return E_PAR;
	}
#endif

	SRkeep = InterruptDisable();

	systim = *pk_tim;

	set_SR( SRkeep );
	return E_OK;
}
#endif

#ifdef USED_GET_TIM
/*-----------------------------------------------------------------------------
; Get System Clock [S]
-----------------------------------------------------------------------------*/
ER get_tim( SYSTIME *pk_tim )
{

	STATUS_REG SRkeep;					/* SR(Status Register) keep area */

#ifdef DEBUG_OS
	set_dbgtrc(currentrun, "get_tim");
#endif

#ifndef NO_ERCHK
	if( pk_tim == NULL )
	{
		error_trap( "get_tim", E_PAR );
		return E_PAR;
	}
#endif

	SRkeep = InterruptDisable();

	*pk_tim = systim;

	set_SR( SRkeep );
	return E_OK;
}
#endif

#ifdef USED_DLY_TSK
/*-----------------------------------------------------------------------------
; Delay Task [S]
-----------------------------------------------------------------------------*/
ER dly_tsk( DLYTIME dlytim )
{
	T_TSKCB *tcb;
	STATUS_REG SRkeep;					/* SR(Status Register) keep area */
	ER		ercd;
	SYSTIME st;

#ifdef DEBUG_OS
	set_dbgtrc(currentrun, "dly_tsk");
#endif

#ifndef NO_ERCHK
	if( dlytim <= 0 )
	{
		error_trap( "dly_tsk", E_PAR );
		return E_PAR;
	}

	if( sysstat & (TSS_INDP | TSS_DDSP) )
	{
		error_trap( "dly_tsk", E_CTX );
		return E_CTX;
	}
#endif

	SRkeep = InterruptDisable();

	st = systim + (SYSTIME)dlytim;
	currentrun->waistm = &st;

	for( tcb = (T_TSKCB *)(delyqueue.queue.next);
#if 1
		 ((T_DLYCB *)tcb != &delyqueue) && (st >= *(tcb->waistm));
#else
		 ((T_DLYCB *)tcb != &delyqueue) && (st <= *(tcb->waistm));
#endif
		 tcb = (T_TSKCB *)(tcb->queue.next) )
			;

#if 1
	ercd = wait_task( TTW_DLY, (T_QUEUE *)tcb, TRUE );
#else
	ercd = wait_task( TTW_DLY, (T_QUEUE *)(tcb->queue.next), TRUE );
#endif

	set_SR( SRkeep );
	return ercd;
}
#endif

/*-----------------------------------------------------------------------------
; Timer Interrupt Handler
-----------------------------------------------------------------------------*/
void interrupt_timer( void )
{
	T_TSKCB *tcb;
	STATUS_REG SRkeep;					/* SR(Status Register) keep area */
	SRkeep = InterruptDisable();

	systim += RTOS_TICK_MS;

#ifndef NO_ERCHK
	if( currentrun->tskstat == TTS_RDY )
	{
		currentrun->ttltic += RTOS_TICK_MS;
	}
#endif

	for( tcb = (T_TSKCB *)(delyqueue.queue.next);
		 ((T_DLYCB *)tcb != &delyqueue) && (systim >= *(tcb->waistm));
		 //tcb = (T_TSKCB *)(tcb->queue.next) ) // See comment below!
		 tcb = (T_TSKCB *)(delyqueue.queue.next) )
	{
		// NOTE: wakeup_task() has a side effect of changing the delyqueue, hence
		// the iteration of this loop must NOT use the explicit value of tcb (which
		// by now was changed to point at the next READY task, rather than the next
		// delayed task).
		wakeup_task( E_OK, tcb, FALSE );

#ifdef DEBUG_OS
		set_dbgtrc(tcb, "TMOUT");
#endif

		delaydispatch = TRUE;
	}

#ifdef _TIME_SLICE_
	if( systmslc )
	{
		if( systmslc == 1 )
		{
#ifdef DEBUG_OS
			dbg_trc_ena = FALSE;
#endif

			rot_rdq( TPRI_RUN );

#ifdef DEBUG_OS
			dbg_trc_ena = TRUE;
#endif
		}
		else{
			systmslc--;
		}
	}
#endif

	set_SR( SRkeep );
}

/*=============================================================================
; System Management Functions
=============================================================================*/
#ifdef USED_GET_VER
/*-----------------------------------------------------------------------------
; Get Version Information [R]
-----------------------------------------------------------------------------*/
ER get_ver( T_VER *pk_ver )
{
#ifdef DEBUG_OS
	set_dbgtrc(currentrun, "get_ver");
#endif

	if( pk_ver == NULL )
	{
#ifndef NO_ERCHK
		error_trap( "get_ver", E_PAR );
#endif
		return E_PAR;
	}

	pk_ver->maker	= 0x0000;
	pk_ver->id		= 0x0001;
	pk_ver->spver	= 0x5302;
	pk_ver->prver	= 0x0001;
	pk_ver->prno[0] = 0x0000;
	pk_ver->prno[1] = 0x0000;
	pk_ver->prno[2] = 0x0000;
	pk_ver->prno[3] = 0x0000;
	pk_ver->cpu		= 0x0000;		/* 186 */
	pk_ver->var		= 0x8000;		/* level S */

	return E_OK;
}
#endif

/*=============================================================================
; Dispatcher
=============================================================================*/
static ER dispatch( void )
{
	T_TSKCB *lastrun;
	T_TSKCB *nextrun_tmp;
	ER		ercd;

	ercd = E_OK;

	if( sysstat == TSS_TSK )
	{
		delaydispatch = FALSE;

		nextrun_tmp = nextrun;
		nextrun = NULL;
		if( (nextrun_tmp != NULL) && (nextrun_tmp != currentrun) )
		{
			if(currentrun->tskstat == TTS_RUN){
				currentrun->tskstat = TTS_RDY;
			}
			lastrun = currentrun;
			currentrun = nextrun_tmp;
			currentrun->tskstat = TTS_RUN;

#ifdef _TIME_SLICE_
			systmslc = currentrun->tmslc;
#endif

#ifdef DEBUG_OS
			set_dbgtrc(currentrun, "dispatch");
#endif

#ifndef NO_ERCHK
			dispatch_counter++;
#endif
			ercd = change_stack( &(currentrun->stackp), &(lastrun->stackp) );
		}
		else
		{
			currentrun->tskstat = TTS_RUN;
		}
	}
	else
	{
		delaydispatch = TRUE;
	}

	return ercd;
}

/*=============================================================================
; Functions For support
=============================================================================*/
/*-----------------------------------------------------------------------------
; Is it next-run-task ?
-----------------------------------------------------------------------------*/
static void it_which( T_TSKCB *a_tsk )
{
	if( (a_tsk->tskpri < currentrun->tskpri)
	 && ( (nextrun == NULL)
	   || ( (nextrun != NULL) && (a_tsk->tskpri < nextrun->tskpri) )
	    )
	  )
	{
		if( !(a_tsk->tskstat & TTS_SUS) )
		{
			a_tsk->tskstat = TTS_RDY;
			nextrun = a_tsk;
		}
	}
}

/*-----------------------------------------------------------------------------
; Next run task ?
-----------------------------------------------------------------------------*/
static void next_ready( void )
{
	T_QUEUE *rdypri;

	for( rdypri = &readyqueue[0]; rdypri <= &readyqueue[RDYQMAX-1]; rdypri++ )
	{
		nextrun = (T_TSKCB *)rdypri->next;

		while( nextrun != (T_TSKCB *)rdypri )
		{
			if( !(nextrun->tskstat & TTS_SUS) )
				return;
			nextrun = (T_TSKCB *)(nextrun->queue.next);
		}
	}

	nextrun = NULL;
}

/*=============================================================================
; Wait task
=============================================================================*/
static ER wait_task( UINT tskwait, T_QUEUE *queue, BOOL add_flg )
{
	currentrun->tskstat |= TTS_WAI;
	currentrun->tskwait = tskwait;
	delete_queue( (T_QUEUE *)currentrun );
	if( add_flg )
		add_queue( queue, (T_QUEUE *)currentrun );

	while( 1 )
	{
		next_ready();
		if( nextrun != NULL ) break;
		sysstat |= TSS_DDSP;
		InterruptEnable();
	  	__asm {
	      nop
         nop
      }
		InterruptDisable();
		sysstat &= ~TSS_DDSP;
	}

	return( dispatch() );
}

/*=============================================================================
; Wakeup task
=============================================================================*/
#pragma argsused 
static void wakeup_task( ER ercd, T_TSKCB *tcb, BOOL dsp_flg )
{
	tcb->tskstat &= ~TTS_WAI;
	tcb->tskwait = FALSE;
	//(tcb->stackp)->retval = ercd;
	delete_queue( (T_QUEUE *)tcb );
	add_queue( &readyqueue[tcb->tskpri - 1], (T_QUEUE *)tcb );
	it_which( tcb );
	if( dsp_flg )
		dispatch();
}

/*=============================================================================
; Queue Handling Functions
=============================================================================*/
/*-----------------------------------------------------------------------------
; Add it to queue
-----------------------------------------------------------------------------*/
static void add_queue( T_QUEUE *top_queue, T_QUEUE *a_queue )
{
	a_queue->next = top_queue;
	a_queue->prev = top_queue->prev;
	(top_queue->prev)->next = a_queue;
	top_queue->prev			= a_queue;
}

/*-----------------------------------------------------------------------------
; Delete it from queue
-----------------------------------------------------------------------------*/
static void delete_queue( T_QUEUE *a_queue )
{
	(a_queue->next)->prev = a_queue->prev;
	(a_queue->prev)->next = a_queue->next;
	a_queue->prev = a_queue;
	a_queue->next = a_queue;
}

#if defined(_TIME_SLICE_) || defined(USED_ROT_RDQ)
/*-----------------------------------------------------------------------------
; Get it from queue
-----------------------------------------------------------------------------*/
static T_QUEUE *get_queue( T_QUEUE *a_queue )
{
	T_QUEUE *anode;

	anode = a_queue->next;
	delete_queue( anode );

	return	anode;
}

/*-----------------------------------------------------------------------------
; Rotate queue
-----------------------------------------------------------------------------*/
static void rotate_queue( T_QUEUE *a_queue )
{
	if(a_queue != a_queue->next )
		add_queue( a_queue, get_queue( a_queue ) );
}
#endif

#ifdef DEBUG_OS
/*=============================================================================
; Set debug information to trace buffer
=============================================================================*/
void set_dbgtrc(T_TSKCB *tsk, char* srvnm)
{
	STATUS_REG SRkeep;					/* SR(Status Register) keep area */

	SRkeep = InterruptDisable();

	if(!dbg_trc_ena) return;
	if(dbg_trc_wrp >= TRACEMAXCNT - 1){
		dbg_trc_wrp = 0;
	}else{
		dbg_trc_wrp++;
	}
	dbgtrctbl[dbg_trc_wrp].tskid = (tsk - tcbtbl) + 1;
	dbgtrctbl[dbg_trc_wrp].tskpri = tsk->tskpri;
	dbgtrctbl[dbg_trc_wrp].srvnm = srvnm;
	dbgtrctbl[dbg_trc_wrp].tim = (UINT)systim;

	set_SR( SRkeep );
}
#endif

static void *blcalloc(void)
{
	T_MEMBLC *mb;

  	for (mb = mempool;mb < &mempool[MEM_BLOCK_MAX];mb++)
   {
		if (mb->attr == MEMORY_BLOCK_NOT_USED)
      {
      	mb->attr = MEMORY_BLOCK_USED;
      	return (void*)(mb->data);
      }
   }
   return NULL;
}

static void blcfree(void *mb)
{
	((T_MEMBLC *)mb)->attr = MEMORY_BLOCK_NOT_USED;
}
/* end of file ///////////////////////////////////////////////////////////// */

⌨️ 快捷键说明

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