해결된 질문
작성
·
734
1
현재 test중인 프로젝트의 stack이 강의내용과 달리 static 방식으로만 고정되어 있는 것 같아서 확인 부탁드립니다.
porting에 사용된 파일을 보면 middlewares/third_party/.../portable/gcc/memmang/heap_4.c를 확인한 결과 아래와 같이 기 설정한 배열영역을 대상으로 task의 stack을 할당하는 것처럼 보입니다. malloc을 사용하여 할당하는 부분을 code에서 찾지 못해서 분석을 잘 못 할 수 있으니 확인 부탁드립니다.
#if( configAPPLICATION_ALLOCATED_HEAP == 1 )
/* The application writer has already defined the array used for the RTOS
heap - probably so it can be placed in a special segment or address. */
extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
#else
static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; //cms: the area used for task's stack
#endif /* configAPPLICATION_ALLOCATED_HEAP */
#define configSUPPORT_STATIC_ALLOCATION 1 //cms: stack is created at bss area
#define configSUPPORT_DYNAMIC_ALLOCATION 1 //cms: stack is created at heap area
use 'xTaskCreate' */
#if 1
xTaskCreate( (TaskFunction_t)Task1, "Task1", 256, (void*)Param, TASK_1_PRIO, &xHandle1);
#endif // TODO #1
/* Create the other task in exactly the same way. */
Param = &Param_Tbl; /* get parameter tbl addr */
Param->P1 = 111111; /* set parameter */
Param->P2 = 222222;
#ifdef CMSIS_OS
osThreadDef(Task2, (void const *)Task2, osPriorityBelowNormal, 0, 256);
xHandle2 = osThreadCreate (osThread(Task2), (void*)Param);
#else
xTaskCreate( (TaskFunction_t)Task2, "Task2", 256, (void*)Param, TASK_2_PRIO, &xHandle2 );
xTaskCreate( (TaskFunction_t)Task3, "Task2", 128, (void*)Param, TASK_3_PRIO, &xHandle3 );
#endif
01_TASKMAN.elf: file format elf32-littlearm
Sections:
Idx Name Size VMA LMA File off Algn
0 .isr_vector 00000198 08000000 08000000 00010000 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .text 00004f04 080001a0 080001a0 000101a0 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
2 .rodata 0000092c 080050a4 080050a4 000150a4 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .ARM.extab 00000000 080059d0 080059d0 00020074 2**0
CONTENTS
4 .ARM 00000008 080059d0 080059d0 000159d0 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .preinit_array 00000000 080059d8 080059d8 00020074 2**0
CONTENTS, ALLOC, LOAD, DATA
6 .init_array 00000004 080059d8 080059d8 000159d8 2**2
CONTENTS, ALLOC, LOAD, DATA
7 .fini_array 00000004 080059dc 080059dc 000159dc 2**2
CONTENTS, ALLOC, LOAD, DATA
8 .data 00000074 20000000 080059e0 00020000 2**2
CONTENTS, ALLOC, LOAD, DATA
9 .bss 00004150 20000074 08005a54 00020074 2**2
10 ._user_heap_stack 00000604 200041c4 08005a54 000241c4 2**0
답변 1
0
안녕하세요. chucky2님!
과거 유사 질문이 있었기 때문에 링크드릴게요.
그리고, 다음과 같은 코드가 포함되어야 에러가 발생하지 않을거에요. 관련내용 참조
/* GetIdleTaskMemory prototype (linked to static allocation support) */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );
static StaticTask_t xIdleTaskTCBBuffer;
static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
{
*ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;
*ppxIdleTaskStackBuffer = &xIdleStack[0];
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
답변 감사합니다. 제가 용어의 정의를 잘못 생각하고 질문을 드렸었습니다.
결론적으로,
task를 생성 시, task의 stack을 메모리 상 지정된 위치로 고정시켜서 사용하면 static 방식이고
메모리 pool을 생성한 후, task 생성 시 자동으로 해당 size만큼을 stack으로 할당 받아서 사용하는 게 dynamic 방식이였네요.
현재 porting된 source 상으로는 아래와 같이 정리됩니다.
free-rtos에서 heap memory를 관리하는 방법 중 heap_4.c 방식의 heap managing 기법을 이용 (참조: https://www.freertos.org/a00111.html)
idle task의 stack을 설정 시에는 osKernelStart -> vTaskStartScheduler -> xTaskCreateStatic를 통해서 static 방식 사용
void vTaskStartScheduler( void ) { BaseType_t xReturn; /* Add the idle task at the lowest priority. */ #if( configSUPPORT_STATIC_ALLOCATION == 1 ) { StaticTask_t *pxIdleTaskTCBBuffer = NULL; StackType_t *pxIdleTaskStackBuffer = NULL; uint32_t ulIdleTaskStackSize; /* The Idle task is created using user provided RAM - obtain the address of the RAM then create the idle task. */ vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize ); xIdleTaskHandle = xTaskCreateStatic( prvIdleTask, configIDLE_TASK_NAME, ulIdleTaskStackSize, ( void * ) NULL, /*lint !e961. The cast is not redundant for all compilers. */ portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */ pxIdleTaskStackBuffer, pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ if( xIdleTaskHandle != NULL ) ...생략
교육 예제에서 사용한 타 task들은 xTaskCreate를 사용하여 dynamic 방식 사용
dynamic 방식으로 할당된 stack들은, 배열로 할당된 bss 영역 이용
감사합니다.