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.

MSP432P401R: High Speed timer for PWM

Part Number: MSP432P401R

Hello,

We are developing a lighting product using the MSP432 microcontroller.

For this application we need a high speed PWM timer.  The timer needs to operate at 250kHz or possibly higher. Also we will be running a UART which is also running a 250kHz.

This board is using a 48MHz crystal.  This is a very capable controller but so far I have not been able to get the timer to run faster than about 60 kHz.  Is there a limit to how fast the timer can operate?

 Can you give me some advice on setting the clocks and timers to achieve the 250kHz or higher?  Current settings are listed below.

Please provide suggestions...

Thank you.  Christian Cochran

void clockInit(void)
{
    /* 2 flash wait states, VCORE = 1, running off DC-DC, 48 MHz */

    FlashCtl_setWaitState(FLASH_BANK0, 2);
    FlashCtl_setWaitState(FLASH_BANK1, 2);

    PCM_setPowerState(PCM_AM_DCDC_VCORE1);
    CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_48);    // was CS_DCO_FREQUENCY_48

    CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, 1);                // was CS_MCLK, CS_DCOCLK_SELECT, 1
    CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, 1 );             // was CS_SMCLK, CS_DCOCLK_SELECT, 1
    CS_initClockSignal(CS_HSMCLK, CS_DCOCLK_SELECT, 1);           // was CS_HSMCLK, CS_DCOCLK_SELECT, 1  CS_CLOCK_DIVIDER_2

    return;
}

 

 

