2

I could drive a servo by using PWM0 channel on GPIO 18 of Raspberry Pi with following c code:

#define BCM2708_PERI_BASE       0x3F000000
#define PWM_BASE                (BCM2708_PERI_BASE + 0x20C000)
#define CLOCK_BASE              (BCM2708_PERI_BASE + 0x101000)
#define GPIO_BASE               (BCM2708_PERI_BASE + 0x200000)

#define PWM_CTL 0
#define PWM0_RNG 4
#define PWM0_DAT 5

#define PWM0_MS_MODE    0x0080  // Run in MS mode
#define PWM0_USEFIFO    0x0020  // Data from FIFO
#define PWM0_REVPOLAR   0x0010  // Reverse polarity
#define PWM0_OFFSTATE   0x0008  // Ouput Off state
#define PWM0_REPEATFF   0x0004  // Repeat last value if FIFO empty
#define PWM0_SERIAL     0x0002  // Run in serial mode
#define PWM0_ENABLE     0x0001  // Channel Enable

#define PWMCLK_CNTL 40
#define PWMCLK_DIV 41

// stop clock and waiting for busy flag doesn't work, so kill clock
*(clk + PWMCLK_CNTL) = 0x5A000000 | (1 << 5); usleep(10);

// wait until busy flag is set
while ( (*(clk + PWMCLK_CNTL)) & 0x00000080){}

*(clk + PWMCLK_DIV) = 0x5A000000 | (Divisor << 12);
*(clk + PWMCLK_CNTL) = 0x5A000011;
*(pwm + PWM_CTL) = 0; usleep(10);

*(pwm + PWM0_RNG) = Counts; usleep(10);
*(pwm + PWM0_DAT) = (int) (DutyCycle * Counts / 100); usleep(10);
*(pwm + PWM_CTL) |= ( (1 << 7) | (1 << 0) );

However, when I tried to drive another servo on on another GPIO on PWM1 channel, it didn't work at all. The PWM1 channel has the following values:

#define PWM1_RNG 8
#define PWM1_DAT 9

#define PWM1_MS_MODE    0x8000  // Run in MS mode
#define PWM1_USEFIFO    0x2000  // Data from FIFO
#define PWM1_REVPOLAR   0x1000  // Reverse polarity
#define PWM1_OFFSTATE   0x0800  // Ouput Off state
#define PWM1_REPEATFF   0x0400  // Repeat last value if FIFO empty
#define PWM1_SERIAL     0x0200  // Run in serial mode
#define PWM1_ENABLE     0x0100  // Channel Enable

Can anybody tell me where the registers are modified from PWM0 and PWM1?

mohasalah
  • 43
  • 2
  • 1
    You have shown us some code that you say works, and then told us you have some other code that does not work, but you which have not shown. Then you expect us to tell you what is wrong with the code you have not shown! The correct operation of the code seems to rely on appropriate values of `pwm` and `clk`, which you have not shown in any case. You could perhaps save yourself some trouble by using the [pigpio library](http://abyz.co.uk/rpi/pigpio/cif.html) which allows PWM on any GPIO pin with clever use of DMA, PWM and PCM peripherals for minimal software overhead and good precision. – Clifford Jan 05 '16 at 21:33
  • ... or [ServoBlaster](https://github.com/richardghirst/PiBits/tree/master/ServoBlaster) from which the pigpio PWM control method was derived. – Clifford Jan 05 '16 at 21:36
  • @Clifford: I don't want to use software PWM on any GPIO. what I need to do is just using hardware PWM on a particular pin which is GPIO 19 which provides hardware PWM. However, I couldn't know which values to change as the original code is not mine. My really concern is just manipulating the registers of RPI – mohasalah Jan 06 '16 at 08:58
  • 1
    Read the link to the [ServoBlaster](https://github.com/richardghirst/PiBits/tree/master/ServoBlaster) library on which pigpio's PWM implementation is based - it is not "software PWM" and suited to driving servo's. My point still stands however; you've not posted the appropriate code. You have told us that you have defined the macros `PWM1_MS_MODE` etc, but have not shown us where those macros are used. Simply defining them is certainly not enough. Also "it did not work at all" is not very helpful; at this point I'd be stepping the code in the debugger to see what is *actually* happening. – Clifford Jan 06 '16 at 09:46

1 Answers1

0

Wading through available documentation, you have to set GPIO45 to its Alternate Function 0.

The PWM peripheral registers are described in the Broadcom peripheral documentation (this refers to the RPi1's BCM2835 but is mostly identical to the RPi's BCM2836 with respect to the peripheral set. Be aware that the PWM channels are referred to as PWM1/2 rather then PWM0/1 in the register tables.

Clifford
  • 88,407
  • 13
  • 85
  • 165
  • Thank you Mr. Clifford for your reply, can you please tell me where to find the needed registers in [Boardcom BCM2835 Peripherals](https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2835/BCM2835-ARM-Peripherals.pdf)? I mean how to differentiate between the two PWMs in that documentation? I'v tried to locate them but failed. – mohasalah Jan 08 '16 at 15:51
  • @mohasalah : There is one PWM controller with two channels. The Table in 9.6 summarises the register map. Ther are separate RNG and DAT registers for each PWM. The FIFO register can serve both channels alternately or either one. The CTL register is shared by both channels with separate sub-fields for each channel where appropriate. I am only reading the documentation available. The Broadcom documentation is rather terse and not of the quality you might expect from a generally available device. If you are struggling with it, use the library as suggested. – Clifford Jan 08 '16 at 22:20