์นดํ…Œ๊ณ ๋ฆฌ ์—†์Œ

FreeRTOS ๊ธฐ๋ฐ˜ ์ž„๋ฒ ๋””๋“œ ์‹œ์Šคํ…œ์˜ ์šฐ์„ ์ˆœ์œ„ ์—ญ์ „ ํ˜„์ƒ ๋ถ„์„ ๋ฐ ๋ฎคํ…์Šค ์šฐ์„ ์ˆœ์œ„ ์ƒ์Šน ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ํ†ตํ•œ ๋ฌธ์ œ ํ•ด๊ฒฐ

๊ฒŒ์ž„๊ต์ˆ˜ 2026. 9. 4. 01:01
๋ฐ˜์‘ํ˜•

๐ŸŒ English Abstract

This article provides an in-depth analysis of the Priority Inversion problem that leads to system freezing in FreeRTOS-based real-time embedded systems. It explains the core mechanism where a medium-priority task unintentionally delays a high-priority task when sharing resources. Furthermore, it demonstrates how to resolve resource contention and optimize system responsiveness using FreeRTOS Mutex with Priority Inheritance Mechanism, along with real-world troubleshooting tips and edge-case management.

1. ์„œ๋ก : ์‹ค์‹œ๊ฐ„ ์ž„๋ฒ ๋””๋“œ ์‹œ์Šคํ…œ๊ณผ ์ž์› ๊ฒฝํ•ฉ ๋ฌธ์ œ

์‹ค์‹œ๊ฐ„ ์šด์˜์ฒด์ œ(Real-Time Operating System, RTOS) ๊ธฐ๋ฐ˜์˜ ์ž„๋ฒ ๋””๋“œ ์‹œ์Šคํ…œ ๊ฐœ๋ฐœ์—์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์š”์†Œ ์ค‘ ํ•˜๋‚˜๋Š” ๋ฐ”๋กœ ๊ฒฐ์ •๋ก ์  ๋™์ž‘(Deterministic Behavior)์˜ ๋ณด์žฅ์ž…๋‹ˆ๋‹ค. ํŠน์ • ํƒœ์Šคํฌ(Task)๊ฐ€ ์ •ํ•ด์ง„ ์‹œ๊ฐ„ ๋‚ด์— ๋ฐ˜๋“œ์‹œ ์‹คํ–‰์„ ์™„๋ฃŒํ•ด์•ผ ํ•˜๋Š” ์—„๊ฒฉํ•œ ์ œ์•ฝ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๊ธฐ ์œ„ํ•ด, FreeRTOS์™€ ๊ฐ™์€ RTOS๋Š” ์„ ์ ํ˜• ์Šค์ผ€์ค„๋ง(Preemptive Scheduling) ๋ฐฉ์‹์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์šฐ์„ ์ˆœ์œ„(Priority)์— ๋”ฐ๋ผ ํƒœ์Šคํฌ ์‹คํ–‰ ์ˆœ์„œ๋ฅผ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์—ฌ๋Ÿฌ ํƒœ์Šคํฌ๊ฐ€ ํ•˜๋‚˜์˜ ๊ณต์œ  ์ž์›(Shared Resource)โ€”์˜ˆ๋ฅผ ๋“ค์–ด UART/SPI/I2C ๋ฒ„์Šค, ๊ณต์šฉ ๋ฉ”๋ชจ๋ฆฌ ๋ฒ„ํผ, ๊ธ€๋กœ๋ฒŒ ์ƒํƒœ ๋ณ€์ˆ˜ ๋“ฑโ€”์— ๋™์‹œ์— ์ ‘๊ทผํ•˜๋ ค ํ•  ๋•Œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฒฝํ•ฉ ์ƒํ™ฉ(Resource Contention)์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๋™๊ธฐํ™” ๋ฉ”์ปค๋‹ˆ์ฆ˜(Synchronization Mechanism)์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ์ด๋•Œ ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์€ ๋™๊ธฐํ™” ํ”„๋ฆฌ๋ฏธํ‹ฐ๋ธŒ(Primitive)๋ฅผ ์„ ํƒํ•  ๊ฒฝ์šฐ ์šฐ์„ ์ˆœ์œ„ ์—ญ์ „(Priority Inversion) ํ˜„์ƒ์ด ๋ฐœ์ƒํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด ํ˜„์ƒ์€ ๊ณ ์šฐ์„ ์ˆœ์œ„ ํƒœ์Šคํฌ๊ฐ€ ๋ฌด๊ธฐํ•œ ๋Œ€๊ธฐ ์ƒํƒœ์— ๋น ์ง€๋ฉฐ, ์‹œ์Šคํ…œ ์ „์ฒด๊ฐ€ ๋ฉˆ์ถ”๊ฑฐ๋‚˜ ์™“์น˜๋… ํƒ€์ด๋จธ(Watchdog Timer, WDT) ๋ฆฌ์…‹์„ ์œ ๋ฐœํ•˜๋Š” ์น˜๋ช…์ ์ธ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ… ์ƒํ™ฉ์œผ๋กœ ์ด์–ด์ง‘๋‹ˆ๋‹ค.

