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

📄 os.c

📁 MINI-os code,you can download !
💻 C
📖 第 1 页 / 共 3 页
字号:
	
	/*-- copy the msg into the message buffer --*/
	os_msg_q[os_msg_total].task_id	= task_id;
	os_msg_q[os_msg_total].msg[0]	= msg_data[0];
	os_msg_q[os_msg_total].msg[1]	= msg_data[1];
	os_msg_q[os_msg_total].msg[2]	= msg_data[2];
	os_msg_total++;
	/*-- end --*/
	
	/*-- task message counter add 1, and set task message ready --*/
	os_msg_cnt[task_id]++;
	if (os_task_stat[task_id].waitmsg)
	{
		os_task_stat[task_id].ready	= 1;
		SET_TASK_READY(task_id);
		os_isr_sig	= 1;
	}
	/*-- end --*/
	
	
	return ERR_NONE;
}

/**********************************************************
 *  os_send_message: send a message to a specific task.
 *		This function may be called only from task functions.
 *
 *  @param task_id: the specified task to receive the message.
 *  @param msg_data: data to be sent. msg_data lenght must be 3  bytes.
 *  @return 0: if successful,
 *			!0: error code.
 **********************************************************/
unsigned char os_send_message (unsigned char task_id, unsigned char *msg_data)
{
	if (OS_MAX_TASK_N <= task_id	||
		os_task_stat[task_id].active == 0
	)
	{
		return ERR_MSG_GENERAL;
	}
	
	OS_ENTER_CRITICAL();
	if (OS_MAX_MSG_N <= os_msg_total)
	{
		OS_EXIT_CRITICAL();
		return ERR_MSG_OVF;
	}
	
	
	/*-- copy the msg into the message buffer --*/
	os_msg_q[os_msg_total].task_id	= task_id;
	os_msg_q[os_msg_total].msg[0]	= msg_data[0];
	os_msg_q[os_msg_total].msg[1]	= msg_data[1];
	os_msg_q[os_msg_total].msg[2]	= msg_data[2];
	os_msg_total++;
	/*-- end --*/

	/*-- task message counter add 1, and set task message ready --*/
	os_msg_cnt[task_id]++;
	if (os_task_stat[task_id].waitmsg)
	{
		os_task_stat[task_id].ready	= 1;
		SET_TASK_READY(task_id);
	}
	/*-- end --*/
	OS_EXIT_CRITICAL();


	return ERR_NONE;
}

#if OS_MSG_PRIORITY_EN
/**********************************************************
 *  os_send_message_front: send a message to a specific task. The message is posted at
 *			the front instead of the end of the queue, using os_send_message_front()
 *			allows you to send 'priority' messages.
 *		This function may be called only from task functions.
 *
 *  @param task_id: the specified task to receive the message.
 *  @param msg_data: data to be sent. msg_data lenght must be 3  bytes.
 *  @return 0: if successful,
 *			!0: error code.
 **********************************************************/
unsigned char os_send_message_front (unsigned char task_id, unsigned char *msg_data)
{
	unsigned char	i;


	if (OS_MAX_TASK_N <= task_id	||
		os_task_stat[task_id].active == 0
	)
	{
		return ERR_MSG_GENERAL;
	}
	
	OS_ENTER_CRITICAL();
	if (OS_MAX_MSG_N <= os_msg_total)
	{
		OS_EXIT_CRITICAL();
		return ERR_MSG_OVF;
	}

	i = os_msg_total;
	os_msg_total++;
	OS_EXIT_CRITICAL();				// interrupt enable again, new msg can be sent from isr

	/*-- move one message block behind --*/
	for (; i > 0; i--)
	{
		os_msg_q[i].task_id	= os_msg_q[i-1].task_id;
		os_msg_q[i].msg[0]	= os_msg_q[i-1].msg[0];
		os_msg_q[i].msg[1]	= os_msg_q[i-1].msg[1];
		os_msg_q[i].msg[2]	= os_msg_q[i-1].msg[2];
	}/*-- move end --*/

	/*-- copy the msg into the message buffer --*/
	os_msg_q[0].task_id	= task_id;
	os_msg_q[0].msg[0]	= msg_data[0];
	os_msg_q[0].msg[1]	= msg_data[1];
	os_msg_q[0].msg[2]	= msg_data[2];
	/*-- end --*/

	/*-- task message counter add 1, and set task message ready --*/
	OS_ENTER_CRITICAL();
	os_msg_cnt[task_id]++;
	if (os_task_stat[task_id].waitmsg)
	{
		os_task_stat[task_id].ready	= 1;
		SET_TASK_READY(task_id);
	}
	/*-- end --*/
	OS_EXIT_CRITICAL();


	return ERR_NONE;
}
#endif

