Browse Source

[bsp][stm32]Optimize ADCs and fix some bugs

yiyi 1 year ago
parent
commit
bc3afab2c9
2 changed files with 116 additions and 96 deletions
  1. 55 40
      bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc.c
  2. 61 56
      components/drivers/misc/adc.c

+ 55 - 40
bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc.c

@@ -199,18 +199,19 @@ static rt_err_t stm32_adc_enabled(struct rt_adc_device *device, rt_int8_t channe
         HAL_PWREx_EnableVddA();
 #endif /* defined(SOC_SERIES_STM32U5) */
 
-    if(HAL_ADC_ConfigChannel(stm32_adc_handler, &ADC_ChanConf) != HAL_OK)
-    {
-        LOG_E("Failed to configure ADC channel %d", channel);
-    }
+		if(HAL_ADC_ConfigChannel(stm32_adc_handler, &ADC_ChanConf) != HAL_OK)
+		{
+			LOG_E("Failed to configure ADC channel %d", channel);
+			return -RT_ERROR;
+		}
 
     /* perform an automatic ADC calibration to improve the conversion accuracy */
 #if defined(SOC_SERIES_STM32L4) || defined (SOC_SERIES_STM32WB)
-        if (HAL_ADCEx_Calibration_Start(stm32_adc_handler, ADC_ChanConf.SingleDiff) != HAL_OK)
-        {
-            LOG_E("ADC calibration error!\n");
-            return -RT_ERROR;
-        }
+		if (HAL_ADCEx_Calibration_Start(stm32_adc_handler, ADC_ChanConf.SingleDiff) != HAL_OK)
+		{
+			LOG_E("ADC calibration error!\n");
+			return -RT_ERROR;
+		}
 #elif defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32H7) || defined(SOC_SERIES_STM32U5)
         /* Run the ADC linear calibration in single-ended mode */
         if (HAL_ADCEx_Calibration_Start(stm32_adc_handler, ADC_CALIB_OFFSET_LINEARITY, ADC_ChanConf.SingleDiff) != HAL_OK)
@@ -220,11 +221,14 @@ static rt_err_t stm32_adc_enabled(struct rt_adc_device *device, rt_int8_t channe
             return -RT_ERROR;
         }
 #endif
-        HAL_ADC_Start(stm32_adc_handler);
     }
     else
     {
-        HAL_ADC_Stop(stm32_adc_handler);
+        if (HAL_ADC_Stop(stm32_adc_handler) != HAL_OK)
+		{
+			LOG_E("Stop ADC conversion failed!\n");
+			return -RT_ERROR;
+		}
     }
 
     return RT_EOK;
@@ -255,33 +259,62 @@ static rt_uint8_t stm32_adc_get_resolution(struct rt_adc_device *device)
             return 10;
         case ADC_RESOLUTION_8B:
             return 8;
-#if defined(SOC_SERIES_STM32H7) || defined(SOC_SERIES_STM32U5)
+#if defined(SOC_SERIES_STM32H7) && (ADC_VER_V5_V90) || defined(SOC_SERIES_STM32U5)
         case ADC_RESOLUTION_6B:
             return 6;
-#endif /* defined(SOC_SERIES_STM32H7) || defined(SOC_SERIES_STM32U5) */
+#endif /* defined(SOC_SERIES_STM32H7) && (ADC_VER_V5_V90) || defined(SOC_SERIES_STM32U5) */
         default:
             return 0;
     }
 #endif /* defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32F3) */
 }
 
-static rt_int16_t stm32_adc_get_vref (struct rt_adc_device *device)
+static rt_err_t stm32_adc_get_value(struct rt_adc_device *device, rt_int8_t channel, rt_uint32_t *value)
 {
-    if(device == RT_NULL)
-      return -RT_ERROR;
+    ADC_HandleTypeDef *stm32_adc_handler;
+
+    RT_ASSERT(device != RT_NULL);
+    RT_ASSERT(value != RT_NULL);
+
+    stm32_adc_handler = device->parent.user_data;
+	
+	if (HAL_ADC_Start(stm32_adc_handler) != HAL_OK)
+	{
+		LOG_E("Start ADC conversion error!\n");
+		return -RT_ERROR;
+	}
+
+    /* Wait for the ADC to convert */
+    if (HAL_ADC_PollForConversion(stm32_adc_handler, 100) != RT_EOK)
+	{
+		LOG_E("ADC conversion error!\n");
+		return -RT_ERROR;
+	}
+
+    /* get ADC value */
+    *value = (rt_uint32_t)HAL_ADC_GetValue(stm32_adc_handler);
+
+    return RT_EOK;
+}
 
