This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28377D: SPI_DMA方式与外部芯片通信

Part Number: TMS320F28377D

尊敬的TI工程师

您好,我在使用28377d的SPI的DMA模式时发现问题,请求您的帮助解答。

首先我在syscfg中将SPI与DMA配置如下图。

在board.c中生成的初始化部分对应代码如下:

void Board_init()
{
	EALLOW;

	PinMux_init();
	DMA_init();
	SPI_init();

	EDIS;
}

//*****************************************************************************
//
// PINMUX Configurations
//
//*****************************************************************************
void PinMux_init()
{
	//
	// PinMux for modules assigned to CPU1
	//
	
	//
	// SPIA -> mySPI0 Pinmux
	//
	GPIO_setPinConfig(mySPI0_SPIPICO_PIN_CONFIG);
	GPIO_setPadConfig(mySPI0_SPIPICO_GPIO, GPIO_PIN_TYPE_STD);
	GPIO_setQualificationMode(mySPI0_SPIPICO_GPIO, GPIO_QUAL_ASYNC);

	GPIO_setPinConfig(mySPI0_SPIPOCI_PIN_CONFIG);
	GPIO_setPadConfig(mySPI0_SPIPOCI_GPIO, GPIO_PIN_TYPE_STD);
	GPIO_setQualificationMode(mySPI0_SPIPOCI_GPIO, GPIO_QUAL_ASYNC);

	GPIO_setPinConfig(mySPI0_SPICLK_PIN_CONFIG);
	GPIO_setPadConfig(mySPI0_SPICLK_GPIO, GPIO_PIN_TYPE_STD);
	GPIO_setQualificationMode(mySPI0_SPICLK_GPIO, GPIO_QUAL_ASYNC);

	GPIO_setPinConfig(mySPI0_SPIPTE_PIN_CONFIG);
	GPIO_setPadConfig(mySPI0_SPIPTE_GPIO, GPIO_PIN_TYPE_STD);
	GPIO_setQualificationMode(mySPI0_SPIPTE_GPIO, GPIO_QUAL_ASYNC);


}

//*****************************************************************************
//
// DMA Configurations
//
//*****************************************************************************
void DMA_init(){
    DMA_initController();
	mySPI0_RX_DMA_init();
	mySPI0_TX_DMA_init();
}

void mySPI0_RX_DMA_init(){
    DMA_setEmulationMode(DMA_EMULATION_STOP);
    DMA_configAddresses(mySPI0_RX_DMA_BASE, DualMCUCommSPI_destAddress, mySPI0_RX_DMA_ADDRESS);
    DMA_configBurst(mySPI0_RX_DMA_BASE, 1U, 0, 1);
    DMA_configTransfer(mySPI0_RX_DMA_BASE, 2U, 0, 1);
    DMA_configWrap(mySPI0_RX_DMA_BASE, 65535U, 0, 65535U, 0);
    DMA_configMode(mySPI0_RX_DMA_BASE, mySPI0_RX_DMA_TRIGGER, DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_DISABLE | DMA_CFG_SIZE_16BIT);
    DMA_enableTrigger(mySPI0_RX_DMA_BASE);
    DMA_stopChannel(mySPI0_RX_DMA_BASE);
}
void mySPI0_TX_DMA_init(){
    DMA_setEmulationMode(DMA_EMULATION_STOP);
    DMA_configAddresses(mySPI0_TX_DMA_BASE, mySPI0_TX_DMA_ADDRESS, DualMCUCommSPI_srcAddress);
    DMA_configBurst(mySPI0_TX_DMA_BASE, 1U, 1, 0);
    DMA_configTransfer(mySPI0_TX_DMA_BASE, 2U, 1, 0);
    DMA_configWrap(mySPI0_TX_DMA_BASE, 65535U, 0, 65535U, 0);
    DMA_configMode(mySPI0_TX_DMA_BASE, mySPI0_TX_DMA_TRIGGER, DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_DISABLE | DMA_CFG_SIZE_16BIT);
    DMA_enableTrigger(mySPI0_TX_DMA_BASE);
    DMA_stopChannel(mySPI0_TX_DMA_BASE);
}

