Page 2 of 3

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

Posted: Thu May 18, 2017 4:39 pm
by edogaldo
Just an idea: reinvoking pinMode() doesn't solve the issue?

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

Posted: Thu May 18, 2017 8:34 pm
by rmdMoba
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.

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

Posted: Thu May 18, 2017 8:43 pm
by RogerClark
can you post your test code

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

Posted: Thu May 18, 2017 8:59 pm
by edogaldo
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:

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

Posted: Thu May 18, 2017 9:01 pm
by rmdMoba
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

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

Posted: Thu May 18, 2017 9:27 pm
by victor_pv
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.

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

Posted: Fri May 19, 2017 7:14 am
by rmdMoba
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?

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

Posted: Fri May 19, 2017 4:04 pm
by victor_pv
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.

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

Posted: Fri May 19, 2017 9:21 pm
by rmdMoba
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:

}

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

Posted: Fri May 19, 2017 9:32 pm
by victor_pv
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?