본문 바로가기
MCU/C2000

[TMS320F28377D] EMIF 사용법 : Bitfield 구조 활용 예제 코드

by linuxgo 2025. 8. 17.
반응형

TI의 TMS320F28377D는 C2000 Delfino 시리즈의 32비트 마이크로컨트롤러로, 외부 메모리 인터페이스(EMIF, External Memory Interface)를 통해 SRAM, NOR Flash, SDRAM, 그리고 외부 ADC/DAC 같은 병렬 인터페이스 장치와 고속으로 통신할 수 있습니다. EMIF 모듈은 고속 데이터 전송, 외부 장치 연결, 메모리 매핑 등을 지원하며, 모터 제어, 데이터 로깅, 대용량 데이터 처리, 아날로그-디지털 변환 애플리케이션에 적합합니다. 이 문서에서는 TMS320F28377D EMIF 모듈의 상세 설정 방법, Bitfield 구조를 활용한 레지스터 설정, 그리고 실용적인 예제 코드를 제공하여 초보자와 숙련된 개발자 모두 쉽게 활용할 수 있도록 돕겠습니다. 모든 예제는 Code Composer Studio(CCS)와 C2000Ware 환경에서 실행 가능합니다.

1. TMS320F28377D EMIF 모듈 개요

TMS320F28377D는 두 개의 EMIF 모듈(EMIF1, EMIF2)을 제공하며, 각각 독립적으로 외부 메모리 또는 병렬 인터페이스 장치와 인터페이스를 구성할 수 있습니다. 아래는 주요 사양입니다:

  • 지원 장치 유형:
    • 비동기 메모리(SRAM, NOR Flash)
    • 동기 메모리(SDRAM)
    • 병렬 인터페이스 장치(ADC, DAC, FPGA 등)
  • 주요 기능:
    • 16비트/32비트 데이터 버스
    • 최대 256MB 주소 공간(EMIF1), 2MB 주소 공간(EMIF2)
    • 프로그래밍 가능한 타이밍 파라미터
    • 인터럽트 지원
    • DMA(Direct Memory Access) 지원
  • 클럭 소스: 시스템 클럭(SYSCLK, 최대 200MHz)
  • 핀 구성:
    • EMIF1:
      • 데이터: EM1D[31:0]
      • 주소: EM1A[21:0]
      • 뱅크 주소: EM1BA[1:0] (SDRAM에서 뱅크 선택용)
      • 제어 신호: EM1CS[4:2], EM1WE, EM1OE, EM1SDCE, EM1CAS, EM1RAS
    • EMIF2:
      • 데이터: EM2D[15:0]
      • 주소: EM2A[11:0]
      • 뱅크 주소: EM2BA[1:0] (SDRAM에서 뱅크 선택용)
      • 제어 신호: EM2CS[0], EM2WE, EM2OE
  • EMIF_BA[1:0] 역할:
    • EMIF_BA[1:0]은 SDRAM의 내부 뱅크를 선택하기 위해 사용됩니다.
    • SDRAM은 일반적으로 2개 또는 4개의 내부 뱅크를 가지며, EMIF_BA[1:0]는 액세스할 뱅크를 지정하여 병렬 처리 및 성능 최적화를 지원합니다.
    • 예: 4뱅크 SDRAM의 경우, EM1BA[1:0] 또는 EM2BA[1:0]는 00, 01, 10, 11 값을 통해 각 뱅크를 선택합니다.
    • 비동기 메모리(SRAM, NOR Flash) 또는 병렬 ADC/DAC 인터페이스에서는 일반적으로 사용되지 않으며, SDRAM 전용 신호로 간주됩니다.
    • GPIO 매핑 예: EM1BA0 (GPIO36), EM1BA1 (GPIO37), EM2BA0 (GPIO29), EM2BA1 (GPIO30).
  • 주요 레지스터:
    • RCSR: 리비전 및 모듈 제어
    • ASYNC_CSx_CTRL: 비동기 칩 선택 제어
    • SDRAM_CR: SDRAM 제어
    • SDRAM_TR: SDRAM 타이밍
    • INT_EN: 인터럽트 활성화

2. EMIF Bitfield 설정 상세

TMS320F28377D의 EMIF 레지스터는 Bitfield 구조로 정의되어 있으며, F2837xD_emif.h 헤더 파일을 통해 접근합니다. Bitfield는 레지스터의 개별 비트를 명확히 설정하여 코드 가독성과 유지보수성을 높입니다. 주요 레지스터와 Bitfield는 다음과 같습니다:

2.1 RCSR (리비전 및 제어 레지스터)

  • bit.MODULE_ID: 모듈 식별자 (읽기 전용)
  • bit.MAJOR_REVISION: 메이저 리비전 번호
  • bit.MINOR_REVISION: 마이너 리비전 번호

2.2 ASYNC_CSx_CTRL (비동기 칩 선택 제어 레지스터, x=2,3,4)

  • bit.CS_EN: 칩 선택 활성화 (1: 활성화)
  • bit.ASIZE: 주소 크기 (0: 32비트, 1: 16비트, 2: 8비트)
  • bit.W_SETUP/W_STROBE/W_HOLD: 쓰기 동작 타이밍
  • bit.R_SETUP/R_STROBE/R_HOLD: 읽기 동작 타이밍
  • bit.TURN_AROUND: 턴어라운드 시간

2.3 SDRAM_CR (SDRAM 제어 레지스터)

  • bit.SD_EN: SDRAM 활성화 (1: 활성화)
  • bit.BANK_SIZE: 뱅크 크기 (0: 4뱅크, 1: 2뱅크, EMIF_BA[1:0]와 연계)
  • bit.PAGE_SIZE: 페이지 크기 (0: 256워드, 1: 512워드, 2: 1024워드)
  • bit.CL: CAS 지연 시간 (2: CL=2, 3: CL=3)
  • bit.IBANK: 내부 뱅크 구조

2.4 SDRAM_TR (SDRAM 타이밍 레지스터)

  • bit.T_RFC: 자동 리프레시 주기
  • bit.T_RP: 로우 프리차지 시간
  • bit.T_RCD: 로우 활성화에서 컬럼 액세스 시간
  • bit.T_WR: 쓰기 복구 시간
  • bit.T_RAS: 로우 활성화 시간
  • bit.T_RC: 로우 사이클 시간

2.5 INT_EN (인터럽트 활성화 레지스터)

  • bit.WR_INT_EN: 쓰기 인터럽트 활성화
  • bit.LT_INT_EN: 라인 트랩 인터럽트 활성화
  • bit.AT_INT_EN: 비동기 타임아웃 인터럽트 활성화

Bitfield 사용 이점:

  • 명확한 비트 단위 설정으로 실수 감소
  • 코드 가독성 및 유지보수성 향상
  • F2837xD_emif.h에서 제공하는 구조체로 직관적 접근

3. EMIF 설정 절차

EMIF 모듈을 효과적으로 설정하려면 다음 단계를 따라야 합니다:

  1. 시스템 초기화:
    • InitSysCtrl()를 호출하여 시스템 클럭과 PLL을 초기화합니다.
    • 인터럽트를 비활성화하고 PIE(Peripheral Interrupt Expansion)를 초기화합니다 (DINT, InitPieCtrl, InitPieVectTable).
  2. EMIF 클럭 활성화:
    • CpuSysRegs.PCLKCR8.bit.EMIF1 또는 CpuSysRegs.PCLKCR8.bit.EMIF2를 설정하여 EMIF 모듈 클럭 활성화.
    • 보호된 레지스터 접근을 위해 EALLOW와 EDIS 사용.
  3. GPIO 설정:
    • EMIF 핀을 적절한 기능(EMIF1/EMIF2)으로 설정 (예: GpioCtrlRegs.GPAMUXx.bit.GPIOx).
    • 데이터, 주소, 제어 신호, 그리고 SDRAM 사용 시 EMIF_BA[1:0] 핀을 모두 매핑.
    • 병렬 ADC/DAC의 경우, 칩 선택(CS)과 읽기/쓰기 신호(EMxWE, EMxOE)를 활용하여 데이터 전송 제어.
  4. 비동기 메모리 또는 장치 설정 (SRAM/NOR Flash/ADC/DAC):
    • ASYNC_CSx_CTRL로 칩 선택 활성화 및 타이밍 설정.
    • 읽기/쓰기 타이밍 파라미터(W_SETUP, W_STROBE, R_SETUP, R_STROBE 등) 설정.
  5. SDRAM 설정 (필요 시):
    • SDRAM_CR로 SDRAM 활성화, 뱅크 크기(EMIF_BA[1:0]와 연계), 페이지 크기, CAS 지연 설정.
    • SDRAM_TR로 타이밍 파라미터 설정.
    • 초기화 시퀀스 수행 (예: 리프레시 주기 설정).
  6. 인터럽트 설정 (필요 시):
    • INT_EN으로 원하는 인터럽트 활성화.
    • PIE 벡터 테이블에 인터럽트 서비스 루틴(ISR) 등록.
  7. 모듈 실행:
    • 메모리 또는 장치 테스트를 통해 설정 확인.
    • 외부 메모리 읽기/쓰기 또는 ADC/DAC 데이터 전송 수행.

