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.

TM4C129ENCPDT: not able to receive Data, data sent using SSI uDMA Basic mode in EK-TM4C129EXL board

Part Number: TM4C129ENCPDT

Hi TI community, 

I'm beginner with the interest in transfer array of 1024 bits of data continuously from tm4c129EXL board to 1.3" OLED display using DMA BASIC mode. Before that i tried below code.

Which transfer data from buffer g_ui8TxBuf to the (void *)(SSI1_BASE)  using UDMA_CHANNEL_SSI1TX channel. The data is not transferred.

  • Do i need to trigger using uDMAChannelRequest(UDMA_TRANSFER_CHANNEL); to transfer or uDMAChannelEnable(UDMA_TRANSFER_CHANNEL); is enough
  • i'm not sure that to receive data at destination i used SSIDataGetNonBlocking is this proper way to receive data from SSI1 base.

Please find the code below :

#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "inc/hw_memmap.h"
#include "driverlib/sysctl.h"
#include "driverlib/udma.h"
#include "driverlib/pin_map.h"
#include "driverlib/gpio.h"
#include "driverlib/ssi.h"

#define CLK_FREQ				80000000
#define CLK_RATE				1000000
#define DATA_WIDTH				8

#define SSI_RXBUF_SIZE          256
#define UDMA_TRANSFER_CHANNEL   UDMA_CHANNEL_SSI1TX
#define SSIDATA_FRAME_SIZE      UDMA_SIZE_8
#define TIMES_DMA_TRANSFER      UDMA_ARB_8  
#define UDMA_TRANSFER_MODE      UDMA_MODE_BASIC
#define SSI_TXBUF_SIZE          256

unsigned char g_ui8TxBuf[SSI_TXBUF_SIZE];
unsigned char pui8ControlTable[1024];
static unsigned char u32Rxdata[SSI_TXBUF_SIZE];

void init_uDMA();
void config_DMA_transfer();

void spi1_init()
{
	unsigned int ui32SysClock;
	ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |SYSCTL_OSC_MAIN |SYSCTL_USE_OSC), CLK_FREQ);

	SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI1);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP);

	GPIOPinTypeGPIOOutput(GPIO_PORTP_BASE, GPIO_PIN_0);
	GPIOPinTypeGPIOOutput(GPIO_PORTP_BASE, GPIO_PIN_1);

	GPIOPinConfigure(GPIO_PB4_SSI1FSS);
	GPIOPinConfigure(GPIO_PB5_SSI1CLK);
	GPIOPinConfigure(GPIO_PE4_SSI1XDAT0);

	GPIOPinTypeSSI(GPIO_PORTB_BASE, GPIO_PIN_5 | GPIO_PIN_4);
	GPIOPinTypeSSI(GPIO_PORTE_BASE, GPIO_PIN_4);

	SSIConfigSetExpClk(SSI1_BASE, ui32SysClock, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, CLK_RATE, DATA_WIDTH);

	SSIEnable(SSI1_BASE);
	printf("SPI Iniitiated sh1106 driver\n");
}

