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.

TI-RTOS TM4C129ENCPDT SPI driver unexpected output

Hello. I am using newest TI-RTOS and am trying to send SPI initialization sequence to MCP3909 energy meter.  My code is based on the TI SPI example provided in the CCS. Basically I just changed the MasterTxBuffer and removed the code for RX (loopback).

The SPI seemingly works, I tried at 100kHz and 10MHz, but the output data does not match what I need to send.

For example:

int masterTxBuffer = 0b00000001; // 1

Results in this:

Another example:

int masterTxBuffer = 0b11111111; //255

Result:

int masterTxBuffer = 0b10100100; // 164 = MCP3909 init, output dual channel pre-filter

Result:


SPI example prints correct (expected) decimal value:

SPI initialized
SPI: Master: 164
SPI: Done

As you can see, neither output corresponds to data in masterTxBuffer.

Here is my SPI function, slightly modified from TI SPI loopback example:

Void MCPinitFxn (UArg arg0, UArg arg1)
{
    SPI_Handle masterSpi;
    SPI_Transaction masterTransaction;
    bool transferOK;

    /* Initialize SPI handle as default master */
    SPI_Params_init(&params2);
    params2.bitRate = 100000;
    params2.frameFormat = SPI_POL0_PHA0;
    params2.dataSize = 8;
    masterSpi = SPI_open(SPI3, &params2);
    if (masterSpi == NULL) {
        System_abort("Error initializing SPI\n");
    }
    else {
        System_printf("SPI initialized\n");
    }

    /* Initialize master SPI transaction structure */
    masterTransaction.count = SPI_MSG_LENGTH;
    masterTransaction.txBuf = (Ptr)masterTxBuffer;
    masterTransaction.rxBuf = (Ptr)masterRxBuffer;

    /* Initiate SPI transfer */
    transferOK = SPI_transfer(masterSpi, &masterTransaction);

    if(transferOK) {
        /* Print contents of master receive buffer */
        System_printf("SPI: Master: %d\n", masterTransaction.txBuf);
    }
    else {
        System_printf("SPI: Unsuccessful master SPI transfer");
    }

    /* Deinitialize SPI */
    SPI_close(masterSpi);

    System_printf("SPI: Done\n");
    System_flush();

}

What could be the problem?

  • Hi,

    You need to be passing a pointer to the buffers in the txBuf and rxBuf fields in the transfer structure, not the value. I'm assuming SPI_MSG_LENGTH is 1. You should have the following

    char masterTxBuffer = 0b10100100;
    char masterRxBuffer;
    ...
    masterTransaction.count = SPI_MSG_LENGTH;
    masterTransaction.txBuf = &masterTxBuffer;
    masterTransaction.rxBuf = &masterRxBuffer;
    transferOK = SPI_transfer(masterSpi, &masterTransaction);

    Todd
  • Bingo!

    But why was in the original example (transmitting a text)

    masterTransaction.txBuf = (Ptr)masterTxBuffer

    What is the difference between (Ptr)... and & ... ?  Ptr suggests a pointer to me.

    Sorry for the dumb question.

  • Because in the SPI loopback example, it was an array
    unsigned char masterRxBuffer[SPI_MSG_LENGTH];
    unsigned char masterTxBuffer[SPI_MSG_LENGTH] = "Hello, this is master SPI";

    In your example, it is not an array.

    (Ptr) is just a cast. & means take the address of the variable.

    Todd
  • Dear Todd,

    thanks for explanation. My SPI troubles are however continuing.
    When i send that 0b10100100 and the transfer ends by CS rise to high, the MOSI line remains low. It only gets slowly high after calling SPI_Close, by pull-up resistors. I need it to rise with the CS when transfer ends. First I thought, that MOSI just holds the last bit which in my command was 0, but I tried to send 9 bits adding 1 to the end, but it still pulls the line low just half a cycle before CS rises.

    I tried to find the actual code on SPITivaDMA.c which is seemingly the lowest level I can get, but this DMA stuff is somewhat complicated to me.I have an idea to use some non-DMA way, which would allow for quicker SPI de-init. Or, access the physical register that controls the pin function to quickly switch to GPIO with output set to high. If everything fails, last resort which I thought of but would like to avoid is to give up SPI driver and bit-bang the entire command.. but then I do not hnow how to make 1us delay in Ti-rtos - I need approx. 1M bit rate and Task_Sleep is from 1ms.

    Can you help, please?

  • Does the out of the box SPI example work for you?

    Todd
  • Yes of course, as you can see above, SPI works. Also webserver loading pictures from SD card via SDSPI driver.

    But nevermind, I already did the last-resort bit-bang solution and finally I end up with initialized all four MCP3909! :-)

    Thanks for your help.

    Regards

    Matej