4. EMIF 설정 고려사항

  • 클럭 설정: SYSCLK(200MHz)에서 EMIF 동작 클럭 확인.
  • 타이밍 계산: 외부 메모리 또는 장치(ADC/DAC 포함)의 데이터시트를 참조하여 읽기/쓰기 타이밍 설정.
  • 핀 멀티플렉싱: EMIF 핀(특히 EMIF_BA[1:0])과 다른 기능(GPIO, ePWM 등) 간 충돌 방지.
  • SDRAM 초기화: 리프레시 주기와 타이밍 파라미터를 정확히 설정, EMIF_BA[1:0] 핀 매핑 확인.
  • ADC/DAC 인터페이스: 병렬 ADC/DAC의 데이터시트에 따라 칩 선택 및 타이밍 설정, 데이터 버스 폭 확인.
  • 인터럽트: 비동기 타임아웃, 라인 트랩 등 오류 처리용 인터럽트 활용.
  • 메모리 매핑: EMIF1(0x080000000x0FFFFFFF), EMIF2(0x001000000x0013FFFF) 주소 공간 확인.

5. 실용적인 EMIF 예제 코드 (Bitfield 구조)

아래는 TMS320F28377D EMIF 모듈을 Bitfield 구조로 설정한 7개의 실용적인 예제 코드입니다. 

5.1 예제 1: 비동기 SRAM 읽기/쓰기

// File: emif_async_sram.c
// Description: TMS320F28377D EMIF 비동기 SRAM 읽기/쓰기 예제 (Bitfield 구조)
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28377D

#include "F28x_Project.h"

#define SRAM_BASE 0x08000000 // EMIF1 CS2 메모리 주소

void main(void) {
    // 시스템 초기화
    InitSysCtrl(); // 시스템 클럭 및 PLL 초기화
    DINT; // 모든 인터럽트 비활성화
    InitPieCtrl(); // PIE 초기화
    IER = 0x0000; // CPU 인터럽트 비활성화
    IFR = 0x0000; // 대기 중인 인터럽트 플래그 지우기
    InitPieVectTable(); // PIE 벡터 테이블 초기화

    // GPIO 설정 (EMIF1 CS2, 데이터, 주소, 제어 신호)
    EALLOW;
    // 칩 선택
    GpioCtrlRegs.GPBMUX1.bit.GPIO34 = 2; // EM1CS2
    // 데이터 (EM1D0~EM1D15, 16비트 버스)
    GpioCtrlRegs.GPBMUX1.bit.GPIO40 = 2; // EM1D0
    GpioCtrlRegs.GPBMUX1.bit.GPIO41 = 2; // EM1D1
    GpioCtrlRegs.GPBMUX1.bit.GPIO42 = 2; // EM1D2
    GpioCtrlRegs.GPBMUX1.bit.GPIO43 = 2; // EM1D3
    GpioCtrlRegs.GPBMUX1.bit.GPIO44 = 2; // EM1D4
    GpioCtrlRegs.GPBMUX1.bit.GPIO45 = 2; // EM1D5
    GpioCtrlRegs.GPBMUX1.bit.GPIO46 = 2; // EM1D6
    GpioCtrlRegs.GPBMUX1.bit.GPIO47 = 2; // EM1D7
    GpioCtrlRegs.GPCMUX1.bit.GPIO64 = 2; // EM1D8
    GpioCtrlRegs.GPCMUX1.bit.GPIO65 = 2; // EM1D9
    GpioCtrlRegs.GPCMUX1.bit.GPIO66 = 2; // EM1D10
    GpioCtrlRegs.GPCMUX1.bit.GPIO67 = 2; // EM1D11
    GpioCtrlRegs.GPCMUX1.bit.GPIO68 = 2; // EM1D12
    GpioCtrlRegs.GPCMUX1.bit.GPIO69 = 2; // EM1D13
    GpioCtrlRegs.GPCMUX1.bit.GPIO70 = 2; // EM1D14
    GpioCtrlRegs.GPCMUX1.bit.GPIO71 = 2; // EM1D15
    // 주소 (EM1A0~EM1A11, 예시로 12비트 주소 사용)
    GpioCtrlRegs.GPBMUX2.bit.GPIO58 = 2; // EM1A0
    GpioCtrlRegs.GPBMUX2.bit.GPIO59 = 2; // EM1A1
    GpioCtrlRegs.GPBMUX2.bit.GPIO60 = 2; // EM1A2
    GpioCtrlRegs.GPBMUX2.bit.GPIO61 = 2; // EM1A3
    GpioCtrlRegs.GPBMUX2.bit.GPIO62 = 2; // EM1A4
    GpioCtrlRegs.GPBMUX2.bit.GPIO63 = 2; // EM1A5
    GpioCtrlRegs.GPCMUX2.bit.GPIO72 = 2; // EM1A6
    GpioCtrlRegs.GPCMUX2.bit.GPIO73 = 2; // EM1A7
    GpioCtrlRegs.GPCMUX2.bit.GPIO74 = 2; // EM1A8
    GpioCtrlRegs.GPCMUX2.bit.GPIO75 = 2; // EM1A9
    GpioCtrlRegs.GPCMUX2.bit.GPIO76 = 2; // EM1A10
    GpioCtrlRegs.GPCMUX2.bit.GPIO77 = 2; // EM1A11
    // 제어 신호
    GpioCtrlRegs.GPBMUX2.bit.GPIO56 = 2; // EM1WE
    GpioCtrlRegs.GPBMUX2.bit.GPIO57 = 2; // EM1OE
    EDIS;

    // EMIF1 클럭 활성화
    EALLOW;
    CpuSysRegs.PCLKCR8.bit.EMIF1 = 1; // EMIF1 모듈 클럭 활성화
    EDIS;

    // EMIF1 CS2 설정 (비동기 SRAM)
    EALLOW;
    Emif1Regs.ASYNC_CS2_CTRL.bit.CS_EN = 1; // CS2 활성화
    Emif1Regs.ASYNC_CS2_CTRL.bit.ASIZE = 1; // 16비트 데이터 버스
    Emif1Regs.ASYNC_CS2_CTRL.bit.W_SETUP = 1; // 쓰기 설정 시간
    Emif1Regs.ASYNC_CS2_CTRL.bit.W_STROBE = 4; // 쓰기 스트로브 시간
    Emif1Regs.ASYNC_CS2_CTRL.bit.W_HOLD = 1; // 쓰기 홀드 시간
    Emif1Regs.ASYNC_CS2_CTRL.bit.R_SETUP = 1; // 읽기 설정 시간
    Emif1Regs.ASYNC_CS2_CTRL.bit.R_STROBE = 4; // 읽기 스트로브 시간
    Emif1Regs.ASYNC_CS2_CTRL.bit.R_HOLD = 1; // 읽기 홀드 시간
    Emif1Regs.ASYNC_CS2_CTRL.bit.TURN_AROUND = 1; // 턴어라운드 시간
    EDIS;

    // 메모리 테스트
    volatile Uint16 *sram = (volatile Uint16 *)SRAM_BASE;
    sram[0] = 0x1234; // 데이터 쓰기
    Uint16 read_data = sram[0]; // 데이터 읽기

    // LED 점등 (정상 동작 확인)
    EALLOW;
    GpioCtrlRegs.GPBDIR.bit.GPIO31 = 1; // GPIO31 출력(LED)
    GpioDataRegs.GPBSET.bit.GPIO31 = 1; // LED 켜기
    EDIS;

    for(;;); // 무한 루프
}

설명:

  • 기능: EMIF1 CS2를 통해 비동기 SRAM에 데이터 쓰기 및 읽기.
  • 설정: 16비트 데이터 버스, 읽기/쓰기 타이밍 설정, CS2 활성화.
  • GPIO:
    • 칩 선택: EM1CS2 (GPIO34)
    • 데이터: EM1D015 (GPIO4047, GPIO64~71)
    • 주소: EM1A011 (GPIO5863, GPIO72~77)
    • 제어: EM1WE (GPIO56), EM1OE (GPIO57)
    • LED: GPIO31
  • 출력: SRAM_BASE(0x08000000)에 0x1234 쓰기 및 읽기, 정상 동작 시 LED ON.

5.2 예제 2: SDRAM 초기화 및 액세스

// File: emif_sdram.c
// Description: TMS320F28377D EMIF SDRAM 초기화 및 액세스 예제 (Bitfield 구조)
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28377D

#include "F28x_Project.h"

#define SDRAM_BASE 0x08000000 // EMIF1 SDRAM 메모리 주소

void main(void) {
    // 시스템 초기화
    InitSysCtrl(); // 시스템 클럭 및 PLL 초기화
    DINT; // 모든 인터럽트 비활성화
    InitPieCtrl(); // PIE 초기화
    IER = 0x0000; // CPU 인터럽트 비활성화
    IFR = 0x0000; // 대기 중인 인터럽트 플래그 지우기
    InitPieVectTable(); // PIE 벡터 테이블 초기화

    // GPIO 설정 (EMIF1 SDRAM, 데이터, 주소, 뱅크, 제어 신호)
    EALLOW;
    // SDRAM 제어
    GpioCtrlRegs.GPBMUX1.bit.GPIO32 = 2; // EM1SDCE
    GpioCtrlRegs.GPBMUX1.bit.GPIO33 = 2; // EM1CAS
    GpioCtrlRegs.GPBMUX1.bit.GPIO35 = 2; // EM1RAS
    // 뱅크 주소
    GpioCtrlRegs.GPBMUX1.bit.GPIO36 = 2; // EM1BA0
    GpioCtrlRegs.GPBMUX1.bit.GPIO37 = 2; // EM1BA1
    // 데이터 (EM1D0~EM1D15, 16비트 버스)
    GpioCtrlRegs.GPBMUX1.bit.GPIO40 = 2; // EM1D0
    GpioCtrlRegs.GPBMUX1.bit.GPIO41 = 2; // EM1D1
    GpioCtrlRegs.GPBMUX1.bit.GPIO42 = 2; // EM1D2
    GpioCtrlRegs.GPBMUX1.bit.GPIO43 = 2; // EM1D3
    GpioCtrlRegs.GPBMUX1.bit.GPIO44 = 2; // EM1D4
    GpioCtrlRegs.GPBMUX1.bit.GPIO45 = 2; // EM1D5
    GpioCtrlRegs.GPBMUX1.bit.GPIO46 = 2; // EM1D6
    GpioCtrlRegs.GPBMUX1.bit.GPIO47 = 2; // EM1D7
    GpioCtrlRegs.GPCMUX1.bit.GPIO64 = 2; // EM1D8
    GpioCtrlRegs.GPCMUX1.bit.GPIO65 = 2; // EM1D9
    GpioCtrlRegs.GPCMUX1.bit.GPIO66 = 2; // EM1D10
    GpioCtrlRegs.GPCMUX1.bit.GPIO67 = 2; // EM1D11
    GpioCtrlRegs.GPCMUX1.bit.GPIO68 = 2; // EM1D12
    GpioCtrlRegs.GPCMUX1.bit.GPIO69 = 2; // EM1D13
    GpioCtrlRegs.GPCMUX1.bit.GPIO70 = 2; // EM1D14
    GpioCtrlRegs.GPCMUX1.bit.GPIO71 = 2; // EM1D15
    // 주소 (EM1A0~EM1A11, 예시로 12비트 주소 사용)
    GpioCtrlRegs.GPBMUX2.bit.GPIO58 = 2; // EM1A0
    GpioCtrlRegs.GPBMUX2.bit.GPIO59 = 2; // EM1A1
    GpioCtrlRegs.GPBMUX2.bit.GPIO60 = 2; // EM1A2
    GpioCtrlRegs.GPBMUX2.bit.GPIO61 = 2; // EM1A3
    GpioCtrlRegs.GPBMUX2.bit.GPIO62 = 2; // EM1A4
    GpioCtrlRegs.GPBMUX2.bit.GPIO63 = 2; // EM1A5
    GpioCtrlRegs.GPCMUX2.bit.GPIO72 = 2; // EM1A6
    GpioCtrlRegs.GPCMUX2.bit.GPIO73 = 2; // EM1A7
    GpioCtrlRegs.GPCMUX2.bit.GPIO74 = 2; // EM1A8
    GpioCtrlRegs.GPCMUX2.bit.GPIO75 = 2; // EM1A9
    GpioCtrlRegs.GPCMUX2.bit.GPIO76 = 2; // EM1A10
    GpioCtrlRegs.GPCMUX2.bit.GPIO77 = 2; // EM1A11
    // 제어 신호
    GpioCtrlRegs.GPBMUX2.bit.GPIO56 = 2; // EM1WE
    GpioCtrlRegs.GPBMUX2.bit.GPIO57 = 2; // EM1OE
    EDIS;

    // EMIF1 클럭 활성화
    EALLOW;
    CpuSysRegs.PCLKCR8.bit.EMIF1 = 1; // EMIF1 모듈 클럭 활성화
    EDIS;

    // SDRAM 설정
    EALLOW;
    Emif1Regs.SDRAM_CR.bit.SD_EN = 1; // SDRAM 활성화
    Emif1Regs.SDRAM_CR.bit.PAGE_SIZE = 1; // 512워드 페이지
    Emif1Regs.SDRAM_CR.bit.BANK_SIZE = 0; // 4뱅크 (EM1BA[1:0] 사용)
    Emif1Regs.SDRAM_CR.bit.CL = 3; // CAS 지연 3
    Emif1Regs.SDRAM_CR.bit.IBANK = 1; // 2 내부 뱅크

    // SDRAM 타이밍 설정 (200MHz SYSCLK 기준)
    Emif1Regs.SDRAM_TR.bit.T_RFC = 12; // 자동 리프레시 주기 (60ns)
    Emif1Regs.SDRAM_TR.bit.T_RP = 4; // 로우 프리차지 (20ns)
    Emif1Regs.SDRAM_TR.bit.T_RCD = 4; // 로우 활성화에서 컬럼 액세스 (20ns)
    Emif1Regs.SDRAM_TR.bit.T_WR = 2; // 쓰기 복구 (10ns)
    Emif1Regs.SDRAM_TR.bit.T_RAS = 8; // 로우 활성화 (40ns)
    Emif1Regs.SDRAM_TR.bit.T_RC = 14; // 로우 사이클 (70ns)

    // SDRAM 리프레시 주기 설정
    Emif1Regs.SDRAM_RCR.bit.REFRESH_RATE = 781; // 7.81us 리프레시 주기 (200MHz 기준)
    EDIS;

    // 지연 (SDRAM 초기화 완료 대기)
    asm(" RPT #100 || NOP");

    // 메모리 테스트
    volatile Uint16 *sdram = (volatile Uint16 *)SDRAM_BASE;
    sdram[0] = 0xABCD; // 데이터 쓰기
    Uint16 read_data = sdram[0]; // 데이터 읽기

    // LED 점등 (정상 동작 확인)
    EALLOW;
    GpioCtrlRegs.GPBDIR.bit.GPIO31 = 1; // GPIO31 출력(LED)
    GpioDataRegs.GPBSET.bit.GPIO31 = 1; // LED 켜기
    EDIS;

    for(;;); // 무한 루프
}