int main()
{
    spi1_init();

    //initialize uDMA module with transfer size of 16 bits
    init_uDMA();
    config_DMA_transfer();

    uint_fast32_t i;

    for(i = 0; i < SSI_TXBUF_SIZE; i++)
    {
        // Wait for data to be available in the receive buffer
        while(SSIDataGetNonBlocking(SSI1_BASE, &u32Rxdata[i])) {}
    }

    //print on console 
    for(i = 0; i< SSI_TXBUF_SIZE; i++)
    {

        printf("u32Rxdata[%d] = %d\n", i, u32Rxdata[i]);
    }
    uDMADisable();
}
//*****************************************************************************
// initiate uDMA module and configure SSI for uDMA transfer
//*****************************************************************************
void init_uDMA()
{
    printf("uDMA module initiating\n");
    //called once to configure or initiate uDMA


    //
    // Enable the UDMA peripheral
    //
    printf("---- Enabling UDMA Peripheral----\n");
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);

    //
    // Wait for the UDMA module to be ready.
    //
    printf("---- Waiting for UDMA Peripheral to ready----\n");
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_UDMA))
    {
    }
    uDMAControlBaseSet(&pui8ControlTable[0]);

    printf("uDMA channel control base set done\n");
    //
    // Put the attributes in a known state for the uDMA SSI1TX channel.  These
    // should already be disabled by default.
    //
    uDMAChannelAttributeDisable(UDMA_TRANSFER_CHANNEL,UDMA_ATTR_ALTSELECT |
                                    UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);

    //
    // Set the USEBURST attribute for the uDMA SSI TX channel.  This will
    // force the controller to always use a burst when transferring data from
    // the TX buffer to the UART.  This is somewhat more efficient bus usage
    // than the default which allows single or burst transfers.
    //
    uDMAChannelAttributeEnable(UDMA_TRANSFER_CHANNEL, UDMA_ATTR_USEBURST);
    printf("uDMA channel attributes set done\n");

   
    uDMAChannelControlSet(UDMA_TRANSFER_CHANNEL | UDMA_PRI_SELECT,
                          SSIDATA_FRAME_SIZE | UDMA_SRC_INC_8 |
                          UDMA_DST_INC_NONE | TIMES_DMA_TRANSFER);
    printf("uDMA channel control set is done\n");
    //enabling the uDMA module
    uDMAEnable();

    //
    // Enable the uDMA interface for TX channel.
    //
    //
    SSIDMAEnable(SSI1_BASE, SSI_DMA_TX); // transfer the control to uDMA controller
}

void config_DMA_transfer()
{
    printf("SSI1 Transfering\n");
       static uint_fast16_t ui16Idx;

       //
       // Fill the TX buffer with a simple data 0 to 255.
       //
       for(ui16Idx = 0; ui16Idx < SSI_TXBUF_SIZE; ui16Idx++)
       {
           g_ui8TxBuf[ui16Idx] = ui16Idx;
           printf("g_ui8TxBuf %d\n", g_ui8TxBuf[ui16Idx]);
       }

       printf("DMA Transfer enabled\n");
    //
    // Set up the transfer parameters for the uDMA SSI TX channel.  This will
    // configure the transfer source and destination and the transfer size.
    // Basic mode is used because the peripheral is making the uDMA transfer
    // request.  The source is the TX buffer and the destination is the SSI
    // data register.
    //

// Not transfering data from tx to SSI Base
   uDMAChannelTransferSet(UDMA_TRANSFER_CHANNEL | UDMA_PRI_SELECT,
                          UDMA_TRANSFER_MODE, g_ui8TxBuf,
                          (void *)(SSI1_BASE),
                          sizeof(g_ui8TxBuf));

   uDMAChannelEnable(UDMA_TRANSFER_CHANNEL);
   printf("uDMA transfer channel enabled\n");
   printf("--- Waiting to complete data transfer ---\n");
   //wait for DMA transfer to complete
   while(uDMAChannelIsEnabled(UDMA_TRANSFER_CHANNEL)) {}
  printf("\n--- Transfer completed ---\n");
}

