iT邦幫忙

2024 iThome 鐵人賽

DAY 3
0
佛心分享-IT 人自學之術

韌體小白之路系列 第 3

[Day03] 韌體小白之路_建立Task

  • 分享至 

  • xImage
  •  

建立Task & 相關知識補充

Creating & Implementing a Task API

BaseType_t xTaskCreate (
    TaskFunction_t pxTaskCode, // Address of the associated task handler
    const char* const pcName, // A descriptive name to identify this task
    const configSTACK_DEPTH_TYPE usStackDepth, // Amount of stack memory allocated to this task (memory in words not in bytes)
    void* const pvParameters, // Pointer of the data which needs to be passed to the task handler once it gets scheduled
    UBaseType_t uxPrioritym // Task priority value
    TaskHandle_t* const pxCreatedTask // Used to save the task handle (an address of the task created)
)
  • Implementing the task
void vATaskFunction( void *pvParameters) {
    for ( ; ; ) {
        --Task application code here.
    }
}
補充 Task Priorities
  • A priority value comes into the picture when there are 2 or more tasks in the system
  • Priority value helps the scheduler to decide which task should run first on the processor
  • Lower the priority value, lesser the task priority(urgency)
  • In freeRTOS each task can be assigned a priority value from 0 to configMax_PRIORITIES - 1 where configMAX_PRIORITIES may be defined in FreeRTOSConfig.h
  • you must decide configMAX_PRIORITIES as per your application need. Using too many task priority values could lead to RAM's overconsumption. if many tasks are allowed to execute
    with varying task priorities, it may decrease the system's overall performance.
  • Limit configMAX_PRIORITIES to 5, unless you have a valid reason to increase this.

開始建立Task

目標: 建立Task1 & Task2,步驟如下:

  1. 改名: 將原本FreeRTOS_Projects名稱改為001Tasks,重新Build Project,因為之前解決所有的問題了,所以應該是Build通過
    https://ithelp.ithome.com.tw/upload/images/20240917/20155520Qz9jkLpyr5.png
  2. 增加頭文件:
    將Task1&Task2的Code放入Src資料夾下的main.c中,請放置在它規定的位置上(一定要寫在USER CODE裡面,不然在編譯時會將不屬於原本code給砍掉)
/* Includes ------------------------------------------------------------------*/
#include "main.h" //原有的Code

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h> // 新增,因為Task1 & Task2是要print
#include "FreeRTOS.h" // 新增,因為要使用FreeRTOS的Kernel
#include "task.h" // 新增,從xTaskCreate() 發現,要引用task.h才能使用此function
/* USER CODE END Includes */
  1. 創建Task:
    我會把一些原始code加進來看,在未來看的時候才知道要加在哪裡
  • 建立變數: 大概在第68行左右