설명:

  • 기능: EMIF1을 통해 SDRAM 초기화 및 데이터 쓰기/읽기, EM1BA[1:0]로 뱅크 선택.
  • 설정: 512워드 페이지, 4뱅크, CAS 지연 3, 타이밍 파라미터 설정, 7.81us 리프레시 주기.
  • GPIO:
    • SDRAM 제어: EM1SDCE (GPIO32), EM1CAS (GPIO33), EM1RAS (GPIO35)
    • 뱅크 주소: EM1BA0 (GPIO36), EM1BA1 (GPIO37)
    • 데이터: EM1D015 (GPIO4047, GPIO64~71)
    • 주소: EM1A011 (GPIO5863, GPIO72~77)
    • 제어: EM1WE (GPIO56), EM1OE (GPIO57)
    • LED: GPIO31
  • 출력: SDRAM_BASE(0x08000000)에 0xABCD 쓰기 및 읽기, 정상 동작 시 LED ON.

5.3 예제 3: EMIF 인터럽트 기반 데이터 전송

// File: emif_interrupt.c
// Description: TMS320F28377D EMIF 인터럽트 기반 데이터 전송 예제 (Bitfield 구조)
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28377D

#include "F28x_Project.h"

#define SRAM_BASE 0x08000000 // EMIF1 CS2 메모리 주소
volatile Uint16 data_buffer = 0x0000;

__interrupt void emif1_isr(void)
{
    // 데이터 쓰기
    volatile Uint16 *sram = (volatile Uint16 *)SRAM_BASE;
    data_buffer = (data_buffer == 0x5555) ? 0xAAAA : 0x5555; // 데이터 토글
    sram[0] = data_buffer;

    // 인터럽트 플래그 클리어
    Emif1Regs.INT_CLR.bit.WR_INT = 1;
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP12;
}

void main(void) {
    // 시스템 초기화
    InitSysCtrl(); // 시스템 클럭 및 PLL 초기화
    DINT; // 모든 인터럽트 비활성화
    InitPieCtrl(); // PIE 초기화
    IER = 0x0000; // CPU 인터럽트 비활성화
    IFR = 0x0000; // 대기 중인 인터럽트 플래그 지우기
    InitPieVectTable(); // PIE 벡터 테이블 초기화

    // 인터럽트 벡터 설정
    EALLOW;
    PieVectTable.EMIF1_INT = &emif1_isr; // EMIF1 인터럽트 벡터 설정
    EDIS;

    // GPIO 설정 (EMIF1 CS2, 데이터, 주소, 제어 신호)
    EALLOW;
    // 칩 선택
    GpioCtrlRegs.GPBMUX1.bit.GPIO34 = 2; // EM1CS2
    // 데이터 (EM1D0~EM1D15, 16비트 버스)
    GpioCtrlRegs.GPBMUX1.bit.GPIO40 = 2; // EM1D0
    GpioCtrlRegs.GPBMUX1.bit.GPIO41 = 2; // EM1D1
    GpioCtrlRegs.GPBMUX1.bit.GPIO42 = 2; // EM1D2
    GpioCtrlRegs.GPBMUX1.bit.GPIO43 = 2; // EM1D3
    GpioCtrlRegs.GPBMUX1.bit.GPIO44 = 2; // EM1D4
    GpioCtrlRegs.GPBMUX1.bit.GPIO45 = 2; // EM1D5
    GpioCtrlRegs.GPBMUX1.bit.GPIO46 = 2; // EM1D6
    GpioCtrlRegs.GPBMUX1.bit.GPIO47 = 2; // EM1D7
    GpioCtrlRegs.GPCMUX1.bit.GPIO64 = 2; // EM1D8
    GpioCtrlRegs.GPCMUX1.bit.GPIO65 = 2; // EM1D9
    GpioCtrlRegs.GPCMUX1.bit.GPIO66 = 2; // EM1D10
    GpioCtrlRegs.GPCMUX1.bit.GPIO67 = 2; // EM1D11
    GpioCtrlRegs.GPCMUX1.bit.GPIO68 = 2; // EM1D12
    GpioCtrlRegs.GPCMUX1.bit.GPIO69 = 2; // EM1D13
    GpioCtrlRegs.GPCMUX1.bit.GPIO70 = 2; // EM1D14
    GpioCtrlRegs.GPCMUX1.bit.GPIO71 = 2; // EM1D15
    // 주소 (EM1A0~EM1A11, 예시로 12비트 주소 사용)
    GpioCtrlRegs.GPBMUX2.bit.GPIO58 = 2; // EM1A0
    GpioCtrlRegs.GPBMUX2.bit.GPIO59 = 2; // EM1A1
    GpioCtrlRegs.GPBMUX2.bit.GPIO60 = 2; // EM1A2
    GpioCtrlRegs.GPBMUX2.bit.GPIO61 = 2; // EM1A3
    GpioCtrlRegs.GPBMUX2.bit.GPIO62 = 2; // EM1A4
    GpioCtrlRegs.GPBMUX2.bit.GPIO63 = 2; // EM1A5
    GpioCtrlRegs.GPCMUX2.bit.GPIO72 = 2; // EM1A6
    GpioCtrlRegs.GPCMUX2.bit.GPIO73 = 2; // EM1A7
    GpioCtrlRegs.GPCMUX2.bit.GPIO74 = 2; // EM1A8
    GpioCtrlRegs.GPCMUX2.bit.GPIO75 = 2; // EM1A9
    GpioCtrlRegs.GPCMUX2.bit.GPIO76 = 2; // EM1A10
    GpioCtrlRegs.GPCMUX2.bit.GPIO77 = 2; // EM1A11
    // 제어 신호
    GpioCtrlRegs.GPBMUX2.bit.GPIO56 = 2; // EM1WE
    GpioCtrlRegs.GPBMUX2.bit.GPIO57 = 2; // EM1OE
    EDIS;

    // EMIF1 클럭 활성화
    EALLOW;
    CpuSysRegs.PCLKCR8.bit.EMIF1 = 1; // EMIF1 모듈 클럭 활성화
    EDIS;

    // EMIF1 CS2 설정 (비동기 SRAM)
    EALLOW;
    Emif1Regs.ASYNC_CS2_CTRL.bit.CS_EN = 1; // CS2 활성화
    Emif1Regs.ASYNC_CS2_CTRL.bit.ASIZE = 1; // 16비트 데이터 버스
    Emif1Regs.ASYNC_CS2_CTRL.bit.W_SETUP = 1; // 쓰기 설정 시간
    Emif1Regs.ASYNC_CS2_CTRL.bit.W_STROBE = 4; // 쓰기 스트로브 시간
    Emif1Regs.ASYNC_CS2_CTRL.bit.W_HOLD = 1; // 쓰기 홀드 시간
    Emif1Regs.ASYNC_CS2_CTRL.bit.R_SETUP = 1; // 읽기 설정 시간
    Emif1Regs.ASYNC_CS2_CTRL.bit.R_STROBE = 4; // 읽기 스트로브 시간
    Emif1Regs.ASYNC_CS2_CTRL.bit.R_HOLD = 1; // 읽기 홀드 시간
    Emif1Regs.ASYNC_CS2_CTRL.bit.TURN_AROUND = 1; // 턴어라운드 시간

    // 인터럽트 설정
    Emif1Regs.INT_EN.bit.WR_INT_EN = 1; // 쓰기 인터럽트 활성화
    PieCtrlRegs.PIEIER12.bit.INTx1 = 1; // PIE 그룹 12, EMIF1 인터럽트 활성화
    IER |= M_INT12; // CPU 인터럽트 12 활성화
    EDIS;

    EINT; // 글로벌 인터럽트 활성화

    // 초기 데이터 쓰기
    volatile Uint16 *sram = (volatile Uint16 *)SRAM_BASE;
    sram[0] = data_buffer;

    // LED 점등 (정상 동작 확인)
    EALLOW;
    GpioCtrlRegs.GPBDIR.bit.GPIO31 = 1; // GPIO31 출력(LED)
    GpioDataRegs.GPBSET.bit.GPIO31 = 1; // LED 켜기
    EDIS;

    for(;;); // 무한 루프
}

