#include "registers.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
#undef GPIOA
#undef GPIOB
#undef RCC
#undef SYSCFG
GPIO_TypeDef a,b;
RCC_TypeDef r;
SYSCFG_TypeDef y;
#define GPIOA (&a)
#define GPIOB (&b)
#define RCC (&r)
#define SYSCFG (&y)
#define __DSB() ((void)0)
static unsigned before_mapping;
static void apply(GPIO_TypeDef *p) {p->ODR=(p->ODR & ~(p->BSRR>>16))|(p->BSRR&65535u); assert((a.ODR&((1u<<9)|(1u<<11)))==0);}
static void before_clear(void) {
 assert(((a.MODER>>22)&3)==1 && ((a.MODER>>18)&3)==1);
 assert(((a.MODER>>24)&3)==0 && ((a.MODER>>20)&3)==0);
 assert(((a.PUPDR>>24)&3)==2 && ((a.PUPDR>>20)&3)==2);
 assert((a.ODR&((1u<<9)|(1u<<11)))==0);before_mapping++;
}
static void gpio_drive(GPIO_TypeDef *port, uint32_t pin, uint32_t high) {
    const uint32_t shift = pin * 2u;
    port->BSRR = high ? (1u << pin) : (1u << (pin + 16u));
    apply(port);
    port->OTYPER &= ~(1u << pin);
    port->OSPEEDR &= ~(3u << shift);
    port->PUPDR &= ~(3u << shift);
    port->MODER = (port->MODER & ~(3u << shift)) | (1u << shift);
}

static void gpio_input(GPIO_TypeDef *port, uint32_t pin, uint32_t pull_up) {
    const uint32_t shift = pin * 2u;
    port->MODER &= ~(3u << shift);
    port->PUPDR = (port->PUPDR & ~(3u << shift)) |
                  ((pull_up ? 1u : 2u) << shift);
}

static void board_safe_boot(void) {
    RCC->IOPENR |= RCC_IOPENR_GPIOAEN | RCC_IOPENR_GPIOBEN;
    (void)RCC->IOPENR;
    RCC->APBENR2 |= RCC_APBENR2_SYSCFGEN;
    (void)RCC->APBENR2;

    /* Set output latches before changing pin modes to avoid an active pulse. */
    GPIOA->BSRR = (1u << (4u + 16u)) | (1u << 7u) | (1u << (9u + 16u)) |
                  (1u << (11u + 16u));
    GPIOB->BSRR = (1u << (9u + 16u));
    apply(GPIOA); apply(GPIOB);
    __DSB();

    gpio_drive(GPIOA, 4u, 0u);  /* LED_PWR_REQ_MCU: power gate disabled. */
    gpio_drive(GPIOA, 7u, 1u);  /* LED_OE_N_MCU: outputs blanked. */
    /* Stage both pin16 aliases low before restoring the default mapping.
     * DS12991 Rev6 Table12: package pin16=PA11, pin17=PA12.
     * PA9/PA10 reach these pads only with explicit SYSCFG remapping. */
    gpio_drive(GPIOA, 9u, 0u);
    gpio_drive(GPIOA, 11u, 0u); /* WDOG_KICK: no external watchdog kick. */
    gpio_input(GPIOA, 10u, 0u);
    gpio_input(GPIOA, 12u, 0u); /* THERM_OK: open defaults unsafe. */
    before_clear();
    SYSCFG->CFGR1 &= ~(SYSCFG_CFGR1_PA11_RMP | SYSCFG_CFGR1_PA12_RMP);
    __DSB();
    gpio_drive(GPIOB, 9u, 0u);  /* LED_RESET_N_MCU: driver held in reset. */

    gpio_input(GPIOA, 0u, 0u);  /* INTERLOCK_OK: open defaults unsafe. */

    gpio_input(GPIOB, 0u, 1u);  /* USER_KEY_N: sampled only after validation. */
}


int main(void) {
 unsigned cases=0;
 for(unsigned seed=0;seed<2;seed++) for(unsigned remap=0;remap<4;remap++) {
 memset(&a,seed?255:0,sizeof a);memset(&b,seed?255:0,sizeof b);memset(&r,0,sizeof r);memset(&y,0,sizeof y);
 /* Reset only the ODR image at the preloading checkpoint, representing BSRR
    writes; high prior latches are allowed and tested before any mode change. */
 y.CFGR1=0x80u|((remap&1)?SYSCFG_CFGR1_PA11_RMP:0)|((remap&2)?SYSCFG_CFGR1_PA12_RMP:0);
 board_safe_boot();
 assert(((a.MODER>>22)&3)==1);assert((a.ODR&(1u<<11))==0);
 assert(((a.MODER>>24)&3)==0);assert(((a.PUPDR>>24)&3)==2);
 assert((y.CFGR1&(SYSCFG_CFGR1_PA11_RMP|SYSCFG_CFGR1_PA12_RMP))==0);
 assert((y.CFGR1&0x80u)!=0);
 assert((r.APBENR2&RCC_APBENR2_SYSCFGEN)!=0);
 assert(((a.MODER>>8)&3)==1 && (a.ODR&(1u<<4))==0);
 assert(((a.MODER>>14)&3)==1 && (a.ODR&(1u<<7))!=0);
 assert(((b.MODER>>18)&3)==1 && (b.ODR&(1u<<9))==0);
 assert(((a.PUPDR>>0)&3)==2 && ((b.PUPDR>>0)&3)==1);
 cases++;
 }
 assert(before_mapping==8);printf("PASS: %u boot cases; both remap bits, prior GPIO zero/all-ones; physical pin16 low and pin17 input pulldown; mapping staged before switch. MMIO model only.\n",cases);
}
