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

📄 4avros.c

📁 4avrOS realtime OS for AVR
💻 C
📖 第 1 页 / 共 3 页
字号:
            } //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 + -