RM57L843: RM57 SPI with DMA Master / Slave

Part Number: RM57L843

Tool/software:

Hi, Ti,

I want to use SPI Master and Slave with DMA.

For this, I desigend SPI1 Master only and SPI3 Slave only.

Master function is no problem, but SPI3 Slave only function, it has a problem.

I intented to this function  should be working without tx dummy, because some examples from e2e I couldn't see dummy tx.

so I need you cofirm my codes attatche.

Also here is my H/W connection. additionally I'm not using ENA control signal.

#include "ChComm.h"

spiDAT1_t g_stSpi1Fmt =
{
    .CS_HOLD = FALSE,
    .DFSEL   = SPI_FMT_0,
    .WDEL    = 0U,
    .CSNR    = SPI_CS_1  /* 0xFD */
};

spiDAT1_t g_stSpi3Fmt =
{
    .CS_HOLD = FALSE,
    .DFSEL   = SPI_FMT_0,
    .WDEL    = 0U,
    .CSNR    = SPI_CS_0  /* 0xFE */
};


static uint8 g_aTxData[1024] = {0,};
static uint8 g_aRxData[1024] = {0,};


static uint16 g_aTxDat1[ SPI_WORDS_FROM_BYTES(SPI_MAX_BYTES) ];
static uint16 g_aRxBuf[ SPI_WORDS_FROM_BYTES(SPI_MAX_BYTES) ] = {0,};
static g_dmaCTRL g_stTxSpiDmaCtrlPkt;
static g_dmaCTRL g_stRxSpiDmaCtrlPkt;

static uint32 g_nRxCnt = 0U;
uint32 nLen = 1001U;

void dmaGroupANotification(dmaInterrupt_t inttype, uint32 channel)
{
	uint32 nTimeout = 10000000U;
	uint32 nStatus = 0;

	switch (channel)
	{
		case DMA_CH_SPI1_TX:
			if(inttype == BTC)
			{

				SPI1_TX->INT0 &=  ~((uint32)SPI_INT_TX_DMA_EN);
				dmaREG->BTCFLAG = (uint32)(1U << DMA_CH_SPI1_TX);
				dmaREG->HBCFLAG = (uint32)(1U << DMA_CH_SPI1_TX);
			}
		break;

		case DMA_CH_SPI3_TX:
			if(inttype == BTC)
			{

				SPI3_TX->INT0 &=  ~((uint32)SPI_INT_TX_DMA_EN);
				dmaREG->BTCFLAG = (uint32)(1U << DMA_CH_SPI3_TX);
				dmaREG->HBCFLAG = (uint32)(1U << DMA_CH_SPI3_TX);
			}
		break;

		case DMA_CH_SPI3_RX:
			if(inttype == BTC)
			{
//				while (dmaGetInterruptStatus(DMA_CH_SPI3_RX, BTC) == 0U)  { }

				SPI3_RX->INT0 &= ~(uint32)SPI_DMA_REQ_EN;
				dmaREG->BTCFLAG = (uint32)(1U << DMA_CH_SPI3_RX);
				dmaREG->HBCFLAG = (uint32)(1U << DMA_CH_SPI3_RX);
				Spi3RxFinalize(g_aRxData, nLen);
//	            NotifyChCommStatus();
			}
		break;

    }
	return;
}

static void PackBytesToWords16(const uint8 *pIn, uint32 nLen, uint16 *pOut16, uint32 *pOutWords)
{
    uint32 nWordCnt = 0U;
    for (uint32 i = 0U; i < nLen; i += 2U)
    {
        uint16 nHi = pIn[i];
        uint16 nLo = (i + 1U < nLen) ? pIn[i + 1U] : 0U; 
        pOut16[nWordCnt++] = (uint16)((nHi << 8) | nLo);        /* MSB-first */
    }
    *pOutWords = nWordCnt;

    return;
}

static void UnpackWords16ToBytes(const uint16 *pIn16, uint32 nWords, uint8 *pOut, uint32 nLenBytes)
{
    uint32 nPos = 0U;
    for (uint32 i = 0U; i < nWords; ++i)
    {
        if (nPos < nLenBytes)
        {
            pOut[nPos++] = (uint8)((pIn16[i] >> 8) & 0xFFU);
        } /* MSB */

        if (nPos < nLenBytes)
        {
            pOut[nPos++] = (uint8)( pIn16[i]       & 0xFFU);
        } /* LSB */
    }
	return;
}

