LAUNCHXL-F28P55X: Universal Motor Control Lab - Datalog DMA

Part Number: LAUNCHXL-F28P55X
Other Parts Discussed in Thread: C2000WARE

Tool/software:

Hi,

I am trying to use the datalog module to observe at the motor voltage and current values at run time and have managed to start with the example of below.

C:\ti\c2000\C2000Ware_MotorControl_SDK_5_04_00_00\solutions\universal_motorcontrol_lab\f28p65x\ccs\motor_control

I can see inside the datalogIF.c and datalogIF.h have the options to define symbol to use the 2-ch (DATALOGF2_EN) or 4-ch (DATALOGF4_EN) datalog with dma.

However, I would like ask if I can extend it to 6 channels given the f28p55x chip has 6 dma channels?

I am aware the motor control SDK has included 6-ch datalog source file and I would like to ask if there is any example showing how to use it please?

C:\ti\c2000\C2000Ware_MotorControl_SDK_5_04_00_00\libraries\utilities\datalog\source

Thanks!

Siu

  • Hi Siu,

    It should be doable. However, we do not have an exact example showing this. You may refer to the 4-channel case and develop it.

    However, I would like ask if I can extend it to 6 channels given the f28p55x chip has 6 dma channels?

    Thanks,

    Jiaxin

  • Hi Jiaxin,

    Thanks for getting back to me.

    I have successfully extended the dma channel from 4-ch to 6-ch. However, I can see that the last data point of one of the channel seems to have captured data from other channel.

    e.g. dataBuffer3 has jumper from -50 range to 3.

    // datalogIF.c
    
    // the includes
    #include "datalogIF.h"
    
    // **************************************************************************
    // the defines
    
    // **************************************************************************
    // the globals
    #if defined(DATALOGF6_EN)
    DATALOG_Obj datalog;
    DATALOG_Handle datalogHandle;       //!< the handle for the Datalog object
    
    #pragma DATA_SECTION(datalog, "datalog_data");
    #pragma DATA_SECTION(datalogHandle, "datalog_data");
    
    float32_t datalogBuff1[DATA_LOG_BUFF_SIZE + DATA_SIZE_EXT];
    float32_t datalogBuff2[DATA_LOG_BUFF_SIZE + DATA_SIZE_EXT];
    float32_t datalogBuff3[DATA_LOG_BUFF_SIZE + DATA_SIZE_EXT];
    float32_t datalogBuff4[DATA_LOG_BUFF_SIZE + DATA_SIZE_EXT];
    float32_t datalogBuff5[DATA_LOG_BUFF_SIZE + DATA_SIZE_EXT];
    float32_t datalogBuff6[DATA_LOG_BUFF_SIZE + DATA_SIZE_EXT];
    
    #pragma DATA_SECTION(datalogBuff1, "datalog_data");
    #pragma DATA_SECTION(datalogBuff2, "datalog_data");
    #pragma DATA_SECTION(datalogBuff3, "datalog_data");
    #pragma DATA_SECTION(datalogBuff4, "datalog_data");
    #pragma DATA_SECTION(datalogBuff5, "datalog_data");
    #pragma DATA_SECTION(datalogBuff6, "datalog_data");
    
    // **************************************************************************
    // the functions
    
    DATALOG_Handle DATALOGIF_init(void *pMemory, const size_t numBytes)
    {
        DATALOG_Handle handle;
    
        if(numBytes < sizeof(DATALOG_Obj))
        {
            return((DATALOG_Handle)NULL);
        }
    
        // assign the handle
        handle = (DATALOG_Handle)pMemory;
    
        DATALOG_Obj *obj = (DATALOG_Obj *)handle;
    
        obj->cntr = 0;
        obj->size = DATA_LOG_BUFF_SIZE;
    
        obj->scaleCnt = 0;
        obj->scaleFactor = DATA_LOG_SCALE_FACTOR;
    
        return(handle);
    } // end of DATALOG_init() function
    
    #endif  // DATALOGF6_EN
    
    // end of file
    

    // datalogIF.h

    #ifndef DATALOG_H
    #define DATALOG_H

    //*****************************************************************************
    //
    // If building with a C++ compiler, make all of the definitions in this header
    // have a C binding.
    //
    //*****************************************************************************
    #ifdef __cplusplus
    extern "C"
    {
    #endif

    //*****************************************************************************
    //
    //! \defgroup DATALOGIF DATALOGIF
    //! @{
    //
    //*****************************************************************************

    // the includes
    #include <math.h>

    // system
    #include "stdbool.h" // needed for bool type, true/false
    #if !defined(__TMS320C28XX_CLA__)
    #include "string.h" // needed for size_t typedef
    #endif
    #include "stdint.h" // needed for C99 data types

    // **************************************************************************
    // the defines
    #if defined(DATALOGF6_EN)

    #include "libraries/math/include/math.h"

    #define DATA_LOG_BUFF_SIZE 300 // Must be integral times of (20)
    #define DATA_SIZE_EXT 2 //

    #define DATA_LOG_BUFF_NUM 6 // 6 channels dma

    #define DLOG_BURST_SIZE 20 // write 200 to the register for
    // a burst size of 20

    #define DLOG_TRANSFER_SIZE (3 + (2 * DATA_LOG_BUFF_SIZE / DLOG_BURST_SIZE))

    //! defines ADC wrap size for ADC,
    #define DLOG_SRC_WRAP_SIZE (0xFFFF)

    //! defines ADC wrap size for ADC,
    #define DLOG_DST_WRAP_SIZE (0xFFFF)

    #define DLOG_WRAP_SIZE DLOG_TRANSFER_SIZE + 1

    #define DATA_LOG_SCALE_FACTOR 1 // 1->update every PWM cycle, 10->update every 10 PWM cycles

    // **************************************************************************
    // the typedefs

    //! \brief Defines the data logging (DATALOG) object
    //!
    typedef struct _DATALOG_OBJ_
    {
    volatile float32_t *iptr[DATA_LOG_BUFF_NUM]; //!< Input: First input pointer
    uint16_t cntr; //!< Variable: Data log counter
    uint16_t size; //!< Parameter: Maximum data buffer
    uint16_t scaleCnt; //!< Variable: datalog skip counter
    uint16_t scaleFactor; //!< Variable: datalog prescale
    } DATALOG_Obj;

    //! \brief Defines the DATALOG handle
    //!
    typedef struct _DATALOG_Obj_ *DATALOG_Handle;

    // **************************************************************************
    // the globals
    extern float32_t datalogBuff1[DATA_LOG_BUFF_SIZE + DATA_SIZE_EXT];
    extern float32_t datalogBuff2[DATA_LOG_BUFF_SIZE + DATA_SIZE_EXT];
    extern float32_t datalogBuff3[DATA_LOG_BUFF_SIZE + DATA_SIZE_EXT];
    extern float32_t datalogBuff4[DATA_LOG_BUFF_SIZE + DATA_SIZE_EXT];
    extern float32_t datalogBuff5[DATA_LOG_BUFF_SIZE + DATA_SIZE_EXT];
    extern float32_t datalogBuff6[DATA_LOG_BUFF_SIZE + DATA_SIZE_EXT];

    //! \brief Defines the DATALOG object
    //!
    extern DATALOG_Obj datalog;
    extern DATALOG_Handle datalogHandle;

    // **************************************************************************
    // the globals

    // **************************************************************************
    // the function prototypes

    //! \brief Initializes the data logger
    //! \param[in] ptr The pointer to memory
    extern DATALOG_Handle DATALOGIF_init(void *pMemory, const size_t numBytes);

    //! \brief Updates the data logger
    //! \param[in] ptr The pointer to memory
    static inline bool DATALOGIF_enable(DATALOG_Handle handle)
    {
    DATALOG_Obj *obj = (DATALOG_Obj *)handle;
    bool enableFlag = false;

    obj->scaleCnt++;

    if(obj->scaleCnt >= obj->scaleFactor)
    {
    enableFlag = true;
    obj->scaleCnt = 0;
    }

    return(enableFlag);
    }


    //! \brief Updates the data logger
    //! \param[in] ptr The pointer to memory
    static inline void DATALOGIF_setPrescalar(DATALOG_Handle handle, uint16_t prescalar)
    {
    DATALOG_Obj *obj = (DATALOG_Obj *)handle;

    obj->scaleFactor = prescalar;

    return;
    }

    //! \brief Updates the data logger
    //! \param[in] ptr The pointer to memory
    static inline void DATALOGIF_update(DATALOG_Handle handle)
    {
    DATALOG_Obj *obj = (DATALOG_Obj *)handle;

    obj->scaleCnt++;

    if(obj->scaleCnt >= obj->scaleFactor)
    {
    if(obj->cntr >= obj->size)
    {
    obj->cntr = 0;
    }

    datalogBuff1[obj->cntr] = (*obj->iptr[0]);
    datalogBuff2[obj->cntr] = (*obj->iptr[1]);
    datalogBuff3[obj->cntr] = (*obj->iptr[2]);
    datalogBuff4[obj->cntr] = (*obj->iptr[3]);
    datalogBuff5[obj->cntr] = (*obj->iptr[4]);
    datalogBuff6[obj->cntr] = (*obj->iptr[5]);

    obj->cntr++;
    obj->scaleCnt = 0;
    }

    return;
    }

    //! \brief Updates the data logger
    //! \param[in] ptr The pointer to memory
    static inline void DATALOGIF_updateWithDMA(DATALOG_Handle handle)
    {
    DATALOG_Obj *obj = (DATALOG_Obj *)handle;
    uint16_t number = obj->size - 1;

    datalogBuff1[obj->size] = (*obj->iptr[0]);
    datalogBuff1[number] = (*obj->iptr[0]);

    datalogBuff2[obj->size] = (*obj->iptr[1]);
    datalogBuff2[number] = (*obj->iptr[1]);

    datalogBuff3[obj->size] = (*obj->iptr[2]);
    datalogBuff3[number] = (*obj->iptr[2]);

    datalogBuff4[obj->size] = (*obj->iptr[3]);
    datalogBuff4[number] = (*obj->iptr[3]);

    datalogBuff5[obj->size] = (*obj->iptr[4]);
    datalogBuff5[number] = (*obj->iptr[4]);

    datalogBuff6[obj->size] = (*obj->iptr[5]);
    datalogBuff6[number] = (*obj->iptr[5]);

    return;
    }
    #endif // DATALOGF6_EN

    //*****************************************************************************
    //
    // Close the Doxygen group.
    //! @}
    //
    //*****************************************************************************

    //*****************************************************************************
    //
    // Mark the end of the C bindings section for C++ compilers.
    //
    //*****************************************************************************
    #ifdef __cplusplus
    }
    #endif

    #endif // end of DATALOG_H definition

    I have attached the modified datalog source file.

    // linker.cmd
    
       .freertosStaticStack : > RAMGS0,          ALIGN(8),   PAGE(1)
       .TI.memcrc     : > APPLICATION_SIGNATURE, ALIGN(8),   PAGE(0)
       .reset          : > RESET,                TYPE = DSECT /* not used, */
       codestart       : > BOOT_SELECT_ENTRY,    ALIGN(8),   PAGE(0)
    
       est_data     	: > RAMLS07
                         LOAD_START(loadStart_est_data),
                         LOAD_END(loadEnd_est_data),
                         LOAD_SIZE(loadSize_est_data)
    
       datalog_data   : > RAMGS0,
                         LOAD_START(loadStart_datalog_data),
                         LOAD_END(loadEnd_datalog_data),
                         LOAD_SIZE(loadSize_datalog_data)

    Could you please point out if I have made any changes by mistake? e.g. how to determine the  DLOG_TRANSFER_SIZE?

    Thanks!

    Siu

  • Hi Siu,

    I can see that the last data point of one of the channel seems to have captured data from other channel.

    Please make sure the memory sections have no overlap to each other. To determine transfer size of the DMA, you can refer to DMA material on C28x Academy.

    Thanks,

    Jiaxin

  • Hi, I switched to test the 4ch dma from the example. 

    C:\ti\c2000\C2000Ware_MotorControl_SDK_5_04_00_00\solutions\universal_motorcontrol_lab\f28p65x\ccs\motor_control

    #if defined(DATALOGF4_EN)
    
    #define DATA_LOG_BUFF_SIZE      400     // Must be integral times of (20)
    #define DATA_SIZE_EXT           2       //
    
    #define DATA_LOG_BUFF_NUM       4       // = 4 for F28003x
    
    #define DLOG_BURST_SIZE         20       // write 200 to the register for
                                             // a burst size of 20
    
    #define DLOG_TRANSFER_SIZE      (3 + (2 * DATA_LOG_BUFF_SIZE / DLOG_BURST_SIZE)) //43

    I can see that the last index value in buffer 2 and 4 are not configured correctly?

    For the memory section, I have confirmed no memory is overlapped. 

    And I have followed the DMA material on C28x Academy to determine the transfer size for the 6 channels dma.

    #define DATA_LOG_BUFF_SIZE      300   // Must be integral times of (20)
    #define DATA_SIZE_EXT                  2
    #define DATA_LOG_BUFF_NUM      6       // 6 channels dma
    #define DLOG_BURST_SIZE            20     // write 300 samples to the register for
                                                                        // a burst size of 20
    #define DLOG_TRANSFER_SIZE      (2 * DATA_LOG_BUFF_SIZE / DLOG_BURST_SIZE) //30

    Could you please help to verify if they are correct?

  • You don't need to change the other parameters, just change DATA_LOG_BUFF_NUM to 6, and increase the buffer array to 6 as well, and assign the DMA channel in hal.h and hal.c as below.

    // DMA for Datalog in hal.h
    #define DMA_DATALOG1_BASE DMA_CH1_BASE
    #define DMA_DATALOG2_BASE DMA_CH2_BASE
    #define DMA_DATALOG3_BASE DMA_CH3_BASE
    #define DMA_DATALOG4_BASE DMA_CH4_BASE

    #define DMA_DATALOG5_BASE DMA_CH5_BASE
    #define DMA_DATALOG6_BASE DMA_CH6_BASE

    hal.c

    obj->dmaChHandle[0] = DMA_DATALOG1_BASE; //!< the DMA Channel handle
    obj->dmaChHandle[1] = DMA_DATALOG2_BASE; //!< the DMA Channel handle
    obj->dmaChHandle[2] = DMA_DATALOG3_BASE; //!< the DMA Channel handle
    obj->dmaChHandle[3] = DMA_DATALOG4_BASE; //!< the DMA Channel handle

    obj->dmaChHandle[4] = DMA_DATALOG5_BASE; //!< the DMA Channel handle

    obj->dmaChHandle[5] = DMA_DATALOG6_BASE; //!< the DMA Channel handle

    And call HAL_setupDMAforDLOG() 6 times to set up DMA channel.