1. TMS320F28335 DMA 모듈 개요
TI의 TMS320F28335는 C2000 Delfino 시리즈의 32비트 마이크로컨트롤러로, 고속 데이터 전송을 위한 DMA(Direct Memory Access) 모듈을 제공합니다. DMA 모듈은 CPU의 개입 없이 메모리 간 데이터 전송을 수행하여 ADC 데이터 처리, 메모리 복사, 외부 인터페이스 데이터 전송 등에 적합합니다. 이 문서에서는 TMS320F28335 DMA 모듈의 설정 방법, Bitfield 구조를 활용한 레지스터 설정, 그리고 실용적인 예제 코드를 제공하여 초보자와 숙련된 개발자 모두 쉽게 활용할 수 있도록 돕습니다.
주요 사양
- 채널 수: 6개의 독립적인 DMA 채널 (채널 1~6)
- 전송 모드:
- 블록 전송: 고정된 데이터 블록 전송
- 버스트 전송: 작은 데이터 단위 전송
- 트리거 소스:
- 소프트웨어 트리거
- ADC, ePWM, McBSP, XINT 등 하드웨어 트리거
- 데이터 크기: 16비트 또는 32비트 워드
- 주소 모드: 증가, 감소, 고정
- 인터럽트: 전송 완료, 에러 시 인터럽트 지원
- 메모리 액세스: 내부 RAM, 외부 메모리, 주변 장치 레지스터
- 클럭 소스: 시스템 클럭(SYSCLK, 최대 150MHz)
2. DMA Bitfield 설정 상세
TMS320F28335의 DMA 레지스터는 Bitfield 구조로 정의되어 있으며, F2833x_dma.h 헤더 파일을 통해 접근합니다. 주요 레지스터는 다음과 같습니다:
2.1 DMACTRL (DMA 제어 레지스터)
- bit.HARDRESET: DMA 모듈 리셋 (1: 리셋)
- bit.PRIORITY: 채널 우선순위 (0: 고정, 1: 라운드 로빈)
- bit.PRIORITYRESET: 우선순위 리셋
2.2 MODE (채널 모드 레지스터)
- bit.CHxEN: 채널 활성화 (1: 활성화, x=1~6)
- bit.DATASIZE: 데이터 크기 (0: 16비트, 1: 32비트)
- bit.CONTINUOUS: 연속 모드 (1: 활성화)
- bit.ONESHOT: 원샷 모드 (1: 활성화)
- bit.TRIGMODE: 트리거 모드 (0: 소프트웨어, 1: 하드웨어)
- bit.SYNCE: 동기화 활성화 (1: 활성화)
- bit.OVRINTE: 오버플로우 인터럽트 활성화
2.3 CONTROL (채널 제어 레지스터)
- bit.RUN: 전송 시작 (1: 시작)
- bit.STOP: 전송 정지 (1: 정지)
- bit.SOFTRESET: 채널 소프트 리셋
- bit.TRANSFERSTS: 전송 상태 플래그
- bit.ERRCLR: 에러 플래그 클리어
2.4 BURST_SIZE (버스트 크기 레지스터)
- bit.BURSTSIZE: 버스트당 전송 워드 수 (0~31)
2.5 SRC/DST_ADDR (소스/목적지 주소 레지스터)
- bit.SRCADDR: 소스 메모리 주소
- bit.DSTADDR: 목적지 메모리 주소
2.6 TRANSFER_SIZE (전송 크기 레지스터)
- bit.TRANSFERSIZE: 전체 전송 워드 수
3. DMA 설정 절차
- 시스템 초기화:
- InitSysCtrl()로 시스템 클럭과 PLL 초기화
- 인터럽트 비활성화 및 PIE 초기화 (DINT, InitPieCtrl, InitPieVectTable)
- DMA 클럭 활성화:
- CpuSysRegs.PCLKCR0.bit.DMA = 1로 DMA 모듈 클럭 활성화
- 보호된 레지스터 접근을 위해 EALLOW와 EDIS 사용
- DMA 채널 설정:
- MODE.bit.CHxEN으로 채널 활성화
- MODE.bit.DATASIZE로 데이터 크기 설정 (16비트/32비트)
- MODE.bit.TRIGMODE로 트리거 소스 설정
- 소스 및 목적지 설정:
- SRC_ADDR와 DST_ADDR로 소스/목적지 메모리 주소 설정
- 주소 모드 설정 (증가/감소/고정)
- 버스트 및 전송 크기 설정:
- BURST_SIZE.bit.BURSTSIZE로 버스트 크기 설정
- TRANSFER_SIZE.bit.TRANSFERSIZE로 전체 전송 크기 설정
- 인터럽트 설정 (필요 시):
- MODE.bit.OVRINTE로 오버플로우 인터럽트 활성화
- PieVectTable.DMAx_INT로 인터럽트 벡터 설정
- DMA 실행:
- CONTROL.bit.RUN = 1로 전송 시작
4. DMA 설정 고려사항
- 메모리 정렬: 소스/목적지 주소는 워드(16비트) 단위로 정렬
- 트리거 선택: ADC, ePWM, McBSP 등 하드웨어 트리거와 동기화
- 우선순위: 다중 채널 사용 시 우선순위 설정 필요
- 인터럽트: 전송 완료 인터럽트로 데이터 처리 최적화
- 에러 처리: 오버플로우, 주소 에러 확인 및 처리
- 성능 최적화: 버스트 크기와 전송 크기 최적화로 대역폭 활용
5. 실용적인 DMA 예제 코드 (Bitfield 구조)
아래는 TMS320F28335 DMA 모듈을 Bitfield 구조로 설정한 예제 코드들입니다. GPIO와 DMA 설정은 별도의 함수로 분리되었으며, 각 라인에 상세한 주석이 추가되었습니다. Code Composer Studio(CCS)와 C2000Ware 환경에서 실행 가능합니다.
5.1 예제 1: ADC 데이터 DMA 전송
// File: dma_adc_transfer.c
// Description: TMS320F28335 DMA를 사용한 ADC 데이터 전송 예제
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28335
#include "F28x_Project.h"
volatile Uint16 AdcBuffer[256]; // DMA 목적지 버퍼: ADC 데이터 저장
// 인터럽트 서비스 루틴: DMA 채널 1 인터럽트 처리
__interrupt void dma_ch1_isr(void)
{
DmaRegs.CH1.CONTROL.bit.TRANSFERSTS = 0; // 전송 상태 플래그 클리어
DmaRegs.CH1.CONTROL.bit.ERRCLR = 1; // 에러 플래그 클리어
PieCtrlRegs.PIEACK.all = PIEACK_GROUP7; // PIE 그룹 7 인터럽트 ACK
}
// GPIO 설정 함수
void ConfigureGPIO(void) {
EALLOW; // 보호된 레지스터 접근 허용
GpioCtrlRegs.GPBDIR.bit.GPIO34 = 1; // GPIO34를 출력으로 설정 (LED용)
GpioDataRegs.GPBSET.bit.GPIO34 = 1; // GPIO34를 High로 설정하여 LED 켬
EDIS; // 보호된 레지스터 접근 비허용
}
// ADC 설정 함수
void ConfigureADC(void) {
EALLOW; // 보호된 레지스터 접근 허용
AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1; // ADC 인터럽트 펄스 위치: 변환 완료 시
AdcRegs.ADCCTL1.bit.ADCENABLE = 1; // ADC 모듈 활성화
AdcRegs.ADCCTL1.bit.ADCBGPWD = 1; // 백그라운드 전원 활성화
AdcRegs.ADCCTL1.bit.ADCPWDN = 1; // ADC 전원 활성화
AdcRegs.ADCSOC0CTL.bit.CHSEL = 0; // ADC 채널 A0 선택
AdcRegs.ADCSOC0CTL.bit.ACQPS = 6; // 샘플링 윈도우 설정 (7 사이클)
AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 5; // 트리거 소스: ePWM1 SOCA
EDIS; // 보호된 레지스터 접근 비허용
}
// ePWM1 설정 함수 (ADC 트리거용)
void ConfigureEPWM1(void) {
EALLOW; // 보호된 레지스터 접근 허용
CpuSysRegs.PCLKCR1.bit.EPWM1 = 1; // ePWM1 모듈 클럭 활성화
EDIS; // 보호된 레지스터 접근 비허용
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // 타임-베이스 카운터를 업 카운트 모드로 설정
EPwm1Regs.TBCTL.bit.CLKDIV = 0; // 클럭 분주비 1/1 (SYSCLK = 150MHz)
EPwm1Regs.TBCTL.bit.HSPCLKDIV = 2; // 고속 클럭 분주비 1/2 (TBCLK = 75MHz)
EPwm1Regs.TBPRD = 750; // 주기 레지스터 설정: 100kHz (10us)
EPwm1Regs.CMPA.bit.CMPA = 375; // 비교 레지스터 A 설정: 50% 듀티
EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET; // TBCTR=0일 때 PWM_A 출력을 High로 설정
EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // TBCTR=CMPA일 때 PWM_A 출력을 Low로 설정
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 모드
}
// DMA 채널 1 설정 함수
void ConfigureDMA(void) {
EALLOW; // 보호된 레지스터 접근 허용
CpuSysRegs.PCLKCR0.bit.DMA = 1; // DMA 모듈 클럭 활성화
DmaRegs.DMACTRL.bit.HARDRESET = 1; // DMA 모듈 하드 리셋
DmaRegs.DMACTRL.bit.PRIORITY = 0; // 고정 우선순위
EDIS; // 보호된 레지스터 접근 비허용
EALLOW; // 보호된 레지스터 접근 허용
DmaRegs.CH1.MODE.bit.CH1EN = 1; // 채널 1 활성화
DmaRegs.CH1.MODE.bit.DATASIZE = 0; // 16비트 데이터 전송
DmaRegs.CH1.MODE.bit.TRIGMODE = 1; // 하드웨어 트리거 (ADC SOCA)
DmaRegs.CH1.MODE.bit.ONESHOT = 0; // 연속 모드
DmaRegs.CH1.MODE.bit.SYNCE = 0; // 동기화 비활성화
DmaRegs.CH1.MODE.bit.OVRINTE = 1; // 오버플로우 인터럽트 활성화
DmaRegs.CH1.BURST_SIZE.all = 0; // 버스트 크기: 1 워드
DmaRegs.CH1.SRC_BURST_STEP = 0; // 소스 주소 고정 (ADC 결과 레지스터)
DmaRegs.CH1.DST_BURST_STEP = 1; // 목적지 주소 증가
DmaRegs.CH1.TRANSFER_SIZE = 255; // 전송 크기: 256 워드
DmaRegs.CH1.SRC_ADDR = (Uint32)&AdcRegs.ADCRESULT0; // 소스: ADC 결과 레지스터
DmaRegs.CH1.DST_ADDR = (Uint32)&AdcBuffer[0]; // 목적지: AdcBuffer
DmaRegs.CH1.DMA_CH1_TRIGSEL = DMA_ADCSOC1; // 트리거: ADC SOCA
DmaRegs.CH1.CONTROL.bit.RUN = 1; // DMA 전송 시작
EDIS; // 보호된 레지스터 접근 비허용
}
void main(void) {
InitSysCtrl(); // 시스템 클럭(150MHz)과 PLL 초기화
DINT; // 모든 인터럽트 비활성화
InitPieCtrl(); // PIE 컨트롤러 초기화
IER = 0x0000; // CPU 인터럽트 레지스터 비활성화
IFR = 0x0000; // 인터럽트 플래그 레지스터 클리어
InitPieVectTable(); // PIE 인터럽트 벡터 테이블 초기화
EALLOW; // 보호된 레지스터 접근 허용
PieVectTable.DMA_CH1_INT = &dma_ch1_isr; // DMA 채널 1 인터럽트 벡터 설정
EDIS; // 보호된 레지스터 접근 비허용
ConfigureGPIO(); // GPIO 설정 함수 호출
ConfigureADC(); // ADC 설정 함수 호출
ConfigureEPWM1(); // ePWM1 설정 함수 호출 (ADC 트리거용)
ConfigureDMA(); // DMA 설정 함수 호출
PieCtrlRegs.PIEIER7.bit.INTx1 = 1; // PIE 그룹 7에서 DMA 채널 1 인터럽트 활성화
IER |= M_INT7; // CPU 인터럽트 그룹 7 활성화
EINT; // 글로벌 인터럽트 활성화
ERTM; // 실시간 모드 활성화
for(;;); // 무한 루프: DMA 전송 지속
}
설명:
- 기능: ePWM1의 SOCA 트리거를 사용하여 ADC 데이터를 DMA로 전송하여 AdcBuffer에 저장
- 설정:
- ePWM1: 100kHz 주기, SOCA 트리거 활성화
- ADC: 채널 A0, ePWM1 SOCA로 트리거
- DMA 채널 1: ADC 결과 레지스터에서 AdcBuffer로 256 워드 전송
- GPIO: GPIO34(LED)
- 출력: AdcBuffer에 ADC 데이터 저장, LED ON
5.2 예제 2: 메모리 간 데이터 전송
// File: dma_memory_transfer.c
// Description: TMS320F28335 DMA를 사용한 메모리 간 데이터 전송 예제
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28335
#include "F28x_Project.h"
volatile Uint16 SourceBuffer[128]; // 소스 버퍼
volatile Uint16 DestBuffer[128]; // 목적지 버퍼
// 인터럽트 서비스 루틴: DMA 채널 2 인터럽트 처리
__interrupt void dma_ch2_isr(void)
{
DmaRegs.CH2.CONTROL.bit.TRANSFERSTS = 0; // 전송 상태 플래그 클리어
DmaRegs.CH2.CONTROL.bit.ERRCLR = 1; // 에러 플래그 클리어
PieCtrlRegs.PIEACK.all = PIEACK_GROUP7; // PIE 그룹 7 인터럽트 ACK
}
// GPIO 설정 함수
void ConfigureGPIO(void) {
EALLOW; // 보호된 레지스터 접근 허용
GpioCtrlRegs.GPBDIR.bit.GPIO34 = 1; // GPIO34를 출력으로 설정 (LED용)
GpioDataRegs.GPBSET.bit.GPIO34 = 1; // GPIO34를 High로 설정하여 LED 켬
EDIS; // 보호된 레지스터 접근 비허용
}
// 소스 버퍼 초기화 함수
void InitSourceBuffer(void) {
Uint16 i;
for (i = 0; i < 128; i++) {
SourceBuffer[i] = i; // 소스 버퍼에 0~127 값 초기화
}
}
// DMA 채널 2 설정 함수
void ConfigureDMA(void) {
EALLOW; // 보호된 레지스터 접근 허용
CpuSysRegs.PCLKCR0.bit.DMA = 1; // DMA 모듈 클럭 활성화
DmaRegs.DMACTRL.bit.HARDRESET = 1; // DMA 모듈 하드 리셋
DmaRegs.DMACTRL.bit.PRIORITY = 0; // 고정 우선순위
EDIS; // 보호된 레지스터 접근 비허용
EALLOW; // 보호된 레지스터 접근 허용
DmaRegs.CH2.MODE.bit.CH2EN = 1; // 채널 2 활성화
DmaRegs.CH2.MODE.bit.DATASIZE = 0; // 16비트 데이터 전송
DmaRegs.CH2.MODE.bit.TRIGMODE = 0; // 소프트웨어 트리거
DmaRegs.CH2.MODE.bit.ONESHOT = 1; // 원샷 모드
DmaRegs.CH2.MODE.bit.SYNCE = 0; // 동기화 비활성화
DmaRegs.CH2.MODE.bit.OVRINTE = 1; // 오버플로우 인터럽트 활성화
DmaRegs.CH2.BURST_SIZE.all = 3; // 버스트 크기: 4 워드
DmaRegs.CH2.SRC_BURST_STEP = 1; // 소스 주소 증가
DmaRegs.CH2.DST_BURST_STEP = 1; // 목적지 주소 증가
DmaRegs.CH2.TRANSFER_SIZE = 31; // 전송 크기: 128 워드 (32 버스트)
DmaRegs.CH2.SRC_ADDR = (Uint32)&SourceBuffer[0]; // 소스: SourceBuffer
DmaRegs.CH2.DST_ADDR = (Uint32)&DestBuffer[0]; // 목적지: DestBuffer
DmaRegs.CH2.CONTROL.bit.RUN = 1; // DMA 전송 시작
EDIS; // 보호된 레지스터 접근 비허용
}
void main(void) {
InitSysCtrl(); // 시스템 클럭(150MHz)과 PLL 초기화
DINT; // 모든 인터럽트 비활성화
InitPieCtrl(); // PIE 컨트롤러 초기화
IER = 0x0000; // CPU 인터럽트 레지스터 비활성화
IFR = 0x0000; // 인터럽트 플래그 레지스터 클리어
InitPieVectTable(); // PIE 인터럽트 벡터 테이블 초기화
EALLOW; // 보호된 레지스터 접근 허용
PieVectTable.DMA_CH2_INT = &dma_ch2_isr; // DMA 채널 2 인터럽트 벡터 설정
EDIS; // 보호된 레지스터 접근 비허용
ConfigureGPIO(); // GPIO 설정 함수 호출
InitSourceBuffer(); // 소스 버퍼 초기화
ConfigureDMA(); // DMA 설정 함수 호출
PieCtrlRegs.PIEIER7.bit.INTx2 = 1; // PIE 그룹 7에서 DMA 채널 2 인터럽트 활성화
IER |= M_INT7; // CPU 인터럽트 그룹 7 활성화
EINT; // 글로벌 인터럽트 활성화
ERTM; // 실시간 모드 활성화
for(;;); // 무한 루프: DMA 전송 완료 대기
}
설명:
- 기능: 소프트웨어 트리거를 사용하여 SourceBuffer에서 DestBuffer로 128개의 16비트 데이터를 전송
- 설정:
- DMA 채널 2: 소프트웨어 트리거, 원샷 모드, 4 워드 버스트, 128 워드 전송
- GPIO: GPIO34(LED)
- 출력: DestBuffer에 SourceBuffer 데이터 복사, LED ON
5.3 예제 3: ePWM 데이터 DMA 전송
// File: dma_epwm_transfer.c
// Description: TMS320F28335 DMA를 사용한 ePWM 데이터 전송 예제
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28335
#include "F28x_Project.h"
volatile Uint16 PwmData[64]; // DMA 소스 버퍼: ePWM CMPA 값
volatile Uint16 PwmBuffer[64]; // DMA 목적지 버퍼: ePWM CMPA 저장
// 인터럽트 서비스 루틴: DMA 채널 3 인터럽트 처리
__interrupt void dma_ch3_isr(void)
{
DmaRegs.CH3.CONTROL.bit.TRANSFERSTS = 0; // 전송 상태 플래그 클리어
DmaRegs.CH3.CONTROL.bit.ERRCLR = 1; // 에러 플래그 클리어
PieCtrlRegs.PIEACK.all = PIEACK_GROUP7; // PIE 그룹 7 인터럽트 ACK
}
// GPIO 설정 함수
void ConfigureGPIO(void) {
EALLOW; // 보호된 레지스터 접근 허용
GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1; // GPIO0을 ePWM1A로 설정
GpioCtrlRegs.GPBDIR.bit.GPIO34 = 1; // GPIO34를 출력으로 설정 (LED용)
GpioDataRegs.GPBSET.bit.GPIO34 = 1; // GPIO34를 High로 설정하여 LED 켬
EDIS; // 보호된 레지스터 접근 비허용
}
// ePWM1 설정 함수
void ConfigureEPWM1(void) {
EALLOW; // 보호된 레지스터 접근 허용
CpuSysRegs.PCLKCR1.bit.EPWM1 = 1; // ePWM1 모듈 클럭 활성화
EDIS; // 보호된 레지스터 접근 비허용
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // 타임-베이스 카운터를 업 카운트 모드로 설정
EPwm1Regs.TBCTL.bit.CLKDIV = 0; // 클럭 분주비 1/1 (SYSCLK = 150MHz)
EPwm1Regs.TBCTL.bit.HSPCLKDIV = 2; // 고속 클럭 분주비 1/2 (TBCLK = 75MHz)
EPwm1Regs.TBPRD = 750; // 주기 레지스터 설정: 100kHz (10us)
EPwm1Regs.CMPA.bit.CMPA = 375; // 비교 레지스터 A 설정: 초기 50% 듀티
EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET; // TBCTR=0일 때 PWM_A 출력을 High로 설정
EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // TBCTR=CMPA일 때 PWM_A 출력을 Low로 설정
EPwm1Regs.ETSEL.bit.INTEN = 1; // ePWM1 인터럽트 활성화
EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // TBCTR=0일 때 인터럽트 발생
EPwm1Regs.ETPS.bit.INTPRD = 1; // 첫 번째 이벤트에서 인터럽트 발생
EPwm1Regs.TBCTL.bit.FREE_SOFT = 2; // Free run 모드
}
// 소스 버퍼 초기화 함수
void InitPwmData(void) {
Uint16 i;
for (i = 0; i < 64; i++) {
PwmData[i] = 188 + (i * 4); // 듀티 사이클 25%~75% 범위로 초기화
}
}
// DMA 채널 3 설정 함수
void ConfigureDMA(void) {
EALLOW; // 보호된 레지스터 접근 허용
CpuSysRegs.PCLKCR0.bit.DMA = 1; // DMA 모듈 클럭 활성화
DmaRegs.DMACTRL.bit.HARDRESET = 1; // DMA 모듈 하드 리셋
DmaRegs.DMACTRL.bit.PRIORITY = 0; // 고정 우선순위
EDIS; // 보호된 레지스터 접근 비허용
EALLOW; // 보호된 레지스터 접근 허용
DmaRegs.CH3.MODE.bit.CH3EN = 1; // 채널 3 활성화
DmaRegs.CH3.MODE.bit.DATASIZE = 0; // 16비트 데이터 전송
DmaRegs.CH3.MODE.bit.TRIGMODE = 1; // 하드웨어 트리거 (ePWM1 INT)
DmaRegs.CH3.MODE.bit.ONESHOT = 0; // 연속 모드
DmaRegs.CH3.MODE.bit.SYNCE = 0; // 동기화 비활성화
DmaRegs.CH3.MODE.bit.OVRINTE = 1; // 오버플로우 인터럽트 활성화
DmaRegs.CH3.BURST_SIZE.all = 0; // 버스트 크기: 1 워드
DmaRegs.CH3.SRC_BURST_STEP = 1; // 소스 주소 증가
DmaRegs.CH3.DST_BURST_STEP = 0; // 목적지 주소 고정 (ePWM1 CMPA)
DmaRegs.CH3.TRANSFER_SIZE = 63; // 전송 크기: 64 워드
DmaRegs.CH3.SRC_ADDR = (Uint32)&PwmData[0]; // 소스: PwmData
DmaRegs.CH3.DST_ADDR = (Uint32)&EPwm1Regs.CMPA.all; // 목적지: ePWM1 CMPA
DmaRegs.CH3.DMA_CH3_TRIGSEL = DMA_EPWM1_INT; // 트리거: ePWM1 인터럽트
DmaRegs.CH3.CONTROL.bit.RUN = 1; // DMA 전송 시작
EDIS; // 보호된 레지스터 접근 비허용
}
void main(void) {
InitSysCtrl(); // 시스템 클럭(150MHz)과 PLL 초기화
DINT; // 모든 인터럽트 비활성화
InitPieCtrl(); // PIE 컨트롤러 초기화
IER = 0x0000; // CPU 인터럽트 레지스터 비활성화
IFR = 0x0000; // 인터럽트 플래그 레지스터 클리어
InitPieVectTable(); // PIE 인터럽트 벡터 테이블 초기화
EALLOW; // 보호된 레지스터 접근 허용
PieVectTable.DMA_CH3_INT = &dma_ch3_isr; // DMA 채널 3 인터럽트 벡터 설정
EDIS; // 보호된 레지스터 접근 비허용
ConfigureGPIO(); // GPIO 설정 함수 호출
InitPwmData(); // PWM 데이터 초기화
ConfigureEPWM1(); // ePWM1 설정 함수 호출
ConfigureDMA(); // DMA 설정 함수 호출
PieCtrlRegs.PIEIER7.bit.INTx3 = 1; // PIE 그룹 7에서 DMA 채널 3 인터럽트 활성화
IER |= M_INT7; // CPU 인터럽트 그룹 7 활성화
EINT; // 글로벌 인터럽트 활성화
ERTM; // 실시간 모드 활성화
for(;;); // 무한 루프: DMA 전송 및 PWM 출력 지속
}
설명:
- 기능: ePWM1 인터럽트를 트리거로 사용하여 PwmData에서 ePWM1 CMPA 레지스터로 데이터 전송, PWM 듀티 사이클 동적 변경
- 설정:
- ePWM1: 100kHz 주기, 인터럽트 활성화
- DMA 채널 3: ePWM1 인터럽트 트리거, 64 워드 전송
- GPIO: GPIO0(ePWM1A), GPIO34(LED)
- 출력: ePWM1A에 동적 듀티 사이클 PWM 신호 출력, LED ON
5.4 예제 4: McBSP 데이터 DMA 전송
// File: dma_mcbsp_transfer.c
// Description: TMS320F28335 DMA를 사용한 McBSP 데이터 전송 예제
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28335
#include "F28x_Project.h"
volatile Uint16 McbspTxBuffer[128]; // McBSP 전송 버퍼
volatile Uint16 McbspRxBuffer[128]; // McBSP 수신 버퍼
// 인터럽트 서비스 루틴: DMA 채널 4 인터럽트 처리
__interrupt void dma_ch4_isr(void)
{
DmaRegs.CH4.CONTROL.bit.TRANSFERSTS = 0; // 전송 상태 플래그 클리어
DmaRegs.CH4.CONTROL.bit.ERRCLR = 1; // 에러 플래그 클리어
PieCtrlRegs.PIEACK.all = PIEACK_GROUP7; // PIE 그룹 7 인터럽트 ACK
}
// GPIO 설정 함수
void ConfigureGPIO(void) {
EALLOW; // 보호된 레지스터 접근 허용
GpioCtrlRegs.GPBMUX1.bit.MCLKXA = 1; // McBSP 클럭 출력
GpioCtrlRegs.GPBMUX1.bit.MDXA = 1; // McBSP 데이터 전송
GpioCtrlRegs.GPBMUX1.bit.MDRXA = 1; // McBSP 데이터 수신
GpioCtrlRegs.GPBMUX1.bit.MFSXA = 1; // McBSP 프레임 동기
GpioCtrlRegs.GPBDIR.bit.GPIO34 = 1; // GPIO34를 출력으로 설정 (LED용)
GpioDataRegs.GPBSET.bit.GPIO34 = 1; // GPIO34를 High로 설정하여 LED 켬
EDIS; // 보호된 레지스터 접근 비허용
}
// McBSP 설정 함수
void ConfigureMcBSP(void) {
EALLOW; // 보호된 레지스터 접근 허용
CpuSysRegs.PCLKCR0.bit.MCBSPA = 1; // McBSP-A 모듈 클럭 활성화
EDIS; // 보호된 레지스터 접근 비허용
McbspbRegs.SPCR2.bit.GRST = 0; // McBSP 리셋
McbspbRegs.SPCR1.bit.RRST = 0; // 수신 리셋
McbspbRegs.RCR1.bit.RWDLEN1 = 1; // 16비트 데이터
McbspbRegs.XCR1.bit.XWDLEN1 = 1; // 16비트 데이터
McbspbRegs.SPCR2.bit.XRDY = 0; // 전송 준비 플래그 클리어
McbspbRegs.SPCR1.bit.RRDY = 0; // 수신 준비 플래그 클리어
McbspbRegs.PCR.bit.CLKXM = 1; // 클럭 마스터 모드
McbspbRegs.PCR.bit.FSXM = 1; // 프레임 동기 마스터 모드
McbspbRegs.SRGR2.bit.CLKSM = 1; // 클럭 소스: 내부
McbspbRegs.SRGR1.bit.CLKGDV = 49; // 클럭 분주: 150MHz/(49+1) = 3MHz
McbspbRegs.SPCR2.bit.GRST = 1; // McBSP 활성화
McbspbRegs.SPCR2.bit.XRST = 1; // 전송 활성화
McbspbRegs.SPCR1.bit.RRST = 1; // 수신 활성화
}
// 전송 버퍼 초기화 함수
void InitMcBSPTxBuffer(void) {
Uint16 i;
for (i = 0; i < 128; i++) {
McbspTxBuffer[i] = i; // 전송 버퍼에 0~127 값 초기화
}
}
// DMA 채널 4 설정 함수
void ConfigureDMA(void) {
EALLOW; // 보호된 레지스터 접근 허용
CpuSysRegs.PCLKCR0.bit.DMA = 1; // DMA 모듈 클럭 활성화
DmaRegs.DMACTRL.bit.HARDRESET = 1; // DMA 모듈 하드 리셋
DmaRegs.DMACTRL.bit.PRIORITY = 0; // 고정 우선순위
EDIS; // 보호된 레지스터 접근 비허용
EALLOW; // 보호된 레지스터 접근 허용
DmaRegs.CH4.MODE.bit.CH4EN = 1; // 채널 4 활성화
DmaRegs.CH4.MODE.bit.DATASIZE = 0; // 16비트 데이터 전송
DmaRegs.CH4.MODE.bit.TRIGMODE = 1; // 하드웨어 트리거 (McBSP TX)
DmaRegs.CH4.MODE.bit.ONESHOT = 0; // 연속 모드
DmaRegs.CH4.MODE.bit.SYNCE = 0; // 동기화 비활성화
DmaRegs.CH4.MODE.bit.OVRINTE = 1; // 오버플로우 인터럽트 활성화
DmaRegs.CH4.BURST_SIZE.all = 0; // 버스트 크기: 1 워드
DmaRegs.CH4.SRC_BURST_STEP = 1; // 소스 주소 증가
DmaRegs.CH4.DST_BURST_STEP = 0; // 목적지 주소 고정 (McBSP DXR)
DmaRegs.CH4.TRANSFER_SIZE = 127; // 전송 크기: 128 워드
DmaRegs.CH4.SRC_ADDR = (Uint32)&McbspTxBuffer[0]; // 소스: McbspTxBuffer
DmaRegs.CH4.DST_ADDR = (Uint32)&McbspbRegs.DXR1.all; // 목적지: McBSP DXR
DmaRegs.CH4.DMA_CH4_TRIGSEL = DMA_MXEVTA; // 트리거: McBSP 전송 이벤트
DmaRegs.CH4.CONTROL.bit.RUN = 1; // DMA 전송 시작
EDIS; // 보호된 레지스터 접근 비허용
}
void main(void) {
InitSysCtrl(); // 시스템 클럭(150MHz)과 PLL 초기화
DINT; // 모든 인터럽트 비활성화
InitPieCtrl(); // PIE 컨트롤러 초기화
IER = 0x0000; // CPU 인터럽트 레지스터 비활성화
IFR = 0x0000; // 인터럽트 플래그 레지스터 클리어
InitPieVectTable(); // PIE 인터럽트 벡터 테이블 초기화
EALLOW; // 보호된 레지스터 접근 허용
PieVectTable.DMA_CH4_INT = &dma_ch4_isr; // DMA 채널 4 인터럽트 벡터 설정
EDIS; // 보호된 레지스터 접근 비허용
ConfigureGPIO(); // GPIO 설정 함수 호출
InitMcBSPTxBuffer(); // McBSP 전송 버퍼 초기화
ConfigureMcBSP(); // McBSP 설정 함수 호출
ConfigureDMA(); // DMA 설정 함수 호출
PieCtrlRegs.PIEIER7.bit.INTx4 = 1; // PIE 그룹 7에서 DMA 채널 4 인터럽트 활성화
IER |= M_INT7; // CPU 인터럽트 그룹 7 활성화
EINT; // 글로벌 인터럽트 활성화
ERTM; // 실시간 모드 활성화
for(;;); // 무한 루프: DMA 전송 및 McBSP 통신 지속
}
설명:
- 기능: McBSP 전송 이벤트를 트리거로 사용하여 McbspTxBuffer에서 McBSP DXR로 128 워드 전송
- 설정:
- McBSP: 3MHz 클럭, 16비트 데이터
- DMA 채널 4: McBSP 전송 이벤트 트리거, 128 워드 전송
- GPIO: McBSP 핀(MCLKXA, MDXA, MDRXA, MFSXA), GPIO34(LED)
- 출력: McBSP를 통해 데이터 전송, LED ON
6. 사용 방법
6.1 환경 설정
- C2000Ware 설치: C:\ti\c2000\C2000Ware_x_xx_xx_xx
- CCS 프로젝트: TMS320F28335 타겟으로 프로젝트 생성, F28x_Project.h 포함
- 링커 파일: device_support\f2833x 폴더에서 링커 파일 추가
6.2 코드 실행
- 각 예제를 별도의 .c 파일로 저장하거나, main.c에 복사
- 다른 예제 코드 주석 처리
6.3 하드웨어 준비
- ADC 입력: ADCINA0 핀에 아날로그 신호 연결 (예제 1)
- PWM 출력: GPIO0(ePWM1A)에 오실로스코프 연결 (예제 3)
- McBSP 인터페이스: McBSP 핀에 외부 장치 연결 (예제 4)
- LED: GPIO34에 LED 연결
6.4 디버깅
- CCS Expressions 창에서 AdcBuffer, DestBuffer, PwmBuffer, McbspRxBuffer 확인
- DmaRegs.CHx.CONTROL.bit.TRANSFERSTS로 전송 상태 점검
- DmaRegs.CHx.CONTROL.bit.ERR로 에러 상태 확인
7. 추가 팁
- 캘리브레이션: ADC 사용 시 Device_cal() 호출
- 노이즈 감소: ADC 입력 또는 McBSP 신호에 저역통과 필터 사용
- C2000Ware 참고: C:\ti\c2000\C2000Ware_x_xx_xx_xx\device_support\f2833x\examples\cpu1\dma
- 문제 해결:
- DMA 전송 실패: MODE.bit.CHxEN, TRIGSEL 확인
- 인터럽트 실패: PieVectTable.DMAx_INT, PIEIER7 설정 확인
- 데이터 손실: 버스트 크기 및 메모리 정렬 확인
- TI 리소스: TI E2E 포럼, C2000Ware 예제
8. 결론
이 문서는 TMS320F28335 DMA 모듈의 설정 방법과 Bitfield 구조를 활용한 예제 코드를 제공하여 ADC 데이터 전송, 메모리 복사, ePWM 데이터 업데이트, McBSP 통신 등 다양한 애플리케이션에 적용 가능하도록 구성했습니다.
키워드: TMS320F28335, DMA, C2000, ADC 데이터 전송, 메모리 전송, ePWM, McBSP, 마이크로컨트롤러, Code Composer Studio, 하드웨어 트리거, 인터럽트
'MCU > C2000' 카테고리의 다른 글
[TI C2000]TI TMS320F280049C DSP를 적용한 동기 벅 컨버터 설계 - PCMC (0) | 2025.08.21 |
---|---|
[TI C2000]TMS320F280049C DSP를 적용한 동기 벅 컨버터 설계 절차-VMC (0) | 2025.08.20 |
[TMS320F28335] CAN, I2C, McBSP 사용법 : Bitfield 구조 활용 예제 코드 (0) | 2025.08.19 |
[TMS320F28335] eQEP 및 eCAP 사용법 : Bitfield 구조 활용 예제 코드 (0) | 2025.08.19 |
[TMS320F28335] XINTF 사용법 : Bitfield 구조 활용 예제 코드 (0) | 2025.08.19 |
[TMS320F28335] ADC 사용법 : Bitfield 구조 활용 예제 코드 (0) | 2025.08.18 |
[TMS320F28335] ePWM 사용법 : Bitfield 구조 활용 예제 코드 (1) | 2025.08.18 |
[TMS320F28377D] DC-DC 변환 토포롤로지별 ePWM 생성 방법: Bitfield 구조 활용 예제 코드 (1) | 2025.08.18 |