创建单线程—SRAM 动态内存(学习笔记)

本文参考自[野火EmbedFire]《RT-Thread内核实现与应用开发实战——基于STM32》,仅作为个人学习笔记。更详细的内容和步骤请查看原文(可到野火资料下载中心下载)

动态内存空间

上一节静态线程的线程空间为一个静态数组,每个静态线程的空间都需要提前定义好大小。而动态线程的使用的栈和线程控制块是在创建线程的时候 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
}

上面三个函数的功能分别是获取堆的起始地址,获取堆的结束地址以及初始化系统堆空间。要使能动态堆,还需要在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()函数来创建一个线程,两者的函数名不一样,具体的形参也有区别。

// 创建一个动态线程
	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;
							
}

猜你喜欢

转载自blog.csdn.net/weixin_43772810/article/details/123643333