/**********************************************************
 *  os_get_message: get a message to task's message queue.
 *		This function may be called only from task functions.
 *
 *  @param msg_buf: the buffer to receive the message. buffer lenght must be 3 bytes.
 *  @return >=0: number of unread msg still in the task's message queue,
 *			-1: no message.
 **********************************************************/
char os_get_message (unsigned char *msg_buf)
{
	unsigned char	i;


	/*--  retrieve the message from system buffer --*/
	for (i = 0; i < os_msg_total; i++)
	{
		if (os_msg_q[i].task_id == os_task_curr)
		{
			msg_buf[0]	= os_msg_q[i].msg[0];
			msg_buf[1]	= os_msg_q[i].msg[1];
			msg_buf[2]	= os_msg_q[i].msg[2];

			/*-- move one message block fronter --*/
			OS_ENTER_CRITICAL();				// maybe a new message comes from isr, so disable intereupt
			for (; i < (os_msg_total-1); i++)
			{
				OS_EXIT_CRITICAL();				// interrupt enable again, new msg can be sent from isr
				os_msg_q[i].task_id	= os_msg_q[i+1].task_id;
				os_msg_q[i].msg[0]	= os_msg_q[i+1].msg[0];
				os_msg_q[i].msg[1]	= os_msg_q[i+1].msg[1];
				os_msg_q[i].msg[2]	= os_msg_q[i+1].msg[2];

				OS_ENTER_CRITICAL();			// disable to check if we move msg block end
			}
			/*-- move end --*/

			os_msg_total--;						// total msg number -1
			os_msg_cnt[os_task_curr]--;			// task msg -1
			OS_EXIT_CRITICAL();

			return os_msg_cnt[os_task_curr];
		}
	}/*-- end --*/


	return ERR_MSG_NONE;
}

/**********************************************************
 *  os_running_task_id: determines the task id of the task currently executing.
 *
 *  @param none
 *  @return 0: function returns the task ID of the task currently executing.
 *		This value is a number in the range 0-15.
 **********************************************************/
unsigned char os_running_task_id (void)
{
	return os_task_curr;
}

/**********************************************************
 *  os_reset_interval: The os_reset_interval function is used to correct timer
 *		problems that occur when the os_wait function is used to wait for
 *		K_IVL and K_SIG events simultaneously. In such a case, if a signal
 *		(K_SIG) event causes os_wait to exit, the interval timer is not adjusted
 *		and subsequent calls to os_wait to wait for an interval may not delay
 *		for the required time period. The os_reset_interval allows you to reset
 *		the interval timer in such an event.
 *
 *  @param ticks: number of timer ticks
 *  @return none
 **********************************************************/
void os_reset_interval (unsigned char ticks)
{
	OS_ENTER_CRITICAL();
	os_timer[os_task_curr]	-= ticks;
	OS_EXIT_CRITICAL();
}

/**********************************************************
 *  os_time_get: This function is used by your application to obtain the current value of the 32-bit
 *						counter which keeps track of the number of clock ticks.
 *
 *  @param none
 *  @return: The current value of os_time.
 **********************************************************/
unsigned long os_time_get (void)
{
    unsigned long	ticks;

    OS_ENTER_CRITICAL();
    ticks	= os_time;
    OS_EXIT_CRITICAL();
    return (ticks);
}

/**********************************************************
 *  os_time_set: This function sets the 32-bit counter which keeps track of the number of clock ticks.
 *
 *  @param ticks: specifies the new value that os_time needs to take.
 *  @return: none.
 **********************************************************/
void os_time_set (unsigned long ticks)
{
    OS_ENTER_CRITICAL();
    os_time	= ticks;
    OS_EXIT_CRITICAL();
}

#if OS_STK_CHK_EN
/*********************************************************************************************************
*                                             STACK CHECKING
*
*	os_get_stack_usage: This function is called to get the max usage of system stack.
*
*	@param: prio, not used
*	@return: the max usage of stack in %
*********************************************************************************************************/
unsigned char os_get_stack_usage (unsigned char prio)
{
	unsigned char	usage;

    OS_ENTER_CRITICAL();
    usage	= os_stk_usage_max;
    OS_EXIT_CRITICAL();
    return (usage);
}
#endif

/**********************************************************
 *  os_switch_task: The os_switch_task function allows a task to give up
 *		the CPU and allow another task run. If the task calling os_switch_task
 *		is the only task ready for execution it resumes running immediately.
 *
 *  @param none
 *  @return none
 **********************************************************/
static unsigned int		temp;
static unsigned int		stkptr;