Thank you in Advance

  • Hello Ajaykumar,

    I apologize but I was not able to analyze your code today to review for issues. I will aim to do so tomorrow and provide feedback. Generally only uDMAChannelEnable is needed as the peripheral would issue the transfer requests. uDMAChannelRequest is generally used for SW transfers as no peripheral would trigger the transfer requests.

    I'll try and spot the issue with your code once I get to review it. uDMA can be tricky to enable so might just be a small tweak needed.

    Best Regards,

    Ralph Jacobi

  • Hello Ajaykumar,

    At the start of my code review, the first observation I had is that your clock configuration hits our SYSCTL#23 errata, so the program may not be working as a result of this.

    Please change your clock configuration to the following: 

    SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN |
                        SYSCTL_USE_PLL | SYSCTL_CFG_VCO_240), 120000000);

    You can read the errata details here: https://www.ti.com/lit/pdf/spmz850

    Now following that, you do a number of uDMA configurations but you don't enable to module before that. You need to start by enabling the module. So place the uDMAEnable(); API call after your while(!SysCtlPeripheralReady(SYSCTL_PERIPH_UDMA)) check and before the uDMAControlBaseSet call.

    I don't see anything else standing out initially to me to adjust, but those two are significant changes so please make those updates and see if you are able to get transfers operational with them.

    Best Regards,

    Ralph Jacobi

  • Hello Ralph Jacobi,

    first of all i would like Thank for replay,

    I did as per your instructions as follows :  

    changed clock configurations to SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN |
    SYSCTL_USE_PLL | SYSCTL_CFG_VCO_240), 120000000);

    after that 

    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_UDMA)) 

    uDMAEnable();

    uDMAControlBaseSet(&pui8ControlTable[0]);

    and rest of the uDMA configurations like ChannelAttributeEnable, ChannelControlSet, SSIDMAEnable

    I'm able to put data into SSI port when verifing that written data at u32Rxdata after SSIDataGetNonBlocking(SSI1_BASE, &u32Rxdata[i]) i'm getting 

    u32Rxdata[0] = 0 upto u32Rxdata[255] = 0 in console expecting result as u32Rxdata[0] = 0 upto u32Rxdata[255] = 255.

    Best Regards;

    Ajaykumar V

  • Hello Ajaykumar,

    Digging further into your use case here, I think I need to get more clarity on exactly what you are looking to achieve with your current testing with the DMA:

    I'm beginner with the interest in transfer array of 1024 bits of data continuously from tm4c129EXL board to 1.3" OLED display using DMA BASIC mode.
    i'm not sure that to receive data at destination i used SSIDataGetNonBlocking is this proper way to receive data from SSI1 base.

    Unless you are using internal loopback mode, using SSIDataGetNonBlocking wouldn't work for your purposes.

    By setting up the DMA for SSI TX, you wouldn't be receiving any data in the SSI RX buffer. The SSI peripheral when configured to use DMA data would stream out the data from your buffer onto the SSI pins, not to an SSI RX buffer.

    From what it sounded like originally, you are trying to send the data over those pins to a display - so if that is your primary test case then you should focus on reading the SPI pins with a logic analyzer (or oscilloscope if necessary) to observe any data outputs and you wouldn't use any SSIDataGet APIs.

    If you want to test looping back the data to simply see how the DMA performs, then you'd need to use SSILoopbackEnable at which point you would be able to loop the data internally. That would be a different initial use case from what you originally described however.

    Best Regards,

    Ralph Jacobi

  • Hello Ralph Jacobi,

    The main use case is to display data on OLED display using SSI DMA basic mode of transfer. 

    I wanted to let you know that I'll be out of office for two days (IST).

    I'll do my best to respond to your suggestions as soon as possible when I return.

    Thank you for your patience and understanding.

    Best regards.

    Ajaykumar V

  • Hello Ajakumar,

    No worries about being out of office, we can resume this when you are back - the thread won't lock for 30 days, plenty of time.

    Once you return I think the most important test will be to monitor the actual SSI pins and see if data is being output on them.

    To make it as simple as possible initially, you may want to verify you get output data with SSIDataPutNonBlocking without the DMA. Then test with the DMA configured and triggering with a DMA transfer.

    Best Regards,

    Ralph Jacobi

  • Hello RAlph Jacobi,

    To make it as simple as possible initially, you may want to verify you get output data with SSIDataPutNonBlocking without the DMA. Then test with the DMA configured and triggering with a DMA transfer.

    I can able to transfer data using SSIDataPut() without DMA, When tried with DMA configuration and triggering I'm not able to transfer data.

    Best Regards,

    Ajaykumar V

  • Hello Ajaykumar,

    I am going to try and run the code you've provided on my own hardware to test and debug, but I haven't had a chance to do so today - so I will try and do so on Monday and report back then.

    Best Regards,

    Ralph Jacobi

  • Hello Ajaykumar,

    I've built your example but I am uncertain how it is intended to be working.

    Namely I see in your main the following:

        for(i = 0; i < SSI_TXBUF_SIZE; i++)
        {
            // Wait for data to be available in the receive buffer
            while(SSIDataGetNonBlocking(SSI1_BASE, &u32Rxdata[i])) {}
        }
    
        //print on console
        for(i = 0; i< SSI_TXBUF_SIZE; i++)
        {
    
            printf("u32Rxdata[%d] = %d\n", i, u32Rxdata[i]);
        }

    But I do not see the SSI module being configured for RX at all and the pin to receive data isn't configured.

    SSIDataGetNonBlocking is looking for data in the RX FIFO which there wouldn't be any given your configuration.

    Can you better explain what your example project is supposed to do if it works the way you are intending?

    Best Regards,

    Ralph Jacobi

  • Hello Ralph Jacobi,

    I apologize, for missing part in above code , above code is to verify the data being sent through SSI DMA Channel not the full idea of the project.

    What i'm working on is: only send the data from TM4C129ENCPDT using SSI DMA (with basic mode of transfer) and is only received at 1.3" Adafruit OLED display continuously.

    I followed following procedure to display the data on OLED:

    1. Initiated OLED Display, which contains SSI module configurations and Display turn off, Clock settings,update, turn on commands.
    2.  uDMA_Configuration(); which has
      1. uDMA Peripheral Enable.
      2. uDMA is ready then enable the uDMA module
      3. uDMAControlBaseSet();
      4. Channel attribute first disabled then enabled for UDMA_CHANNEL_SSI1TX,USER BURST mode
      5. set up the characteristics of the with transfer for 8-bit data size, with source increments in bytes, and a byte-wise buffer copy. A bus arbitration size of 128 is used. i.e., 

        uDMAChannelControlSet (UDMA_CHANNEL_SSI1TX | UDMA_PRI_SELECT,UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_128);

      6.  SSIDMAEnable(SSI1_BASE, SSI, DMA_TX); //transfer the control to uDMA controller
    3. DMA_transfer(); The transfer buffers and transfer size are now configured. The transfer uses BASIC mode.
      1. uDMAChannelTransferSet(UDMA_CHANNEL_SSI1TX | UDMA_PRI_SELECT,UDMA_MODE_BASIC, dummy_data ,(void *)(SSI1_BASE),1024);
      2. uDMAChannelEnable(UDMA_CHANNEL_SSI1TX); Start transferring data.

      3. //wait for DMA transfer to complete
        while(uDMAChannelIsEnabled(UDMA_CHANNEL_SSI1TX)) {}
    4. DMA_Rx(); Receive data from SSI1_BASE to Receive buffer of OLED
    5. display(); send data in Receive buffer to Display.

    please find the below code which follows above procedure:

    // uDMA_OLED_transfer.c
    // this transfer data from data buffer of uC to OLED display
    
    #include <stdint.h>
    #include <stdbool.h>
    #include <stdio.h>
    #include <string.h>
    #include "inc/hw_memmap.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/udma.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/gpio.h"
    #include "driverlib/ssi.h"
    
    #define UDMA_TRANSFER_CHANNEL   UDMA_CHANNEL_SSI1TX
    #define UDMA_RX_CHANNEL   		UDMA_CHANNEL_SSI1RX
    #define SSIDATA_FRAME_SIZE      UDMA_SIZE_8
    #define TIMES_DMA_TRANSFER      UDMA_ARB_128
    #define UDMA_TRANSFER_MODE      UDMA_MODE_BASIC
    #define SSI_TXBUF_SIZE          1024
    
    unsigned char pui8ControlTable[1024];
    unsigned char g_ui8TxBuf[SSI_TXBUF_SIZE];
    
    OLED_Init()
    {
        SSI_Init();
        ....
    }
    void init_uDMA()
    {
        //called once to configure or initiate uDMA
        printf("uDMA module initiating\n");
        //
        // Enable the UDMA peripheral
        //
        printf("---- Enabling UDMA Peripheral----\n");
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
    
        //
        // Wait for the UDMA module to be ready.
        //
        printf("---- Waiting for UDMA Peripheral to ready----\n");
        while(!SysCtlPeripheralReady(SYSCTL_PERIPH_UDMA)){}
    	
        //enabling the uDMA module
        uDMAEnable();
    
        uDMAControlBaseSet(&pui8ControlTable[0]);
    
        printf("uDMA channel control base set done\n");
        //
        // Put the attributes in a known state for the uDMA SSI1TX channel.  These
        // should already be disabled by default.
        //
        uDMAChannelAttributeDisable(UDMA_TRANSFER_CHANNEL | ,UDMA_ATTR_ALTSELECT |
                                    UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);
    
        uDMAChannelAttributeEnable(UDMA_TRANSFER_CHANNEL | , UDMA_ATTR_USEBURST);
        printf("uDMA channel attributes set done\n");
    
    
        uDMAChannelControlSet(UDMA_TRANSFER_CHANNEL | UDMA_PRI_SELECT,
                              SSIDATA_FRAME_SIZE | UDMA_SRC_INC_8 |
                              UDMA_DST_INC_NONE | TIMES_DMA_TRANSFER);
        printf("uDMA channel control set is done\n");
    
    
        //
        // Enable the uDMA interface for TX channel.
        //
        //
        SSIDMAEnable(SSI1_BASE, SSI_DMA_TX); // transfer the control to uDMA controller
    }
    
    void config_DMA_transfer()
    {
       printf("SSI1 Transfering\n");
       static uint_fast16_t ui16Idx;
    
           //
           // Fill the TX buffer with a simple data 0 to 255.
           //
       for(ui16Idx = 0; ui16Idx < SSI_TXBUF_SIZE; ui16Idx++)
           {
               g_ui8TxBuf[ui16Idx] = ui16Idx;
               printf("g_ui8TxBuf %d\n", g_ui8TxBuf[ui16Idx]);
           }
    
       printf("DMA Transfer enabled\n");
        
    
       uDMAChannelTransferSet(UDMA_TRANSFER_CHANNEL | UDMA_PRI_SELECT,
                              UDMA_TRANSFER_MODE, g_ui8TxBuf ,
                              (void *)(SSI1_BASE),
                              sizeof(g_ui8TxBuf));
    
       uDMAChannelEnable(UDMA_TRANSFER_CHANNEL);
       
       printf("uDMA transfer channel enabled\n");
       //printf("--- Waiting to complete data transfer ---\n");
       //wait for DMA transfer to complete
       while(uDMAChannelIsEnabled(UDMA_TRANSFER_CHANNEL)){}
    }
    
    void Write_display(unsigned char *buff)
    {
    
    		SSIDataPut(SSI1_BASE,0x00 | 0x0);
    		SSIDataPut(SSI1_BASE,0x10 | 0x0);
    		SSIDataPut(SSI1_BASE,0x40 | 0x0);
    		int height = 64;
    		int width = 132; // same even for 128 width.
    		int m_row = 0;
    		int m_col = 2;
    		int p = 0;
    		int i, j, k = 0;
    		height >>= 3;
    		width >>= 3;
    		//printf("Page : %i\n", i);
    		for ( i = 0; i < height; i++)
    		{
    			// send a bunch of data in one xmission
    			SSIDataPut(SSI1_BASE, 0xB0 + i + m_row);    //set page address
    			SSIDataPut(SSI1_BASE, m_col & 0xf);         //set lower column address
    			SSIDataPut(SSI1_BASE, 0x10 | (m_col >> 4));  //set higher column address
    
    			DelayMs(1);
    
    	        for( j = 0; j < 8; j++)
    	        {
    	        	ulDelayMs(1);
    				SH1106_Disp_ACCESS();
    
    	            for (k = 0; k < width; k++)
    	            {
    	            		Delay_ms(1); //1 milli Second Delay
    	            		SSIDataPut(SSI1_BASE, buff[p]);
    	            		//printf("value :%02x\n", buff[p]);
    	            		p++;
    	            }
    	        }
    	 	}
    }
    
    unsigned char* DMA_RX()
    {
    uint_fast32_t i;
    unsigned char Rx[SSI_TXBUF_SIZE];
    
    uDMAChannelAttributeDisable(UDMA_RX_CHANNEL,UDMA_ATTR_ALTSELECT |
                                UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);
    
       
    uDMAChannelAttributeEnable(UDMA_RX_CHANNEL, UDMA_ATTR_USEBURST);
    printf("uDMA channel attributes set done\n");
    
    
    uDMAChannelControlSet(UDMA_RX_CHANNEL | UDMA_PRI_SELECT,
                              SSIDATA_FRAME_SIZE | UDMA_SRC_INC_8 |
                              UDMA_DST_INC_NONE | TIMES_DMA_TRANSFER);
    printf("uDMA channel control set is done\n");
    
       
    SSIDMAEnable(SSI1_BASE, SSI_DMA_RX); // transfer the control to uDMA controller
    
     uDMAChannelTransferSet(UDMA_RX_CHANNEL | UDMA_PRI_SELECT,
                              UDMA_TRANSFER_MODE,(void *)(SSI1_BASE), 
    						  Rx, sizeof(g_ui8TxBuf));
    
    uDMAChannelEnable(UDMA_RX_CHANNEL);
    for(i = 0; i < SSI_TXBUF_SIZE; i++)
    	{
    	// Wait for data to be available in the receive buffer
    		while(SSIDataGetNonBlocking(SSI1_BASE, &u32Rx[i])) {}
    	}
    	return u32Rx;
    }
    int main()
    {
    	
        OLED_Init();
        init_uDMA();
        config_DMA_transfer();
        static unsigned char* u32Rxdata = DMA_RX();
        Write_display(u32Rxdata);
        uDMADisable();
    }
    
    
    void SSI_Init()
    {
        unsigned int ui32SysClock;
    	ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN |
                                           SYSCTL_USE_PLL | SYSCTL_CFG_VCO_240), 120000000);
    
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI1);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    
    	GPIOPinConfigure(GPIO_PB4_SSI1FSS);
    	GPIOPinConfigure(GPIO_PB5_SSI1CLK);
    	GPIOPinConfigure(GPIO_PE4_SSI1XDAT0);
    	GPIOPinConfigure(GPIO_PE5_SSI1XDAT1);
    
    	GPIOPinTypeSSI(GPIO_PORTB_BASE, GPIO_PIN_5 | GPIO_PIN_4);
    	GPIOPinTypeSSI(GPIO_PORTE_BASE, GPIO_PIN_4 | GPIO_PIN_5);
    
    	SSIConfigSetExpClk(SSI1_BASE, ui32SysClock, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 1000000, 8);
    
    	SSIEnable(SSI1_BASE);
    }

    Are below mentioned methods can be used receive data at OLED peripheral and processed further? If not proper way, please do suggest proper way i'm happy to learn new techniques.

    • Using the SSI DMA Rx channel (which i used)
    • Using polling: (uses uC cycles not useful for me)
    • Using interrupts
    • Using polling and Interrupts

    Best Regards,

    Ajaykumar V

  • Hello Ajaykumar,

    Thanks. I was able to find the issue with your DMA TX. When using uDMAChannelTransferSet you had one slight but crucial omission that caused the DMA to not operate correctly. 

    When pointing to the Destination Address, you can't just point to the SSI1_BASE peripheral address, you need to point specifically to the data register for it.

    Your function used only (void *)(SSI1_BASE), but you need to use (void *)(SSI1_BASE + SSI_O_DR)

    To do so, you must add #include "inc/hw_ssi.h" to the top of your file or it won't be able to find the SSI_O_DR register address.

    With this change, I was able to get the SSI data transmitting via DMA onto my SSI pins.

        uDMAChannelTransferSet(UDMA_TRANSFER_CHANNEL | UDMA_PRI_SELECT,
                               UDMA_TRANSFER_MODE, g_ui8TxBuf ,
                               (void *)(SSI1_BASE + SSI_O_DR),
                               sizeof(g_ui8TxBuf));

    As I don't have an Adafruit display, I commented out the RX code and did not test that. But I noticed you need to make the same change in your DMA_RX function as well.

    Hopefully that is the missing step that will get you rolling moving forward.

    Best Regards,

    Ralph Jacobi

  • Hello Ralph Jacobi,

    i made changes as you suggested, it worked.

    use (void *)(SSI1_BASE + SSI_O_DR)

    which solved some part of the issue from the above solution i'm able to transfer pre-written data (junk values) present at u32Rxdata. I think i'm not able to write data from SSI_O_DR to u32Rxdata. As you said

    The SSI peripheral when configured to use DMA data would stream out the data from your buffer onto the SSI pins, not to an SSI RX buffer

    how can i receive data from SSI_O_DR to Rx buffer so that i can display data on display.

    when i tried with below code;

    uDMAChannelTransferSet(UDMA_CHANNEL_SSI1RX | UDMA_PRI_SELECT,
                              UDMA_TRANSFER_MODE, (void *)(SSI1_BASE + SSI_O_DR),
                              u32Rxdata,
                              sizeof(u32Rxdata));
    
    uDMAChannelEnable(UDMA_TRANSFER_CHANNEL | UDMA_CHANNEL_SSI1RX);

    data read data from 0x2000026c which contains some junk values. i wrote data to u32Rxdata using mentioned code but not written to u32Rxdata.

    1. Do i need to send and receive at the same time? to write on display.
    2.  

      Are below mentioned methods can be used receive data at OLED peripheral and processed further? If not proper way, please do suggest proper way

    and/or suggest method to receive data from SSI_O_DR to receive buffer so that i can able to display on OLED.

    And it is also observed that i'm not able to see the data which i'm transferring from g_ui8TxBuf to SSI_O_DR in Memory browser at SSI_O_DR when i try to see using break point in debug run mode. it is writing pre-written data present in the SSI_O_DR.  

    Best Regards,

    Ajaykumar V

  • Hello Ajaykumar,

    The configuration for the Channel Transfer looks okay so there has to be something else on going that is impacting the receive.

    Can you please get a capture on an oscilloscope or logic state analyzer of the SSI bus where the LCD is sending data to your TM4C MCU? I won't be able to replicate your exact situation as I don't have the screen, so I'm going to need to see the SSI lines before I can offer any more feedback.

    Best Regards,

    Ralph Jacobi

  • Hello Ralph Jacobi

    Thank you for your patience.

    As i didn't have access to logic analyzer or osciloscope. i'm working using break points in program.

    i'm not able to write/read data to SSI_O_DR. previously g_ui8TxBuf  was filled with 0x00 only i didn't tried with other last time when i tried with other data i'm not able to see that data which i'm transferring from g_ui8TxBuf to SSI_O_DR in Memory browser at SSI_O_DR when i try to see using break point in debug run mode. or it is not printing on display it is writing pre-written data present in the SSI_O_DR.

    Best Regards,

    Ajaykumar V

  • Hello Ajaykumar,

    When using the DMA you won't be able to observe anything meaningful through breakpoints. You will need to acquire access to a tool that can allow you to view the SSI lines.

    Alternatively, you can simply the problem initially by removing the DMA operations until you can get standard SSI bi-directional communication validated and then re-add the DMA after that has been achieved. Even in this case, viewing the SSI lines would significantly speed debug, but at least without using DMA you could try and achieve what you are currently looking for.

    Best Regards,

    Ralph Jacobi