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

📄 4avros.c

📁 4avrOS realtime OS for AVR
💻 C
📖 第 1 页 / 共 3 页
字号:



    /*-----------------------------------------------------------------------------------------------------------
         ___ _   _ _  _  ___ _____ ___ ___  _  _     ___ ___  ___ _____ ___ _______   _____ ___ ___
        | __| | | | \| |/ __|_   _|_ _/ _ \| \| |   | _ \ _ \/ _ \_   _/ _ \_   _\ \ / / _ \ __/ __|
        | _|| |_| | .` | (__  | |  | | (_) | .` |   |  _/   / (_) || || (_) || |  \ 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 + -