Unexpected behaviour of pwmc configuration in Arduino Due

After reading other posts here I have been experimenting with generating PWM in my Arduino Due using the Atmel SAM3X pwmc library and have seen some strange behaviour.

Using the attached code the prescaler set for channel PWML0 has no effect. Measuring with a scope I get about 70KHz PWM on PWML0 whereas PWML1 generates the expected 17.5KHz.

Now here comes the weird thing: If I swap the 2 x 4 lines in the sketch setup so I configure PWML1 before PWML0 I get the expected 17.5KHz on both channels.

If I leave out the configuration of PWML1 completely PWML0 also shows correct behaviour.

I use Arduino IDE 1.6.4, but get the same result with an old IDE 1.5.6-r2 I have on another computer.

I hope someone can help me to understand why this is happening?

Arduino_Due_PWML0_and_PWML1_test.ino (1.02 KB)

I think you’ll need to re-order your lines of code.

Some notes from the datasheet:

39.5.1 I/O Lines <<>>

39.5.2 Power Management <<<The programmer must first enable the PWM clock in the Power Management Controller (PMC) before using the PWM.>>>

Perhaps something like this:

void setup() {

  // Configure PWMLx pins to be driven by peripheral B (PWM channel 0 L)
  // PC4, PC2 = 0x14
  PIOC->PIO_PDR = 0x14; // disable PIO control
  PIOC->PIO_IDR = 0x14; // disable PIO interrupts
  PIOC->PIO_ABSR |= 0x14; // switch to B peripheral

 pmc_enable_periph_clk (PWM_INTERFACE_ID) ;  // turn on clocking to PWM unit

  // Configure PWML0 & PWML1 channels to 17.5kHz
  // Master clock of 42MHz, prescaler = 3, 600 periods
  
  PWMC_ConfigureChannel (PWM, 0, 3, 0, 0) ; // PWM channel 0, clock = MCLK/2 = 42MHz
  PWMC_SetPeriod (PWM, 0, 600) ;  // period = 600 pwm clocks (17.5kHz)
  PWMC_SetDutyCycle (PWM, 0, 20*600/100) ;  // duty set to 20%
  PWMC_EnableChannel (PWM, 0) ;   // enable
  
  PWMC_ConfigureChannel (PWM, 1, 3, 0, 0) ; // PWM channel 1, clock = MCLK/2 = 42MHz
  PWMC_SetPeriod (PWM, 1, 600) ;  // period = 600 pwm clocks (17.5kHz)
  PWMC_SetDutyCycle (PWM, 1, 40*600/100) ;  // duty set to 40%
  PWMC_EnableChannel (PWM, 1) ;   // enable
}

void loop() {
  // put your main code here, to run repeatedly:
}

Thanks dlloyd.

I tried what you suggested, but it makes no difference. Anyway I didn't think it would since as I understand the datasheet configuring the PIO pins has nothing to do with PWM generation in the chip (in other words you can have the pwm running in the chip without sending it out on the pins)

In my application I can just swap the code lines as I said in my first post and PWM generations is correct. But not understanding why it makes a difference concerns me, as I am using this code in a customer application.

I have been fighting with this for days now. Could there be something wrong with the pwmc library?

If you or anybody else can help to shed more light on this matter it would be much appreciated.

Update:

I finally figured out what caused the problem. As expected it was the latest version of the Atmel SAM3x pwmc.c library that had been changed in just one line. This library is included by default in the Arduino IDE.

If you look at the PWMC_ConfigureChannel function in the most recent version of pwmc.c dated 2011-12

https://github.com/matthijskooijman/arduino-platform-sam/blob/master/system/libsam/source/pwmc.c

the first statement in the PWMC_ConfigureChannel function is:

pPwm->PWM_CH_NUM[0].PWM_CMR = 1;

I am no C expert but what I can figure out is that if you have called the PWMC_ConfigureChannel function initially to configure PWML0, and then call the function again to configure another PWMLx channel, this single statement will overwrite your prescaler settings for PWML0 you just configured with a 1, meaning no prescaling. The result is that PWML0 will run with no prescaler (i.e. at the base frequency) and the rest of the PWMLx channels configured will run with the frequency divided by the prescaler value you use when calling the configuration funtion.

I also found out that the single statement causing the problem had been commented in the 2009 version of pwmc.c. I must have used this older library with an earlier version of my Arduino IDE, and therefore had no problems with configuring PWMLx channels at the time.

I have no idea why the statement has been un-commented in the latest pwmc.c library, but it certainly caused me a big headache for days!

The way to come around the problem is to either configure PWML0 as the last channel in a sequence of other PWMLx channel configurations in your sketch or to make you own local PWMC_ConfigureChannel function/library where the pPwm statement is commented. Then all should work as intended.

Warning to all Arduino Dee users: Be aware of this if you are playing with the PWMLx in Arduino Due!!!!!

It won't have been uncommented, it will have reverted when a newer version of libsam was
substituted. It sounds like a fix that isn't / won't make it back to the original libsam code base.
libsam is third party, not Arduino controlled.