この記事では、[WildfireEmbedFire]「RTスレッドカーネルの実装とアプリケーション開発-STM32に基づく」について説明します。これは個人的な学習ノートとしてのみ使用されます。詳細な内容と手順については、元のテキストを確認してください(Wildfire Data Download Centerからダウンロードできます)。
動的メモリスペース
前のセクションの静的スレッドのスレッドスペースは静的配列であり、各静的スレッドのスペースは事前に定義する必要があります。動的スレッドで使用されるスタックおよびスレッド制御ブロックは、スレッドの作成時にRT-Threadによって動的に割り当てられ、事前定義されたグローバル変数ではありません。
では、スレッドの動的空間はどこから来るのでしょうか?
RT-Threadは、システムの動的メモリ割り当て機能のためにSRAMに大きな配列を定義します。これらのコードはboard.c
最初、内容は次のとおりです。
#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
/*
* Please modify RT_HEAP_SIZE if you enable RT_USING_HEAP
* the RT_HEAP_SIZE max value = (sram size - ZI size), 2048 means 2048*4 bytes
*/
#define RT_HEAP_SIZE 2048
static uint32_t rt_heap[RT_HEAP_SIZE];
RT_WEAK void *rt_heap_begin_get(void)
{
return rt_heap;
}
RT_WEAK void *rt_heap_end_get(void)
{
return rt_heap + RT_HEAP_SIZE;
}
#endif
/**
* This function will initial your board.
*/
void rt_hw_board_init(void)
{
/* ...省略部分代码 */
#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get());
#endif
}
上記の3つの関数の機能は、ヒープの開始アドレスを取得し、ヒープの終了アドレスを取得し、システムヒープスペースを初期化することです。動的ヒープを有効にするには、次の設定も必要rtconfig.h
です。
スレッド制御ブロックポインタを定義する
rt_thread_t
スレッド制御ブロック構造のポインタ型ですrt_thread
。動的スレッドは、スレッド作成機能を介してスレッド制御ブロックを取得する必要があります。
// 定义线程控制块指针
static rt_thread_t led0_thread = RT_NULL;
スレッド関数を定義する
スレッド機能は、スレッドの機能コードであるスレッドエントリ機能です。スレッドは連続して実行する必要があるため、追加する必要がありますwhile(1)
。次のスレッド機能によって実装される機能は、LED0が500ms間隔で点滅することです。
/******************************************************************************
* @ 函数名 : led0_thread_entry
* @ 功 能 : LED0线程入口函数
* @ 参 数 : parameter 外部传入的参数
* @ 返回值 : 无
******************************************************************************/
static void led0_thread_entry(void *parameter)
{
while(1)
{
LED0(ON);
rt_thread_delay(500); // 500个tick(500ms)
LED0(OFF);
rt_thread_delay(500);
}
}
スレッドを作成する
静的スレッドとの違いrt_thread_init()
は、動的スレッドはrt_thread_create()
関数を使用してスレッドを作成することです。2つの関数名は異なり、特定のパラメーターも異なります。
// 创建一个动态线程
led0_thread = // 线程控制块指针
rt_thread_create("led0", // 线程名字
led0_thread_entry, // 线程入口函数
RT_NULL, // 入口函数参数
255, // 线程栈大小
5, // 线程优先级
10); // 线程时间片
スレッドの優先度については、必ずrtconfig.h
指定範囲内の数値を入力してください(システム移植の際は、最大スレッド優先度を8に設定します)。スレッド初期化時に優先度を大きく設定しすぎると、スレッドは動作しません。
スレッドを開始
スレッドが初期化された後、スレッドは初期状態(RT_THREAD_INIT)のみになります。スレッドを準備完了状態(RT_THREAD_READY)にするには、rt_thread_startup()
関数を使用する必要があります。スレッド制御ブロックポインタは動的に取得されるため、スレッドをスケジュールする前に、動的スレッドが正常に作成されているかどうかを確認する必要があります。
// 开启线程调度
if(led0_thread != RT_NULL)
rt_thread_startup(led0_thread);
else
return -1;
実験効果
完全なコード
すべての動的スレッド関連関数をmain.cに配置しました。次のコードには、基になるドライバーコード(LEDの初期化など)は含まれていません。
#include "board.h"
#include "rtthread.h"
// 定义线程控制块指针
static rt_thread_t led0_thread = RT_NULL;
/******************************************************************************
* @ 函数名 : led0_thread_entry
* @ 功 能 : LED0线程入口函数
* @ 参 数 : parameter 外部传入的参数
* @ 返回值 : 无
******************************************************************************/
static void led0_thread_entry(void *parameter)
{
while(1)
{
LED0(ON);
rt_thread_delay(500); // 500个tick(500ms)
LED0(OFF);
rt_thread_delay(500);
}
}
int main(void)
{
// 硬件初始化和RTT的初始化已经在component.c中的rtthread_startup()完成
// 创建一个动态线程
led0_thread = // 线程控制块指针
rt_thread_create("led0", // 线程名字
led0_thread_entry, // 线程入口函数
RT_NULL, // 入口函数参数
255, // 线程栈大小
5, // 线程优先级
10); // 线程时间片
// 开启线程调度
if(led0_thread != RT_NULL)
rt_thread_startup(led0_thread);
else
return -1;
}