freeRTOS 공부를 시작하며 태스크에 대한 내용부터 필기합니다.
CMSIS (Cortex(Common) Microcontroller Software Interface Standard)
CubeIDE에서 freeRTOS를 사용할때,xtaskCreate,vtaskxx,pxreadylist~ 등 freeRTOS함수를 감싸는 ostaskCreate등의 CMSIS함수들이 있다.


FreeRTOS API에 기반한 CMSIS-RTOS를 사용하여 스레드(태스크)를 생성한다
Application: CMSIS-OS API만 사용
Wrapper: CMSIS-OS API 호출을 FreeRTOS 네이티브 호출로 변환
FreeRTOS Kernel: 실제 스레드 관리·동기화 실행
CMSIS 사용하는 이유 : 여러가지 펌웨어 버전들을 표준화하여 OS에서 API 호출방법을 편리하게 할 수 있도록 한다.
단점 : 함수 안에 freeRTOS 함수를 또 감싸며 호출하고 있어,코드 속도나 효율성면에서는 떨어진다.
Task 생성

아래에 osThreadCreate에는 여러 선택지 중 Static과 dynamic이 있는데,
크게 나누면 RAM에서 TCB의 공간과 스택 공간이 있는데, Static은 사용자가 직접 스택 메모리 배열을 선언해서 사용하고,
Dynamic은 내부의 malloc함수를 이용해 힙 메모리를 할당해 사용한다. FreeRTOS/Source/portable/MemMang/heap4.c에서 확인 가능.
osThreadCreate(CMSIS -RTOS API)
생성할 스레드(태스크)를 정의하고, xTaskCreate함수를 호출하여 생성한다.

Create의 파라미터를 →Handle이 전달한다.
cmsis_os.c의 Handle은 곧 tasks.c의 tskTaskContrlBlock 구조체포인터이다.

os_thread_def 구조체

xTaskCreate(freeRTOS)

xTaskCreate(
vTaskFunction, // Task 함수 포인터(함수명)
"UART Task", // Task 이름(디버깅 용도)
128, // Task에 할당할 Stack의 깊이 (타입사이즈*바이트로 워드 단위)
NULL, // Task함수로 전달할 사용자 정의 매개 변수 (void*포인터) 다양한 목적에 따라 구조체/포인터 전달.
2, // Task 우선순위 (0~configMAX값-1)
&uartTaskHandle // 우선순위 변경, 삭제 등 API 호출 가능한 핸들, 필요 없으면 NULL
반환 값 : pdPASS (생성 성공), pdFAIL(Task생성실패)
→ 이 파라미터들로 Task를 생성한다.
);
BaseType_t xTaskCreate( TaskFunction_t pvTaskCode,
const char * const pcName,
uint16_t usStackDepth,
void *pvParameters,
UBaseType_t uxPriority,
TaskHandle_t *pxCreatedTask );
- TCB(Task Control Block) 메모리 힙에 동적 할당
- Task용 스택 메모리를 동적 할당
- 할당이 되면 Task를 init 및 TCB를 넘겨 ready 상태로 등록 후 pdPASS 성공상태 반환한다.

- pvPortMalloc함수 확인→FreeRTOS/Source/portable/MemMang/heap4.c

5. TaskControlBlock 구조체
- 태스크 스택 포인터(SP)(어셈블리 접근성을 위해 가장 위에 위치)스택 포인터가 가리키는 ****컨텍스트에는 8개의 레지스터 세트로 구성된다.
- xPSR,리턴 주소, LR(R14),R12, R3,R2,R1,R0 →이걸 MSP 또는 PSP에 푸시한다
- 태스크가 마지막으로 실행되던 레지스터 값들(컨텍스트)은 태스크 스택(MSP,PSP)에 Push,pop으로 저장됨. 이걸 가리키는 스택 포인터를 TCB에 저장.
- 태스크의 현재 상태 저장(정수값)(Ready,Blocked,Suspended)
- 우선순위
- 태스크 이름
TCB 구조체 코드
typedef struct tskTaskControlBlock /\* The old naming convention is used to prevent breaking kernel aware debuggers. _/
{ ~~~~
//주요 내용만 발췌
ListItem_t xStateListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
ListItem_t xEventListItem; /*< Used to reference a task from an event list. */
UBaseType_t uxPriority; /*< The priority of the task. 0 is the lowest priority. */
StackType_t *pxStack; /*< Points to the start of the stack. */
char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
~~~~
} tskTCB;
이후 create된 태스크는 xStateListItem을 통해 순위에 따라 double linked list구조인 ready list에 저장된다.
* Place the task represented by pxTCB into the appropriate ready list for
* the task. It is inserted at the end of the list.
*/
#define prvAddTaskToReadyList( pxTCB ) \
traceMOVED_TASK_TO_READY_STATE( pxTCB ); \
taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \
tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB )
/*-----------------------------------------------------------*/
