Mateusz Faderewski 5b85b0f661
[SC64][SW] Added board bring-up via UART header (#20)
* [SC64][SW] Added board bring-up via UART header

* [SC64][SW] Made I2C in primer stable

* [SC64][SW] LCMXO2 primer fixes

* [SC64][SW] SC64 primer PC software

* [SC64][SW] Added primer.py to release package

* [SC64][SW] Fixed FPGA refresh

* [SC64][SW] Changed release package contents
2023-01-21 04:08:15 +01:00

677 lines
20 KiB
C

#include <stddef.h>
#include <stm32g0xx.h>
#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;
}
}