シングルスレッドを作成する-SRAMスタティックメモリ(研究ノート)

この記事では、[WildfireEmbedFire]「RTスレッドカーネルの実装とアプリケーション開発-STM32に基づく」について説明します。これは個人的な学習ノートとしてのみ使用されます。詳細な内容と手順については、元のテキストを確認してください(Wildfire Data Download Centerからダウンロードできます)。

ハードウェアの初期化

この記事ではLED点滅用のスレッドを作成するため、最初にLEDのハードウェア構成を行う必要があります。使用する開発ボードはPunctual Atomic STM32F103ZET6コアボードで、それぞれPB5とPE5に対応する2つのLEDがあります。bspファイルLEDのは次のとおりです:
bsp_led。h

#ifndef __BSP_LED_H
#define __BSP_LED_H

#include "stm32f10x.h"

#define LED0_GPIO_PIN              GPIO_Pin_5
#define LED0_GPIO_PORT             GPIOB
#define LED0_GPIO_CLK              RCC_APB2Periph_GPIOB


#define LED1_GPIO_PIN              GPIO_Pin_5
#define LED1_GPIO_PORT             GPIOE
#define LED1_GPIO_CLK              RCC_APB2Periph_GPIOE

#define    ON        1
#define    OFF       0

// \  C语言里面叫续行符,后面不能有任何的东西

#define   LED0(a)   if(a) \
	                       GPIO_ResetBits(LED0_GPIO_PORT, LED0_GPIO_PIN); \
                     else  GPIO_SetBits(LED0_GPIO_PORT, LED0_GPIO_PIN);


#define   LED1(a)   if(a) \
	                       GPIO_ResetBits(LED1_GPIO_PORT, LED1_GPIO_PIN); \
                     else  GPIO_SetBits(LED1_GPIO_PORT, LED1_GPIO_PIN);

// ^ 异或,C语言的一个二进制的运算符
// 与1异或改变,与0异或不变

#define LED0_TOGGLE        {LED0_GPIO_PORT->ODR ^= LED0_GPIO_PIN;}
#define LED1_TOGGLE        {LED1_GPIO_PORT->ODR ^= LED1_GPIO_PIN;}

void LED_GPIO_Config(void);

#endif /* __BSP_LED_H */


bsp_led.c

// bsp :board support package 板级支持包
#include "bsp_led.h"

void LED_GPIO_Config(void)
{
    
    
	GPIO_InitTypeDef  GPIO_InitStruct;
	
	RCC_APB2PeriphClockCmd(LED0_GPIO_CLK, ENABLE);
	RCC_APB2PeriphClockCmd(LED1_GPIO_CLK, ENABLE);
	
	// LED0
	GPIO_InitStruct.GPIO_Pin = LED0_GPIO_PIN;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIO_Init(LED0_GPIO_PORT, &GPIO_InitStruct);

	// 默认拉高
	GPIO_SetBits(LED0_GPIO_PORT, LED0_GPIO_PIN);
	
	// LED1
	GPIO_InitStruct.GPIO_Pin = LED1_GPIO_PIN;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStruct);
	
	// 默认拉高
	GPIO_SetBits(LED1_GPIO_PORT, LED1_GPIO_PIN);
}

ledの基礎となるドライバーを記述した後、それは関数に追加LED_GPIO_Config()れます。board.crt_hw_board_init()

void rt_hw_board_init(void)
{
    
    
#if 0
    /* TODO: OS Tick Configuration */
    _SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);
#endif
	
	/* 初始化 SysTick */
	SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);

	/* 硬件 BSP 初始化统统放在这里,比如 LED,串口,LCD 等 */
	
	// LED初始化
	LED_GPIO_Config();
	
	// 测试
	//LED0(1);
	//LED1(1);

    /* Call components board initial (use INIT_BOARD_EXPORT()) */
#ifdef RT_USING_COMPONENTS_INIT
    rt_components_board_init();
#endif

#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
    rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get());
#endif
}

スレッドスタックを定義する

今回作成したスレッドは静的スレッドであるため、独自のスタックスペースがあります。

// 线程栈需要 RT_ALIGN_SIZE 个字节对齐
ALIGN(RT_ALIGN_SIZE)

