📄 os.c
字号:
os_stkptr[os_task_curr] = stkptr + limit;
os_task_curr--;
if (limit)
{
++temp;
++stkptr;
asm("lds R30,_stkptr"); // Z register
asm("lds R31, _stkptr+1");
}
while (limit--)
{
asm("pop r0"); // sp += 1; stack pointer move up
asm("st Z+, r0");
}
}
/*-- method 2 end --*/
/*-- deal with task wake up event(time out, signal...) --*/
lable_task_sw_end:
os_task_switching = 0;
if (os_task_stat[os_task_next].sigflag && os_task_stat[os_task_next].waitsig)
{
event = EVENT_SIG;
}
else if (os_task_stat[os_task_next].toflag && os_task_stat[os_task_next].waitto)
{
OS_ENTER_CRITICAL();
os_task_stat[os_task_next].waitto = 0;
os_task_stat[os_task_next].toflag = 0;
OS_EXIT_CRITICAL();
event = EVENT_TMO;
}
else if (os_msg_cnt[os_task_next] && os_task_stat[os_task_next].waitmsg)
{
event = EVENT_MSG;
}
else
{
event = EVENT_NONE;
}
/*-- deal with task wake up event end --*/
/* restore sw stack pointer */
temp = os_stkptr_sw[os_task_curr];
OS_ENTER_CRITICAL();
asm("lds R28, _temp");
asm("lds R29, _temp+1");
OS_EXIT_CRITICAL();
return event;
}
/*********************************************************************************************************
* STATISTICS TASK
*
* os_task_stat: This task is internal to Mini OS and is used to compute some statistics about the
* multitasking environment. Specifically, OSTaskStat() computes the CPU usage.
* CPU usage is determined by:
*
* os_idle_ctr
* CPU Usage (%) = 100 * (1 - -----------------) (units are in %)
* os_idle_ctr_max
*
* @param: pdata this pointer is not used at this time.
*
* @return none
*
* Notes: 1) This task runs at a priority level higher than the idle task. In fact, it runs at the
* next higher priority, OS_IDLE_PRIO-1.
* 2) You can disable this task by setting the configuration #define OS_TASK_STAT_EN to 0.
* 3) We delay for 2 seconds in the beginning to allow the system to reach steady state and
* have all other tasks created before we do statistics. You MUST have at least a delay
* of 2 seconds to allow for the system to establish the maximum value for the idle
* counter.
*********************************************************************************************************/
#if OS_TASK_STAT_EN
static void os_task_statistics (void)
{
os_wait(K_IVL, 2, 0); // Synchronize with clock tick
OS_ENTER_CRITICAL();
os_idle_ctr = 0L; // Clear idle counter
os_cpu_usage = 0;
OS_EXIT_CRITICAL();
os_wait(K_IVL, OS_TICKS_PER_SEC/2, 0); // Wait idle task run for 1s
os_wait(K_IVL, OS_TICKS_PER_SEC/2, 0);
OS_ENTER_CRITICAL();
os_idle_ctr_max = os_idle_ctr; // Store maximum idle counter count in 1 second
os_idle_ctr = 0L;
OS_EXIT_CRITICAL();
os_wait(K_IVL, OS_TICKS_PER_SEC/2, 0);
os_wait(K_IVL, OS_TICKS_PER_SEC/2, 0);
OS_ENTER_CRITICAL();
os_idle_ctr = 0L; // Clear idle counter
OS_EXIT_CRITICAL();
os_wait(K_IVL, OS_TICKS_PER_SEC/2, 0);
os_wait(K_IVL, OS_TICKS_PER_SEC/2, 0);
while(1)
{
unsigned long run;
signed char usage;
OS_ENTER_CRITICAL();
run = os_idle_ctr;
os_idle_ctr = 0L; // Reset the idle counter for the next second
OS_EXIT_CRITICAL();
if (os_idle_ctr_max > 0L)
{
usage = (unsigned char)(100L - 100L*run/os_idle_ctr_max);
if (usage > 100)
{
os_cpu_usage = 100;
}
else if (usage < 0)
{
os_cpu_usage = 0;
}
else
{
os_cpu_usage = usage;
}
}
else
{
os_cpu_usage = 0;
}
os_task_stat_hook(); // Invoke user definable hook
os_wait(K_IVL, OS_TICKS_PER_SEC/2, 0);
os_wait(K_IVL, OS_TICKS_PER_SEC/2, 0);
}
}
#endif
/*********************************************************************************************************
* STATISTICS INITIALIZATION
*
* os_statistics_init: This function is called by your application to establish CPU usage by first determining
* how high a 32-bit counter would count to in 1 second if no other tasks were to execute
* during that time. CPU usage is then determined by a low priority task which keeps track
* of this 32-bit counter every second but this time, with other tasks running. CPU usage is
* determined by:
*
* os_idle_ctr
* CPU Usage (%) = 100 * (1 - -----------------)
* os_idle_ctr_max
*
* @param: none
*
* @return: none
*********************************************************************************************************/
#if OS_TASK_STAT_EN
static void os_statistics_init (void)
{
os_create_task (OS_LOWEST_PRIO, os_task_statistics); // create the 'statistics task' to calculate the CPU usage
os_wait(K_IVL, OS_TICKS_PER_SEC/2, 0); // delay 2s to make statistics task get 'os_idle_ctr_max'
os_wait(K_IVL, OS_TICKS_PER_SEC/2, 0);
os_wait(K_IVL, 5, 0);
os_wait(K_IVL, OS_TICKS_PER_SEC/2, 0);
os_wait(K_IVL, OS_TICKS_PER_SEC/2, 0);
}
#endif
#if 0
/*********************************************************************************************************
* IDLE TASK
*
* os_task_idle: This task is internal to Mini OS and executes whenever no other higher priority tasks
* executes because they are waiting for event(s) to occur.
*
* @param: none
*
* @return: none
*********************************************************************************************************/
static void os_task_idle (void)
{
static unsigned char i;
i = 0;
while(1)
{
if (os_task_stat[i].ready)
{
os_switch_task(); // if other higher task ready, we shall switch task
}
if (++i >= OS_LOWEST_PRIO)
{
i = 0;
}
OS_ENTER_CRITICAL();
os_idle_ctr++;
OS_EXIT_CRITICAL();
}
}
#endif
/**********************************************************
* os_init: OS startup routine, init for Mini OS. After init end, it will start with task0(main)
*
* @param none
* @return none
**********************************************************/
#pragma ctask os_start
void os_start (void)
{
extern void main(void);
unsigned char i;
OS_ENTER_CRITICAL(); // interrupt disable
asm("ldi R30,<_os_stack_bottom"); // initialize hw stack pointer:
asm("ldi R31,>_os_stack_bottom");
asm("lpm R0,Z+");
asm("lpm R1,Z");
asm("OUT 0x3D,R0");
asm("OUT 0x3E,R1");
asm("ldi R30,<_os_stack_top"); // initialize hw stack pointer:
asm("ldi R31,>_os_stack_top");
asm("lpm R28,Z+");
asm("lpm R29,Z");
asm("ldi R30,<PL_main"); // push task 0: main to hw stack
asm("ldi R31, >PL_main");
asm("lpm R0,Z+");
asm("lpm R1,Z");
asm("PUSH R0");
asm("PUSH R1");
if (main); // avoid compiler err: undefined symbol 'PL_main'
/*-- start real-time kernel --*/
memset (os_timer, 0x00, sizeof(os_timer));
memset (os_msg_cnt, 0x00, sizeof(os_msg_cnt));
os_msg_total = 0x00;
memset (os_signal, 0x00, sizeof(os_signal));
for (i = 0; i < sizeof(os_stkptr_sw)/sizeof(os_stkptr_sw[0]); i++)
{
os_stkptr_sw[i] = OS_STACK_TOP-2; // sw stack
}
for (i = 0; i < sizeof(os_stkptr)/sizeof(os_stkptr[0]); i++)
{
os_stkptr[i] = OS_STACK_TOP; // hw stack
}
os_stkptr[0] = OS_STACK_BOTTOM;
memset (os_task_stat, 0x00, sizeof(os_task_stat));
os_task_stat[0].active = 1;
os_task_stat[0].ready = 1;
memset (os_task_rdy, 0x00, sizeof(os_task_rdy));
SET_TASK_READY(0);
os_task_curr = 0x00;
os_task_next = 0x00;
os_isr_sig = 0;
os_task_switching = 0;
os_time = 0L;
/* start os timer */
//TIMER2 initialize - prescale:64
// WGM: CTC
// desired value: 4mSec
// actual value: 4.016mSec (0.4%)TCCR2 = 0x00; //stop
ASSR = 0x00; //set async mode
TCNT2 = 0x06; //setup
OCR2 = OS_TICK_TIMER_VALUE;
TCCR2 = 0x0C; //start
MCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x80; //timer interrupt sources
/*-- end --*/
OS_EXIT_CRITICAL();
#if OS_TASK_STAT_EN
os_statistics_init();
#endif
asm("ret");
}
/**********************************************************
* os_tick: os interval timer interrupt service routine
*
* @param none
* @return none
**********************************************************/
static void os_tick (void)
{
unsigned char i;
os_time++;
/*-- deal with task timer out --*/
for (i = 0; i < sizeof(os_timer)/sizeof(os_timer[0]); i++)
{
if (--os_timer[i] == 0)
{
if (os_task_stat[i].waitto)
{
os_isr_sig = 1;
os_task_stat[i].toflag = 1;
os_task_stat[i].ready = 1;
SET_TASK_READY(i);
}
}
}
}
/**********************************************************
* os_time_isr: os timer interrupt service routine(timer A1 is used as os timer)
*
* @param none
* @return none
**********************************************************/
#pragma interrupt_handler os_time_isr:4
void os_time_isr(void)
{
os_tick();
#if OS_CPU_HOOKS_EN
{
extern void os_time_tick_hook(void);
os_time_tick_hook();
}
#endif
#if OS_STK_CHK_EN
if (!os_task_switching)
{
unsigned char use;
/* get current stack pointer value to calculate the stack usage */
asm ld a,s;
asm ld use,a; // use = stack pointer;
use = OS_STACK_TOTAL_SZ - (use - (unsigned char)os_stkptr[os_task_curr+1]);
os_stk_usage = (unsigned char)(100*(unsigned int)use/(unsigned int)OS_STACK_TOTAL_SZ);
if (os_stk_usage_max < os_stk_usage)
{
os_stk_usage_max = os_stk_usage;
}
if (os_stk_usage_max < 0)
{
os_stk_usage_max = 0;
}
}
#endif
}
#if OS_CPU_HOOKS_EN
/*********************************************************************************************************
* TASK SWITCH HOOK
*
* os_task_sw_hook: This function is called when a task switch is performed. This allows you to perform other
* operations during a context switch.
*
* @param: none
* @return: none
*
*********************************************************************************************************/
void os_task_sw_hook (void)
{
}
/*********************************************************************************************************
* STATISTIC TASK HOOK
*
* os_task_stat_hook: This function is called every second by Mini OS's statistics task. This allows your
* application to add functionality to the statistics task.
*
* @param: none
* @return: none
*********************************************************************************************************/
void os_task_stat_hook (void)
{
}
/*********************************************************************************************************
* TICK HOOK
*
* os_time_tick_hook: This function is called every tick.
*
* @param: none
* @return: none
*
* Note(s): 1) Interrupts may or may not be ENABLED during this call.
*********************************************************************************************************/
void os_time_tick_hook (void)
{
}
#endif
/************************************************
* @ os.c v1.0 log @
*
* Revision 1.0.0.0 Wanghong 2004/09/05
* create file
*
* Revision 1.2.0.0 Wanghong 2005/12/17
* added bit-mapped signal,
* added os message,
* added interface function for user in os_tick(),
* optimize some code in os_task_switch().
*
* Revision 1.2.0.1 Wanghong 2005/12/19
* added task timer init in os_create_task().
*
* Revision 1.2.0.2 Wanghong 2006/9/10
* modified os kernel from st7 mcu to avr mega8/16 cpu
*
***********************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -