본문 바로가기
임베디드 개발/TMS320F2838x (C28x)

TMS320F28388D ] 멀티 코어 사용하기

by eteo 2022. 9. 16.

 

 

TMS320F28388D 모듈은 C28x 듀얼 코어에 CM(Connectivity Manager) 이라고 Arm Cortex-M4 까지붙어있다.

 

 

 

TI에서 기본 제공하는 예제는 보면 듀얼 코어를 사용하는 예제와 CM을 사용하는 예제들이 많다.

 

 

 

 

그 중에 CM이 led blink 하는 예제를 실행해보겠다. 듀얼코어를 사용하는 방법도 다르지 않다.

 

 

 

 

Import 하면 다음과 같이 프로젝트 두 개가 생성된다.

 

 

 

 

아래가 CPU1이 CM을 위해 pin mux 세팅을 해주는 부분, 위가 CM이 led blink 하는 부분으로 구성되어 있다.

 

 

//
// Included Files
//
#include "driverlib.h"
#include "device.h"

//
// Main
//
void main(void)
{
    //
    // Initialize device clock and peripherals
    //
    Device_init();

    //
    // Boot CM core
    //
#ifdef _FLASH
    Device_bootCM(BOOTMODE_BOOT_TO_FLASH_SECTOR0);
#else
    Device_bootCM(BOOTMODE_BOOT_TO_S0RAM);
#endif

    //
    // Initialize GPIO and configure the GPIO pin as a push-pull output
    //
    Device_initGPIO();
    GPIO_setPadConfig(DEVICE_GPIO_PIN_LED1, GPIO_PIN_TYPE_STD);
    GPIO_setDirectionMode(DEVICE_GPIO_PIN_LED1, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(DEVICE_GPIO_PIN_LED2, GPIO_PIN_TYPE_STD);
    GPIO_setDirectionMode(DEVICE_GPIO_PIN_LED2, GPIO_DIR_MODE_OUT);

    //
    // Configure CPU2 to control the LED GPIO
    //
    GPIO_setMasterCore(DEVICE_GPIO_PIN_LED2, GPIO_CORE_CM);

    //
    // Initialize PIE and clear PIE registers. Disables CPU interrupts.
    //
    Interrupt_initModule();

    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    //
    Interrupt_initVectorTable();

    //
    // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
    //
    EINT;
    ERTM;

    //
    // Loop Forever
    //
    for(;;)
    {
        //
        // Turn on LED
        //
        GPIO_writePin(DEVICE_GPIO_PIN_LED1, 0);

        //
        // Delay for a bit.
        //
        DEVICE_DELAY_US(500000);

        //
        // Turn off LED
        //
        GPIO_writePin(DEVICE_GPIO_PIN_LED1, 1);

        //
        // Delay for a bit.
        //
        DEVICE_DELAY_US(500000);
    }
}

//
// End of File
//

 

clock 과 peripherals init 하고 FLASH인지 RAM 빌드인지 구분하여 CM 코어를 부팅시키고 LED1 과 LED2를 GPIO push-pull output으로 설정하는데 그 중 LED2의 제어권을 CM에게 넘기고 CPU1은 루프안에서 LED1만 블링크한다.

 

 

 

CM 쪽 소스코드

//
// Included Files
//
#include "driverlib_cm.h"
#include "cm.h"

//
// Main
//
void main(void)
{
    //
    // Initialize device clock and peripherals
    //
    CM_init();

    //
    // Initialize GPIO and configure the GPIO pin as a push-pull output
    //
    // This is configured by CPU1

    //
    // Loop Forever
    //
    for(;;)
    {
        //
        // Turn on LED
        //
        GPIO_writePin(DEVICE_GPIO_PIN_LED2, 0);

        //
        // Delay for 500000uS.
        //
        DEVICE_DELAY_US(500000);

        //
        // Turn off LED
        //
        GPIO_writePin(DEVICE_GPIO_PIN_LED2, 1);

        //
        // Delay for 500000uS.
        //
        DEVICE_DELAY_US(500000);
    }
}

//
// End of File
//

 

init 설정 후 LED2를 블링크한다.

 

 

 

양 쪽 프로젝트에 중단점을 설정하고 디버깅하려면 이전에 썼던 방법으로 해야하는데 단순히 실행만 시켜보려면 다른방법이 있다.

 

2022.09.14 - [DSP, MCU/TMS320F2838x (C28x)] - TMS320F28388D ] 멀티 코어 환경에서 디버깅하기

 

TMS320F28388D ] 멀티 코어 환경에서 디버깅하기

examples/cm 의 uart 예제를 찾아보면 CPU1(c28x) 코어가 uart config 하는 예제와 CM(ARM Cortex-M4) 코어가 uart echoback 을 수행하는 예제 두 개 가 보인다. 둘 다 import 한다. 첫 번째 예제는 CPU1이 CM을..

eteo.tistory.com

 

 

 

 

 

일단 CM 쪽 프로젝트를 플래시로 빌드하고 로드한 다음에 CPU1 프로젝트를 CPU1에 로드해서 실행시키면 CPU1이 CM을 부팅시킬거고 CM에는 플래시 메모리에 기록된 소스코드가 실행될테니 내가 의도한 대로 돌아가는 것을 볼 수 있다.

 

 

 

 

 

 

CPU1 프로젝트를 보면 앞쪽에 CM을 부트시키는 코드가 있다.

 

#ifdef _FLASH
    Device_bootCM(BOOTMODE_BOOT_TO_FLASH_SECTOR0);
#else
    Device_bootCM(BOOTMODE_BOOT_TO_S0RAM);
#endif

 

 #ifdef _FLASH 인지 확인하고 해당 코드를 실행 시키는데 이 _FLASH는 플래시 빌드를 하면 사전 정의된 매크로로 들어간다.

프로젝트 오른쪽 클릭 properties - CCS Build - C2000 Compiler 에서 사전 정의된 매크로들을 볼 수 있다.

 

 

 

다만 여기선 CPU1은 램빌드를 해도 상관없고 CM을 플래시 부트섹터에서 부팅시키면 되는 거라서 해당 코드만 남기고 지워도 된다.

Device_bootCM(BOOTMODE_BOOT_TO_FLASH_SECTOR0);

 

 

LED1과 LED2 가 1초 주기로 동시에 깜빡이는 것을 볼 수 있다.