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.

CCS/TMS570LC4357: N2HEt HTU doesn't generate proper PWM.

Part Number: TMS570LC4357
Other Parts Discussed in Thread: HALCOGEN

Tool/software: Code Composer Studio

Hi there

I was trying to use project SPNA217  - "Sine Wave Generation Using PWM With Hercules N2HET and HTU" 

I was imported  the project into new CCS7.0  it was used Launchboard with this TMS570LC43. 

Halcogen for initial setup 04.05.02.

I was trying to generate PWM.  Without effect. 

In Debug mode right after the   hetREG1->REQENS = 1 ;  PWM stops ....   of course PWM should has different duty cycle but it doesn't.

There is full project folder .zip   CCS7.0 / halcogen files/ HET project   etc.

2311.Sine_wave_PWM2.zip

  

  • Hello Marcin,

    Thanks for posting your question and associated project. I'll have a look at it and get back with you when I've found the root cause.
  • I've just realized that there is newer Halcogen 04.06.00, I 've used it, unfo;rtunatelly the same results , no proper PWM generation.
  • Marcin,

    You state that you were trying to generate the PWM without effect or that it wasn't generating the PWM but you also state that it stropped generating the PWM in debug mode right after the hetREG1->REQEN=1. So before it stopped was it working as intended? Did it stop when you hit a break point in the debug mode? If so, did you enable continue on suspend so the HET will continue to generate the PWM even if the CPU suspends?
  • First, I would strongly suggest getting a LS1224 launchpad (only ~$20) so that you can run the Appnote code as-is.

    Now if you had to port it to the LC4357 then that's ok but there are many many screens in HalCoGen and the .hcg/dil file for a 1224 don't
    load into a LC4357 project. And it's not really safe to 'edit' the file manually.

    So you have a lot of configuration to work through and it's easy to make a mistake when filling out pages of GUI.

    This way if you get a 1224 you'd have some reference that should work as-is and you can compare against it.

    Now the LC4357 has Cache - so this brings about additional complexities.

    The default in HalCoGen is to have the RAM Write-Back type. That doesn't work so well when putting data into L2SRAM for DMA (including HTU) to pick up because Write Back type cache doesn't evict the data until it's necessary to, so when you write the table for the HTU to pick up, the writes may be stuck in Cache and not yet written back to L2SRAM. The DMA can't read from the cache (only the L2SRAM) so it might read '0's or stale data instead.

    Try disabling cache or changing the type to write through (WT) instead of write-back (WB).

    Longer term you would want to make one area of SRAM write-through for buffers that hold DATA to go to DMA, and another area write back for the rest of the data (like stack, global variables etc) that the CPU processes but isn't sharing w. the DMA.. This is because WB will be a little faster normally. [which is why it is the default for HalCoGen because the casual user is more likely to run a benchmark of some algo. when they are getting started than to delve into DMA or HTU...]

    Best Regards,
    Anthony
  • Ok  I try to clarify step by step:

    as PWM i'm using port   N2HET1_09    which is mapped  as  V7 - this is Pin J1.10 (Hercules TMS570LC43x LaunchPad Development Kit)   this is set in HAlcogen ,

    my main function : 

    int main(void)
    {
            /* initialize HTU1 based on HalCoGen settings */
            htuInit();
    
            /* initialize NHET1 based on HalCoGen settings */
            hetInit();
    
            /* Configure additional settings of NHET1 based on the macros settings */
            configNHET1();
    
            while(1);
    
      //  return 0;
    }

    function htuINIT   

    void htuInit(void){
        /* DCP0 CPx element count = 1, frame count = SAMPLE_SIZE */
        htuDCP1->ITCOUNT  = 0x00010000 + SAMPLE_SIZE;
    
        htuDCP1->IHADDRCT = (htuDCP1->IHADDRCT & 0x0) |
                                     0x1 << 23 | // DIR
                                     0x0 << 22 | // SIZE
                                     0x0 << 21 | // ADDMH
                                     0x0 << 20 | // ADDFM
                                     0x1 << 18 | // TMBA
                                     0x0 << 16 | // TMBB
                                     0x28 << 0;  // IHADDR
    
    
        /* DCP0 CPA start address of source buffer */
        htuDCP1  -> IFADDRA = (unsigned int)sine_table;
    
        /* enable DCP0 CPA */
        htuREG1 ->CPENA = 0x00000001;
        /* enable HTU */
        htuREG1 ->GC    = 0x00010000;
    }

    function hetInit comes from HalcoGEn 

    void hetInit(void)
    {
        /** @b initialize @b HET */
    
        /** - Set HET pins default output value */
        hetREG1->DOUT = (uint32)((uint32)0U << 31U)
                      | (uint32)((uint32)0U << 30U)
                      | (uint32)((uint32)0U << 29U)
                      | (uint32)((uint32)0U << 28U)
                      | (uint32)((uint32)0U << 27U)
                      | (uint32)((uint32)0U << 26U)
                      | (uint32)((uint32)0U << 25U)
                      | (uint32)((uint32)0U << 24U)
                      | (uint32)((uint32)0U << 23U)
                      | (uint32)((uint32)0U << 22U)
                      | (uint32)((uint32)0U << 21U)
                      | (uint32)((uint32)0U << 20U)
                      | (uint32)((uint32)0U << 19U)
                      | (uint32)((uint32)0U << 18U)
                      | (uint32)((uint32)0U << 17U)
                      | (uint32)((uint32)0U << 16U)
                      | (uint32)((uint32)0U << 15U)
                      | (uint32)((uint32)0U << 14U)
                      | (uint32)((uint32)0U << 13U)
                      | (uint32)((uint32)0U << 12U)
                      | (uint32)((uint32)0U << 11U)
                      | (uint32)((uint32)0U << 10U)
                      | (uint32)((uint32)1U << 9U)
                      | (uint32)((uint32)0U << 8U)
                      | (uint32)((uint32)0U << 7U)
                      | (uint32)((uint32)0U << 6U)
                      | (uint32)((uint32)0U << 5U)
                      | (uint32)((uint32)0U << 4U)
                      | (uint32)((uint32)0U << 3U)
                      | (uint32)((uint32)0U << 2U)
                      | (uint32)((uint32)0U << 1U)
                      | (uint32)((uint32)0U << 0U);
    
        /** - Set HET pins direction */
        hetREG1->DIR = (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000200U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U;
    
        /** - Set HET pins open drain enable */
        hetREG1->PDR = (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U;
    
        /** - Set HET pins pullup/down enable */
        hetREG1->PULDIS = (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U
                        | (uint32) 0x00000000U;
    
        /** - Set HET pins pullup/down select */
        hetREG1->PSL = (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U;
    
        /** - Set HET pins high resolution share */
        hetREG1->HRSH = (uint32) 0x00008000U
                      | (uint32) 0x00004000U
                      | (uint32) 0x00002000U
                      | (uint32) 0x00001000U
                      | (uint32) 0x00000000U
                      | (uint32) 0x00000000U
                      | (uint32) 0x00000000U
                      | (uint32) 0x00000000U
                      | (uint32) 0x00000000U
                      | (uint32) 0x00000000U
                      | (uint32) 0x00000000U
                      | (uint32) 0x00000000U
                      | (uint32) 0x00000008U
                      | (uint32) 0x00000004U
                      | (uint32) 0x00000002U
                      | (uint32) 0x00000001U;
    
        /** - Set HET pins AND share */
        hetREG1->AND = (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U;
    
        /** - Set HET pins XOR share */
        hetREG1->XOR = (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U
                     | (uint32) 0x00000000U;
    
    /* USER CODE BEGIN (1) */
    /* USER CODE END */
    
        /** - Setup prescaler values
        *     - Loop resolution prescaler
        *     - High resolution prescaler
        */
        hetREG1->PFR = (uint32)((uint32) 6U << 8U)
                    | ((uint32) 0U);
    
    
       /** - Parity control register
        *     - Enable/Disable Parity check
        */
        hetREG1->PCR = (uint32) 0x00000005U;
    
        /** - Fill HET RAM with opcodes and Data */
        /** - "x" in "HET_INITx_PST" denote the HET module Instance
        *      Valid range of x - 0 to 9
        *      For HET1 module x = 0
        *      Refer HET assembler User guide for more Info
        */
        /*SAFETYMCUSW 94 S MR:11.1,11.2,11.4 <APPROVED> "HET RAM Fill from the table - Allowed as per MISRA rule 11.2" */
        /*SAFETYMCUSW 95 S MR:11.1,11.4 <APPROVED> "HET RAM Fill from the table - Allowed as per MISRA rule 11.2" */
        /*SAFETYMCUSW 95 S MR:11.1,11.4 <APPROVED> "HET RAM Fill from the table - Allowed as per MISRA rule 11.2" */
        (void)memcpy((void*)hetRAM1, (void*)HET_INIT0_PST, sizeof(HET_INIT0_PST));
    
        /** - Setup interrupt priority level */
        hetREG1->PRY = 0xFFFFFFFF;
    
        /** - Enable interrupts */
        hetREG1->INTENAC = 0xFFFFFFFFU;
        hetREG1->INTENAS = (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U
                         | (uint32) 0x00000000U;
    
    
       /** - Setup control register
        *     - Enable output buffers
        *     - Ignore software breakpoints
        *     - Master or Slave Clock Mode
        *     - Enable HET
        */
        hetREG1->GCR = ( 0x00000001U 
                       | (uint32)((uint32)1U << 24U)
    	               | (uint32)((uint32)1U << 16U)
                       | (0x00020000U));
    
    
    /* USER CODE BEGIN (4) */
    /* USER CODE END */
    
    }

    function htuINITConfigNHET1(): 

    void configNHET1()
    {
        /* configure the LRP prescaler, the hr is always 1 and lr can be
         * either 16, 32, 64 or 128 */
        hetREG1->PFR = LRPFC << 8;
    
      //  calculate_ecmp_compare();  removed  but the sine_table table is declared as:   uint32 sine_table[SAMPLE_SIZE] = {1,20000,5000,5,30};
      
    
        /* Enable DMA request on channel 0 of HTU. In the CNT instruction, the
         * DMA request is asserted to channel 0 of the HTU module */
        hetREG1->REQENS = 1 ;
    
        /* Set the selected pin to output. */
        hetREG1->DIR = (1 << NHET1_PIN_PWM) ;
    
        /* Load the PWM period based on the defined macro to the CNT instruction */
        hetRAM1->Instruction[pHET_L00_0].Control = (uint32)(CNT_MAX_PERIOD - 1) |
        (hetRAM1->Instruction[pHET_L00_0].Control & 0xFFFD0000);
    
        /* Configure the pin number to output the PWM */
        hetRAM1->Instruction[pHET_L01_0].Control =
                (hetRAM1->Instruction[pHET_L01_0].Control & 0xFFFFE0FF) |
                (NHET1_PIN_PWM << 8);
    
    }
    
    

    function htuINITConfigNHET1(): 

    So, when it executes
    hetREG1->PFR = LRPFC << 8;
    the PWM is started (but duty cycle is const) it doesn't change duty cycle




    when
    hetREG1->REQENS = 1 ;
    then PWM stops .. and thats all ;-(

    When I try to execute without Debug mode there are only two PWM pulses. In my opinion the change of duty cycle (picture below) is not related with DMA/HTU functioning, but rather with change of configuration.



    I think that right now I need to rather take care of memory cache problems what mentioned.

    Regards MArcin.

  • Finally the solution is to turn off the cache from halcogen.
    now it is working, thank you for your help.
    The question is :
    -does the turning cache off much decrease the performance ?
    - is there any other solution ?

    Thank you,
    regard MArcin.
  • Yes turning off the cache will kill your performance.

    Please read the above post. You've got two basic options:
    1) configure some area of RAM as Write-Through type instead of Write-Back.
    2) manually force a write back with cache-maintenance & barriers after you write the buffers that DMA should pick up.

    1) is probably the simplest & least impact so I would suggest trying this.
  • so  I'm  trying do next  step. Generate 2  PWM's   using HTU / DMA.  Unfortunatelly only one PWM generate properly. The next one doesn't change the duty cycle.

    I've modified the   project SPNA217. "Sine Wave Generation Using PWM  With HErcules" 

    ...

    According to Anthony suggestion I've created new post 

    This is moved here : 

    Marcin.