空闲线程是系统线程中一个比较特殊的线程,它具有最低的优先级,当系统中无其他线程可运行时,调度器将调度到空闲线程。空闲线程通常是一个死循环,永远不被挂起。RT-Thread实时操作系统为空闲线程提供了钩子函数(钩子函数:用户提供的一段代码,在系统运行的某一路径上设置一个钩子,当系统经过这个位置时,转而执行这个钩子函数,然后再返回到它的正常路径上),可以让系统在空闲的时候执行一些特定的任务,例如系统运行指示灯闪烁,电源管理等。除了调用钩子函数,RT-Thread也把线程清理(rt_thread->cleanup回调函数)函数、真正的线程删除动作放到了空闲线程中(在脱离或删除线程时,仅改变线程的状态为关闭状态不再参与系统调度)。

空闲线程函数接口:(在src/idle.c中定义)

空闲线程初始化:
/*** @ingroup SystemInit** This function will initialize idle thread, then start it.** @note this function must be invoked when system init.*/
void rt_thread_idle_init(void)
{/* initialize thread */rt_thread_init(&idle,"tidle",rt_thread_idle_entry,      //空闲线程入口函数RT_NULL,                   //入口函数参数为空&rt_thread_stack[0],       //空闲线程栈地址sizeof(rt_thread_stack),   //栈大小,默认为128字节,若使用钩子函数或动态堆时为256字节,在idle.c中宏定义RT_THREAD_PRIORITY_MAX - 1,//空闲线程优先级最低32);                       //时间片为32个时钟节拍/* startup */rt_thread_startup(&idle);
}

空闲线程入口函数:
static void rt_thread_idle_entry(void *parameter)
{while (1){#ifdef RT_USING_HOOKif (rt_thread_idle_hook != RT_NULL)rt_thread_idle_hook();//若使用钩子且钩子函数不为空,则执行钩子函数#endifrt_thread_idle_excute();  //空闲线程的真正执行函数
    }
}

空闲线程执行函数:
void rt_thread_idle_excute(void)
{/* Loop until there is no dead thread. So one call to rt_thread_idle_excute* will do all the cleanups. */while (_has_defunct_thread())        //检查僵尸线程链表中是否存在僵尸线程,以前的版本中用if (!rt_list_isempty(&rt_thread_defunct))来判断,这样每次只能清除一个僵尸线程
    {rt_base_t lock;rt_thread_t thread;
#ifdef RT_USING_MODULErt_module_t module = RT_NULL;
#endifRT_DEBUG_NOT_IN_INTERRUPT;      //确保此函数不是在中断服务中,若RT_DEBUG_CONTEXT_CHECK is 1 in rtdebug.h,则该宏表示这个函数不能用于中断ISR中。通过检查rt_interrupt_nest中断嵌套计数器是否为0来判断/* disable interrupt */lock = rt_hw_interrupt_disable();/* re-check whether list is empty */if (_has_defunct_thread())      //再次判断rt_thread_defunct是否为空,若不为空
        {/* get defunct thread */thread = rt_list_entry(rt_thread_defunct.next,struct rt_thread,tlist);          //获取待回收的僵尸线程
#ifdef RT_USING_MODULE/* get thread's parent module */module = (rt_module_t)thread->module_id;//得到模块ID/* if the thread is module's main thread */if (module != RT_NULL && module->module_thread == thread){/* detach module's main thread */module->module_thread = RT_NULL;    //清空模块线程
            }
#endif/* remove defunct thread */rt_list_remove(&(thread->tlist));       //重置线程链表节点为初始值,即节点next与prev均指向自身节点,即将线程从僵尸线程链表中移除  /* invoke thread cleanup */if (thread->cleanup != RT_NULL)thread->cleanup(thread);            //执行线程清理函数 /* if it's a system object, not delete it */if (rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE)//若该僵尸线程内核对象为静态对象,则不删除该对程内核对象
            {/* enable interrupt */rt_hw_interrupt_enable(lock);return;}}else                        //若再次判断rt_thread_defunct僵尸线程链表为空
        {/* enable interrupt */rt_hw_interrupt_enable(lock);/* may the defunct thread list is removed by others, just return */return;}/* enable interrupt */rt_hw_interrupt_enable(lock);#ifdef RT_USING_HEAP                //程序运行到这,说明上文处理的僵尸线程为动态创建的线程
#if defined(RT_USING_MODULE) && defined(RT_USING_SLAB)/* the thread belongs to an application module */if (thread->flags & RT_OBJECT_FLAG_MODULE)rt_module_free((rt_module_t)thread->module_id, thread->stack_addr);//释放模块主线程栈所占内存else
#endif/* release thread's stack */RT_KERNEL_FREE(thread->stack_addr);   //释放动态线程栈所占内存/* delete thread object */rt_object_delete((rt_object_t)thread);//删除动态线程内核对象,即从当前类型的内核对象链表中移除,同时释放内核对象所占空间(若使用了模块功能,还要释放模块ID所占空间)
#endif#ifdef RT_USING_MODULEif (module != RT_NULL){extern rt_err_t rt_module_destroy(rt_module_t module);/* if sub thread list and main thread are all empty */  //若模块主线程为空,且子线程对象链表为空if ((module->module_thread == RT_NULL) &&rt_list_isempty(&module->module_object[RT_Object_Class_Thread].object_list)){module->nref --;}/* destroy module */if (module->nref == 0)rt_module_destroy(module);//销毁模块
        }
#endif}
}