#pragma ctask	os_switch_task

unsigned char os_switch_task (void)
{
	static unsigned char	event;
	static unsigned char	limit;
	static unsigned char	j;
	static unsigned char	mask;
	
	
	/* save sw stack pointer */
	asm("sts _temp,R28");
	asm("sts _temp+1,R29");
	os_stkptr_sw[os_task_curr]	= temp;
	
	os_isr_sig		= 0;
	
	/*-- if task priority enabled --*/
	if (os_priority_en)
	{
		j	= 0;
		goto loop_chk_task_ready;
	}
	/*-- else task priority not enabled --*/
	else
	{
		os_isr_sig		= 1;	// make sure the task ready checker run for a whole cycle
		
		os_task_next	= os_task_curr+1;
		if (os_task_next >= OS_MAX_TASK_N)	// task id range check
		{
			os_task_next	= 0;
		}
		
		j				= os_task_next/8;
		mask			= ~((0x01<<(os_task_next%8))-1);	// suspend the current task and see if there is(are) other task(s) ready.
		temp			= (os_task_rdy[j] & mask);
		if (temp == 0)
		{
			if (++j >= sizeof(os_task_rdy))
			{
				j	= 0;
			}

loop_chk_task_ready:
			while (1)
			{
				temp	= os_task_rdy[j];
				if (temp)
				{
					break;
				}

				if (++j >= sizeof(os_task_rdy))
				{
					j	= 0;
					while (os_isr_sig == 0)		// os timer overflowed/interrupt signal
					{
						CPU_IDLE_CODE();		// enter sleep mode to decrease power consumption
						
					#if OS_TASK_STAT_EN
						OS_ENTER_CRITICAL();
						os_idle_ctr++;			// idle counter for calculate the usage of cpu
						OS_EXIT_CRITICAL();
					#endif
					}
					os_isr_sig	= 0;
				}
			}
		}
	}
	/*-- end of while(1) --*/

	/*-- find the task to run --*/
	if (temp & 0x0f)
	{
		j	*= 8;
		if (temp & 0x01)		{os_task_next	= j+0;}
		else if (temp & 0x02)	{os_task_next	= j+1;}
		else if (temp & 0x04)	{os_task_next	= j+2;}
		else if (temp & 0x08)	{os_task_next	= j+3;}
	}
	else if (temp & 0xf0)
	{
		j	*= 8;
		if (temp & 0x10)		{os_task_next	= j+4;}
		else if (temp & 0x20)	{os_task_next	= j+5;}
		else if (temp & 0x40)	{os_task_next	= j+6;}
		else if (temp & 0x80)	{os_task_next	= j+7;}
	}
	/*-- end --*/
	
	
	asm("NOP");		// for debug
	
	os_task_switching	= 1;
	
#if OS_CPU_HOOKS_EN
	os_task_sw_hook();
#endif

	/*-- judge how to deal with the task switch process --*/
	if (os_task_curr < os_task_next)
	{
		goto	lable_task_sw_method1;			// need to do task switch process method 1
	}
	else if (os_task_curr > os_task_next)
	{
		goto	lable_task_sw_method2;			// need to do task switch process method 2
	}
	else
	{
		goto	lable_task_sw_end;
	}/*-- end --*/
	
	
	/*-- method 1: number of current task is smaller than number of the next task to run --*/
lable_task_sw_method1:
	while (os_task_curr < os_task_next)
	{
		os_task_curr++;
		stkptr	= os_stkptr[os_task_curr];
		
		/* move stack up by limit bytes */
		limit	= (stkptr - os_stkptr[os_task_curr+1]);
		
		/* temp = sp */
		asm("in r0, 0x3d");
		asm("in r1, 0x3e");
		asm("sts _temp,R0");
		asm("sts _temp+1,R1");
		os_stkptr[os_task_curr] = temp;	// get new top stack pointer
		
		++stkptr;
		asm("lds R30,_stkptr");
		asm("lds R31, _stkptr+1");
		while (limit--)
		{
			asm("ld R0,-Z");
			asm("push r0");				// sp -= 1; stack pointer move down
		}
	}
	goto lable_task_sw_end;
	/*-- method 1 end --*/
	
	
	/*-- method 2: number of current task is larger than number of the next task to run --*/
lable_task_sw_method2:
	while (os_task_curr > os_task_next)
	{
		stkptr = os_stkptr[os_task_curr+1];

		/* temp = sp */
		asm("in r0, 0x3d");
		asm("in r1, 0x3e");
		asm("sts _temp,R0");
		asm("sts _temp+1,R1");
		
		limit	= (os_stkptr[os_task_curr] - temp);

⌨️ 快捷键说明

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