2021-06-02

RTthread再学习记录(二)

创建第一个自己的任务



前言

接着上一篇继续记录RTT学习历程


一、RTT的启动流程

  官方给出的RTT启动流程如图,需要注意的是:以MDK工程为例,程序入口函数是 S u b Sub Sub$main(),它调用rtthread_startup()完成操作系统启动,而CUBEMX生成代码里的main()函数只是一个用户任务入口,对应的任务创建代码在rt_application_init()内实现。另外在系统启动过程中,还会创建定时器任务(需要启用宏:RT_USING_TIMER_SOFT,用于处理实时性要求较高的操作)和空闲任务(用于系统资源回收),如果使能了Finsh组件,还会启用一个tshell任务,用于处理Finsh终端的输出和输入。
在这里插入图片描述

二、创建自己的用户任务

  因为RTT提供动态和静态2种对象创建方式(和FreeRTOS类似),所以也就有了2种任务创建方式。

1.动态的创建(任务栈使用heap)

代码如下(示例):

		rt_thread_t led_thread=rt_thread_create(
		"LED_THREAD",          //任务名称
		LED_task_entry,        //任务入口函数
		RT_NULL,               //入口函数参数   
		512,                   //任务栈空间大小 
		10,                    //任务优先级   
		20	                   //任务时间片轮转tcik周期,同优先级任务调用时起作用
		);
		RT_ASSERT(led_thread != RT_NULL);//断言语句检查任务是否创建成功,防止动态内存分配失败
		rt_thread_startup(led_thread);	//启动任务	

2.静态的创建

代码如下(以启动代码中空闲任务创建为例):

    static rt_uint8_t rt_thread_stack[IDLE_THREAD_STACK_SIZE]; //事先分配任务栈使用的静态内存区
    rt_thread_init(&idle,                  //任务结构体指针       
                   "tidle",                //任务名称  
                   rt_thread_idle_entry,   //任务入口函数
                   RT_NULL,                //入口函数参数
                   &rt_thread_stack[0],    //任务栈起始地址 
                   sizeof(rt_thread_stack), //任务栈大小
                   RT_THREAD_PRIORITY_MAX - 1, //任务优先级
                   32);                        //任务时间片轮转tcik周期,同优先级任务调用时起作用
    rt_thread_startup(&idle);    //启动任务                

  鉴于CUBEMX工程的结构,建议用户任务创建都在main()任务里完成,由main()任务创建其他任务。当然你如果非要在rt_application_init()里面和main()任务并列创建也不是不可以,看个人习惯吧。

三、完成用户代码函数

  还是用入门级的点灯,串口打印之类的功能来玩一下用户任务函数,记得要使用rt_thread_mdelay()函数进行任务切换,要不然高优先级的任务会一直占用内核哦,代码如下:

int main(void)
{
  /* USER CODE BEGIN 1 */
    list_node * P=create(2);
    list_node * Pcurrnt=P->next;
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  //HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  //SystemClock_Config();

  /* USER CODE BEGIN SysInit */


  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_CRC_Init();
  MX_DMA2D_Init();
  MX_FMC_Init();
  MX_I2C3_Init();
  MX_LTDC_Init();
  MX_SPI5_Init();
  MX_TIM1_Init();
  //MX_USART1_UART_Init();

  /* Initialize interrupts */
  MX_NVIC_Init();
  /* USER CODE BEGIN 2 */

    while(Pcurrnt!=NULL)
    {
        rt_kprintf("%s", Pcurrnt->date);
        Pcurrnt=Pcurrnt->next;
    }
        R32(GPIOG->BSRR,b13)=1;  //位域操作
        R32(GPIOG->BSRR,b14)=1;
		rt_kprintf("\n系统时钟:%d\n",HAL_RCC_GetSysClockFreq());
	    rt_kprintf("Currnt position is %s,%s,line%d\n",__FUNCTION__,__FILE__,__LINE__);
    
		rt_thread_t led_thread=rt_thread_create(
		"LED_THREAD",          //任务名称
		LED_task_entry,        //任务入口函数
		RT_NULL,               //入口函数参数   
		512,                   //任务栈空间大小 
		10,                    //任务优先级   
		20	                   //任务时间片tcik周期,同优先级任务调用时起作用
		);   
		RT_ASSERT(led_thread != RT_NULL);
		rt_thread_startup(led_thread);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
    while (1)
    {
    /* USER CODE END WHILE */	
		HAL_GPIO_TogglePin(GPIOG,LD4_Pin);			
        rt_thread_mdelay(1000);
    /* USER CODE BEGIN 3 */
    }
  /* USER CODE END 3 */
}
static void LED_task_entry(void * parm){
		while(1)
		{
	    HAL_GPIO_TogglePin(GPIOG,LD3_Pin);	
		rt_kprintf("hello!\n");	
        rt_thread_mdelay(2000);
		}
}

四、测试

在这里插入图片描述


总结

  RTT任务创建并没有什么特别的,和其他RTOS差不多,只是要注意他的启动过程,以及工程代码结构。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值