임베디드 소프트웨어 엔지니어 면접: 실제 시나리오 문제 분석
임베디드 소프트웨어 엔지니어의 면접에서는 알고리즘 문제가 단순한 입문일 뿐, 진정으로 중요한 것은 하드웨어와 소프트웨어를 결합한 실제 상황 문제입니다. 이러한 문제는 코딩 능력뿐만 아니라 임베디드 시스템의 특성 이해, 리소스 관리 의식 및 공학적 사고를 평가합니다.
1. 저전력 센서 펌웨어 업데이트 메커니즘 설계
시나리오 설명: 외부에 배치된 온습도 센서의 펌웨어 업데이트 방안을 설계해야 합니다. 장치는 배터리로 구동되며 LoRaWAN을 통해 데이터 전송이 이루어지고, Flash 저장 공간은 256KB만 가능합니다.
typedef struct {
uint32_t magic_num;
uint16_t ver_major;
uint16_t ver_minor;
uint32_t checksum;
uint32_t img_size;
uint32_t entry_addr;
} firmware_hdr_t;
증분 업데이트 방식을 사용하여 네트워크 대역폭과 에너지를 최소화하고, 신뢰성을 확보합니다.
2. 리소스 제약 MCU에서 비차단 CLI 구현
시나리오 설명: 32KB RAM만 있는 STM32F0 시리즈 MCU에서 명령 줄 인터페이스(CLI)를 구현해야 합니다. 사용자 입력 처리와 장치 상태 모니터링을 동시에 수행하면서 입력 지연이 발생하지 않도록 해야 합니다.
#define CLI_BUF_LEN 128
typedef struct {
char buffer[CLI_BUF_LEN];
volatile uint16_t head;
volatile uint16_t tail;
} cli_buffer_t;
void USART1_ISR(void) {
if(USART1->ISR & USART_ISR_RXNE) {
uint8_t ch = USART1->RDR;
cli_buffer.buffer[cli_buffer.head++] = ch;
cli_buffer.head %= CLI_BUF_LEN;
}
}
중단 드라이브와 유한 상태 기계를 혼합하여 실시간 응답성을 보장합니다.
3. 실시간 데이터 수집 시스템의 메모리 관리
시나리오 설명: 8채널 16비트 ADC 데이터 수집 시스템을 설계해야 합니다. 샘플링 속도는 1kHz이며 각 채널의 RMS 값을 실시간으로 계산해야 하고 최근 10초 동안의 원본 데이터를 유지해야 합니다.
typedef struct {
uint32_t time_mark;
float rms_vals[8];
uint16_t peak_vals[8];
} compressed_blk_t;
데이터 압축과 DMA 이중 버퍼 모드를 활용하여 메모리 효율성을 극대화합니다.
4. 다중 작업 시스템 내 우선 순위 역전 문제
시나리오 설명: FreeRTOS를 사용하는 시스템에서 고우선순위 작업 A가 낮은 우선순위 작업 C로부터 세마포어를 기다리고 있지만 중간 우선순위 작업 B에 의해 차단됩니다.
SemaphoreHandle_t xMutex = xSemaphoreCreateMutex();
if(xMutex == NULL) {
// 오류 처리
}
if(xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) {
// 공유 자원 접근
xSemaphoreGive(xMutex);
}
우선 순위 상속 또는 천장 설정을 통해 문제를 해결할 수 있습니다.
5. 하드웨어 예외의 진단 및 복구
시나리오 설명: 현장 장치에서 가끔 HardFault가 발생하므로 장애 발생 시 주요 정보를 기록하고 안전하게 복구하는 메커니즘을 설계해야 합니다.
__attribute__((naked)) void HardFault_Handler(void) {
__asm volatile(
"tst lr, #4\n"
"ite eq\n"
"mrseq r0, msp\n"
"mrsne r0, psp\n"
"b HardFault_Handler_C\n"
);
}
void HardFault_Handler_C(uint32_t* stack_frame) {
uint32_t reg0 = stack_frame[0];
uint32_t reg1 = stack_frame[1];
uint32_t reg2 = stack_frame[2];
uint32_t reg3 = stack_frame[3];
uint32_t reg12 = stack_frame[4];
uint32_t lr = stack_frame[5];
uint32_t pc = stack_frame[6];
uint32_t psr = stack_frame[7];
save_fault_dump(reg0, reg1, reg2, reg3, reg12, lr, pc, psr);
NVIC_SystemReset();
}
장애 진단 후 적절한 복구 전략을 적용하여 시스템을 안정적으로 운영합니다.