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.

LAUNCHXL2-570LC43: MIBSPI with DMA support: extract 8 bit MIBSPI values to 8 bit array

Genius 9880 points
Part Number: LAUNCHXL2-570LC43
Other Parts Discussed in Thread: TMS570LC4357

Hi,

Customer is trying to configure the TMS570LC4357 Launchpad please see details below.

I'm is trying to configure the TMS570LC4357 LaunchPad example example_mibspiDMA.c with the MIBSPI charlen set to 8 bits and use the DMA to transfer the received data to an 8 bit array. The example works correctly with 16 bit charlen and the example code. I don't want to store twice the data required so I just want to store the 8 LSB from the mibspiRAM1 received data into a second array. This post suggests this is possible: https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/870652/rm57l843-mib-spi-with-dma-support but changing the byte offsets hasn't been successful. Could you give me more information on how to implement this? I've attached my latest attempt.

example_mibspiDMA_test8bits.c
/** @file HL_sys_main.c 
*   @brief Application main file
*   @date 11-Dec-2018
*   @version 04.07.01
*
*   This file contains an empty main function,
*   which can be used for the application.
*/

/* 
* Copyright (C) 2009-2018 Texas Instruments Incorporated - www.ti.com  
* 
* 
*  Redistribution and use in source and binary forms, with or without 
*  modification, are permitted provided that the following conditions 
*  are met:
*
*    Redistributions of source code must retain the above copyright 
*    notice, this list of conditions and the following disclaimer.
*
*    Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the 
*    documentation and/or other materials provided with the   
*    distribution.
*
*    Neither the name of Texas Instruments Incorporated nor the names of
*    its contributors may be used to endorse or promote products derived
*    from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/


/* USER CODE BEGIN (0) */
/* USER CODE END */

/* Include Files */

#include "HL_sys_common.h"

/* USER CODE BEGIN (1) */
#include "HL_mibspi.h"
#include "HL_sys_dma.h"

// C Library
#include <stdio.h>

/* example data Pattern configuration */
#define D_SIZE      128

void loadDataPattern(uint32 psize, uint16* pptr);
void mibspiEnableInternalLoopback(mibspiBASE_t *mibspi);
void dmaConfigCtrlPacket(uint32 sadd,uint32 dadd,uint32 dsize);
void mibspiDmaConfig(mibspiBASE_t *mibspi,uint32 channel, uint32 txchannel, uint32 rxchannel);

#pragma SET_DATA_SECTION(".sharedRAM")
uint16 TXDATA[D_SIZE];         /* transmit buffer in sys ram */
uint8 RXDATA[D_SIZE]= {0};    /* receive  buffer in sys ram */
#pragma SET_DATA_SECTION()

g_dmaCTRL g_dmaCTRLPKT1, g_dmaCTRLPKT2;    /* dma control packet configuration stack */
/* USER CODE END */

/** @fn void main(void)
*   @brief Application main function
*   @note This function is empty by default.
*
*   This function is called after startup.
*   The user can use this function to implement the application.
*/

/* USER CODE BEGIN (2) */
/* USER CODE END */

