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.

RM57L843: DMA and SPI (non MIBSPI) - Not continuous Chip Select signal

Part Number: RM57L843
Other Parts Discussed in Thread: HALCOGEN

Hello there!

I am using RM57 SPI (MIBSPI compatibility mode) with DMA. I am using SPI3 with CS1 line.

My code almost identical to the one used in this thread:

https://e2e.ti.com/support/microcontrollers/hercules/f/312/t/384808

In this thread, some code was attached (3681.rm57_spi_dma.zip) which helped me to successfully test my SPI - DMA code.

The only issue I am having (and the only difference with the code provided in 3681.rm57_spi_dma.zip) is related to the Chip Select line. I am not using a GPIO to drive the Chip Select signal, but the CS1 line connected to the SPI3 (I would like the Chip Select line to be driven automatically by the peripheral and not manually using a GPIO).

The problem I have is that the Chip Select is not CONTINUOUS during the whole SPI transaction (in this case a 4-word 16 bit transmission) but the Chip Select returns to high level state after transmitting 1 or 2 words, as seen in the following picture:

In a previous development stage, I was able to use a continuous Chip Select signal when no using DMA but using SPI with interrupts.

Is there anything I can do to solve this issue? Or I am forced to use a manually controlled GPIO?

Thanks!

  • Hello Jor,

    Check to make sure you are enabling CSHOLD in SPIDAT1. From what I have seen, HalCoGen doesn't directly support this configuration so you will have to manually set it to 1 using one of the user code sections.

    In all of the send, recevive, send and receive functions I can see in the spi.c driver file, CSHOLD is configured like this:

    uint32 Chip_Select_Hold = (dataconfig_t->CS_HOLD) ? 0x10000000U : 0U;

    But, there is nowhere in the code where dataconfig-->CS_HOLD is set to 1 so this always results in CSHOLD = 0. This will cause the behavior you are seeing where the CS de-asserts between messages.
  • Hello Chuck,

    Thanks you for attending my question.

    You are right in the fact that CSHOLD should be enabled in SPIDAT1. That is what HalCoGen does when using SPI with SPI interrupts. The calls:

    uint32 spiTransmitData(spiBASE_t *spi, spiDAT1_t *dataconfig_t, uint32 blocksize, uint16 * srcbuff);
    void spiSendData(spiBASE_t *spi, spiDAT1_t *dataconfig_t, uint32 blocksize, uint16 * srcbuff);
    uint32 spiReceiveData(spiBASE_t *spi, spiDAT1_t *dataconfig_t, uint32 blocksize, uint16 * destbuff);
    void spiGetData(spiBASE_t *spi, spiDAT1_t *dataconfig_t, uint32 blocksize, uint16 * destbuff);
    uint32 spiTransmitAndReceiveData(spiBASE_t *spi, spiDAT1_t *dataconfig_t, uint32 blocksize, uint16 * srcbuff, uint16 * destbuff);
    void spiSendAndGetData(spiBASE_t *spi, spiDAT1_t *dataconfig_t, uint32 blocksize, uint16 * srcbuff, uint16 * destbuff);
    void spiEnableLoopback(spiBASE_t *spi, loopBackType_t Loopbacktype);

    provide the parameter spiDAT1_t *dataconfig_t so the chip select behaviour can be configured when accesing the spi->DAT1 register in order to transmit, via polling or via interrupts.

    But, with DMA, in transmission, is the DMA who sends the data from a SRAM buffer to the spi->DAT0 OR the spi->DAT1 register.

    For your records, and in order to support my following questions, this is the current DMA Tx packet configuration I am using:

    #define SPI3_TX_ADDR ((uint32_t)(&(spiREG3->DAT1)))

    uint16_t DmaTxBuffer[SIZE_DMA_BUFFER] __attribute__((section("sharedRAM"))) = { 0xA1A2, 0xA3A4, 0xA5A6, 0xA7A8 };

    // Config dma control packets
    m_dmaCtrlTxPkt.SADD = (uint32_t)DmaTxBuffer; /* source address */
    m_dmaCtrlTxPkt.DADD = SPI3_TX_ADDR;
    m_dmaCtrlTxPkt.CHCTRL = 0; /* channel control */

    // Generates a nCS for each frame sending the right data:
    m_dmaCtrlTxPkt.FRCNT = 4; /* frame count */
    m_dmaCtrlTxPkt.ELCNT = 1; /* element count */

    m_dmaCtrlTxPkt.ELDOFFSET = 0; /* element destination offset */
    m_dmaCtrlTxPkt.ELSOFFSET = 0; /* element source offset */
    m_dmaCtrlTxPkt.FRDOFFSET = 0; /* frame destination offset */
    m_dmaCtrlTxPkt.FRSOFFSET = 0; /* frame destination offset */
    m_dmaCtrlTxPkt.PORTASGN = PORTA_READ_PORTB_WRITE; /* ports assignment */
    m_dmaCtrlTxPkt.RDSIZE = ACCESS_16_BIT; /* read size */
    m_dmaCtrlTxPkt.WRSIZE = ACCESS_16_BIT; /* write size */
    m_dmaCtrlTxPkt.TTYPE = FRAME_TRANSFER; /* transfer type */
    m_dmaCtrlTxPkt.ADDMODERD = ADDR_INC1; /* address mode read */
    m_dmaCtrlTxPkt.ADDMODEWR = ADDR_FIXED; /* address mode write */
    m_dmaCtrlTxPkt.AUTOINIT = AUTOINIT_OFF; /* autoinit */

    So, your solution (thanks for it) makes me wonder several things:

    1. Should I use the spi->DAT0 OR the spi->DAT1 register as destination address for the DMA in case I want automatic chip select bahviour (and not manual GPIO behaviour)? (I have seen several examples using SPI-DMA that use spi->DAT0, like the one in the thread I mentioned before: https://e2e.ti.com/support/microcontrollers/hercules/f/312/t/384808)

    2. I understand that I need to use the spiDAT1_t *dataconfig_t struct to configure the chip select behaviour, but given that I am not polling and not using SPI interrupts but DMA interrupts, what function is provided to do that with DMA functionality? If no function exists at the moment for this purpose (not provided by HalCoGen) a simple code snippet would help me a lot.

    I am asking this because any write to the spi->DAT1 register produces a write also in the field TXDATA, which can trigger a transmission if not properly handled. In that case, should I set SPIEN = 0 before accessing spi->DAT1 and set SPIEN = 1 after configuring the chip select fields? (This is something I have tried but if I do it the SPI transmissions do not generate any nCS signal anymore).

    3. Another solution that comes to my mind is to use the SRAM buffer used for the DMA source address as 32-bit words to be able to fit the whole spi->DAT1 register, having the upper 16-bit filled with the nCS configuration and the lower 16-bit with the data to be transmitted, but that will force me to perform 32-bit accesses by the DMA:

    m_dmaCtrlTxPkt.RDSIZE = ACCESS_32_BIT; /* read size */
    m_dmaCtrlTxPkt.WRSIZE = ACCESS_32_BIT; /* write size */

    Is this a possible solution?

    4. My last question is related to the Frame versus Element count. Given that I would like to send 4-words of 16-bit which a continuous chip select signal on each SPI transmission, I was hoping to be able to use the configuration

    m_dmaCtrlTxPkt.FRCNT = 1; /* frame count */
    m_dmaCtrlTxPkt.ELCNT = 4; /* element count */

    But this configuration produces an unexpected result: Only DmaTxBuffer buffer contents related to index 0 and index 3 are transmitted in the SPI bus:

    RM57_SPI_DMA_FR4_ELEM1_nCS_after_each_element_take3.png

    Alternatively, if I use the following config, the right data (the full buffer contents) shows up in the SPI bus:

    // Generates a nCS for each frame sending the right data:
    m_dmaCtrlTxPkt.FRCNT = 4; /* frame count */
    m_dmaCtrlTxPkt.ELCNT = 1; /* element count */

    Is there any explanation for this?

    Thank you so much for your help. I can't wait to have this properly running :)

    Kind Regards,

    Jor Sas

     

  • Hi,
    Do you think you will be able to attend this request anytime soon?
    I would really appreciate it.

    Kind Regards,
    Jor Sas
  • Hi,

    Is there any possibility that you can guide me with the following two questions?

    1. Should I use the spi->DAT0 OR the spi->DAT1 register as destination address for the SPI DMA in case I want automatic chip select behaviour (and not manual GPIO behaviour)?
    I can see that the spi->DAT1 is the only one providing chip select configuration.
    (I have seen several examples using SPI-DMA that use spi->DAT0, like the one in the thread I mentioned before:
    e2e.ti.com/.../384808
    but I think they implement chip select control by means of GPIO).

    2. I understand that I need to use the spiDAT1_t *dataconfig_t struct to configure the chip select behaviour, but given that I am not using SPI polling and not using SPI interrupts but DMA interrupts:
    How can I use the spiDAT_t* struct to force automatic chip select behaviour (and no manual GPIO chip select functionality) with DMA?
    (I was able to succesfully use it with SPI interrupts but not with DMA interrupts).

    Thanks for your support,

    Kind Regards,
    Jor Sas
  • Refer to 

    https://e2e.ti.com/support/microcontrollers/hercules/f/312/p/664673/2447853#2447853

    for the solution.

    Again, thanks for no help.

    More than 10 days lost with Halcogen <> FreeRTOS undocumented issues.

    Jor Sas.