설명:

  • 기능: EMIF1 CS2를 통해 비동기 SRAM에 인터럽트 기반으로 데이터(0x5555, 0xAAAA) 토글 쓰기.
  • 설정: 16비트 데이터 버스, 읽기/쓰기 타이밍 설정, 쓰기 인터럽트 활성화.
  • GPIO:
    • 칩 선택: EM1CS2 (GPIO34)
    • 데이터: EM1D015 (GPIO4047, GPIO64~71)
    • 주소: EM1A011 (GPIO5863, GPIO72~77)
    • 제어: EM1WE (GPIO56), EM1OE (GPIO57)
    • LED: GPIO31
  • 출력: SRAM_BASE(0x08000000)에 데이터 토글 쓰기, 정상 동작 시 LED ON.

5.4 예제 4: EMIF2 NOR Flash 읽기

// File: emif2_nor_flash.c
// Description: TMS320F28377D EMIF2 NOR Flash 읽기 예제 (Bitfield 구조)
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28377D

#include "F28x_Project.h"

#define NOR_BASE 0x00100000 // EMIF2 CS0 메모리 주소

void main(void) {
    // 시스템 초기화
    InitSysCtrl(); // 시스템 클럭 및 PLL 초기화
    DINT; // 모든 인터럽트 비활성화
    InitPieCtrl(); // PIE 초기화
    IER = 0x0000; // CPU 인터럽트 비활성화
    IFR = 0x0000; // 대기 중인 인터럽트 플래그 지우기
    InitPieVectTable(); // PIE 벡터 테이블 초기화

    // GPIO 설정 (EMIF2 CS0, 데이터, 주소, 제어 신호)
    EALLOW;
    // 칩 선택
    GpioCtrlRegs.GPAMUX2.bit.GPIO28 = 2; // EM2CS0
    // 데이터 (EM2D0~EM2D15, 16비트 버스)
    GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 2; // EM2D0
    GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 2; // EM2D1
    GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 2; // EM2D2
    GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 2; // EM2D3
    GpioCtrlRegs.GPAMUX2.bit.GPIO20 = 2; // EM2D4
    GpioCtrlRegs.GPAMUX2.bit.GPIO21 = 2; // EM2D5
    GpioCtrlRegs.GPAMUX2.bit.GPIO22 = 2; // EM2D6
    GpioCtrlRegs.GPAMUX2.bit.GPIO23 = 2; // EM2D7
    GpioCtrlRegs.GPAMUX2.bit.GPIO24 = 2; // EM2D8
    GpioCtrlRegs.GPAMUX2.bit.GPIO25 = 2; // EM2D9
    GpioCtrlRegs.GPAMUX2.bit.GPIO26 = 2; // EM2D10
    GpioCtrlRegs.GPAMUX2.bit.GPIO27 = 2; // EM2D11
    GpioCtrlRegs.GPBMUX1.bit.GPIO48 = 2; // EM2D12
    GpioCtrlRegs.GPBMUX1.bit.GPIO49 = 2; // EM2D13
    GpioCtrlRegs.GPBMUX1.bit.GPIO50 = 2; // EM2D14
    GpioCtrlRegs.GPBMUX1.bit.GPIO51 = 2; // EM2D15
    // 주소 (EM2A0~EM2A11)
    GpioCtrlRegs.GPBMUX1.bit.GPIO52 = 2; // EM2A0
    GpioCtrlRegs.GPBMUX1.bit.GPIO53 = 2; // EM2A1
    GpioCtrlRegs.GPBMUX1.bit.GPIO54 = 2; // EM2A2
    GpioCtrlRegs.GPBMUX1.bit.GPIO55 = 2; // EM2A3
    GpioCtrlRegs.GPBMUX2.bit.GPIO60 = 2; // EM2A4
    GpioCtrlRegs.GPBMUX2.bit.GPIO61 = 2; // EM2A5
    GpioCtrlRegs.GPBMUX2.bit.GPIO62 = 2; // EM2A6
    GpioCtrlRegs.GPBMUX2.bit.GPIO63 = 2; // EM2A7
    GpioCtrlRegs.GPCMUX1.bit.GPIO64 = 2; // EM2A8
    GpioCtrlRegs.GPCMUX1.bit.GPIO65 = 2; // EM2A9
    GpioCtrlRegs.GPCMUX1.bit.GPIO66 = 2; // EM2A10
    GpioCtrlRegs.GPCMUX1.bit.GPIO67 = 2; // EM2A11
    // 제어 신호
    GpioCtrlRegs.GPAMUX2.bit.GPIO30 = 2; // EM2WE
    GpioCtrlRegs.GPAMUX2.bit.GPIO31 = 2; // EM2OE
    EDIS;

    // EMIF2 클럭 활성화
    EALLOW;
    CpuSysRegs.PCLKCR8.bit.EMIF2 = 1; // EMIF2 모듈 클럭 활성화
    EDIS;

    // EMIF2 CS0 설정 (비동기 NOR Flash)
    EALLOW;
    Emif2Regs.ASYNC_CS0_CTRL.bit.CS_EN = 1; // CS0 활성화
    Emif2Regs.ASYNC_CS0_CTRL.bit.ASIZE = 1; // 16비트 데이터 버스
    Emif2Regs.ASYNC_CS0_CTRL.bit.W_SETUP = 2; // 쓰기 설정 시간
    Emif2Regs.ASYNC_CS0_CTRL.bit.W_STROBE = 6; // 쓰기 스트로브 시간
    Emif2Regs.ASYNC_CS0_CTRL.bit.W_HOLD = 2; // 쓰기 홀드 시간
    Emif2Regs.ASYNC_CS0_CTRL.bit.R_SETUP = 2; // 읽기 설정 시간
    Emif2Regs.ASYNC_CS0_CTRL.bit.R_STROBE = 6; // 읽기 스트로브 시간
    Emif2Regs.ASYNC_CS0_CTRL.bit.R_HOLD = 2; // 읽기 홀드 시간
    Emif2Regs.ASYNC_CS0_CTRL.bit.TURN_AROUND = 2; // 턴어라운드 시간
    EDIS;

    // 메모리 테스트
    volatile Uint16 *nor = (volatile Uint16 *)NOR_BASE;
    Uint16 read_data = nor[0]; // 데이터 읽기

    // LED 점등 (정상 동작 확인)
    EALLOW;
    GpioCtrlRegs.GPBDIR.bit.GPIO31 = 1; // GPIO31 출력(LED)
    GpioDataRegs.GPBSET.bit.GPIO31 = 1; // LED 켜기
    EDIS;

    for(;;); // 무한 루프
}

설명:

  • 기능: EMIF2 CS0를 통해 NOR Flash에서 데이터 읽기.
  • 설정: 16비트 데이터 버스, 읽기/쓰기 타이밍 설정(NOR Flash에 적합), CS0 활성화.
  • GPIO:
    • 칩 선택: EM2CS0 (GPIO28)
    • 데이터: EM2D015 (GPIO1627, GPIO48~51)
    • 주소: EM2A011 (GPIO5255, GPIO60~67)
    • 제어: EM2WE (GPIO30), EM2OE (GPIO31)
    • LED: GPIO31
  • 출력: NOR_BASE(0x00100000)에서 데이터 읽기, 정상 동작 시 LED ON.

5.5 예제 5: EMIF1 DMA 데이터 전송

// File: emif_dma.c
// Description: TMS320F28377D EMIF1 DMA 데이터 전송 예제 (Bitfield 구조)
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28377D

#include "F28x_Project.h"

#define SRAM_BASE 0x08000000 // EMIF1 CS2 메모리 주소
#define BUFFER_SIZE 16
Uint16 internal_buffer[BUFFER_SIZE] = {0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888,
                                      0x9999, 0xAAAA, 0xBBBB, 0xCCCC, 0xDDDD, 0xEEEE, 0xFFFF, 0x0000};

