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.

AM335x: PWM on DMTimer

 Hi All,

I want to generate PWM using timer4, for this what should i do? Currently I've in dts files

1.               timer4: timer@48044000 {
                        compatible = "ti,am335x-timer";
                        reg = <0x48044000 0x400>;
                        interrupts = <92>;
                        ti,hwmods = "timer4";
                        clocks = <&timer4_fck>;
                        clock-names = "fck";
                        ti,timer-pwm;
                };  


2. Pinmux for XDMA_EVENT_INTR0/TIMER4/CLKOUT1/SPI1_CS1/PR1_PRU1_PRU_R31_16/EMU2/GPIO0_19

0x1B0 (PIN_OUTPUT | MUX_MODE1)  /* xdma_event_intr0.timer4_mux1  */

3. duty cycle from 0%-100%.  Frequency approx. 100 kHz.

Regards,

Gangadhar

  • Can you be more specific? What exactly is your question?

  • generate squarewave with different duty cycles using timer4 on pin,

    XDMA_EVENT_INTR0/TIMER4/CLKOUT1/SPI1_CS1/PR1_PRU1_PRU_R31_16/EMU2/GPIO0_19

    Regards,

    Gangadhar

  • I don't think there is a ready Linux example for this, you will probably have to write your own code.

  • Gangadhar,

    Here is an example script to configure Timer4 in PWM mode.

    Hope this helps.

     

    -Mark

  • Hi Mark,
    I used the script file provided by you to generate PWM on TIMER4. The only change I did was to use CLK_M_OSC clock instead of 32kHz clock. However I could only see timer pin going low momentarily(I think this happens when timer is configured, same response with 32kHz clock and CLK_M_OSC clock). I referred TRM Section 20.1.3.5 Pulse-Width Modulation. Every thing seems to be ok. But not able to get PWM on timer. I've attached the modified script file that I'm using. Probed R384 on DV board.
    Please look into this.

    Regards,
    Gangadhar

    0383.timer.txt
    #!/bin/sh
    
    # timer_run.sh
    #
    # This script configures Timer4 to be run
    # on the VP1 Board. After configured,
    # the timer runs indefinitely at a fixed
    # freq and duty cycle, fed from the
    # internal CLK_M_OSC clock
    #
    
    echo "Configuring Timer 4...\n"
    
    # Enable Timer4's clock in CM_PER
    # This allows us to access it's control regs
    devmem2 0x44e00088 w 0x2
    
    # Set the Pinmux for Timer4 (0x2 because its mode 2 of this pin)
    # Using the pin mux linux driver from the SDK
    #echo 0x22 > /sys/kernel/debug/omap_mux/xdma_event_intr0
    
    # Timer configurations.. Stop Timer.
    # Auto-Reload
    # Compare Mode Enabled
    # Trigger set on overflow
    # Toggle Mode
    devmem2 0x48044038 w 0x1842
    
    # Write to the CM_DPLL registers to select the clk source
    # Selected the clk source for the Timer4
    # This should be &= (default 0x12) (writing a 0x2 for 32kHz)
    #0x1 = SEL2 : Select CLK_M_OSC clock
    devmem2 0x44e00510 w 0x1
    
    # Initial count value
    devmem2 0x4804403C w 0xFFFFAFFF
    
    # Set the re-load value
    devmem2 0x48044040 w 0xFFFFDFFF
    
    # Setting a duty cycle
    devmem2 0x4804404C w 0xFFFFAFFF
    
    # Force the Timer to Smart-Idle
    devmem2 0x48044010 w 0x8
    
    # Start Timer
    devmem2 0x48044038 w 0x1843
    
    # Verify that the timer is running,
    # by polling the count register a
    # few times. We should we up counting.
    for i in {1..10}
    do
     echo "Timer Value $i"
     devmem2 0x4804403C
    done
    
    # End
    echo "Timer is Running!"
    echo ""
    echo "See TP31 on the EVM"
    echo ""
    
    # Delay added to allow time for the first timer
    # overflow to occur, before any consecutive memory
    # accesses are made. (Just for standby testing).
    sleep 1
    
    # Disable MODULEMODE of CM_PER_TIMER4_CLKCTRL register
    # Only if this value is 0, are we able to wake-up from standby??
    devmem2 0x44e00088 w 0x0
    
    #END
    

  • Hi Mark,
    it's been a while, but maybe you or somebody read this.

    I tested your script and I got the same effect like Gangadhar.

    I have 2 questions:

    1) You activate in the controller register the mode "Trigger on overflow and match" (0x1842 -> Bit 11-10 -> 0x2).
    In my understanding the counter...
    step 1) ... starts with the register TCRR (0x4804403C). Pin is HIGH.
    step 2) The counter will be incremented.
    step 3) The counter reaches the value of the TMAR register (0x4804404C) (mode "Trigger on ...and match". So, the pin switches to LOW.
    step 4) The counter reaches the value 0XFFFFFFFF -> Overflow -> (mode "Trigger on overflow ...". So, the pin switches to HIGH.
    step 5) The counter is reload by the reload register TLDR ( 0x48044040) -> go to step 2)

    If this is correct, you have to switch your register values of TMAR and TLDR in your script:

    # Initial count value
    devmem2 0x4804403C w 0xFFFFAFFF

    # Set the re-load value
    devmem2 0x48044040 w 0xFFFFDFFF --> 0xFFFFAFFF

    # Setting a duty cycle
    devmem2 0x4804404C w 0xFFFFAFFF --> 0xFFFFDFFF

    2) The PWM stops with the last command after a few cyles

    devmem2 0x44e00088 w 0x0

    What is the correct way to generate a permanent pwm signal? Just delete this command?

    Regards,
    Markus
  • For anyone who has come across this thread and is wondering if you still have to implement the dm timer pwm driver in userspace for Linux, the answer is no. Several fine individuals have written the pwm-omap-dmtimer driver which takes care of producing a pwm signal on the dm timer pins. As far as I can tell, this driver was introduced into the mainline kernel sometime in between v4.4 and v4.7 (I have a copy of the 4.7 code that has it), so if you need them for an earlier version (4.4 and earlier) then you'll have to back-port it or stick to the userspace implementation.

    The links below show where the documentation is located relative to the Linux source directory ("root") and if you click on the link, it should take you to the 4.8 version of each doc. on the free electrons website.

    You will also have to include the driver in the kernel config. In menuconfig, Device Drivers ---> <*> Pulse Width Modulation(PWM) Support ---> <*> OMAP Dual-Mode Timer PWM support

    The Driver Usage section in TI's Linux Core PWM User's Guide shows how to use the driver from sysfs in userspace (it shows them using ecap, but the process is the same).

    I've tested it on a Beaglebone Black Rev. C with the Linux Yocto 4.9.4 kernel and the core-image-minimal poky distro (YP Core - Morty 2.2) from the Yocto Project. I had to add the below nodes to the am335x-boneblack.dts:

    / {
            ...
    
    	pwm7: dmtimer-pwm@7 {
    		compatible = "ti,omap-dmtimer-pwm";
    		ti,timers = <&timer7>;
    		#pwm-cells = <3>;
    		pinctrl-names = "default";
    		pinctrl-0 = <&dmtimer7_pins>;
    	};
    };
    
    &am33xx_pinmux {
    
            ...
    
    	dmtimer7_pins: dmtimer7_pins {
    		pinctrl-single,pins = <
    			AM33XX_IOPAD(0x894, PIN_OUTPUT | MUX_MODE2 | PULL_DISABLE)
    		>;
    	};
    
            ...
    };

    Please note that I had to add the pinctrl properties to the pwm7 node because the pin wasn't being muxed correctly without them.

    I hope someone finds this helpful.

    Regards,

    Jon

  • Of course, its helpful!

    Thx Jon!

    Regards,
    Markus