Lec. 18. DMA(Direct Memory Access)
DMA
Direct memory access
프로그램 명령어 없이 주변 하드웨어에 의해 수행되는 메모리 접근 Basic DMA operations
- 전송 시작: 트리거 이벤트가 전송을 시작합니다. (일반적으로 소프트웨어에 의해 관리됨)
- 데이터 읽기: DMA 컨트롤러가 MCU의 주소 및 데이터 버스를 제어하여 소스 위치에서 데이터를 읽습니다. (소스 주소 레지스터에 의해 지정되며, 이 주소는 메모리나 주변 장치일 수 있음)
- 데이터 쓰기: DMA 컨트롤러는 주소 및 데이터 버스를 사용하여 데이터를 목적지 위치에 씁니다. (목적지 주소 레지스터에 의해 지정됨)
- 버스 해제: DMA 컨트롤러는 CPU가 버스를 사용할 수 있도록 버스를 해제합니다. (선택 사항)
- 주소 증가: DMA 컨트롤러는 다음 전송을 위해 소스 및 목적지 주소 레지스터를 증가시킵니다.
- 카운트 업데이트: DMA 컨트롤러는 전송된 항목 수를 추적하는 카운트 레지스터를 업데이트합니다. 전송할 항목이 더 있는 경우, 이 과정은 2단계부터 반복됩니다.
- 전송 완료 알림: DMA 컨트롤러는 최종 전송이 완료되었음을 상태 플래그를 설정하고 인터럽트를 트리거함으로써 알립니다. (인터럽트가 활성화된 경우) -> 다른 작업 가능
Variations
- 특정 경우에는 DMA 컨트롤러가 동일한 값을 모든 목적지에 복사하거나, 동일한 소스로부터 연속적인 값을 읽어들이기를 원할 수 있음
- Two transfer modes
- continuous (burst) mode: 트리거되면 DMA 컨트롤러가 버스를 점유하여 전송이 완료될 때까지 데이터 전송을 멈추지 않고 계속합니다.
- cycle-stealing(time-sharing) mode: DMA 컨트롤러가 MCU와 버스를 공유한다. 매 트리거마다 버스를 제어하여 하나의 항목을 전송한 후 버스를 MCU에 양보한다.
Using DMA operation
- 버퍼를 지운다
- 데이터 구조를 초기화한다
- 프레임버퍼에 이미지를 복사한다 DMA 컨트롤러가 다른 peripheral 모듈과 함께 사용되면 문제가 발생할 수 있다 DMA operation을 사용해서 전체적인 전력 소모를 줄여줄 수 있다.(CPU가 sleep이나 low frequency 모드가 되는 것을 허용)
KL25Z DMA Controller
DMA 전송은 소프트웨어의 쓰기 동작 또는 하드웨어의 트리거 이벤트에 의해 발생한다.
- DMA_MUX 하드웨어 트리거에 맞는 적절한 input 설정
DMAMUXx_CHCFGn control register (x=0,1,2,3)
- ENBL: 1인 경우 DMA 채널 활성화
- TRIG: 1인 경우 DMA 채널의 트리거링을 활성화
- SOURCE: 트리거 소스들 중 하나를 선택
Controller uses a number of registers for the basic operation.
- Source address register (SAR)
- Destination address register (DAR)
- DMA_DCRn register: DMA 명령을 정의해준다.
- DMA_DSR_BCRn register: byte count register
Fields for defining the basic aspects of the transfer
- BCR (DMA_DSR_BCRn 19~0)
- 전송해줄 바이트의 개수
- 각각의 DMA 전송 이후에, 하드웨어는 전송된 바이트 개수만큼 BCR을 감소시킨다.
- SSIZE / DSIZE (DMA_DCRn)
- source/destination의 데이터 크기를 설정
- 00 -> 32bit
- 10 -> 16bit
- 01 -> 8bit
- SINC / DINC: SAR DAR을 데이터 사이즈(SSIZE/DSIZE)만큼 증가할지 말지 결정(1->증가 0 -> x)
- SMOD / DMOD (DMA_DCRn)
- 0이 아닌 값의 경우, 원형 버퍼를 제공하기 위해 이동시켜주어야 하는 주소의 크기를 정의함.
- Circular buffer의 크기를 정의
- CS (DMA_DCRn)
- 전송모드 설정 (cycle-stealing(1) 또는 continuous mode(0))
- AA (DMA_DCRn)
- 하드웨어가 주소를 자동적으로 정렬하게끔 허락한다.
- CPU가 32bit 연산이 제일 빠르기 때문에 4byte씩 정보를 처리해주는데 이를 위해서 자동적으로 정렬 과정을 수행해줌
Fields for starting the transfer
- ERQ() - enable request
- 1 -> 하드웨어 트리거에 대해서 peripheral 이 전송시작을 요구하는 것을 가능하게 함
- START()
- 1 -> 소프트웨어 트리거 전송 시작
Fields for indicating errors
- CE (in DMA_DSR_BCRn)
- Configuration error 설정 에러 발생
- BES/BED (in DMA_DSR_BCRn)
- source/destination의 버스 에러
Fields for indicating the current progress
- REQ (in DMA_DSR_BCRn)
- 1 -> 전송이 요청됐지만 시작되지 않음
- BSY (in DMA_DSR_BCRn)
- 1 -> 채널이 전송을 시작한 시간부터 끝난 시간까지 1
- DONE (in DMA_DSR_BCRn)
- 모든 전송을 완료하면 1이됨
- DMA가 인터럽트를 발생시킬 때, ISR에 의해 클리어된다.
Fields for the interrupt
- EINT (DMA_DCRn) - enable interrupt
- 전송이 끝난 다음에 DMA 인터럽트를 활성화해줌
Fields for the linked (or triggered) channel
- CH0은 cycle-stealing 전송 이후에 CH1을 트리거
- CH1은 CH1의 BCR이 0에 도달하면 CH2를 트리거
- LINKCC (in DMA_DCRn)
- 채널들을 어떻게 연결해줄지 표현
- LCH1 / LCH2 (in DMA_DCRn)
- CH1, CH2 트리거 bit
Basic DMA configuration and use
Basic configuration
- DMA 모듈의 클럭 게이팅 활성화:
- SIM->SCGC7에서 DMA 모듈로의 클럭 게이팅을 활성화합니다.
- 하드웨어 트리거링 사용 시, DMAMUX 모듈의 클럭 게이팅 활성화:
- 하드웨어 트리거링이 사용되는 경우, SIM->SCGC6에서 DMAMUX(DMA Multiplexer) 모듈로의 클럭 게이팅을 활성화합니다.
- 하드웨어 트리거링 사용 시, DMA 채널 비활성화:
- 하드웨어 트리거링이 사용되는 경우, DMAMUX0의 채널의 CHCFG필드를 0으로 설정하여 DMA 채널을 잠시 비활성화합니다. -> 나중에 다시 활성화 해줌
- DMA 채널 n의 제어 레지스터 초기화:
- DMA 채널 n에 대한 제어 레지스터를 초기화합니다.
- 소스 및 목적지 주소 레지스터(SARn, DARn) 로드:
- SARn와 DARn에 소스 및 목적지 주소를 로드합니다.
- 전송할 바이트 수를 BCRn에 로드:
- BCRn에 전송할 바이트 수를 로드합니다.
- DSRn의 DONE 플래그를 클리어하여 컨트롤러 초기화:
- DSRn의 DONE 플래그를 클리어하여 DMA 컨트롤러를 초기화합니다.
- 하드웨어 트리거링 사용 시:
- DMA 채널 활성화:
- DMAMUX0의 채널의 CHCFG 필드에 트리거 소스 번호를 써서 DMA 채널을 활성화합니다.
- 주변 장치 트리거 활성화:
- ERQ 플래그를 1로 설정하여 주변 장치 트리거를 활성화합니다.
- DMA 채널 활성화:
- 인터럽트 사용 시, EINT 플래그 설정:
- 인터럽트가 사용되는 경우, EINT 플래그를 1로 설정합니다.
- 소프트웨어 트리거 DMA 사용 시, START 플래그 설정:
- 소프트웨어 트리거 DMA를 사용하는 경우, START 플래그를 설정하여 DMA 채널을 트리거합니다.
Init_DMA_To_Copy(void)
: DMA 설정을 초기화하는 함수입니다.SIM->SCGC7 |= SIM_SCGC7_DMA_MASK;
: DMA 모듈의 클록을 활성화합니다.DMA0->DMA[0].DCR = DMA_DCR_SINC_MASK | DMA_DCR_SSIZE(0) | DMA_DCR_DINC_MASK | DMA_DCR_DSIZE(0);
: DMA 제어 레지스터(DCR)를 설정합니다. 여기서는 소스 주소 증가, 소스 크기 설정, 목적지 주소 증가, 목적지 크기 설정 등의 옵션을 설정합니다.- SIZE(0)->32bit
Copy_Longwords(uint32_t *source, uint32_t *dest, uint32_t count)
: DMA를 사용하여 데이터를 복사하는 함수입니다.DMA0->DMA[0].SAR = DMA_SAR_SAR((uint32_t) source);
: 소스 주소 레지스터(SAR)를 소스 배열의 시작 주소로 설정합니다.DMA0->DMA[0].DAR = DMA_DAR_DAR((uint32_t) dest);
: 목적지 주소 레지스터(DAR)를 목적지 배열의 시작 주소로 설정합니다.DMA0->DMA[0].DSR_BCR = DMA_DSR_BCR_BCR(count * 4);
: 전송할 데이터의 총 바이트 수를 설정합니다.- count*4 : 4바이트
DMA0->DMA[0].DSR_BCR &= ~DMA_DSR_BCR_DONE_MASK;
: 완료 플래그를 클리어합니다.DMA0->DMA[0].DCR |= DMA_DCR_START_MASK;
: DMA 전송을 시작합니다.while (!(DMA0->DMA[0].DSR_BCR & DMA_DSR_BCR_DONE_MASK));
: 전송이 완료될 때까지 대기합니다.
Test_DMA_Copy(void)
: DMA 복사를 테스트하는 함수입니다.Init_DMA_To_Copy();
: DMA 설정을 초기화합니다.for (i=0; i<ARR_SIZE; i++) { s[i] = i; d[i] = 0; }
: 소스 배열s
는 인덱스 값으로 초기화하고, 목적지 배열d
는 0으로 초기화합니다.Copy_Longwords(s, d, ARR_SIZE);
:s
배열의 데이터를d
배열로 복사합니다.