๋ณธ ํฌ์ŠคํŒ…์—์„œ๋Š” FreeRTOS ํ™˜๊ฒฝ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์šฐ์„ ์ˆœ์œ„ ์—ญ์ „ ๋ฉ”์ปค๋‹ˆ์ฆ˜์˜ ๊ทผ๋ณธ ์›์ธ์„ ๋Œ€ํ™”ํ˜• ํŠธ๋ ˆ์ด์Šค ์ˆ˜์ค€์œผ๋กœ ์ •๋ฐ€ํžˆ ๋ถ„์„ํ•˜๊ณ , ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ์šฐ์„ ์ˆœ์œ„ ์ƒ์Šน ๋ฉ”์ปค๋‹ˆ์ฆ˜(Priority Inheritance Mechanism)์˜ ์ ์šฉ ๋ฐฉ์‹๊ณผ ํ˜„์—…์—์„œ์˜ ์ตœ์ ํ™” ๊ฐ€์ด๋“œ๋ฅผ ๋‹ค๋ฃน๋‹ˆ๋‹ค.



2. ์šฐ์„ ์ˆœ์œ„ ์—ญ์ „(Priority Inversion) ํ˜„์ƒ์˜ ๋ฉ”์ปค๋‹ˆ์ฆ˜ ๋ถ„์„

์šฐ์„ ์ˆœ์œ„ ์—ญ์ „ ํ˜„์ƒ์ด๋ž€, ๋‚ฎ์€ ์šฐ์„ ์ˆœ์œ„๋ฅผ ๊ฐ€์ง„ ํƒœ์Šคํฌ๊ฐ€ ๊ณต์œ  ์ž์›์„ ์ ์œ ํ•˜๊ณ  ์žˆ๋Š” ๋™์•ˆ, ๋†’์€ ์šฐ์„ ์ˆœ์œ„๋ฅผ ๊ฐ€์ง„ ํƒœ์Šคํฌ๊ฐ€ ํ•ด๋‹น ์ž์›์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๊ณผ์ •์—์„œ ์ค‘๊ฐ„ ์šฐ์„ ์ˆœ์œ„๋ฅผ ๊ฐ€์ง„ ๋‹ค๋ฅธ ํƒœ์Šคํฌ๋“ค์— ์˜ํ•ด ๋ฐฉํ•ด๋ฅผ ๋ฐ›์•„ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋‚ฎ์€ ํƒœ์Šคํฌ๋ณด๋‹ค๋„ ๋Šฆ๊ฒŒ ์‹คํ–‰๋˜๋Š” ๊ธฐ์ดํ•œ ํ˜„์ƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

์šฐ์„ ์ˆœ์œ„ ์—ญ์ „ ๋ฐœ์ƒ ๋‹จ๊ณ„๋ณ„ ๋ถ„์„

์‹œ์Šคํ…œ์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ธ ๊ฐ€์ง€ ํƒœ์Šคํฌ๊ฐ€ ์กด์žฌํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

  • Task H (High Priority): ๊ฐ€์žฅ ๋†’์€ ์šฐ์„ ์ˆœ์œ„๋ฅผ ๊ฐ€์ง„ ์ •๋ฐ€ ์ œ์–ด ํƒœ์Šคํฌ
  • Task M (Medium Priority): ์ค‘๊ฐ„ ์šฐ์„ ์ˆœ์œ„๋ฅผ ๊ฐ€์ง„ ์—ฐ์‚ฐ ์ฒ˜๋ฆฌ ํƒœ์Šคํฌ (๊ณต์œ  ์ž์› ๋ฏธ์‚ฌ์šฉ)
  • Task L (Low Priority): ๊ฐ€์žฅ ๋‚ฎ์€ ์šฐ์„ ์ˆœ์œ„๋ฅผ ๊ฐ€์ง„ ์„ผ์„œ ๋กœ๊น… ํƒœ์Šคํฌ

