#include "firmware/固件/drill_target/src/drill_clock.c"
#include <assert.h>
#include <stdio.h>
#include <string.h>
RCC_TypeDef rcc;GPIO_TypeDef ga,gb,gf;TIM_TypeDef timer,timer2;SPI_TypeDef spi;host_systick_type systick;unsigned host_systick_config_calls;
#include "host_clock_fixture.h"
static unsigned fault,barriers,switches,half_steps;
void host_wait(void){assert(0);}
void host_dsb(void){
 ++barriers;
 if(fault==1)pwr.SR2=PWR_SR2_VOSF;
 if(fault==2)flash.ACR&=~FLASH_ACR_LATENCY;
 if(fault==5 && rcc.PLLCFGR==DRILL_PLL_CONFIG)rcc.PLLCFGR^=RCC_PLLCFGR_PLLN_0;
 if(rcc.CR&RCC_CR_PLLON){assert((flash.ACR&FLASH_ACR_LATENCY)==4);assert((pwr.CR1&PWR_CR1_VOS)==PWR_CR1_VOS_0);if(fault!=3)rcc.CR|=RCC_CR_PLLRDY;}
 if((rcc.CFGR&RCC_CFGR_HPRE)==RCC_CFGR_HPRE_DIV2)++half_steps;
 if((rcc.CFGR&RCC_CFGR_SW)==RCC_CFGR_SW_PLL && (rcc.CFGR&RCC_CFGR_SWS)!=RCC_CFGR_SWS_PLL){
  assert((rcc.CFGR&RCC_CFGR_HPRE)==RCC_CFGR_HPRE_DIV2&&half_steps);
  assert(rcc.CR&RCC_CR_PLLRDY);assert((flash.ACR&FLASH_ACR_LATENCY)==4);
  if(fault!=4){rcc.CFGR=(rcc.CFGR&~RCC_CFGR_SWS)|RCC_CFGR_SWS_PLL;++switches;}
 }
}
static void cold(void){
 memset(&rcc,0,sizeof rcc);memset(&ga,0,sizeof ga);memset(&gb,0,sizeof gb);memset(&gf,0,sizeof gf);memset(&systick,0,sizeof systick);
 host_clock_profile();rcc.CR=RCC_CR_HSION|RCC_CR_HSIRDY;rcc.CFGR=RCC_CFGR_SW_HSI|RCC_CFGR_SWS_HSI;rcc.PLLCFGR=0;rcc.APB1ENR1=0;
 pwr.CR1=PWR_CR1_VOS_1;pwr.CR5=0;flash.ACR=0;SystemCoreClock=16000000;
 rcc.AHB2ENR=RCC_AHB2ENR_GPIOAEN|RCC_AHB2ENR_GPIOBEN|RCC_AHB2ENR_GPIOFEN;
 for(unsigned pin=5;pin<=12;++pin)if(pin!=6&&pin!=11)ga.MODER|=1u<<(2u*pin);gb.MODER=5;gf.MODER=4;ga.ODR=ga.IDR=1u<<12;
 clock_started=clock_failed=false;fault=barriers=switches=half_steps=0;
}
int main(void){unsigned cases=0;
 cold();assert(drill_clock_init()&&drill_clock_available()&&SystemCoreClock==128000000&&switches==1&&half_steps);assert(drill_clock_init());++cases;
 for(unsigned mode=1;mode<=5;++mode){cold();GPIO_TypeDef a=ga,b=gb,f=gf;fault=mode;assert(!drill_clock_init()&&clock_failed);assert(barriers<=CLOCK_POLL_LIMIT+12);unsigned prior=barriers;fault=0;assert(!drill_clock_init()&&barriers==prior);assert(!memcmp(&a,&ga,sizeof ga)&&!memcmp(&b,&gb,sizeof gb)&&!memcmp(&f,&gf,sizeof gf));++cases;}
 for(unsigned mode=0;mode<16;++mode){cold();
  if(mode==0)rcc.CR|=RCC_CR_PLLON;if(mode==1)rcc.CR|=RCC_CR_HSEON;if(mode==2)rcc.CR&=~RCC_CR_HSIRDY;
  if(mode==3)rcc.CFGR|=RCC_CFGR_HPRE_DIV2;if(mode==4)rcc.CFGR|=RCC_CFGR_PPRE1_DIV2;if(mode==5)rcc.CFGR|=RCC_CFGR_PPRE2_DIV2;
  if(mode==6)rcc.APB2ENR|=RCC_APB2ENR_TIM1EN;if(mode==7)rcc.APB1ENR1|=RCC_APB1ENR1_TIM2EN;if(mode==8)rcc.APB1ENR1|=RCC_APB1ENR1_SPI2EN;
  if(mode==9)rcc.AHB2ENR|=RCC_AHB2ENR_ADC12EN;if(mode==10)rcc.AHB1ENR|=RCC_AHB1ENR_DMA1EN;if(mode==11)rcc.AHB1ENR|=RCC_AHB1ENR_DMA2EN;if(mode==12)rcc.AHB1ENR|=RCC_AHB1ENR_DMAMUX1EN;
  if(mode==13)systick.CTRL=1;if(mode==14)rcc.APB1RSTR1|=RCC_APB1RSTR1_PWRRST;if(mode==15)ga.IDR&=~(1u<<12);
  RCC_TypeDef before=rcc;assert(!drill_clock_init()&&!barriers&&!memcmp(&before,&rcc,sizeof rcc));++cases;
 }
 for(unsigned reg=0;reg<9;++reg)for(unsigned bit=0;bit<32;++bit){cold();assert(drill_clock_init());
  volatile uint32_t *rs[]={&rcc.CR,&rcc.PLLCFGR,&rcc.CFGR,&rcc.APB1ENR1,&rcc.APB1RSTR1,&pwr.CR1,&pwr.CR5,&pwr.SR2,&flash.ACR};
  uint32_t masks[]={RCC_CR_HSION|RCC_CR_HSIRDY|RCC_CR_PLLON|RCC_CR_PLLRDY|RCC_CR_HSEON|RCC_CR_HSEBYP,UINT32_MAX,RCC_CFGR_SW|RCC_CFGR_SWS|RCC_CFGR_HPRE|RCC_CFGR_PPRE1|RCC_CFGR_PPRE2,RCC_APB1ENR1_PWREN,RCC_APB1RSTR1_PWRRST,PWR_CR1_VOS|PWR_CR1_LPR,PWR_CR5_R1MODE,PWR_SR2_VOSF,FLASH_ACR_LATENCY};
  *rs[reg]^=1u<<bit;assert(drill_clock_available()==!(masks[reg]&(1u<<bit)));++cases;
 }
 cold();assert(drill_clock_init());SystemCoreClock=16000000;assert(!drill_clock_available());++cases;
 printf("%u CLOCK TRANSITION / BOUNDED FAIL / PROFILE SCENARIOS PASS\n",cases);
}
