【RT-thread studio 下使用STM32F103-學習sem-信號量-初步使用-線程之間控制-基礎樣例】
- 1、前言
- 2、環境
- 3、事項了解
- (1)了解sem概念-了解官網消息
- (2)根據自己理解,設計幾個使用方式
- (3)不建議運行中,反復刪除,在運行線程。
- 4、實驗過程
- 實驗說明
- 1、第一部分實驗
- (1)實驗說明-創建工程
- (2)編寫代碼
- (3)驗證結果
- 2、第二部分實驗
- (1)實驗說明
- (2)編寫代碼
- (3)驗證結果
- 3、第三部分實驗
- (1)實驗說明
- (2)編寫代碼
- (3)驗證結果
- 5、代碼鏈接
- 6、細節部分
- 1、dome 文件報錯
- 7、總結
1、前言
最近,在使用rt-thread的時候,想要用一個線程控制另一個線程的暫停與運行,
但看資料的時候,發現刪除線程和重啟線程的時候,好像不太理想,這么弄是容易出現問題的,但通過信號量的方式,比較好,所以這次咱們一起來學習下sem。
自己也從新手的角度,一點點學習。整個rt-thread 還是挺大的,不是深耕多年,很難面面聚到,不過用那學哪里。
2、環境
3、事項了解
(1)了解sem概念-了解官網消息
大概看了一遍整個資料,還是挺多的,當你想要使用的時候,其實多少還是有些摸不到頭腦的。
但既然要使用Rt-thread的,官方的文檔還是要讀一下。
鏈接:https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/ipc1/ipc1?id=%e4%bf%a1%e5%8f%b7%e9%87%8f
(2)根據自己理解,設計幾個使用方式
我們使用某種RT-thread帶有的功能,是為了解決我們自己出現的問題。
設計實驗1:
通過使用sem信號量,當一個線程先運行后,再運行另一個線程。這樣其實就是讓線程之間形成先后關系,適合一定是某個線程完成后,在運行另一個線程。
設計實驗2:
通過使用sem信號量,用一個線程,或者一個變量,控制或者暫停另一個線程。這樣其實就是有個主線程,或不一定是主線程,可以控制其他線程運行。
以上都是小的功能模塊,但是大的項目,都是小模塊一點點搭建起來,這算是其中一個磚塊,使用的時候,根據自己情況再調整下。
(3)不建議運行中,反復刪除,在運行線程。
在看網上資料是,看到有說到,其實不建議反復掛起或刪除創建線程,很容易出現問題。
當時看到了資料忘記去哪里,不過本片將有關sem信號量的。
4、實驗過程
實驗說明
1、第一部分實驗
萬事皆有要基礎,一步一個腳印,如果環境不能使用的話,后續代碼都是無用的,所以第一步是要搭建一個可以運行的程序。自己這塊沒注意,認為軟件裝好后,隨便創建一個工程,就可以運行,沒想到卡了一下。
(1)實驗說明-創建工程
(2)編寫代碼
以下內容,RT-Thread Studio工具會自動生成的。
int main(void)
{int count = 1;while (count++){LOG_D("Hello RT-Thread!");rt_thread_mdelay(1000);}return RT_EOK;
}
(3)驗證結果
這塊其實遇到一個內存相關報錯,更細節部分可以看細節說明部分。
上述問題解決后,然后連接硬件代碼,進行下載驗證。
2、第二部分實驗
(1)實驗說明
此部分,主要是讓一個線程先運行,運行完畢,再運行了另一個線程。在現實應用中,很多情況下,都是需要的,并且有實際意義的。
舉個例子,現實中,有很多測溫需求,溫度過高過低,都需要做些事情,相當觸發異常,這個時候,溫度異常,必須先出現,才做后面事情,可以用這樣邏輯解決。
(2)編寫代碼
/** Copyright (c) 2006-2024, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date Author Notes* 2024-06-21 RT-Thread first version*/#include <rtthread.h>#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>//第一步
//#include <rtthread.h>static rt_sem_t sem; // 信號量//第二步
void sem1_init(void)
{// 創建一個信號量,初始值為 0sem = rt_sem_create("sem", 0, RT_IPC_FLAG_FIFO);if (sem == RT_NULL){rt_kprintf("create semaphore failed.\n");}
}
//第三步
void thread1_entry(void *parameter)
{while (1){// 嘗試獲取信號量,如果信號量值為 0,則線程將被阻塞rt_sem_take(sem, RT_WAITING_FOREVER);rt_kprintf("Thread 1 is running.\n");rt_thread_mdelay(1000); // 模擬線程工作}
}
//第四步
void thread2_entry(void *parameter)
{while (1){rt_thread_mdelay(3000); // 等待 3 秒rt_kprintf("Thread 2 releases semaphore.\n");rt_sem_release(sem); // 釋放信號量}
}int main(void)
{int count = 1;//第五步 應用sem1_init();// 創建線程 1rt_thread_t tid1 = rt_thread_create("thread1",thread1_entry, RT_NULL,1024, 10, 10);if (tid1 != RT_NULL)rt_thread_startup(tid1);// 創建線程 2rt_thread_t tid2 = rt_thread_create("thread2",thread2_entry, RT_NULL,1024, 10, 10);if (tid2 != RT_NULL)rt_thread_startup(tid2);while (count++){//LOG_D("Hello RT-Thread!");rt_thread_mdelay(1000);}return RT_EOK;
}
(3)驗證結果
如下為具體實驗驗證,必須是線程2運行完,才會運行線程1,是按照順序運行。
3、第三部分實驗
(1)實驗說明
這種情況,更為復雜些,需要一個線程控制另一個線程,雖然實現方式很多,不一定非要使用這種,但是工具給你準備好了,使不使用看自己,并且是實現比較簡單,實際項目,根據自己需求使用。
(2)編寫代碼
簡單講解下,本實驗中,主要是根據a的值,來決定是否運行線程1。
/** Copyright (c) 2006-2024, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date Author Notes* 2024-06-21 RT-Thread first version*/#include <rtthread.h>#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>//第一步
static rt_sem_t sem; // 信號量
volatile int a = 0; // 控制變量//第二步
void sem_init(void)
{// 創建一個信號量,初始值為 0sem = rt_sem_create("sem", 0, RT_IPC_FLAG_FIFO);if (sem == RT_NULL){rt_kprintf("create semaphore failed.\n");}
}
//第三步
void thread1_entry(void *parameter)
{while (1){// 嘗試獲取信號量,如果信號量值為 0,則線程將被阻塞rt_sem_take(sem, RT_WAITING_FOREVER);rt_kprintf("Thread 1 is running.\n");rt_thread_mdelay(1000); // 模擬線程工作}
}
//第四步
void thread2_entry(void *parameter)
{while (1){rt_thread_mdelay(1000); // 每秒檢查一次變量 a 的值if (a == 1){// 如果 a == 1,則釋放信號量,允許線程 1 運行if (rt_sem_release(sem) == RT_EOK){rt_kprintf("Thread 2 releases semaphore.\n");}}else{// 如果 a == 0,則確保信號量不會釋放,線程 1 將被暫停rt_kprintf("Thread 2: a is 0, thread 1 will pause.\n");}}
}void set_a(int value)
{a = value;rt_kprintf("Variable a set to %d\n", a);
}int main(void)
{int count = 1;// 初始化信號量sem_init();// 創建線程 1rt_thread_t tid1 = rt_thread_create("thread1",thread1_entry, RT_NULL,1024, 10, 10);if (tid1 != RT_NULL)rt_thread_startup(tid1);// 創建線程 2rt_thread_t tid2 = rt_thread_create("thread2",thread2_entry, RT_NULL,1024, 10, 10);if (tid2 != RT_NULL)rt_thread_startup(tid2);while (count++){set_a(0);rt_thread_mdelay(10000);set_a(1);//LOG_D("Hello RT-Thread!");rt_thread_mdelay(10000);}return RT_EOK;
}
(3)驗證結果
5、代碼鏈接
代碼鏈接:https://download.csdn.net/download/qq_22146161/89466496
6、細節部分
1、dome 文件報錯
7、總結
一個磚一個磚,壘起來。