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.

AM2732-Q1: AM2732: HWA Multiple Parameter Chaining

Part Number: AM2732-Q1

Hi,

I have a two stage pipeline on HWA (FFT/Vector Multiplication + IFFT). FFT is triggered with HWA_TRIG_MODE_DMA an the second is triggered by HWA_TRIG_MODE_IMMEDIATE. My intention is the second stage to run automatically right after FFT.
In common config i set:
paramStartIdx = 0
paramStopIdx = 1
numLoops =1
And i programmed both stage once with HWA_configParamSet at init.

At runtime i call HWA_reset() once and then i trigger once the FFT channel with HWA_setDMA2ACCManualTrig(), expecting the state machine to run 0 then 1 and raise a single done interrupt at the end. 

The problem is that FFT stage executes correctly, but the seep never advances to stage 1 (done ISR never fires) and the DSP hangs waiting on it. If i drop the sweep and trigger each paramset individually with its own HWA_setDMA2ACCManualTrig() (wiaitng on the done ISR between them), both stages run correctly and ISR fires each time. So the parameters are configuredcorrectly and only the automatic advnace from stage 0 to 1 fails.

My question is that for an automated run after FFT stage(DMA triggered), is setting triggerMode = HWA_TRIG_MODE_IMMEDIATE on IFFT stage sufficient, or an additional configuraiton is required ?

