RT-Thread 内核学习 >> (四)跑马灯线程实例

线程状态切换

在这里插入图片描述
在系统运行时,同一时间只允许有一个线程在运行

从运行过程划分,RT-Thread 中的线程分为5种状态:

  1. 初始状态
  2. 就绪状态
  3. 运行状态
  4. 挂起状态
  5. 关闭状态

初始状态

当调用rt_thread_create()rt_thread_init() 创建了动态线程或静态线程时,此时线程状态即处于初始状态。

即刚创建完成的线程,还没有开始运行就是处于初始状态。

就绪状态

当创建完成的线程调用rt_thread_startup() 后就处于就绪状态。

当处于挂起状态的线程在某种条件下也可以转变为就绪状态。

运行状态

处于就绪状态的线程按照优先级顺序排队等待执行,当处理器让出运行资源时,此时依照优先级顺序开始运行的线程即处于运行状态。

一旦处于运行状态的线程运行完毕,让出处理器资源时,处理器就会马上寻找优先级最高的处于就绪状态的线程。

挂起状态

处于运行状态的线程当需要等待共享资源,或者自身主动延续一段时间,又或是处于就绪状态的线程调用rt_thread_suspend() ,该线程即处于挂起状态。

挂起状态又称为阻塞状态。

关闭状态

处于运行状态的线程调用rt_thread_exit() 或处于挂起状态的线程调用rt_thread_delete()rt_thread_detach(),该线程即可进入关闭状态。

还有一种情况是当一个线程顺序执行,执行完最后一个事务,退出运行。此时也能进入关闭状态。


RT-Thread 的运行就是各个线程的不停循环,其更多地处于就绪状态、运行状态和关闭状态3种状态。

系统滴答时钟

  1. 每一个操作系统都存在一个“系统心跳”时钟,是操作系统中最小的时钟单位。这个时钟负责系统和时间相关的一些操作。作为操作系统运行的时间尺度,心跳时钟是由硬件定时器的定时中断产生;
  2. 系统的心跳时钟我们也常称之为系统滴答或时钟节拍,系统滴答的频率需要我们根据CPU 的处理能力来决定;
  3. 时钟节拍使得内核可以将线程延时若干个整数时钟节拍,以及线程等待事件发生时,提供等待超时的依据;
  4. 频率越快,内核函数介入系统运行的几率就越大,内核占用的处理器时间就越长,系统的负荷就变大;频率越小,时间处理精度又不够;
  5. 我们在stm32 平台上一般设置系统滴答频率为100Hz,即每个滴答的时间是10ms。

GPIO 驱动框架操作IO

IO 初始化

void rt_pin_mode(rt_base_t pin, rt_base_t mode)
参数 说明
pin 需要进行配置的引脚号
mode 需要配置的模式
static const struct pin_index pins[] =
{
	......
	/* PE7 的引脚号为38 */
    __STM32_PIN(38, E, 7),      // PE7 :  LED_R        --> LED
    ......
};

/* 能配置的模式只有5种 */
#define PIN_MODE_OUTPUT         0x00
#define PIN_MODE_INPUT          0x01
#define PIN_MODE_INPUT_PULLUP   0x02
#define PIN_MODE_INPUT_PULLDOWN 0x03
#define PIN_MODE_OUTPUT_OD      0x04


int main(void)
{
	rt_pin_mode(38, PIN_MODE_OUTPUT);
}

IO 写入

void rt_pin_write(rt_base_t pin, rt_base_t value)
参数 说明
pin 需要进行写入的引脚号
value 写入高电平或低电平
#define PIN_LOW                 0x00
#define PIN_HIGH                0x01

int main(void)
{
	rt_pin_write(38, PIN_HIGH);
}

IO 读出

int rt_pin_read(rt_base_t pin)
参数 说明
pin 需要进行读取的引脚号

线程栈大小分配