์ด ์„ธ ๊ฐ€์ง€ ํƒœ์Šคํฌ ์‚ฌ์ด์—์„œ ์ผ์–ด๋‚˜๋Š” ๋ฌธ์ œ ์ƒํ™ฉ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ˆœ์„œ๋กœ ์ „๊ฐœ๋ฉ๋‹ˆ๋‹ค.

  1. [์ž์› ์„ ์ ] Task L์ด ์‹คํ–‰ ์ค‘ ๊ณต์œ  ์ž์›(์˜ˆ: I2C ๋ฒ„์Šค)์„ ์ œ์–ดํ•˜๊ธฐ ์œ„ํ•ด ์ด์ง„ ์„ธ๋งˆํฌ์–ด(Binary Semaphore)๋ฅผ ํš๋“(Take)ํ•ฉ๋‹ˆ๋‹ค.
  2. [๊ณ ์šฐ์„ ์ˆœ์œ„ ํƒœ์Šคํฌ ๋Œ€๊ธฐ] ์ด ์‹œ์ ์— Task H๊ฐ€ ๊นจ์–ด๋‚˜ ์„ ์ (Preemption)์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. Task H๋Š” ๋™์ผํ•œ I2C ๋ฒ„์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์„ธ๋งˆํฌ์–ด๋ฅผ ์š”์ฒญํ•˜์ง€๋งŒ, ์ด๋ฏธ Task L์ด ์ ์œ ํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ ์ฐจ๋‹จ ์ƒํƒœ(Blocked State)๋กœ ์ง„์ž…ํ•ฉ๋‹ˆ๋‹ค.
  3. [์ค‘๊ฐ„ ์šฐ์„ ์ˆœ์œ„ ํƒœ์Šคํฌ์˜ ๋ฐฉํ•ด] ์ด๋•Œ ๊ณต์œ  ์ž์›๊ณผ ์•„๋ฌด ๊ด€๋ จ์ด ์—†๋Š” Task M์ด ๊นจ์–ด๋‚ฉ๋‹ˆ๋‹ค. Task M์€ Task L๋ณด๋‹ค ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’๊ธฐ ๋•Œ๋ฌธ์— CPU ์ œ์–ด๊ถŒ์„ ์„ ์ ํ•˜์—ฌ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
  4. [์šฐ์„ ์ˆœ์œ„ ์—ญ์ „ ์™„์„ฑ] ๊ฒฐ๊ณผ์ ์œผ๋กœ Task H๋Š” Task L์ด ์„ธ๋งˆํฌ์–ด๋ฅผ ๋ฐ˜ํ™˜(Give)ํ•˜๊ธฐ๋งŒ์„ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ์ง€๋งŒ, ์ •์ž‘ Task L์€ Task M์—๊ฒŒ CPU๋ฅผ ๋นผ์•—๊ฒจ ์‹คํ–‰์กฐ์ฐจ ๋˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ๊ฒฐ๋ก ์ ์œผ๋กœ Task H๋Š” ์ž์›๊ณผ ์•„๋ฌด ์ƒ๊ด€ ์—†๋Š” Task M์˜ ์‹คํ–‰์ด ์™„์ „ํžˆ ๋๋‚  ๋•Œ๊นŒ์ง€ ๋ฌด์ œํ•œ ๋Œ€๊ธฐ(Unbounded Inversion)ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก ์™œ ์‹œ์Šคํ…œ ๋ฉˆ์ถค(System Freeze)์ด ๋ฐœ์ƒํ•˜๋Š”๊ฐ€?
