[Libmaple] pinMode() disables timer even if no PWM mode involved

Cores are the underlying magic that make the Arduino API possible
edogaldo
Posts: 254
Joined: Fri Jun 03, 2016 8:19 am

Re: pinMode() disables timer even if no PWM mode involved

Post by edogaldo » Thu May 18, 2017 4:39 pm

Just an idea: reinvoking pinMode() doesn't solve the issue?

rmdMoba
Posts: 16
Joined: Thu May 11, 2017 10:44 am

Re: pinMode() disables timer even if no PWM mode involved

Post by rmdMoba » Thu May 18, 2017 8:34 pm

victor_pv wrote:I suspect the case may be that when SPI or Serial end, the pins are not configured completely back to default and something extra may need to be done.
I supposed this too, and changed the end method of SPI tentatively. I set all the control registers to '0' ( the reset state ), but it changed nothing.
edogaldo wrote:Just an idea: reinvoking pinMode() doesn't solve the issue?
That's the way how I tried to switch back to PWM: seting pinMode to PWM and then pwmWrite() - but it didn't work.
Last edited by rmdMoba on Thu May 18, 2017 8:46 pm, edited 1 time in total.

User avatar
RogerClark
Posts: 6668
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: pinMode() disables timer even if no PWM mode involved

Post by RogerClark » Thu May 18, 2017 8:43 pm

can you post your test code

edogaldo
Posts: 254
Joined: Fri Jun 03, 2016 8:19 am

Re: pinMode() disables timer even if no PWM mode involved

Post by edogaldo » Thu May 18, 2017 8:59 pm

By the way, I just noticed this thread is in "STM core: Bugs and enhancements" section.
If we are referring to the Maple core I'd suggest to move it elsewhere..
Too many cores these days... :? :lol:

rmdMoba
Posts: 16
Joined: Thu May 11, 2017 10:44 am

Re: pinMode() disables timer even if no PWM mode involved

Post by rmdMoba » Thu May 18, 2017 9:01 pm

I checked the output on PA7 with a scope:

Code: Select all

// Test PWM on maplemini  pin 4 / PA7 ( general Output / SPI and PWM )
#include <SPI.h>
const byte Led1P = 16; // Led active during PWM Output
const byte test1P = 4;  // = port A7 ( SPI1-MOSI or TIM3 Ch2 )
SPIClass mySPI(1);
void setup() {
  // put your setup code here, to run once:
  pinMode( Led1P, OUTPUT );
  digitalWrite( Led1P, HIGH );
  delay(1000);

  pinMode( test1P, INPUT_PULLUP );
  delay( 1000 );
  digitalWrite( Led1P, LOW );
  pinMode( test1P, PWM );           // This PWM Sequence works fine
  for ( byte i=0; i<220; i++ ) {
     //analogWrite( test1P, i );
     pwmWrite( test1P, i*257 );
     delay( 20 );
  }
  digitalWrite( Led1P, HIGH );
  delay( 1000 );
  
  pinMode( test1P, OUTPUT );        // General IO - works fine too
  for ( byte i=0; i<11; i++ ) {
    digitalWrite(test1P, i&1 );
    delay( 5 );
  }
  pinMode( test1P, INPUT );
  delay(1000);
  mySPI.begin();                    // SPI output - works fine
  mySPI.beginTransaction(SPISettings(550000, MSBFIRST, SPI_MODE0, DATA_SIZE_16BIT));
  for ( byte i=0; i<11; i++ ) {  
    mySPI.write(0x5555);
    delay( 5 );
  }
  mySPI.endTransaction();
  mySPI.end();
  delay(1000);
  pinMode( test1P, OUTPUT );        // general OUTPUT - it works
  digitalWrite( test1P, LOW );
  delay(500);
  digitalWrite( test1P, HIGH );
  delay(1000);
  digitalWrite( Led1P, LOW );
  pinMode( test1P, PWM );           // The following PWM sequence doesn't work
  for ( int i=220; i>0; i-- ) {     // pin test1P seems to be in high impedance
     //analogWrite( test1P, i );    // state
     pwmWrite( test1P, i*257 );
     delay( 20 );
  }
  digitalWrite( Led1P, HIGH );
  delay(1000);
  mySPI.begin();                    // This again works
  mySPI.beginTransaction(SPISettings(550000, MSBFIRST, SPI_MODE0, DATA_SIZE_16BIT));
  for ( int i=0; i<11; i++ ) {  
    mySPI.write(0x5555);
    delay( 5 );
  }
  mySPI.endTransaction();
  mySPI.end();
  
/*  Serial1.begin( 1200 );
  delay( 1000);
  Serial1.println("start-dimming");
  delay(1000); */

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

}
Edit: I used the 'rogerclarkmelbourne/Arduino_STM32' repository from Github

victor_pv
Posts: 1599
Joined: Mon Apr 27, 2015 12:12 pm

Re: pinMode() disables timer even if no PWM mode involved

Post by victor_pv » Thu May 18, 2017 9:27 pm

