日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

rtthread

發布時間:2024/3/26 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 rtthread 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

鏈表

初始化雙向鏈表

rt_inline void rt_list_init(rt_list_t *l) {l->next = l->prev = l; }

插入

rt_inline void rt_list_insert_after(rt_list_t *l, rt_list_t *n) {l->next->prev = n;n->next = l->next;l->next = n;n->prev = l; }


在NODE1后面插入節點n,可以理解為:NODE3的前一個結點為n,n的后一個節點為NODE3,NODE3即l->next

刪除

rt_inline void rt_list_remove(rt_list_t *n) {n->next->prev = n->prev;n->prev->next = n->next;n->next = n->prev = n; }

就緒列表

就是一個rt_list_t類型的數組。

/* 線程就緒列表 */ rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];

每個線程控制塊都有一個成員tlist,類型為rt_list_t.我們將線程插入到就緒列表里面,就是通過將線程控制塊的 tlist 這個節點插入到就緒列表中來實現的。

/* 初始化線程 */ rt_thread_init( &rt_flag1_thread, /* 線程控制塊 */flag1_thread_entry, /* 線程入口地址 */RT_NULL, /* 線程形參 */&rt_flag1_thread_stack[0], /* 線程棧起始地址 */sizeof(rt_flag1_thread_stack) ); /* 線程棧大小,單位為字節 */ /* 將線程插入到就緒列表 */ rt_list_insert_before( &(rt_thread_priority_table[0]),&(rt_flag1_thread.tlist) );

系統調度初始化

/*** @ingroup SystemInit* This function will initialize the system scheduler*/ void rt_system_scheduler_init(void) {register rt_base_t offset;/* 線程就緒列表初始化 */for (offset = 0; offset < RT_THREAD_PRIORITY_MAX; offset ++){rt_list_init(&rt_thread_priority_table[offset]);}/* 初始化當前線程控制塊指針 */rt_current_thread = RT_NULL; }

此時的鏈表為空

啟動調度器

/*** @ingroup SystemInit* This function will startup scheduler. It will select one thread* with the highest priority level, then switch to it.*/ void rt_system_scheduler_start(void) {register struct rt_thread *to_thread;register rt_ubase_t highest_ready_priority;#if RT_THREAD_PRIORITY_MAX > 32register rt_ubase_t number;number = __rt_ffs(rt_thread_ready_priority_group) - 1;highest_ready_priority = (number << 3) + __rt_ffs(rt_thread_ready_table[number]) - 1; #elsehighest_ready_priority = __rt_ffs(rt_thread_ready_priority_group) - 1; #endif/* get switch to thread */to_thread = rt_list_entry(rt_thread_priority_table[highest_ready_priority].next,struct rt_thread,tlist);rt_current_thread = to_thread;/* switch to new thread */rt_hw_context_switch_to((rt_uint32_t)&to_thread->sp);/* never come back */ }

臨界段保護

PRIMASK寄存器

這個寄存器只有一個位,置1后,將關閉所有可屏蔽中斷的異常,只剩NMI和硬fault,默認值為0

;/* ; * rt_base_t rt_hw_interrupt_disable(); ; */ rt_hw_interrupt_disable PROCEXPORT rt_hw_interrupt_disableMRS r0, PRIMASKCPSID IBX LRENDP;/* ; * void rt_hw_interrupt_enable(rt_base_t level); ; */ rt_hw_interrupt_enable PROCEXPORT rt_hw_interrupt_enableMSR PRIMASK, r0BX LRENDP

為什么不直接這樣寫?

;/* ; * void rt_hw_interrupt_disable(); ; */ rt_hw_interrupt_disable PROC EXPORT rt_hw_interrupt_disable CPSID I BX LR ENDP;/* ; * void rt_hw_interrupt_enable(void); ; */ rt_hw_interrupt_enable PROC EXPORT rt_hw_interrupt_enable CPSIE I BX LR ENDP

避免在嵌套的臨界段失效,如下所示

/* 臨界段代碼 */ {/* 臨界段 1 開始 */rt_hw_interrupt_disable(); /* 關中斷,PRIMASK = 1 */{/* 臨界段 2 */rt_hw_interrupt_disable(); /* 關中斷,PRIMASK = 1 */{}rt_hw_interrupt_enable(); /* 開中斷,PRIMASK = 0 */ //(注意)}/* 這里已經開啟了中斷,而臨界段1還未結束 *//* 臨界段 1 結束 */rt_hw_interrupt_enable(); /* 開中斷,PRIMASK = 0 */ }

正確做法如下:

PRIMASK = 0; /* PRIMASK 初始值為 0,表示沒有關中斷 */ rt_base_t level1; rt_base_t level2;/* 臨界段代碼 */ {/* 臨界段 1 開始 */level1 = rt_hw_interrupt_disable(); /* 關中斷,level1=0,PRIMASK=1 */{/* 臨界段 2 */level2 = rt_hw_interrupt_disable(); /* 關中斷,level2=1,PRIMASK=1 */ {}rt_hw_interrupt_enable(level2); /* 開中斷,level2=1,PRIMASK=1 */}/* 臨界段 1 結束 */rt_hw_interrupt_enable(level1); /* 開中斷,level1=0,PRIMASK=0 */ }

對象

軟件定時器

總結

以上是生活随笔為你收集整理的rtthread的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。