Greetings,
Prior to posting I have searched the forums for a solution to my problem and tried everything but was unable to get the GSPI module working with DMA transfer enable on the TX channel only.
For my application I need to send data over SPI to an OLED/LCD display module.
I have authored similar drivers for both msp430 and cc2538 platform and it's working fine, so now I needed to port to the cc3200 platform.
However, I am unable to get anything on the SPI pins, there is no Clock output and no data outpot on MOSI pin.
This happens only when I use DMA, when I use simple SPI transfers the code works fine.
For the record I need to control the CS manually, that's why I don't set it as a peripheral pin, same goes for the MISO/RX pin.
This is my SPI/uDMA initialization code.
#define SPI_BIT_RATE 8000000
#define OLED_SYSCTL_PERIPH_SPI PRCM_GSPI
#define OLED_SPI_BASE GSPI_BASE
#define OLED_SPI_CLK_PIN PIN_05
#define OLED_SPI_TX_PIN PIN_07
#define OLED_CS_PORT_BASE GPIOA1_BASE
#define OLED_SPI_CS_PIN_NUM GPIO_PIN_4
#define OLED_SPI_CS_PIN PIN_03
#define OLED_RS_PORT_BASE GPIOA1_BASE
#define OLED_SPI_RS_PIN_NUM GPIO_PIN_5
#define OLED_SPI_RS_PIN PIN_04
#define OLED_RST_PORT_BASE GPIOA1_BASE
#define OLED_SPI_RST_PIN_NUM GPIO_PIN_7
#define OLED_SPI_RST_PIN PIN_06
#define OLED_SPI_UDMA_TX_CHANNEL UDMA_CH31_GSPI_TX
#define OLED_SPI_UDMA_STRUCT UDMA_PRI_SELECT
#define DMA_BLOCK 1024
void OLED_SPI_INIT()
{
MAP_PRCMPeripheralClkEnable(OLED_SYSCTL_PERIPH_SPI, PRCM_RUN_MODE_CLK);
MAP_PinTypeSPI(OLED_SPI_CLK_PIN, PIN_MODE_7);
MAP_PinTypeSPI(OLED_SPI_TX_PIN, PIN_MODE_7);
MAP_PinTypeGPIO(OLED_SPI_CS_PIN, PIN_MODE_0, false);
MAP_GPIODirModeSet(OLED_CS_PORT_BASE, OLED_SPI_CS_PIN_NUM, GPIO_DIR_MODE_OUT);
MAP_GPIOPinWrite(OLED_CS_PORT_BASE, OLED_SPI_CS_PIN_NUM, OLED_SPI_CS_PIN_NUM);
MAP_PinTypeGPIO(OLED_SPI_RS_PIN, PIN_MODE_0, false);
MAP_GPIODirModeSet(OLED_RS_PORT_BASE, OLED_SPI_RS_PIN_NUM, GPIO_DIR_MODE_OUT);
MAP_GPIOPinWrite(OLED_RS_PORT_BASE, OLED_SPI_RS_PIN_NUM, OLED_SPI_RS_PIN_NUM);
MAP_PinTypeGPIO(OLED_SPI_RST_PIN, PIN_MODE_0, false);
MAP_GPIODirModeSet(OLED_RST_PORT_BASE, OLED_SPI_RST_PIN_NUM, GPIO_DIR_MODE_OUT);
MAP_GPIOPinWrite(OLED_RST_PORT_BASE, OLED_SPI_RST_PIN_NUM, OLED_SPI_RST_PIN_NUM);
MAP_UtilsDelay(PRCMPeripheralClockGet(PRCM_GPIOA0)/3000);
MAP_PRCMPeripheralReset(OLED_SYSCTL_PERIPH_SPI);
MAP_SPIReset(OLED_SPI_BASE);
UDMAInit();
MAP_SPIConfigSetExpClk(OLED_SPI_BASE,MAP_PRCMPeripheralClockGet(OLED_SYSCTL_PERIPH_SPI),
SPI_BIT_RATE,SPI_MODE_MASTER,SPI_SUB_MODE_0,(SPI_3PIN_MODE | SPI_TURBO_OFF | SPI_WL_8));
MAP_SPIEnable(OLED_SPI_BASE);
}
When transferring a single byte I use the function below. The StartAndCompleteTransfer is take from the uDMA example of the cc3200 SDK as is.
void OLED_SPI_WRITE(unsigned char out)
{
MAP_SPIDmaDisable(OLED_SPI_BASE, SPI_TX_DMA);
MAP_uDMAChannelDisable((OLED_SPI_UDMA_TX_CHANNEL|OLED_SPI_UDMA_STRUCT));
SetupTransfer((OLED_SPI_UDMA_TX_CHANNEL|OLED_SPI_UDMA_STRUCT), UDMA_MODE_BASIC, 1, UDMA_SIZE_8, UDMA_ARB_1,&out, UDMA_SRC_INC_8, (void *)(GSPI_BASE + MCSPI_O_RX0), UDMA_DST_INC_NONE);
MAP_SPIWordCountSet(OLED_SPI_BASE, 1);
MAP_SPIDmaEnable(OLED_SPI_BASE, SPI_TX_DMA);
StartAndCompleteSWTransfer((OLED_SPI_UDMA_TX_CHANNEL|OLED_SPI_UDMA_STRUCT));
MAP_uDMAChannelDisable((OLED_SPI_UDMA_TX_CHANNEL|OLED_SPI_UDMA_STRUCT));
}
This is the function I use when I want to transfer large data blocks (over DMA_BLOCK size which is 1024 bytes)
void OLED_SPI_WRITE_MORE_CHUNK(unsigned char* data, unsigned long len)
{
unsigned long sbytes = 0;
unsigned long ind = 0;
if(len > DMA_BLOCK)
sbytes = DMA_BLOCK;
else
sbytes = len;
while (len > 0)
{
memcpy(&oled_tx_buffer[0],&data[ind],sbytes);
MAP_SPIDmaDisable(OLED_SPI_BASE, SPI_TX_DMA);
MAP_uDMAChannelDisable((OLED_SPI_UDMA_TX_CHANNEL|OLED_SPI_UDMA_STRUCT));
SetupTransfer((OLED_SPI_UDMA_TX_CHANNEL|OLED_SPI_UDMA_STRUCT), UDMA_MODE_BASIC, sbytes,
UDMA_SIZE_8, UDMA_ARB_1,(void *)&oled_tx_buffer[0], UDMA_SRC_INC_8,
(void *)(GSPI_BASE + MCSPI_O_RX0), UDMA_DST_INC_NONE);
MAP_SPIWordCountSet(OLED_SPI_BASE, sbytes);
MAP_SPIDmaEnable(OLED_SPI_BASE, SPI_TX_DMA);
StartAndCompleteSWTransfer((OLED_SPI_UDMA_TX_CHANNEL|OLED_SPI_UDMA_STRUCT));
len-=sbytes;
ind+=sbytes;
if(len >= DMA_BLOCK)
sbytes = DMA_BLOCK;
else
sbytes = len;
}
}
What am I doing wrong and get no outpun on CLK and TX pin ?
Thank you in advance for any assistance.
Regards,
Pavlos