static void dmaConfigCtrlTxPacket (uint32 nSrcAddr, uint32 nDestAddr, uint16 nElmntCnt, uint16 nFrameCnt)
{
    /* - configuring dma control packets   */
    g_stTxSpiDmaCtrlPkt.SADD      = nSrcAddr;
    g_stTxSpiDmaCtrlPkt.DADD      = nDestAddr;
    g_stTxSpiDmaCtrlPkt.CHCTRL    = 0;
    g_stTxSpiDmaCtrlPkt.FRCNT     = nFrameCnt;   //1000
    g_stTxSpiDmaCtrlPkt.ELCNT     = nElmntCnt;  //1
    g_stTxSpiDmaCtrlPkt.ELDOFFSET = 0;
    g_stTxSpiDmaCtrlPkt.ELSOFFSET = 0;
    g_stTxSpiDmaCtrlPkt.FRDOFFSET = 0;
    g_stTxSpiDmaCtrlPkt.FRSOFFSET = 0;
    g_stTxSpiDmaCtrlPkt.PORTASGN  = PORTA_READ_PORTB_WRITE;
    g_stTxSpiDmaCtrlPkt.RDSIZE    = ACCESS_16_BIT;
    g_stTxSpiDmaCtrlPkt.WRSIZE    = ACCESS_16_BIT;
    g_stTxSpiDmaCtrlPkt.TTYPE     = FRAME_TRANSFER;
    g_stTxSpiDmaCtrlPkt.ADDMODERD = ADDR_INC1;
    g_stTxSpiDmaCtrlPkt.ADDMODEWR = ADDR_FIXED;
    g_stTxSpiDmaCtrlPkt.AUTOINIT  = AUTOINIT_OFF;

    return;
}

static void dmaConfigCtrlRxPacket (uint32 nSrcAddr, uint32 nDestAddr, uint16 nElmntCnt, uint16 nFrameCnt)
{
    /* - configuring dma control packets   */
    g_stRxSpiDmaCtrlPkt.SADD      = nSrcAddr;
    g_stRxSpiDmaCtrlPkt.DADD      = nDestAddr;
    g_stRxSpiDmaCtrlPkt.CHCTRL    = 0;
    g_stRxSpiDmaCtrlPkt.FRCNT     = nFrameCnt;
    g_stRxSpiDmaCtrlPkt.ELCNT     = nElmntCnt;
    g_stRxSpiDmaCtrlPkt.ELDOFFSET = 0;
    g_stRxSpiDmaCtrlPkt.ELSOFFSET = 0;
    g_stRxSpiDmaCtrlPkt.FRDOFFSET = 0;
    g_stRxSpiDmaCtrlPkt.FRSOFFSET = 0;
    g_stRxSpiDmaCtrlPkt.PORTASGN  = PORTB_READ_PORTA_WRITE;
    g_stRxSpiDmaCtrlPkt.RDSIZE    = ACCESS_16_BIT;
    g_stRxSpiDmaCtrlPkt.WRSIZE    = ACCESS_16_BIT;
    g_stRxSpiDmaCtrlPkt.TTYPE     = FRAME_TRANSFER;
    g_stRxSpiDmaCtrlPkt.ADDMODERD = ADDR_FIXED;
    g_stRxSpiDmaCtrlPkt.ADDMODEWR = ADDR_INC1;
    g_stRxSpiDmaCtrlPkt.AUTOINIT  = AUTOINIT_OFF;

    return;
}

/* DMA: SPI1 TX (Source=DAT1[], Dest=&SPI1_TX->DAT1) */
static void SpiDmaTxConfig(uint16 *pSrcDat1, uint32 nWordLen, dmaChannel_t eDmaChannel)
{
	dmaChannel_t nCh = (eDmaChannel == DMA_CH_SPI1_TX) ? DMA_CH_SPI1_TX : DMA_CH_SPI3_TX;
    uint32 nDst = (eDmaChannel == DMA_CH_SPI1_TX) ? SPI1_DMA_TX_ADDR : SPI3_DMA_TX_ADDR;
    volatile spiBASE_t *pSpiTx = (eDmaChannel == DMA_CH_SPI1_TX) ? SPI1_TX : SPI3_TX;

    dmaREG->BTCFLAG = (uint32)(1U << nCh);
    dmaREG->HBCFLAG = (uint32)(1U << nCh);

    dmaConfigCtrlTxPacket((uint32)pSrcDat1, nDst, 1, (uint16)nWordLen);
    dmaSetCtrlPacket(nCh, g_stTxSpiDmaCtrlPkt);

    pSpiTx->INT0 |= (uint32)SPI_INT_TX_DMA_EN;

    dmaSetChEnable(nCh, DMA_HW);

    return;
}

