5.1原因
线程延时是浪费CPU资源,受否可以考虑延时的时候放弃CPU使用权,这样就充分利用了CPU的资源。
如果线程进入阻塞状态,没有其他线程运行,是否可以运行一个空闲线程来做一些内存的清理等系统工作呢:
5.2 实现
5.2.1 定义空闲线程的栈
src中定义idle.c
#include <rtthread.h>
#include <rthw.h>
extern rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];
#define IDLE_THREAD_STACK_SIZE 512
ALIGN(RT_ALIGN_SIZE)
static rt_uint8_t rt_thread_stack[IDLE_THREAD_STACK_SIZE];
5.2.2 定义空闲线程的线程控制块
struct rt_thread idle;
5.2.3 定义空闲线程函数
rt_ubase_t rt_idletask_ctr = 0;
void rt_thread_idle_entry(void *parameter)
{
parameter = parameter;
while(1)
{
rt_idletask_ctr++;
}
}
5.2.4 空闲线程初始化
oid rt_thread_idle_init(void)
{
rt_thread_init(&idle,"idle",rt_thread_idle_entry,RT_NULL,&rt_thread_stack[0],sizeof(rt_thread_stack),RT_THREAD_PRIORITY_MAX - 1);
rt_list_insert_before(&(rt_thread_priority_table[RT_THREAD_PRIORITY_MAX-1]),&(idle.tlist));
}
5.3 实现阻塞延时
5.3.1 thread.c中
void rt_thread_delay(rt_tick_t tick)
{
struct rt_thread *thread;
thread = rt_current_thread;
thread->remaining_tick = tick;
rt_schedule();
}
5.3.2 struct thread中
添加 rt_ubase_t remaining_tick;成员
5.3.3 schedule.c
/* 系统调度 */
void rt_schedule(void)
{
struct rt_thread *to_thread;
struct rt_thread *from_thread;
if(rt_current_thread == &idle)
{
if(rt_flag1_thread.remaining_tick == 0)
{
from_thread = rt_current_thread;
to_thread = &rt_flag1_thread;
rt_current_thread = to_thread;
}
else if(rt_flag2_thread.remaining_tick == 0)
{
from_thread = rt_current_thread;
to_thread = &rt_flag2_thread;
rt_current_thread = to_thread;
}
else
{
return ;
}
}
else
{
if(rt_current_thread == &rt_flag1_thread)
{
if(rt_flag2_thread.remaining_tick == 0)
{
from_thread = rt_current_thread;
to_thread = &rt_flag2_thread;
rt_current_thread = to_thread;
}
else if(rt_current_thread->remaining_tick == 0)
{
from_thread = rt_current_thread;
to_thread = &idle;
rt_current_thread = to_thread;
}
else
{
return;
}
}
else if(rt_current_thread == &rt_flag2_thread)
{
if(rt_flag1_thread.remaining_tick == 0)
{
from_thread = rt_current_thread;
to_thread = &rt_flag1_thread;
rt_current_thread = to_thread;
}
else if(rt_current_thread->remaining_tick == 0)
{
from_thread = rt_current_thread;
to_thread = &idle;
rt_current_thread = to_thread;
}
else
{
return;
}
}
}
rt_hw_context_switch((rt_uint32_t)&from_thread->sp,(rt_uint32_t)&to_thread->sp);
/* 产生上下文切换 */
}
5.3.4 main.c中添加systick
void __attribute__((interrupt)) _SysTick_exception (void)
{
rt_interrupt_enter();
rt_tick_increase();
rt_interrupt_leave();
}
void SysTick_Config(uint32_t Reload)
{
SYSTICK_Cmd (FALSE);
SYSTICK_Reload_Config(Reload);
SYSTICK_Counter_Updata(); //向ST_CV寄存器写任意值,以清零当前值寄存器
SYSTICK_Clock_Config(SYSTICK_SYS_CLOCK_DIV_1); //系统节拍定时器时钟源选择,SCLK作为时钟源
SYSTICK_Systick_INT_Enable(TRUE);
SYSTICK_Cmd(TRUE);
INT_Interrupt_Enable(INT_SysTick,TRUE); //使能SYSTICK中断
INT_All_Enable (TRUE);
}
5.3.5 系统时基更新函数
clock.c
#include <rtthread.h>
#include <rthw.h>
#include "debug.h"
static rt_tick_t rt_tick = 0;
extern rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];
void rt_tick_increase(void)
{
rt_ubase_t i;
struct rt_thread *thread;
rt_tick++;
for(i = 0;i < RT_THREAD_PRIORITY_MAX;i++)
{
thread = rt_list_entry(rt_thread_priority_table[i].next,struct rt_thread,tlist);
if(thread->remaining_tick > 0)
{
thread->remaining_tick--;
}
rt_schedule();
}
}
5.3.6 中断函数
irq.c文章来源:https://www.toymoban.com/news/detail-735097.html
#include <rthw.h>
#include <rtthread.h>
volatile rt_uint8_t rt_interrupt_nest;
void rt_interrupt_enter(void)
{
rt_base_t level;
// RT_DEBUG_LOG(RT_DEBUG_IRQ, ("irq coming..., irq nest:%d\n",
// rt_interrupt_nest));
level = rt_hw_interrupt_disable();
rt_interrupt_nest ++;
//RT_OBJECT_HOOK_CALL(rt_interrupt_enter_hook,());
rt_hw_interrupt_enable(level);
}
/**
* This function will be invoked by BSP, when leave interrupt service routine
*
* @note please don't invoke this routine in application
*
* @see rt_interrupt_enter
*/
void rt_interrupt_leave(void)
{
rt_base_t level;
// RT_DEBUG_LOG(RT_DEBUG_IRQ, ("irq leave, irq nest:%d\n",
// rt_interrupt_nest));
level = rt_hw_interrupt_disable();
rt_interrupt_nest --;
// RT_OBJECT_HOOK_CALL(rt_interrupt_leave_hook,());
rt_hw_interrupt_enable(level);
}
5.4 案例
main.c文章来源地址https://www.toymoban.com/news/detail-735097.html
rt_hw_interrupt_disable();
SysTick_Config(SystemCoreClock/RT_TICK_PER_SECOND);
void flag1_thread_entry( void *p_arg )
{
for( ;; )
{
P_DBG("flag1 thread\n");
flag2 = 1;
P_DBG("flag1 thread will dela1\n");
rt_thread_delay(10);
flag2 = 0;
P_DBG("flag1 thread will dela2\n");
rt_thread_delay(10);
}
}
/* 线程2 */
void flag2_thread_entry( void *p_arg )
{
for( ;; )
{
P_DBG("flag2 thread\n");
flag2 = 1;
rt_thread_delay(2);
flag2 = 0;
P_DBG("flag2 thread will dela1\n");
rt_thread_delay(2);
}
}
到了这里,关于Rt-Thread 移植5--空闲线程和线程阻塞(KF32)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!