void main(void) {
    // 시스템 초기화
    InitSysCtrl(); // 시스템 클럭 및 PLL 초기화
    DINT; // 모든 인터럽트 비활성화
    InitPieCtrl(); // PIE 초기화
    IER = 0x0000; // CPU 인터럽트 비활성화
    IFR = 0x0000; // 대기 중인 인터럽트 플래그 지우기
    InitPieVectTable(); // PIE 벡터 테이블 초기화

    // GPIO 설정 (EMIF1 CS2, 데이터, 주소, 제어 신호)
    EALLOW;
    // 칩 선택
    GpioCtrlRegs.GPBMUX1.bit.GPIO34 = 2; // EM1CS2
    // 데이터 (EM1D0~EM1D15, 16비트 버스)
    GpioCtrlRegs.GPBMUX1.bit.GPIO40 = 2; // EM1D0
    GpioCtrlRegs.GPBMUX1.bit.GPIO41 = 2; // EM1D1
    GpioCtrlRegs.GPBMUX1.bit.GPIO42 = 2; // EM1D2
    GpioCtrlRegs.GPBMUX1.bit.GPIO43 = 2; // EM1D3
    GpioCtrlRegs.GPBMUX1.bit.GPIO44 = 2; // EM1D4
    GpioCtrlRegs.GPBMUX1.bit.GPIO45 = 2; // EM1D5
    GpioCtrlRegs.GPBMUX1.bit.GPIO46 = 2; // EM1D6
    GpioCtrlRegs.GPBMUX1.bit.GPIO47 = 2; // EM1D7
    GpioCtrlRegs.GPCMUX1.bit.GPIO64 = 2; // EM1D8
    GpioCtrlRegs.GPCMUX1.bit.GPIO65 = 2; // EM1D9
    GpioCtrlRegs.GPCMUX1.bit.GPIO66 = 2; // EM1D10
    GpioCtrlRegs.GPCMUX1.bit.GPIO67 = 2; // EM1D11
    GpioCtrlRegs.GPCMUX1.bit.GPIO68 = 2; // EM1D12
    GpioCtrlRegs.GPCMUX1.bit.GPIO69 = 2; // EM1D13
    GpioCtrlRegs.GPCMUX1.bit.GPIO70 = 2; // EM1D14
    GpioCtrlRegs.GPCMUX1.bit.GPIO71 = 2; // EM1D15
    // 주소 (EM1A0~EM1A11, 예시로 12비트 주소 사용)
    GpioCtrlRegs.GPBMUX2.bit.GPIO58 = 2; // EM1A0
    GpioCtrlRegs.GPBMUX2.bit.GPIO59 = 2; // EM1A1
    GpioCtrlRegs.GPBMUX2.bit.GPIO60 = 2; // EM1A2
    GpioCtrlRegs.GPBMUX2.bit.GPIO61 = 2; // EM1A3
    GpioCtrlRegs.GPBMUX2.bit.GPIO62 = 2; // EM1A4
    GpioCtrlRegs.GPBMUX2.bit.GPIO63 = 2; // EM1A5
    GpioCtrlRegs.GPCMUX2.bit.GPIO72 = 2; // EM1A6
    GpioCtrlRegs.GPCMUX2.bit.GPIO73 = 2; // EM1A7
    GpioCtrlRegs.GPCMUX2.bit.GPIO74 = 2; // EM1A8
    GpioCtrlRegs.GPCMUX2.bit.GPIO75 = 2; // EM1A9
    GpioCtrlRegs.GPCMUX2.bit.GPIO76 = 2; // EM1A10
    GpioCtrlRegs.GPCMUX2.bit.GPIO77 = 2; // EM1A11
    // 제어 신호
    GpioCtrlRegs.GPBMUX2.bit.GPIO56 = 2; // EM1WE
    GpioCtrlRegs.GPBMUX2.bit.GPIO57 = 2; // EM1OE
    EDIS;

    // EMIF1 클럭 활성화
    EALLOW;
    CpuSysRegs.PCLKCR8.bit.EMIF1 = 1; // EMIF1 모듈 클럭 활성화
    EDIS;

    // EMIF1 CS2 설정 (비동기 SRAM)
    EALLOW;
    Emif1Regs.ASYNC_CS2_CTRL.bit.CS_EN = 1; // CS2 활성화
    Emif1Regs.ASYNC_CS2_CTRL.bit.ASIZE = 1; // 16비트 데이터 버스
    Emif1Regs.ASYNC_CS2_CTRL.bit.W_SETUP = 1; // 쓰기 설정 시간
    Emif1Regs.ASYNC_CS2_CTRL.bit.W_STROBE = 4; // 쓰기 스트로브 시간
    Emif1Regs.ASYNC_CS2_CTRL.bit.W_HOLD = 1; // 쓰기 홀드 시간
    Emif1Regs.ASYNC_CS2_CTRL.bit.R_SETUP = 1; // 읽기 설정 시간
    Emif1Regs.ASYNC_CS2_CTRL.bit.R_STROBE = 4; // 읽기 스트로브 시간
    Emif1Regs.ASYNC_CS2_CTRL.bit.R_HOLD = 1; // 읽기 홀드 시간
    Emif1Regs.ASYNC_CS2_CTRL.bit.TURN_AROUND = 1; // 턴어라운드 시간
    EDIS;

    // DMA 초기화
    EALLOW;
    CpuSysRegs.PCLKCR0.bit.DMA = 1; // DMA 클럭 활성화
    EDIS;
    DMAInitialize();

    // DMA 채널 1 설정 (내부 메모리 -> EMIF1 SRAM)
    DMACH1AddrConfig((volatile Uint16 *)SRAM_BASE, internal_buffer);
    DMACH1BurstConfig(15, 1, 1); // 16워드 전송, 소스/대상 1워드 증가
    DMACH1TransferConfig(0, 0, 0); // 단일 전송
    DMACH1ModeConfig(DMA_EMIF1, PERINT_ENABLE, false, true, false, 0, 0, false);
    StartDMACH1();

    // 지연 (DMA 전송 완료 대기)
    asm(" RPT #100 || NOP");

    // LED 점등 (정상 동작 확인)
    EALLOW;
    GpioCtrlRegs.GPBDIR.bit.GPIO31 = 1; // GPIO31 출력(LED)
    GpioDataRegs.GPBSET.bit.GPIO31 = 1; // LED 켜기
    EDIS;

    for(;;); // 무한 루프
}

설명:

  • 기능: EMIF1 CS2를 통해 내부 메모리에서 SRAM으로 DMA를 사용한 데이터 전송.
  • 설정: 16비트 데이터 버스, 읽기/쓰기 타이밍 설정, DMA 채널 1 설정(16워드 전송).
  • GPIO:
    • 칩 선택: EM1CS2 (GPIO34)
    • 데이터: EM1D015 (GPIO4047, GPIO64~71)
    • 주소: EM1A011 (GPIO5863, GPIO72~77)
    • 제어: EM1WE (GPIO56), EM1OE (GPIO57)
    • LED: GPIO31
  • 출력: SRAM_BASE(0x08000000)에 internal_buffer 데이터 전송, 정상 동작 시 LED ON.

5.6 예제 6: 병렬 ADC 데이터 읽기

// File: emif_adc.c
// Description: TMS320F28377D EMIF 병렬 ADC 데이터 읽기 예제 (Bitfield 구조)
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28377D

#include "F28x_Project.h"

#define ADC_BASE 0x08010000 // EMIF1 CS3 메모리 주소
#define ADC_CONTROL_ADDR 0x08010002 // ADC 제어 레지스터 주소 (예: 변환 시작)
volatile Uint16 adc_data = 0;

