/* * main.c: test-o continuity and diode tester * * your robot addon badge buddy for testing all the things * * file creation: 20231015 0021 */ #include "testo.h" #include "adc.h" #include "flash.h" #include "led.h" #include "userio.h" uint16_t ctr; uint32_t uptime; static inline void gpio_init() { // set registers manually instead of with // LL functions to save space. // though we probably don't _need_ this space... // PF2=OUT(high), low speed // unused pins are analog GPIOF->ODR = (1 << 2); GPIOF->MODER = 0xFFFFFCDF; // set I2C outputs as open drain GPIOA->OTYPER = 0x000c; // enable pullups on I2C outputs GPIOA->PUPDR = 0x24000050; // datasheet doesn't say what the speeds are for GPIO... // so set SWDIO to very high speed, PA12 low speed, all other outputs as high speed GPIOA->OSPEEDR = 0x2C002AA0; // alternate function select // PA6=T3C1, PA5=T3C2, PA4=T3C3, PA3=I2C_SCL, PA2=I2C_SDA GPIOA->AFR[0] = 0x01DDCC00; // PA12=OUT(high) GPIOA->ODR = (1 << 12); // PA14=ALT, PA13=ALT, PA12=OUT, PA11=OUT // PA7=AN, PA6=AF, PA5=AF, PA4=AF // PA3=AF, PA2=AF, PA1=AN, PA0=AN // unused pins are digital inputs GPIOA->MODER = 0x2900EAAF; // PB1=OUT(HIGH), PB0=AN // unused pins are analog, all outputs are low speed GPIOB->OSPEEDR = 0x00000000; GPIOB->ODR = (1 << 1); GPIOB->MODER = 0xfffffff7; } static inline void clk_init() { // run all buses at core clock speed LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); // enable GPIO and peripheral clocks RCC->IOPENR = LL_IOP_GRP1_PERIPH_GPIOA | LL_IOP_GRP1_PERIPH_GPIOB | LL_IOP_GRP1_PERIPH_GPIOF; RCC->AHBENR = LL_AHB1_GRP1_PERIPH_DMA1; RCC->APBENR1 = LL_APB1_GRP1_PERIPH_TIM3; RCC->APBENR2 = LL_APB1_GRP2_PERIPH_ADC1 | LL_APB1_GRP2_PERIPH_SYSCFG; } static inline void systick_init() { // configure nvic NVIC_EnableIRQ(SysTick_IRQn); NVIC_SetPriority(SysTick_IRQn, 0); // configure timebase with interrupt at 4096Hz // this assumes we'll always be running at 8MHz SysTick_Config((8000000 / 4096) - 1); } /* * get things started, then * low priority application execution */ int main() { // base hardware initialization clk_init(); flash_init(); // also configures option bytes to enable PF2, if necessary gpio_init(); // peripheral initialization led_init(); adc_init(); // mainline loop interrupt systick_init(); // let's go __enable_irq(); while (1) { // run LED programs out of interrupt context at 256Hz if ((ctr & 0xf) == 0) { } // nap time __WFI(); } } /* * main application interrupt */ __attribute__ ((long_call, section(".ramfunc"))) void SysTick_Handler(void) { uint16_t cs; ctr++; // run LED programs quickly led_next(); // limit counter to 4096 counts ctr &= 0xfff; if (!ctr) { uptime++; } // run main logic at 1024Hz if (!(ctr & 0x3)) { // shifted counter for use in the program cs = ctr >> 2; // adc tested to result in about 61 reads/second if (!adc_next()) { // adc has new computed results, so we can do userio, probe, etc if (uptime || cs) { userio_parse(); } } } }