Best Regards,
George Sarantakis

  • Hi George,

    Which SDK are you using for your application, the mmWaveSDK or the MCU+ SDK? Which version of the SDK are you using? What is the HW platform are you using?

    Best regards,

    Ming

  • Hello Ming,

    I am using the mcu_plus_sdk_am273x_11_02_00_25 for this project

    Best regards,

    George

  • Hi George,

    Since you are doing the chained HWA operations, you will need to do not only the HWA parameter set (HWA_configParamSet), but also the HWA common config (HWA_configCommon). Please see the HWA compression example in HWACompression_config() in C:\ti\mcu_plus_sdk_am273x_11_02_00_25\examples\drivers\hwa\hwa_bfp_compression\hwa_bfp_compression.c for details.

    Best regards,

    Ming

  • Hi MIng,

    I am already using HWA_configCommon() with these configurations:

     e->commonCfg.configMask                 = HWA_COMMONCONFIG_MASK_STATEMACHINE_CFG | HWA_COMMONCONFIG_MASK_TWIDDITHERENABLE | HWA_COMMONCONFIG_MASK_LFSRSEED;

        e->commonCfg.fftConfig.lfsrSeed         = 11U;
        e->commonCfg.fftConfig.twidDitherEnable = 1U;
        e->commonCfg.numLoops                   = 1U;
        e->commonCfg.paramStartIdx              = 0U;
        e->commonCfg.paramStopIdx               = 1U;
        
        status = HWA_configCommon(e->hwaHandle, &e->commonCfg);
        DebugP_assert(status == SystemP_SUCCESS);

    StartIdx refers to the FFT and StopIdx refers to the IFFT + vector multiplication operation.

    I went through the example and the only difference is that a HWA_reset() is never used.
    My questions are:

    1.) Does HWA_reset() clear the state machine configuration written HWA_configCommon()? If so, is HWA_reset() simply not meant to be used in a sweep flow as the example implies or is there another supported way to restore the range before a chained trigger ?

    2.) Without HWA_reset() between triggers what is the correct way to re-arm the sweep for the next iteration in a repeating pipeline ?

    Best regards,
    George Sarantakis

  • Hi George,

    If you look the HWAFFT_ifftCmplxToRealFloat() in C:\ti\mcu_plus_sdk_am273x_11_02_00_25\examples\drivers\hwa\common\hwa_fft.c, you will see that the HWA_reset () is used before the HWA_setDMA2ACCManualTrig(). I think it is OK to use the HWA_Reset() before the trigger.

    Did you mean that even you used the common configure, you still cannot get the first HWA operation started? If so, can you try to use manual trigger to do so? just for testing purpose.

    Best regards,

    Ming

  • Hi Ming,

    Thank you for the response and the pointers.

    Let me restate simply what I'm trying to do and what's failing, since i want to make sure we're on the same page.
    My goal is to trigger the HWA once, have run the FFT and then automatically run the IFFT stage and get a single done signal at the end of both instead of having the DSP triggering each stage separately. The setup is two parameter sets configured with HWA_configParamSet at init. Common config has paramStartIdx = 0, paramStopIdx = 1 and numLoops = 1. FFT is DMA triggered and IFFT stage is set to IMMEDIATE(expecting to start right after FFT finishes). In reality, what it actually happens is FFT being triggered once, executes and runs correctly but the IFFT stage never runs on its own no matter what i've tried (DMA trigger, Software trigger). The only way i can get the IFFT stage to run is if i trigger it myself separately myself as i do for the FFT. So my config matches what BFP example suggests, but the HWA doesn't chain, it just runs the one stage i manually triggered.


    I thought that HWA_reset() was the issue, but it doesn't clear the configurations from HWA_configCommon, they remain intact at trigger time.

    What am i missing that would make the second stage actually run automatically after the first ? Is there some additional setup beyond what's in HWA_configCommon/HWA_configParamSet, or is automatic chaining only possible if the trigger comes from an EDMA event rather than manual/software trigger like I'm using ?

    Best regards,
    George Sarantakis

  • Hi George,

    I noticed that in the BFP example, the two chained HWA operations are using the local memory banks only (for source and destination addresses). It is sort of make sense, because the HWA cannot handle the data copy to/from the HWA to system memory. The chained HWA operations have to be based on the local memory (CSL_DSS_HWA_DMA0_RAM_BANKx_BASE). 

    Can you share the code for setting up the HWA operation for IFFT?

    Best regards,

    Ming

  • Hi Ming,

    Here is the function that sets up both operations.

    {
        int32_t status;
        ComplexOP *ops[2];
        int32_t i;
        
        memset(e, 0, sizeof(*e));
        
        e->hwaHandle = hwaHandle;
        
        e->edmaBaseAddr = EDMA_getBaseAddr(edmaHandle);
        e->edmaRegionId = EDMA_getRegionId(edmaHandle);
        
        DebugP_assert(e->edmaBaseAddr != 0U);
        DebugP_assert(e->edmaRegionId < SOC_EDMA_NUM_REGIONS);

        e->fft.paramIdx      = ST_FFT; /* 0 */
        e->fft.fftEnable     = 1U;
        e->fft.isInverse     = 0U;
        e->fft.rdMemBankAddr = CSL_DSS_HWA_DMA0_RAM_BANK0_BASE;
        e->fft.wrMemBankAddr = CSL_DSS_HWA_DMA0_RAM_BANK1_BASE;


        e->ifft.paramIdx      = ST_IFFT; /* 1 */
        e->ifft.fftEnable     = 1U;
        e->ifft.isInverse     = 1U;
        e->ifft.rdMemBankAddr = CSL_DSS_HWA_DMA0_RAM_BANK1_BASE;
        e->ifft.wrMemBankAddr = CSL_DSS_HWA_DMA0_RAM_BANK2_BASE;



        ops[0] = &e->fft;
        ops[1] = &e->ifft;

        /* Allocate EDMA and config each param set */

        for(i = 0; i < 2; i++)
        {
            ComplexOP *op = ops[i];
            op->rdDmaCh   = EDMA_RESOURCE_ALLOC_ANY;
            op->wrDmaCh   = EDMA_RESOURCE_ALLOC_ANY;
            op->rdTcc     = EDMA_RESOURCE_ALLOC_ANY;
            op->wrTcc     = EDMA_RESOURCE_ALLOC_ANY;
            op->rdParamId = EDMA_RESOURCE_ALLOC_ANY;
            op->wrParamId = EDMA_RESOURCE_ALLOC_ANY;

            status  = EDMA_allocDmaChannel(edmaHandle, &op->rdDmaCh);
            DebugP_assert(status == SystemP_SUCCESS);

            status = EDMA_allocDmaChannel(edmaHandle, &op->wrDmaCh);
            DebugP_assert(status == SystemP_SUCCESS);
            
            status  = EDMA_allocTcc(edmaHandle, &op->rdTcc);
            DebugP_assert(status == SystemP_SUCCESS);

            status = EDMA_allocTcc(edmaHandle, &op->wrTcc);
            DebugP_assert(status == SystemP_SUCCESS);

            status  = EDMA_allocParam(edmaHandle, &op->rdParamId);
            DebugP_assert(status == SystemP_SUCCESS);

            status = EDMA_allocParam(edmaHandle, &op->wrParamId);
            DebugP_assert(status == SystemP_SUCCESS);
            

            EDMA_configureChannelRegion(e->edmaBaseAddr, e->edmaRegionId, EDMA_CHANNEL_TYPE_DMA, op->rdDmaCh, op->rdTcc, op->rdParamId, EDMA_EVENT_QUEUE);
            EDMA_configureChannelRegion(e->edmaBaseAddr, e->edmaRegionId, EDMA_CHANNEL_TYPE_DMA, op->wrDmaCh, op->wrTcc, op->wrParamId, EDMA_EVENT_QUEUE);

            EDMA_ccPaRAMEntry_init(&op->rdDmaParam);
            op->rdDmaParam.linkAddr = 0xFFFFU;
            
            EDMA_ccPaRAMEntry_init(&op->wrDmaParam);
            op->wrDmaParam.linkAddr = 0xFFFFU;

            buildParamset(op, FFT_SIZE); // this function configures the operaitons (FFT,IFFT)

            status = HWA_configParamSet(e->hwaHandle, op->paramIdx, &op->paramCfg, NULL);
            DebugP_assert(status == SystemP_SUCCESS);
        }
         
        /* Setup Output Interrupt */
        gOutIntrObj.tccNum  = e->ifft.wrTcc;
        gOutIntrObj.cbFxn   = &outputEdmaISR;
        gOutIntrObj.appData = NULL;
        status = EDMA_registerIntr(gEdmaHandle[0], &gOutIntrObj);
        DebugP_assert(status ==  SystemP_SUCCESS);

        EDMA_enableEvtIntrRegion(e->edmaBaseAddr, e->edmaRegionId, e->ifft.wrDmaCh);
          
        memset(&e->commonCfg, 0 ,sizeof(e->commonCfg));

        e->commonCfg.configMask                 = HWA_COMMONCONFIG_MASK_STATEMACHINE_CFG | HWA_COMMONCONFIG_MASK_TWIDDITHERENABLE | HWA_COMMONCONFIG_MASK_LFSRSEED;
        e->commonCfg.fftConfig.lfsrSeed         = 11U;
        e->commonCfg.fftConfig.twidDitherEnable = 1U;
        e->commonCfg.numLoops                   = 1U;
        e->commonCfg.paramStartIdx              = 0U;
        e->commonCfg.paramStopIdx               = 1U;
        
        status = HWA_configCommon(e->hwaHandle, &e->commonCfg);
        DebugP_assert(status == SystemP_SUCCESS);

        status = SemaphoreP_constructBinary(&e->doneSem, 0U);
        DebugP_assert(status == SystemP_SUCCESS);
        
        status = HWA_enableDoneInterrupt(e->hwaHandle, 0U, ComplexFFTDoneISR, NULL);
        DebugP_assert(status == SystemP_SUCCESS);

        return SystemP_SUCCESS;
    }

    Best regards,
    George Sarantakis

  • Hi George,

    In the above code section, I did not see where you set the .triggerMode for neither FFT nor IFFT.

    Also, I did see where you set the .source.srcAddr or .dest.dstAddr.

    Please refer to HWAFFT_init() in C:\ti\mcu_plus_sdk_am273x_11_02_00_25\examples\drivers\hwa\common\hwa_fft.c for details.

    Best regards

    Ming