+static rt_int16_t stm32_adc_get_vref (struct rt_adc_device *device)
+{
     rt_uint16_t vref_mv;
 #ifdef __LL_ADC_CALC_VREFANALOG_VOLTAGE
-    rt_err_t ret = RT_EOK;
+    rt_err_t ret;
     rt_uint32_t vref_value;
 
     ADC_HandleTypeDef *stm32_adc_handler = device->parent.user_data;
 
-    ret = rt_adc_enable(device, RT_ADC_INTERN_CH_VREF);
-    if (ret != RT_EOK) return (rt_int16_t)ret;
-    vref_value = rt_adc_read(device, RT_ADC_INTERN_CH_VREF);
-    ret = rt_adc_disable(device, RT_ADC_INTERN_CH_VREF);
-    if (ret != RT_EOK) return (rt_int16_t)ret;
+	ret = stm32_adc_enabled(device, RT_ADC_INTERN_CH_VREF, RT_TRUE);
+    if (ret != RT_EOK) 
+		return 0;
+    ret = stm32_adc_get_value(device, RT_ADC_INTERN_CH_VREF, &vref_value);
+	if (ret != RT_EOK) 
+		return 0;
+    ret = stm32_adc_enabled(device, RT_ADC_INTERN_CH_VREF, RT_FALSE);
+    if (ret != RT_EOK) 
+		return 0;
 
 #ifdef SOC_SERIES_STM32U5
     vref_mv = __LL_ADC_CALC_VREFANALOG_VOLTAGE(stm32_adc_handler->Instance, vref_value, stm32_adc_handler->Init.Resolution);
@@ -295,24 +328,6 @@ static rt_int16_t stm32_adc_get_vref (struct rt_adc_device *device)
     return vref_mv;
 }
 