/* DMA: SPI3 RX (Source=&SPI3_RX->BUF, Dest=g_aRxBuf[]) */
static void SpiDmaRxConfig(uint16 *pDestBuf, uint16 nWordLen)
{

    dmaREG->BTCFLAG = (uint32)(1U << DMA_CH_SPI3_RX);
    dmaREG->FTCFLAG = (uint32)(1U << DMA_CH_SPI3_RX);

    dmaConfigCtrlRxPacket(SPI3_DMA_RX_ADDR, (uint32)pDestBuf, 1, nWordLen);
    dmaSetCtrlPacket(DMA_CH_SPI3_RX, g_stRxSpiDmaCtrlPkt);  //Src: SPI->BUF, Dest: Variable

//    SPI3_RX->INT0 |=  ((uint32)SPI_INT_RX_DMA_EN);    /* DMAREQEN=1 */

    dmaSetChEnable(DMA_CH_SPI3_RX, DMA_HW);   /* HW trigger by SPI3 RX */
    return;
}

E_SPI_STATE_RESULT Spi3RxReady(uint32 nLen)
{
    if (nLen == 0U || nLen > SPI_MAX_BYTES)
    {
        return eSPI_STATE_ERR_PARAM;
    }
    g_nRxCnt = SPI_WORDS_FROM_BYTES(nLen);

    /* RX DMA: SPI3_RX->BUF -> g_aRxBuf[] */
    SpiDmaRxConfig(g_aRxBuf, g_nRxCnt);

    return eSPI_STATE_OK;
}

E_SPI_STATE_RESULT Spi3TxDummy(const uint8 *pData, uint32 nLen)
{
    uint32 nWords = 0U;

    if (pData == NULL || nLen == 0U || nLen > SPI_MAX_BYTES)
    {
        return eSPI_STATE_ERR_PARAM;
    }

    PackBytesToWords16(pData, nLen, g_aTxDat1, &nWords);

    SpiDmaTxConfig(g_aTxDat1, nWords, DMA_CH_SPI3_TX);

    return eSPI_STATE_OK;
}

E_SPI_STATE_RESULT Spi1TxSend(const uint8 *pData, uint32 nLen)
{
    uint32 nWords = 0U;

    if (pData == NULL || nLen == 0U || nLen > SPI_MAX_BYTES)
    {
        return eSPI_STATE_ERR_PARAM;
    }

    PackBytesToWords16(pData, nLen, g_aTxDat1, &nWords);

    SpiDmaTxConfig(g_aTxDat1, nWords, DMA_CH_SPI1_TX);

    return eSPI_STATE_OK;
}

E_SPI_STATE_RESULT Spi3RxFinalize(uint8 *pOut, uint32 nLen)
{
    if (pOut == NULL || nLen == 0U || nLen > SPI_MAX_BYTES)
    {
        return eSPI_STATE_ERR_PARAM;
    }
    if (g_nRxCnt != SPI_WORDS_FROM_BYTES(nLen))
    {
        return eSPI_STATE_ERR_PARAM;
    }

    UnpackWords16ToBytes((const uint16 *)g_aRxBuf, g_nRxCnt, pOut, nLen);

    return eSPI_STATE_OK;
}

void Spi3Init(void)
{
	uint16 *pSpiCfg = (uint16 *)((uint32)(&SPI3_TX->DAT1)+2);

	*pSpiCfg = ( (uint16)(g_stSpi3Fmt.DFSEL << 8U) | (uint16)(g_stSpi3Fmt.CSNR  << 0U) |
			(uint32)((g_stSpi3Fmt.WDEL) ? 0x0400U : 0 == 1 ? 0x0400U : 0U) |
			(uint32)((g_stSpi3Fmt.CS_HOLD) ? 0x1000U : 0 == 1 ? 0x0400U : 0U) );

	dmaReqAssign(DMA_CH_SPI3_TX, DMA_REQ_SPI3_TX);
	dmaReqAssign(DMA_CH_SPI3_RX, DMA_REQ_SPI3_RX);

	dmaEnableInterrupt(DMA_CH_SPI3_TX, BTC, DMA_INTA);
	dmaEnableInterrupt(DMA_CH_SPI3_TX, HBC, DMA_INTA);
	dmaEnableInterrupt(DMA_CH_SPI3_RX, BTC, DMA_INTA);
	dmaEnableInterrupt(DMA_CH_SPI3_RX, HBC, DMA_INTA);

	SPI3_TX->INT0 &= ~(uint32)SPI_INT_TX_DMA_EN;
	SPI3_RX->INT0 &= ~(uint32)SPI_INT_RX_DMA_EN; //명시적
    dmaREG->BTCFLAG = (1U << DMA_CH_SPI3_RX);
    dmaREG->HBCFLAG = (1U << DMA_CH_SPI3_RX);
//
    dmaREG->BTCFLAG = ((1U << DMA_CH_SPI3_TX) | (1U << DMA_CH_SPI3_RX));
    dmaREG->HBCFLAG = ((1U << DMA_CH_SPI3_TX) | (1U << DMA_CH_SPI3_RX));


    return;
}

