From 0 begin to learn FreeRTOS- (create a task) -2

supplement

Before you start today, start by supplementing the articles from the microcontroller to the operating system -1 knowledge of missing the point a little bit.

 BaseType_t xTaskCreate(       TaskFunction_t pvTaskCode,
                               const char * const pcName,
                               uint16_t usStackDepth,
                               void *pvParameters,
                               UBaseType_t uxPriority,
                               TaskHandle_t *pvCreatedTask
                           );

Create a task stack size problems, is described like this in task.h in:

/**
* @param usStackDepth The size of the task stack specified as the number of variables the stack * can hold - not the number of bytes.  For example, if the stack is 16 bits wide and  
* usStackDepth is defined as 100, 200 byteswill be allocated for stack storage.
*/

When a task is created, the kernel stack into the only task assigned to each task belongs to their own. usStackDepth value is used to tell the kernel that it should be allocated how much stack space.

This value specifies how much stack space characters (word) can be saved, rather than how many bytes (byte).

Document also shows that if a 16-bit word, if usStackDepth = 100; it is 200 bytes (byte).

Of course, I use stm32,32 bit width, usStackDepth = 100; it is 400 bytes (byte).

Well, replenish completed. Here we started our topic today.


I have learned what is the application layer, the bottom of a lot of things I do not know, limited, wrong also please bear with me.

In fact, I wrote the article, they also talk to brother fire book looking at the bottom of things matter, but themselves do not understand myself, not scrawl. So, this "from the microcontroller to the operating system" series of articles, I will speak a little bottom, more of the application layer, mainly is excluded.

According to the general habit of writing code, the main function of which various types of initialization finished, and create a task successfully, then, can open the task scheduler.

int main(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4    
    Delay_Init();                       //延时函数初始化     
    Uart_Init(115200);                  //初始化串口
    LED_Init();                     //初始化LED
    KEY_Init(); 
    //创建开始任务
    xTaskCreate((TaskFunction_t )start_task,            //任务函数
                (const char*    )"start_task",          //任务名称
                (uint16_t       )START_STK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )START_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&StartTask_Handler);   //任务句柄              
    vTaskStartScheduler();          //开启任务调度
}

Probably look to analyze the process of creating the task, although that would be used on the line, but also to know the look.

Note: The following tasks are said to create xTaskCreate (dynamically created) rather than static created.

pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); 
 /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
             if( pxStack != NULL )
             {
                 /* Allocate space for the TCB. */
                 pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
                 /*lint !e961 MISRA exception as the casts are only redundant for some paths. */
                 if( pxNewTCB != NULL )
                 {
                    /* Store the stack location in the TCB. */
                    pxNewTCB->pxStack = pxStack;
                }
                else
                {
                    /* The stack cannot be used as the TCB was not created.  Free
                    it again. */
                    vPortFree( pxStack );
                }
            }
            else
            {
                pxNewTCB = NULL;
            }
        }

The first is the use of pvPortMalloca spatial task stack allocation, if( pxStack != NULL )if the memory request is successful, then the memory request to the task control block. pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );Also to use pvPortMalloc();before the task control block of memory if the application fails to release the application has been successful mission Stack的内存vPortFree( pxStack );

Then initialization tasks related stuff, and add a new initialization of the task control block to the listprvAddNewTaskToReadyList( pxNewTCB );

  Finally, return to the task of the state, if it is successful pdPASS, if the failure is returnederrCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;

prvInitialiseNewTask(    pxTaskCode, 
                         pcName, 
                         ( uint32_t ) usStackDepth,
                         pvParameters,
                         uxPriority, 
                         pxCreatedTask,
                         pxNewTCB, 
                         NULL );
            prvAddNewTaskToReadyList( pxNewTCB );
            xReturn = pdPASS;
        }
        else
        {
            xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
        }
        return xReturn;
    }
// 相关宏定义
#define pdPASS            ( pdTRUE )
#define pdTRUE            ( ( BaseType_t ) 1 )
/* FreeRTOS error definitions. */
#define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY    ( -1 )

Specific static void prvInitialiseNewTask()realization, please refer to FreeRTOSthe tasks.cfile of 767lines of code. Specific static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )realization, please refer to FreeRTOSthe tasks.cfile of 963lines of code.

Because these are tasks.cthe 静态的函数only for xTaskCreate create an internal task calls, we do not care about implementation of these functions, of course, if you need your own understanding.

We have created the task to open the Task Scheduler:

vTaskStartScheduler();          //开启任务调度

Task scheduling which will create a free task (we are dynamically created task, in fact, create the same static)

xReturn = xTaskCreate(    prvIdleTask,
                          "IDLE", configMINIMAL_STACK_SIZE,
                          ( void * ) NULL,
                          ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ),
                          &xIdleTaskHandle ); 