int main(void)
{
/* USER CODE BEGIN (3) */

   /* - creating a data chunk in system ram to start with ... */
   loadDataPattern(D_SIZE,&TXDATA[0]);

   /* - initializing mibspi - enabling tg 0 , length 127 (halcogen file)*/
   mibspiInit();

   /* - enabling loopback ( this is to emulate data transfer without external wires */
   mibspiEnableInternalLoopback(mibspiREG1);

   /* - configuring dma control packets   */
   g_dmaCTRLPKT1.SADD      = (uint32)TXDATA;    /* source address             */
   g_dmaCTRLPKT1.DADD      = (uint32)&(mibspiRAM1->tx[0].data);    /* destination  address       */
   g_dmaCTRLPKT1.CHCTRL    = 0;                 /* channel control            */
   g_dmaCTRLPKT1.FRCNT     = 1;                 /* frame count                */
   g_dmaCTRLPKT1.ELCNT     = D_SIZE;            /* element count              */
   g_dmaCTRLPKT1.ELDOFFSET = 4;                 /* element destination offset */
   g_dmaCTRLPKT1.ELSOFFSET = 0;                 /* element source offset */
   g_dmaCTRLPKT1.FRDOFFSET = 0;                 /* frame destination offset   */
   g_dmaCTRLPKT1.FRSOFFSET = 0;                 /* frame destination offset   */
   g_dmaCTRLPKT1.PORTASGN  = PORTA_READ_PORTB_WRITE;
   g_dmaCTRLPKT1.RDSIZE    = ACCESS_16_BIT;     /* read size                  */
   g_dmaCTRLPKT1.WRSIZE    = ACCESS_16_BIT;     /* write size                 */
   g_dmaCTRLPKT1.TTYPE     = FRAME_TRANSFER ;   /* transfer type              */
   g_dmaCTRLPKT1.ADDMODERD = ADDR_INC1;         /* address mode read          */
   g_dmaCTRLPKT1.ADDMODEWR = ADDR_OFFSET;       /* address mode write         */
   g_dmaCTRLPKT1.AUTOINIT  = AUTOINIT_ON;       /* autoinit                   */

   g_dmaCTRLPKT2.SADD      = (uint32)&(mibspiRAM1->rx[0].data);    /* source address             */
   g_dmaCTRLPKT2.DADD      = (uint32)RXDATA;    /* destination  address       */
   g_dmaCTRLPKT2.CHCTRL    = 0;                 /* channel control            */
   g_dmaCTRLPKT2.FRCNT     = 1;                 /* frame count                */
   g_dmaCTRLPKT2.ELCNT     = D_SIZE;             /* element count              */
   g_dmaCTRLPKT2.ELDOFFSET = 0;                 /* element destination offset */
   g_dmaCTRLPKT2.ELSOFFSET = 4;                 /* element source offset */
   g_dmaCTRLPKT2.FRDOFFSET = 0;                 /* frame destination offset   */
   g_dmaCTRLPKT2.FRSOFFSET = 0;                 /* frame destination offset   */
   g_dmaCTRLPKT2.PORTASGN  = PORTB_READ_PORTA_WRITE;
   g_dmaCTRLPKT2.RDSIZE    = ACCESS_8_BIT;     /* read size                  */
   g_dmaCTRLPKT2.WRSIZE    = ACCESS_8_BIT;     /* write size                 */
   g_dmaCTRLPKT2.TTYPE     = FRAME_TRANSFER ;   /* transfer type              */
   g_dmaCTRLPKT2.ADDMODERD = ADDR_OFFSET;         /* address mode read          */
   g_dmaCTRLPKT2.ADDMODEWR = ADDR_INC1;       /* address mode write         */
   g_dmaCTRLPKT2.AUTOINIT  = AUTOINIT_ON;       /* autoinit                   */

   /* upto 32 control packets are supported. */

   /* - setting dma control packets */
   dmaSetCtrlPacket(DMA_CH0,g_dmaCTRLPKT2);
   dmaSetCtrlPacket(DMA_CH1,g_dmaCTRLPKT1);

   /* - setting the dma channel to trigger on h/w request */
   dmaSetChEnable(DMA_CH0, DMA_HW);
   dmaSetChEnable(DMA_CH1, DMA_HW);

   /* - configuring the mibspi dma , channel 0 , tx line -0 , rxline -1     */
   /* - refer to the device data sheet dma request source for mibspi tx/rx  */
   mibspiDmaConfig(mibspiREG1,0,0,1);

   dmaEnable();

   /* - start the mibspi transfer tg 0 */
   mibspiTransfer(mibspiREG1,0 );

   while(1){
       int i =0;
       while (i < 4000){
           i++;
       }

       uint8 value = *(&(mibspiRAM1->rx[0].data));
       printf("Address mibspiRAM1->rx[0].data: %X , value: %X \n", &(mibspiRAM1->rx[0].data), value);
       value = *(&(mibspiRAM1->rx[0].data) + 1);
       printf("Address 0 + 1: %X , value: %X \n", &(mibspiRAM1->rx[0].data) + 1, value);
       value = *(&(mibspiRAM1->rx[0].data) + 2);
       printf("Address 0 + 2: %X , value: %X \n", &(mibspiRAM1->rx[0].data) + 2, value);
       value = *(&(mibspiRAM1->rx[0].data) + 3);
       printf("Address 0 + 3: %X , value: %X \n", &(mibspiRAM1->rx[0].data) + 3, value);
       value = *(&(mibspiRAM1->rx[0].data) + 4);
       printf("Address 0 + 4: %X , value: %X \n", &(mibspiRAM1->rx[0].data) + 4, value);

       printf("Address mibspiRAM1->rx[1].data: %X , value: %X \n", &(mibspiRAM1->rx[1].data), mibspiRAM1->rx[1].data);

       printf("Address RXDATA 0: %X , value: %X \n", &RXDATA[0], RXDATA[0]);
       printf("Address RXDATA 1: %X , value: %X \n", &RXDATA[1], RXDATA[1]);

       printf("Complete: %i \n", mibspiIsTransferComplete(mibspiREG1, 0));
       printf("0 - TX: %X RX: %X \n", TXDATA[0], RXDATA[0]);
       printf("0 - TX: %X RX: %X \n", mibspiRAM1->tx[0].data, mibspiRAM1->rx[0].data);
       printf("1 - TX: %X RX: %X \n", TXDATA[1], RXDATA[1]);
       printf("1 - TX: %X RX: %X \n", mibspiRAM1->tx[1].data, mibspiRAM1->rx[1].data);
       printf("2 - TX: %X RX: %X \n", TXDATA[2], RXDATA[2]);
       printf("2 - TX: %X RX: %X \n", mibspiRAM1->tx[2].data, mibspiRAM1->rx[2].data);
       printf("3 - TX: %X RX: %X \n", TXDATA[3], RXDATA[3]);
       printf("3 - TX: %X RX: %X \n", mibspiRAM1->tx[3].data, mibspiRAM1->rx[3].data);
       printf("4 - TX: %X RX: %X \n", TXDATA[4], RXDATA[4]);
       printf("4 - TX: %X RX: %X \n", mibspiRAM1->tx[4].data, mibspiRAM1->rx[4].data);
       printf("5 - TX: %X RX: %X \n", TXDATA[5], RXDATA[5]);
       printf("5 - TX: %X RX: %X \n", mibspiRAM1->tx[5].data, mibspiRAM1->rx[5].data);

   };

/* USER CODE END */

    return 0;
}


