PWM signal randomly inverted on RX and PX (P1 and Photon) [Solved]


I’m having some strange trouble with the PWM signals on pin RX and TX on a P1 based device. The problem is that the signal is the inverse of the expected when using HAL_PWM_Write on this pins. And even more confusing is that if I make consecutive calls and have the SYSTEM_MODE set to automatic, then about every 16th second, the output is correct until another call to HAL_PWM_Write is made, then it is reversed again.

If I have SYSTEM_MODE set to manual, then the signal is always the inverse of expected.

To make it clear what I expect: using HAL_PWM_Write(RX,40), I expect an 500Hz out signal which is around 16% high and 84% low, instead I get the inverse.

I have also tried using analogWrite(RX,40), it behaves better most of the time, but still it produces more of a random change to the inverse when making several calls. Other pins I have tried does not seem to cause this kind of problems.

Have I missed some basic configuration? Do I need to disable anything?
Can anyone reproduce this? It should be simple! I noticed that RX and TX are not included in tinker app!

I have included a short application.cpp to show the problem. I’m building locally on Windows using the development branch.

#include "application.h"


void setup() {
    pinMode(RX, OUTPUT);
    pinMode(TX, OUTPUT);

void loop() {

    HAL_PWM_Write(RX, 40);
    HAL_PWM_Write(TX, 40);



After much digging and looking in the datasheet for this to me new MCU family, I have finally solved it. There is a small bug in function HAL_PWM_Write. The problem occurs when using an advanced timer (TIM1 or TIM8).They use some more settings in the structure (TIM_OCInitTypeDef) then the normal timers. They are then used by TIM_OCxInit, so they need to be initialized or they will have whatever value was on the stack when “allocated” and in the end causes random values in the TIM1(8)->CCER register.
Setting all the extra values in TIM_OCInitTypeDef to zeros works fine as long as you are not going into using any of the complementary outputs of the advanced timers.

So finally the small simplest fix is just to add a = {0}.

The row 51 in hal/src/stm32f2xx/pwm_hal.c should be changed to:

TIM_OCInitTypeDef  TIM_OCInitStructure = {0};

I’m a bit surprised that no one else has seen the problem; it should appear on the Photon as well as the P1 and applies to all Timer1 and Timer8 (none of TIM8 channels are mapped as default) channels.

I’m hoping someone on the firmware team (@mdma) can catch this up and make the fix, seems a bit much to do a pull request for this small change.

I hope this can help someone avoiding the struggle I had with this :smile:



I havn’t really tested, but just had a look at hal/src/stm32f2xx/servo_hal.c and I guess that it might have the same sort of problem in HAL_Servo_Attach when using servo on the RX and TX pin.


Testing this change now… hopefully we can get this into v0.4.4. I can confirm the inverted PWM on RX and TX.

1 Like

Great! Thank you for confirming the problem!

Ok this definitely solves the issue for RX and TX, and I tested the servo on RX and TX and with and without initializing that structure to all zeros did not flip it’s polarity or timing. Servo.write(170) and Servo.writeMicrosecond(2400) both correspond to a ~2.4mS high pulse. This will be included in v0.4.4 :wink: Thanks @janne68!