📄 4avros.c
字号:
} //for
wdt_reset(); // reset wdt here (in case wdt fused always on)
// if using watchdog and timeout occurs, that means
// the scheduler is not resetting the watchdog, which
// means a task is stuck, or taking too long
// set watchdog timeout to max time you want to let a
// task run
//---------------------------------------------------------------------------------------------------
// check if a task found, if highestPriority is not 8, a task was found
//---------------------------------------------------------------------------------------------------
if(highestPriority != 8){ // found a task to run
thisTaskN = save_tn; // save task number
thisTaskP = &myTasks[save_tn]; // save pointer to task struct
thisTaskP->sch_count=0; // clear sch_count of task
// ( (void (*)(uint8_t *)) address_to_call )(uint8_t *);
// read address of task stored in program memory
// typecast as a function pointer with no return value, and passing a uint8_t pointer
// then call that function, with the task goto_label as a parameter
( (void (*)(uint8_t *)) pgm_read_word(&taskAddress[save_tn].addr) ) (thisTaskP->goto_label);
}
//---------------------------------------------------------------------------------------------------
// no task was found rtr
//---------------------------------------------------------------------------------------------------
//else{
// can put to sleep here if needed, as no tasks were found ready to run
// and the only thing now that can start a task is an interrupt
// after wakeup, continue, and check tasks status again
//}
} //for
} //void
/*-----------------------------------------------------------------------------------------------------------
disable task, load wait value in myTasks struct
-----------------------------------------------------------------------------------------------------------*/
void __wait(uint8_t nTicks){
thisTaskP->status &= ~RTR_ON; // turn off task ready-to-run bit
thisTaskP->ticks = nTicks; // store tick value into task ticks variable
}
/*-----------------------------------------------------------------------------------------------------------
if sema number in use, suspend task and store sema number in task status
return 1 if sema was available, return 0 if not
also bump up priority of semaphore owner if another higher priority task also wants that semaphore
-----------------------------------------------------------------------------------------------------------*/
#if (SEMAPHORES_ON)
uint8_t __getSema(uint8_t n){
if((n == 0) || (n >= nSemas)){ // make sure a valid sema number is passed
__osError(ERR__getSema,n); // not a valid sema number
return 0; // keep compiler happy
}
else if(semaOwner[n] == thisTaskN){ // if trying to get the same sema it already owns
return 1; // just return 1
}
else if(semaOwner[n] == 0xFF){ // if available
semaOwner[n] = thisTaskN; // put task number in semaOwner
return 1; // available, return 1
}
else{ // not available
thisTaskP->status &= ~RTR_ON; // suspend this task
thisTaskP->status |= n; // set sema number in this task that wanted it
if(__get_priority(thisTaskN) < __get_priority(semaOwner[n])){ // if this task has higher priority
__set_priority(semaOwner[n],__get_priority(thisTaskN)); // bump up owner priority
}
return 0; // not available
}
}
#endif
/*-----------------------------------------------------------------------------------------------------------
clear sema bits from task, then check if any other tasks have that sema number, set highest
priority task with the sema number ready to run
-----------------------------------------------------------------------------------------------------------*/
#if (SEMAPHORES_ON)
void __releaseSema(uint8_t n){
uint8_t i; // temp counter
uint8_t this_pri; // priority of task i
uint8_t this_cnt; // sch_count of task i
uint8_t save_tn=0; // highest priotiy task number found wanting semaphore
uint8_t save_cnt=0; // sch_count of highest priority task number foun wanting semaphore
uint8_t highestPriority=8; // highest priority found, any task will be higher priority than 8
if((n==0) || (n>=nSemas)){ // make sure a valid sema number is passed
__osError(ERR__releaseSema,n); // not a valid sema number
}
else if(semaOwner[n] != thisTaskN){ // only sema owner can release semaphore
__osError(ERR__releaseSemaTN,n); // non-owner tried to release semaphore
}
else{
__restore_priority(semaOwner[n]); // restore priority
semaOwner[n] = 0xFF; // clear owner from sema
for(i = 0; i < nTasks; i++){ // find other tasks wanting this semaphore
this_pri = myTasks[i].status; // get status byte
if((this_pri & SEMA_BITS) == n){ // if sema number matches this sema
this_pri = (this_pri >> 4) & 0x07; // get priority
this_cnt = myTasks[i].sch_count; // get sch_count of task
if(this_pri < highestPriority){ // if higher priority task
highestPriority = this_pri; // save priority number
save_tn = i; // then save task number
save_cnt = this_cnt; // save sch_count
}
else if(this_pri == highestPriority){ // if same priority
if(this_cnt > save_cnt){ // check if was waiting longer
save_tn = i; // yes, then save task number
save_cnt = this_cnt; // and save sch_count
}
}
}
}
if(highestPriority != 8){ // found a task to set rtr
myTasks[save_tn].status |= RTR_ON; // enable the task
myTasks[save_tn].status &= ~SEMA_BITS; // clear sema bits in task
semaOwner[n] = save_tn; // set sema owner to task number
}
}
}
#endif
/*-----------------------------------------------------------------------------------------------------------
___ _ _ _____ ___ ___ ___ _ _ ___ _____ ___
|_ _| \| |_ _| __| _ \ _ \ | | | _ \_ _/ __|
| || .` | | | | _|| / / |_| | _/ | | \__ \
|___|_|\_| |_| |___|_|_\_|_\\___/|_| |_| |___/
-----------------------------------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------------------------------
TIMER0 INTERRUPT'S
-------------------------------------------------------------------------------------------------------------
timer0 overflows every 256 ticks (with prescale=8, cpu freq/8/100= timer ticks per 10ms)
when timer0_acc >= cpu freq/800, enable compareA irq (flag is already set)
the 'splitting' of the timer0 routines is done to keep the overflow irq time to a minumum, since this will
be run more often (irq runs faster because of less push/pop of registers)
-----------------------------------------------------------------------------------------------------------*/
ISR(TIMER0_OVF_vect){ // Timer0 overflows every 256 timer ticks
timer0_acc += 256; // add timer ticks
if(timer0_acc >= Timer0_tp10ms){ // if acumulated ticks >= timer ticks per 10ms
TIMSK0 |= (1<<OCIE0A); // enable compareA irq
}
}
/*-----------------------------------------------------------------------------------------------------------
timer0 compareA irq will run every ~10ms, enabled by the overflow irq
the compare irq is disabled, and timer ticks per 10ms is subtracted from timer0_acc
the time between compareA irq's will be 'about' 10ms, but the accumulated error will average to 0
-----------------------------------------------------------------------------------------------------------*/
ISR(TIMER0_COMPA_vect){ // timer0 overflow enables this irq every ~10ms
uint8_t i; // loop counter
TIMSK0 &= ~(1<<OCIE0A); // disable compareA irq
timer0_acc -= Timer0_tp10ms; // subtract timer ticks per 10ms
for (i = 0; i < nTasks; i++){ // go through each task
if (myTasks[i].ticks){ // if tick value not 0 for a task
if (--myTasks[i].ticks==0){ // decrement and check again
myTasks[i].status |= RTR_ON; // now is 0, so set it ready-to-run again
}
}
}
}
/*===========================================================================================================
__ __ _ ___ _ _
| \/ | /_\ |_ _| \| |
| |\/| |/ _ \ | || .` |
|_| |_/_/ \_\___|_|\_|
===========================================================================================================*/
int main(void){
// make sure wdt disabled, even if not used
MCUSR = 0; // clear reset flags (important on newer avr's)
wdt_disable(); // disable watchdog timer
/*-----------------------------------------------------------------------------------------------------------
initialize user stuff- ports,io registers, etc
-----------------------------------------------------------------------------------------------------------*/
init_mystuff(); // in 4AvrOS_Tasks.c
/*-----------------------------------------------------------------------------------------------------------
initialize semaOwner array to 0xFF
thisTaskN is used, and will be 0 when done, semaOwner[0] will not be set (not used)
-----------------------------------------------------------------------------------------------------------*/
#if (SEMAPHORES_ON)
thisTaskN=nSemas;
while(--thisTaskN){
semaOwner[thisTaskN]=0xFF;
}
#endif
/*-----------------------------------------------------------------------------------------------------------
Initialize timer0 with prescale value, turn on timer0 irq
-----------------------------------------------------------------------------------------------------------*/
Timer0_Control = Timer0_Prescale;
Timer0_Irq_Mask |= (1<<TOIE0);
/*-----------------------------------------------------------------------------------------------------------
initialize myTasks[]
-----------------------------------------------------------------------------------------------------------*/
thisTaskN=nTasks;
do{
thisTaskN--;
myTasks[thisTaskN].status = pgm_read_byte(&taskAddress[thisTaskN].init);
}while(thisTaskN);
/*-----------------------------------------------------------------------------------------------------------
turn on interrupts, start scheduler (never returns)
-----------------------------------------------------------------------------------------------------------*/
sei();
__schedule();
return 0; // keep compiler happy (should never get here)
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -