get mcu temperature within port (#2326)
* remove EFI_ADC_TEMP_SENSOR * implement * comment * s * switch adc_inputs over * header * s * I think aligned-on-stack should work ok * num channels * cache safety * move adc init too * don't compile that file for the h7 * cypress & kinetis * ports * guard against bootloader Co-authored-by: Matthew Kennedy <makenne@microsoft.com>
This commit is contained in:
parent
0cb079c2a3
commit
85fab40d21
|
@ -99,6 +99,4 @@
|
|||
#define STM32_HAS_GPIOJ TRUE
|
||||
#define STM32_HAS_GPIOK TRUE
|
||||
|
||||
#define adcSTM32EnableTSVREFE()
|
||||
|
||||
#endif /* CYPRESS_STM32_H_ */
|
||||
|
|
|
@ -98,6 +98,4 @@
|
|||
#define STM32_HAS_GPIOG KINETIS_HAS_GPIOG
|
||||
#define STM32_HAS_GPIOH KINETIS_HAS_GPIOH
|
||||
|
||||
#define adcSTM32EnableTSVREFE()
|
||||
|
||||
#endif /* KINETIS_STM32_H_ */
|
||||
|
|
|
@ -92,8 +92,6 @@ case EFI_ADC_LAST_CHANNEL:
|
|||
return "EFI_ADC_LAST_CHANNEL";
|
||||
case EFI_ADC_NONE:
|
||||
return "EFI_ADC_NONE";
|
||||
case EFI_ADC_TEMP_SENSOR:
|
||||
return "EFI_ADC_TEMP_SENSOR";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -286,9 +286,7 @@ typedef enum __attribute__ ((__packed__)) {
|
|||
EFI_ADC3_14 = 23, // PF4
|
||||
EFI_ADC3_15 = 24, // PF5
|
||||
|
||||
EFI_ADC_TEMP_SENSOR = 25, // Internal temp sensor
|
||||
|
||||
EFI_ADC_LAST_CHANNEL = 26, // Please keep this in sync with the last valid channel index!
|
||||
EFI_ADC_LAST_CHANNEL = 25, // Please keep this in sync with the last valid channel index!
|
||||
|
||||
EFI_ADC_ERROR = 50,
|
||||
} adc_channel_e;
|
||||
|
|
|
@ -76,8 +76,6 @@ case EFI_ADC_LAST_CHANNEL:
|
|||
return "EFI_ADC_LAST_CHANNEL";
|
||||
case EFI_ADC_NONE:
|
||||
return "EFI_ADC_NONE";
|
||||
case EFI_ADC_TEMP_SENSOR:
|
||||
return "EFI_ADC_TEMP_SENSOR";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -289,9 +289,7 @@ typedef enum __attribute__ ((__packed__)) {
|
|||
EFI_ADC_14 = 15, // PC4
|
||||
EFI_ADC_15 = 16, // PC5
|
||||
|
||||
EFI_ADC_TEMP_SENSOR = 17, // Internal temp sensor
|
||||
|
||||
EFI_ADC_LAST_CHANNEL = 18, // Please keep this in sync with the last valid channel index!
|
||||
EFI_ADC_LAST_CHANNEL = 17, // Please keep this in sync with the last valid channel index!
|
||||
|
||||
EFI_ADC_ERROR = 50,
|
||||
} adc_channel_e;
|
||||
|
|
|
@ -249,22 +249,10 @@ static void fast_adc_callback(GPTDriver*) {
|
|||
}
|
||||
#endif /* HAL_USE_GPT */
|
||||
|
||||
static float mcuTemperature;
|
||||
|
||||
float getMCUInternalTemperature() {
|
||||
#if defined(ADC_CHANNEL_SENSOR)
|
||||
float TemperatureValue = adcToVolts(slowAdc.getAdcValueByHwChannel(EFI_ADC_TEMP_SENSOR));
|
||||
TemperatureValue -= 0.760f; // Subtract the reference voltage at 25 deg C
|
||||
TemperatureValue /= 0.0025f; // Divide by slope 2.5mV
|
||||
|
||||
TemperatureValue += 25.0; // Add the 25 deg C
|
||||
|
||||
if (TemperatureValue > 150.0f || TemperatureValue < -50.0f) {
|
||||
firmwareError(OBD_PCM_Processor_Fault, "Invalid CPU temperature measured %f", TemperatureValue);
|
||||
}
|
||||
|
||||
return TemperatureValue;
|
||||
#else
|
||||
return 0;
|
||||
#endif /* ADC_CHANNEL_SENSOR */
|
||||
return mcuTemperature;
|
||||
}
|
||||
|
||||
int getInternalAdcValue(const char *msg, adc_channel_e hwChannel) {
|
||||
|
@ -360,11 +348,6 @@ void AdcDevice::enableChannel(adc_channel_e hwChannel) {
|
|||
int logicChannel = channelCount++;
|
||||
|
||||
size_t channelAdcIndex = hwChannel - 1;
|
||||
#if defined(STM32F7XX)
|
||||
/* the temperature sensor is internally connected to ADC1_IN18 */
|
||||
if (hwChannel == EFI_ADC_TEMP_SENSOR)
|
||||
channelAdcIndex = 18;
|
||||
#endif
|
||||
|
||||
internalAdcIndexByHardwareIndex[hwChannel] = logicChannel;
|
||||
hardwareIndexByIndernalAdcIndex[logicChannel] = hwChannel;
|
||||
|
@ -492,6 +475,9 @@ public:
|
|||
void proteusAdcHack();
|
||||
proteusAdcHack();
|
||||
#endif
|
||||
|
||||
// Ask the port to sample the MCU temperature
|
||||
mcuTemperature = getMcuTemperature();
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -608,36 +594,7 @@ void initAdcInputs() {
|
|||
addConsoleActionI("adcdebug", &setAdcDebugReporting);
|
||||
|
||||
#if EFI_INTERNAL_ADC
|
||||
/*
|
||||
* Initializes the ADC driver.
|
||||
*/
|
||||
adcStart(&ADC_SLOW_DEVICE, NULL);
|
||||
adcStart(&ADC_FAST_DEVICE, NULL);
|
||||
adcSTM32EnableTSVREFE(); // Internal temperature sensor
|
||||
#if defined(STM32F7XX)
|
||||
/* the temperature sensor is internally
|
||||
* connected to the same input channel as VBAT. Only one conversion,
|
||||
* temperature sensor or VBAT, must be selected at a time. */
|
||||
adcSTM32DisableVBATE();
|
||||
#endif
|
||||
|
||||
/* Enable this code only when you absolutly sure
|
||||
* that there is no possible errors from ADC */
|
||||
#if 0
|
||||
/* All ADC use DMA and DMA calls end_cb from its IRQ
|
||||
* If none of ADC users need error callback - we can disable
|
||||
* shared ADC IRQ and save some CPU ticks */
|
||||
if ((adcgrpcfgSlow.error_cb == NULL) &&
|
||||
(adcgrpcfgFast.error_cb == NULL)
|
||||
/* TODO: Add ADC3? */) {
|
||||
nvicDisableVector(STM32_ADC_NUMBER);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ADC_CHANNEL_SENSOR)
|
||||
// Internal temperature sensor, Available on ADC1 only
|
||||
slowAdc.enableChannel(EFI_ADC_TEMP_SENSOR);
|
||||
#endif /* ADC_CHANNEL_SENSOR */
|
||||
portInitAdc();
|
||||
|
||||
slowAdc.init();
|
||||
|
||||
|
|
|
@ -257,4 +257,17 @@ uintptr_t getFlashAddrSecondCopy() {
|
|||
return FLASH_ADDR_SECOND_COPY;
|
||||
}
|
||||
|
||||
void portInitAdc() {
|
||||
// Init slow ADC
|
||||
adcStart(&ADCD1, NULL);
|
||||
|
||||
// Init fast ADC (MAP sensor)
|
||||
adcStart(&ADCD2, NULL);
|
||||
}
|
||||
|
||||
float getMcuTemperature() {
|
||||
// TODO: implement me!
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* EFI_PROD_CODE */
|
||||
|
|
|
@ -262,4 +262,17 @@ uintptr_t getFlashAddrSecondCopy() {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void portInitAdc() {
|
||||
// Init slow ADC
|
||||
adcStart(&ADCD1, NULL);
|
||||
|
||||
// Init fast ADC (MAP sensor)
|
||||
adcStart(&ADCD2, NULL);
|
||||
}
|
||||
|
||||
float getMcuTemperature() {
|
||||
// TODO: implement me!
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* EFI_PROD_CODE */
|
||||
|
|
|
@ -10,6 +10,11 @@
|
|||
void baseMCUInit(void);
|
||||
void jump_to_bootloader();
|
||||
|
||||
// ADC
|
||||
void portInitAdc();
|
||||
float getMcuTemperature();
|
||||
|
||||
|
||||
// CAN bus
|
||||
#if HAL_USE_CAN
|
||||
bool isValidCanTxPin(brain_pin_e pin);
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
/**
|
||||
* @file stm32_adc_v2.cpp
|
||||
* @brief Port implementation for the STM32 "v2" ADC found on the STM32F4 and STM32F7
|
||||
*
|
||||
* @date February 9, 2021
|
||||
* @author Matthew Kennedy, (c) 2021
|
||||
*/
|
||||
|
||||
#include "engine_ptr.h"
|
||||
#include "persistent_configuration.h"
|
||||
|
||||
#if HAL_USE_ADC
|
||||
|
||||
EXTERN_CONFIG;
|
||||
|
||||
void portInitAdc() {
|
||||
// Init slow ADC
|
||||
adcStart(&ADCD1, NULL);
|
||||
|
||||
// Init fast ADC (MAP sensor)
|
||||
adcStart(&ADCD2, NULL);
|
||||
|
||||
// Enable internal temperature reference
|
||||
adcSTM32EnableTSVREFE(); // Internal temperature sensor
|
||||
|
||||
#if defined(STM32F7XX)
|
||||
/* the temperature sensor is internally
|
||||
* connected to the same input channel as VBAT. Only one conversion,
|
||||
* temperature sensor or VBAT, must be selected at a time. */
|
||||
adcSTM32DisableVBATE();
|
||||
#endif
|
||||
|
||||
/* Enable this code only when you absolutly sure
|
||||
* that there is no possible errors from ADC */
|
||||
#if 0
|
||||
/* All ADC use DMA and DMA calls end_cb from its IRQ
|
||||
* If none of ADC users need error callback - we can disable
|
||||
* shared ADC IRQ and save some CPU ticks */
|
||||
if ((adcgrpcfgSlow.error_cb == NULL) &&
|
||||
(adcgrpcfgFast.error_cb == NULL)
|
||||
/* TODO: Add ADC3? */) {
|
||||
nvicDisableVector(STM32_ADC_NUMBER);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* ADC conversion group.
|
||||
*/
|
||||
static const ADCConversionGroup tempSensorConvGroup = {
|
||||
.circular = FALSE,
|
||||
.num_channels = 1,
|
||||
.end_cb = nullptr,
|
||||
.error_cb = nullptr,
|
||||
/* HW dependent part below */
|
||||
.cr1 = 0,
|
||||
.cr2 = ADC_CR2_SWSTART,
|
||||
// sample times for channels 10...18
|
||||
.smpr1 =
|
||||
ADC_SMPR1_SMP_VBAT(ADC_SAMPLE_144) | /* input18 - temperature and vbat input on some STM32F7xx */
|
||||
ADC_SMPR1_SMP_SENSOR(ADC_SAMPLE_144), /* input16 - temperature sensor input on STM32F4xx */
|
||||
.smpr2 = 0,
|
||||
.htr = 0, .ltr = 0,
|
||||
.sqr1 = 0,
|
||||
.sqr2 = 0,
|
||||
#if defined(STM32F4XX)
|
||||
.sqr3 = ADC_SQR3_SQ1_N(16),
|
||||
#endif
|
||||
#if defined(STM32F7XX)
|
||||
.sqr3 = ADC_SQR3_SQ1_N(18),
|
||||
#endif
|
||||
};
|
||||
|
||||
float getMcuTemperature() {
|
||||
// 4x oversample is plenty
|
||||
constexpr int oversample = 4;
|
||||
|
||||
// Buffer is a full 32 bytes to occupy a full cache line
|
||||
__ALIGNED(32) adcsample_t samples[16];
|
||||
|
||||
// Temperature sensor is only physically wired to ADC1
|
||||
adcConvert(&ADCD1, &tempSensorConvGroup, samples, oversample);
|
||||
|
||||
#if CORTEX_MODEL == 7
|
||||
// The STM32F7xx/STM32H7xx has a data cache
|
||||
// DMA operations DO NOT invalidate cache lines, since the ARM m7 doesn't have
|
||||
// anything like a CCI that maintains coherency across multiple bus masters.
|
||||
// As a result, we have to manually invalidate the D-cache any time we (the CPU)
|
||||
// would like to read something that somebody else wrote (ADC via DMA, in this case)
|
||||
SCB_InvalidateDCache_by_Addr(reinterpret_cast<uint32_t*>(samples), sizeof(samples));
|
||||
#endif /* CORTEX_MODEL == 7 */
|
||||
|
||||
uint32_t sum = 0;
|
||||
for (size_t i = 0; i < oversample; i++) {
|
||||
sum += samples[i];
|
||||
}
|
||||
|
||||
float volts = (float)sum / (4096 * oversample);
|
||||
volts *= CONFIG(adcVcc);
|
||||
|
||||
volts -= 0.760f; // Subtract the reference voltage at 25 deg C
|
||||
float degrees = volts / 0.0025f; // Divide by slope 2.5mV
|
||||
|
||||
degrees += 25.0; // Add the 25 deg C
|
||||
|
||||
if (degrees > 150.0f || degrees < -50.0f) {
|
||||
firmwareError(OBD_PCM_Processor_Fault, "Invalid CPU temperature measured %f", degrees);
|
||||
}
|
||||
|
||||
return degrees;
|
||||
}
|
||||
|
||||
#endif // HAL_USE_ADC
|
|
@ -3,7 +3,8 @@ include $(PROJECT_DIR)/hw_layer/ports/stm32/stm32_common.mk
|
|||
HW_LAYER_EMS += $(PROJECT_DIR)/hw_layer/ports/stm32/stm32f4/stm32f4xx_hal_flash.c \
|
||||
$(PROJECT_DIR)/hw_layer/ports/stm32/stm32f4/stm32f4xx_hal_flash_ex.c \
|
||||
|
||||
HW_LAYER_EMS_CPP += $(PROJECT_DIR)/hw_layer/ports/stm32/stm32f4/mpu_util.cpp
|
||||
HW_LAYER_EMS_CPP += $(PROJECT_DIR)/hw_layer/ports/stm32/stm32f4/mpu_util.cpp \
|
||||
$(PROJECT_DIR)/hw_layer/ports/stm32/stm32_adc_v2.cpp \
|
||||
|
||||
DDEFS += -DSTM32F407xx
|
||||
LDSCRIPT = $(PROJECT_DIR)/hw_layer/ports/stm32/stm32f4/STM32F405xG.ld
|
||||
|
|
|
@ -3,7 +3,8 @@ include $(PROJECT_DIR)/hw_layer/ports/stm32/stm32_common.mk
|
|||
HW_LAYER_EMS += $(PROJECT_DIR)/hw_layer/ports/stm32/stm32f7/stm32f7xx_hal_flash.c \
|
||||
$(PROJECT_DIR)/hw_layer/ports/stm32/stm32f7/stm32f7xx_hal_flash_ex.c
|
||||
|
||||
HW_LAYER_EMS_CPP += $(PROJECT_DIR)/hw_layer/ports/stm32/stm32f7/mpu_util.cpp
|
||||
HW_LAYER_EMS_CPP += $(PROJECT_DIR)/hw_layer/ports/stm32/stm32f7/mpu_util.cpp \
|
||||
$(PROJECT_DIR)/hw_layer/ports/stm32/stm32_adc_v2.cpp \
|
||||
|
||||
DDEFS += -DSTM32F767xx
|
||||
LDSCRIPT = $(PROJECT_DIR)/hw_layer/ports/stm32/stm32f7/STM32F76xxI.ld
|
||||
|
|
Loading…
Reference in New Issue