📄 4avros.c
字号:
/*-----------------------------------------------------------------------------------------------------------
___ _ _ _ _ ___ _____ ___ ___ _ _ ___ ___ ___ _____ ___ _______ _____ ___ ___
| __| | | | \| |/ __|_ _|_ _/ _ \| \| | | _ \ _ \/ _ \_ _/ _ \_ _\ \ / / _ \ __/ __|
| _|| |_| | .` | (__ | | | | (_) | .` | | _/ / (_) || || (_) || | \ V /| _/ _|\__ \
|_| \___/|_|\_|\___| |_| |___\___/|_|\_| |_| |_|_\\___/ |_| \___/ |_| |_| |_| |___|___/
-----------------------------------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------------------------------
these are 'private' functions to this file only ('puclic' functions are in the 4AvrOS.h file)
-----------------------------------------------------------------------------------------------------------*/
static void __osError(uint8_t err,uint8_t bad_num);
static void __restore_priority(uint8_t tn);
static void __inc_sch_count(uint8_t tn);
static void __schedule(void);
/*-----------------------------------------------------------------------------------------------------------
___ _ _ _ _ ___ _____ ___ ___ _ _ ___
| __| | | | \| |/ __|_ _|_ _/ _ \| \| |/ __|
| _|| |_| | .` | (__ | | | | (_) | .` |\__ \
|_| \___/|_|\_|\___| |_| |___\___/|_|\_||___/
-----------------------------------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------------------------------
save 'goto label address' for returning to task after os call
-----------------------------------------------------------------------------------------------------------*/
void __save_goto(uint8_t *gl){
thisTaskP->goto_label = gl;
}
/*-----------------------------------------------------------------------------------------------------------
error handling function, can use to troubleshoot problems
-----------------------------------------------------------------------------------------------------------*/
static void __osError(uint8_t err,uint8_t bad_num){ // error code + bad number
// turn off irq's (no irq's while __osError does its thing)
cli();
while(1); //just halt here (can do whatever you want)
}
/*-----------------------------------------------------------------------------------------------------------
restore priority number of a task from progtram memory (original setting)
only used by __releaseSema, so no error checking on tn done
-----------------------------------------------------------------------------------------------------------*/
static void __restore_priority(uint8_t tn){
__set_priority(tn, (pgm_read_byte(&taskAddress[tn].init))>>4 & 7 );
}
/*-----------------------------------------------------------------------------------------------------------
get priority number of a task
-----------------------------------------------------------------------------------------------------------*/
uint8_t __get_priority(uint8_t tn){
if(tn >= nTasks){ // make sure a valid task number
__osError(ERR__get_priority,tn); // error, invalid task number
return 0;
}
else{
return ((myTasks[tn].status >> 4) & 7); // lower 3 bits in high nibble
}
}
/*-----------------------------------------------------------------------------------------------------------
set priority number of a task
-----------------------------------------------------------------------------------------------------------*/
void __set_priority(uint8_t tn, uint8_t pri){
if(tn >= nTasks){ // make sure a valid task number
__osError(ERR__set_priority,tn); // error, invalid task number
}
else if(pri > 7){ // make sure a valid priority
__osError(ERR__set_priorityP,pri); // error, invalid priority
}
else{
uint8_t temp_s; // temp status byte storage
temp_s = myTasks[tn].status & 0x8F; // clear out priority bits (bits4-6)
pri <<= 4; // move priority number up into position
myTasks[tn].status = temp_s | pri; // save previous status + new priority
}
}
/*-----------------------------------------------------------------------------------------------------------
enable task number ready to run status if a valid task number, and not waiting for a semaphore
also check if the task tn owns a semaphore (only if semaphores enabled)
-----------------------------------------------------------------------------------------------------------*/
void __set_rtr(uint8_t tn, uint8_t i){
if(tn >= nTasks){ // make sure a valid task number
__osError(ERR__set_rtr,tn); // error, invalid task number
}
else{
#if (SEMAPHORES_ON)
// check all semaphores (if nSemas passed) to see if task owns any
// osSET_SEMA_OWNER_RTR(semaowner),osENABLE_SEMA_OWNER(semaowner) will skip this check
// because they pass 1, which will predecrement to 0,skipping this check
while(--i){ // pre-decrement (check sema 1 to nSemas)
if(semaOwner[i] == tn){ // if task owns a semaphore,
return; // return
}
}
// if waiting for a semaphore, do not enable
if(myTasks[tn].status & 0x0F){ // if waiting for a semaphore, do not enable task
return; // just return
}
#endif
myTasks[tn].status |= RTR_ON; // turn on rtr bit
myTasks[tn].ticks = 0; // clear tick counter, so if task was waiting, it will
// not be re-enabled when wait time is done
}
}
/*-----------------------------------------------------------------------------------------------------------
clear task number ready to run status
-----------------------------------------------------------------------------------------------------------*/
void __clear_rtr(uint8_t tn){
if(tn >= nTasks){ // make sure a valid task number
__osError(ERR__clear_rtr,tn); // error, invalid task number
}
else{
myTasks[tn].status &= ~RTR_ON;
myTasks[tn].ticks = 0; // clear tick counter, so if task was waiting, it will
} // not be re-enabled when wait time is done
}
/*-----------------------------------------------------------------------------------------------------------
increase sch_count of task (keep track of how many times a task was ready, but was not run because of a
higher priority task that was also ready, or was waiting for a semaphore)
-----------------------------------------------------------------------------------------------------------*/
static void __inc_sch_count(uint8_t tn){
struct ts *mt; // pointer to myTasks[tn] struct
mt = &myTasks[tn]; // get address of myTasks[tn]
if(mt->sch_count < 0xFF){ // only increase count if not 0xFF (prevent rollover)
mt->sch_count++; // increase the sch_count of task
}
}
/*-----------------------------------------------------------------------------------------------------------
scheduler finds the highest priority task ready to run (if any), loops if none found
tasks that have been waiting longest, are given priority for same priority tasks
if a task is ready, find task address from pgm memory, then call it (goto number passed to task)
-----------------------------------------------------------------------------------------------------------*/
static void __schedule(void){
uint8_t highestPriority; // keep track of highest priority task found
uint8_t i; // loop counter
uint8_t this_pri; // priority of myTasks[i] (current task in loop)
uint8_t save_tn=0; // task number of task to run
uint8_t this_cnt; // sch_count of myTasks[i] (how many times waiting)
uint8_t save_cnt=0; // sch_count of task to run
for(;;){ // loop in scheduler forever
//---------------------------------------------------------------------------------------------------
// set priority higher than any task
//---------------------------------------------------------------------------------------------------
highestPriority=8; // start 1 more than possible
//---------------------------------------------------------------------------------------------------
// loop through all tasks to find a task to run
//---------------------------------------------------------------------------------------------------
for(i=0; i < nTasks; i++){ // loop through all tasks
this_pri = myTasks[i].status >> 4; // get status byte, move high nibble to low nibble
this_cnt = myTasks[i].sch_count; // get sch_count of task
//-----------------------------------------------------------------------------------------------
// if a task has the rtr bit set
//-----------------------------------------------------------------------------------------------
if(this_pri & 8){ // if rtr bit set
this_pri &= 7; // mask off rtr bit, only priority number is left
//-------------------------------------------------------------------------------------------
// first, find out if this is the highest priority task
// the first rtr task will always be the highest priority (is > 8)
//-------------------------------------------------------------------------------------------
if(this_pri < highestPriority){ // if higher priority task
//---------------------------------------------------------------------------------------
// found a higher priority task, so now see if this was not the first
// task found (highestPriority will not be 8), if was not the first, the previously
// saved task needs its sch_count increased, since it will not run
//---------------------------------------------------------------------------------------
if(highestPriority!=8){ // this is not the first task found
__inc_sch_count(save_tn); // increase sch_count of previous task
}
highestPriority = this_pri; // save this priority number as the highest found
save_tn = i; // save task number of this task
save_cnt = this_cnt; // save sch_count of this task
}
//-------------------------------------------------------------------------------------------
// was not a higher priority, so now check if it is the same priority as the highest
// priority previously found
//-------------------------------------------------------------------------------------------
else if(this_pri == highestPriority){ // this must be at least the second task found ready
//---------------------------------------------------------------------------------------
// same priority, so now check if this task has a higher sch_count (waiting longer)
//---------------------------------------------------------------------------------------
if(this_cnt > save_cnt){ // if been waiting longer,
__inc_sch_count(save_tn); // increase sch_count of previous task
save_tn = i; // save the task number of this task
save_cnt = this_cnt; // save sch_count of this task
}
else{ // have not been waiting longer than previous task
__inc_sch_count(i); // just increase sch_count of this task
}
}
//-------------------------------------------------------------------------------------------
// this task is a lower priority task, so just increase its sch_count
//-------------------------------------------------------------------------------------------
else{ // is lower priority task
__inc_sch_count(i); // increase sch_count of this task
}
} //if
//-----------------------------------------------------------------------------------------------
// rtr bit was not set
//-----------------------------------------------------------------------------------------------
else{ // is not rtr, but check if waiting for semaphore
if(myTasks[i].status & 0x0F){ // if low nibble not 0, then is waiting for a semaphore
__inc_sch_count(i); // increase sch_count of this task
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -