火牛板学习RT-Thread Step by Step——第二篇:跑马灯,动态线程及静态线程
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; // 跑马灯线程用到的栈
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) 不错,支持 占位学习 马甲 这个必须学习,必须顶! 不错! 好,mark 这个ok.f教程太好了, 支持一下。。 支持! 楼主 设置为100表示10ms, 设置为1000表示1ms. 这个不明白。请说下。 ******************************************************************************
* @brief系统嘀嗒时钟初始化为RT-Thread配置的周期. 其中断处理函数见"rt_hw_timer_handler.c".
* 参考RT_TICK_PER_SECOND. 设置为100表示10ms, 设置为1000表示1ms.// 1s=1000=1000ms 100
* @paramNone
* @retval None
******************************************************************************
*/
void SysTickInit(void)
{
RCC_ClocksTypeDef rcc_clocks;
uint32_t cnts;
RCC_GetClocksFreq(&rcc_clocks); //获取外接晶振
cnts = (rt_uint32_t)rcc_clocks.HCLK_Frequency / RT_TICK_PER_SECOND; // msRT_TICK_PER_SECOND= 1000, 1ms sytick 中断一次72000 &0xFFFFFF
SysTick_Config(cnts);
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
}
/**
******************************************************************************
* @brief毫秒延时函数
* @paramtime, 要延时的毫秒时间. 误差为最小系统嘀嗒时钟. 该函数不允许在中断中使用!
* 例如, 系统嘀嗒时钟为10ms, 则使用DelayMs(1), 也将延时10ms.
* @retval None
******************************************************************************
*/
void Delay_ms(uint32_t time)
{
uint32_t base, tdly;
base = 1000 / RT_TICK_PER_SECOND; // 获取基值
tdly = time / base; // 获取系统延时时间
if (time % base) tdly++; // 有余数, 延时取大值
rt_thread_delay(tdly);
} 100 应该是 1s RT_TICK_PER_SECOND
设置的是每秒有多少个系统节拍。设为100就是:每秒有100个系统节拍。
那系统节拍时间就是 1000ms/100 = 10ms 系列教程,支持! 回复【楼主位】draapho
-----------------------------------------------------------------------
跟着楼主学习,很好的东西~ mark,支持一下 谢谢分享引导入门,但是附件下不了 写得不错, 继续学习,支持
页:
[1]