void main(void) {
    // 시스템 초기화
    InitSysCtrl(); // 시스템 클럭 및 PLL 초기화
    DINT; // 모든 인터럽트 비활성화
    InitPieCtrl(); // PIE 초기화
    IER = 0x0000; // CPU 인터럽트 비활성화
    IFR = 0x0000; // 대기 중인 인터럽트 플래그 지우기
    InitPieVectTable(); // PIE 벡터 테이블 초기화

    // GPIO 설정 (EMIF1 CS3, 데이터, 제어 신호)
    EALLOW;
    // 칩 선택
    GpioCtrlRegs.GPBMUX1.bit.GPIO35 = 2; // EM1CS3
    // 데이터 (EM1D0~EM1D15, 16비트 ADC)
    GpioCtrlRegs.GPBMUX1.bit.GPIO40 = 2; // EM1D0
    GpioCtrlRegs.GPBMUX1.bit.GPIO41 = 2; // EM1D1
    GpioCtrlRegs.GPBMUX1.bit.GPIO42 = 2; // EM1D2
    GpioCtrlRegs.GPBMUX1.bit.GPIO43 = 2; // EM1D3
    GpioCtrlRegs.GPBMUX1.bit.GPIO44 = 2; // EM1D4
    GpioCtrlRegs.GPBMUX1.bit.GPIO45 = 2; // EM1D5
    GpioCtrlRegs.GPBMUX1.bit.GPIO46 = 2; // EM1D6
    GpioCtrlRegs.GPBMUX1.bit.GPIO47 = 2; // EM1D7
    GpioCtrlRegs.GPCMUX1.bit.GPIO64 = 2; // EM1D8
    GpioCtrlRegs.GPCMUX1.bit.GPIO65 = 2; // EM1D9
    GpioCtrlRegs.GPCMUX1.bit.GPIO66 = 2; // EM1D10
    GpioCtrlRegs.GPCMUX1.bit.GPIO67 = 2; // EM1D11
    GpioCtrlRegs.GPCMUX1.bit.GPIO68 = 2; // EM1D12
    GpioCtrlRegs.GPCMUX1.bit.GPIO69 = 2; // EM1D13
    GpioCtrlRegs.GPCMUX1.bit.GPIO70 = 2; // EM1D14
    GpioCtrlRegs.GPCMUX1.bit.GPIO71 = 2; // EM1D15
    // 제어 신호
    GpioCtrlRegs.GPBMUX2.bit.GPIO57 = 2; // EM1OE (ADC 읽기)
    GpioCtrlRegs.GPBMUX2.bit.GPIO56 = 2; // EM1WE (ADC 제어 신호)
    // 주소 (최소 주소 라인, 제어 레지스터 접근용)
    GpioCtrlRegs.GPBMUX2.bit.GPIO58 = 2; // EM1A0
    GpioCtrlRegs.GPBMUX2.bit.GPIO59 = 2; // EM1A1
    EDIS;

    // EMIF1 클럭 활성화
    EALLOW;
    CpuSysRegs.PCLKCR8.bit.EMIF1 = 1; // EMIF1 모듈 클럭 활성화
    EDIS;

    // EMIF1 CS3 설정 (비동기 ADC)
    EALLOW;
    Emif1Regs.ASYNC_CS3_CTRL.bit.CS_EN = 1; // CS3 활성화
    Emif1Regs.ASYNC_CS3_CTRL.bit.ASIZE = 1; // 16비트 데이터 버스
    Emif1Regs.ASYNC_CS3_CTRL.bit.W_SETUP = 1; // 쓰기 설정 시간
    Emif1Regs.ASYNC_CS3_CTRL.bit.W_STROBE = 2; // 쓰기 스트로브 시간
    Emif1Regs.ASYNC_CS3_CTRL.bit.W_HOLD = 1; // 쓰기 홀드 시간
    Emif1Regs.ASYNC_CS3_CTRL.bit.R_SETUP = 1; // 읽기 설정 시간
    Emif1Regs.ASYNC_CS3_CTRL.bit.R_STROBE = 2; // 읽기 스트로브 시간
    Emif1Regs.ASYNC_CS3_CTRL.bit.R_HOLD = 1; // 읽기 홀드 시간
    Emif1Regs.ASYNC_CS3_CTRL.bit.TURN_AROUND = 1; // 턴어라운드 시간
    EDIS;

    // ADC 초기화 (변환 시작)
    volatile Uint16 *adc_control = (volatile Uint16 *)ADC_CONTROL_ADDR;
    *adc_control = 0x0001; // 변환 시작 명령 (ADC 데이터시트 참조)

    // 지연 (ADC 변환 완료 대기, 데이터시트 기준)
    asm(" RPT #50 || NOP");

    // ADC 데이터 읽기
    volatile Uint16 *adc = (volatile Uint16 *)ADC_BASE;
    adc_data = *adc; // 16비트 ADC 데이터 읽기

    // LED 점등 (정상 동작 확인)
    EALLOW;
    GpioCtrlRegs.GPBDIR.bit.GPIO31 = 1; // GPIO31 출력(LED)
    GpioDataRegs.GPBSET.bit.GPIO31 = 1; // LED 켜기
    EDIS;

    for(;;); // 무한 루프
}

설명:

  • 기능: EMIF1 CS3를 통해 병렬 16비트 ADC에서 데이터 읽기.
  • 설정: 16비트 데이터 버스, 빠른 읽기/쓰기 타이밍(ADC에 최적화), CS3 활성화.
  • GPIO:
    • 칩 선택: EM1CS3 (GPIO35)
    • 데이터: EM1D015 (GPIO4047, GPIO64~71)
    • 주소: EM1A01 (GPIO5859, 제어 레지스터 접근용)
    • 제어: EM1WE (GPIO56, ADC 제어), EM1OE (GPIO57, 데이터 읽기)
    • LED: GPIO31
  • 출력: ADC_BASE(0x08010000)에서 변환된 데이터 읽기, 정상 동작 시 LED ON.
  • 참고: ADC 데이터시트에 따라 제어 명령(예: 변환 시작)과 타이밍 조정 필요.

5.7 예제 7: 병렬 DAC 데이터 쓰기

// File: emif_dac.c
// Description: TMS320F28377D EMIF 병렬 DAC 데이터 쓰기 예제 (Bitfield 구조)
// Compiler: Code Composer Studio (TI C2000 Compiler)
// Target: TMS320F28377D

#include "F28x_Project.h"

#define DAC_BASE 0x08020000 // EMIF1 CS4 메모리 주소
#define DAC_CONTROL_ADDR 0x08020002 // DAC 제어 레지스터 주소 (예: 출력 업데이트)