-static rt_err_t stm32_adc_get_value(struct rt_adc_device *device, rt_int8_t channel, rt_uint32_t *value)
-{
-    ADC_HandleTypeDef *stm32_adc_handler;
-
-    RT_ASSERT(device != RT_NULL);
-    RT_ASSERT(value != RT_NULL);
-
-    stm32_adc_handler = device->parent.user_data;
-
-    /* Wait for the ADC to convert */
-    HAL_ADC_PollForConversion(stm32_adc_handler, 100);
-
-    /* get ADC value */
-    *value = (rt_uint32_t)HAL_ADC_GetValue(stm32_adc_handler);
-
-    return RT_EOK;
-}
-
 static const struct rt_adc_ops stm_adc_ops =
 {
     .enabled = stm32_adc_enabled,

+ 61 - 56
components/drivers/misc/adc.c

@@ -22,14 +22,14 @@
 
 static rt_ssize_t _adc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
 {
-    rt_err_t result = RT_EOK;
-    rt_size_t i;
-    struct rt_adc_device *adc = (struct rt_adc_device *)dev;
-    rt_uint32_t *value = (rt_uint32_t *)buffer;
+    rt_err_t              result;
+    rt_size_t             i;
+    struct rt_adc_device *adc   = (struct rt_adc_device *)dev;
+    rt_uint32_t          *value = (rt_uint32_t *)buffer;
 
-    for (i = 0; i < size; i += sizeof(int))
+    for (i = 0; i < size; i++)
     {
-        result = adc->ops->convert(adc, pos + i, value);
+        result = adc->ops->convert(adc, pos, value);
         if (result != RT_EOK)
         {
             return 0;
@@ -42,8 +42,9 @@ static rt_ssize_t _adc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size
 
 static rt_err_t _adc_control(rt_device_t dev, int cmd, void *args)
 {
-    rt_err_t result = -RT_EINVAL;
     rt_adc_device_t adc = (struct rt_adc_device *)dev;
+    rt_err_t        result;
+
 
     if (cmd == RT_ADC_CMD_ENABLE && adc->ops->enabled)
     {
@@ -56,9 +57,9 @@ static rt_err_t _adc_control(rt_device_t dev, int cmd, void *args)
     else if (cmd == RT_ADC_CMD_GET_RESOLUTION && adc->ops->get_resolution && args)
     {
         rt_uint8_t resolution = adc->ops->get_resolution(adc);
-        if(resolution != 0)
+        if (resolution != 0)
         {
-            *((rt_uint8_t*)args) = resolution;
+            *((rt_uint8_t *)args) = resolution;
             LOG_D("resolution: %d bits", resolution);
             result = RT_EOK;
         }
@@ -66,10 +67,10 @@ static rt_err_t _adc_control(rt_device_t dev, int cmd, void *args)
     else if (cmd == RT_ADC_CMD_GET_VREF && adc->ops->get_vref && args)
     {
         rt_int16_t value = adc->ops->get_vref(adc);
-        if(value != 0)
+        if (value != 0)
         {
-            *((rt_int16_t *) args) = value;
-            result = RT_EOK;
+            *((rt_int16_t *)args) = value;
+            result                = RT_EOK;
         }
     }
 
@@ -78,36 +79,36 @@ static rt_err_t _adc_control(rt_device_t dev, int cmd, void *args)
 
 #ifdef RT_USING_DEVICE_OPS
 const static struct rt_device_ops adc_ops =
-{
-    RT_NULL,
-    RT_NULL,
-    RT_NULL,
-    _adc_read,
-    RT_NULL,
-    _adc_control,
+    {
+        RT_NULL,
+        RT_NULL,
+        RT_NULL,
+        _adc_read,
+        RT_NULL,
+        _adc_control,
 };
 #endif
 
 rt_err_t rt_hw_adc_register(rt_adc_device_t device, const char *name, const struct rt_adc_ops *ops, const void *user_data)
 {
-    rt_err_t result = RT_EOK;
     RT_ASSERT(ops != RT_NULL && ops->convert != RT_NULL);
+    rt_err_t result;
 
-    device->parent.type = RT_Device_Class_ADC;
+    device->parent.type        = RT_Device_Class_ADC;
     device->parent.rx_indicate = RT_NULL;
     device->parent.tx_complete = RT_NULL;
 
 #ifdef RT_USING_DEVICE_OPS
-    device->parent.ops         = &adc_ops;
+    device->parent.ops = &adc_ops;
 #else
-    device->parent.init        = RT_NULL;
-    device->parent.open        = RT_NULL;
-    device->parent.close       = RT_NULL;
-    device->parent.read        = _adc_read;
-    device->parent.write       = RT_NULL;
-    device->parent.control     = _adc_control;
+    device->parent.init    = RT_NULL;
+    device->parent.open    = RT_NULL;
+    device->parent.close   = RT_NULL;
+    device->parent.read    = _adc_read;
+    device->parent.write   = RT_NULL;
+    device->parent.control = _adc_control;
 #endif
-    device->ops = ops;
+    device->ops              = ops;
     device->parent.user_data = (void *)user_data;
 
     result = rt_device_register(&device->parent, name, RT_DEVICE_FLAG_RDWR);
@@ -117,20 +118,21 @@ rt_err_t rt_hw_adc_register(rt_adc_device_t device, const char *name, const stru
 
 rt_uint32_t rt_adc_read(rt_adc_device_t dev, rt_int8_t channel)
 {
-    rt_uint32_t value;
-
     RT_ASSERT(dev);
+    rt_uint32_t value;
+    rt_err_t    result;
 
-    dev->ops->convert(dev, channel, &value);
+    result = dev->ops->convert(dev, channel, &value);
+    if (result != RT_EOK)
+        return 0;
 
     return value;
 }
 
 rt_err_t rt_adc_enable(rt_adc_device_t dev, rt_int8_t channel)
 {
-    rt_err_t result = RT_EOK;
-
     RT_ASSERT(dev);
+    rt_err_t result;
 
     if (dev->ops->enabled != RT_NULL)
     {
@@ -146,9 +148,8 @@ rt_err_t rt_adc_enable(rt_adc_device_t dev, rt_int8_t channel)
 
 rt_err_t rt_adc_disable(rt_adc_device_t dev, rt_int8_t channel)
 {
-    rt_err_t result = RT_EOK;
-
     RT_ASSERT(dev);
+    rt_err_t result;
 
     if (dev->ops->enabled != RT_NULL)
     {
@@ -164,26 +165,30 @@ rt_err_t rt_adc_disable(rt_adc_device_t dev, rt_int8_t channel)
 
 rt_int16_t rt_adc_voltage(rt_adc_device_t dev, rt_int8_t channel)
 {
-    rt_uint32_t value = 0;
-    rt_int16_t vref = 0, voltage = 0;
-    rt_uint8_t resolution = 0;
-
     RT_ASSERT(dev);
 
-    /*get the resolution in bits*/
-    if (_adc_control((rt_device_t) dev, RT_ADC_CMD_GET_RESOLUTION, &resolution) != RT_EOK)
-    {
-        goto _voltage_exit;
-    }
+    rt_uint32_t value;
+    rt_int16_t  vref, voltage;
+    rt_uint8_t  resolution;
+    rt_err_t    result;
 
+    /*get the resolution in bits*/
+    resolution = dev->ops->get_resolution(dev);
     /*get the reference voltage*/
-    if (_adc_control((rt_device_t) dev, RT_ADC_CMD_GET_VREF, &vref) != RT_EOK)
-    {
+    vref = dev->ops->get_vref(dev);
+    if (vref == 0)
         goto _voltage_exit;
-    }
 
     /*read the value and convert to voltage*/
-    dev->ops->convert(dev, channel, &value);
+    result = dev->ops->enabled(dev, channel, RT_TRUE);
+    if (result != RT_EOK)
+        goto _voltage_exit;
+    result = dev->ops->convert(dev, channel, &value);
+    if (result != RT_EOK)
+        goto _voltage_exit;
+    result = dev->ops->enabled(dev, channel, RT_FALSE);
+    if (result != RT_EOK)
+        goto _voltage_exit;
     voltage = value * vref / ((1 << resolution) - 1);
 
 _voltage_exit:
@@ -194,11 +199,11 @@ _voltage_exit:
 
 static int adc(int argc, char **argv)
 {
-    int value = 0;
-    rt_int16_t voltage = 0;
-    rt_err_t result = -RT_ERROR;
+    int                    value      = 0;
+    rt_int16_t             voltage    = 0;
+    rt_err_t               result     = -RT_ERROR;
     static rt_adc_device_t adc_device = RT_NULL;
-    char *result_str;
+    char                  *result_str;
 
     if (argc > 1)
     {
@@ -226,7 +231,7 @@ static int adc(int argc, char **argv)
             {
                 if (argc == 3)
                 {
-                    result = rt_adc_enable(adc_device, atoi(argv[2]));
+                    result     = rt_adc_enable(adc_device, atoi(argv[2]));
                     result_str = (result == RT_EOK) ? "success" : "failure";
                     rt_kprintf("%s channel %d enables %s \n", adc_device->parent.parent.name, (rt_base_t)atoi(argv[2]), result_str);
                 }
@@ -251,7 +256,7 @@ static int adc(int argc, char **argv)
             {
                 if (argc == 3)
                 {
-                    result = rt_adc_disable(adc_device, atoi(argv[2]));
+                    result     = rt_adc_disable(adc_device, atoi(argv[2]));
                     result_str = (result == RT_EOK) ? "success" : "failure";
                     rt_kprintf("%s channel %d disable %s \n", adc_device->parent.parent.name, (rt_base_t)atoi(argv[2]), result_str);
                 }
@@ -262,7 +267,7 @@ static int adc(int argc, char **argv)
             }
             else if (!strcmp(argv[1], "voltage"))
             {
-                if(argc == 3)
+                if (argc == 3)
                 {
                     voltage = rt_adc_voltage(adc_device, atoi(argv[2]));
                     rt_kprintf("%s channel %d voltage is %d.%03dV \n", adc_device->parent.parent.name, (rt_base_t)atoi(argv[2]), voltage / 1000, voltage % 1000);