/* USER CODE BEGIN (4) */
/** void mibspiEnableLoopback(mibspiBASE_t *mibspi )
*
*   enabling internal loopback on mibspix
*/
void mibspiEnableInternalLoopback(mibspiBASE_t *mibspi )
{
    /* enabling internal loopback */
    mibspi->GCR1 |= 1U << 16U;
}

/** void mibspiDmaConfig(mibspiBASE_t *mibspi,uint32 channel, uint32 txchannel, uint32 rxchannel)
*
*   configuring mibspi dma with
*
*       channel   > mibspi dma channel number
*       txchannel > transmit channel dedicated for mibspi
*       rxchannel > receive  channel dedicated for mibspi
*/
void mibspiDmaConfig(mibspiBASE_t *mibspi,uint32 channel, uint32 txchannel, uint32 rxchannel)
{
    uint32 bufid  = D_SIZE - 1;
    uint32 icount = 0;

    /* setting transmit and receive channels */
    mibspi->DMACTRL[channel] |= (((rxchannel<<4)|txchannel) << 16);

    /* enabling transmit and receive dma */
    mibspi->DMACTRL[channel] |=  0x8000C000;

    /* setting Initial Count of DMA transfers and the buffer utilized for DMA transfer */
    mibspi->DMACTRL[channel] |=  (icount << 8) |(bufid<<24);

}


/** void loadDataPattern(uint32 psize, uint16* pptr)
*
*   loading a randam data chunk into system ram
*
*     pptr  > sys ram address
*     psize > chunkl size
*
*/
void loadDataPattern(uint32 psize, uint16* pptr)
{
    int i;
    for(i=0;i<psize;i++)
    {
        TXDATA[i] = i;
    }
 }
