线程状态切换
在系统运行时,同一时间只允许有一个线程在运行
从运行过程划分,RT-Thread 中的线程分为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种状态。
系统滴答时钟
- 每一个操作系统都存在一个“系统心跳”时钟,是操作系统中最小的时钟单位。这个时钟负责系统和时间相关的一些操作。作为操作系统运行的时间尺度,心跳时钟是由硬件定时器的定时中断产生;
- 系统的心跳时钟我们也常称之为系统滴答或时钟节拍,系统滴答的频率需要我们根据CPU 的处理能力来决定;
- 时钟节拍使得内核可以将线程延时若干个整数时钟节拍,以及线程等待事件发生时,提供等待超时的依据;
- 频率越快,内核函数介入系统运行的几率就越大,内核占用的处理器时间就越长,系统的负荷就变大;频率越小,时间处理精度又不够;
- 我们在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%
跑马灯编程
创建动态线程:
示例代码:
#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;
}
创建静态线程:
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;
}