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.

EK-TM4C1294XL: EK-TM4C1294XL

Part Number: EK-TM4C1294XL

Dear Sir/Madam:

I am using a EK-TM4C1294XL board  and need to generate a 5 Mhz signal from one of its GPIO lines.  I am using TIMERA and am able to generate a 1.17Mhz signal through a GPIO line.  My TIMERA ISR only has the two following lines:

g_ui32Flags = 1 - g_ui32Flags;

GPIOPinWrite(GPIO_PORTL_BASE,GPIO_PIN_0, g_ui32Flags);

Is there a way to generate a 5Mhz signal?  I assumed that with a system clock of 120Mhz I would be able to do this but I would like to know if this is possible even if I have to do this in some other fashion.

Thanks for your help.

Jorge Gonzalez

  • Hi,

      In order to increase the frequency you will need to write directly to the GPIO data register as GPIOPinWrite() function is doing some shift operations to calculate the address before writing the data. Your g_ui32Flags = 1 - g_ui32Flags will also take some cycles to do. Look at the disassembly windows and you can find out the assembly instructions generated and derive the number of cycles needed. If you know the exact value and register address to write to, you can reduce the latency by directly writing to the register as follows:

      HWREG(GPIOPx_ADDR, 0x55); // Example writing to an arbitrary address GPIOx_ADDR with value 0x55

    However, you can never be precise on what frequency you will be getting. To get consistent 5Mhz, you should generate a PWM signal. The Timer module can be configured for PWM. All you need is to set up the period and duty cycle that will give you the 5Mhz periodic signal you need.

    See example C:\ti\TivaWare_C_Series-2.2.0.295\examples\peripherals\timer\pwm.c.

    void
    GPIOPinWrite(uint32_t ui32Port, uint8_t ui8Pins, uint8_t ui8Val)
    {
    //
    // Check the arguments.
    //
    ASSERT(_GPIOBaseValid(ui32Port));

    //
    // Write the pins.
    //
    HWREG(ui32Port + (GPIO_O_DATA + (ui8Pins << 2))) = ui8Val;
    }

  • Thanks so much Charles.  I'll try your suggestion.

  • Charles,

    I found a PWM example for the EK-TM4C1294XL board but the fastest period I can produce is in the kilohertz range.  I thought with a 120Mhz system clock I would be able to generate a 5Mhz but I am starting to think that I can't.  Am I correct?

    Thanks for all your help.

    Jorge Gonzalez

  • Here is a 5Mhz PWM example. The PWM period is 5Mhz and the duty cycle varies between 25% and 75%. 

     

    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_memmap.h"
    #include "driverlib/debug.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/pwm.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    
    
    //*****************************************************************************
    //
    // The variable g_ui32SysClock contains the system clock frequency in Hz.
    //
    //*****************************************************************************
    uint32_t g_ui32SysClock;
    
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    void
    __error__(char *pcFilename, uint32_t ui32Line)
    {
    }
    #endif
    
    
    //*****************************************************************************
    //
    // Configure PWM for a 25% duty cycle signal running at 250Hz.
    //
    //*****************************************************************************
    int
    main(void)
    {
        uint32_t ui32PWMClockRate;
    
        //
        // Run from the PLL at 120 MHz.
        // Note: SYSCTL_CFG_VCO_240 is a new setting provided in TivaWare 2.2.x and
        // later to better reflect the actual VCO speed due to SYSCTL#22.
        //
        g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                                 SYSCTL_OSC_MAIN |
                                                 SYSCTL_USE_PLL |
                                                 SYSCTL_CFG_VCO_240), 120000000);
    
    
        //
        // The PWM peripheral must be enabled for use.
        //
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);
    
        //
        // Enable the GPIO port that is used for the PWM output.
        //
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    
        //
        // Configure the PWM function for this pin.
        //
        MAP_GPIOPinConfigure(GPIO_PF2_M0PWM2);
        MAP_GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_2);
    
        //
        // Set the PWM clock to be SysClk / 8.
        //
        MAP_PWMClockSet(PWM0_BASE, PWM_SYSCLK_DIV_1);
        //
        // Use a local variable to store the PWM clock rate which will be
        // 120 MHz / 8 = 15 MHz. This variable will be used to set the
        // PWM generator period.
        //
        ui32PWMClockRate = g_ui32SysClock / 1;
    
        //
        // Configure PWM2 to count up/down without synchronization.
        //
        MAP_PWMGenConfigure(PWM0_BASE, PWM_GEN_1,
                            PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);
    
        //
        // Set the PWM period to 5Mhz.  To calculate the appropriate parameter
        // use the following equation: N = (1 / f) * PWMClk.  Where N is the
        // function parameter, f is the desired frequency, and PWMClk is the
        // PWM clock frequency based on the system clock.
        //
        MAP_PWMGenPeriodSet(PWM0_BASE, PWM_GEN_1, (ui32PWMClockRate / 5000000));
    
        //
        // Set PWM2 to a duty cycle of 25%.  You set the duty cycle as a function
        // of the period.  Since the period was set above, you can use the
        // PWMGenPeriodGet() function.  For this example the PWM will be high for
        // 25% of the time or (PWM Period / 4).
        //
        MAP_PWMPulseWidthSet(PWM0_BASE, PWM_OUT_2,
                             MAP_PWMGenPeriodGet(PWM0_BASE, PWM_GEN_1) / 4);
    
        //
        // Enable PWM Out Bit 2 (PF2) output signal.
        //
        MAP_PWMOutputState(PWM0_BASE, PWM_OUT_2_BIT, true);
    
        //
        // Enable the PWM generator block.
        //
        MAP_PWMGenEnable(PWM0_BASE, PWM_GEN_1);
    
        //
        // Loop forever while the PWM signals are generated.
        //
        while(1)
        {
            //
            // This function provides a means of generating a constant length
            // delay.  The function delay (in cycles) = 3 * parameter.  Delay
            // 2 seconds arbitrarily.
            //
            MAP_SysCtlDelay((g_ui32SysClock * 2) / 3);
    
            //
            // Invert PWM2 signal.
            //
            MAP_PWMOutputInvert(PWM0_BASE, PWM_OUT_2_BIT, true);
    
            //
            // This function provides a means of generating a constant length
            // delay.  The function delay (in cycles) = 3 * parameter.  Delay
            // 2 seconds arbitrarily.
            //
            MAP_SysCtlDelay((g_ui32SysClock * 2) / 3);
    
            //
            // Switch PWM2 signal back to regular operation.
            //
            MAP_PWMOutputInvert(PWM0_BASE, PWM_OUT_2_BIT, false);
        }
    }
    

  • In case you want to use timer module to generate PWM, here is another example for generating 5Mhz PWM. 

    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_gpio.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_timer.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/timer.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    
    
    //*****************************************************************************
    //
    // The g_ui32SysClock contains the system clock frequency
    //
    //*****************************************************************************
    
    uint32_t g_ui32SysClock;
    
    
    //*****************************************************************************
    //
    // Configure Timer3A as a 16-bit PWM with a duty cycle of 66%.
    //
    //*****************************************************************************
    int
    main(void)
    {
        //
        // Set the clocking to run directly from the external crystal/oscillator.
        // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the
        // crystal on your board.
        //
    
        g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                           SYSCTL_OSC_MAIN |
                                           SYSCTL_USE_PLL |
                                           SYSCTL_CFG_VCO_480), 120000000);
    
        //
        // The Timer1 peripheral must be enabled for use.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER3);
    
        //
        // For this example T3CCP0 is used with port B pin 2 or port M pin 2.
        // The actual port and pins used may be different on your part, consult
        // the data sheet for more information.
        // GPIO port B needs to be enabled so these pins can be used.
        // TODO: change this to whichever GPIO port you are using.
        //
    
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOM);
    
        //
        // Configure the GPIO pin muxing for the Timer/CCP function.
        // This is only necessary if your part supports GPIO pin function muxing.
        // Study the data sheet to see which functions are allocated per pin.
        // TODO: change this to select the port/pin you are using
        //
        GPIOPinConfigure(GPIO_PM2_T3CCP0);
    
        //
        // Configure the ccp settings for CCP pin.  This function also gives
        // control of these pins to the SSI hardware.  Consult the data sheet to
        // see which functions are allocated per pin.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinTypeTimer(GPIO_PORTM_BASE, GPIO_PIN_2);
    
        //
        // Configure Timer3A as a 16-bit periodic timer.
        //
        TimerConfigure(TIMER3_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PWM);
    
        //
        // Set the Timer3A load value to (120000000/5000000=24) - 1
        //
        TimerLoadSet(TIMER3_BASE, TIMER_A, g_ui32SysClock / 5000000 - 1);
    
        //
        // Set the Timer3A match value to load value / 2.
        //
        TimerMatchSet(TIMER3_BASE, TIMER_A,
                      TimerLoadGet(TIMER3_BASE, TIMER_A) / 2);
    
        //
        // Enable Timer3A.
        //
        TimerEnable(TIMER3_BASE, TIMER_A);
    
        //
        // Loop forever while the Timer3A PWM runs.
        //
        while(1)
        {
    
        }
    }