Make Safety ADC use sequnece feature of ADC and use DMA to write data
This commit is contained in:
parent
898feac168
commit
91d9db6a4e
@ -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) {
|
||||
|
@ -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__ */
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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), \
|
||||
|
@ -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;
|
||||
|
||||
|
@ -28,9 +28,17 @@
|
||||
#include <helper-macros/helper-macros.h>
|
||||
#include <stm-periph/clock-enable-manager.h>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
@ -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:
|
||||
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);
|
||||
break;
|
||||
case SAFETY_ADC_MEAS_VREF:
|
||||
analog_value = safety_adc_convert_channel(SAFETY_ADC_MEAS_VREF, channels[1]);
|
||||
safety_controller_report_analog_value(ERR_AMON_VREF, analog_value);
|
||||
break;
|
||||
default:
|
||||
safety_controller_report_error(ERR_FLAG_SAFETY_ADC);
|
||||
break;
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user