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.

AM4379: eCAP PWM duty cycle issue

Part Number: AM4379
Other Parts Discussed in Thread: SYSBIOS

Hi

i am using the eCAP APWM cabability and now i need to change the DutyCycle after every Period.

I have tried it with a hardware interrupt every Period but the Interrupt latency seems to be to slow to handle a Period Time of 1.7us (584kHz).

I just need to overwrite the ECAP_CAP2 compareVal after every period.

what possibilities do i have to achive this ? Any suggestions?

Thx in Advance

  • I use RTOS and PDK 1.0.15 

  • Hi Haxor,

    Have you enabled shadow register mode?

    How is the MMU memory region configured which contains the eCAP registers? Please confirm the memory type is set as Device (instead of Strongly Orderered).

    Regards,
    Frank

  • Hi i think i need some clarrification of the actual problem

    so i added some scopes for your understanding.

      

    Here you see (yellow) my PWM Signal which changes from 80% Duty Cycle to 20% every Period. 

    (blue) you see my actual ISR-Time (set Gpio when entering ISR) for changing the DutyCycle.

    As you can see time to enter ISR is aprox 800ns the Time it takes to handle actual ISR is aprox 2,3us.

    with A period of 5us everything works fine. Now i need Period of 1,7us because i want to connect PL9823 LED's.

    But when i change Period to 1.7us the ISR takes Longer than PWM period and i get unknown behavior:

     

    Here is allready Optimized code of my ISR:

    void APWMPeriodIsr(UArg arg)
    {
    
    HW_WR_REG32((SOC_PWMSS1_ECAP_REG + ECAP_CAP4),SendArrayISR[ArrayCount++]); //write cmp value only
    
    HWREGH(SOC_PWMSS1_ECAP_REG + ECAP_ECCTL2) &= ((uint16_t)(~ECAP_ECCTL2_TSCTRSTOP)); // STOP PWM TSCTR 
    
    HW_WR_REG16(SOC_PWMSS1_ECAP_REG+ECAP_ECCLR, 0xC0);// Clear Interrupt Flags. This only works when counter is stopped!!
    
    
    if (ArrayCount == 24)
    {
        HWREGH(SOC_PWMSS1_ECAP_REG + ECAP_ECEINT) = ((uint16_t)(HWREG(SOC_PWMSS1_ECAP_REG + ECAP_ECEINT) & ~0x0040u)); // Disable Int End of Transmission
        ArrayCount = 0; //reset array count
    }
    else
    {
    
        HWREGH(SOC_PWMSS1_ECAP_REG + ECAP_ECCTL2) |= ((uint16_t)ECAP_ECCTL2_TSCTRSTOP); //Start PWM
      
        HWREGH(SOC_PWMSS1_ECAP_REG + ECAP_ECEINT) |= ((uint16_t)0x0040u); // Enable Int
    }
    
    }

    I need to reduce ISR Time to 1.7us !

    1.Do you think it Is  possible when using Assembler only Code to reduce this Time?

    2. Im thinking of using edma to write the compare Value but not shure if this is efficient for just writing one register, also i dont know how to setup edma for this.

    Thx 

  • Hi Haxor,

    Inspecting your ISR, I see you're using shadow mode (i.e. writing to CMP4 to update the CMP2 value for the next PWM period).

    I have a few questions for you:

    • What is the CPU frequency? By default it should be set to 600 MHz (OPP100) in the AM437x IDK GEL file.
    • Are you using CSL for interrupt handling? How do you register your user ISR (APWMPeriodIsr)? 800 nsec. seems like a slow interrupt response time. At 600 MHz, that's 600e6 * 800e-9 = 480 cycles.
    • Is only the PRDEQ interrupt enabled? Are you driving the GPIO high on ISR entry and low on ISR exit? I don't see the GPIO code in the ISR code.
    • Why do you stop & re-start TSCNT in the ISR? I wasn't aware this was necessary for clearing the interrupt status bits, and I don't recall seeing this in the TRM.
    • This probably won't impact the ISR performance, but why are are you clearing the CMPEQ interrupt?

    2.3 usec. seems too long for the ISR code you've shared (2.3 usec @ 600 MHz is 1380 cycles!). For the normal case (not the end of the array), there are 2x register writes and 3x read-modify writes These are handled via low-level CSL function calls HWREGH, etc. 

    • Have you tried adding timestamps to the ISR code? This would provide independent verification of the GPIO signals & show CPU speed (ARM PMC should run at CPU frequency).
    • Which part of the ISR is taking so long? You could place GPIO & timestamps at different points in the ISR to figure this out.
    • Have inspected the generated assembly?

    I asked about MMU settings since I'm wondering the the eCAP register writes are unnecessarily slowed down because the region is marked as strongly ordered memory.

    >> Do you think it Is possible when using Assembler only Code to reduce this Time?

    Possibly, but I'd check the generated assembly first.

    >> Im thinking of using edma to write the compare Value but not shure if this is efficient for just writing one register, also i dont know how to setup edma for this.

    This would offload the CPU, but I don't think it will provide better performance than the CPU, especially if the CPU is currently dedicated to servicing the eCAP PWM.

    Regards,
    Frank

  • >>>What is the CPU frequency? By default it should be set to 600 MHz (OPP100) in the AM437x IDK GEL file.

    We run at 600Mhz

    >>>Are you using CSL for interrupt handling? How do you register your user ISR (APWMPeriodIsr)? 800 nsec. seems like a slow interrupt response time. At 600 MHz, that's 600e6 * 800e-9 = 480 cycles.

    in .cfg File 

    var Hwi0Params = new Hwi.Params();
    Hwi0Params.instance.name = "APWM_PRD_INTERRUPT";
    Hwi0Params.priority = 1; // Priority 1

    //for id nr see Table TRM 8.1
    Hwi.create(79, "&APWMPeriodIsr",Hwi0Params);

    >>>Is only the PRDEQ interrupt enabled? Are you driving the GPIO high on ISR entry and low on ISR exit? I don't see the GPIO code in the ISR code.

    Yes only PRDEQ is enabled. I removed gpio code for the post but it is as you mentioned.

    >>>Why do you stop & re-start TSCNT in the ISR? I wasn't aware this was necessary for clearing the interrupt status bits, and I don't recall seeing this in the TRM.

    This was necessary for me otherwise  the TSCNT didnt reset.

    >>>This probably won't impact the ISR performance, but why are are you clearing the CMPEQ interrupt?

    I saw when checking Registers CMPEQ flag was also set so i am clearing both for security .

    >>>Have you tried adding timestamps to the ISR code? This would provide independent verification of the GPIO signals & show CPU speed (ARM PMC should run at CPU frequency).

    >>>Which part of the ISR is taking so long? You could place GPIO & timestamps at different points in the ISR to figure this out.

    >>>Have inspected the generated assembly?

    We decided to solve our Problem with Uart for generating the PWM Pulses that  we need for the PL9823 works fine so far and seems to be the better solution because we do not need to handle so many ISR's in terms of processor load. But we are still interested in getting more perfomant  for future ISR Tasks. But right now i have no time to try your Suggestions, sorry for that.

    How do i check the MMU settings which contain the ECAP Registers im not aware of how to do this?

    thx Haxor

  • Hi Haxor,

    >> How do i check the MMU settings which contain the ECAP Registers im not aware of how to do this?

    Where is the code in your application for configuring/enabling the MMU? It's not clear to me if you're using SYS/BIOS or Starterware to configure the MMU.

    I suggest inspecting this code to determine what settings are applied for the memory containing the eCAP registers. It should be possible to inspect the MMU L1 / L2 translation table entries in the CCS Memory Browser.

    For SYS/BIOS:

    • MMU docs are here: <BIOS>/docs/cdoc/ti/sysbios/family/arm/a8/Mmu.html#xdoc-desc
    • MMU module is here: <BIOS>\packages\ti\sysbios\family\arm\a8
    • SYS/BIOS maintains the L1 translation table in the section ti.sysbios.family.arm.a8.mmuTableSection.

    For Starterware:

    • API docs are here: <PDK>\packages\ti\starterware\docs\API_Reference.chm
    • The MMU API is here: <PDK>\packages\ti\starterware\include\mmu.handle
    • Starterware expect the application to provide memory for the translation tables (see MMUInit()).

    If you don't know where the MMU is being configured in your application, or where the MMU translation tables reside in memory, you could read the Translation Table Base Registers (TTRB0 and TTRB1). Since these are CP15 registers, they aren't directly accessible in CCS, so you'd need to write assembly code to read them into ARM core registers. Please see ARM Cortex-A Series v4.0 Programmer's guide (DEN0013D_cortex_a_series_PG.pdf), Ch. 9: Memory Management Unit.

    Regards,
    Frank