//*****************************************************************************
//
// SPI Configurations
//
//*****************************************************************************
void SPI_init(){
	mySPI0_init();
}

void mySPI0_init(){
	SPI_disableModule(mySPI0_BASE);
	SPI_setConfig(mySPI0_BASE, DEVICE_LSPCLK_FREQ, SPI_PROT_POL0PHA1,
				  SPI_MODE_CONTROLLER, mySPI0_BITRATE, mySPI0_DATAWIDTH);
	SPI_setPTESignalPolarity(mySPI0_BASE, SPI_PTE_ACTIVE_LOW);
	SPI_enableFIFO(mySPI0_BASE);
	SPI_disableLoopback(mySPI0_BASE);
	SPI_setEmulationMode(mySPI0_BASE, SPI_EMULATION_STOP_AFTER_TRANSMIT);
	SPI_enableModule(mySPI0_BASE);
}

我在使用该SPI模块时发现,当我使用NonFIFO的primitive模式或pollingFIFO模式时,都能正确传输,但是当我用DMA模式时,传输故障,具体表现为:传输主机端完成发送接收动作后跳出该轮任务并判定传输失败,但从机却一直处在准备态,等待主机发起传输。

我把主机端的SPI应用函数放在下面这里:

typedef union SPI_ExchangeData
{
		uint16_t data16[2];  // 16-bit representation
		uint32_t data32;     // 32-bit representation
} SPI_ExchangeData;
SPI_ExchangeData gdataSendSPI[DualMCUCommSPI_BUFFER_SIZE_32BIT];
SPI_ExchangeData gdataReceiveSPI[DualMCUCommSPI_BUFFER_SIZE_32BIT];
const void *DualMCUCommSPI_destAddress = (const void*) gdataReceiveSPI;
const void *DualMCUCommSPI_srcAddress = (const void*) gdataSendSPI;

typedef enum
{
	PRIMITIVE,
	POLLING,
	DMA,
} TRANSFER_METHOD;
void DualMCUCommSPI_transfer(TRANSFER_METHOD transferMethod)
{
	switch(transferMethod)
	{
		case PRIMITIVE:
		{
			DualMCUCommSPI_transferPrimitive();
			break;
		}

		case POLLING:
		{
			DualMCUCommSPI_transferPolling();
			break;
		}

		case DMA:
		{
			DualMCUCommSPI_transferDMA();
			break;
		}
	}
}
void DualMCUCommSPI_transferDMA(void)
{
		DMA_startChannel(DualMCUCommSPI_TX_DMA_BASE);
		DMA_startChannel(DualMCUCommSPI_RX_DMA_BASE);
}
void DualMCUCommSPI_transferPolling(void)
{
		SPI_pollingFIFOTransaction(DualMCUCommSPI_BASE, 16,
		                           (uint16_t *)&gdataSendSPI, (uint16_t *)&gdataReceiveSPI,
		                           2, 0);
}

void DualMCUCommSPI_transferPrimitive(void)
{
    SPI_writeDataNonBlocking(DualMCUCommSPI_BASE, gdataSendSPI[0].data16[0]);

    gdataReceiveSPI[0].data16[0] = SPI_readDataBlockingNonFIFO(DualMCUCommSPI_BASE);

    SPI_writeDataNonBlocking(DualMCUCommSPI_BASE, gdataSendSPI[0].data16[1]);

    gdataReceiveSPI[0].data16[1] = SPI_readDataBlockingNonFIFO(DualMCUCommSPI_BASE);
}

SPI_DMA的方式我在F28388D上面曾验证测试通过,现在同样的调用方法在F28377D上却行不通,您帮我看看故障原因是DMA配置有误还是调用方式有误,除了开启TX和RX的DMA通道 还需要别的动作吗。