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

📄 cpu_calls.c

📁 日本著名的的嵌入式实时操作系统T-Kernel的源码及用户手册。
💻 C
字号:
/* *---------------------------------------------------------------------- *    T-Kernel * *    Copyright (C) 2004 by Ken Sakamura. All rights reserved. *    T-Kernel is distributed under the T-License. *---------------------------------------------------------------------- * *    Version:   1.01.00 *    Released by T-Engine Forum(http://www.t-engine.org) at 2004/6/28. * *---------------------------------------------------------------------- *//* *	cpu_calls.c (VR4131) *	CPU-Dependant System Call */#include "kernel.h"#include "task.h"#include "check.h"#include "cpu_task.h"#include <sys/sysinfo.h>#include <tk/sysdef.h>#include "cpu_insn.h"/* * Dispatch enable/disable  */SYSCALL ER c_tk_dis_dsp( UW *psr ){	CHECK_CTX(!in_loc());	/* Change PSR saved in stack */	*psr &= ~SR_IM(1);	return E_OK;}/* * Dispatch enable  */SYSCALL ER c_tk_ena_dsp( UW *psr ){	CHECK_CTX(!in_loc());	/* Change PSR saved in stack */	*psr |= SR_IM(1);	return E_OK;}/* ------------------------------------------------------------------------ *//* For saving monitor exception handler */EXPORT MONHDR	SaveMonHdr;/* * High level programming language *//* High level programming language interrupt handler entry */EXPORT FP hll_inthdr[N_INTVEC];/* High level programming language interrupt handler 'gp' */EXPORT VP hll_inthdr_gp[N_INTVEC];/* High level programming language routine */IMPORT void inthdr_startup();/* For default handler */IMPORT void defaulthdr_startup();/* * Interrupt handler definition */SYSCALL ER _tk_def_int P2( UINT dintno, T_DINT *pk_dint ){	FP	inthdr;	CHECK_PAR(dintno >= 0 && dintno < N_INTVEC);	if ( pk_dint != NULL ) {		/* Set interrupt handler */		CHECK_RSATR(pk_dint->intatr, TA_HLNG|TA_GP);		if ( dintno >= 1 && dintno <= 4 ) {			/* TA_HLNG is not available in 1-4 */			if ( (pk_dint->intatr & TA_HLNG) != 0 ) return E_PAR;		}		inthdr = pk_dint->inthdr;		if ( (pk_dint->intatr & TA_GP) != 0 ) gp = pk_dint->gp;		BEGIN_CRITICAL_SECTION;		if ( (pk_dint->intatr & TA_HLNG) != 0 ) {			hll_inthdr[dintno] = inthdr;			hll_inthdr_gp[dintno] = gp;			inthdr = ( dintno == EIT_DEFAULT )? defaulthdr_startup:				                            inthdr_startup;		}		define_inthdr(dintno, inthdr);		END_CRITICAL_SECTION;	} else {		/* Free interrupt handler */		switch ( dintno ) {		  case VECNO_DEFAULT:	inthdr = SaveMonHdr.default_hdr; break;		  case VECNO_INTERRUPT:	inthdr = SaveMonHdr.interrupt_hdr;									 break;		  case VECNO_SYSCALL:	inthdr = SaveMonHdr.syscall_hdr; break;		  case VECNO_WATCH:	inthdr = SaveMonHdr.watch_hdr;	 break;		  case VECNO_MONITOR:	inthdr = SaveMonHdr.monitor_hdr; break;		  case VECNO_BREAK:	inthdr = SaveMonHdr.break_hdr;	 break;		  case VECNO_IP2:	inthdr = SaveMonHdr.ip2_hdr;	 break;		  case VECNO_GPIO:	inthdr = SaveMonHdr.gpio_hdr;	 break;		  case VECNO_FPGA:	inthdr = SaveMonHdr.fpga_hdr;	 break;		  default:		inthdr = NULL;		}		BEGIN_CRITICAL_SECTION;		define_inthdr(dintno, inthdr);		hll_inthdr[dintno] = NULL;		END_CRITICAL_SECTION;	}	return E_OK;}/* ------------------------------------------------------------------------ *//* * Get/Set task space */SYSCALL ER _tk_get_tsp( ID tskid, T_TSKSPC *pk_tskspc ){	TCB	*tcb;	ER	ercd = E_OK;	CHECK_TSKID_SELF(tskid);	CHECK_INTSK();	tcb = get_tcb_self(tskid);	BEGIN_CRITICAL_SECTION;	if ( tcb->state == TS_NONEXIST ) {		ercd = E_NOEXS;	} else {		pk_tskspc->uatb = tcb->tskctxb.uatb;		pk_tskspc->lsid = tcb->tskctxb.lsid;	}	END_CRITICAL_SECTION;	return ercd;}/* * Set task space */SYSCALL ER _tk_set_tsp( ID tskid, T_TSKSPC *pk_tskspc ){	TCB	*tcb;	ER	ercd = E_OK;	CHECK_TSKID_SELF(tskid);	CHECK_INTSK();	tcb = get_tcb_self(tskid);	BEGIN_CRITICAL_SECTION;	if ( tcb->state == TS_NONEXIST) {		ercd = E_NOEXS;	} else {		tcb->tskctxb.uatb = pk_tskspc->uatb;		tcb->tskctxb.lsid = pk_tskspc->lsid;		/* When it is the currently running task, switch the		   current space */		if ( tcb == ctxtsk ) {			change_space(tcb->tskctxb.lsid);		}	}	END_CRITICAL_SECTION;	return ercd;}/* ------------------------------------------------------------------------ *//* * Set task register contents */LOCAL void set_reg( TCB *tcb, T_REGS *regs, T_EIT *eit, T_CREGS *cregs ){	SStackFrame	*ssp;	UW	psr;	INT	i;	ssp = (VP)tcb->tskctxb.ssp.lo;	psr = ssp->rng0_3.psr;	if ( cregs != NULL ) ssp = (VP)cregs->ssp.lo;	if ( regs != NULL ) {		ssp->rng0_3.at = regs->at;		ssp->rng0_3.v[0] = regs->v[0];		ssp->rng0_3.v[1] = regs->v[1];		for ( i = 0; i < 4; ++i ) {			ssp->rng0_3.a[i] = regs->a[i];		}		for ( i = 0; i < 8; ++i ) {			ssp->rng0_3.t[i] = regs->t[i];			ssp->rng0_3.s[i] = regs->s[i];		}		ssp->rng0_3.t8 = regs->t[8];		ssp->rng0_3.t9 = regs->t[9];		ssp->rng0_3.gp = regs->gp;		ssp->rng0_3.fp = regs->fp;		ssp->rng0_3.ra = regs->ra;		ssp->rng0_3.hi = regs->hi;		ssp->rng0_3.lo = regs->lo;	}	if ( eit != NULL ) {		ssp->rng0_3.epc = eit->pc;		ssp->rng0_3.psr = psr;		ssp->rng0_3.taskmode = eit->taskmode;	}	if ( cregs != NULL ) {		tcb->tskctxb.ssp  = cregs->ssp;		tcb->tskctxb.uatb = cregs->uatb;		tcb->tskctxb.lsid = cregs->lsid;		if ( (tcb->tskatr & TA_RNG3) != 0 ) {			/* Only RNG 1-3 */			((DW*)tcb->isstack)[-1] = cregs->usp;		}	}}/* * Set task register contents */SYSCALL ER _tk_set_reg( ID tskid,		T_REGS *pk_regs, T_EIT *pk_eit, T_CREGS *pk_cregs ){	TCB		*tcb;	ER		ercd = E_OK;	CHECK_TSKID(tskid);	CHECK_NONSELF(tskid);	CHECK_INTSK();	tcb = get_tcb(tskid);	BEGIN_CRITICAL_SECTION;	if ( tcb->state == TS_NONEXIST ) {		ercd = E_NOEXS;	} else {		set_reg(tcb, pk_regs, pk_eit, pk_cregs);	}	END_CRITICAL_SECTION;	return ercd;}/* * Get task register contents. */LOCAL void get_reg( TCB *tcb, T_REGS *regs, T_EIT *eit, T_CREGS *cregs ){	SStackFrame	*ssp;	INT	i;	ssp = (VP)tcb->tskctxb.ssp.lo;	if ( regs != NULL ) {		regs->at   = ssp->rng0_3.at;		regs->v[0] = ssp->rng0_3.v[0];		regs->v[1] = ssp->rng0_3.v[1];		for ( i = 0; i < 4; ++i ) {			regs->a[i] = ssp->rng0_3.a[i];		}		for ( i = 0; i < 8; ++i ) {			regs->t[i] = ssp->rng0_3.t[i];			regs->s[i] = ssp->rng0_3.s[i];		}		regs->t[8] = ssp->rng0_3.t8;		regs->t[9] = ssp->rng0_3.t9;		regs->gp   = ssp->rng0_3.gp;		regs->fp   = ssp->rng0_3.fp;		regs->ra   = ssp->rng0_3.ra;		regs->hi   = ssp->rng0_3.hi;		regs->lo   = ssp->rng0_3.lo;	}	if ( eit != NULL ) {		eit->pc       = ssp->rng0_3.epc;		eit->psr      = ssp->rng0_3.psr & ~SR_EXL;		eit->taskmode = ssp->rng0_3.taskmode;		/* Set PSR.CU1 to indicate the state of TA_FPU attribute */		if ( (tcb->tskatr & TA_FPU) != 0 ) eit->psr |= SR_CU1;	}	if ( cregs != NULL ) {		cregs->sstktop = tcb->isstack;		cregs->ssp  = tcb->tskctxb.ssp;		cregs->uatb = tcb->tskctxb.uatb;		cregs->lsid = tcb->tskctxb.lsid;		cregs->usp  = ((DW*)tcb->isstack)[-1];	}}/* * Get task register contents. */SYSCALL ER _tk_get_reg( ID tskid,		T_REGS *pk_regs, T_EIT *pk_eit, T_CREGS *pk_cregs ){	TCB		*tcb;	ER		ercd = E_OK;	CHECK_TSKID(tskid);	CHECK_NONSELF(tskid);	CHECK_INTSK();	tcb = get_tcb(tskid);	BEGIN_CRITICAL_SECTION;	if ( tcb->state == TS_NONEXIST ) {		ercd = E_NOEXS;	} else {		get_reg(tcb, pk_regs, pk_eit, pk_cregs);	}	END_CRITICAL_SECTION;	return ercd;}/* * Set task coprocessor register */SYSCALL ER _tk_set_cpr( ID tskid, INT copno, T_COPREGS *pk_copregs ){	ATR	copatr = TA_COP0 << copno;	TCB	*tcb;	ER	ercd = E_OK;	CHECK_TSKID(tskid);	CHECK_NONSELF(tskid);	CHECK_PAR((copatr & available_cop) != 0);	CHECK_INTSK();	tcb = get_tcb(tskid);	BEGIN_CRITICAL_SECTION;	if ( tcb->state == TS_NONEXIST ) {		ercd = E_NOEXS;	} else if ( (tcb->tskatr & copatr) == 0 ) {		ercd = E_PAR;	} else {#if TA_FPU		/* If the current FPU context belongs to 'tcb,' disable it. */		if ( fpu_ctxtsk == tcb ) fpu_ctxtsk = NULL;		/* Set FPU register */		memcpy(tcb->isstack, pk_copregs, sizeof(T_COP0REGS));#endif	}	END_CRITICAL_SECTION;	return ercd;}/* * Get task coprocessor register */SYSCALL ER _tk_get_cpr( ID tskid, INT copno, T_COPREGS *pk_copregs ){	ATR	copatr = TA_COP0 << copno;	TCB	*tcb;	ER	ercd = E_OK;	CHECK_TSKID(tskid);	CHECK_NONSELF(tskid);	CHECK_PAR((copatr & available_cop) != 0);	CHECK_INTSK();	tcb = get_tcb(tskid);	BEGIN_CRITICAL_SECTION;	if ( tcb->state == TS_NONEXIST ) {		ercd = E_NOEXS;	} else if ( (tcb->tskatr & copatr) == 0 ) {		ercd = E_PAR;	} else {#if TA_FPU		IMPORT void save_fpuctx( T_COP0REGS *save_area );		if ( fpu_ctxtsk == tcb ) {			/* Because the current FPU context belongs to 'tcb,'			   retrieve directly from the register */			save_fpuctx(&pk_copregs->cop0);		} else {			/* Retrieve directly from the saved context */			memcpy(pk_copregs, tcb->isstack, sizeof(T_COP0REGS));		}#endif	}	END_CRITICAL_SECTION;	return ercd;}/* ------------------------------------------------------------------------ *//* *	Debugger support function */#if USE_DBGSPT/* * Set task register */SYSCALL ER _td_set_reg( ID tskid, T_REGS *regs, T_EIT *eit, T_CREGS *cregs ){	TCB	*tcb;	ER	ercd = E_OK;	CHECK_TSKID(tskid);	tcb = get_tcb(tskid);	if ( tcb == ctxtsk ) return E_OBJ;	BEGIN_DISABLE_INTERRUPT;	if ( tcb->state == TS_NONEXIST ) {		ercd = E_NOEXS;	} else {		set_reg(tcb, regs, eit, cregs);	}	END_DISABLE_INTERRUPT;	return ercd;}/* * Get task register */SYSCALL ER _td_get_reg( ID tskid, T_REGS *regs, T_EIT *eit, T_CREGS *cregs ){	TCB	*tcb;	ER	ercd = E_OK;	CHECK_TSKID(tskid);	tcb = get_tcb(tskid);	if ( tcb == ctxtsk ) return E_OBJ;	BEGIN_DISABLE_INTERRUPT;	if ( tcb->state == TS_NONEXIST ) {		ercd = E_NOEXS;	} else {		get_reg(tcb, regs, eit, cregs);	}	END_DISABLE_INTERRUPT;	return ercd;}#endif /* USE_DBGSPT */

⌨️ 快捷键说明

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