/*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
    }
相关宏定义:
#define tskIDLE_PRIORITY            ( ( UBaseType_t ) 0U )
#ifndef portPRIVILEGE_BIT
    #define portPRIVILEGE_BIT ( ( UBaseType_t ) 0x00 )
#endif
#define configUSE_TIMERS                        1                              
 //为1时启用软件定时器

We can see from the above code, the priority of the idle task is tskIDLE_PRIORITY is 0, that is the lowest priority of the idle task. When the CPU is nothing to do when it is idle task execution, pending any time to switch tasks of higher priority.

If you use a software timer, then we also need to create a task timer function is created:

#if ( configUSE_TIMERS == 1 )
    BaseType_t xTimerCreateTimerTask( void )

Then look at but also to break off

portDISABLE_INTERRUPTS();

As for why disable interrupts, also described:

/* Interrupts are turned off here, toensure a tick does not occur
before or during the call toxPortStartScheduler().  The stacks of
the created tasks contain a status wordwith interrupts switched on
so interrupts will automatically getre-enabled when the first task
starts to run. */

Interrupted here is closed to ensure that during the tick before calling xPortStartScheduler () or will not happen. Create a task stack contains open interrupt status word will automatically re-enable interrupts therefore start running when the first task.

So how do you break it open? ? ? ? This is a very important issue

Do not worry, we interrupt service function which will open in SVC interruption

Look at the code:

__asm void vPortSVCHandler( void )
{
         PRESERVE8
         ldr    r3, =pxCurrentTCB  /* Restore the context. */
         ldrr1, [r3]                            /* UsepxCurrentTCBConst to get the pxCurrentTCB address. */
         ldrr0, [r1]                            /* Thefirst item in pxCurrentTCB is the task top of stack. */
         ldmiar0!, {r4-r11}             /* Pop theregisters that are not automatically saved on exception entry and the criticalnesting count. */
         msrpsp, r0                                   /*Restore the task stack pointer. */
         isb
         movr0, #0
         msr  basepri, r0
         orrr14, #0xd
         bxr14
}
msr  basepri, r0

It is to break open. Read did not matter, I do not know assembler, able to understand know Jiuhaola.

xSchedulerRunning = pdTRUE;

Task scheduling starts running

/* If configGENERATE_RUN_TIME_STATS isdefined then the following
macro must be defined to configure thetimer/counter used to generate
the run time counter time base. */
portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();

If you configGENERATE_RUN_TIME_STATSuse time statistics features, this macro 1, then the user must implement a macro portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();to set a timer or counter.

To our focus, and open the task scheduler, the task to which the would not returned.

if( xPortStartScheduler() != pdFALSE )
{
   /*Should not reach here as if the scheduler is running the
    functionwill not return. */                   
 }

Then you can start the first task, I feel it is so hard, I also began to think, but to write this article, I feel okay, not too difficult, and perhaps look at the code in the book with others I, write something but it is still fine, can deepen understanding, to know who wrote the article, written not be able to understand, so I very much hope that the friends can contribute. JJ always welcome. . .

Start task add your own code templates thousand million according to routine, very simple.

First create a task:

 xTaskCreate((TaskFunction_t )led0_task,    
              (const char*    )"led0_task",  
              (uint16_t       )LED0_STK_SIZE,
              (void*          )NULL,                                    
              (UBaseType_t    )LED0_TASK_PRIO,   
              (TaskHandle_t*  )&LED0Task_Handler);  
   //创建LED1任务
  xTaskCreate((TaskFunction_t )led1_task,    
              (const char*    )"led1_task",  
              (uint16_t       )LED1_STK_SIZE,
              (void*          )NULL,
              (UBaseType_t    )LED1_TASK_PRIO,
              (TaskHandle_t*  )&LED1Task_Handler);      

We have created the task to open the task scheduler:

1vTaskStartScheduler();          //开启任务调度

Then concrete realization of the task function:

//LED0任务函数
void led0_task(void *pvParameters)
{
   while(1)
    {
       LED0=~LED0;
       vTaskDelay(500);
    }
}  

//LED1任务函数
void led1_task(void *pvParameters)
{
   while(1)
    {
       LED1=0;
       vTaskDelay(200);
       LED1=1;
       vTaskDelay(800);
    }
}

Well, today's the introduction to this date, the latter will continue to update, so stay tuned Oh ~

Welcome everyone together to discuss the knowledge of the operating system

Our group number is: 783 234 154

I welcome public attention No.

For more information please concern "Things IoT development," the public number!

Guess you like

Origin www.cnblogs.com/iot-dev/p/11681017.html