Task H๊ฐ€ ์ฃผ๊ธฐ์ ์ธ ์•ˆ์ „ ๊ฒ€์‚ฌ๋‚˜ ํ•˜๋“œ์›จ์–ด ์ œ์–ด๋ฅผ ๋‹ด๋‹นํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, Task M์˜ ์žฅ์‹œ๊ฐ„ ์—ฐ์‚ฐ์œผ๋กœ ์ธํ•ด Task H์˜ ๋ฐ๋“œ๋ผ์ธ(Deadline)์„ ๋„˜๊ธฐ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๊ฒฐ๊ตญ ์‹œ์Šคํ…œ ์‘๋‹ต ๋ถˆ๋Šฅ ํ˜„์ƒ์„ ๊ฐ€์ ธ์˜ค๋ฉฐ, ์‹œ์Šคํ…œ ๋ณด์กฐ ์™“์น˜๋…(System Watchdog)์ด ์ž‘๋™ํ•˜์—ฌ ํ•˜๋“œ์›จ์–ด ๋ฆฌ์…‹์„ ์œ ๋ฐœํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

3. FreeRTOS์—์„œ ์ด์ง„ ์„ธ๋งˆํฌ์–ด์™€ ๋ฎคํ…์Šค์˜ ๊ฒฐ์ •์  ์ฐจ์ด

๋งŽ์€ ๊ฐœ๋ฐœ์ž๋“ค์ด FreeRTOS์—์„œ ๋™๊ธฐํ™”๋ฅผ ๊ตฌํ˜„ํ•  ๋•Œ ์ด์ง„ ์„ธ๋งˆํฌ์–ด(Binary Semaphore)์™€ ๋ฎคํ…์Šค(Mutex)๋ฅผ ํ˜ผ์šฉํ•˜๊ณค ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ƒํ˜ธ ๋ฐฐ์ œ(Mutual Exclusion) ๋ชฉ์ ์—์„œ๋Š” ๋‘ ๊ฐ์ฒด ๊ฐ„์˜ ๋‚ด๋ถ€ ์ปค๋„ ๋™์ž‘ ๊ตฌ์กฐ๊ฐ€ ์™„์ „ํžˆ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

๊ตฌ๋ถ„ ์ด์ง„ ์„ธ๋งˆํฌ์–ด (Binary Semaphore) ๋ฎคํ…์Šค (Mutex)
์ฃผ ์‚ฌ์šฉ ๋ชฉ์  ํƒœ์Šคํฌ ๊ฐ„ ๋˜๋Š” ISR ๊ฐ„ ๋™๊ธฐํ™” (Signaling) ๊ณต์œ  ์ž์›์— ๋Œ€ํ•œ ์ƒํ˜ธ ๋ฐฐ์ œ (Mutual Exclusion)
์†Œ์œ ๊ถŒ (Ownership) ์—†์Œ (Task A๊ฐ€ Takeํ•˜๊ณ  Task B๊ฐ€ Give ๊ฐ€๋Šฅ) ์žˆ์Œ (Take๋ฅผ ์‹คํ–‰ํ•œ ํƒœ์Šคํฌ๋งŒ Give ๊ฐ€๋Šฅ)
์šฐ์„ ์ˆœ์œ„ ์Šน๊ณ„ ์ง€์›ํ•˜์ง€ ์•Š์Œ (Priority Inheritance X) ์ง€์›ํ•จ (Priority Inheritance O)
ISR ๋‚ด ์‚ฌ์šฉ ๊ฐ€๋Šฅ (`xSemaphoreGiveFromISR` ๋“ฑ) ๋ถˆ๊ฐ€ (ISR์€ ์ฐจ๋‹จ ์ƒํƒœ๊ฐ€ ๋  ์ˆ˜ ์—†์Œ)


4. ํ•ด๊ฒฐ์ฑ…: ์šฐ์„ ์ˆœ์œ„ ์ƒ์Šน ๋ฉ”์ปค๋‹ˆ์ฆ˜(Priority Inheritance) ๋™์ž‘ ์›๋ฆฌ

FreeRTOS์˜ ๋ฎคํ…์Šค(`xSemaphoreCreateMutex()`)๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ ์šฐ์„ ์ˆœ์œ„ ์Šน๊ณ„/์ƒ์Šน ๋ฉ”์ปค๋‹ˆ์ฆ˜(Priority Inheritance Protocol)์„ ๋‚ด์žฅํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์ ์šฉํ•˜๋ฉด ์•ž์„œ ๋ฐœ์ƒํ–ˆ๋˜ ๋ฌด์ œํ•œ ์šฐ์„ ์ˆœ์œ„ ์—ญ์ „ ๋ฌธ์ œ๊ฐ€ ์™„๋ฒฝํ•˜๊ฒŒ ํ•ด๊ฒฐ๋ฉ๋‹ˆ๋‹ค.

