본문 바로가기
Embedded SW/Embedded SW Introduction

SPI 예제 코드를 포팅, 동작 확인 2편 (T275 인피니언 MCU)

by 방구석 임베디드 2022. 9. 12.
반응형

인피니언 MCU인 TC275를 이용하여 SPI 예제코드를 포팅해서

동작해 보도록 하겠습니다.

 

지금 쓰는 글은 2편입니다 ㅎ

따라서 1편글을 읽고 오셔야 이해가 되실 겁니다.

1편글의 링크를 아래와 같이 전달 드립니다.

https://embeddedchallenge.tistory.com/444

 

이제 Slave 쪽을 포팅할게요!

IFX_INTERRUPT(SPI1_TxHandler, 0, ISR_PRIORITY_QSPI1_TX);
IFX_INTERRUPT(SPI1_RxHandler, 0, ISR_PRIORITY_QSPI1_RX);
IFX_INTERRUPT(SPI1_ErHandler, 0, ISR_PRIORITY_QSPI1_ER);

void SPI1_TxHandler(void)
{
    IfxCpu_enableInterrupts();
    IfxQspi_SpiSlave_isrTransmit(&g_QspiCpu.drivers.spiSlave);
}

void SPI1_RxHandler(void)
{
    IfxCpu_enableInterrupts();
    IfxQspi_SpiSlave_isrReceive(&g_QspiCpu.drivers.spiSlave);
}

void SPI1_ErHandler(void)
{
    IfxCpu_enableInterrupts();
    IfxQspi_SpiSlave_isrError(&g_QspiCpu.drivers.spiSlave);
}

static void Driver_Spi1_Init(void)
{
    IfxQspi_SpiSlave_Config spiSlaveConfig;
    int i;

    /* create module config */
    IfxQspi_SpiSlave_initModuleConfig(&spiSlaveConfig, &MODULE_QSPI1);

    /* set the maximum baudrate */
    spiSlaveConfig.base.maximumBaudrate = 10000000;

    /* ISR priorities and interrupt target */
    spiSlaveConfig.base.txPriority  = ISR_PRIORITY_QSPI1_TX;
    spiSlaveConfig.base.rxPriority  = ISR_PRIORITY_QSPI1_RX;
    spiSlaveConfig.base.erPriority  = ISR_PRIORITY_QSPI1_ER;
    spiSlaveConfig.base.isrProvider = (IfxSrc_Tos)IfxCpu_getCoreIndex();

    /* pin configuration */
    const IfxQspi_SpiSlave_Pins slavePins = {&IfxQspi1_SCLKA_P10_2_IN,                               /* SCLK Pin */
                                             IfxPort_InputMode_pullDown,
                                             &IfxQspi1_MTSRA_P10_3_IN,  IfxPort_InputMode_pullDown,  /* MTSR Pin */
                                             &IfxQspi1_MRST_P10_1_OUT,  IfxPort_OutputMode_pushPull, /* MRST Pin */
                                             &IfxQspi1_SLSIA_P11_10_IN,  IfxPort_InputMode_pullDown,  /* SLSI Pin */
                                             IfxPort_PadDriver_cmosAutomotiveSpeed3                  /* pad driver mode */
    };
    spiSlaveConfig.pins = &slavePins;

    /* initialize module */
    IfxQspi_SpiSlave_initModule(&g_QspiCpu.drivers.spiSlave, &spiSlaveConfig);


    /* init tx buffer area */
    for (i = 0; i < SPI_BUFFER_SIZE; i++)
    {
        g_QspiCpu.qspiBuffer.spi1TxBuffer[i] = (uint8)(i + 100);
        g_QspiCpu.qspiBuffer.spi1RxBuffer[i] = (uint8)(0);
    }
}



void Driver_Spi_Init(void)
{
    /* disable interrupts */
    boolean interruptState = IfxCpu_disableInterrupts();

    Driver_Spi1_Init();

    /* enable interrupts again */
    IfxCpu_restoreInterrupts(interruptState);
}

void Driver_Spi_SlaveTest(void)
{
    uint32 size = SPI_BUFFER_SIZE;

    /* Slave transfer */
    while (IfxQspi_SpiSlave_getStatus(&g_QspiCpu.drivers.spiSlave) == SpiIf_Status_busy)
    {}

    IfxQspi_SpiSlave_exchange(&g_QspiCpu.drivers.spiSlave, &g_QspiCpu.qspiBuffer.spi1TxBuffer[0],
        &g_QspiCpu.qspiBuffer.spi1RxBuffer[0], SPI_BUFFER_SIZE);

    #if 0
    /* wait until slave received all data */
    while (IfxQspi_SpiSlave_getStatus(&g_QspiCpu.drivers.spiSlave) == SpiIf_Status_busy)
    {}
    #endif
}

