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,