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)
)
void vATaskFunction( void *pvParameters) {
for ( ; ; ) {
--Task application code here.
}
}
目標: 建立Task1 & Task2,步驟如下:
/* 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 */
int main(void)
{
/* USER CODE BEGIN 1 */
TaskHandle_t task1_handle; //增加,變數
TaskHandle_t task2_handle; //增加,變數
BaseType_t status; //增加,變數
/* USER CODE END 1 */
/* 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 */
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 */
#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;
}
__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;
}
#define configUSE_IDLE_HOOK 1
修改為:
#define configUSE_IDLE_HOOK 0
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);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// 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的現象~