DMA 활용: ADC와 UART를 CPU 없이
ADC 값을 순환 버퍼로 계속 채우고, UART로 길이를 모르는 패킷을 받는 실전 DMA 설정 두 가지.
ADC + 순환 DMA
ADC 스캔 결과를 DMA가 배열에 계속 채웁니다. CPU는 배열을 읽기만 하면 최신 값이 들어 있습니다.
uint16_t adc_buf[4];
HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc_buf, 4); // 순환 모드로 설정해 두면 계속 갱신
긴 파형을 모을 때는 버퍼를 둘로 나눠 절반 완료 / 완료 인터럽트마다 반대쪽 절반을 처리합니다(더블 버퍼링).
UART 수신 + IDLE 라인
패킷 길이를 모를 때의 정석입니다.
- UART RX를 순환 DMA로 큰 버퍼(예: 256바이트)에 계속 받음
- 선이 1바이트 시간 이상 조용하면 IDLE 인터럽트 발생
- DMA 남은 개수(NDTR)로 현재 쓰기 위치를 계산해 새로 들어온 구간만 처리
HAL에는 HAL_UARTEx_ReceiveToIdle_DMA()가 있습니다.
체크할 것
- DMA 스트림과 채널 번호는 주변장치마다 정해져 있습니다(레퍼런스 매뉴얼 표).
- DMA가 접근할 수 없는 메모리 영역이 있는 칩도 있습니다(일부 STM32의 CCM RAM, DTCM).
- 캐시가 있는 칩(H7, F7)은 DMA 버퍼를 캐시 비활성 영역에 두거나 캐시 정리·무효화를 합니다.