实例应用:

  RT-Thread-v2.0.0移植到STM32及驱动LCD和测温

/*
application.c
2015.12.4 by Huangtao*/#include <board.h>
#include <rtthread.h>#ifdef  RT_USING_COMPONENTS_INIT
#include <components.h>
#endif  /* RT_USING_COMPONENTS_INIT */#ifdef RT_USING_DFS
/* dfs filesystem:ELM filesystem init */
#include <dfs_elm.h>
/* dfs Filesystem APIs */
#include <dfs_fs.h>
#endif#ifdef RT_USING_RTGUI
#include <rtgui/rtgui.h>
#include <rtgui/rtgui_server.h>
#include <rtgui/rtgui_system.h>
#include <rtgui/driver.h>
#include <rtgui/calibration.h>
#endif#include "led.h"
#include "LCD5110.h"
#include "ds18b20.h"// Thread ID
static rt_thread_t led_id = RT_NULL;
static rt_thread_t lcd5110_id = RT_NULL;
static rt_thread_t ds18b20_id = RT_NULL;#define CPU_USAGE_CALC_TICK    10
#define CPU_USAGE_LOOP        100static rt_uint8_t  cpu_usage_major = 0, cpu_usage_minor= 0;
static rt_uint32_t total_count = 0;static void cpu_usage_idle_hook()
{rt_tick_t tick;rt_uint32_t count;volatile rt_uint32_t loop;if (total_count == 0){/* get total count */rt_enter_critical();tick = rt_tick_get();while(rt_tick_get() - tick < CPU_USAGE_CALC_TICK){total_count ++;loop = 0;while (loop < CPU_USAGE_LOOP) loop ++;}rt_exit_critical();}count = 0;/* get CPU usage */tick = rt_tick_get();while (rt_tick_get() - tick < CPU_USAGE_CALC_TICK){count ++;loop  = 0;while (loop < CPU_USAGE_LOOP) loop ++;}/* calculate major and minor */if (count < total_count){count = total_count - count;cpu_usage_major = (count * 100) / total_count;cpu_usage_minor = ((count * 100) % total_count) * 100 / total_count;}else{total_count = count;/* no CPU usage */cpu_usage_major = 0;cpu_usage_minor = 0;}}/*void cpu_usage_get(rt_uint8_t *major, rt_uint8_t *minor)
{RT_ASSERT(major != RT_NULL);RT_ASSERT(minor != RT_NULL);*major = cpu_usage_major;*minor = cpu_usage_minor;
}*/void cpu_usage_init()
{/* set idle thread hook */rt_thread_idle_sethook(cpu_usage_idle_hook);
}/*
// led
ALIGN(RT_ALIGN_SIZE)
static rt_uint8_t led_stack[ 512 ];
static struct rt_thread led_thread;*/
static void led_thread_entry(void* parameter)
{rt_hw_led_init();while (1){/* led1 on */rt_hw_led_on(0);// 顺便清屏
        ClearScreen();rt_thread_delay( 100 ); /* sleep 1 second and switch to other thread *//* led1 off */rt_hw_led_off(0);// 顺便清屏//ClearScreen();
rt_thread_delay( 100 );}
}// lcd5110
static void lcd5110_thread_entry(void* parameter)
{LcdInit();while(1){DispString(15,0,"RT-Thread");DispString(0,1,"CPU:");DispNum(30,1,cpu_usage_major);DispChar(45,1,'%');rt_thread_delay( 5 );}}// ds18b20
static void ds18b20_thread_entry(void* parameter)
{short temperature = 0;while(DS18B20_Init());while(1){DispString(0,3,"Temp: ");temperature = DS18B20_Get_Temp();if(temperature<0){DispChar(40,3,'-');         temperature=-temperature;   }else DispChar(40,3,' '); DispNum(48,3,((u16)temperature)/10);    //显示正数部分    DispChar(60,3,'.');     DispNum(67,3,((u16)temperature)%10);    //显示小数部分
rt_thread_delay( 5 );}}void rt_init_thread_entry(void* parameter)
{
#ifdef RT_USING_COMPONENTS_INIT/* initialization RT-Thread Components */rt_components_init();
#endif#ifdef  RT_USING_FINSHfinsh_set_device(RT_CONSOLE_DEVICE_NAME);
#endif  /* RT_USING_FINSH *//* Filesystem Initialization */
#if defined(RT_USING_DFS) && defined(RT_USING_DFS_ELMFAT)/* mount sd card fat partition 1 as root directory */if (dfs_mount("sd0", "/", "elm", 0, 0) == 0){rt_kprintf("File System initialized!\n");}elsert_kprintf("File System initialzation failed!\n");
#endif  /* RT_USING_DFS */#ifdef RT_USING_RTGUI{extern void rt_hw_lcd_init();extern void rtgui_touch_hw_init(void);rt_device_t lcd;/* init lcd */rt_hw_lcd_init();/* init touch panel */rtgui_touch_hw_init();/* find lcd device */lcd = rt_device_find("lcd");/* set lcd device as rtgui graphic driver */rtgui_graphic_set_device(lcd);#ifndef RT_USING_COMPONENTS_INIT/* init rtgui system server */rtgui_system_server_init();
#endifcalibration_set_restore(cali_setup);calibration_set_after(cali_store);calibration_init();}
#endif /* #ifdef RT_USING_RTGUI */
}int rt_application_init(void)
{rt_thread_t init_thread;/*rt_err_t result;// 静态创建 led 线程 result = rt_thread_init(&led_thread,                // 线程控制块内存地址"led",                      // 线程名称led_thread_entry,           // 线程入口入口函数RT_NULL,                    // 线程入口入口函数参数(rt_uint8_t*)&led_stack[0], // 线程栈起始地址sizeof(led_stack),          // 线程栈大小20,                         // 线程优先级5);                         // 线程时间片大小if (result == RT_EOK){rt_thread_startup(&led_thread);}*/// 动态创建 led 线程led_id = rt_thread_create("led",            // 线程名称led_thread_entry,   // 线程入口入口函数 RT_NULL,            // 线程入口入口函数参数 512,                // 线程栈大小21,                 // 线程优先级10);                // 线程时间片大小// 如果获得线程控制块,启动这个线程if (led_id != RT_NULL) rt_thread_startup(led_id);// 动态创建 lcd5110 线程lcd5110_id = rt_thread_create("lcd5110",        // 线程名称lcd5110_thread_entry,   // 线程入口入口函数 RT_NULL,                // 线程入口入口函数参数 2048,                   // 线程栈大小20,                     // 线程优先级20);                    // 线程时间片大小if (lcd5110_id != RT_NULL) rt_thread_startup(lcd5110_id);// 动态创建 ds18b20 线程ds18b20_id = rt_thread_create("ds18b20",        // 线程名称ds18b20_thread_entry,   // 线程入口入口函数 RT_NULL,                // 线程入口入口函数参数 2048,                   // 线程栈大小19,                     // 线程优先级20);                    // 线程时间片大小if (ds18b20_id != RT_NULL) rt_thread_startup(ds18b20_id);// CPU %
    cpu_usage_init();#if (RT_THREAD_PRIORITY_MAX == 32)init_thread = rt_thread_create("init",rt_init_thread_entry, RT_NULL,2048, 8, 20);
#elseinit_thread = rt_thread_create("init",rt_init_thread_entry, RT_NULL,2048, 80, 20);
#endifif (init_thread != RT_NULL)rt_thread_startup(init_thread);return 0;
}