์šฐ์„ ์ˆœ์œ„ ์ƒ์Šน ๋ฉ”์ปค๋‹ˆ์ฆ˜ ๋™์ž‘ ๋‹จ๊ณ„

  1. Task L์ด ๋ฎคํ…์Šค๋ฅผ ํš๋“ํ•˜๊ณ  ๊ณต์œ  ์ž์› ์ž‘์—…์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
  2. Task H๊ฐ€ ๋™์ผํ•œ ๋ฎคํ…์Šค๋ฅผ ์š”์ฒญํ•˜๋ฉฐ ๋Œ€๊ธฐ ์ƒํƒœ(Blocked)๋กœ ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค.
  3. FreeRTOS ์ปค๋„์€ ์ฆ‰์‹œ ๋ฎคํ…์Šค๋ฅผ ์†Œ์œ ํ•œ Task L์˜ ์šฐ์„ ์ˆœ์œ„๋ฅผ Task H์˜ ์šฐ์„ ์ˆœ์œ„ ์ˆ˜์ค€์œผ๋กœ ์ž„์‹œ ์ƒํ–ฅ(Inherit)์‹œํ‚ต๋‹ˆ๋‹ค.
  4. ์ด ์‹œ์ ์— Task M์ด ๊นจ์–ด๋‚˜๋”๋ผ๋„, ์ž„์‹œ๋กœ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์•„์ง„ Task L์„ ์„ ์ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
  5. Task L์€ ๋น ๋ฅด๊ฒŒ ์ž์› ์ž‘์—…์„ ๋งˆ์น˜๊ณ  ๋ฎคํ…์Šค๋ฅผ ๋ฐ˜ํ™˜(`xSemaphoreGive`)ํ•ฉ๋‹ˆ๋‹ค.
  6. ๋ฎคํ…์Šค๊ฐ€ ๋ฐ˜ํ™˜๋˜๋Š” ์ˆœ๊ฐ„, Task L์˜ ์šฐ์„ ์ˆœ์œ„๋Š” ์›๋ž˜ ์ˆ˜์ค€์œผ๋กœ ๋ณต์›๋˜๊ณ , ์ฆ‰์‹œ ์„ ์  ๋ฉ”์ปค๋‹ˆ์ฆ˜์— ์˜ํ•ด ๊ฐ€์žฅ ๋†’์•˜๋˜ Task H๊ฐ€ ๋ฎคํ…์Šค๋ฅผ ํš๋“ํ•˜์—ฌ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

FreeRTOS ๋ฎคํ…์Šค ์ ์šฉ ์ฝ”๋“œ ์˜ˆ์‹œ

๋‹ค์Œ์€ ์ด์ง„ ์„ธ๋งˆํฌ์–ด๋กœ ์ธํ•œ ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ณ , ์šฐ์„ ์ˆœ์œ„ ์ƒ์Šน์ด ์ ์šฉ๋œ ๋ฎคํ…์Šค๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๊ณต์œ  ์ž์›์„ ์•ˆ์ „ํ•˜๊ฒŒ ๋ณดํ˜ธํ•˜๋Š” C ์–ธ์–ด ๊ตฌํ˜„ ํŒจํ„ด์ž…๋‹ˆ๋‹ค.

#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"

// ๊ณต์œ  ์ž์› ๋ฎคํ…์Šค ํ•ธ๋“ค ์„ ์–ธ
SemaphoreHandle_t xResourceMutex;

void vSystemInit(void)
{
    // ์šฐ์„ ์ˆœ์œ„ ์Šน๊ณ„ ๊ธฐ๋Šฅ์ด ํ™œ์„ฑํ™”๋œ ๋ฎคํ…์Šค ์ƒ์„ฑ
    xResourceMutex = xSemaphoreCreateMutex();

    if(xResourceMutex == NULL)
    {
        // ๋ฎคํ…์Šค ์ƒ์„ฑ ์‹คํŒจ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ (๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ ๋“ฑ)
        configASSERT(0);
    }
}

// ๊ณ ์šฐ์„ ์ˆœ์œ„ ํƒœ์Šคํฌ (Task H)
void vTaskHighPriority(void *pvParameters)
{
    for(;;)
    {
        vTaskDelay(pdMS_TO_TICKS(100)); // ์ฃผ๊ธฐ์  ์‹คํ–‰

        // ๋ฎคํ…์Šค ํš๋“ ์‹œ๋„ (์ตœ๋Œ€ 100ms ๋Œ€๊ธฐ)
        if(xSemaphoreTake(xResourceMutex, pdMS_TO_TICKS(100)) == pdTRUE)
        {
            // [Critical Section] ํฌ๋ฆฌํ‹ฐ์ปฌ ์„น์…˜: ๊ณต์œ  ์ž์› ์•ˆ์ „ ์ ‘๊ทผ
            AccessSharedResource();

            // ๋ฎคํ…์Šค ๋ฐ˜ํ™˜
            xSemaphoreGive(xResourceMutex);
        }
        else
        {
            // ํƒ€์ž„์•„์›ƒ ๋ฐœ์ƒ ์‹œ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ… ๋กœ๊น…
            TraceResourceTimeoutError();
        }
    }
}

// ์ €์šฐ์„ ์ˆœ์œ„ ํƒœ์Šคํฌ (Task L)
void vTaskLowPriority(void *pvParameters)
{
    for(;;)
    {
        if(xSemaphoreTake(xResourceMutex, portMAX_DELAY) == pdTRUE)
        {
            // Task L์ด ๋ฎคํ…์Šค๋ฅผ ๋ณด์œ ํ•œ ๋™์•ˆ Task H๊ฐ€ Take๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด,
            // Task L์˜ ์šฐ์„ ์ˆœ์œ„๊ฐ€ Task H ์ˆ˜์ค€์œผ๋กœ ์ผ์‹œ ์ƒ์Šนํ•จ.
            AccessSharedResource();

            xSemaphoreGive(xResourceMutex);
        }
    }
}

5. ์‹ค๋ฌด ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ… ๋ฐ ์—ฃ์ง€ ์ผ€์ด์Šค(Edge Cases) ๊ณ ๋ ค์‚ฌํ•ญ

์šฐ์„ ์ˆœ์œ„ ์Šน๊ณ„ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์ ์šฉํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ ๋ชจ๋“  ๋™๊ธฐํ™” ๋ฌธ์ œ๊ฐ€ ์™„๋ฒฝํ•˜๊ฒŒ ํ•ด๊ฒฐ๋˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ์‹ค๋ฌด์—์„œ ์ ‘ํ•˜๊ฒŒ ๋˜๋Š” ๊ณ ๊ธ‰ ์—ฃ์ง€ ์ผ€์ด์Šค๋“ค๊ณผ ์ตœ์ ํ™” ๊ธฐ๋ฒ•์„ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค.

1) ์ค‘์ฒฉ ๋ฎคํ…์Šค ๋ฐ ๋ฐ๋“œ๋ฝ(Deadlock) ์œ„ํ—˜์„ฑ

์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋ฎคํ…์Šค๋ฅผ ์ค‘์ฒฉํ•ด์„œ ํš๋“ํ•  ๋•Œ(Nested Mutex Taking) ์„œ๋กœ ๋‹ค๋ฅธ ์ˆœ์„œ๋กœ ์ž์›์„ ์š”์ฒญํ•˜๋ฉด ๊ต์ฐฉ ์ƒํƒœ(Deadlock)๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ํ•ด๊ฒฐ ์›์น™: ์‹œ์Šคํ…œ ์ „์ฒด์—์„œ ๋ฎคํ…์Šค๋ฅผ ํš๋“ํ•˜๋Š” ์ˆœ์„œ(Lock Ordering)๋ฅผ ํ‘œ์ค€ํ™”ํ•˜์—ฌ ํ†ต์ผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ํ•ญ์ƒ `Mutex A -> Mutex B` ์ˆœ์„œ๋กœ๋งŒ ํš๋“ํ•˜๋„๋ก ๊ทœ์ •ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, ๋ณต์žกํ•œ ์ค‘์ฒฉ ๊ตฌ์กฐ์—์„œ๋Š” ์žฌ๊ท€ ๋ฎคํ…์Šค(`xSemaphoreCreateRecursiveMutex()`) ํ™œ์šฉ์„ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

2) ISR(์ธํ„ฐ๋ŸฝํŠธ ์„œ๋น„์Šค ๋ฃจํ‹ด)๊ณผ์˜ ์ž์› ๊ณต์œ 