const Timer_A_UpModeConfig upA1Config = {  // PWM

        TIMER_A_CLOCKSOURCE_SMCLK,              // SMCLK Clock Source

        TIMER_A_CLOCKSOURCE_DIVIDER_2,          // SMCLK/2

        50,                                  // timer period

        TIMER_A_TAIE_INTERRUPT_DISABLE,         // Disable Timer interrupt

        TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE ,    // Enable CCR0 interrupt

        TIMER_A_DO_CLEAR                        // Clear value

};

  • Hello,

    The following is an adaptation from the example found here:

    /* --COPYRIGHT--,BSD
     * Copyright (c) 2017, Texas Instruments Incorporated
     * All rights reserved.
     *
     * 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.
     * --/COPYRIGHT--*/
    /*******************************************************************************
     * MSP432 Timer_A - Variable PWM
     *
     * Description: In this example, the Timer_A module is used to create a precision 
     * PWM with 50% duty cycle
     *
     *                MSP432P401
     *             ------------------
     *         /|\|                  |
     *          | |                  |
     *          --|RST           |
     *            |                  |
     *            |                  |
     *            |            P2.4  |--> Output PWM
     *            |                  |
     *            |                  |
     *
     *******************************************************************************/
    /* DriverLib Includes */
    #include <ti/devices/msp432p4xx/driverlib/driverlib.h>
    
    /* Standard Includes */
    #include <stdint.h>
    #include <stdbool.h>
    
    //![Simple Timer_A Config]
    /* Timer_A PWM Configuration Parameter */
    Timer_A_PWMConfig pwmConfig =
    {
            TIMER_A_CLOCKSOURCE_SMCLK,
            TIMER_A_CLOCKSOURCE_DIVIDER_1,
            95,  //  24Mhz/(N+1) = 250k
            TIMER_A_CAPTURECOMPARE_REGISTER_1,
            TIMER_A_OUTPUTMODE_RESET_SET,
            48   // 50% duty cycle
    };
    //![Simple Timer_A Config]
    
    int main(void)
    {
        /* Halting the watchdog */
        MAP_WDT_A_holdTimer();
    
        //![Simple Timer_A Example]
        /*
         * Revision C silicon supports wait states of 1 at 48Mhz
         */
        MAP_PCM_setCoreVoltageLevel(PCM_VCORE1);
        MAP_FlashCtl_setWaitState(FLASH_BANK0, 1);
        MAP_FlashCtl_setWaitState(FLASH_BANK1, 1);
    
        /*
         * Setting up clocks
         * MCLK = MCLK = 48MHz
         * SMCLK = MCLK/2 = 24Mhz
         * ACLK = REFO = 32Khz
         */
        MAP_CS_setDCOFrequency(48000000);
        MAP_CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);
        MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_2);
        MAP_CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);
        /* Configuring GPIO2.4 as peripheral output for PWM  */
        MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN4,
                GPIO_PRIMARY_MODULE_FUNCTION);
        MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig);
        //![Simple Timer_A Example]
        /* Sleeping when not in use */
        while (1)
        {
            MAP_PCM_gotoLPM0();
        }
    }
    

    Regards,

    Chris

  • Sorry, I forgot to mention that if you want to use the external crystal then setup the clocks as follows:

    CS_setExternalClockSourceFrequency(32000,48000000);
    hfxtResult = CS_startHFXTWithTimeout(false,100000);
    if(hfxtResult == true)
    {
      /* Initializing MCLK to HFXT (effectively 48MHz) */
      MAP_CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);
      MAP_CS_initClockSignal(CS_SMCLK, CS_HFXTCLK_SELECT, CS_CLOCK_DIVIDER_2);
      MAP_CS_initClockSignal(CS_MCLK, CS_HFXTCLK_SELECT, CS_CLOCK_DIVIDER_1);
      //![Simple CS Config]
    }
    else
    {
      while(1); // HFXT failed
    }

    Regards,
    Chris

  • Chris,
    Thank you very much for the detailed suggestion and setup code.
    Glad to see the PWM will run at 250kHz. But, I am running PWM on up to 6 output pins and need to do separate PWM for each.
    Looks like we can only set up PWM on 4 timers.. right?

    What I need is a timer interrupt TA1_0_IRQHandler to operate at 250kHz. I have 6 bits that will be set in the timer as determined in the application code.

    Can you show me Timer_A_UpModeConfig settings to run the interrupt at 250kHz (calling TA1_0_IRQHandler every 4uS).
    Thanks,
    Christian
  • "calling TA1_0_IRQHandler every 4uS"

    it may make sense to understand the overall design goals and how kind of drain isr overhead can be at that kind of rate.
  • Danny,

    The application is a 5 color LED dimmer controller.  I understand that running the ISR that fast will occupy much of the processor time.  But that ISR is the priority of what the controller does for this application.

    So please let me know, can the TA1_0_IRQHandler ISR operate at 250kHz and what are the settings to achieve that?  I have a working prototype that is operating at about 66kHz now. 

    Thank you for your assistance,

    Christian

  • Is 66kHz using Chris Sterzik's code or yours? 66kHz*51 sounds suspiciously close to 3MHz, the SMCLK speed after Reset, so my first thought is that your clock isn't being set appropriately. It's possible to get the SMCLK signal on P7.0 if you have a scope to read it with.

    I'm pretty sure you can run an ISR at 250kHz, but you need to not try to do much. At 48MHz, 4us is 192 MCLKs. Estimate maybe 30 clocks to get in/out of the ISR, then de-rate by say 25% for Flash wait states, and you're left with 120 MCLKs. Managing 4x streams gives 120/4=30 MCLKs for each stream, which isn't a whole lot of time for decisions.

    I'll point out that (despite conventional wisdom) your CPU will be close enough to saturation that the main()/ISR split for making decisions won't really be relevant. You might as well make all the decisions in the ISR, or do all the work in main (i.e.polling).

    There may be a DMA trick possible here. That would give you a marginal improvement, but you're still left with making 4x decisions every 192 clocks.
  • "can the TA1_0_IRQHandler ISR operate at 250kHz and what are the settings to achieve that?"

    in the simplest case, it can run much higher than 250Khz - you just don't have much processing power left for anything else.

    however, whether you can do that in this particular design of yours is entirely up to your design -> which we know nothing of.
  • Yes. I do understand the CPU will be close to max'd out. This is the main function of the application so that is ok and what I really need.
    Please let me know the setting of the timer configuration and clocks to get to the 250kHz. I can take care of the housekeeping of other items.

    The DMA sounds like a nice suggestion. I have done DMA on the MSP432 for the Uart so I am willing to take a look at that too.

    Thanks,
    Christian
  • Yes. Please let me know how to set the timer for 250kHz and above.

    Thank you. Christian
  • Didn't Chris Sterzik already do that? All you need to do is replicate what he did for one channel out to four.
  • "Please let me know how to set the timer for 250kHz and above."

    if you didn't know that, how did you write the code you posted earlier?????
  • Christian,
    The upmode configuration API can be found here:
    dev.ti.com/.../group__timera__api.html

    The configuration structure is defined here:
    dev.ti.com/.../struct___timer___a___up_mode_config.html

    You would use CCR0 to define the period and the CCR1,2, 3, and 4 to define the PWM duty cycles. I would recommend simply copying the APIs and applying to another A5 timer to get the remaining 2 outputs for 6 in total. There are 4 instances of TimerA, each with ability to provide 4 PWMs. In one of the up mode configurations you would enable the CCR0 interrupt and it would be during this interrupt that you would update all 6 PWMs.

    I think that this example would be a good place to start. You would need to replace the up/down config with simply the up config, add another configuration for the second timer which would run from the same source clock, and finally add the interrupt service routine. Remember that there is an extra clock cycle when going from CCR0 to 0, so if SMCLK is 24Mhz, a timer period of 95 counts would result in 250Khz (24M/(95+1)).

    dev.ti.com/.../

    Regards,
    Chris
  • Excellent.  This is very good suggestion.  The 4 PWMs for each Timer sounds like the solution. 

    I am out of town for the week, and I will try this as soon as I return.

    Thank you,  Christian

  • Chris,
    Thank you very much for the guidance. Using the mapped pins for TA1.1 TA1.2 TA1.3 TA1.4 and TA0.1 TA0.2 did the trick.
    Christian

**Attention** This is a public forum