void main(void) {
    // 시스템 초기화
    InitSysCtrl(); // 시스템 클럭 및 PLL 초기화
    DINT; // 모든 인터럽트 비활성화
    InitPieCtrl(); // PIE 초기화
    IER = 0x0000; // CPU 인터럽트 비활성화
    IFR = 0x0000; // 대기 중인 인터럽트 플래그 지우기
    InitPieVectTable(); // PIE 벡터 테이블 초기화

    // GPIO 설정 (EMIF1 CS4, 데이터, 제어 신호)
    EALLOW;
    // 칩 선택
    GpioCtrlRegs.GPBMUX1.bit.GPIO36 = 2; // EM1CS4
    // 데이터 (EM1D0~EM1D15, 16비트 DAC)
    GpioCtrlRegs.GPBMUX1.bit.GPIO40 = 2; // EM1D0
    GpioCtrlRegs.GPBMUX1.bit.GPIO41 = 2; // EM1D1
    GpioCtrlRegs.GPBMUX1.bit.GPIO42 = 2; // EM1D2
    GpioCtrlRegs.GPBMUX1.bit.GPIO43 = 2; // EM1D3
    GpioCtrlRegs.GPBMUX1.bit.GPIO44 = 2; // EM1D4
    GpioCtrlRegs.GPBMUX1.bit.GPIO45 = 2; // EM1D5
    GpioCtrlRegs.GPBMUX1.bit.GPIO46 = 2; // EM1D6
    GpioCtrlRegs.GPBMUX1.bit.GPIO47 = 2; // EM1D7
    GpioCtrlRegs.GPCMUX1.bit.GPIO64 = 2; // EM1D8
    GpioCtrlRegs.GPCMUX1.bit.GPIO65 = 2; // EM1D9
    GpioCtrlRegs.GPCMUX1.bit.GPIO66 = 2; // EM1D10
    GpioCtrlRegs.GPCMUX1.bit.GPIO67 = 2; // EM1D11
    GpioCtrlRegs.GPCMUX1.bit.GPIO68 = 2; // EM1D12
    GpioCtrlRegs.GPCMUX1.bit.GPIO69 = 2; // EM1D13
    GpioCtrlRegs.GPCMUX1.bit.GPIO70 = 2; // EM1D14
    GpioCtrlRegs.GPCMUX1.bit.GPIO71 = 2; // EM1D15
    // 제어 신호
    GpioCtrlRegs.GPBMUX2.bit.GPIO56 = 2; // EM1WE (DAC 쓰기)
    GpioCtrlRegs.GPBMUX2.bit.GPIO57 = 2; // EM1OE
    // 주소 (최소 주소 라인, 제어 레지스터 접근용)
    GpioCtrlRegs.GPBMUX2.bit.GPIO58 = 2; // EM1A0
    GpioCtrlRegs.GPBMUX2.bit.GPIO59 = 2; // EM1A1
    EDIS;

    // EMIF1 클럭 활성화
    EALLOW;
    CpuSysRegs.PCLKCR8.bit.EMIF1 = 1; // EMIF1 모듈 클럭 활성화
    EDIS;

    // EMIF1 CS4 설정 (비동기 DAC)
    EALLOW;
    Emif1Regs.ASYNC_CS4_CTRL.bit.CS_EN = 1; // CS4 활성화
    Emif1Regs.ASYNC_CS4_CTRL.bit.ASIZE = 1; // 16비트 데이터 버스
    Emif1Regs.ASYNC_CS4_CTRL.bit.W_SETUP = 1; // 쓰기 설정 시간
    Emif1Regs.ASYNC_CS4_CTRL.bit.W_STROBE = 2; // 쓰기 스트로브 시간
    Emif1Regs.ASYNC_CS4_CTRL.bit.W_HOLD = 1; // 쓰기 홀드 시간
    Emif1Regs.ASYNC_CS4_CTRL.bit.R_SETUP = 1; // 읽기 설정 시간
    Emif1Regs.ASYNC_CS4_CTRL.bit.R_STROBE = 2; // 읽기 스트로브 시간
    Emif1Regs.ASYNC_CS4_CTRL.bit.R_HOLD = 1; // 읽기 홀드 시간
    Emif1Regs.ASYNC_CS4_CTRL.bit.TURN_AROUND = 1; // 턴어라운드 시간
    EDIS;

    // DAC 데이터 쓰기
    volatile Uint16 *dac = (volatile Uint16 *)DAC_BASE;
    *dac = 0x7FFF; // 16비트 DAC에 중간 값 쓰기 (예: 0V~3.3V 기준)

    // DAC 출력 업데이트
    volatile Uint16 *dac_control = (volatile Uint16 *)DAC_CONTROL_ADDR;
    *dac_control = 0x0001; // 출력 업데이트 명령 (DAC 데이터시트 참조)

    // 지연 (DAC 출력 안정화 대기, 데이터시트 기준)
    asm(" RPT #50 || NOP");

    // LED 점등 (정상 동작 확인)
    EALLOW;
    GpioCtrlRegs.GPBDIR.bit.GPIO31 = 1; // GPIO31 출력(LED)
    GpioDataRegs.GPBSET.bit.GPIO31 = 1; // LED 켜기
    EDIS;

    for(;;); // 무한 루프
}

설명:

  • 기능: EMIF1 CS4를 통해 병렬 16비트 DAC에 데이터 쓰기.
  • 설정: 16비트 데이터 버스, 빠른 쓰기 타이밍(DAC에 최적화), CS4 활성화.
  • GPIO:
    • 칩 선택: EM1CS4 (GPIO36)
    • 데이터: EM1D015 (GPIO4047, GPIO64~71)
    • 주소: EM1A01 (GPIO5859, 제어 레지스터 접근용)
    • 제어: EM1WE (GPIO56, 데이터 쓰기), EM1OE (GPIO57)
    • LED: GPIO31
  • 출력: DAC_BASE(0x08020000)에 0x7FFF 쓰기(중간 전압 출력), 정상 동작 시 LED ON.
  • 참고: DAC 데이터시트에 따라 제어 명령(예: 출력 업데이트)과 타이밍 조정 필요.

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 하드웨어 준비

  • 메모리/장치 연결: EMIF1 또는 EMIF2 핀에 SRAM, SDRAM, NOR Flash, ADC, DAC 연결. SDRAM의 경우 EMIF_BA[1:0] 핀 연결 필수.
  • 타이밍 확인: 메모리 또는 장치(ADC/DAC 포함) 데이터시트에 따라 타이밍 파라미터 조정.
  • LED: GPIO31에 LED 연결 (정상 동작 확인용).
  • 디버깅 도구: 오실로스코프 또는 로직 분석기로 신호 확인.

6.4 디버깅

  • CCS Expressions 창: Emif1Regs.ASYNC_CSx_CTRL, Emif1Regs.SDRAM_CR, Emif1Regs.SDRAM_TR, Emif2Regs.ASYNC_CS0_CTRL 확인.
  • 인터럽트 상태: Emif1Regs.INT_RAW로 인터럽트 플래그 점검.
  • 메모리/장치 테스트: 읽기/쓰기 데이터 일치 여부 확인.
  • 문제 해결:
    • 메모리/장치 액세스 실패: GPIO 설정(특히 EMIF_BA[1:0], ADC/DAC 제어), 타이밍 파라미터 확인.
    • 인터럽트 미발생: INT_EN, PIEIER12, IER 설정 확인.
    • DMA 전송 실패: DMA 설정(DMACH1AddrConfig, DMACH1BurstConfig) 확인.
    • SDRAM 뱅크 액세스 오류: SDRAM_CR.bit.BANK_SIZE, EMIF_BA[1:0] 핀 매핑 확인.
    • ADC/DAC 오류: 데이터시트 기반으로 제어 신호 및 타이밍 점검.

7. 추가 팁

  • 캘리브레이션: Device_cal() 호출로 클럭 보정.
  • 타이밍 최적화: 메모리 또는 장치(ADC/DAC 포함) 데이터시트 기반으로 최소 타이밍 설정.
  • EMIF_BA[1:0] 확인: SDRAM 사용 시 뱅크 선택이 올바르게 매핑되었는지 확인 (예: GPIO36, GPIO37 for EM1BA[1:0]).
  • ADC/DAC 설정: 장치별 데이터시트를 참조하여 제어 레지스터 명령 및 타이밍 최적화.
  • C2000Ware 참고: C:\ti\c2000\C2000Ware_x_xx_xx_xx\device_support\f2837xd\examples\cpu1\emif.
  • 문제 해결:
    • 데이터 오류: ASIZE, PAGE_SIZE, BANK_SIZE, EMIF_BA[1:0], ADC/DAC 설정 확인.
    • SDRAM 초기화 실패: SDRAM_RCR, 타이밍 설정, EMIF_BA[1:0] 핀 점검.
    • ADC/DAC 동작 실패: EMIF 타이밍 및 제어 신호(EMxWE, EMxOE) 점검.
  • TI 리소스: TI E2E 포럼, C2000Ware 예제.

8. 결론

이 문서는 TMS320F28377D EMIF 모듈의 설정 방법과 Bitfield 구조를 활용한 예제 코드를 제공하여, 초보자부터 숙련된 개발자까지 쉽게 활용할 수 있도록 구성했습니다. 비동기 SRAM 읽기/쓰기, SDRAM 초기화(EMIF_BA[1:0] 포함), 인터럽트 기반 데이터 전송, NOR Flash 읽기, DMA 데이터 전송, 병렬 ADC 데이터 읽기, 병렬 DAC 데이터 쓰기 예제를 통해 다양한 애플리케이션에 적용 가능합니다.

키워드: TMS320F28377D, EMIF, C2000, SRAM, SDRAM, NOR Flash, ADC, DAC, 비동기 메모리, 동기 메모리, DMA, EMIF_BA, 마이크로컨트롤러, Code Composer Studio, 인터럽트, 타이밍 설정, 메모리 매핑

반응형