// 定义线程栈
static rt_uint8_t rt_led0_thread_stack[1024];

ほとんどのシステムでは、スタックスペースアドレスのアラインメントが必要であり、ARMアーキテクチャでは、4バイトアドレスにアラインメントする必要があります。RT_ALIGN_SIZEはのrtconfig.hマクロです。

スレッド制御ブロックを定義する

スレッド制御ブロックは、スレッドのすべての情報を格納する構造であり、通常はスレッドのIDカードと呼ばれます。

// 定义线程控制块
static struct rt_thread led0_thread;

スレッド関数を定義する

スレッド機能は、スレッドの機能コードであるスレッドエントリ機能です。スレッドは連続して実行する必要があるため、追加する必要がありますwhile(1)。次のスレッド機能によって実装される機能は、LED0が500ms間隔で点滅することです。

/******************************************************************************
* @ 函数名  : led0_thread_entry
* @ 功  能  : LED0线程入口函数
* @ 参  数  : parameter 外部传入的参数
* @ 返回值  : 无
******************************************************************************/
static void led0_thread_entry(void *parameter)
{
    
    
	while(1)
	{
    
    
		LED0(1);
		rt_thread_delay(500); // 500个tick(500ms)
		LED0(0);
		rt_thread_delay(500);
	}
}

スレッドを初期化します

静的スレッドの3つの要素は、スレッドエントリ関数スレッドスタック、およびスレッド制御ブロックrt_thread_init()です。3つを接続して動作するスレッドにするために、関数を使用する必要があります。

	// 初始化一个静态线程
	rt_thread_init(&led0_thread,                  // 线程控制块
					"led0",                       // 线程名字
	                led0_thread_entry,            // 线程入口函数
	                RT_NULL,                      // 入口函数参数
	                &rt_led0_thread_stack[0],     // 线程栈起始地址
					sizeof(rt_led0_thread_stack), // 线程栈大小
				    5,                            // 线程优先级
					10);                          // 线程时间片
							

スレッドの優先度については、必ずrtconfig.h指定範囲内の数値を入力してください(昨日システムを移植したときは、最大スレッド優先度を8に設定しました)。スレッド初期化時に優先度を高く設定しすぎると、スレッドは機能しません。

ここに画像の説明を挿入

スレッドを開始

スレッドが初期化された後、スレッドは初期状態(RT_THREAD_INIT)のみになります。スレッドを準備完了状態(RT_THREAD_READY)にするには、rt_thread_startup()関数を使用する必要があります。

	// 开启线程调度
	rt_thread_startup(&led0_thread);
							

実験効果

画像の説明を追加してください

完全なコード

静的スレッドに関連するすべての関数をmain.cに配置しました。次のコードには、基になるドライバーコードは含まれていません。

#include "board.h"
#include "rtthread.h"

// 线程栈需要 RT_ALIGN_SIZE 个字节对齐
ALIGN(RT_ALIGN_SIZE)

// 定义线程栈
static rt_uint8_t rt_led0_thread_stack[1024];

// 定义线程控制块
static struct rt_thread led0_thread;

/******************************************************************************
* @ 函数名  : led0_thread_entry
* @ 功  能  : LED0线程入口函数
* @ 参  数  : parameter 外部传入的参数
* @ 返回值  : 无
******************************************************************************/
static void led0_thread_entry(void *parameter)
{
    
    
	while(1)
	{
    
    
		LED0(1);
		rt_thread_delay(500); // 500个tick(500ms)
		LED0(0);
		rt_thread_delay(500);
	}
}

int main(void)
{
    
    
	// 硬件初始化和RTT的初始化已经在component.c中的rtthread_startup()完成
	
	// 初始化一个静态线程
	rt_thread_init(&led0_thread,                  // 线程控制块
					"led0",                       // 线程名字
	                led0_thread_entry,            // 线程入口函数
	                RT_NULL,                      // 入口函数参数
	                &rt_led0_thread_stack[0],     // 线程栈起始地址
					sizeof(rt_led0_thread_stack), // 线程栈大小
				    5,                            // 线程优先级
					10);                          // 线程时间片
	
	// 开启线程调度
	rt_thread_startup(&led0_thread);
							
}


おすすめ

転載: blog.csdn.net/weixin_43772810/article/details/123567499