From 91d9db6a4ebf2c4022c6742763e00808491fb1ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Mon, 30 Nov 2020 00:01:26 +0100 Subject: [PATCH] Make Safety ADC use sequnece feature of ADC and use DMA to write data --- stm-firmware/adc-meas.c | 2 +- .../periph-config/safety-adc-hwcfg.h | 3 + .../reflow-controller/safety/safety-adc.h | 10 +- .../reflow-controller/safety/safety-config.h | 4 +- stm-firmware/main.c | 2 +- stm-firmware/safety/safety-adc.c | 103 ++++++++++++------ stm-firmware/safety/safety-controller.c | 51 +++------ 7 files changed, 101 insertions(+), 74 deletions(-) diff --git a/stm-firmware/adc-meas.c b/stm-firmware/adc-meas.c index 816b993..aa42058 100644 --- a/stm-firmware/adc-meas.c +++ b/stm-firmware/adc-meas.c @@ -382,7 +382,7 @@ void DMA2_Stream0_IRQHandler(void) uint32_t lisr; float adc_val; - lisr = DMA2->LISR; + lisr = DMA2->LISR & (0x3F); DMA2->LIFCR = lisr; if (lisr & DMA_LISR_TCIF0) { diff --git a/stm-firmware/include/reflow-controller/periph-config/safety-adc-hwcfg.h b/stm-firmware/include/reflow-controller/periph-config/safety-adc-hwcfg.h index 26a23c8..4b362d6 100644 --- a/stm-firmware/include/reflow-controller/periph-config/safety-adc-hwcfg.h +++ b/stm-firmware/include/reflow-controller/periph-config/safety-adc-hwcfg.h @@ -34,5 +34,8 @@ #define SAFETY_ADC_TEMP_NOM_MV 760.0f #define SAFETY_ADC_TEMP_MV_SLOPE 2.5f +#define SAFETY_ADC_NUM_OF_CHANNELS 2 +#define SAFETY_ADC_CHANNELS TEMP_CHANNEL_NUM, INT_REF_CHANNEL_NUM + #endif /* __SAFETY_ADC_HWCFG_H__ */ diff --git a/stm-firmware/include/reflow-controller/safety/safety-adc.h b/stm-firmware/include/reflow-controller/safety/safety-adc.h index bcbb2e0..0bf4645 100644 --- a/stm-firmware/include/reflow-controller/safety/safety-adc.h +++ b/stm-firmware/include/reflow-controller/safety/safety-adc.h @@ -31,20 +31,20 @@ enum safety_adc_meas_channel {SAFETY_ADC_MEAS_VREF, SAFETY_ADC_MEAS_TEMP}; -void safety_adc_init(); +void safety_adc_init(void); -void safety_adc_deinit(); +void safety_adc_deinit(void); -void safety_adc_trigger_meas(enum safety_adc_meas_channel measurement); +void safety_adc_trigger_meas(void); /** * @brief Poll ADC result. * @param results adc results * @return 1 if measurement successful, 0 if not ready, -1 if ADC aborted or not started */ -int safety_adc_poll_result(uint16_t *adc_result); +int safety_adc_poll_result(void); -enum safety_adc_check_result handle_safety_adc(); +const uint16_t *safety_adc_get_values(void); float safety_adc_convert_channel(enum safety_adc_meas_channel channel, uint16_t analog_value); diff --git a/stm-firmware/include/reflow-controller/safety/safety-config.h b/stm-firmware/include/reflow-controller/safety/safety-config.h index 9fb01f6..f97a055 100644 --- a/stm-firmware/include/reflow-controller/safety/safety-config.h +++ b/stm-firmware/include/reflow-controller/safety/safety-config.h @@ -101,7 +101,7 @@ enum analog_value_monitor { */ #define MEAS_ADC_SAFETY_FLAG_KEY 0xe554dac3UL -#define SAFETY_CONTROLLER_ADC_DELAY_MS 120 +#define SAFETY_CONTROLLER_ADC_DELAY_MS 250 #define SAFETY_CONFIG_DEFAULT_PERSIST ERR_FLAG_PERSIST_ENTRY(ERR_FLAG_MEAS_ADC_OFF, false), \ ERR_FLAG_PERSIST_ENTRY(ERR_FLAG_MEAS_ADC_WATCHDOG, false), \ @@ -132,7 +132,7 @@ enum analog_value_monitor { ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_STACK, SAFETY_FLAG_CONFIG_WEIGHT_PANIC), \ ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_SAFETY_ADC, SAFETY_FLAG_CONFIG_WEIGHT_PANIC), \ ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_SYSTICK, SAFETY_FLAG_CONFIG_WEIGHT_PANIC), \ - /* Watchdog timeout is not handled perioodically, but only on startup. + /* Watchdog timeout is not handled periodically, but only on startup. * Therefore, it is not listed here */\ ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_WTCHDG_FIRED, SAFETY_FLAG_CONFIG_WEIGHT_NONE), \ ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_UNCAL, SAFETY_FLAG_CONFIG_WEIGHT_NONE), \ diff --git a/stm-firmware/main.c b/stm-firmware/main.c index e2c4f84..cb055ec 100644 --- a/stm-firmware/main.c +++ b/stm-firmware/main.c @@ -233,7 +233,7 @@ void sdio_wait_ms(uint32_t ms) */ void DMA2_Stream7_IRQHandler(void) { - uint32_t hisr = DMA2->HISR; + uint32_t hisr = DMA2->HISR & (0x3F << 22); DMA2->HIFCR = hisr; diff --git a/stm-firmware/safety/safety-adc.c b/stm-firmware/safety/safety-adc.c index 5f83888..4486933 100644 --- a/stm-firmware/safety/safety-adc.c +++ b/stm-firmware/safety/safety-adc.c @@ -28,9 +28,17 @@ #include #include -void safety_adc_init() +static const uint8_t safety_adc_channels[SAFETY_ADC_NUM_OF_CHANNELS] = {SAFETY_ADC_CHANNELS}; +static volatile uint8_t safety_adc_conversion_complete; +static volatile uint8_t safety_adc_triggered; +static volatile uint16_t safety_adc_conversions[SAFETY_ADC_NUM_OF_CHANNELS]; + +void safety_adc_init(void) { + int i; + rcc_manager_enable_clock(&RCC->APB2ENR, BITMASK_TO_BITNO(SAFETY_ADC_ADC_RCC_MASK)); + rcc_manager_enable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(RCC_AHB1ENR_DMA2EN)); /* Enable temperature and VREFINT measurement */ ADC->CCR |= ADC_CCR_TSVREFE; @@ -38,17 +46,48 @@ void safety_adc_init() /* Set sample time for channels 16 and 17 */ SAFETY_ADC_ADC_PERIPHERAL->SMPR1 |= ADC_SMPR1_SMP17 | ADC_SMPR1_SMP16; - /* Standard sequence. One measurement */ - SAFETY_ADC_ADC_PERIPHERAL->SQR1 = 0UL; + /* Standard sequence. Measure all channels in one sequence */ + SAFETY_ADC_ADC_PERIPHERAL->SQR1 = (SAFETY_ADC_NUM_OF_CHANNELS - 1) << 20 ; + SAFETY_ADC_ADC_PERIPHERAL->SQR2 = 0UL; + SAFETY_ADC_ADC_PERIPHERAL->SQR3 = 0UL; + + for (i = 0; i < SAFETY_ADC_NUM_OF_CHANNELS; i++) { + switch (i) { + case 0 ... 5: + SAFETY_ADC_ADC_PERIPHERAL->SQR3 |= safety_adc_channels[i] << (i * 5); + break; + case 6 ... 11: + SAFETY_ADC_ADC_PERIPHERAL->SQR2 |= safety_adc_channels[i] << ((i-6) * 5); + break; + case 12 ... 15: + SAFETY_ADC_ADC_PERIPHERAL->SQR1 |= safety_adc_channels[i] << ((i-12) * 5); + break; + } + } + + safety_adc_conversion_complete = 0; + safety_adc_triggered = 0; + + /* Setup the DMA to move the data */ + DMA2_Stream4->PAR = (uint32_t)&SAFETY_ADC_ADC_PERIPHERAL->DR; + DMA2_Stream4->M0AR = (uint32_t)safety_adc_conversions; + DMA2_Stream4->NDTR = SAFETY_ADC_NUM_OF_CHANNELS; + DMA2_Stream4->CR = DMA_SxCR_PL_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC | DMA_SxCR_CIRC | DMA_SxCR_TCIE | DMA_SxCR_EN; + NVIC_EnableIRQ(DMA2_Stream4_IRQn); + + /* Enable ADC */ + SAFETY_ADC_ADC_PERIPHERAL->CR2 = ADC_CR2_ADON | ADC_CR2_DMA | ADC_CR2_DDS; } -void safety_adc_deinit() +void safety_adc_deinit(void) { SAFETY_ADC_ADC_PERIPHERAL->CR1 = 0UL; SAFETY_ADC_ADC_PERIPHERAL->CR2 = 0UL; SAFETY_ADC_ADC_PERIPHERAL->SMPR1 = 0UL; - rcc_manager_enable_clock(&RCC->APB1ENR, BITMASK_TO_BITNO(RCC_APB2ENR_ADC2EN)); + rcc_manager_disable_clock(&RCC->APB1ENR, BITMASK_TO_BITNO(RCC_APB2ENR_ADC2EN)); + DMA2_Stream4->CR = 0; + rcc_manager_disable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(RCC_AHB1ENR_DMA2EN)); } float safety_adc_convert_channel(enum safety_adc_meas_channel channel, uint16_t analog_value) @@ -72,42 +111,44 @@ float safety_adc_convert_channel(enum safety_adc_meas_channel channel, uint16_t return converted_val; } -int safety_adc_poll_result(uint16_t *adc_result) +int safety_adc_poll_result(void) { - int ret = 0; + if (safety_adc_triggered) + return 0; - if (!adc_result) - return -1000; - - if (!(SAFETY_ADC_ADC_PERIPHERAL->CR2 & ADC_CR2_ADON)) { + if (safety_adc_conversion_complete) + return 1; + else return -1; - } - - if (SAFETY_ADC_ADC_PERIPHERAL->SR & ADC_SR_EOC) { - *adc_result = (uint16_t)SAFETY_ADC_ADC_PERIPHERAL->DR; - SAFETY_ADC_ADC_PERIPHERAL->CR2 &= ~ADC_CR2_ADON; - ret = 1; - } - - return ret; } -void safety_adc_trigger_meas(enum safety_adc_meas_channel measurement) +const uint16_t *safety_adc_get_values(void) { - switch (measurement) { - case SAFETY_ADC_MEAS_TEMP: - SAFETY_ADC_ADC_PERIPHERAL->SQR3 = TEMP_CHANNEL_NUM; - break; - case SAFETY_ADC_MEAS_VREF: - SAFETY_ADC_ADC_PERIPHERAL->SQR3 = INT_REF_CHANNEL_NUM; - break; - default: - return; - } + safety_adc_conversion_complete = 0; + return (const uint16_t *)safety_adc_conversions; +} +void safety_adc_trigger_meas(void) +{ + safety_adc_conversion_complete = 0; + + SAFETY_ADC_ADC_PERIPHERAL->CR1 |= ADC_CR1_SCAN; SAFETY_ADC_ADC_PERIPHERAL->CR2 |= ADC_CR2_ADON; SAFETY_ADC_ADC_PERIPHERAL->CR2 |= ADC_CR2_SWSTART; + safety_adc_triggered = 1; } +void DMA2_Stream4_IRQHandler() +{ + uint32_t hisr; + + hisr = DMA2->HISR & 0x3F; + DMA2->HIFCR = hisr; + + if (hisr & DMA_HISR_TCIF4) { + safety_adc_triggered = 0; + safety_adc_conversion_complete = 1; + } +} /** @} */ diff --git a/stm-firmware/safety/safety-controller.c b/stm-firmware/safety/safety-controller.c index 608de44..25ffa6c 100644 --- a/stm-firmware/safety/safety-controller.c +++ b/stm-firmware/safety/safety-controller.c @@ -536,46 +536,29 @@ static void safety_controller_check_stack() static void safety_controller_handle_safety_adc() { - static enum safety_adc_meas_channel current_channel = SAFETY_ADC_MEAS_TEMP; static uint64_t last_result_timestamp = 0; + const uint16_t *channels; int poll_result; - uint16_t result; float analog_value; - poll_result = safety_adc_poll_result(&result); - if (!systick_ticks_have_passed(last_result_timestamp, SAFETY_CONTROLLER_ADC_DELAY_MS) && poll_result != 1) - return; + poll_result = safety_adc_poll_result(); - if (poll_result) { - if (poll_result == -1) { - switch (current_channel) { - case SAFETY_ADC_MEAS_TEMP: - current_channel = SAFETY_ADC_MEAS_VREF; - break; - case SAFETY_ADC_MEAS_VREF: - /* Expected fallthru */ - default: - current_channel = SAFETY_ADC_MEAS_TEMP; - break; - } - safety_adc_trigger_meas(current_channel); - } else if (poll_result == 1) { - last_result_timestamp = systick_get_global_tick(); - analog_value = safety_adc_convert_channel(current_channel, result); - safety_controller_report_timing(ERR_TIMING_SAFETY_ADC); - switch (current_channel) { - case SAFETY_ADC_MEAS_TEMP: - safety_controller_report_analog_value(ERR_AMON_UC_TEMP, analog_value); - break; - case SAFETY_ADC_MEAS_VREF: - safety_controller_report_analog_value(ERR_AMON_VREF, analog_value); - break; - default: - safety_controller_report_error(ERR_FLAG_SAFETY_ADC); - break; - } - } + if (poll_result == 1) { + /* Data available */ + channels = safety_adc_get_values(); + analog_value = safety_adc_convert_channel(SAFETY_ADC_MEAS_TEMP, channels[0]); + safety_controller_report_analog_value(ERR_AMON_UC_TEMP, analog_value); + analog_value = safety_adc_convert_channel(SAFETY_ADC_MEAS_VREF, channels[1]); + safety_controller_report_analog_value(ERR_AMON_VREF, analog_value); + last_result_timestamp = systick_get_global_tick(); + safety_controller_report_timing(ERR_TIMING_SAFETY_ADC); } + + if (systick_ticks_have_passed(last_result_timestamp, SAFETY_CONTROLLER_ADC_DELAY_MS)) { + if (poll_result != 1 && poll_result != 0) + safety_adc_trigger_meas(); + } + } /**