TI의 TMS320F28377D는 C2000 Delfino 시리즈의 32비트 마이크로컨트롤러로, 고성능 데이터 처리 및 전송에 최적화된 DMA(Direct Memory Access) 모듈을 제공합니다. DMA는 CPU 개입 없이 메모리 간 데이터 전송을 가능하게 하여 모터 제어, 데이터 로깅, 고속 데이터 수집과 같은 애플리케이션에서 효율적인 데이터 처리를 지원합니다. 이 문서에서는 TMS320F28377D의 DMA 모듈 설정 방법, Bitfield 구조를 활용한 레지스터 설정, 그리고 실용적인 예제 코드를 제공하여 초보자와 숙련된 개발자 모두가 쉽게 활용할 수 있도록 돕겠습니다.
1. TMS320F28377D DMA 모듈 개요
TMS320F28377D는 최대 6개의 독립적인 DMA 채널(CH1~CH6)을 포함하며, 각 채널은 고속 데이터 전송을 지원합니다. 아래는 주요 사양입니다:
- 클럭 소스: 시스템 클럭(SYSCLK, 최대 200MHz)
- 전송 모드:
- 기본 모드: 단일 데이터 블록 전송
- 버스트 모드: 고정 크기 데이터 버스트 전송
- 연속 모드: 반복 전송
- 소스/대상: RAM, 외부 메모리, 주변 장치(ADC, ePWM, SPI, McBSP 등)
- 트리거 소스: 소프트웨어, ADC, ePWM, 외부 인터럽트(XINT), 타이머 등
- 주요 기능:
- 워드 크기: 16비트 또는 32비트
- 인터럽트 지원: 전송 완료, 에러 발생 시
- 채널 우선순위 설정
- 동기화 지원: 다중 채널 간 동기화
- 인터럽트: 전송 완료, 오버런, 에러 이벤트
- 주소 지정 모드:
- 고정 주소
- 증가/감소 주소
- 순환 버퍼 지원
2. DMA Bitfield 설정 상세
TMS320F28377D의 DMA 레지스터는 Bitfield 구조로 정의되어 있으며, F2837xD_dma.h 헤더 파일을 통해 접근합니다. Bitfield는 레지스터의 개별 비트를 명확히 설정하여 코드 가독성과 유지보수성을 높입니다. 주요 레지스터와 Bitfield는 다음과 같습니다:
2.1 DMACTRL (DMA 제어 레지스터)
- bit.HARDRESET: DMA 모듈 리셋 (1: 리셋)
- bit.PRIORITY: 채널 우선순위 (0: 고정, 1: 라운드 로빈)
- bit.PRIORITYRESET: 우선순위 설정 리셋
2.2 MODE (채널 모드 레지스터)
- bit.CHSEL: 채널 선택 (0~5)
- bit.PERINTSEL: 주변 장치 인터럽트 소스 선택 (예: ADCINT1, EPWM1_INT)
- bit.ONESHOT: 단일 전송 모드 (0: 연속, 1: 단일)
- bit.CONTINUOUS: 연속 전송 모드 (1: 활성화)
- bit.DATASIZE: 데이터 크기 (0: 16비트, 1: 32비트)
- bit.BURSTSIZE: 버스트 크기 (0~31 워드)
2.3 CONTROL (채널 제어 레지스터)
- bit.RUN: 전송 시작 (1: 시작)
- bit.HALT: 전송 중지 (1: 중지)
- bit.SOFTRESET: 소프트웨어 리셋 (1: 리셋)
- bit.PERINTCLR: 인터럽트 플래그 클리어
- bit.ERRCLR: 에러 플래그 클리어
2.4 SRC/DST ADDR (소스/대상 주소 레지스터)
- bit.SRC_ADDR: 소스 시작 주소
- bit.DST_ADDR: 대상 시작 주소
- bit.SRC_BEG_ADDR: 소스 순환 버퍼 시작 주소
- bit.DST_BEG_ADDR: 대상 순환 버퍼 시작 주소
2.5 BURST/TRANSFER SIZE
- bit.BURST_SIZE: 버스트당 전송 워드 수
- bit.TRANSFER_SIZE: 전체 전송 워드 수
2.6 SRC/DST STEP (주소 스텝 레지스터)
- bit.SRC_STEP: 소스 주소 증가/감소 값
- bit.DST_STEP: 대상 주소 증가/감소 값
Bitfield 사용 이점:
- 명확한 비트 단위 설정으로 실수 감소
- 코드 가독성 및 유지보수성 향상
- F2837xD_dma.h에서 제공하는 구조체로 직관적 접근
3. DMA 설정 절차
DMA 모듈을 효과적으로 설정하려면 다음 단계를 따라야 합니다:
- 시스템 초기화:
- InitSysCtrl()를 호출하여 시스템 클럭과 PLL을 초기화합니다.
- 인터럽트를 비활성화하고 PIE를 초기화합니다 (DINT, InitPieCtrl, InitPieVectTable).
- DMA 클럭 활성화:
- CpuSysRegs.PCLKCR0.bit.DMA = 1을 설정하여 DMA 모듈 클럭을 활성화합니다.
- 보호된 레지스터 접근을 위해 EALLOW와 EDIS 사용.
- DMA 채널 설정:
- MODE.bit.CHSEL로 채널 선택 (CH1~CH6).
- MODE.bit.PERINTSEL로 트리거 소스 선택 (예: ADCINT1).
- MODE.bit.DATASIZE로 데이터 크기 설정 (16/32비트).
- MODE.bit.ONESHOT 또는 MODE.bit.CONTINUOUS로 전송 모드 설정.
- 소스 및 대상 설정:
- SRC_ADDR와 DST_ADDR로 소스/대상 메모리 주소 설정.
- 순환 버퍼 사용 시 SRC_BEG_ADDR, DST_BEG_ADDR 설정.
- SRC_STEP, DST_STEP으로 주소 증가/감소 설정.
- 버스트 및 전송 크기 설정:
- BURST_SIZE로 버스트당 전송 워드 수 설정.
- TRANSFER_SIZE로 전체 전송 워드 수 설정.
- 인터럽트 설정 (필요 시):
- CONTROL.bit.PERINTSEL로 인터럽트 활성화.
- PIE 벡터 테이블에 ISR(인터럽트 서비스 루틴) 등록.
- DMA 실행:
- CONTROL.bit.RUN = 1로 전송 시작.
- 필요 시 CONTROL.bit.HALT로 전송 중지.
4. DMA 설정 고려사항
- 트리거 소스: 트리거 소스는 애플리케이션에 맞게 선택 (예: ADC 변환 완료, ePWM 이벤트).
- 메모리 정렬: 소스/대상 주소는 16비트 또는 32비트 정렬 필요.
- 우선순위: 다중 채널 사용 시 DMACTRL.bit.PRIORITY로 우선순위 설정.
- 인터럽트: 전송 완료 시 ISR에서 플래그 클리어 (CONTROL.bit.PERINTCLR).
- 에러 처리: 오버런 또는 에러 발생 시 CONTROL.bit.ERRCLR로 플래그 클리어.
- 성능 최적화: 버스트 크기를 최적화하여 CPU 부하 감소.
5. 실용적인 DMA 예제 코드 (Bitfield 구조)
아래는 TMS320F28377D DMA 모듈을 Bitfield 구조로 설정한 3개의 실용적인 예제 코드입니다. 각 예제는 Code Composer Studio(CCS)와 C2000Ware 환경에서 실행 가능합니다.
5.1 예제 1: ADC 데이터를 RAM으로 전송
#include "F28x_Project.h"
volatile Uint16 adcBuffer[256]; // ADC 데이터 저장 버퍼
void main(void) {
// 시스템 초기화
InitSysCtrl(); // 시스템 클럭 및 PLL 초기화
DINT; // 모든 인터럽트 비활성화
InitPieCtrl(); // PIE 초기화
IER = 0x0000; // CPU 인터럽트 비활성화
IFR = 0x0000; // 대기 중인 인터럽트 플래그 지우기
InitPieVectTable(); // PIE 벡터 테이블 초기화
// GPIO 및 ADC 설정
EALLOW;
GpioCtrlRegs.GPBDIR.bit.GPIO31 = 1; // GPIO31을 출력(LED)으로 설정
GpioDataRegs.GPBSET.bit.GPIO31 = 1; // LED 켜기
AdcSetMode(ADC_ADCA, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE);
AdcaRegs.ADCCTL2.bit.PRESCALE = 6; // ADC 클럭 분주
AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1; // 인터럽트 펄스 위치
AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1; // ADC 전원 활성화
AdcaRegs.ADCSOC0CTL.bit.CHSEL = 0; // ADC 채널 A0
AdcaRegs.ADCSOC0CTL.bit.ACQPS = 15; // 샘플링 윈도우
AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 5; // ePWM1 SOCA 트리거
EDIS;
// ePWM1 설정 (ADC 트리거용)
EALLOW;
CpuSysRegs.PCLKCR2.bit.EPWM1 = 1; // ePWM1 모듈 클럭 활성화
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // 업 카운트 모드
EPwm1Regs.TBCTL.bit.CLKDIV = 0; // 클럭 분주비 1/1
EPwm1Regs.TBCTL.bit.HSPCLKDIV = 1; // 고속 클럭 분주비 1/1
EPwm1Regs.TBPRD = 2000; // 주기 = 2000 TBCLK (100kHz)
EPwm1Regs.ETSEL.bit.SOCAEN = 1; // SOCA 활성화
EPwm1Regs.ETSEL.bit.SOCASEL = ET_CTR_ZERO; // TBCTR=0일 때 SOCA 발생
EPwm1Regs.ETPS.bit.SOCAPRD = 1; // 첫 번째 이벤트에서 SOCA 발생
EPwm1Regs.TBCTL.bit.FREE_SOFT = 2; // Free run 모드
EDIS;
// DMA 클럭 활성화
EALLOW;
CpuSysRegs.PCLKCR0.bit.DMA = 1; // DMA 클럭 활성화
EDIS;
// DMA 채널 1 설정 (Bitfield 사용)
DMAInitialize(); // DMA 초기화
DMACH1AddrConfig(&adcBuffer[0], &AdcaResultRegs.ADCRESULT0); // 소스: ADC, 대상: RAM
DMACH1BurstConfig(0, 1, 1); // 버스트 크기: 1 워드, 소스/대상 스텝: 1
DMACH1TransferConfig(255, 1, 1); // 전송 크기: 256 워드
DMACH1WrapConfig(0xFFFF, 0, 0xFFFF, 0); // 순환 버퍼 비활성화
DMACH1ModeConfig(DMA_ADCAINT1, PERINT_ENABLE, ONESHOT_DISABLE,
CONT_ENABLE, SYNC_DISABLE, SYNC_SRC,
DATASIZE_16BIT, CH1_ENABLE); // ADCINT1 트리거, 16비트 데이터
StartDMACH1(); // DMA 채널 1 시작
for(;;); // 무한 루프
}
설명:
- 기능: ADC 채널 A0의 데이터를 DMA 채널 1을 통해 RAM 버퍼(adcBuffer)로 전송.
- 설정: ADC는 ePWM1 SOCA로 트리거, 100kHz 샘플링, DMA는 256 워드 전송, 16비트 데이터.
- GPIO: GPIO31(LED).
- 출력: ADC 데이터가 adcBuffer에 저장, 정상 동작 시 LED ON.
5.2 예제 2: RAM 간 데이터 전송 (소프트웨어 트리거)
#include "F28x_Project.h"
volatile Uint16 srcBuffer[256]; // 소스 버퍼
volatile Uint16 dstBuffer[256]; // 대상 버퍼
void main(void) {
// 시스템 초기화
InitSysCtrl(); // 시스템 클럭 및 PLL 초기화
DINT; // 모든 인터럽트 비활성화
InitPieCtrl(); // PIE 초기화
IER = 0x0000; // CPU 인터럽트 비활성화
IFR = 0x0000; // 대기 중인 인터럽트 플래그 지우기
InitPieVectTable(); // PIE 벡터 테이블 초기화
// GPIO 설정
EALLOW;
GpioCtrlRegs.GPBDIR.bit.GPIO31 = 1; // GPIO31을 출력(LED)으로 설정
GpioDataRegs.GPBSET.bit.GPIO31 = 1; // LED 켜기
EDIS;
// 소스 버퍼 초기화
Uint16 i;
for (i = 0; i < 256; i++) {
srcBuffer[i] = i; // 테스트 데이터
}
// DMA 클럭 활성화
EALLOW;
CpuSysRegs.PCLKCR0.bit.DMA = 1; // DMA 클럭 활성화
EDIS;
// DMA 채널 1 설정 (Bitfield 사용)
DMAInitialize(); // DMA 초기화
DMACH1AddrConfig(&dstBuffer[0], &srcBuffer[0]); // 소스: srcBuffer, 대상: dstBuffer
DMACH1BurstConfig(7, 1, 1); // 버스트 크기: 8 워드
DMACH1TransferConfig(31, 1, 1); // 전송 크기: 32 버스트 (256 워드)
DMACH1WrapConfig(0xFFFF, 0, 0xFFFF, 0); // 순환 버퍼 비활성화
DMACH1ModeConfig(0, PERINT_DISABLE, ONESHOT_ENABLE,
CONT_DISABLE, SYNC_DISABLE, SYNC_SRC,
DATASIZE_16BIT, CH1_ENABLE); // 소프트웨어 트리거, 16비트 데이터
StartDMACH1(); // DMA 채널 1 시작
for(;;); // 무한 루프
}
설명:
- 기능: RAM 내 srcBuffer의 데이터를 DMA 채널 1을 통해 dstBuffer로 전송 (소프트웨어 트리거).
- 설정: 256 워드 전송, 16비트 데이터, 버스트 크기 8 워드, 총 32 버스트.
- GPIO: GPIO31(LED).
- 출력: srcBuffer 데이터가 dstBuffer로 복사, 정상 동작 시 LED ON.
5.3 예제 3: DMA 인터럽트 기반 데이터 전송
#include "F28x_Project.h"
volatile Uint16 srcBuffer[256]; // 소스 버퍼
volatile Uint16 dstBuffer[256]; // 대상 버퍼
volatile Uint16 transferComplete = 0; // 전송 완료 플래그
__interrupt void dma_ch1_isr(void) {
DmaRegs.CH1.CONTROL.bit.PERINTCLR = 1; // 인터럽트 플래그 클리어
transferComplete = 1; // 전송 완료 표시
PieCtrlRegs.PIEACK.all = PIEACK_GROUP7; // PIE 그룹 7 ACK
}
void main(void) {
// 시스템 초기화
InitSysCtrl(); // 시스템 클럭 및 PLL 초기화
DINT; // 모든 인터럽트 비활성화
InitPieCtrl(); // PIE 초기화
IER = 0x0000; // CPU 인터럽트 비활성화
IFR = 0x0000; // 대기 중인 인터럽트 플래그 지우기
InitPieVectTable(); // PIE 벡터 테이블 초기화
// 인터럽트 벡터 설정
EALLOW;
PieVectTable.DMA_CH1_INT = &dma_ch1_isr; // DMA 채널 1 인터럽트 벡터
EDIS;
// GPIO 설정
EALLOW;
GpioCtrlRegs.GPBDIR.bit.GPIO31 = 1; // GPIO31을 출력(LED)으로 설정
GpioDataRegs.GPBSET.bit.GPIO31 = 1; // LED 켜기
EDIS;
// 소스 버퍼 초기화
Uint16 i;
for (i = 0; i < 256; i++) {
srcBuffer[i] = i; // 테스트 데이터
}
// DMA 클럭 활성화
EALLOW;
CpuSysRegs.PCLKCR0.bit.DMA = 1; // DMA 클럭 활성화
EDIS;
// DMA 채널 1 설정 (Bitfield 사용)
DMAInitialize(); // DMA 초기화
DMACH1AddrConfig(&dstBuffer[0], &srcBuffer[0]); // 소스: srcBuffer, 대상: dstBuffer
DMACH1BurstConfig(7, 1, 1); // 버스트 크기: 8 워드
DMACH1TransferConfig(31, 1, 1); // 전송 크기: 32 버스트 (256 워드)
DMACH1WrapConfig(0xFFFF, 0, 0xFFFF, 0); // 순환 버퍼 비활성화
DMACH1ModeConfig(0, PERINT_ENABLE, ONESHOT_ENABLE,
CONT_DISABLE, SYNC_DISABLE, SYNC_SRC,
DATASIZE_16BIT, CH1_ENABLE); // 소프트웨어 트리거, 인터럽트 활성화
PieCtrlRegs.PIEIER7.bit.INTx1 = 1; // PIE 그룹 7, DMA CH1 인터럽트 활성화
IER |= M_INT7; // CPU 인터럽트 7 활성화
EINT; // 글로벌 인터럽트 활성화
StartDMACH1(); // DMA 채널 1 시작
// 전송 완료 대기
while (!transferComplete); // 전송 완료까지 대기
GpioDataRegs.GPBTOGGLE.bit.GPIO31 = 1; // LED 토글 (완료 표시)
for(;;); // 무한 루프
}
설명:
- 기능: RAM 내 srcBuffer의 데이터를 DMA 채널 1을 통해 dstBuffer로 전송, 전송 완료 시 인터럽트 발생.
- 설정: 256 워드 전송, 16비트 데이터, 버스트 크기 8 워드, 총 32 버스트, 인터럽트 활성화.
- GPIO: GPIO31(LED).
- 완료 동작: 전송 완료 시 transferComplete 플래그 설정, LED 토글.
6. 사용 방법
6.1 환경 설정
- C2000Ware 설치: C:\ti\c2000\C2000Ware_x_xx_xx_xx에서 라이브러리 다운로드.
- CCS 프로젝트: TMS320F28377D 타겟으로 프로젝트 생성, F28x_Project.h 포함.
- 링커 파일: device_support\f2837xd 폴더에서 링커 파일 추가.
6.2 코드 실행
- 각 예제를 별도의 .c 파일로 저장하거나, main.c에 복사.
- 원하는 예제만 실행되도록 다른 코드 주석 처리.
6.3 하드웨어 준비
- ADC 입력: 예제 1의 경우, ADC A0 핀에 아날로그 입력 연결.
- LED: GPIO31에 LED 연결 (정상 동작 확인용).
- 디버깅 장비: CCS와 JTAG 디버거로 변수 및 메모리 점검.
6.4 디버깅
- CCS Expressions 창: adcBuffer, dstBuffer 확인.
- 레지스터 점검: DmaRegs.CH1.CONTROL, DmaRegs.CH1.BURST_SIZE 모니터링.
- 인터럽트 확인: DmaRegs.CH1.CONTROL.bit.PERINTFLG로 인터럽트 상태 점검.
- 에러 확인: DmaRegs.CH1.CONTROL.bit.ERRFLG로 에러 상태 점검.
7. 추가 팁
- 캘리브레이션: ADC 사용 시 Device_cal() 호출로 클럭 보정.
- 노이즈 감소: ADC 입력에 저역통과 필터 사용.
- C2000Ware 참고: C:\ti\c2000\C2000Ware_x_xx_xx_xx\device_support\f2837xd\examples\cpu1\dma.
- 문제 해결:
- 데이터 전송 실패: SRC_ADDR, DST_ADDR 정렬 확인.
- 인터럽트 미발생: MODE.bit.PERINTSEL, PieCtrlRegs.PIEIER7 확인.
- DMA 미작동: CpuSysRegs.PCLKCR0.bit.DMA 및 CONTROL.bit.RUN 확인.
- TI 리소스: TI E2E 포럼, C2000Ware 예제.
8. 결론
이 문서는 TMS320F28377D DMA 모듈의 설정 방법과 Bitfield 구조를 활용한 예제 코드를 제공하여, 초보자부터 숙련된 개발자까지 쉽게 활용할 수 있도록 구성했습니다. ADC 데이터 전송, RAM 간 데이터 전송, 인터럽트 기반 전송 예제를 통해 다양한 애플리케이션에 적용 가능합니다.
키워드: TMS320F28377D, DMA, C2000, 데이터 전송, 마이크로컨트롤러, Code Composer Studio, ADC, RAM 전송, 인터럽트, 버스트 모드, 순환 버퍼
'MCU > C2000' 카테고리의 다른 글
[TMS320F28377D] USB, I2C, McBSP, uPP 사용법 : Bitfield 구조 활용 예제 코드 (0) | 2025.08.18 |
---|---|
[TMS320F28377D] SDFM 사용법 : Bitfield 구조 활용 예제 코드 (1) | 2025.08.18 |
[TMS320F28377D] ePWM CMPASS 사용법: Bitfield 구조 활용 예제 코드 (0) | 2025.08.18 |
[TMS320F28377D] SPI 사용법 : Bitfield 구조 활용 예제 코드 (2) | 2025.08.18 |
[TMS320F28377D] CLA 사용법 : Bitfield 구조 활용 예제 코드 (1) | 2025.08.18 |
[TMS320F28377D] CPU1, CPU2 멀티코어 사용법 : Bitfield 구조 활용 예제 코드 (1) | 2025.08.18 |
[TMS320F28377D] EMIF 사용법 : Bitfield 구조 활용 예제 코드 (1) | 2025.08.17 |
[TMS320F28377D] eCAP 사용법 : Bitfield 구조 활용 예제 코드 (1) | 2025.08.17 |