rmdMoba wrote:I checked the output on PA7 with a scope:

Code: Select all

// Test PWM on maplemini  pin 4 / PA7 ( general Output / SPI and PWM )
#include <SPI.h>
const byte Led1P = 16; // Led active during PWM Output
const byte test1P = 4;  // = port A7 ( SPI1-MOSI or TIM3 Ch2 )
SPIClass mySPI(1);
void setup() {
  // put your setup code here, to run once:
  pinMode( Led1P, OUTPUT );
  digitalWrite( Led1P, HIGH );
  delay(1000);

  pinMode( test1P, INPUT_PULLUP );
  delay( 1000 );
  digitalWrite( Led1P, LOW );
  pinMode( test1P, PWM );           // This PWM Sequence works fine
  for ( byte i=0; i<220; i++ ) {
     //analogWrite( test1P, i );
     pwmWrite( test1P, i*257 );
     delay( 20 );
  }
  digitalWrite( Led1P, HIGH );
  delay( 1000 );
  
  pinMode( test1P, OUTPUT );        // General IO - works fine too
  for ( byte i=0; i<11; i++ ) {
    digitalWrite(test1P, i&1 );
    delay( 5 );
  }
  pinMode( test1P, INPUT );
  delay(1000);
  mySPI.begin();                    // SPI output - works fine
  mySPI.beginTransaction(SPISettings(550000, MSBFIRST, SPI_MODE0, DATA_SIZE_16BIT));
  for ( byte i=0; i<11; i++ ) {  
    mySPI.write(0x5555);
    delay( 5 );
  }
  mySPI.endTransaction();
  mySPI.end();
  delay(1000);
  pinMode( test1P, OUTPUT );        // general OUTPUT - it works
  digitalWrite( test1P, LOW );
  delay(500);
  digitalWrite( test1P, HIGH );
  delay(1000);
  digitalWrite( Led1P, LOW );
  pinMode( test1P, PWM );           // The following PWM sequence doesn't work
  for ( int i=220; i>0; i-- ) {     // pin test1P seems to be in high impedance
     //analogWrite( test1P, i );    // state
     pwmWrite( test1P, i*257 );
     delay( 20 );
  }
  digitalWrite( Led1P, HIGH );
  delay(1000);
  mySPI.begin();                    // This again works
  mySPI.beginTransaction(SPISettings(550000, MSBFIRST, SPI_MODE0, DATA_SIZE_16BIT));
  for ( int i=0; i<11; i++ ) {  
    mySPI.write(0x5555);
    delay( 5 );
  }
  mySPI.endTransaction();
  mySPI.end();
  
/*  Serial1.begin( 1200 );
  delay( 1000);
  Serial1.println("start-dimming");
  delay(1000); */

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

}
Edit: I used the 'rogerclarkmelbourne/Arduino_STM32' repository from Github
Not sure if you already address that, but the SPI library disables the Timer device mapped to the pins it uses:

Code: Select all

    disable_pwm(nssi);
    disable_pwm(scki);
    disable_pwm(misoi);
    disable_pwm(mosii);
So you will need to enable the timer device again.

rmdMoba
Posts: 16
Joined: Thu May 11, 2017 10:44 am

Re: pinMode() disables timer even if no PWM mode involved

Post by rmdMoba » Fri May 19, 2017 7:14 am

victor_pv wrote:So you will need to enable the timer device again.
Yes, sure. But that is what

Code: Select all

  pinMode( test1P, PWM );           // The following PWM sequence doesn't work
should do.
After a reset the timer is disabled too, and pinMode() sets it accordingly to create PWM pulses. Why does this not work when SPI disabled the timer?

victor_pv
Posts: 1599
Joined: Mon Apr 27, 2015 12:12 pm

Re: pinMode() disables timer even if no PWM mode involved

Post by victor_pv » Fri May 19, 2017 4:04 pm

rmdMoba wrote:
victor_pv wrote:So you will need to enable the timer device again.
Yes, sure. But that is what

Code: Select all

  pinMode( test1P, PWM );           // The following PWM sequence doesn't work
should do.
After a reset the timer is disabled too, and pinMode() sets it accordingly to create PWM pulses. Why does this not work when SPI disabled the timer?
Not sure if pinMode really enables the Timer device, or just enables the channel output. If you have confirmed it in the code already then that's it, but if you haven't, confirm it to be sure.

EDIT:
I confirmed it, does not enable the timer device, only the channel.

rmdMoba
Posts: 16
Joined: Thu May 11, 2017 10:44 am

Re: pinMode() disables timer even if no PWM mode involved

Post by rmdMoba » Fri May 19, 2017 9:21 pm

victor_pv wrote: I confirmed it, does not enable the timer device, only the channel.
That's true, but it's not the problem. Activating SPI also disables only the channel. The timer itself is still running. This is essential, because there are other channels where pwm may be active on non SPI pins.
The problem is obviously, that SPI blocks the PWM output even after an SPI.end().
If I remap the SPI output ( AFIO Register MAPR ) to the alternate pins after executing SPI.end(), then PWM works again.