Slave 입장에서는

Clock 부분이 SCLK의 핀은 input입니다.

이 SCLK는 Master MCU가 만들어 주어서 Slave쪽으로 주기 때문입니다.

CS핀도 역시 Master MCU가 만들어 주기 때문에 Input입니다.

MOSI(MTSR)핀도 Input이고

오직

MISO(MRST)핀만이 Output입니다.

해당 내용은 기본적인 내용이며 아래 글에서 확인하실 수 있습니다.

https://embeddedchallenge.tistory.com/58

 

05. SPI 통신이란 무엇인가?

SPI(Serial Peripheral Interface)는 Electric Control Unit안에서 IC(Integrated Chip) 끼리 통신을 수행하기 위한 통신 기법입니다. 아래 두개의 자동차 ECU가 있습니다. VCM(Vehicle Control Module) 와 BCM(Bo..

embeddedchallenge.tistory.com

그렇다면 Master SPI 설정과 정 반대라는 사실을 아실 수 있을 것입니다.

&IfxQspi1_SCLKA_P10_2_IN,                               /* SCLK Pin */

&IfxQspi1_MTSRA_P10_3_IN,  IfxPort_InputMode_pullDown,  /* MTSR Pin */

&IfxQspi1_MRST_P10_1_OUT,  IfxPort_OutputMode_pushPull, /* MRST Pin */

&IfxQspi1_SLSIA_P11_10_IN,  IfxPort_InputMode_pullDown,  /* SLSI Pin */

그리고 Test Code는 아래와 같이 만들었습니다.

void Driver_Spi_SlaveTest(void)
{
    uint32 size = SPI_BUFFER_SIZE;

    /* Slave transfer */
    while (IfxQspi_SpiSlave_getStatus(&g_QspiCpu.drivers.spiSlave) == SpiIf_Status_busy)
    {}

    IfxQspi_SpiSlave_exchange(&g_QspiCpu.drivers.spiSlave, &g_QspiCpu.qspiBuffer.spi1TxBuffer[0],
        &g_QspiCpu.qspiBuffer.spi1RxBuffer[0], SPI_BUFFER_SIZE);
}

위의 코드는 Slave가 보내려는 값을

미리 Tx 버퍼에 채우고 있는 것을 확인하실 수 있습니다.

그리고 Master가 SCK라인을 통해서 Clock을 날리면

그 Clock에 맞추어(동기화되어) 지금 채워진 버퍼를 

그대로 날리는 구조로 되어 있다는 것을 알 수 있습니다.

이제 두개의 보드를 한번 연결해 보도록 하게요!!

위의 위치한 보드가 Slave 입니다.

아래 위치한 보드가 Master 입니다.

두개의 보드가 SPI모듈핀을 통해서 연결이 되어 있습니다.

이제 Master에서 SCK라인을 통해 Clock을 날리게 되면

Slave는 아래와 같이 값을 Master MCU쪽으로 주게될 것입니다.

    /* init tx buffer area */
    for (i = 0; i < SPI_BUFFER_SIZE; i++)
    {
        g_QspiCpu.qspiBuffer.spi1TxBuffer[i] = (uint8)(i + 100);
        g_QspiCpu.qspiBuffer.spi1RxBuffer[i] = (uint8)(0);
    }

TxBuffer는 총 10개의 값을 날리고 있습니다.

100, 101 ... 109

이것을 16진수로 변경하면

0x64 ... 0x6D입니다.

 

그러면 한번 Logic Analyzer를 이용해서 계측을 해보도록 하겠습니다.

역시 예상대로 동작하는 것을 확인 할 수 있습니다.

채널3번이 Slave에서 Master쪽으로 보내는 데이터 입니다.

Slave에 채워진 버퍼가 SCK를 받으면 바로 뱉어내고 있는 것을 볼 수 있습니다.

 

이제 한번 디버거를 이용해서 확인해 보도록 하겠습니다.

Slave도 Master가 보낸 데이터를 잘 받은 것을 확인 할 수 있습니다.

현재 작업한 코드는 아래 링크에서 다운로드 가능하니 참고해 주세요.

https://cafe.naver.com/binaryembedded/141

 

실제로 SPI는 MCU와 MCU끼리 통신을 하는데 사용하지는 않습니다.

MCU와 IC끼리 통신을 하는데 사용하는데

그 예제를 아래와 같이 구현하여 동작시켜 보았으니 참고해 보시면 좋을 것 같습니다.

https://embeddedchallenge.tistory.com/442 

https://embeddedchallenge.tistory.com/443 

 

이상으로 금일 포스팅을 마치도록 하겠습니다.

반응형

댓글