Part Number: TMS320F28379D
DSP作为从机,利用DMA传输的MISO延迟了四个字节,利用逻辑分析仪抓取的波形如下图

main.c的测试程序如下
//
// Included Files
//
#include "driverlib.h"
#include "device.h"
#include "board.h"
#include <string.h>
#define SPI_FRAME_LEN 20
// volatile uint16_t spi_rx_cnt = 0;
// #pragma DATA_SECTION(rData, "ramgs0");
// static uint16_t rData[SPI_FRAME_LEN];
// const void *rdataPtr = (void*)rData;
// #pragma DATA_SECTION(tData, "ramgs0");
// static uint16_t tData[SPI_FRAME_LEN];
// const void *tdataPtr = (void*)tData;
//===========================================
#pragma DATA_SECTION(rPing, "ramgs0");
#pragma DATA_SECTION(rPong, "ramgs0");
uint16_t rPing[SPI_FRAME_LEN];
uint16_t rPong[SPI_FRAME_LEN];
#pragma DATA_SECTION(tPing, "ramgs0");
#pragma DATA_SECTION(tPong, "ramgs0");
uint16_t tPing[SPI_FRAME_LEN];
uint16_t tPong[SPI_FRAME_LEN];
typedef struct {
uint16_t *rxBuf;
uint16_t *txBuf;
} SPI_Buffer;
SPI_Buffer bufPing = {rPing, tPing};
SPI_Buffer bufPong = {rPong, tPong};
SPI_Buffer *dmaBuf = &bufPing; // DMA正在用
SPI_Buffer *cpuBuf = &bufPong; // CPU正在处理
const void *rdataPtr;
const void *tdataPtr;
void SPI_initBuffers(void)
{
rdataPtr = dmaBuf->rxBuf;
tdataPtr = dmaBuf->txBuf;
}
// const void *rdataPtr = dmaBuf->rxBuf;
// const void *tdataPtr = dmaBuf->txBuf;
typedef enum {
SPI_IDLE = 0,
SPI_RX_DONE,
SPI_PROCESSING,
SPI_TX_READY
} SPI_State;
volatile SPI_State spiState = SPI_IDLE;
//===========================================
void process_frame(uint16_t *rx, uint16_t *tx)
{
int i;
for(i = 0; i < SPI_FRAME_LEN; i++)
{
tx[i] = rx[i]; // 示例:简单回传
}
}
// switch(spiState)
// {
// case SPI_RX_DONE:
// {
// spiState = SPI_PROCESSING;
// // 处理上一帧数据
// process_frame(cpuBuf->rxBuf, cpuBuf->txBuf);
// // DMA_startChannel(DMA_CH2_BASE);
// spiState = SPI_TX_READY;
// break;
// }
// case SPI_TX_READY:
// {
// // 等待下一帧自动发送
// spiState = SPI_IDLE;
// break;
// }
// default:
// break;
// }
//
// Main
//
void main(void)
{
//
// Initialize device clock and peripherals
//
Device_init();
//
// Disable pin locks and enable internal pullups.
//
Device_initGPIO();
//
// 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();
//
// Board initialization
//
memset((void*)tPing, 0xFF, sizeof(tPing));
memset((void*)tPong, 0x66, sizeof(tPong));
SPI_initBuffers();
Board_init();
SysCtl_selectSecController(SYSCTL_SEC_CONTROLLER_DMA, SYSCTL_SEC_CONTROLLER_DMA);
// SysCtl_selectSecMaster(0, SYSCTL_SEC_MASTER_DMA);
//
// Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
//
EINT;
ERTM;
//
// Loop forever. Suspend or place breakpoints to observe the buffers.
//
while(1)
{
DEVICE_DELAY_US(100);
}
}
volatile float32_t dma_rx_time = 0;
__attribute__((ramfunc))
__interrupt void INT_mySPI0_RX_DMA_ISR(void)
{
Interrupt_clearACKGroup(INT_mySPI0_RX_DMA_INTERRUPT_ACK_GROUP);
DMA_stopChannel(DMA_CH2_BASE);
// 交换缓冲区(Ping-Pong切换)
SPI_Buffer *tmp = dmaBuf;
dmaBuf = cpuBuf;
cpuBuf = tmp;
//更新DMA地址
rdataPtr = (void *)(dmaBuf->rxBuf);
tdataPtr = (void *)(dmaBuf->txBuf);
DMA_configAddresses(mySPI0_RX_DMA_BASE, rdataPtr, mySPI0_RX_DMA_ADDRESS);
DMA_configAddresses(mySPI0_TX_DMA_BASE, mySPI0_TX_DMA_ADDRESS, tdataPtr);
DMA_startChannel(DMA_CH2_BASE);
// 标记接收完成
spiState = SPI_RX_DONE;
}
__interrupt void INT_mySPI0_TX_DMA_ISR(void)
{
Interrupt_clearACKGroup(INT_mySPI0_TX_DMA_INTERRUPT_ACK_GROUP);
}
__interrupt void INT_mySPI0_RX_ISR(void)
{
//
// Clear interrupt flag and issue ACK
//
// uint16_t data = SPI_readDataNonBlocking(mySPI0_BASE);
// rData[spi_rx_cnt++] = data;
SPI_clearInterruptStatus(mySPI0_BASE, SPI_INT_RXFF);
Interrupt_clearACKGroup(INT_mySPI0_RX_INTERRUPT_ACK_GROUP);
}
__interrupt void INT_mySPI0_TX_ISR(void)
{
SPI_clearInterruptStatus(mySPI0_BASE, INT_mySPI0_TX);
Interrupt_clearACKGroup(INT_mySPI0_TX_INTERRUPT_ACK_GROUP);
}
DMA配置如下:
/*
* Copyright (c) 2020 Texas Instruments Incorporated - http://www.ti.com
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "board.h"
//*****************************************************************************
//
// Board Configurations
// Initializes the rest of the modules.
// Call this function in your application if you wish to do all module
// initialization.
// If you wish to not use some of the initializations, instead of the
// Board_init use the individual Module_inits
//
//*****************************************************************************
void Board_init()
{
EALLOW;
PinMux_init();
CPUTIMER_init();
DMA_init();
SPI_init();
INTERRUPT_init();
EDIS;
}
//*****************************************************************************
//
// PINMUX Configurations
//
//*****************************************************************************
void PinMux_init()
{
//
// PinMux for modules assigned to CPU1
//
//
// SPIB -> 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);
}
//*****************************************************************************
//
// CPUTIMER Configurations
//
//*****************************************************************************
void CPUTIMER_init(){
myCPUTIMER0_init();
}
void myCPUTIMER0_init(){
CPUTimer_setEmulationMode(myCPUTIMER0_BASE, CPUTIMER_EMULATIONMODE_STOPAFTERNEXTDECREMENT);
CPUTimer_setPreScaler(myCPUTIMER0_BASE, 0U);
CPUTimer_setPeriod(myCPUTIMER0_BASE, 4294967295U);
CPUTimer_disableInterrupt(myCPUTIMER0_BASE);
CPUTimer_stopTimer(myCPUTIMER0_BASE);
CPUTimer_reloadTimerCounter(myCPUTIMER0_BASE);
CPUTimer_startTimer(myCPUTIMER0_BASE);
}
//*****************************************************************************
//
// 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, rdataPtr, mySPI0_RX_DMA_ADDRESS);
DMA_configBurst(mySPI0_RX_DMA_BASE, 1U, 0, 1);
DMA_configTransfer(mySPI0_RX_DMA_BASE, 20U, 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_ENABLE | DMA_CFG_SIZE_16BIT);
DMA_setInterruptMode(mySPI0_RX_DMA_BASE, DMA_INT_AT_END);
DMA_enableInterrupt(mySPI0_RX_DMA_BASE);
DMA_disableOverrunInterrupt(mySPI0_RX_DMA_BASE);
DMA_enableTrigger(mySPI0_RX_DMA_BASE);
DMA_startChannel(mySPI0_RX_DMA_BASE);
}
void mySPI0_TX_DMA_init(){
DMA_setEmulationMode(DMA_EMULATION_STOP);
DMA_configAddresses(mySPI0_TX_DMA_BASE, mySPI0_TX_DMA_ADDRESS, tdataPtr);
DMA_configBurst(mySPI0_TX_DMA_BASE, 1U, 1, 0);
DMA_configTransfer(mySPI0_TX_DMA_BASE, 20U, 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_ENABLE | DMA_CFG_SIZE_16BIT);
DMA_setInterruptMode(mySPI0_TX_DMA_BASE, DMA_INT_AT_END);
DMA_enableInterrupt(mySPI0_TX_DMA_BASE);
DMA_disableOverrunInterrupt(mySPI0_TX_DMA_BASE);
DMA_enableTrigger(mySPI0_TX_DMA_BASE);
DMA_startChannel(mySPI0_TX_DMA_BASE);
}
//*****************************************************************************
//
// INTERRUPT Configurations
//
//*****************************************************************************
void INTERRUPT_init(){
// Interrupt Settings for INT_mySPI0_RX
// ISR need to be defined for the registered interrupts
Interrupt_register(INT_mySPI0_RX, &INT_mySPI0_RX_ISR);
Interrupt_enable(INT_mySPI0_RX);
// Interrupt Settings for INT_mySPI0_TX
// ISR need to be defined for the registered interrupts
Interrupt_register(INT_mySPI0_TX, &INT_mySPI0_TX_ISR);
Interrupt_enable(INT_mySPI0_TX);
// Interrupt Settings for INT_mySPI0_RX_DMA
// ISR need to be defined for the registered interrupts
Interrupt_register(INT_mySPI0_RX_DMA, &INT_mySPI0_RX_DMA_ISR);
Interrupt_enable(INT_mySPI0_RX_DMA);
// Interrupt Settings for INT_mySPI0_TX_DMA
// ISR need to be defined for the registered interrupts
Interrupt_register(INT_mySPI0_TX_DMA, &INT_mySPI0_TX_DMA_ISR);
Interrupt_enable(INT_mySPI0_TX_DMA);
}
//*****************************************************************************
//
// SPI Configurations
//
//*****************************************************************************
void SPI_init(){
mySPI0_init();
}
void mySPI0_init(){
SPI_disableModule(mySPI0_BASE);
SPI_setConfig(mySPI0_BASE, DEVICE_LSPCLK_FREQ, SPI_PROT_POL1PHA0,
SPI_MODE_PERIPHERAL, mySPI0_BITRATE, mySPI0_DATAWIDTH);
SPI_setPTESignalPolarity(mySPI0_BASE, SPI_PTE_ACTIVE_LOW);
SPI_enableFIFO(mySPI0_BASE);
SPI_setFIFOInterruptLevel(mySPI0_BASE, SPI_FIFO_TXEMPTY, SPI_FIFO_RX1);
SPI_clearInterruptStatus(mySPI0_BASE, SPI_INT_RXFF | SPI_INT_TXFF);
SPI_enableInterrupt(mySPI0_BASE, SPI_INT_RXFF | SPI_INT_TXFF);
SPI_disableLoopback(mySPI0_BASE);
SPI_setEmulationMode(mySPI0_BASE, SPI_EMULATION_STOP_AFTER_TRANSMIT);
SPI_enableModule(mySPI0_BASE);
}