• 카테고리

    질문 & 답변
  • 세부 분야

    임베디드 · IoT

  • 해결 여부

    해결됨

[질문/해결완료] Task에서 사용하는 stack 영역 위치

22.09.15 19:36 작성 조회수 517

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 */

freertosconfig_base.h 설정

#define configSUPPORT_STATIC_ALLOCATION 1 //cms: stack is created at bss area

#define configSUPPORT_DYNAMIC_ALLOCATION 1 //cms: stack is created at heap area

task.c에서 task 생성시 사용한 함수

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

memory map

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

task 동작시 확인한 stack 영역은 bss영역

답변 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;
}
chucky2님의 프로필

chucky2

질문자

2022.09.16

답변 감사합니다. 제가 용어의 정의를 잘못 생각하고 질문을 드렸었습니다.

결론적으로,

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 영역 이용

 

감사합니다.