#include #include #include "hw.h" #define UART_BAUD (115200) typedef enum { GPIO_INPUT = 0b00, GPIO_OUTPUT = 0b01, GPIO_ALT = 0b10, GPIO_ANALOG = 0b11 } gpio_mode_t; typedef enum { GPIO_PP = 0b0, GPIO_OD = 0b1 } gpio_ot_t; typedef enum { GPIO_SPEED_VLOW = 0b00, GPIO_SPEED_LOW = 0b01, GPIO_SPEED_HIGH = 0b10, GPIO_SPEED_VHIGH = 0b11 } gpio_ospeed_t; typedef enum { GPIO_PULL_NONE = 0b00, GPIO_PULL_UP = 0b01, GPIO_PULL_DOWN = 0b10 } gpio_pupd_t; typedef enum { GPIO_AF_0 = 0x00, GPIO_AF_1 = 0x01, GPIO_AF_2 = 0x02, GPIO_AF_3 = 0x03, GPIO_AF_4 = 0x04, GPIO_AF_5 = 0x05, GPIO_AF_6 = 0x06, GPIO_AF_7 = 0x07 } gpio_af_t; typedef struct { void (*volatile falling)(void); void (*volatile rising)(void); } gpio_irq_callback_t; static const GPIO_TypeDef *gpios[] = { GPIOA, GPIOB, 0, 0, 0, 0, 0, 0 }; static gpio_irq_callback_t gpio_irq_callbacks[16]; static volatile uint8_t *i2c_data_txptr; static volatile uint8_t *i2c_data_rxptr; static volatile uint32_t i2c_next_cr2; static void (*volatile i2c_callback)(void); static const TIM_TypeDef *tims[] = { TIM14, TIM16, TIM17, TIM3, TIM1 }; static void (*volatile tim_callbacks[5])(void); static void hw_gpio_init (gpio_id_t id, gpio_mode_t mode, gpio_ot_t ot, gpio_ospeed_t ospeed, gpio_pupd_t pupd, gpio_af_t af, int value) { GPIO_TypeDef tmp; GPIO_TypeDef *gpio = ((GPIO_TypeDef *) (gpios[(id >> 4) & 0x07])); uint8_t pin = (id & 0x0F); uint8_t afr = ((pin < 8) ? 0 : 1); tmp.MODER = (gpio->MODER & ~(GPIO_MODER_MODE0_Msk << (pin * 2))); tmp.OTYPER = (gpio->OTYPER & ~(GPIO_OTYPER_OT0_Msk << pin)); tmp.OSPEEDR = (gpio->OSPEEDR & ~(GPIO_OSPEEDR_OSPEED0_Msk << (pin * 2))); tmp.PUPDR = (gpio->PUPDR & ~(GPIO_PUPDR_PUPD0_Msk << (pin * 2))); tmp.AFR[afr] = (gpio->AFR[afr] & ~(GPIO_AFRL_AFSEL0_Msk << ((pin - (afr * 8)) * 4))); gpio->MODER |= (GPIO_MODER_MODE0_Msk << (pin * 2)); gpio->OTYPER = (tmp.OTYPER | (ot << pin)); gpio->OSPEEDR = (tmp.OSPEEDR | (ospeed << (pin * 2))); gpio->PUPDR = (tmp.PUPDR | (pupd << (pin * 2))); gpio->AFR[afr] = (tmp.AFR[afr] | (af << ((pin - (afr * 8)) * 4))); gpio->BSRR = ((value ? GPIO_BSRR_BS0 : GPIO_BSRR_BR0) << pin); gpio->MODER = (tmp.MODER | (mode << (pin * 2))); } void hw_gpio_irq_setup (gpio_id_t id, gpio_irq_t irq, void (*callback)(void)) { uint8_t port = ((id >> 4) & 0x07); uint8_t pin = (id & 0x0F); if (irq == GPIO_IRQ_FALLING) { EXTI->FTSR1 |= (EXTI_FTSR1_FT0 << pin); gpio_irq_callbacks[pin].falling = callback; } else { EXTI->RTSR1 |= (EXTI_RTSR1_RT0 << pin); gpio_irq_callbacks[pin].rising = callback; } EXTI->EXTICR[pin / 4] |= (port << (8 * (pin % 4))); EXTI->IMR1 |= (EXTI_IMR1_IM0 << pin); } uint32_t hw_gpio_get (gpio_id_t id) { GPIO_TypeDef *gpio = ((GPIO_TypeDef *) (gpios[(id >> 4) & 0x07])); uint8_t pin = (id & 0x0F); return gpio->IDR & (GPIO_IDR_ID0 << pin); } void hw_gpio_set (gpio_id_t id) { GPIO_TypeDef *gpio = ((GPIO_TypeDef *) (gpios[(id >> 4) & 0x07])); uint8_t pin = (id & 0x0F); gpio->BSRR = (GPIO_BSRR_BS0 << pin); } void hw_gpio_reset (gpio_id_t id) { GPIO_TypeDef *gpio = ((GPIO_TypeDef *) (gpios[(id >> 4) & 0x07])); uint8_t pin = (id & 0x0F); gpio->BSRR = (GPIO_BSRR_BR0 << pin); } void hw_uart_read (uint8_t *data, int length) { for (int i = 0; i < length; i++) { while (!(USART1->ISR & USART_ISR_RXNE_RXFNE)); *data++ = (uint8_t) (USART1->RDR); } } void hw_uart_write (uint8_t *data, int length) { for (int i = 0; i < length; i++) { while (!(USART1->ISR & USART_ISR_TXE_TXFNF)); USART1->TDR = *data++; } } void hw_uart_wait_busy (void) { while (!(USART1->ISR & USART_ISR_TC)); } void hw_spi_start (void) { hw_gpio_reset(GPIO_ID_SPI_CS); } void hw_spi_stop (void) { while (SPI1->SR & SPI_SR_BSY); hw_gpio_set(GPIO_ID_SPI_CS); } void hw_spi_trx (uint8_t *data, int length, spi_direction_t direction) { volatile uint8_t dummy __attribute__((unused)); DMA1_Channel1->CNDTR = length; DMA1_Channel2->CNDTR = length; if (direction == SPI_TX) { DMA1_Channel1->CMAR = (uint32_t) (&dummy); DMA1_Channel1->CCR = DMA_CCR_EN; DMA1_Channel2->CMAR = (uint32_t) (data); DMA1_Channel2->CCR = (DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_EN); } else { DMA1_Channel1->CMAR = (uint32_t) (data); DMA1_Channel1->CCR = (DMA_CCR_MINC | DMA_CCR_EN); DMA1_Channel2->CMAR = (uint32_t) (&dummy); DMA1_Channel2->CCR = (DMA_CCR_DIR | DMA_CCR_EN); } while (DMA1_Channel1->CNDTR || DMA1_Channel2->CNDTR); DMA1_Channel1->CCR = 0; DMA1_Channel2->CCR = 0; } void hw_i2c_read (uint8_t i2c_address, uint8_t address, uint8_t *data, uint8_t length, void (*callback)(void)) { i2c_data_rxptr = data; i2c_callback = callback; I2C1->TXDR = address; i2c_next_cr2 = ( I2C_CR2_AUTOEND | (length << I2C_CR2_NBYTES_Pos) | I2C_CR2_START | I2C_CR2_RD_WRN | (i2c_address << I2C_CR2_SADD_Pos) ); I2C1->CR2 = ( (1 << I2C_CR2_NBYTES_Pos) | I2C_CR2_START | (i2c_address << I2C_CR2_SADD_Pos) ); } void hw_i2c_write (uint8_t i2c_address, uint8_t address, uint8_t *data, uint8_t length, void (*callback)(void)) { i2c_data_txptr = data; i2c_callback = callback; I2C1->TXDR = address; I2C1->CR2 = ( I2C_CR2_AUTOEND | ((length + 1) << I2C_CR2_NBYTES_Pos) | I2C_CR2_START | (i2c_address << I2C_CR2_SADD_Pos) ); } uint32_t hw_i2c_get_error (void) { return (I2C1->ISR & I2C_ISR_NACKF); } void hw_i2c_raw (uint8_t i2c_address, uint8_t *tx_data, uint8_t tx_length, uint8_t *rx_data, uint8_t rx_length) { while (I2C1->ISR & I2C_ISR_BUSY); if (tx_length > 0) { I2C1->ICR = I2C_ICR_NACKCF; I2C1->CR2 = ( ((rx_length == 0) ? I2C_CR2_AUTOEND : 0) | (tx_length << I2C_CR2_NBYTES_Pos) | I2C_CR2_START | (i2c_address << I2C_CR2_SADD_Pos) ); for (int i = 0; i < tx_length; i++) { while (!(I2C1->ISR & I2C_ISR_TXIS)); I2C1->TXDR = *tx_data++; } if (!(I2C1->CR2 & I2C_CR2_AUTOEND)) { while (!(I2C1->ISR & (I2C_ISR_NACKF | I2C_ISR_TC))); } } if (rx_length > 0) { I2C1->CR2 = ( I2C_CR2_AUTOEND | (rx_length << I2C_CR2_NBYTES_Pos) | I2C_CR2_START | I2C_CR2_RD_WRN | (i2c_address << I2C_CR2_SADD_Pos) ); for (int i = 0; i < rx_length; i++) { while (!(I2C1->ISR & I2C_ISR_RXNE)); *rx_data++ = I2C1->RXDR; } } if ((tx_length > 0) || (rx_length > 0)) { while (!(I2C1->ISR & I2C_ISR_STOPF)); } } void hw_i2c_disable_irq (void) { NVIC_DisableIRQ(I2C1_IRQn); } void hw_i2c_enable_irq (void) { NVIC_EnableIRQ(I2C1_IRQn); } void hw_tim_setup (tim_id_t id, uint16_t delay, void (*callback)(void)) { if (delay == 0) { if (callback) { callback(); } return; } TIM_TypeDef *tim = ((TIM_TypeDef *) (tims[id])); tim->CR1 = (TIM_CR1_OPM | TIM_CR1_URS); tim->PSC = (64000 - 1); tim->ARR = delay; tim->DIER = TIM_DIER_UIE; tim->EGR = TIM_EGR_UG; tim->SR = 0; tim->CR1 |= TIM_CR1_CEN; tim_callbacks[id] = callback; } void hw_tim_stop (tim_id_t id) { TIM_TypeDef *tim = ((TIM_TypeDef *) (tims[id])); tim->CR1 &= ~(TIM_CR1_CEN); tim_callbacks[id] = 0; } void hw_tim_disable_irq (tim_id_t id) { switch (id) { case TIM_ID_CIC: NVIC_DisableIRQ(TIM14_IRQn); break; case TIM_ID_RTC: NVIC_DisableIRQ(TIM16_IRQn); break; case TIM_ID_SD: NVIC_DisableIRQ(TIM17_IRQn); break; case TIM_ID_DD: NVIC_DisableIRQ(TIM3_IRQn); break; case TIM_ID_LED: NVIC_DisableIRQ(TIM1_BRK_UP_TRG_COM_IRQn); break; default: break; } } void hw_tim_enable_irq (tim_id_t id) { switch (id) { case TIM_ID_CIC: NVIC_EnableIRQ(TIM14_IRQn); break; case TIM_ID_RTC: NVIC_EnableIRQ(TIM16_IRQn); break; case TIM_ID_SD: NVIC_EnableIRQ(TIM17_IRQn); break; case TIM_ID_DD: NVIC_EnableIRQ(TIM3_IRQn); break; case TIM_ID_LED: NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn); break; default: break; } } void hw_delay_ms (uint32_t ms) { SysTick->VAL = 0; for (uint32_t i = 0; i < ms; i++) { while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk)); } } void hw_crc32_reset (void) { CRC->CR |= CRC_CR_RESET; } uint32_t hw_crc32_calculate (uint8_t *data, uint32_t length) { for (uint32_t i = 0; i < length; i++) { *(__IO uint8_t *) (&CRC->DR) = data[i]; } return (CRC->DR ^ 0xFFFFFFFF); } uint32_t hw_flash_size (void) { return FLASH_SIZE; } static void hw_flash_unlock (void) { while (FLASH->SR & FLASH_SR_BSY1); if (FLASH->CR & FLASH_CR_LOCK) { FLASH->KEYR = 0x45670123; __ISB(); FLASH->KEYR = 0xCDEF89AB; } } void hw_flash_erase (void) { hw_flash_unlock(); FLASH->CR |= (FLASH_CR_STRT | FLASH_CR_MER1); while (FLASH->SR & FLASH_SR_BSY1); } void hw_flash_program (uint32_t offset, hw_flash_t value) { hw_flash_unlock(); FLASH->CR |= FLASH_CR_PG; *(__IO uint32_t *) (FLASH_BASE + offset) = ((value) & 0xFFFFFFFF); __ISB(); *(__IO uint32_t *) (FLASH_BASE + offset + 4) = ((value >> 32) & 0xFFFFFFFF); while (FLASH->SR & FLASH_SR_BSY1); FLASH->CR &= ~(FLASH_CR_PG); } hw_flash_t hw_flash_read (uint32_t offset) { return *(uint64_t *) (FLASH_BASE + offset); } void hw_reset (loader_parameters_t *parameters) { if (parameters != NULL) { RCC->APBENR1 |= RCC_APBENR1_PWREN | RCC_APBENR1_RTCAPBEN; PWR->CR1 |= PWR_CR1_DBP; TAMP->BKP0R = parameters->magic; TAMP->BKP1R = parameters->flags; TAMP->BKP2R = parameters->mcu_address; TAMP->BKP3R = parameters->fpga_address; TAMP->BKP4R = parameters->bootloader_address; PWR->CR1 &= ~(PWR_CR1_DBP); RCC->APBENR1 &= ~(RCC_APBENR1_PWREN | RCC_APBENR1_RTCAPBEN); } NVIC_SystemReset(); } void hw_loader_get_parameters (loader_parameters_t *parameters) { RCC->APBENR1 |= RCC_APBENR1_PWREN | RCC_APBENR1_RTCAPBEN; parameters->magic = TAMP->BKP0R; parameters->flags = TAMP->BKP1R; parameters->mcu_address = TAMP->BKP2R; parameters->fpga_address = TAMP->BKP3R; parameters->bootloader_address = TAMP->BKP4R; PWR->CR1 |= PWR_CR1_DBP; TAMP->BKP0R = 0; TAMP->BKP1R = 0; TAMP->BKP2R = 0; TAMP->BKP3R = 0; TAMP->BKP4R = 0; PWR->CR1 &= ~(PWR_CR1_DBP); RCC->APBENR1 &= ~(RCC_APBENR1_PWREN | RCC_APBENR1_RTCAPBEN); } static void hw_init_mcu (void) { FLASH->ACR |= (FLASH_ACR_PRFTEN | (2 << FLASH_ACR_LATENCY_Pos)); while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != (2 << FLASH_ACR_LATENCY_Pos)); RCC->PLLCFGR = ( ((2 - 1) << RCC_PLLCFGR_PLLR_Pos) | RCC_PLLCFGR_PLLREN | (16 << RCC_PLLCFGR_PLLN_Pos) | ((2 - 1) << RCC_PLLCFGR_PLLM_Pos) | RCC_PLLCFGR_PLLSRC_HSI ); RCC->CR |= RCC_CR_PLLON; while ((RCC->CR & RCC_CR_PLLRDY_Msk) != RCC_CR_PLLRDY); RCC->CFGR = RCC_CFGR_SW_1; while ((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_1); RCC->IOPENR |= RCC_IOPENR_GPIOAEN | RCC_IOPENR_GPIOBEN; SysTick->LOAD = (((64000000 / 1000)) - 1); SysTick->VAL = 0; SysTick->CTRL = (SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk); hw_gpio_init(GPIO_ID_LED, GPIO_OUTPUT, GPIO_PP, GPIO_SPEED_VLOW, GPIO_PULL_NONE, GPIO_AF_0, 0); } static void hw_init_spi (void) { RCC->AHBENR |= RCC_AHBENR_DMA1EN; RCC->APBENR2 |= RCC_APBENR2_SPI1EN; DMAMUX1_Channel0->CCR = (16 << DMAMUX_CxCR_DMAREQ_ID_Pos); DMAMUX1_Channel1->CCR = (17 << DMAMUX_CxCR_DMAREQ_ID_Pos); DMA1_Channel1->CPAR = (uint32_t) (&SPI1->DR); DMA1_Channel2->CPAR = (uint32_t) (&SPI1->DR); SPI1->CR2 = ( SPI_CR2_FRXTH | (8 - 1) << SPI_CR2_DS_Pos | SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN ); SPI1->CR1 = ( SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_BR_1 | SPI_CR1_SPE | SPI_CR1_MSTR | SPI_CR1_CPHA ); hw_gpio_init(GPIO_ID_SPI_CS, GPIO_OUTPUT, GPIO_PP, GPIO_SPEED_HIGH, GPIO_PULL_NONE, GPIO_AF_0, 1); hw_gpio_init(GPIO_ID_SPI_CLK, GPIO_ALT, GPIO_PP, GPIO_SPEED_HIGH, GPIO_PULL_NONE, GPIO_AF_0, 0); hw_gpio_init(GPIO_ID_SPI_MISO, GPIO_ALT, GPIO_PP, GPIO_SPEED_HIGH, GPIO_PULL_DOWN, GPIO_AF_0, 0); hw_gpio_init(GPIO_ID_SPI_MOSI, GPIO_ALT, GPIO_PP, GPIO_SPEED_HIGH, GPIO_PULL_NONE, GPIO_AF_0, 0); } static void hw_init_i2c (void) { RCC->APBENR1 |= RCC_APBENR1_I2C1EN; I2C1->TIMINGR = 0x00C12166UL; I2C1->CR1 |= (I2C_CR1_TCIE | I2C_CR1_STOPIE | I2C_CR1_RXIE | I2C_CR1_TXIE | I2C_CR1_PE); hw_gpio_init(GPIO_ID_I2C_SCL, GPIO_ALT, GPIO_OD, GPIO_SPEED_VLOW, GPIO_PULL_NONE, GPIO_AF_6, 0); hw_gpio_init(GPIO_ID_I2C_SDA, GPIO_ALT, GPIO_OD, GPIO_SPEED_VLOW, GPIO_PULL_NONE, GPIO_AF_6, 0); } static void hw_init_uart (void) { RCC->APBENR2 |= (RCC_APBENR2_USART1EN | RCC_APBENR2_SYSCFGEN); SYSCFG->CFGR1 |= (SYSCFG_CFGR1_PA12_RMP | SYSCFG_CFGR1_PA11_RMP); hw_gpio_init(GPIO_ID_UART_TX, GPIO_ALT, GPIO_PP, GPIO_SPEED_LOW, GPIO_PULL_UP, GPIO_AF_1, 0); hw_gpio_init(GPIO_ID_UART_RX, GPIO_ALT, GPIO_PP, GPIO_SPEED_LOW, GPIO_PULL_UP, GPIO_AF_1, 0); USART1->BRR = (64000000UL) / UART_BAUD; USART1->RQR = USART_RQR_TXFRQ | USART_RQR_RXFRQ; USART1->CR1 = USART_CR1_FIFOEN | USART_CR1_M0 | USART_CR1_PCE | USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; } static void hw_init_tim (void) { RCC->APBENR1 |= ( RCC_APBENR1_DBGEN | RCC_APBENR1_TIM3EN ); RCC->APBENR2 |= ( RCC_APBENR2_TIM17EN | RCC_APBENR2_TIM16EN | RCC_APBENR2_TIM14EN | RCC_APBENR2_USART1EN | RCC_APBENR2_TIM1EN ); DBG->APBFZ1 |= DBG_APB_FZ1_DBG_TIM3_STOP; DBG->APBFZ2 |= ( DBG_APB_FZ2_DBG_TIM17_STOP | DBG_APB_FZ2_DBG_TIM16_STOP | DBG_APB_FZ2_DBG_TIM14_STOP | DBG_APB_FZ2_DBG_TIM1_STOP ); } static void hw_init_crc (void) { RCC->AHBENR |= RCC_AHBENR_CRCEN; CRC->CR = (CRC_CR_REV_OUT | CRC_CR_REV_IN_0); } static void hw_init_misc (void) { hw_gpio_init(GPIO_ID_N64_RESET, GPIO_INPUT, GPIO_PP, GPIO_SPEED_VLOW, GPIO_PULL_DOWN, GPIO_AF_0, 0); hw_gpio_init(GPIO_ID_N64_CIC_CLK, GPIO_INPUT, GPIO_PP, GPIO_SPEED_VLOW, GPIO_PULL_DOWN, GPIO_AF_0, 0); hw_gpio_init(GPIO_ID_N64_CIC_DQ, GPIO_OUTPUT, GPIO_OD, GPIO_SPEED_VLOW, GPIO_PULL_UP, GPIO_AF_0, 1); hw_gpio_init(GPIO_ID_FPGA_INT, GPIO_INPUT, GPIO_PP, GPIO_SPEED_VLOW, GPIO_PULL_UP, GPIO_AF_0, 0); hw_gpio_init(GPIO_ID_RTC_MFP, GPIO_INPUT, GPIO_PP, GPIO_SPEED_VLOW, GPIO_PULL_UP, GPIO_AF_0, 0); } void hw_set_vector_table (uint32_t offset) { SCB->VTOR = (__IOM uint32_t) (offset); } void hw_init (void) { hw_init_mcu(); hw_init_spi(); hw_init_i2c(); hw_init_uart(); hw_init_tim(); hw_init_crc(); hw_init_misc(); NVIC_SetPriority(EXTI0_1_IRQn, 0); NVIC_SetPriority(EXTI2_3_IRQn, 1); NVIC_SetPriority(EXTI4_15_IRQn, 2); NVIC_SetPriority(I2C1_IRQn, 1); NVIC_SetPriority(TIM14_IRQn, 0); NVIC_SetPriority(TIM16_IRQn, 1); NVIC_SetPriority(TIM17_IRQn, 2); NVIC_SetPriority(TIM3_IRQn, 2); NVIC_SetPriority(TIM1_BRK_UP_TRG_COM_IRQn, 1); NVIC_EnableIRQ(EXTI0_1_IRQn); NVIC_EnableIRQ(EXTI2_3_IRQn); NVIC_EnableIRQ(EXTI4_15_IRQn); NVIC_EnableIRQ(I2C1_IRQn); NVIC_EnableIRQ(TIM14_IRQn); NVIC_EnableIRQ(TIM16_IRQn); NVIC_EnableIRQ(TIM17_IRQn); NVIC_EnableIRQ(TIM3_IRQn); NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn); } void hw_loader_init (void) { hw_init_mcu(); hw_init_spi(); } void hw_primer_init (void) { hw_init_mcu(); hw_init_spi(); hw_init_i2c(); hw_init_uart(); hw_init_crc(); } void EXTI0_1_IRQHandler (void) { for (int i = 0; i <= 1; i++) { if (EXTI->FPR1 & (EXTI_FPR1_FPIF0 << i)) { EXTI->FPR1 = (EXTI_FPR1_FPIF0 << i); if (gpio_irq_callbacks[i].falling) { gpio_irq_callbacks[i].falling(); } } if (EXTI->RPR1 & (EXTI_RPR1_RPIF0 << i)) { EXTI->RPR1 = (EXTI_RPR1_RPIF0 << i); if (gpio_irq_callbacks[i].rising) { gpio_irq_callbacks[i].rising(); } } } } void EXTI2_3_IRQHandler (void) { for (int i = 2; i <= 3; i++) { if (EXTI->FPR1 & (EXTI_FPR1_FPIF0 << i)) { EXTI->FPR1 = (EXTI_FPR1_FPIF0 << i); if (gpio_irq_callbacks[i].falling) { gpio_irq_callbacks[i].falling(); } } if (EXTI->RPR1 & (EXTI_RPR1_RPIF0 << i)) { EXTI->RPR1 = (EXTI_RPR1_RPIF0 << i); if (gpio_irq_callbacks[i].rising) { gpio_irq_callbacks[i].rising(); } } } } void EXTI4_15_IRQHandler (void) { for (int i = 4; i <= 15; i++) { if (EXTI->FPR1 & (EXTI_FPR1_FPIF0 << i)) { EXTI->FPR1 = (EXTI_FPR1_FPIF0 << i); if (gpio_irq_callbacks[i].falling) { gpio_irq_callbacks[i].falling(); } } if (EXTI->RPR1 & (EXTI_RPR1_RPIF0 << i)) { EXTI->RPR1 = (EXTI_RPR1_RPIF0 << i); if (gpio_irq_callbacks[i].rising) { gpio_irq_callbacks[i].rising(); } } } } void I2C1_IRQHandler (void) { if (I2C1->ISR & I2C_ISR_TXIS) { I2C1->TXDR = *i2c_data_txptr++; } if (I2C1->ISR & I2C_ISR_RXNE) { *i2c_data_rxptr++ = I2C1->RXDR; } if (I2C1->ISR & I2C_ISR_TC) { I2C1->CR2 = i2c_next_cr2; } if (I2C1->ISR & I2C_ISR_STOPF) { I2C1->ICR = I2C_ICR_STOPCF; if (i2c_callback) { i2c_callback(); i2c_callback = 0; } } } void TIM14_IRQHandler (void) { TIM14->SR &= ~(TIM_SR_UIF); if (tim_callbacks[0]) { tim_callbacks[0](); tim_callbacks[0] = 0; } } void TIM16_IRQHandler (void) { TIM16->SR &= ~(TIM_SR_UIF); if (tim_callbacks[1]) { tim_callbacks[1](); tim_callbacks[1] = 0; } } void TIM17_IRQHandler (void) { TIM17->SR &= ~(TIM_SR_UIF); if (tim_callbacks[2]) { tim_callbacks[2](); tim_callbacks[2] = 0; } } void TIM3_IRQHandler (void) { TIM3->SR &= ~(TIM_SR_UIF); if (tim_callbacks[3]) { tim_callbacks[3](); tim_callbacks[3] = 0; } } void TIM1_BRK_UP_TRG_COM_IRQHandler (void) { TIM1->SR &= ~(TIM_SR_UIF); if (tim_callbacks[4]) { tim_callbacks[4](); tim_callbacks[4] = 0; } }