임베디드/펌웨어 기초

FreeRTOS porting

twoweeks-within 2025. 1. 28. 17:22

 

RTOS 사용

 : thread 들이 거의 동시에 동작하면서도(실제로는 CPU가 왔다갔다)

    그와중에 진짜 필요한 task는 우선적으로 실행될 수 있도록함 (우선순위)

 

0. STM32 cubeide > from1.5.0 

1. cube32 Folder > Third party > FreeRTOS Folder

2. lib 폴더에 복붙

3.빌드제외

     CMSIS V2 

     portable Folder > gcc, memmang 이외 

     GCC Folder      > ARM_CM3        이외

     Mammeng        > heap_4              이외

                              // 정적으로 스택메모리 사용 (static)

4. Include

    Include Folder , ARM_CM3, CMSIS_RTOS

5. config.h

     config_templete > bsp > config rename

     Total_Heap_Size : 6 // 메모리 용량 부족할때

      sysTick 을 따로 사용할 경우 Handler 주석처리 

      SVC, pendSV 따로 사용할 경우 > stm32xx.it.c (자체 it) > 주석처리 (#if 0, endif)

/*

sysTick 을 공유해서 같이 사용 할 경우

  : FreeRTOS 에서는 최하위 우선순위

   > 더 높은 우선순위에서 Hal_Dealy, getTick 같은 함수를 쓰면 sysTick 이 안걸리고 Hang 발생

// 원래 sysTick 이 계속 돌아가면서 시간 계산 해줘야함

//

  • 높은 우선순위 인터럽트 내에서는 HAL_Delay()를 사용하지 않는 것이 원칙
  • > FreeRTOS의 vTaskDelay() or 타이머 기능을 사용하는 것이 좋음

FreeRTOS 에서 sysTick 을 최하위로 두는이유

  : FreeRTOS > Task scheduling

  :: sysTick > 단순히 시간 늘려서 다음 스케쥴링 호출 하는 용도

  > USART, CAN  :: us 단위로 통신 ( sysTick 보통 ms )

     > sysTick 에게 방해받으면 안됨.

 

 

6. bsp.h > #include : cmsis_os.h

7. osSysTickHandler >  sysTick 에 추가  :: 스케쥴러 호출

    > HAL 과 FreeRTOS tick 동기화 > 간단하게 사용 하기위한 용도

 

>> Porting 완료

 

 

1. 쓰레드 선언

static void threadMain(void const *argument);

 

 

2. 쓰레드 생성

osThreadDef(threadMain, threadMain, _HW_DEF_RTOS_THREAD_PRI_MAIN, 0, _HW_DEF_RTOS_THREAD_MEM_MAIN);

if (osThreadCreate(osThread(threadMain), NULL) != NULL)

{

logPrintf("threadMain \t\t: OK\r\n");

}

else

{

logPrintf("threadMain \t\t: Fail\r\n");

while(1);

}

 

osKernelStart();

 

>> Google : cmsis rtos :: Reference 확인 가능

 

 

3. 쓰레드 정의

    > 우선순위, 스택메모리 관리

#define _HW_DEF_RTOS_MEM_SIZE(x) ((x)/4)

   > 내부를 들여다 보면 쓰레드 사이즈를 잡을때 * sizeof( StackType_t) // uint32_t

       > 다시 4를 나누어줌 > byte 단위로 확인

 

 

#define _HW_DEF_RTOS_THREAD_PRI_MAIN osPriorityNormal

#define _HW_DEF_RTOS_THREAD_PRI_LED osPriorityNormal

 

 

#define _HW_DEF_RTOS_THREAD_MEM_MAIN _HW_DEF_RTOS_MEM_SIZE( 2*1024)

#define _HW_DEF_RTOS_THREAD_MEM_LED _HW_DEF_RTOS_MEM_SIZE( 256)

 

 

 

#define _USE_HW_RTOS

 

 

4. main 내에서 oskernelStart > threadMain 이 실행됨

     > apMain 이 하나의 쓰레드로서 동작함 

static void threadMain(void const *argument)

{

UNUSED(argument);

 

apMain();

}

 

5. dalay

스케쥴 실행  > osDelay

         아니면 > Hal_Delay

::

HAL_Delay : 쓰레드 실행중에 (계속 점유하면서) 지연시킴

                      > 같은 우선순위면 몇개씩 실행됨 > 비효율적

osDelay      : 지정한 시간만큼 쓰레드 suspend

                      > 그 시간동안 다른 쓰레드 동작

 

void delay(uint32_t ms)

{

#ifdef _USE_HW_RTOS

if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)

{

osDelay(ms);

}

else

{

HAL_Delay(ms);

}

#else

HAL_Delay(ms);

}

#endif

}

 

6. 여러개의 쓰레드를 만들어보자 ex) LED

[ ap.c ]

 

(1) 쓰레드 선언

static void threadLed(void const *argument);

 

(2) 쓰레드 init

osThreadDef(threadLed, threadLed, _HW_DEF_RTOS_THREAD_PRI_LED, 0, _HW_DEF_RTOS_THREAD_MEM_LED);

if (osThreadCreate(osThread(threadLed), NULL) != NULL)

{

logPrintf("threadLed \t\t: OK\r\n");

}

else

{

logPrintf("threadLed \t\t: Fail\r\n");

while(1);

}

 

(3) 쓰레드 만들기

void apMain(void)

  while(1)

  {

     delay(1);

  }

}

 

static void threadLed(void const *argument)

  {

     UNUSED(argument);

      while(1)

        {

          ledToggle(_DEF_LED1);

          delay(500);

        }

}

 

>> Window > show view > FreeRTOS :: 각종 정보 확인가능

'임베디드 > 펌웨어 기초' 카테고리의 다른 글

스타트업 코드 분석  (0) 2025.01.29
Flash  (0) 2025.01.22
UART, DMA  (0) 2025.01.19
reset  (0) 2025.01.08
cdc 2  (0) 2025.01.05