์ธํ„ฐ๋ŸฝํŠธ ๋งฅ๋ฝ(Interrupt Context)์—์„œ๋Š” ๋Œ€๊ธฐ(Blocking)๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ, ๋ฎคํ…์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ISR๊ณผ ํƒœ์Šคํฌ ๊ฐ„ ๊ณต์œ  ์ž์› ๊ฒฝํ•ฉ์„ ๋ฐฉ์ง€ํ•˜๋ ค๋ฉด ๋ฎคํ…์Šค๊ฐ€ ์•„๋‹Œ ํฌ๋ฆฌํ‹ฐ์ปฌ ์„น์…˜ ์ง„์ž…(`taskENTER_CRITICAL_FROM_ISR()`) ๋˜๋Š” **์ด์ง„ ์„ธ๋งˆํฌ์–ด/ํ(Queue)**๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

3) ์šฐ์„ ์ˆœ์œ„ ์ƒํ•œ ํ”„๋กœํ† ์ฝœ(Priority Ceiling Protocol) ๊ฒ€ํ† 

์šฐ์„ ์ˆœ์œ„ ์Šน๊ณ„(Priority Inheritance) ์™ธ์—๋„ ์šฐ์„ ์ˆœ์œ„ ์ƒํ•œ(Priority Ceiling) ๋ฐฉ์‹์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ์ž์›์„ ์ ์œ ํ•˜๋Š” ์ˆœ๊ฐ„, ํ•ด๋‹น ์ž์›์„ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ํƒœ์Šคํฌ ์ค‘ ๊ฐ€์žฅ ๋†’์€ ์šฐ์„ ์ˆœ์œ„๋กœ ์ฆ‰์‹œ ์Šน์ƒ์‹œํ‚ค๋Š” ๊ธฐ๋ฒ•์ž…๋‹ˆ๋‹ค. FreeRTOS ๊ธฐ๋ณธ ์‚ฌ์–‘์€ Priority Inheritance ๋ฐฉ์‹์ด์ง€๋งŒ, ์‹œ์Šคํ…œ ์š”๊ตฌ์‚ฌํ•ญ์— ๋”ฐ๋ผ ํฌ๋ฆฌํ‹ฐ์ปฌ ์„น์…˜์˜ ๊ธธ์ด๋ฅผ ๊ทน๋„๋กœ ์ค„์ด๋Š” ์„ค๊ณ„ ๊ธฐ๋ฒ•์ด ์กฐํ•ฉ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

4) ๋ฌธ๋งฅ ๊ตํ™˜ ์˜ค๋ฒ„ํ—ค๋“œ(Context Switch Overhead) ์ตœ์ ํ™”

์šฐ์„ ์ˆœ์œ„ ์ƒํ–ฅ ๋ฐ ๋ณต์› ๊ณผ์ •์—์„œ ์ถ”๊ฐ€์ ์ธ ์ปค๋„ ์—ฐ์‚ฐ๊ณผ **๋ฌธ๋งฅ ๊ตํ™˜(Context Switching)**์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ํฌ๋ฆฌํ‹ฐ์ปฌ ์„น์…˜ ๋‚ด๋ถ€์˜ ์ฝ”๋“œ๊ฐ€ ๋‹จ ๋ช‡ ์ค„์— ๋ถˆ๊ณผํ•˜๋‹ค๋ฉด, ๋ฎคํ…์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค `vTaskSuspendAll()` ๋˜๋Š” `taskENTER_CRITICAL()`์„ ์‚ฌ์šฉํ•˜์—ฌ ์Šค์ผ€์ค„๋ง์„ ์ž ์‹œ ๋ฉˆ์ถ”๋Š” ๊ฒƒ์ด ์˜ค๋ฒ„ํ—ค๋“œ ์ธก๋ฉด์—์„œ ํ›จ์”ฌ ์œ ๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.



6. ๊ฒฐ๋ก : ์•ˆ์ •์ ์ธ RTOS ์„ค๊ณ„๋ฅผ ์œ„ํ•œ ํ•ต์‹ฌ ์ฒดํฌ๋ฆฌ์ŠคํŠธ

