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.

LP-MSPM0G3507: Issue sending just 2 bytes command over SPI

Part Number: LP-MSPM0G3507

Hello,

I'm using LP-MSPM0G3507 Rev.A and CCS Theia 1.2.0.

I'm trying to send a command to an external peripheral over SPI.

The content of the SPI message must be exactly 0x06, so I tried using the API functions DL_SPI_setDataSize and DL_SPI_transmitData8 in the following way:

DL_SPI_setDataSize(SPI_0_INST, DL_SPI_DATA_SIZE_8);
DL_SPI_transmitData8(SPI_0_INST, 0x06);

Unfortunalely, observing the result on a scope I see that when CS go low I get 0x0006 instead of 0x06;

Now, I did set the initial configuration of the SPI in the following way:

because I need to send other 16 bit wide messages before sending the 8 bit command: do I perhaps need to reinitialize SPI to make it work?

Is this bounded to happen because SPI FIFO is 16 bit wide?

Thanks in advance,

Stefano

  • Each FIFO entry is (effectively) as wide as CTL0:DSS says it is. [Ref TRM (SLAU846A) Sec 17.2.2.2]

    TRM Table 17-57 doesn't explicitly say that DSS can't be modified while CTL1:ENABLE=1, but Sec 17.2.5 (along with your observed behavior) suggests it. 

    I suspect you need to bracket the DL_SPI_setDataSize call with DL_SPI_disable/DL_SPI_enable. Doing this mid-transaction might have other (unwanted) effects (I haven't tried it). If you have to send an odd number of bytes, it might be simpler to just break the 16-bit frames down and send them all as bytes.

  • Hello Bruce,

    Another question then, if I put 16 bits into SPI FIFO and set the frame size to 8, what would happen?

    Only 8 MSB will be sent? If so I need to rework my code to put 1 byte at a time into SPI FIFO.

    Otherwise, if all 16 bits will be sent, but in 2 frames by 8 bits, it would be nothing but changing the starting config of SPI, am I right?

    Thanks for your answers,

    Stefano

  • Can you tell us what peripheral this is? It is uncommon to require two data widths for SPI.

    I would just switch to an 8 bit transmission and send two transmissions when 16 bits are called for.

  • If {DSS}=8, it will send the 8x low-order bits from the FIFO entry, and ignore the rest [Ref Sec 17.2.2.2 + Table 17-63].

    Corollary: If you only ever write an even number of bytes, you could pack more bits into the FIFO by writing bytes pair-wise with {DSS}=16, but you would need to assure the correct byte order (perhaps more trouble than it's worth).

    Aside: The verbiage in Sec 17.2.2.2 seems to say it's important whether the TXDATA register is written using 8-bit vs 16-bit vs 32-bit writes from the CPU, but then de-fuses those words with "at least". I do 32-bit writes to TXDATA with {DSS}=8, and it performs as expected. [Edit: The Driverlib (DL_SPI_transmitData8) also does this.]

  • It is an SPI Nand Flash memory: usually a write command (ie: 0x84) is immediatly followed by 16 bit memory column address and then data (up to 2048 bytes), in a continuous transmission (CS low for the entire duration).

    The data I'm sending are samples from ADC: they are 16 bit, so I did convert them in 2 - 8 bit samples and now I'm trying to send them over SPI as suggested by Bruce.

    I'm still fighting with the right timing though, I'm using DMA to move the data from a buffer to SPI FIFO and there is some sort of race condition in my code between DMA and SPI sending where I have transmission holes in tha data, something I didn't experience when I was using 16 bit frame: I think I just need to tailor the timing a little around the 8 bit frame.

    This is my code regarding DMA and SPI:

    Sample_buffer_8[64];                // Buffer that contains 64 half (8bit) ADC samples
    uint16_t Mem_Address = 0x0000;      // Current Memory Column Address
    
    for (int k = 0; k < 64; k+=4)
    {
        DL_DMA_setSrcAddr (DMA, DMA_CH2_CHAN_ID, (uint32_t) &Sample_Buffer8[k]);
        DL_DMA_setDestAddr(DMA, DMA_CH2_CHAN_ID, (uint32_t)(&SPI_0_INST->TXDATA));
        DL_DMA_setTransferSize(DMA, DMA_CH2_CHAN_ID, 4);
        
        if (k == 0)
        {
            DL_SPI_transmitData8 (SPI_0_INST, 0x84);
            DL_SPI_transmitData8 (SPI_0_INST, Mem_Address >> 8);
            DL_SPI_transmitData8 (SPI_0_INST, Mem_Address & 0xFF);
        }
        
        DL_DMA_enableChannel(DMA, DMA_CH2_CHAN_ID);
    }

  • Generally, an SPI target doesn't care about gaps in the transmission. ("Generally" meaning "I've never seen one that did".)

    If it does matter, I suspect you're trying to achieve "continuous" transmission [Ref TRM Sec 17.2.3.1 (e.g.)] using the SPI unit's built-in /CS (CSSEL) by never letting the FIFO go empty. This might be difficult to achieve by writing bytes to a 32MHz SPI; if nothing else, you should probably consider the effects of an ill-timed interrupt from some other part of the system.

    You may want to consider driving /CS with a GPIO instead. That way you get to decide when the transaction starts and stops.