Skip to content

Commit

Permalink
HAL refactoring part 2 (commaai#682)
Browse files Browse the repository at this point in the history
* Move harness threshold

* Move interrupt handlers

* timers.h refactor

* rtc.h refactor

* pwm.h and fan.h refactor

* clock_source is hw specific

* refactor uart.h

* macro naming

* minor fixes

* redo rtc
  • Loading branch information
briskspirit authored Jul 13, 2021
1 parent 062b271 commit eab9c9e
Show file tree
Hide file tree
Showing 21 changed files with 463 additions and 459 deletions.
1 change: 0 additions & 1 deletion board/bootstub.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
#include "config.h"

#include "drivers/pwm.h"
#include "drivers/spi.h"
#include "drivers/usb.h"

#include "early_init.h"
Expand Down
2 changes: 2 additions & 0 deletions board/bootstub_declarations.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ typedef struct board board;
typedef struct harness_configuration harness_configuration;
// No CAN support on bootloader
void can_flip_buses(uint8_t bus1, uint8_t bus2){UNUSED(bus1); UNUSED(bus2);}
void pwm_init(TIM_TypeDef *TIM, uint8_t channel);
void pwm_set(TIM_TypeDef *TIM, uint8_t channel, uint8_t percentage);
void can_set_obd(uint8_t harness_orientation, bool obd){UNUSED(harness_orientation); UNUSED(obd);}

// ********************* Globals **********************
Expand Down
34 changes: 2 additions & 32 deletions board/drivers/fan.h
Original file line number Diff line number Diff line change
@@ -1,44 +1,14 @@
// Function prototypes
void pwm_init(TIM_TypeDef *TIM, uint8_t channel);
void pwm_set(TIM_TypeDef *TIM, uint8_t channel, uint8_t percentage);

uint16_t fan_tach_counter = 0U;
uint16_t fan_rpm = 0U;

void fan_set_power(uint8_t percentage){
pwm_set(TIM3, 3, percentage);
}

uint16_t fan_tach_counter = 0U;
uint16_t fan_rpm = 0U;

// Can be way more acurate than this, but this is probably good enough for our purposes.

// Call this every second
void fan_tick(void){
// 4 interrupts per rotation
fan_rpm = fan_tach_counter * 15U;
fan_tach_counter = 0U;
}

// TACH interrupt handler
void EXTI2_IRQ_Handler(void) {
volatile unsigned int pr = EXTI->PR & (1U << 2);
if ((pr & (1U << 2)) != 0U) {
fan_tach_counter++;
}
EXTI->PR = (1U << 2);
}

void fan_init(void){
// 5000RPM * 4 tach edges / 60 seconds
REGISTER_INTERRUPT(EXTI2_IRQn, EXTI2_IRQ_Handler, 700U, FAULT_INTERRUPT_RATE_TACH)

// Init PWM speed control
pwm_init(TIM3, 3);

// Init TACH interrupt
register_set(&(SYSCFG->EXTICR[0]), SYSCFG_EXTICR1_EXTI2_PD, 0xF00U);
register_set_bits(&(EXTI->IMR), (1U << 2));
register_set_bits(&(EXTI->RTSR), (1U << 2));
register_set_bits(&(EXTI->FTSR), (1U << 2));
NVIC_EnableIRQ(EXTI2_IRQn);
}
3 changes: 0 additions & 3 deletions board/drivers/harness.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ uint8_t car_harness_status = 0U;
#define HARNESS_STATUS_NORMAL 1U
#define HARNESS_STATUS_FLIPPED 2U

// Threshold voltage (mV) for either of the SBUs to be below before deciding harness is connected
#define HARNESS_CONNECTED_THRESHOLD 2500U

struct harness_configuration {
const bool has_harness;
GPIO_TypeDef *GPIO_SBU1;
Expand Down
101 changes: 0 additions & 101 deletions board/drivers/interrupts.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,104 +56,3 @@ void init_interrupts(bool check_rate_limit){
// Init interrupt timer for a 1s interval
interrupt_timer_init();
}

// ********************* Bare interrupt handlers *********************
// Only implemented the STM32F413 interrupts for now, the STM32F203 specific ones do not fall into the scope of SIL2

void WWDG_IRQHandler(void) {handle_interrupt(WWDG_IRQn);}
void PVD_IRQHandler(void) {handle_interrupt(PVD_IRQn);}
void TAMP_STAMP_IRQHandler(void) {handle_interrupt(TAMP_STAMP_IRQn);}
void RTC_WKUP_IRQHandler(void) {handle_interrupt(RTC_WKUP_IRQn);}
void FLASH_IRQHandler(void) {handle_interrupt(FLASH_IRQn);}
void RCC_IRQHandler(void) {handle_interrupt(RCC_IRQn);}
void EXTI0_IRQHandler(void) {handle_interrupt(EXTI0_IRQn);}
void EXTI1_IRQHandler(void) {handle_interrupt(EXTI1_IRQn);}
void EXTI2_IRQHandler(void) {handle_interrupt(EXTI2_IRQn);}
void EXTI3_IRQHandler(void) {handle_interrupt(EXTI3_IRQn);}
void EXTI4_IRQHandler(void) {handle_interrupt(EXTI4_IRQn);}
void DMA1_Stream0_IRQHandler(void) {handle_interrupt(DMA1_Stream0_IRQn);}
void DMA1_Stream1_IRQHandler(void) {handle_interrupt(DMA1_Stream1_IRQn);}
void DMA1_Stream2_IRQHandler(void) {handle_interrupt(DMA1_Stream2_IRQn);}
void DMA1_Stream3_IRQHandler(void) {handle_interrupt(DMA1_Stream3_IRQn);}
void DMA1_Stream4_IRQHandler(void) {handle_interrupt(DMA1_Stream4_IRQn);}
void DMA1_Stream5_IRQHandler(void) {handle_interrupt(DMA1_Stream5_IRQn);}
void DMA1_Stream6_IRQHandler(void) {handle_interrupt(DMA1_Stream6_IRQn);}
void ADC_IRQHandler(void) {handle_interrupt(ADC_IRQn);}
void CAN1_TX_IRQHandler(void) {handle_interrupt(CAN1_TX_IRQn);}
void CAN1_RX0_IRQHandler(void) {handle_interrupt(CAN1_RX0_IRQn);}
void CAN1_RX1_IRQHandler(void) {handle_interrupt(CAN1_RX1_IRQn);}
void CAN1_SCE_IRQHandler(void) {handle_interrupt(CAN1_SCE_IRQn);}
void EXTI9_5_IRQHandler(void) {handle_interrupt(EXTI9_5_IRQn);}
void TIM1_BRK_TIM9_IRQHandler(void) {handle_interrupt(TIM1_BRK_TIM9_IRQn);}
void TIM1_UP_TIM10_IRQHandler(void) {handle_interrupt(TIM1_UP_TIM10_IRQn);}
void TIM1_TRG_COM_TIM11_IRQHandler(void) {handle_interrupt(TIM1_TRG_COM_TIM11_IRQn);}
void TIM1_CC_IRQHandler(void) {handle_interrupt(TIM1_CC_IRQn);}
void TIM2_IRQHandler(void) {handle_interrupt(TIM2_IRQn);}
void TIM3_IRQHandler(void) {handle_interrupt(TIM3_IRQn);}
void TIM4_IRQHandler(void) {handle_interrupt(TIM4_IRQn);}
void I2C1_EV_IRQHandler(void) {handle_interrupt(I2C1_EV_IRQn);}
void I2C1_ER_IRQHandler(void) {handle_interrupt(I2C1_ER_IRQn);}
void I2C2_EV_IRQHandler(void) {handle_interrupt(I2C2_EV_IRQn);}
void I2C2_ER_IRQHandler(void) {handle_interrupt(I2C2_ER_IRQn);}
void SPI1_IRQHandler(void) {handle_interrupt(SPI1_IRQn);}
void SPI2_IRQHandler(void) {handle_interrupt(SPI2_IRQn);}
void USART1_IRQHandler(void) {handle_interrupt(USART1_IRQn);}
void USART2_IRQHandler(void) {handle_interrupt(USART2_IRQn);}
void USART3_IRQHandler(void) {handle_interrupt(USART3_IRQn);}
void EXTI15_10_IRQHandler(void) {handle_interrupt(EXTI15_10_IRQn);}
void RTC_Alarm_IRQHandler(void) {handle_interrupt(RTC_Alarm_IRQn);}
void OTG_FS_WKUP_IRQHandler(void) {handle_interrupt(OTG_FS_WKUP_IRQn);}
void TIM8_BRK_TIM12_IRQHandler(void) {handle_interrupt(TIM8_BRK_TIM12_IRQn);}
void TIM8_UP_TIM13_IRQHandler(void) {handle_interrupt(TIM8_UP_TIM13_IRQn);}
void TIM8_TRG_COM_TIM14_IRQHandler(void) {handle_interrupt(TIM8_TRG_COM_TIM14_IRQn);}
void TIM8_CC_IRQHandler(void) {handle_interrupt(TIM8_CC_IRQn);}
void DMA1_Stream7_IRQHandler(void) {handle_interrupt(DMA1_Stream7_IRQn);}
void FSMC_IRQHandler(void) {handle_interrupt(FSMC_IRQn);}
void SDIO_IRQHandler(void) {handle_interrupt(SDIO_IRQn);}
void TIM5_IRQHandler(void) {handle_interrupt(TIM5_IRQn);}
void SPI3_IRQHandler(void) {handle_interrupt(SPI3_IRQn);}
void UART4_IRQHandler(void) {handle_interrupt(UART4_IRQn);}
void UART5_IRQHandler(void) {handle_interrupt(UART5_IRQn);}
void TIM6_DAC_IRQHandler(void) {handle_interrupt(TIM6_DAC_IRQn);}
void TIM7_IRQHandler(void) {handle_interrupt(TIM7_IRQn);}
void DMA2_Stream0_IRQHandler(void) {handle_interrupt(DMA2_Stream0_IRQn);}
void DMA2_Stream1_IRQHandler(void) {handle_interrupt(DMA2_Stream1_IRQn);}
void DMA2_Stream2_IRQHandler(void) {handle_interrupt(DMA2_Stream2_IRQn);}
void DMA2_Stream3_IRQHandler(void) {handle_interrupt(DMA2_Stream3_IRQn);}
void DMA2_Stream4_IRQHandler(void) {handle_interrupt(DMA2_Stream4_IRQn);}
void CAN2_TX_IRQHandler(void) {handle_interrupt(CAN2_TX_IRQn);}
void CAN2_RX0_IRQHandler(void) {handle_interrupt(CAN2_RX0_IRQn);}
void CAN2_RX1_IRQHandler(void) {handle_interrupt(CAN2_RX1_IRQn);}
void CAN2_SCE_IRQHandler(void) {handle_interrupt(CAN2_SCE_IRQn);}
void OTG_FS_IRQHandler(void) {handle_interrupt(OTG_FS_IRQn);}
void DMA2_Stream5_IRQHandler(void) {handle_interrupt(DMA2_Stream5_IRQn);}
void DMA2_Stream6_IRQHandler(void) {handle_interrupt(DMA2_Stream6_IRQn);}
void DMA2_Stream7_IRQHandler(void) {handle_interrupt(DMA2_Stream7_IRQn);}
void USART6_IRQHandler(void) {handle_interrupt(USART6_IRQn);}
void I2C3_EV_IRQHandler(void) {handle_interrupt(I2C3_EV_IRQn);}
void I2C3_ER_IRQHandler(void) {handle_interrupt(I2C3_ER_IRQn);}
#ifdef STM32F4
void DFSDM1_FLT0_IRQHandler(void) {handle_interrupt(DFSDM1_FLT0_IRQn);}
void DFSDM1_FLT1_IRQHandler(void) {handle_interrupt(DFSDM1_FLT1_IRQn);}
void CAN3_TX_IRQHandler(void) {handle_interrupt(CAN3_TX_IRQn);}
void CAN3_RX0_IRQHandler(void) {handle_interrupt(CAN3_RX0_IRQn);}
void CAN3_RX1_IRQHandler(void) {handle_interrupt(CAN3_RX1_IRQn);}
void CAN3_SCE_IRQHandler(void) {handle_interrupt(CAN3_SCE_IRQn);}
void RNG_IRQHandler(void) {handle_interrupt(RNG_IRQn);}
void FPU_IRQHandler(void) {handle_interrupt(FPU_IRQn);}
void UART7_IRQHandler(void) {handle_interrupt(UART7_IRQn);}
void UART8_IRQHandler(void) {handle_interrupt(UART8_IRQn);}
void SPI4_IRQHandler(void) {handle_interrupt(SPI4_IRQn);}
void SPI5_IRQHandler(void) {handle_interrupt(SPI5_IRQn);}
void SAI1_IRQHandler(void) {handle_interrupt(SAI1_IRQn);}
void UART9_IRQHandler(void) {handle_interrupt(UART9_IRQn);}
void UART10_IRQHandler(void) {handle_interrupt(UART10_IRQn);}
void QUADSPI_IRQHandler(void) {handle_interrupt(QUADSPI_IRQn);}
void FMPI2C1_EV_IRQHandler(void) {handle_interrupt(FMPI2C1_EV_IRQn);}
void FMPI2C1_ER_IRQHandler(void) {handle_interrupt(FMPI2C1_ER_IRQn);}
void LPTIM1_IRQHandler(void) {handle_interrupt(LPTIM1_IRQn);}
void DFSDM2_FLT0_IRQHandler(void) {handle_interrupt(DFSDM2_FLT0_IRQn);}
void DFSDM2_FLT1_IRQHandler(void) {handle_interrupt(DFSDM2_FLT1_IRQn);}
void DFSDM2_FLT2_IRQHandler(void) {handle_interrupt(DFSDM2_FLT2_IRQn);}
void DFSDM2_FLT3_IRQHandler(void) {handle_interrupt(DFSDM2_FLT3_IRQn);}
#endif
135 changes: 67 additions & 68 deletions board/drivers/rtc.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#define RCC_BDCR_OPTIONS (RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL_0 | RCC_BDCR_LSEON)
#define RCC_BDCR_MASK (RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL | RCC_BDCR_LSEMOD | RCC_BDCR_LSEBYP | RCC_BDCR_LSEON)

#define YEAR_OFFSET 2000U

Expand All @@ -14,95 +13,95 @@ typedef struct __attribute__((packed)) timestamp_t {
} timestamp_t;

uint8_t to_bcd(uint16_t value){
return (((value / 10U) & 0x0FU) << 4U) | ((value % 10U) & 0x0FU);
return (((value / 10U) & 0x0FU) << 4U) | ((value % 10U) & 0x0FU);
}

uint16_t from_bcd(uint8_t value){
return (((value & 0xF0U) >> 4U) * 10U) + (value & 0x0FU);
return (((value & 0xF0U) >> 4U) * 10U) + (value & 0x0FU);
}

void rtc_init(void){
if(current_board->has_rtc){
// Initialize RTC module and clock if not done already.
if((RCC->BDCR & RCC_BDCR_MASK) != RCC_BDCR_OPTIONS){
puts("Initializing RTC\n");
// Reset backup domain
register_set_bits(&(RCC->BDCR), RCC_BDCR_BDRST);
if(current_board->has_rtc){
// Initialize RTC module and clock if not done already.
if((RCC->BDCR & RCC_BDCR_MASK) != RCC_BDCR_OPTIONS){
puts("Initializing RTC\n");
// Reset backup domain
register_set_bits(&(RCC->BDCR), RCC_BDCR_BDRST);

// Disable write protection
register_set_bits(&(PWR->CR), PWR_CR_DBP);
// Disable write protection
disable_bdomain_protection();

// Clear backup domain reset
register_clear_bits(&(RCC->BDCR), RCC_BDCR_BDRST);
// Clear backup domain reset
register_clear_bits(&(RCC->BDCR), RCC_BDCR_BDRST);

// Set RTC options
register_set(&(RCC->BDCR), RCC_BDCR_OPTIONS, RCC_BDCR_MASK);
// Set RTC options
register_set(&(RCC->BDCR), RCC_BDCR_OPTIONS, RCC_BDCR_MASK);

// Enable write protection
register_clear_bits(&(PWR->CR), PWR_CR_DBP);
}
// Enable write protection
enable_bdomain_protection();
}
}
}

void rtc_set_time(timestamp_t time){
if(current_board->has_rtc){
puts("Setting RTC time\n");
if(current_board->has_rtc){
puts("Setting RTC time\n");

// Disable write protection
register_set_bits(&(PWR->CR), PWR_CR_DBP);
RTC->WPR = 0xCA;
RTC->WPR = 0x53;
// Disable write protection
disable_bdomain_protection();
RTC->WPR = 0xCA;
RTC->WPR = 0x53;

// Enable initialization mode
register_set_bits(&(RTC->ISR), RTC_ISR_INIT);
while((RTC->ISR & RTC_ISR_INITF) == 0){}
// Enable initialization mode
register_set_bits(&(RTC->ISR), RTC_ISR_INIT);
while((RTC->ISR & RTC_ISR_INITF) == 0){}

// Set time
RTC->TR = (to_bcd(time.hour) << RTC_TR_HU_Pos) | (to_bcd(time.minute) << RTC_TR_MNU_Pos) | (to_bcd(time.second) << RTC_TR_SU_Pos);
RTC->DR = (to_bcd(time.year - YEAR_OFFSET) << RTC_DR_YU_Pos) | (time.weekday << RTC_DR_WDU_Pos) | (to_bcd(time.month) << RTC_DR_MU_Pos) | (to_bcd(time.day) << RTC_DR_DU_Pos);
// Set time
RTC->TR = (to_bcd(time.hour) << RTC_TR_HU_Pos) | (to_bcd(time.minute) << RTC_TR_MNU_Pos) | (to_bcd(time.second) << RTC_TR_SU_Pos);
RTC->DR = (to_bcd(time.year - YEAR_OFFSET) << RTC_DR_YU_Pos) | (time.weekday << RTC_DR_WDU_Pos) | (to_bcd(time.month) << RTC_DR_MU_Pos) | (to_bcd(time.day) << RTC_DR_DU_Pos);

// Set options
register_set(&(RTC->CR), 0U, 0xFCFFFFU);
// Set options
register_set(&(RTC->CR), 0U, 0xFCFFFFU);

// Disable initalization mode
register_clear_bits(&(RTC->ISR), RTC_ISR_INIT);
// Disable initalization mode
register_clear_bits(&(RTC->ISR), RTC_ISR_INIT);

// Wait for synchronization
while((RTC->ISR & RTC_ISR_RSF) == 0){}
// Wait for synchronization
while((RTC->ISR & RTC_ISR_RSF) == 0){}

// Re-enable write protection
RTC->WPR = 0x00;
register_clear_bits(&(PWR->CR), PWR_CR_DBP);
}
// Re-enable write protection
RTC->WPR = 0x00;
enable_bdomain_protection();
}
}

timestamp_t rtc_get_time(void){
timestamp_t result;
// Init with zero values in case there is no RTC running
result.year = 0U;
result.month = 0U;
result.day = 0U;
result.weekday = 0U;
result.hour = 0U;
result.minute = 0U;
result.second = 0U;

if(current_board->has_rtc){
// Wait until the register sync flag is set
while((RTC->ISR & RTC_ISR_RSF) == 0){}

// Read time and date registers. Since our HSE > 7*LSE, this should be fine.
uint32_t time = RTC->TR;
uint32_t date = RTC->DR;

// Parse values
result.year = from_bcd((date & (RTC_DR_YT | RTC_DR_YU)) >> RTC_DR_YU_Pos) + YEAR_OFFSET;
result.month = from_bcd((date & (RTC_DR_MT | RTC_DR_MU)) >> RTC_DR_MU_Pos);
result.day = from_bcd((date & (RTC_DR_DT | RTC_DR_DU)) >> RTC_DR_DU_Pos);
result.weekday = ((date & RTC_DR_WDU) >> RTC_DR_WDU_Pos);
result.hour = from_bcd((time & (RTC_TR_HT | RTC_TR_HU)) >> RTC_TR_HU_Pos);
result.minute = from_bcd((time & (RTC_TR_MNT | RTC_TR_MNU)) >> RTC_TR_MNU_Pos);
result.second = from_bcd((time & (RTC_TR_ST | RTC_TR_SU)) >> RTC_TR_SU_Pos);
}
return result;
timestamp_t result;
// Init with zero values in case there is no RTC running
result.year = 0U;
result.month = 0U;
result.day = 0U;
result.weekday = 0U;
result.hour = 0U;
result.minute = 0U;
result.second = 0U;

if(current_board->has_rtc){
// Wait until the register sync flag is set
while((RTC->ISR & RTC_ISR_RSF) == 0){}

// Read time and date registers. Since our HSE > 7*LSE, this should be fine.
uint32_t time = RTC->TR;
uint32_t date = RTC->DR;

// Parse values
result.year = from_bcd((date & (RTC_DR_YT | RTC_DR_YU)) >> RTC_DR_YU_Pos) + YEAR_OFFSET;
result.month = from_bcd((date & (RTC_DR_MT | RTC_DR_MU)) >> RTC_DR_MU_Pos);
result.day = from_bcd((date & (RTC_DR_DT | RTC_DR_DU)) >> RTC_DR_DU_Pos);
result.weekday = ((date & RTC_DR_WDU) >> RTC_DR_WDU_Pos);
result.hour = from_bcd((time & (RTC_TR_HT | RTC_TR_HU)) >> RTC_TR_HU_Pos);
result.minute = from_bcd((time & (RTC_TR_MNT | RTC_TR_MNU)) >> RTC_TR_MNU_Pos);
result.second = from_bcd((time & (RTC_TR_ST | RTC_TR_SU)) >> RTC_TR_SU_Pos);
}
return result;
}
2 changes: 1 addition & 1 deletion board/drivers/timers.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ void microsecond_timer_init(void) {
}

void interrupt_timer_init(void) {
register_set_bits(&(RCC->APB1ENR), RCC_APB1ENR_TIM6EN); // Enable interrupt timer peripheral
enable_interrupt_timer();
REGISTER_INTERRUPT(INTERRUPT_TIMER_IRQ, interrupt_timer_handler, 1, FAULT_INTERRUPT_RATE_INTERRUPTS)
register_set(&(INTERRUPT_TIMER->PSC), ((uint16_t)(15.25*APB1_FREQ)-1U), 0xFFFFU);
register_set(&(INTERRUPT_TIMER->DIER), TIM_DIER_UIE, 0x5F5FU);
Expand Down
Loading

0 comments on commit eab9c9e

Please sign in to comment.