int main(void) 
{
  /* USER CODE BEGIN 1 */
  TaskHandle_t task1_handle; //增加,變數
  TaskHandle_t task2_handle; //增加,變數
  
  BaseType_t status; //增加,變數
  /* USER CODE END 1 */
  • task宣告: 大概在第93行左右
    想要Trace BaseType_t xTaskCreate()的功能,可以在FreeRTOS資料夾下的task.c查看
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */
  
  status = xTaskCreate(task1_handler, "Task-1", 200, "Hello World from Task-1", 4, &task1_handle); 
  configASSERT(status == pdPASS); //configASSERT 確保任務創建成功,檢查 status 是否等於 pdPASS,pdPASS 表示任務創建成功,如果不等於 pdPASS,則觸發 assert 失敗,導致系統停下來進行除錯
  
  xTaskCreate(task2_handler, "Task-2", 200, "Hello World from Task-2", 4, &task2_handle);
  configASSERT(status == pdPASS);
  
  //start the freeRTOS scheduler
  vTaskStartScheduler(); // if the control comes here means the scheduler has failed due to insufficient memory in heap.
  /* USER CODE END 2 */
  • task 函數宣告: 大概在第292行左右
    printf over SWO pin!
  HAL_GPIO_Init(MEMS_INT2_GPIO_Port, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */
static void task1_handler(void* parameters) //增加,函式
{
    while (1)
	{
		printf("%s\n", (char*)parameters);
	}
}

static void task2_handler(void* parameters) //增加,函式
{
	while (1)
	{
		printf("%s\n", (char*)parameters);
	}
}
/* USER CODE END 4 */
  • 函式宣告:
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
/* USER CODE BEGIN PFP */ //PFP: Private Function Prototype
static void task1_handler(void* parameters); //增加,靜態函式宣告
static void task2_handler(void* parameters); //增加,靜態函式宣告
/* USER CODE END PFP */
  • Src資料夾下的syscalls.c加入ITM Code (為了printf)

#include <sys/time.h>
#include <sys/times.h>
//以下為新增的ITM Code
//Debug Exception and Monitor Control Register base address
#define DEMCR        			*((volatile uint32_t*) 0xE000EDFCU )

/* ITM register addresses */
#define ITM_STIMULUS_PORT0   	*((volatile uint32_t*) 0xE0000000 )
#define ITM_TRACE_EN          	*((volatile uint32_t*) 0xE0000E00 )

void ITM_SendChar(uint8_t ch)
{

	//Enable TRCENA
	DEMCR |= ( 1 << 24);

	//enable stimulus port 0
	ITM_TRACE_EN |= ( 1 << 0);

	// read FIFO status in bit [0]:
	while(!(ITM_STIMULUS_PORT0 & 1));

	//Write to ITM stimulus port0
	ITM_STIMULUS_PORT0 = ch;
}
  • Src資料夾下的syscalls.c修改write
    原本:
__attribute__((weak)) int _write(int file, char *ptr, int len)
{
	int DataIdx;

	for (DataIdx = 0; DataIdx < len; DataIdx++)
	{
		__io_putchar(*ptr++);
	}
	return len;
}

修改為:

__attribute__((weak)) int _write(int file, char *ptr, int len)
{
	int DataIdx;

	for (DataIdx = 0; DataIdx < len; DataIdx++)
	{
		//__io_putchar(*ptr++);
		ITM_SendChar(*ptr++);
	}
	return len;
}
  • 修改FreeRTOS資料夾下的FreeRTOSConfig.h的#define:
    原本:
#define configUSE_IDLE_HOOK				1

修改為:

#define configUSE_IDLE_HOOK				0
介紹task_handler:
void task_handler(void* parameters)
{
	/*These Local variables will get created in Task's Private stack memory */
    /*More variables, more stack consumption */
    int var1, var2;
    
    /*This static variable will not get created in Task's private stack memoyr */
    /*在global area創建 */
    static int staticVar1;
    
    while(1) {
        /*Task's work here */
    }
    
    /*Before exit, clean up */
    vTaskDelete(NULL);
}
ITM Code:
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//					Implementation of printf like feature using ARM Cortex M3/M4/ ITM functionality
//					This function will not work for ARM Cortex M0/M0+
//					If you are using Cortex M0, then you can use semihosting feature of openOCD
/////////////////////////////////////////////////////////////////////////////////////////////////////////


//Debug Exception and Monitor Control Register base address
#define DEMCR        			*((volatile uint32_t*) 0xE000EDFCU )

/* ITM register addresses */
#define ITM_STIMULUS_PORT0   	*((volatile uint32_t*) 0xE0000000 )
#define ITM_TRACE_EN          	*((volatile uint32_t*) 0xE0000E00 )

void ITM_SendChar(uint8_t ch)
{

	//Enable TRCENA
	DEMCR |= ( 1 << 24);

	//enable stimulus port 0
	ITM_TRACE_EN |= ( 1 << 0);

	// read FIFO status in bit [0]:
	while(!(ITM_STIMULUS_PORT0 & 1));

	//Write to ITM stimulus port0
	ITM_STIMULUS_PORT0 = ch;
}

應該可以Build過了! 明天再說怎麼觀察preemption的現象~


上一篇
[Day02] 韌體小白之路_應用環境安裝
下一篇
[Day04] 韌體小白之路_建立Task-2
系列文
韌體小白之路7
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言