21.6.2.1.1. `wq_rate_ctrl` (초고우선순위): 1kHz 이상 자이로/가속도 데이터 처리용 스택 할당

21.6.2.1.1. wq_rate_ctrl (초고우선순위): 1kHz 이상 자이로/가속도 데이터 처리용 스택 할당

비행 제어의 세계에서 1밀리초(ms)는 영겁의 시간이다. 1초에 1,000번 이상 회전하며 찰나의 순간마다 기체의 수평을 맞춰야 하는 코어 제어 로직들을 위해, PX4는 자원을 몰빵해 둔 전용 고속도로를 깔아두었다. 그 버스의 이름이 바로 wq_rate_ctrl (Rate Control Work Queue)이다.

만약 여러분이 자이로스코프 센서의 노이즈를 깎아내는 커스텀 소프트 패스 필터(Custom Low-pass Filter) 모듈이나, 로봇 팔의 반작용 토크를 실시간으로 보상하는 민첩한 모터 믹서(Mixer)를 짰다면, 뒤도 돌아보지 말고 생성자 초기화 리스트에 이 버스 번호표를 적어 넣어야 한다.

// 1000Hz의 심장박동을 견딜 수 있는 초고속 모듈의 생성자
CustomFastController() :
    ModuleParams(nullptr),
    ScheduledWorkItem(MODULE_NAME, px4::wq_configurations::rate_ctrl) // 초고우선순위 배정
{
    // ...
}

1. wq_rate_ctrl 버스의 강력한 권력

이 버스(rate_ctrl)에 탑승한 승객(Work Item)들은 NuttX 운영체제 내에서 최고 권력을 누리게 된다.
NuttX 커널 스케줄러 내에서 wq_rate_ctrl 스레드 풀은 시스템 내에서 허용 가능한 **최고 수준의 우선순위(Priority)**를 할당받는다. (일반적으로 NuttX의 스케줄러에서 255에 가까운 수치)

이 말은 즉, 픽스호크 CPU가 SD 카드에 텍스트를 저장하고 있건, GPS 위성 신호를 파싱하고 있건 상관없이, 이 rate_ctrl 버스가 “나 지금 돌아야 해!“라고 손을 드는 순간, 운영체제는 하던 모든 잡일을 내팽개치고(Preemption) 이 버스 안의 화물을 최우선으로 실행시킨다는 뜻이다.
이 강력한 선점(Preemption) 능력 덕분에 rate_ctrl에 속한 모듈들은 Jitter(주기 떨림 현상)를 거의 0에 가깝게 유지하며 마치 하드웨어 타이머처럼 기계적으로 정확하게 실행될 수 있다.

2. 스택(Stack) 메모리 할당의 철칙과 딜레마

이처럼 막강한 성능을 자랑하지만, 이 버스에는 치명적인 제한 사항이 하나 있다. 바로 **스택 메모리(Stack Memory)**의 한계다.

wq_rate_ctrl 스레드 풀이 시스템 부팅 시에 미리 커널로부터 할당받는 스택 메모리 크기는 보통 2KB ~ 4KB 남짓으로 매우 좁게 설정되어 있다.
왜 이렇게 좁게 만들었을까? 초고속 연산을 돌리기 위해서는 CPU의 캐시(L1 Cache) 적중률이 극도로 높아야 하는데, 스택이 너무 크면 캐시 미스(Cache Miss)가 발생하여 연산 속도가 눈에 띄게 느려지기 때문이다.

따라서 rate_ctrl 버스에 올라탄 모듈의 Run() 함수 안에서 다음과 같은 금기(Taboo)를 저지르면, 픽스호크는 그 즉시 Stack Overflow (스택 넘침) 에러를 뿜어내며 공중에서 돌덩이가 되어 추락한다.

  1. 거대한 지역 변수 배열 선언: float temp_matrix[100][100]; 같은 미친 배열을 스택 영역에 냅다 선언하는 행위.
  2. 재귀 함수 (Recursive Call): 팩토리얼(Factorial)이나 깊숙한 트리 탐색처럼 함수 안에서 자기를 무한정 다시 부르는 행위 (스택을 겹겹이 쌓아 올리다 터짐).
  3. 무거운 C 표준 라이브러리 사용: C 언어의 printf나 화려한 문자열 처리 함수들, 그리고 깊은 라이브러리 트리 호출은 내부적으로 스택을 무지막지하게 잡아먹는다.

결론적으로 wq_rate_ctrl에 탑승하는 모듈은 “가벼운 장비(Float 배열 몇 개)만 들고 타서, 숨도 쉬지 않고 곱셈/덧셈만 미친 듯이 연산한 다음, 0.05ms 안에 버스에서 뛰어내려야 하는” 극강의 달리기 선수(Sprinter)들만을 위한 공간인 것이다.

그렇다면 삼각함수와 행렬 연산이 난무하는 무거운 위치 제어기(Position Controller)나, 용량이 큰 I/O 작업들은 도대체 어느 버스에 타야 할까? 다음 장(21.6.2.1.2)에서 그 대안책인 중간 우선순위 버스 노선들을 탐방해 보자.