void Spi1Init(void)
{
	uint16 *pSpiCfg = (uint16 *)((uint32)(&SPI1_TX->DAT1)+2);

	*pSpiCfg = ( (uint16)(g_stSpi1Fmt.DFSEL << 8U) | (uint16)(g_stSpi1Fmt.CSNR  << 0U) |
			(uint32)((g_stSpi1Fmt.WDEL) ? 0x0400U : 0 == 1 ? 0x0400U : 0U) |
			(uint32)((g_stSpi1Fmt.CS_HOLD) ? 0x1000U : 0 == 1 ? 0x0400U : 0U) );

    dmaReqAssign(DMA_CH_SPI1_TX, DMA_REQ_SPI1_TX);

	dmaEnableInterrupt(DMA_CH_SPI1_TX, BTC, DMA_INTA);
	dmaEnableInterrupt(DMA_CH_SPI1_TX, HBC, DMA_INTA);

	SPI1_TX->INT0 &= ~(uint32)SPI_INT_TX_DMA_EN;

    dmaREG->BTCFLAG = (1U << DMA_CH_SPI1_TX);
    dmaREG->HBCFLAG = (1U << DMA_CH_SPI1_TX);


	return;
}



uint8 bFlag = FALSE;
void SpiCommInit(void)
{
    dmaEnable();
    if(bFlag == TRUE)
    {
    	Spi1Init();
    }
    else
    {
    	Spi3Init();
    }
    return;
}

void SpiCommTest(void)
{
    spiInit();
    SpiCommInit();

    if(bFlag == TRUE)
    {
		 while(1)
		 {
			 for (uint32 i = 0; i < nLen; ++i)
			 {
				 g_aTxData[i] = (uint8)(i & 0xFFU);

			 }
			Spi1TxSend(g_aTxData, nLen);
			for (uint32 j = 0; j < 0x2000000; j++);
		}
    }
    else
    {
//    	while(1)
    	{
    		Spi3RxReady(nLen);
//			for (uint32 j = 0; j < 0x2000000; j++);
    	}

 		(void)Spi3TxDummy(g_aTxData, nLen);

 		Spi3RxFinalize(g_aRxData, nLen);
    }
    while(1);
    return;
}

#ifndef __SPICOMM_H__
#define __SPICOMM_H__

#include "HL_sys_common.h"
#include "HL_spi.h"
#include "HL_sys_dma.h"

#define SPI1_TX                         spiREG1        /* Master */
#define SPI3_TX                        	spiREG3        /* Slave  */
#define SPI3_RX							spiREG3

#define DMA_CH_SPI1_TX                  DMA_CH0
#define DMA_CH_SPI3_TX                  DMA_CH1
#define DMA_CH_SPI3_RX                  DMA_CH2

#define DMA_REQ_SPI1_TX                 DMA_REQ1
#define DMA_REQ_SPI3_TX                 DMA_REQ15
#define DMA_REQ_SPI3_RX                 DMA_REQ14

#define SPI1_DMA_TX_ADDR 	            ((uint32)(&(SPI1_TX->DAT1)) + 0)
#define SPI3_DMA_TX_ADDR 	            ((uint32)(&(SPI3_TX->DAT1)) + 0)
#define SPI3_DMA_RX_ADDR                 ((uint32)(&(SPI3_RX->BUF)) + 0)

#define SPI_GCR1_SPIEN                  (1U << 24)
#define SPI_DMA_REQ_EN					(1U << 16)
#define SPI_INT_RX_DMA_EN               SPI_DMA_REQ_EN
#define SPI_INT_TX_DMA_EN               SPI_DMA_REQ_EN

#define SPI_MAX_BYTES                   (1024U)
#define SPI_WORDS_FROM_BYTES(nBytes)    (((nBytes) + 1U) / 2U)  


typedef enum __eSPI_STATE_RESULT
{
    eSPI_STATE_OK = 0,
    eSPI_STATE_ERR_PARAM,
    eSPI_STATE_ERR_BUSY,
    eSPI_STATE_ERR_TIMEOUT,
    eSPI_STATE_ERR_DMA,
    eSPI_STATE_ERR_MISC
} E_SPI_STATE_RESULT;

#define SPI_DAT1_DFSEL_SHIFT        (24U)
#define SPI_DAT1_CSNR_SHIFT         (16U)
#define SPI_FMT_WAITENA_BIT         (21U)

E_SPI_STATE_RESULT Spi3RxReady(uint32 nLen);
E_SPI_STATE_RESULT Spi1TxSend(const uint8 *pData, uint32 nLen);
E_SPI_STATE_RESULT Spi3RxFinalize(uint8 *pOut, uint32 nLen);
void Spi3Init(void);
void Spi1Init(void);
void SpiCommInit(void);
void SpiCommTest(void);


#endif /* __SPICOMM_H__ */

Best Regards,