<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          基于鏈表管理的單片機(jī)輪詢程序框架

          共 14119字,需瀏覽 29分鐘

           ·

          2022-07-04 15:06

              關(guān)注、星標(biāo)公眾號,直達(dá)精彩內(nèi)容

          來源:ERYUESANHI


          大家好,我是肖遙,今天分享單片機(jī)裸機(jī)程序框架的文章。

          1

          總程序架構(gòu)的重要性

          很多人尤其是初學(xué)者在寫代碼的時候往往都是想一點(diǎn)寫一點(diǎn),最開始沒有一個整體的規(guī)劃,導(dǎo)致后面代碼越寫越亂,bug不斷。
          最終代碼跑起來看似沒有問題(有可能也真的沒有問題),但是要加一個功能的時候會浪費(fèi)大量的時間,甚至導(dǎo)致整個代碼的崩潰。
          所以,在一個項(xiàng)目開始的時候多花一些時間在代碼的架構(gòu)設(shè)計(jì)上是十分有必要的。代碼架構(gòu)確定好了之后你會發(fā)現(xiàn)敲代碼的時候會特別快,并且在后期調(diào)試的時候也不會像無頭蒼蠅一樣胡亂找問題。當(dāng)然,調(diào)試也是一門技術(shù)。
          在學(xué)習(xí)實(shí)時操作系統(tǒng)的過程中,發(fā)現(xiàn)實(shí)時操作系統(tǒng)框架與個人的業(yè)務(wù)代碼之間的耦合性就非常低,都是只需要將業(yè)務(wù)代碼通過一定的接口函數(shù)注冊好后就交給操作系統(tǒng)托管了,十分方便。
          但是操作系統(tǒng)的調(diào)度過于復(fù)雜,這里就使用操作系統(tǒng)的思維方式來重構(gòu)這個時間片輪詢框架。實(shí)現(xiàn)該框架的完全解耦,用戶只需要包含頭文件,并且在使用過程中不需要改動已經(jīng)寫好的庫文件。

          2

          參考代碼

          首先來個demo,該demo是使用電腦開兩個線程:一個線程模擬單片機(jī)的定時器中斷產(chǎn)生時間片輪詢個時鐘,另一個線程則模擬主函數(shù)中一直運(yùn)行的時間片輪詢調(diào)度程序。
            1#include <thread>
          2#include <stdio.h>
          3#include <windows.h>
          4#include "timeslice.h"
          5
          6// 創(chuàng)建5個任務(wù)對象
          7TimesilceTaskObj task_1, task_2, task_3, task_4, task_5;
          8
          9// 具體的任務(wù)函數(shù)
          10void task1_hdl()
          11{
          12    printf(">> task 1 is running ...\n");
          13}
          14
          15void task2_hdl()
          16{
          17    printf(">> task 2 is running ...\n");
          18}
          19
          20void task3_hdl()
          21{
          22    printf(">> task 3 is running ...\n");
          23}
          24
          25void task4_hdl()
          26{
          27    printf(">> task 4 is running ...\n");
          28}
          29
          30void task5_hdl()
          31{
          32    printf(">> task 5 is running ...\n");
          33}
          34
          35// 初始化任務(wù)對象,并且將任務(wù)添加到時間片輪詢調(diào)度中
          36void task_init()
          37{
          38    timeslice_task_init(&task_1, task1_hdl, 110);
          39    timeslice_task_init(&task_2, task2_hdl, 220);
          40    timeslice_task_init(&task_3, task3_hdl, 330);
          41    timeslice_task_init(&task_4, task4_hdl, 440);
          42    timeslice_task_init(&task_5, task5_hdl, 550);
          43    timeslice_task_add(&task_1);
          44    timeslice_task_add(&task_2);
          45    timeslice_task_add(&task_3);
          46    timeslice_task_add(&task_4);
          47    timeslice_task_add(&task_5);
          48}
          49
          50
          51// 開兩個線程模擬在單片機(jī)上的運(yùn)行過程
          52void timeslice_exec_thread()
          53{
          54    while (true)
          55    {
          56        timeslice_exec();
          57    }
          58}
          59
          60void timeslice_tick_thread()
          61{
          62    while (true)
          63    {
          64        timeslice_tick();
          65        Sleep(10);
          66    }
          67}
          68
          69int main()
          70{
          71    task_init();
          72
          73    printf(">> task num: %d\n", timeslice_get_task_num());
          74    printf(">> task len: %d\n", timeslice_get_task_timeslice_len(&task_3));
          75
          76    timeslice_task_del(&task_2);
          77    printf(">> delet task 2\n");
          78    printf(">> task 2 is exist: %d\n", timeslice_task_isexist(&task_2));
          79
          80    printf(">> task num: %d\n", timeslice_get_task_num());
          81
          82    timeslice_task_del(&task_5);
          83    printf(">> delet task 5\n");
          84
          85    printf(">> task num: %d\n", timeslice_get_task_num());
          86
          87    printf(">> task 3 is exist: %d\n", timeslice_task_isexist(&task_3));
          88    timeslice_task_add(&task_2);
          89    printf(">> add task 2\n");
          90    printf(">> task 2 is exist: %d\n", timeslice_task_isexist(&task_2));
          91
          92    timeslice_task_add(&task_5);
          93    printf(">> add task 5\n");
          94
          95    printf(">> task num: %d\n", timeslice_get_task_num());
          96
          97    printf("\n\n========timeslice running===========\n");
          98
          99    std::thread thread_1(timeslice_exec_thread);
          100    std::thread thread_2(timeslice_tick_thread);
          101
          102    thread_1.join();
          103    thread_2.join();
          104
          105
          106    return 0;
          107}


          運(yùn)行結(jié)果如下:

          由以上例子可見,這個框架使用十分方便,甚至可以完全不知道其原理,僅僅通過幾個簡單的接口就可以迅速創(chuàng)建任務(wù)并加入到時間片輪詢的框架中,十分好用。

          3

          時間片輪詢架構(gòu)

          其實(shí)該部分主要使用了面向?qū)ο蟮乃季S,使用結(jié)構(gòu)體作為對象,并使用結(jié)構(gòu)體指針作為參數(shù)傳遞,這樣作可以節(jié)省資源,并且有著極高的運(yùn)行效率。

          其中最難的部分是侵入式鏈表的使用,這種鏈表在一些操作系統(tǒng)內(nèi)核中使用十分廣泛,這里是參考RT-Thread實(shí)時操作系統(tǒng)中的侵入式鏈表實(shí)現(xiàn)。
          h文件:
           1#ifndef _TIMESLICE_H
          2#define _TIMESLICE_H
          3
          4#include "./list.h"
          5
          6typedef enum {
          7    TASK_STOP,
          8    TASK_RUN
          9} IsTaskRun;
          10
          11typedef struct timesilce
          12{
          13    unsigned int id;
          14    void (*task_hdl)(void);
          15    IsTaskRun is_run;
          16    unsigned int timer;
          17    unsigned int timeslice_len;
          18    ListObj timeslice_task_list;
          19} TimesilceTaskObj;
          20
          21void timeslice_exec(void);
          22void timeslice_tick(void);
          23void timeslice_task_init(TimesilceTaskObj* obj, void (*task_hdl)(void), unsigned int id, unsigned int timeslice_len);
          24void timeslice_task_add(TimesilceTaskObj* obj);
          25void timeslice_task_del(TimesilceTaskObj* obj);
          26unsigned int timeslice_get_task_timeslice_len(TimesilceTaskObj* obj);
          27unsigned int timeslice_get_task_num(void);
          28unsigned char timeslice_task_isexist(TimesilceTaskObj* obj);
          29
          30#endif
          .c文件:
           1#include "./timeslice.h"
          2
          3static LIST_HEAD(timeslice_task_list);
          4
          5void timeslice_exec()
          6{
          7    ListObj* node;
          8    TimesilceTaskObj* task;
          9
          10    list_for_each(node, &timeslice_task_list)
          11    {
          12
          13        task = list_entry(node, TimesilceTaskObj, timeslice_task_list);
          14        if (task->is_run == TASK_RUN)
          15        {
          16            task->task_hdl();
          17            task->is_run = TASK_STOP;
          18        }
          19    }
          20}
          21
          22void timeslice_tick()
          23{
          24    ListObj* node;
          25    TimesilceTaskObj* task;
          26
          27    list_for_each(node, &timeslice_task_list)
          28    {
          29        task = list_entry(node, TimesilceTaskObj, timeslice_task_list);
          30        if (task->timer != 0)
          31        {
          32            task->timer--;
          33            if (task->timer == 0)
          34            {
          35                task->is_run = TASK_RUN;
          36                task->timer = task->timeslice_len;
          37            }
          38        }
          39    }
          40}
          41
          42unsigned int timeslice_get_task_num()
          43{
          44    return list_len(&timeslice_task_list);
          45}
          46
          47void timeslice_task_init(TimesilceTaskObj* obj, void (*task_hdl)(void), unsigned int id, unsigned int timeslice_len)
          48{
          49    obj->id = id;
          50    obj->is_run = TASK_STOP;
          51    obj->task_hdl = task_hdl;
          52    obj->timer = timeslice_len;
          53    obj->timeslice_len = timeslice_len;
          54}
          55
          56void timeslice_task_add(TimesilceTaskObj* obj)
          57{
          58    list_insert_before(&timeslice_task_list, &obj->timeslice_task_list);
          59}
          60
          61void timeslice_task_del(TimesilceTaskObj* obj)
          62{
          63    if (timeslice_task_isexist(obj))
          64        list_remove(&obj->timeslice_task_list);
          65    else
          66        return;
          67}
          68
          69
          70unsigned char timeslice_task_isexist(TimesilceTaskObj* obj)
          71{
          72    unsigned char isexist = 0;
          73    ListObj* node;
          74    TimesilceTaskObj* task;
          75
          76    list_for_each(node, &timeslice_task_list)
          77    {
          78        task = list_entry(node, TimesilceTaskObj, timeslice_task_list);
          79        if (obj->id == task->id)
          80            isexist = 1;
          81    }
          82
          83    return isexist;
          84}
          85
          86unsigned int timeslice_get_task_timeslice_len(TimesilceTaskObj* obj)
          87{
          88    return obj->timeslice_len;
          89}

          4

          底層侵入式雙向鏈表

          該鏈表是linux內(nèi)核中使用十分廣泛,也十分經(jīng)典,其原理具體可以參考文章:

          https://www.cnblogs.com/skywang12345/p/3562146.html
          .h文件:
           1#ifndef _LIST_H
          2#define _LIST_H
          3
          4#define offset_of(type, member)             (unsigned long) &((type*)0)->member
          5#define container_of(ptr, type, member)     ((type *)((char *)(ptr) - offset_of(type, member)))
          6
          7typedef struct list_structure
          8{
          9    struct list_structure* next;
          10    struct list_structure* prev;
          11} ListObj;
          12
          13#define LIST_HEAD_INIT(name)    {&(name), &(name)}
          14#define LIST_HEAD(name)         ListObj name = LIST_HEAD_INIT(name)
          15
          16void list_init(ListObj* list);
          17void list_insert_after(ListObj* list, ListObj* node);
          18void list_insert_before(ListObj* list, ListObj* node);
          19void list_remove(ListObj* node);
          20int list_isempty(const ListObj* list);
          21unsigned int list_len(const ListObj* list);
          22
          23#define list_entry(node, type, member) \
          24    container_of(node, type, member)
          25
          26#define list_for_each(pos, head) \
          27    for (pos = (head)->next; pos != (head); pos = pos->next)
          28
          29#define list_for_each_safe(pos, n, head) \
          30  for (pos = (head)->next, n = pos->next; pos != (head); \
          31    pos = n, n = pos->next)
          32
          33#endif
          .c文件:

          1#include "list.h"
          2
          3void list_init(ListObj* list)
          4{
          5    list->next = list->prev = list;
          6}
          7
          8void list_insert_after(ListObj* list, ListObj* node)
          9{
          10    list->next->prev = node;
          11    node->next = list->next;
          12
          13    list->next = node;
          14    node->prev = list;
          15}
          16
          17void list_insert_before(ListObj* list, ListObj* node)
          18{
          19    list->prev->next = node;
          20    node->prev = list->prev;
          21
          22    list->prev = node;
          23    node->next = list;
          24}
          25
          26void list_remove(ListObj* node)
          27{
          28    node->next->prev = node->prev;
          29    node->prev->next = node->next;
          30
          31    node->next = node->prev = node;
          32}
          33
          34int list_isempty(const ListObj* list)
          35{
          36    return list->next == list;
          37}
          38
          39unsigned int list_len(const ListObj* list)
          40{
          41    unsigned int len = 0;
          42    const ListObj* p = list;
          43    while (p->next != list)
          44    {
          45        p = p->next;
          46        len++;
          47    }
          48
          49    return len;
          50}

          到此,一個全新的,完全解耦的,十分方便易用時間片輪詢框架完成。

          版權(quán)聲明:本文來源網(wǎng)絡(luò),免費(fèi)傳達(dá)知識,版權(quán)歸原作者所有。如涉及作品版權(quán)問題,請聯(lián)系我進(jìn)行刪除。

          ????????????????  END  ???????????????

          關(guān)注我的微信公眾號,回復(fù)“加群”按規(guī)則加入技術(shù)交流群。


          點(diǎn)擊“閱讀原文”查看更多分享,歡迎點(diǎn)分享、收藏、點(diǎn)贊、在看。

          瀏覽 56
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产黄色视频观看 | 免费在线黄色成人网站 | 黑人巨大精品A片一区二区七区 | 清清草在线视频 | 婷婷五月中文字幕 |