FreeRTOS ๊ธฐ๋ฐ˜ ์‹ค์‹œ๊ฐ„ ์ž„๋ฒ ๋””๋“œ ์‹œ์Šคํ…œ์—์„œ ๊ณต์œ  ์ž์› ๊ฒฝํ•ฉ์œผ๋กœ ์ธํ•œ ์‹œ์Šคํ…œ ๋ฉˆ์ถค ๋ฐ ์ด์ƒ ๋™์ž‘์„ ์˜ˆ๋ฐฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ ์•„ํ‚คํ…์ฒ˜ ์ˆ˜๋ฆฝ ์›์น™์„ ์ง€์ผœ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  1. ์ƒํ˜ธ ๋ฐฐ์ œ ๋ชฉ์ ์—๋Š” ์ด์ง„ ์„ธ๋งˆํฌ์–ด๊ฐ€ ์•„๋‹Œ ๋ฎคํ…์Šค๋ฅผ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค. ๋ฎคํ…์Šค์— ๋‚ด์žฅ๋œ ์šฐ์„ ์ˆœ์œ„ ์Šน๊ณ„ ๋ฉ”์ปค๋‹ˆ์ฆ˜๋งŒ์ด ๋ฌด์ œํ•œ ์šฐ์„ ์ˆœ์œ„ ์—ญ์ „์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ํฌ๋ฆฌํ‹ฐ์ปฌ ์„น์…˜(Critical Section)์˜ ์‹คํ–‰ ์‹œ๊ฐ„์„ ์ตœ์†Œํ™”ํ•˜์‹ญ์‹œ์˜ค. ๋ฎคํ…์Šค๋ฅผ ๋ณด์œ ํ•œ ์ฑ„ ๊ธด ๋Œ€๊ธฐ ์‹œ๊ฐ„(Delay)์ด๋‚˜ I/O ๋Œ€๊ธฐ ๋ฃจํ”„๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์€ ์ „์ฒด ์‹ค์‹œ๊ฐ„์„ฑ์„ ๋–จ์–ด๋œจ๋ฆฝ๋‹ˆ๋‹ค.
  3. ISR์—์„œ์˜ ๋™๊ธฐํ™” ์ œ์•ฝ์„ ๋ช…ํ™•ํžˆ ์ธ์ง€ํ•˜์‹ญ์‹œ์˜ค. ISR ๋‚ด๋ถ€์—์„œ๋Š” ์ ˆ๋Œ€ ๋ฎคํ…์Šค๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ๋ง๊ณ , `FromISR` ์ „์šฉ API์™€ ์„ธ๋งˆํฌ์–ด/ํ๋ฅผ ํ™œ์šฉํ•˜์„ธ์š”.
  4. Tracealyzer์™€ ๊ฐ™์€ RTOS ๋””๋ฒ„๊น…/ํŠธ๋ ˆ์ด์‹ฑ ๋„๊ตฌ๋ฅผ ํ™œ์šฉํ•˜์‹ญ์‹œ์˜ค. ํƒ€์ž„๋ผ์ธ ๊ธฐ๋ฐ˜์œผ๋กœ ํƒœ์Šคํฌ ์ƒํƒœ ๋ณ€ํ™”์™€ ์„ธ๋งˆํฌ์–ด/๋ฎคํ…์Šค ์ด๋ฒคํŠธ๋ฅผ ์‹œ๊ฐํ™”ํ•˜๋ฉด ์šฐ์„ ์ˆœ์œ„ ์—ญ์ „ ๋ฐ ๋ณ‘๋ชฉ ์ง€์ ์„ ์ •๋ฐ€ํ•˜๊ฒŒ ์ถ”์ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‹ค์‹œ๊ฐ„์„ฑ์„ ๋ณด์žฅํ•ด์•ผ ํ•˜๋Š” ์ž„๋ฒ ๋””๋“œ ํ˜„์žฅ์—์„œ ๊ฒฌ๊ณ ํ•œ ์†Œํ”„ํŠธ์›จ์–ด๋ฅผ ๊ตฌ์ถ•ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ด๋Ÿฌํ•œ ์Šค์ผ€์ค„๋Ÿฌ์˜ ์„ธ๋ถ€ ๋‚ด๋ถ€ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์ •ํ™•ํžˆ ์ดํ•ดํ•˜๊ณ  ์˜ฌ๋ฐ”๋ฅธ ๋™๊ธฐํ™” ๊ธฐ๋ฒ•์„ ์ ์šฉํ•˜๋Š” ๊ฒƒ์ด ํ•„์ˆ˜์ ์ž…๋‹ˆ๋‹ค.

๋ฐ˜์‘ํ˜•