先将线程栈大小设置一个固定值(如2048),在线程运行时通过查看线程栈的使用情况,了解线程栈使用的实际情况,根据情况设置合理的栈大小。
在这里插入图片描述

一般将线程栈最大使用量设置为70%

跑马灯编程

创建动态线程:

Created with Raphaël 2.2.0 编写线程代码 创建线程 运行线程

示例代码:

#define LED_R    38
#define LED_G    39
#define LED_B    40

/* 线程led的入口函数 */
static void led_entry(void *parameter)
{
	rt_pin_mode(LED_R, PIN_MODE_OUTPUT);
	rt_pin_mode(LED_G, PIN_MODE_OUTPUT);
	rt_pin_mode(LED_B, PIN_MODE_OUTPUT);
	
    while (1)
    {
    	rt_pin_write(LED_R, PIN_HIGH);
    	/* 当线程内部进行延时时,线程处于挂起状态 */
    	rt_thread_delay(50); /* 若系统滴答设置为100Hz,则该处延时为500ms */
    	                     /* 也可写作rt_thread_mdelay(500) 或rt_thread_sleep(50) */
    	rt_pin_write(LED_R, PIN_LOW);
    	
    	rt_pin_write(LED_G, PIN_HIGH);
    	rt_thread_delay(50); 
    	rt_pin_write(LED_G, PIN_LOW);    
    		
    	rt_pin_write(LED_B, PIN_HIGH);
    	rt_thread_delay(50); 
    	rt_pin_write(LED_B, PIN_LOW);		
    }
}


void led_test(void)
{
	rt_thread_t tid;
	
    /* 创建线程1,名称是led,入口是led_entry,输入参数是NULL,线程栈大小512字节,优先级10,时间片参数10*/
    /* rt_thread_create 函数返回值为一个线程控制块的指针 */
    tid = rt_thread_create("led",
                            led_entry, RT_NULL,
                            512,
                            10, 10);

    /* 如果获得线程控制块,启动这个线程 */
    if (tid != RT_NULL)
        rt_thread_startup(tid); 
}

int main(void)
{
	led_test();
	return 0;
}

创建静态线程:

Created with Raphaël 2.2.0 创建线程堆 创建线程控制块 编写线程代码 创建线程 运行线程
static char thread2_stack[512];
static struct rt_thread thread2;


void led_entry(void)
{
	rt_pin_mode(LED_R, PIN_MODE_OUTPUT);
	rt_pin_mode(LED_G, PIN_MODE_OUTPUT);
	rt_pin_mode(LED_B, PIN_MODE_OUTPUT);
	
    while (1)
    {
    	rt_pin_write(LED_R, PIN_HIGH);
    	/* 当线程内部进行延时时,线程处于挂起状态 */
    	rt_thread_delay(50); /* 若系统滴答设置为100Hz,则该处延时为500ms */
    	                     /* 也可写作rt_thread_mdelay(500) 或rt_thread_sleep(50) */
    	rt_pin_write(LED_R, PIN_LOW);
    	
    	rt_pin_write(LED_G, PIN_HIGH);
    	rt_thread_delay(50); 
    	rt_pin_write(LED_G, PIN_LOW);    
    		
    	rt_pin_write(LED_B, PIN_HIGH);
    	rt_thread_delay(50); 
    	rt_pin_write(LED_B, PIN_LOW);		
    }

}

void led_test(void)
{
	/* 线程控制块地址为指向线程控制块指针thread2 的地址,线程名称为led,入口是led_entry,输入参数是NULL,线程堆地址是数组thread2_stack  起始地址,线程栈大小512字节,优先级9,时间片参数10*/
    rt_thread_init(&thread2,
                   "led",
                   led_entry,
                   RT_NULL,
                   &thread2_stack[0],
                   512,
                   9, 10);
                   
    rt_thread_startup(&thread2);
}

int main(void)
{
	led_test();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_40973138/article/details/89052230