From 57b068ffa1e3afb8a7e60854c05d921b0ba6f49e Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Sat, 8 May 2021 09:31:55 +0000 Subject: [PATCH] Various ADCv4 fixes and enhancements. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@14357 27425a3e-05d8-49a3-a47f-9c15f0e5edd8 --- os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.c | 82 ++++++++++++------- os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.h | 27 ++++++ .../ADC/cfg/stm32h743zi_nucleo144/mcuconf.h | 2 +- .../ADC/cfg/stm32h743zi_nucleo144/portab.c | 6 +- 4 files changed, 83 insertions(+), 34 deletions(-) diff --git a/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.c b/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.c index 812acd3ba..3810cf393 100644 --- a/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.c +++ b/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.c @@ -31,6 +31,7 @@ /*===========================================================================*/ #if STM32_ADC_DUAL_MODE == TRUE +#define ADC12_CCR_DUAL 0b00110 // TODO use definitions #if STM32_ADC_COMPACT_SAMPLES == TRUE /* Compact type dual mode, 2x8-bit.*/ #define ADC12_DMA_SIZE (STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD) @@ -45,6 +46,7 @@ #endif /* !STM32_ADC_COMPACT_SAMPLES */ #else /* STM32_ADC_DUAL_MODE == FALSE */ +#define ADC12_CCR_DUAL 0b00000 // TODO use definitions #if STM32_ADC_COMPACT_SAMPLES /* Compact type single mode, 8-bit.*/ #define ADC12_DMA_SIZE (STM32_DMA_CR_MSIZE_BYTE | STM32_DMA_CR_PSIZE_BYTE) @@ -317,19 +319,24 @@ OSAL_IRQ_HANDLER(STM32_ADC12_HANDLER) { OSAL_IRQ_PROLOGUE(); + /* Handle ADC1 ISR first in adc_lld_serve_interrupt. */ isr = ADC1->ISR; -#if STM32_ADC_DUAL_MODE - isr |= ADC2->ISR; -#endif ADC1->ISR = isr; -#if STM32_ADC_DUAL_MODE - ADC2->ISR = isr; -#endif #if defined(STM32_ADC_ADC12_IRQ_HOOK) STM32_ADC_ADC12_IRQ_HOOK #endif adc_lld_serve_interrupt(&ADCD1, isr); + /* Handle ADC2 ISR next in adc_lld_serve_interrupt. */ +#if STM32_ADC_DUAL_MODE + isr |= ADC2->ISR; + ADC2->ISR = isr; +#if defined(STM32_ADC_ADC12_IRQ_HOOK) + STM32_ADC_ADC12_IRQ_HOOK +#endif + adc_lld_serve_interrupt(&ADCD1, isr); +#endif + OSAL_IRQ_EPILOGUE(); } #endif /* STM32_ADC_USE_ADC12 == TRUE */ @@ -403,7 +410,7 @@ void adc_lld_init(void) { #if STM32_ADC_USE_ADC12 == TRUE rccEnableADC12(true); rccResetADC12(); - ADC12_COMMON->CCR = STM32_ADC_ADC12_CLOCK_MODE | ADC_DMA_DAMDF; + ADC12_COMMON->CCR = STM32_ADC_ADC12_CLOCK_MODE | ADC_DMA_DAMDF | ADC12_CCR_DUAL; rccDisableADC12(); #endif #if STM32_ADC_USE_ADC3 == TRUE @@ -528,7 +535,7 @@ void adc_lld_stop(ADCDriver *adcp) { adcp->data.dma = NULL; /* Resetting CCR options except default ones.*/ - adcp->adcc->CCR = STM32_ADC_ADC12_CLOCK_MODE | ADC_DMA_DAMDF; + adcp->adcc->CCR = STM32_ADC_ADC12_CLOCK_MODE | ADC_DMA_DAMDF | ADC12_CCR_DUAL; rccDisableADC12(); } #endif @@ -627,25 +634,40 @@ void adc_lld_start_conversion(ADCDriver *adcp) { /* ADC setup, if it is defined a callback for the analog watch dog then it is enabled.*/ + /* clear AWD1..3 flags */ adcp->adcm->ISR = adcp->adcm->ISR; - adcp->adcm->IER = ADC_IER_OVRIE | ADC_IER_AWD1IE; + /* If a callback is set enable the overflow and analog watch dog interrupts. */ + if (grpp->error_cb != NULL) { + adcp->adcm->IER = ADC_IER_OVRIE | ADC_IER_AWD1IE + | ADC_IER_AWD2IE + | ADC_IER_AWD3IE; + } #if STM32_ADC_DUAL_MODE == TRUE && STM32_ADC_USE_ADC12 == TRUE /* Configuration for dual mode ADC12 */ if (&ADCD1 == adcp) { + /* clear AWD1..3 flags */ + adcp->adcs->ISR = adcp->adcs->ISR; + /* If a callback is set enable the overflow and analog watch dog interrupts. */ + if (grpp->error_cb != NULL) { + adcp->adcs->IER = ADC_IER_OVRIE | ADC_IER_AWD1IE + | ADC_IER_AWD2IE + | ADC_IER_AWD3IE; /* Configuring the CCR register with the user-specified settings in the conversion group configuration structure, static settings are preserved.*/ adcp->adcc->CCR = (adcp->adcc->CCR & - (ADC_CCR_CKMODE_MASK | ADC_CCR_DAMDF_MASK)) | ccr; + (ADC_CCR_CKMODE_MASK | ADC_CCR_DAMDF_MASK | ADC_CCR_DUAL_MASK)) | ccr; adcp->adcm->CFGR2 = grpp->cfgr2; adcp->adcm->PCSEL = grpp->pcsel; adcp->adcm->LTR1 = grpp->ltr1; adcp->adcm->HTR1 = grpp->htr1; - adcp->adcm->LTR1 = grpp->ltr2; - adcp->adcm->HTR1 = grpp->htr2; - adcp->adcm->LTR1 = grpp->ltr3; - adcp->adcm->HTR1 = grpp->htr3; + adcp->adcm->LTR2 = grpp->ltr2; + adcp->adcm->HTR2 = grpp->htr2; + adcp->adcm->LTR3 = grpp->ltr3; + adcp->adcm->HTR3 = grpp->htr3; + adcp->adcm->AWD2CR = grpp->awd2cr; + adcp->adcm->AWD3CR = grpp->awd3cr; adcp->adcm->SMPR1 = grpp->smpr[0]; adcp->adcm->SMPR2 = grpp->smpr[1]; adcp->adcm->SQR1 = grpp->sqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels / 2); @@ -654,12 +676,14 @@ void adc_lld_start_conversion(ADCDriver *adcp) { adcp->adcm->SQR4 = grpp->sqr[3]; adcp->adcs->CFGR2 = grpp->cfgr2; adcp->adcs->PCSEL = grpp->pcsel; - adcp->adcs->LTR1 = grpp->ltr1; - adcp->adcs->HTR1 = grpp->htr1; - adcp->adcs->LTR1 = grpp->ltr2; - adcp->adcs->HTR1 = grpp->htr2; - adcp->adcs->LTR1 = grpp->ltr3; - adcp->adcs->HTR1 = grpp->htr3; + adcp->adcs->LTR1 = grpp->sltr1; + adcp->adcs->HTR1 = grpp->shtr1; + adcp->adcs->LTR2 = grpp->sltr2; + adcp->adcs->HTR2 = grpp->shtr2; + adcp->adcs->LTR3 = grpp->sltr3; + adcp->adcs->HTR3 = grpp->shtr3; + adcp->adcs->AWD2CR = grpp->sawd2cr; + adcp->adcs->AWD3CR = grpp->sawd3cr; adcp->adcs->SMPR1 = grpp->ssmpr[0]; adcp->adcs->SMPR2 = grpp->ssmpr[1]; adcp->adcs->SQR1 = grpp->ssqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels / 2); @@ -671,23 +695,22 @@ void adc_lld_start_conversion(ADCDriver *adcp) { adcp->adcm->CFGR = cfgr; adcp->adcs->CFGR = cfgr; } - +} #endif /* STM32_ADC_DUAL_MODE == TRUE && STM32_ADC_USE_ADC12 == TRUE */ #if STM32_ADC_DUAL_MODE == FALSE || STM32_ADC_USE_ADC3 == TRUE /* Configuration for ADC3 and single mode ADC1 */ -#if STM32_ADC_DUAL_MODE == TRUE && STM32_ADC_USE_ADC3 == TRUE - if (&ADCD3 == adcp) -#endif - { + adcp->adcm->CFGR2 = grpp->cfgr2; adcp->adcm->PCSEL = grpp->pcsel; adcp->adcm->LTR1 = grpp->ltr1; adcp->adcm->HTR1 = grpp->htr1; - adcp->adcm->LTR1 = grpp->ltr2; - adcp->adcm->HTR1 = grpp->htr2; - adcp->adcm->LTR1 = grpp->ltr3; - adcp->adcm->HTR1 = grpp->htr3; + adcp->adcm->LTR2 = grpp->ltr2; + adcp->adcm->HTR2 = grpp->htr2; + adcp->adcm->LTR3 = grpp->ltr3; + adcp->adcm->HTR3 = grpp->htr3; + adcp->adcm->AWD2CR = grpp->awd2cr; + adcp->adcm->AWD3CR = grpp->awd3cr; adcp->adcm->SMPR1 = grpp->smpr[0]; adcp->adcm->SMPR2 = grpp->smpr[1]; adcp->adcm->SQR1 = grpp->sqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels); @@ -697,7 +720,6 @@ void adc_lld_start_conversion(ADCDriver *adcp) { /* ADC configuration.*/ adcp->adcm->CFGR = cfgr; - } #endif /* Starting conversion.*/ diff --git a/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.h b/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.h index 63e876683..d23c95045 100644 --- a/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.h +++ b/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.h @@ -607,10 +607,26 @@ typedef union { uint32_t ltr3; \ /* ADC HTR3 register initialization data.*/ \ uint32_t htr3; \ + /* ADC AWD2CR register initialization data.*/ \ + uint32_t awd2cr; \ + /* ADC AWD3CR register initialization data.*/ \ + uint32_t awd3cr; \ /* ADC SMPRx registers initialization data.*/ \ uint32_t smpr[2]; \ /* ADC SQRx register initialization data.*/ \ uint32_t sqr[4]; \ + /* Slave ADC LTR/HTRx registers initialization data. \ + NOTE: This field is only present in dual mode.*/ \ + uint32_t sltr1; \ + uint32_t shtr1; \ + uint32_t sltr2; \ + uint32_t shtr2; \ + uint32_t sltr3; \ + uint32_t shtr3; \ + /* Slave ADC AWDxCR registers initialization data. \ + NOTE: This field is only present in dual mode.*/ \ + uint32_t sawd2cr; \ + uint32_t sawd3cr; \ /* Slave ADC SMPRx registers initialization data. \ NOTE: This field is only present in dual mode.*/ \ uint32_t ssmpr[2]; \ @@ -629,6 +645,8 @@ typedef union { uint32_t htr2; \ uint32_t ltr3; \ uint32_t htr3; \ + uint32_t awd2cr; \ + uint32_t awd3cr; \ uint32_t smpr[2]; \ uint32_t sqr[4] #endif /* STM32_ADC_DUAL_MODE == FALSE */ @@ -690,6 +708,15 @@ typedef union { #define ADC_SMPR2_SMP_AN19(n) ((n) << 27U)/**< @brief AN19 sampling time. */ /** @} */ +/** + * @name Analog watchdog settings helper macros + * @{ + */ +#define ADC_CFGR_AWD1_N(n) ((n) << 26U)/**< @brief AWD1 channel number */ +#define ADC_AWD23_MASK(n) (1U << (n)) /**< @brief AWD2/3 channels mask*/ +/** @} */ + + /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/ diff --git a/testhal/STM32/multi/ADC/cfg/stm32h743zi_nucleo144/mcuconf.h b/testhal/STM32/multi/ADC/cfg/stm32h743zi_nucleo144/mcuconf.h index 9512f4a33..a0a1aa018 100644 --- a/testhal/STM32/multi/ADC/cfg/stm32h743zi_nucleo144/mcuconf.h +++ b/testhal/STM32/multi/ADC/cfg/stm32h743zi_nucleo144/mcuconf.h @@ -61,7 +61,7 @@ */ #define STM32_VOS STM32_VOS_SCALE1 #define STM32_PWR_CR1 (PWR_CR1_SVOS_1 | PWR_CR1_SVOS_0) -#define STM32_PWR_CR2 (PWR_CR2_BREN) +#define STM32_PWR_CR2 (PWR_CR2_BREN | PWR_CR2_MONEN) #define STM32_PWR_CR3 (PWR_CR3_LDOEN | PWR_CR3_USB33DEN) #define STM32_PWR_CPUCR 0 diff --git a/testhal/STM32/multi/ADC/cfg/stm32h743zi_nucleo144/portab.c b/testhal/STM32/multi/ADC/cfg/stm32h743zi_nucleo144/portab.c index 2e16ae935..e031deaac 100644 --- a/testhal/STM32/multi/ADC/cfg/stm32h743zi_nucleo144/portab.c +++ b/testhal/STM32/multi/ADC/cfg/stm32h743zi_nucleo144/portab.c @@ -38,7 +38,7 @@ * GPT configuration. */ const GPTConfig portab_gptcfg1 = { - .frequency = 1000000U, + .frequency = 20000U, .callback = NULL, .cr2 = TIM_CR2_MMS_1, /* MMS = 010 = TRGO on Update Event. */ .dier = 0U @@ -99,8 +99,8 @@ const ADCConversionGroup portab_adcgrpcfg2 = { .num_channels = ADC_GRP2_NUM_CHANNELS, .end_cb = adccallback, .error_cb = adcerrorcallback, - .cfgr = ADC_CFGR_EXTEN_RISING | - ADC_CFGR_EXTSEL_SRC(12), /* TIM4_TRGO */ + .cfgr = ADC_CFGR_CONT_ENABLED /*| ADC_CFGR_EXTEN_RISING | + ADC_CFGR_EXTSEL_SRC(12)*/, /* TIM4_TRGO */ .cfgr2 = 0U, .ccr = 0U, .pcsel = ADC_SELMASK_IN0 | ADC_SELMASK_IN5,