📄 os.c
字号:
/*-- 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 + -