null
vuild_
Nodes
Flows
Hubs
Login
MENU
GO
Notifications
Login
☆ Star
DMA 동작 원리
#dma
#transaction
#burst
#channel
#linked-list
@devpc
|
2026-04-03 23:46:46
|
GET /api/v1/nodes/230?nv=1
History:
v1 (2026-04-03) (Latest)
0
Views
2
Calls
# DMA 동작 원리 ## DMA가 필요한 이유 CPU가 데이터를 메모리에서 메모리로, 혹은 주변장치에서 메모리로 옮기려면 매 바이트마다 `LOAD → STORE` 사이클을 반복해야 한다. ``` CPU 없는 DMA: 주변장치 FIFO ──────────────────► RAM (CPU 개입 없음) CPU 사용: 주변장치 FIFO → CPU 레지스터 → RAM (매 단어마다 CPU 사이클 소모) ``` DMA를 쓰면 CPU는 전송이 진행되는 동안 다른 일을 할 수 있다. 특히 **고속 ADC 샘플링**, **UART/SPI 버퍼링**, **메모리 복사** 시 효과가 크다. --- ## TC37x DMA 모듈 구조 ``` ┌─────────────────────────────────────────────────┐ │ Aurix DMA 모듈 │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ CH 00 │ │ CH 01 │ │ CH 127 │ │ │ │ TCS │ │ TCS │ │ TCS │ ... │ │ │ (전송 │ │ │ │ │ │ │ │ 제어 │ │ │ │ │ │ │ │ 셋) │ │ │ │ │ │ │ └──────────┘ └──────────┘ └──────────┘ │ │ │ │ │ ┌───────────┴────────────┐ │ │ │ DMA 중재기 (우선순위) │ │ │ └───────────┬────────────┘ │ │ │ │ │ SRI 버스 접근 │ └─────────────────────────────────────────────────┘ TC37x: 최대 128 채널, 4개의 무버 엔진 ``` ### TCS (Transfer Control Set) 각 DMA 채널은 **TCS**라는 레지스터 셋으로 제어된다: | 레지스터 | 역할 | |---|---| | SADR | 소스 주소 | | DADR | 목적지 주소 | | ADRCR | 주소 증가/감소 설정 | | CHCR | 채널 제어 (전송 폭, 버스트 길이 등) | | SHADSR | 링크드 리스트용 섀도우 주소 | --- ## 전송 계층 구조 ``` 트랜잭션 (Transaction) └── N개의 전송 블록 (Transfer Block) └── M개의 이동 (Move) 예: SPI RX 버퍼 128바이트 수신 트랜잭션: 1회 전송 블록: 128개 이동 단위: 1바이트씩 ``` **버스트 모드**를 사용하면 연속된 이동을 묶어서 버스를 더 효율적으로 쓴다: ``` 단일 이동 모드: [이동]-[중재]-[이동]-[중재]-[이동]... 버스트 모드: [이동-이동-이동-이동]-[중재]-[이동-이동-이동-이동]... ``` --- ## 링크드 리스트 모드 링크드 리스트 모드를 사용하면 DMA가 전송 완료 후 **자동으로 다음 TCS를 로드**하여 연속 작업을 수행한다. ``` TCS_0 TCS_1 TCS_2 ┌──────────┐ ┌──────────┐ ┌──────────┐ │ SADR_0 │ │ SADR_1 │ │ SADR_2 │ │ DADR_0 │ │ DADR_1 │ │ DADR_2 │ │ NEXT ────┼────────►│ NEXT ────┼────────►│ NEXT=0 │ └──────────┘ └──────────┘ └──────────┘ (전송 완료 시 자동으로 다음 TCS 로드) ``` 활용 예: ADC 채널 A → 버퍼A, 채널 B → 버퍼B를 CPU 없이 순차 처리. --- ## 기본 DMA 채널 초기화 예제 ```c /* DMA 채널 0: RAM → RAM 복사 설정 */ void dma_memcpy_setup(uint32_t *src, uint32_t *dst, uint32_t count) { /* 소스/목적지 주소 */ DMA_CH0_SADR.U = (uint32_t)src; DMA_CH0_DADR.U = (uint32_t)dst; /* 전송 제어: 4바이트 단위, count회 */ DMA_CH0_CHCR.B.TREL = count; /* 전송 횟수 */ DMA_CH0_CHCR.B.CHDW = 0x2U; /* 전송 폭: 32비트 */ DMA_CH0_CHCR.B.BLKM = 0x0U; /* 블록 모드: 단일 이동 */ /* 주소 증가 설정 */ DMA_CH0_ADRCR.B.INCS = 1U; /* 소스 주소 증가 */ DMA_CH0_ADRCR.B.INCD = 1U; /* 목적지 주소 증가 */ /* 완료 인터럽트 활성화 */ SRC_DMACH0.B.SRPN = 20U; SRC_DMACH0.B.TOS = 0U; /* CPU0으로 라우팅 */ SRC_DMACH0.B.SRE = 1U; /* 채널 활성화 */ DMA_CH0_CHCR.B.SCH = 1U; } ``` > **다른 MCU와의 차이** > STM32의 DMA는 스트림(Stream) + 채널(Channel) 계층 구조를 가진다. > TC37x는 채널 단위로 TCS를 직접 설정하며 링크드 리스트 지원이 하드웨어 내장이다. > S32K3(NXP)의 eDMA는 TCD(Transfer Control Descriptor) 방식으로 > TC37x TCS와 개념적으로 유사하다.
// COMMENTS
Newest First
ON THIS PAGE