实例应用2:

/*
application.c
2015.12.4 by Huangtao*/#include <board.h>
#include <rtthread.h>#ifdef  RT_USING_COMPONENTS_INIT
#include <components.h>
#endif  /* RT_USING_COMPONENTS_INIT */#ifdef RT_USING_DFS
/* dfs filesystem:ELM filesystem init */
#include <dfs_elm.h>
/* dfs Filesystem APIs */
#include <dfs_fs.h>
#endif#ifdef RT_USING_RTGUI
#include <rtgui/rtgui.h>
#include <rtgui/rtgui_server.h>
#include <rtgui/rtgui_system.h>
#include <rtgui/driver.h>
#include <rtgui/calibration.h>
#endif// 我加入的
#include "led.h"
#include "LCD5110.h"
#include "ds18b20.h"
#include "usart.h"
#include "TIM3_PWM.h"// Thread ID
static rt_thread_t led_id = RT_NULL;
static rt_thread_t fan_id = RT_NULL;
static rt_thread_t lcd5110_id = RT_NULL;
static rt_thread_t ds18b20_id = RT_NULL;
static rt_thread_t uart2_id = RT_NULL;#define CPU_USAGE_CALC_TICK    10
#define CPU_USAGE_LOOP        100static rt_uint8_t  cpu_usage_major = 0;
//static cpu_usage_minor= 0;
static rt_uint32_t total_count = 0;/*
自定义通信协议:
ledControl:
'L'+0x10----led1 off0x11----led1 on0x20----led2 off0x21----led2 on...
fanControl:
'F'+0xf0----fan off0xf1----speed 10xf2----speed 2...*/
static short temperature = 0;
static char ledControl = 0;
static char fanControl = 0;
// 访问温度的互斥量
static rt_mutex_t mutexTemperature = RT_NULL;
static rt_mutex_t mutexLed = RT_NULL;
static rt_mutex_t mutexFan = RT_NULL;// stm32_usart2发送缓冲区
static char uart_tx_buffer[64] = "\nOpen uart2 OK.\0";
// stm32_usart2接收缓冲区
static char uart_rx_buffer[64];
// USART 接收消息结构
struct rx_msg
{rt_device_t dev;rt_size_t size;
};
// 用于接收消息的消息队列控制块
static rt_mq_t rx_mq;
static struct rt_messagequeue  my_rx_mq;
// 消息队列中用到的放置消息的内存池
static char msg_pool[1024];static void cpu_usage_idle_hook()
{rt_tick_t tick;rt_uint32_t count;volatile rt_uint32_t loop;if (total_count == 0){/* get total count */rt_enter_critical();tick = rt_tick_get();while(rt_tick_get() - tick < CPU_USAGE_CALC_TICK){total_count ++;loop = 0;while (loop < CPU_USAGE_LOOP) loop ++;}rt_exit_critical();}count = 0;/* get CPU usage */tick = rt_tick_get();while (rt_tick_get() - tick < CPU_USAGE_CALC_TICK){count ++;loop  = 0;while (loop < CPU_USAGE_LOOP) loop ++;}/* calculate major and minor */if (count < total_count){count = total_count - count;cpu_usage_major = (count * 100) / total_count;//cpu_usage_minor = ((count * 100) % total_count) * 100 / total_count;
    }else{total_count = count;/* no CPU usage */cpu_usage_major = 0;//cpu_usage_minor = 0;
    }}void cpu_usage_init()
{/* set idle thread hook */rt_thread_idle_sethook(cpu_usage_idle_hook);
}/*
// led
ALIGN(RT_ALIGN_SIZE)
static rt_uint8_t led_stack[ 512 ];
static struct rt_thread led_thread;*/
static void led_thread_entry(void* parameter)
{rt_hw_led_init();while (1){rt_mutex_take(mutexLed, RT_WAITING_FOREVER);if(ledControl == 0x11){// led1 on rt_hw_led_on(0);}else if(ledControl == 0x10){// led1 off rt_hw_led_off(0);}else if(ledControl == 0x21){// led2 on rt_hw_led_on(1);}else if(ledControl == 0x20){// led2 off rt_hw_led_off(1);}rt_mutex_release(mutexLed);// 顺便清屏//ClearScreen();rt_thread_delay( 10 );  }}static void fan_thread_entry(void* parameter)
{short Compare2Num = 0;TIM3_PWM_Init(900,5);    // PWM频率=72000/5/900while(1){rt_mutex_take(mutexFan, RT_WAITING_FOREVER);switch(fanControl){case 0xf0:  Compare2Num=0;    break;    // 关case 0xf1:  Compare2Num=100;  break;    // 1档case 0xf2:  Compare2Num=150;  break;    // 2档case 0xf3:  Compare2Num=200;  break;    // ...case 0xf4:  Compare2Num=250;  break;case 0xf5:  Compare2Num=300;  break;case 0xf6:  Compare2Num=350;  break;case 0xf7:  Compare2Num=400;  break;case 0xf8:  Compare2Num=450;  break;case 0xf9:  Compare2Num=500;  break;case 0xfa:  Compare2Num=600;  break;case 0xfb:  Compare2Num=700;  break;case 0xfc:  Compare2Num=800;  break;case 0xfd:  Compare2Num=900;  break;    // 13档default:  break;}rt_mutex_release(mutexFan);TIM_SetCompare2(TIM3, Compare2Num);rt_thread_delay(10);}
}// lcd5110
static void lcd5110_thread_entry(void* parameter)
{LcdInit();while(1){DispString(15,0,"RT-Thread");DispString(0,1,"CPU:");DispNum(30,1,cpu_usage_major);DispChar(45,1,'%');rt_thread_delay( 5 );}}// ds18b20
static void ds18b20_thread_entry(void* parameter)
{short showTemp;//rt_err_t result;while(DS18B20_Init());while(1){DispString(0,3,"Temp: ");rt_mutex_take(mutexTemperature, RT_WAITING_FOREVER);temperature = DS18B20_Get_Temp();showTemp = temperature;rt_mutex_release(mutexTemperature);if(showTemp<0){DispChar(40,3,'-');         showTemp=-showTemp;   }else DispChar(40,3,' '); DispNum(48,3,((u16)showTemp)/10);    //显示正数部分    DispChar(60,3,'.');     DispNum(67,3,((u16)showTemp)%10);    //显示小数部分
rt_thread_delay( 5 );}}// uart2
//===============================================
// 数据到达回调函数
//  rt_err_t(*)(rt_device_t dev, rt_size_t size)
rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{struct rx_msg msg;msg.dev = dev;msg.size = size;if(size >=2){// 发送消息到消息队列中rt_mq_send(rx_mq, &msg, sizeof(struct rx_msg));}return RT_EOK;
}static void uart2_thread_entry(void* parameter)
{rt_err_t result = RT_EOK;struct rx_msg msg;rt_device_t stm32_uart2;rt_uint32_t rx_length;// 根据注册名查找设备stm32_uart2 = rt_device_find("uart2");if (stm32_uart2 != RT_NULL){// 初始化设备
        rt_device_init(stm32_uart2);// 设置回调函数(当设备接收到数据执行)
        rt_device_set_rx_indicate(stm32_uart2, uart_input);// 打开设备rt_device_open(stm32_uart2, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM);}rt_device_write(stm32_uart2, 0, &uart_tx_buffer[0], 18);while(1){// 从消息队列中读取消息, RT_WAITING_FOREVERresult = rt_mq_recv(rx_mq, &msg, sizeof(struct rx_msg), RT_WAITING_FOREVER);// 成功收到消息if(result == RT_EOK){rx_length = (sizeof(uart_rx_buffer) - 1) > msg.size ?msg.size : sizeof(uart_rx_buffer) - 1;// 读取消息rx_length = rt_device_read(msg.dev, 0, &uart_rx_buffer[0], rx_length);uart_rx_buffer[rx_length] = '\0';// 'F' + fanControlif(uart_rx_buffer[0] == 0x46){rt_mutex_take(mutexFan, RT_WAITING_FOREVER);fanControl = uart_rx_buffer[1];  rt_mutex_release(mutexFan);}// 'L' + ledControlelse if(uart_rx_buffer[0] == 0x4c){rt_mutex_take(mutexLed, RT_WAITING_FOREVER);ledControl = uart_rx_buffer[1];rt_mutex_release(mutexLed);}// 收到'T',则发送温度else if(uart_rx_buffer[0] == 0x54){rt_mutex_take(mutexTemperature, RT_WAITING_FOREVER);uart_tx_buffer[0] = temperature & 0xff;uart_tx_buffer[1] = (temperature >> 8) & 0xff;uart_tx_buffer[2] = '\0';rt_mutex_release(mutexTemperature);rt_device_write(stm32_uart2, 0, &uart_tx_buffer[0], 2);}// 回显观察//rt_device_write(stm32_uart2, 0, &uart_rx_buffer[0], rx_length);
}//rt_thread_delay( 5 );
    }}void rt_init_thread_entry(void* parameter)
{
#ifdef RT_USING_COMPONENTS_INIT/* initialization RT-Thread Components */rt_components_init();
#endif#ifdef  RT_USING_FINSHfinsh_set_device(RT_CONSOLE_DEVICE_NAME);
#endif  /* RT_USING_FINSH *//* Filesystem Initialization */
#if defined(RT_USING_DFS) && defined(RT_USING_DFS_ELMFAT)/* mount sd card fat partition 1 as root directory */if (dfs_mount("sd0", "/", "elm", 0, 0) == 0){rt_kprintf("File System initialized!\n");}elsert_kprintf("File System initialzation failed!\n");
#endif  /* RT_USING_DFS */#ifdef RT_USING_RTGUI{extern void rt_hw_lcd_init();extern void rtgui_touch_hw_init(void);rt_device_t lcd;/* init lcd */rt_hw_lcd_init();/* init touch panel */rtgui_touch_hw_init();/* find lcd device */lcd = rt_device_find("lcd");/* set lcd device as rtgui graphic driver */rtgui_graphic_set_device(lcd);#ifndef RT_USING_COMPONENTS_INIT/* init rtgui system server */rtgui_system_server_init();
#endifcalibration_set_restore(cali_setup);calibration_set_after(cali_store);calibration_init();}
#endif /* #ifdef RT_USING_RTGUI */
}// 创建线程和初始化
//============================================================
int rt_application_init(void)
{rt_thread_t init_thread;// 初始化消息队列rt_mq_init(&my_rx_mq, "mqt", &msg_pool[0], sizeof(struct rx_msg), sizeof(msg_pool), RT_IPC_FLAG_FIFO);rx_mq = &my_rx_mq;// 创建互斥锁mutexTemperature = rt_mutex_create("mutexTemperature", RT_IPC_FLAG_FIFO);if (mutexTemperature == RT_NULL){return 0;}mutexLed = rt_mutex_create("mutexLed", RT_IPC_FLAG_FIFO);if (mutexLed == RT_NULL){return 0;}mutexFan = rt_mutex_create("mutexFan", RT_IPC_FLAG_FIFO);if (mutexFan == RT_NULL){return 0;}/*rt_err_t result;// 静态创建 led 线程 result = rt_thread_init(&led_thread,                // 线程控制块内存地址"led",                      // 线程名称led_thread_entry,           // 线程入口入口函数RT_NULL,                    // 线程入口入口函数参数(rt_uint8_t*)&led_stack[0], // 线程栈起始地址sizeof(led_stack),          // 线程栈大小20,                         // 线程优先级5);                         // 线程时间片大小if (result == RT_EOK){rt_thread_startup(&led_thread);}*/// 动态创建 led 线程led_id = rt_thread_create("led",            // 线程名称led_thread_entry,   // 线程入口入口函数 RT_NULL,            // 线程入口入口函数参数 512,                // 线程栈大小21,                 // 线程优先级10);                // 线程时间片大小// 如果获得线程控制块,启动这个线程if (led_id != RT_NULL) rt_thread_startup(led_id);// 动态创建 fan 线程fan_id = rt_thread_create("fan",            // 线程名称fan_thread_entry,   // 线程入口入口函数 RT_NULL,            // 线程入口入口函数参数 1024,                // 线程栈大小20,                 // 线程优先级10);                // 线程时间片大小// 如果获得线程控制块,启动这个线程if (fan_id != RT_NULL) rt_thread_startup(fan_id);// 动态创建 lcd5110 线程lcd5110_id = rt_thread_create("lcd5110",        // 线程名称lcd5110_thread_entry,   // 线程入口入口函数 RT_NULL,                // 线程入口入口函数参数 512,                   // 线程栈大小20,                     // 线程优先级20);                    // 线程时间片大小if (lcd5110_id != RT_NULL) rt_thread_startup(lcd5110_id);// 动态创建 ds18b20 线程ds18b20_id = rt_thread_create("ds18b20",        // 线程名称ds18b20_thread_entry,   // 线程入口入口函数 RT_NULL,                // 线程入口入口函数参数 1024,                   // 线程栈大小19,                     // 线程优先级20);                    // 线程时间片大小if (ds18b20_id != RT_NULL) rt_thread_startup(ds18b20_id);// 动态创建 usart2 线程uart2_id = rt_thread_create("uart2",            // 线程名称uart2_thread_entry,     // 线程入口入口函数 RT_NULL,                // 线程入口入口函数参数 2048,                   // 线程栈大小19,                     // 线程优先级15);                    // 线程时间片大小if (uart2_id != RT_NULL) rt_thread_startup(uart2_id);// CPU %
    cpu_usage_init();#if (RT_THREAD_PRIORITY_MAX == 32)init_thread = rt_thread_create("init",rt_init_thread_entry, RT_NULL,2048, 8, 20);
#elseinit_thread = rt_thread_create("init",rt_init_thread_entry, RT_NULL,2048, 80, 20);
#endifif (init_thread != RT_NULL)rt_thread_startup(init_thread);return 0;
}

转载于:https://www.cnblogs.com/jiangzhaowei/p/8524692.html

RT-thread内核之空闲线程相关推荐

  1. 从0到1写RT-Thread内核——空闲线程与阻塞延时的实现

    在之前写的另外一篇文章--<从0到1写RT-Thread内核--线程定义及切换的实现>中线程体内的延时使用的是软件延时,即还是让CPU空等来达到延时的效果.RTOS中的延时叫阻塞延时,即线 ...

  2. .NET 线程 Thread 进程 Process、线程池 pool、Invoke、begininvoke、异步回调、APM、EAP、TPL、aysnc、await

    windows系统是一个多线程的操作系统.一个程序至少有一个进程,一个进程至少有一个线程.进程是线程的容器,一个C#客户端程序开始于一个单独的线程,CLR(公共语言运行库)为该进程创建了一个线程,该线 ...

  3. 基于rt thread smart构建EtherCAT主站

    我把源码开源到到了gitee,https://gitee.com/rathon/rt-thread-smart-soem 有兴趣的去可以下载下来跑一下 软件工程推荐用vscode 打开.rt thre ...

  4. 【Java 并发编程】线程池机制 ( 测试线程开销 | 启动线程分析 | 用户态 | 内核态 | 用户线程 | 内核线程 | 轻量级进程 )

    文章目录 一.测试线程开销 1.正常测试 2.不创建线程 3.只创建不启动线程 4.只启动不等待执行完成 二.分析测试结果 1.启动线程分析 2.用户线程与内核线程 3.轻量级进程 4.验证 Java ...

  5. Visual Studio 2013开发 mini-filter driver step by step 内核中使用线程(7)

    在内核中使用线程,其过程和在应用层中使用线程基本类似,创建线程的API为 NTSTATUS PsCreateSystemThread(_Out_ PHANDLE ThreadHandle,_In_ U ...

  6. Windows核心编程:第9章 用内核对象进行线程同步

    Github https://github.com/gongluck/Windows-Core-Program.git //第9章 用内核对象进行线程同步.cpp: 定义应用程序的入口点. //#in ...

  7. RT_thread空闲线程及两个常用的钩子函数

    一.空闲线程 空闲线程是一个比较特殊的系统线程,它具备最低的优先级.当系统中无其他就绪线程可运行,调度器将调度到空闲线程. 空闲线程还负责一些系统资源回收以及将一些处于关闭台的线程从线程调度列表中移除 ...

  8. 【linux kernel】linux内核如何唤醒线程

    linux内核如何唤醒线程 //本文代码片段出自linux内核版本:4.1.15 linux内核唤醒线程主要使用wake_up_process(). 一.wake_up_process()分析 在li ...

  9. Java线程池七个参数详解:核心线程数、最大线程数、空闲线程存活时间、时间单位、工作队列、线程工厂、拒绝策略

    源码简介 ThreadPoolExecutor是JDK中的线程池实现,这个类实现了一个线程池需要的各个方法,它提供了任务提交.线程管理.监控等方法. 下面是ThreadPoolExecutor类的构造 ...

最新文章

  1. LoadRunner监控Linux
  2. C# 代理做为函数参数的时候
  3. access开发精要(5)-合计group by
  4. 求1-2+3-4+5 ... 99的所有数的和
  5. MIMIC-IV数据库介绍与使用说明
  6. C语言stdio头文件常见的输入输出库函数
  7. Iperf官方andriod版iperf3
  8. 分数阶微积分_通知 | 上海大学理学院微积分小导师答疑第一期
  9. 洛谷 P5322 [BJOI2019]排兵布阵
  10. luogu P3899 [湖南集训]谈笑风生 线段树合并
  11. Python语言快速入门(上)
  12. eclipse软件无法打开的原因
  13. 被骗几十万总结出来的Ddos攻击防护经验!(转载)
  14. 正版方舟建服务器,方舟在steam上肿么搭建服务器
  15. android显示伽玛曲线,教你如何看伽玛曲线图
  16. 百余大佬署名AI论文被爆抄袭!智源现已致歉
  17. C语言实现 输入密码显示星号******
  18. Android菜鸟笔记-实现一键重启和关机
  19. R语言如何自定义调整所绘图形的大小?
  20. mysql创建用户语法_MySQL创建用户

热门文章

  1. 精通python网络爬虫-精通python网络爬虫
  2. python散点图点的大小-python散点图面积大小比例轴长度
  3. 学python买什么书好-学python3什么书好
  4. php和python哪个好-PHP和Python语言选择哪个好
  5. python有道api-python 调用有道api接口的方法
  6. python实现简单的api接口-使用Python编写API接口和使用API接口
  7. python自学什么书比较好-如何自学Python ?自学看什么书比较好?
  8. 自学python需要多长时间-自学Python需要多长时间?
  9. python面向对象编程的优点-Python面向对象编程——总结面向对象的优点
  10. python大数据分析实例-python大数据分析代码案例