I'm doing a bare metal project and was configuring the PWM peripheral when I ran across a strange bug. I'm using the imx6 bare metal SDK register definitions, which are produced by the IOMUX tool. Every time I wrote HW_PWM_PWMSAR(instance).B.SAMPLE, it wouldn't take effect. I would read it back and it was still the old value. (This is how it's done in the PWM example in the SDK, so beware) Looking through the assembly, the compiler was generating a strh which only writes the lower 16 bits of the register - exactly what it should do given the register is defined as:
typedef union _hw_pwm_pwmsar
unsigned SAMPLE : 16; //!< [15:0] Sample Value.
unsigned RESERVED0 : 16; //!< [31:16] These are reserved bits and writing a value will not affect the functionality of PWM and are always read as zero.
I switched to using HW_PWM_PWMSAR(instance).U which winds up doing a str into the address, writing all 32 bits and now it works just fine. So if you write 16 bits of the register, it doesn't work. If you write all 32 bits, it does. This makes me very wary of using the structure bitfields, which are used all over the place in the IOMUX register definitions. Is this an error in the PWM hardware specifically or do all registers need to be written 32 bits at a time?