Code: Select all

// Test PWM on libmaple 4 ( general Output / SPI and PWM )
#include <SPI.h>
// const byte test1P = 7;  //Generic = port A7 ( SPI1-MOSI or TIM3 Ch2 ) 
const byte test1P = 4;  // MapleMini = port A7 ( SPI1-MOSI or TIM3 Ch2 )
SPIClass mySPI(1);
void setup() {
    delay( 1000 );
    pinMode( test1P, PWM );           // This PWM Sequence works fine
    for ( byte i=0; i<220; i++ ) {
     //analogWrite( test1P, i );
     pwmWrite( test1P, i*257 );
     delay( 20 );
    }
    delay( 1000 );
    
    mySPI.begin();                    // SPI output - works fine
    mySPI.beginTransaction(SPISettings(550000, MSBFIRST, SPI_MODE0, DATA_SIZE_16BIT));
    for ( byte i=0; i<11; i++ ) {  
    mySPI.write(0x5555);
    delay( 5 );
    }
    mySPI.endTransaction();
    mySPI.end();
    delay(1000);
    AFIO_BASE->MAPR = 1;            // remap SPI1
    pinMode( test1P, PWM );         // The following PWM sequence only works if SPI is remapped
    for ( int i=220; i>0; i-- ) {    
     //analogWrite( test1P, i );   
     pwmWrite( test1P, i*257 );
     delay( 20 );
    }
    delay(1000);
    AFIO_BASE->MAPR = 0;            // remap SPI1 back to standard pins
    mySPI.begin();                  // This again works
    mySPI.beginTransaction(SPISettings(550000, MSBFIRST, SPI_MODE0, DATA_SIZE_16BIT));
    for ( int i=0; i<11; i++ ) {  
    mySPI.write(0x5555);
    delay( 5 );
    }
    mySPI.endTransaction();
    mySPI.end();
    
}
void loop() {
  // put your main code here, to run repeatedly:

}

victor_pv
Posts: 1599
Joined: Mon Apr 27, 2015 12:12 pm

Re: pinMode() disables timer even if no PWM mode involved

Post by victor_pv » Fri May 19, 2017 9:32 pm

rmdMoba wrote:
victor_pv wrote: I confirmed it, does not enable the timer device, only the channel.
That's true, but it's not the problem. Activating SPI also disables only the channel. The timer itself is still running. This is essential, because there are other channels where pwm may be active on non SPI pins.
The problem is obviously, that SPI blocks the PWM output even after an SPI.end().
If I remap the SPI output ( AFIO Register MAPR ) to the alternate pins after executing SPI.end(), then PWM works again.

Code: Select all

// Test PWM on libmaple 4 ( general Output / SPI and PWM )
#include <SPI.h>
// const byte test1P = 7;  //Generic = port A7 ( SPI1-MOSI or TIM3 Ch2 ) 
const byte test1P = 4;  // MapleMini = port A7 ( SPI1-MOSI or TIM3 Ch2 )
SPIClass mySPI(1);
void setup() {
    delay( 1000 );
    pinMode( test1P, PWM );           // This PWM Sequence works fine
    for ( byte i=0; i<220; i++ ) {
     //analogWrite( test1P, i );
     pwmWrite( test1P, i*257 );
     delay( 20 );
    }
    delay( 1000 );
    
    mySPI.begin();                    // SPI output - works fine
    mySPI.beginTransaction(SPISettings(550000, MSBFIRST, SPI_MODE0, DATA_SIZE_16BIT));
    for ( byte i=0; i<11; i++ ) {  
    mySPI.write(0x5555);
    delay( 5 );
    }
    mySPI.endTransaction();
    mySPI.end();
    delay(1000);
    AFIO_BASE->MAPR = 1;            // remap SPI1
    pinMode( test1P, PWM );         // The following PWM sequence only works if SPI is remapped
    for ( int i=220; i>0; i-- ) {    
     //analogWrite( test1P, i );   
     pwmWrite( test1P, i*257 );
     delay( 20 );
    }
    delay(1000);
    AFIO_BASE->MAPR = 0;            // remap SPI1 back to standard pins
    mySPI.begin();                  // This again works
    mySPI.beginTransaction(SPISettings(550000, MSBFIRST, SPI_MODE0, DATA_SIZE_16BIT));
    for ( int i=0; i<11; i++ ) {  
    mySPI.write(0x5555);
    delay( 5 );
    }
    mySPI.endTransaction();
    mySPI.end();
    
}
void loop() {
  // put your main code here, to run repeatedly:

}
I am a bit confused by this sentence " If I remap the SPI output ( AFIO Register MAPR ) to the alternate pins after executing SPI.end(), then PWM works again.". Does that mean you were not using the default SPI pins, but alternate ones instead? or you were using the normal ones, then if you switch to the alternate ones for SPI1 then PWM works again?

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest