|
2011年12月2日。开始学习RT-Thread的第三天。
前两天花了点时间重构了RT-Thread的目录结构。
目录结构见:
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=5247738&bbs_page_no=1&bbs_id=3066
下面就开始学习创建线程。
RT-Thread的线程分为静态线程和动态线程。
要使用动态线程。必须在 rtconfig.h 中宏定义 RT_USING_HEAP,使能堆。
顾名思义,
静态线程的内存地址分配都必须事先定下来,不能进行回收分配。使用 rt_thread_init 对线程进行初始化操作。
动态线程使用 rt_thread_cteate 创建而来,需要由RT-Thread向堆中申请一片内存。当线程删除时 rt thread delete, 系统会回收该片内存。
静态线程不会有创建失败的可能性,在系统上电对其进行初始化后,其内存范围就确定且不可更改了。
动态线程在创建时,较为费时,而且可能由于堆用完等原因创建失败。其优点是RAM资源可回收再利用。
因此,结合我自己的理解,对线程使用的观点是:
重要的线程,以及一直使用的线程,可使用静态线程。
次要的线程,偶尔被使用的线程,可使用动态线程。
线程的几个状态时实时操作系统的基础,不做过多解释
1. 运行状态:当前线程正在使用CPU
2. 就绪状态:线程可以被运行,只是由于有优先级更高的线程正在占用CPU。当此线程成为最高优先级时,就进入运行态
3. 挂起状态:线程被挂起/阻塞,不会被运行。
4. 初始状态:线程初始化,或被删除的一个状态。
状态间的转换图:
![](http://cache.amobbs.com/bbs_upload782111/files_48/ourdev_700946ECC2YP.png)
线程状态的转换图 (原文件名:无标题.png)
第一个范例:跑马灯。
此范例将用到函数:
rt_thread_init // 初始化一个静态线程
rt_thread_create// 创建一个动态线程
rt_thread_delay // 任务延时
一、在stm32f10x_conf.h文件中,配置LED灯的硬件IO口,如果是火牛板,如下:
/// LED硬件配置
#define LED_LEVEL 1 ///< 0, 低电平点亮LED. 1, 高电平点亮LED
#define LED_NUM 4 ///< 设置LED的数量, 该驱动最多允许16个LED灯.
#if (LED_NUM > 16)
#error "LED_NUM define error!"
#endif
#define LED0_PIN GPIO_Pin_8 ///< 设置该LED的PIN口
#define LED0_PORT GPIOD ///< 设置该LED的PORT口
#define LED0_CLK RCC_APB2Periph_GPIOD ///< 设置该LED的时钟模块
#define LED1_PIN GPIO_Pin_9
#define LED1_PORT GPIOD
#define LED1_CLK RCC_APB2Periph_GPIOD
#define LED2_PIN GPIO_Pin_10
#define LED2_PORT GPIOD
#define LED2_CLK RCC_APB2Periph_GPIOD
#define LED3_PIN GPIO_Pin_11
#define LED3_PORT GPIOD
#define LED3_CLK RCC_APB2Periph_GPIOD
typedef enum
{
LED1 = 0, // 4个LED灯的名字
LED2 = 1,
LED3 = 2,
LED4 = 3,
} ledName_t;
二、在application.c文件中写一个线程
static void LedApp(void* parameter)
{
while(1)
{
LedOn(LED1);
// 其本质是rt_thread_delay();
// 为了代码兼容性(我的底层驱动延时都是用的DelayMs函数),
// 用DelayMs函数调用了rt_thread_delay()
DelayMs(500);
LedOn(LED2);
DelayMs(500);
LedOn(LED3);
DelayMs(500);
LedOn(LED4);
DelayMs(500);
LedOff(LED1);
DelayMs(500);
LedOff(LED2);
DelayMs(500);
LedOff(LED3);
DelayMs(500);
LedOff(LED4);
DelayMs(500);
}
}
三、创建或初始化跑马灯线程
//使用静态线程, 需要预留好栈
static uint8_t ledThreadStack[512]; // 跑马灯线程用到的栈
static struct rt_thread ledThread; // 跑马灯线程TCB控制块
void LedAppInit(void)
{
//////静态线程初始化使用 _init函数
//// rt_thread_init(&ledThread,
//// "LedApp", // 线程名称
//// LedApp, RT_NULL, // 线程函数及入口参数
//// ledThreadStack, // 线程栈地址
//// sizeof(ledThreadStack),// 线程栈大小
//// 25, // 线程优先级
//// 8); // 同优先级时的轮询时间片
////
//// rt_thread_startup(&ledThread); // 进入就绪态
//动态线程创建使用 _create函数
rt_thread_t thread;
thread = rt_thread_create(
"led1", // 线程名称
LedApp, RT_NULL, // 线程函数及入口参数
512, // 要动态分配的线程栈大小
20, // 线程优先级
5 ); // 同优先级时的轮询时间片
if (thread != RT_NULL) rt_thread_startup(thread); // 进入就绪态
else assert_param(0); // 创建失败则报错
}
四、在main.c文件中
在HardwareInit()函数中
调用 LedInitAll(); 初始化所有的LED灯
在ApplicationInit()函数中
调用 LedAppInit(); 完成线程的初始化或创建
五、编译和下载,就能看到跑马灯了。
STM32_RTThread 跑马灯ourdev_700974RCJJT7.rar(文件大小:3.26M) (原文件名:STM32_RTThread_V100.rar) |
阿莫论坛20周年了!感谢大家的支持与爱护!!
知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
|