gpio_output_set dissection

In this article I will take a look into the inner workings of gpio_output_set

gpio_output_set disassembly
40004cd0:  61bdf0    l32r    a6, 0x40000fc4 ; dereferences to 0x60000200
40004cd3:  c02000    memw
40004cd6:  226641    s32i    a2, a6, 0x104  ; writes a2 into  0x60000200 + 0x104 (GPIO_OUT_W1TS_ADDRESS)
40004cd9:  c02000    memw
40004cdc:  326642    s32i    a3, a6, 0x108  ; writes a3 into  0x60000200 + 0x108 (GPIO_OUT_W1TC_ADDRESS)
40004cdf:  c02000    memw
40004ce2:  426644    s32i    a4, a6, 0x110  ; writes a4 into  0x60000200 + 0x110 (GPIO_ENABLE_W1TS_ADDRESS)
40004ce5:  c02000    memw
40004ce8:  526645    s32i    a5, a6, 0x114  ; writes a5 into  0x60000200 + 0x114 (GPIO_ENABLE_W1TC_ADDRESS)
40004ceb:  0df0      ret.n

The headers mistakenly call the Direction (ie. GPIO is input or output) registers "ENABLE".

All of the writes in the assembler code (s32i instruction) don't go directly to the GPIO registers, instead they go to the W1T(S|C). Upon behavioral analysis I found that writing to the W1TS and W1TC set and clear respectively the data register bits, and reading them returned always 0. Further playing with the registers demonstrated that it's also possible to write directly to the data registers. This concludes that these W1T registers serve as hardware helper registers. In short:

//writing to the W1TS register triggers the following:

//writing to the W1TC register triggers the following:

In summary here is a functional C code that packs all (?) of the GPIO registers into a single structure:

typedef struct GPIO_struct
    volatile uint32_t ODR;      /*!< Output Data Register       */
    volatile uint32_t OWITS;        /*!< Output Set Helper          */
    volatile uint32_t OWITC;        /*!< Output Clear Helper        */
    volatile uint32_t DDR;      /*!< Direction Data Register    */
    volatile uint32_t DWITS;        /*!< Direction Set Helper       */
    volatile uint32_t DWITC;        /*!< Direction Clear Helper     */
    volatile uint32_t IDR;      /*!< Input Data Register        */
    volatile uint32_t STA;      /*!< Status Register            */
    volatile uint32_t SWITS;        /*!< Status Set Helper          */
    volatile uint32_t SWITC;        /*!< Status Clear Helper        */

#define GPIO ((GPIO_TypeDef *) 0x60000300)