/* USER CODE END */

Thank you.

Regards,
May

  • Hi May,

    1. The charlen must be programmed to the same length for both the master and the slave. The loopback is enabled in your project, so the charlen for TX and RX should be same, either 16-bit or 8-bit.

    2. If a 16-bit data is written to TXRAM (CPU or through DMA transfer), and charlen=8, only 1st byte is transmitted to SPI bus or SPI slave.

        TXRAM->TXDATA[15:0]=0x1234, only 0x34 is transmitted 

    3. If charlen in RX side is 8-bit, the RXed 8-bit data is written to 1st byte of RXRAM

        RXRAM-->RXDATA[15:0]=0x0034

    4. RDSIZE and WRSIZE of DMA transfer for receiving data = ACCESS_8_BIT, 0x34 will be transferred to your data array

  • Hi QJ Wang,

    Please see additional information from customer.

    "

    For the first point, the CHARLEN is set to 8bit. Storing the 8bit value in a 16bit type was a workaround.

    On the second/third point, is the first byte considered to be the LSB or MSB because the system memory is big endian. So is the first byte &(mibspiRAM1->tx[0].data) or is it &(mibspiRAM1->tx[0].data) +1?

     

    Because when I transfer, for example, 0x01 from TXDATA[1] then mibspiRAM1->tx[1].data then it prints as 0x0100.

     

    With this config:

       g_dmaCTRLPKT1.SADD      = (uint32)TXDATA;    /* source address             */

       g_dmaCTRLPKT1.DADD      = (uint32)(&(mibspiRAM1->tx[0].data));    /* destination  address       */

       g_dmaCTRLPKT1.CHCTRL    = 0;                 /* channel control            */

       g_dmaCTRLPKT1.FRCNT     = 1;                 /* frame count                */

       g_dmaCTRLPKT1.ELCNT     = D_SIZE;            /* element count              */

       g_dmaCTRLPKT1.ELDOFFSET = 4;                 /* element destination offset */

       g_dmaCTRLPKT1.ELSOFFSET = 0;                 /* element source offset */

       g_dmaCTRLPKT1.FRDOFFSET = 0;                 /* frame destination offset   */

       g_dmaCTRLPKT1.FRSOFFSET = 0;                 /* frame source offset   */

       g_dmaCTRLPKT1.PORTASGN  = PORTA_READ_PORTB_WRITE;

       g_dmaCTRLPKT1.RDSIZE    = ACCESS_8_BIT;     /* read size                  */

       g_dmaCTRLPKT1.WRSIZE    = ACCESS_8_BIT;     /* write size                 */

       g_dmaCTRLPKT1.TTYPE     = FRAME_TRANSFER ;   /* transfer type              */

       g_dmaCTRLPKT1.ADDMODERD = ADDR_INC1;         /* address mode read          */

       g_dmaCTRLPKT1.ADDMODEWR = ADDR_OFFSET;       /* address mode write         */

       g_dmaCTRLPKT1.AUTOINIT  = AUTOINIT_ON;       /* autoinit                   */

     

    I get:

    Address mibspiRAM1->tx[1].data: FF0E0006 , value: 100

    When the value of TXDATA[1] = 1.

    "

    Regards,
    May

  • On the second/third point, is the first byte considered to be the LSB or MSB because the system memory is big endian. So is the first byte &(mibspiRAM1->tx[0].data) or is it &(mibspiRAM1->tx[0].data) +1?

    If CHARLEN=8, the destination address for DMA TX transfer should be &(mibspiRAM1->tx[0].data) +1

    Because when I transfer, for example, 0x01 from TXDATA[1] then mibspiRAM1->tx[1].data then it prints as 0x0100.

    If the destination address is &(mibspiRAM1->tx[0].data),  the mibspiRAM1->tx[1].data = 0x0100.

    If the destination address is &(mibspiRAM1->tx[0].data) + 1,  the mibspiRAM1->tx[1].data = 0x0001.

  • If CHARLEN=8, only the first byte is transmitted. For example if  mibspiRAM1->tx[1].data = 0x1234, ox34 is transmitted and 0x12 is ignored.