You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by je...@apache.org on 2021/05/20 05:24:10 UTC

[incubator-nuttx] 13/21: arch: cxd56xx: Fix multiple open and close ADC driver

This is an automated email from the ASF dual-hosted git repository.

jerpelea pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit f0cae6cdf351d6842def9aee1c7ac19f40daf76c
Author: SPRESENSE <41...@users.noreply.github.com>
AuthorDate: Wed May 19 17:04:24 2021 +0900

    arch: cxd56xx: Fix multiple open and close ADC driver
    
    ADC driver does not support multiple open and close. It causes the memory
    corruption by multiple free. This commit fixes this problem by introducing
    the reference counter.
---
 arch/arm/src/cxd56xx/cxd56_adc.c | 50 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 49 insertions(+), 1 deletion(-)

diff --git a/arch/arm/src/cxd56xx/cxd56_adc.c b/arch/arm/src/cxd56xx/cxd56_adc.c
index 728a01b..9f3ecda 100644
--- a/arch/arm/src/cxd56xx/cxd56_adc.c
+++ b/arch/arm/src/cxd56xx/cxd56_adc.c
@@ -35,6 +35,7 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/fs/fs.h>
 #include <nuttx/irq.h>
+#include <nuttx/semaphore.h>
 #include <arch/chip/scu.h>
 #include <arch/chip/adc.h>
 
@@ -172,6 +173,8 @@ struct cxd56adc_dev_s
   struct scufifo_wm_s *wm;        /* water mark */
   struct math_filter_s *filter;   /* math filter */
   struct scuev_notify_s * notify; /* notify */
+  sem_t            exclsem;       /* exclusive semaphore */
+  int              crefs;         /* reference count */
 };
 
 /****************************************************************************
@@ -218,6 +221,7 @@ static struct cxd56adc_dev_s g_lpadc0priv =
   .wm     = NULL,
   .filter = NULL,
   .notify = NULL,
+  .crefs  = 0,
 };
 #endif
 
@@ -233,6 +237,7 @@ static struct cxd56adc_dev_s g_lpadc1priv =
   .wm     = NULL,
   .filter = NULL,
   .notify = NULL,
+  .crefs  = 0,
 };
 #endif
 
@@ -248,6 +253,7 @@ static struct cxd56adc_dev_s g_lpadc2priv =
   .wm     = NULL,
   .filter = NULL,
   .notify = NULL,
+  .crefs  = 0,
 };
 #endif
 
@@ -263,6 +269,7 @@ static struct cxd56adc_dev_s g_lpadc3priv =
   .wm     = NULL,
   .filter = NULL,
   .notify = NULL,
+  .crefs  = 0,
 };
 #endif
 
@@ -278,6 +285,7 @@ static struct cxd56adc_dev_s g_hpadc0priv =
   .wm     = NULL,
   .filter = NULL,
   .notify = NULL,
+  .crefs  = 0,
 };
 #endif
 
@@ -293,6 +301,7 @@ static struct cxd56adc_dev_s g_hpadc1priv =
   .wm     = NULL,
   .filter = NULL,
   .notify = NULL,
+  .crefs  = 0,
 };
 #endif
 
@@ -703,9 +712,23 @@ static int cxd56_adc_open(FAR struct file *filep)
   int type;
 
   DEBUGASSERT(priv != NULL);
-  DEBUGASSERT(priv->seq == NULL);
   DEBUGASSERT(priv->ch < CH_MAX);
 
+  /* Increment reference counter */
+
+  nxsem_wait_uninterruptible(&priv->exclsem);
+
+  priv->crefs++;
+  DEBUGASSERT(priv->crefs > 0);
+
+  if (priv->crefs > 1)
+    {
+      nxsem_post(&priv->exclsem);
+      return OK;
+    }
+
+  DEBUGASSERT(priv->seq == NULL);
+
   type = SCU_BUS_LPADC0 + priv->ch;
 
   /* Open sequencer */
@@ -713,6 +736,7 @@ static int cxd56_adc_open(FAR struct file *filep)
   priv->seq = seq_open(SEQ_TYPE_NORMAL, type);
   if (!priv->seq)
     {
+      nxsem_post(&priv->exclsem);
       return -ENOENT;
     }
 
@@ -725,11 +749,14 @@ static int cxd56_adc_open(FAR struct file *filep)
   ret = set_ofstgain(priv);
   if (ret < 0)
     {
+      nxsem_post(&priv->exclsem);
       return ret;
     }
 
   ainfo("open ch%d freq%d scufifo%d\n", priv->ch, priv->freq, priv->fsize);
 
+  nxsem_post(&priv->exclsem);
+
   return OK;
 }
 
@@ -750,6 +777,19 @@ static int cxd56_adc_close(FAR struct file *filep)
   DEBUGASSERT(priv->seq != NULL);
   DEBUGASSERT(priv->ch < CH_MAX);
 
+  /* Decrement reference counter */
+
+  nxsem_wait_uninterruptible(&priv->exclsem);
+
+  DEBUGASSERT(priv->crefs > 0);
+  priv->crefs--;
+
+  if (priv->crefs > 0)
+    {
+      nxsem_post(&priv->exclsem);
+      return OK;
+    }
+
   /* Close sequencer */
 
   seq_close(priv->seq);
@@ -773,6 +813,8 @@ static int cxd56_adc_close(FAR struct file *filep)
       priv->notify = NULL;
     }
 
+  nxsem_post(&priv->exclsem);
+
   return OK;
 }
 
@@ -1058,6 +1100,7 @@ int cxd56_adcinitialize(void)
       return ret;
     }
 
+  nxsem_init(&g_lpadc0priv.exclsem, 0, 1);
 #endif
 #if defined (CONFIG_CXD56_LPADC1) || defined (CONFIG_CXD56_LPADC0_1) || defined (CONFIG_CXD56_LPADC_ALL)
   ret = register_driver("/dev/lpadc1", &g_adcops, 0666, &g_lpadc1priv);
@@ -1067,6 +1110,7 @@ int cxd56_adcinitialize(void)
       return ret;
     }
 
+  nxsem_init(&g_lpadc1priv.exclsem, 0, 1);
 #endif
 #if defined (CONFIG_CXD56_LPADC2) || defined (CONFIG_CXD56_LPADC_ALL)
   ret = register_driver("/dev/lpadc2", &g_adcops, 0666, &g_lpadc2priv);
@@ -1076,6 +1120,7 @@ int cxd56_adcinitialize(void)
       return ret;
     }
 
+  nxsem_init(&g_lpadc2priv.exclsem, 0, 1);
 #endif
 #if defined (CONFIG_CXD56_LPADC3) || defined (CONFIG_CXD56_LPADC_ALL)
   ret = register_driver("/dev/lpadc3", &g_adcops, 0666, &g_lpadc3priv);
@@ -1085,6 +1130,7 @@ int cxd56_adcinitialize(void)
       return ret;
     }
 
+  nxsem_init(&g_lpadc3priv.exclsem, 0, 1);
 #endif
 #ifdef CONFIG_CXD56_HPADC0
   ret = register_driver("/dev/hpadc0", &g_adcops, 0666, &g_hpadc0priv);
@@ -1094,6 +1140,7 @@ int cxd56_adcinitialize(void)
       return ret;
     }
 
+  nxsem_init(&g_hpadc0priv.exclsem, 0, 1);
 #endif
 #ifdef CONFIG_CXD56_HPADC1
   ret = register_driver("/dev/hpadc1", &g_adcops, 0666, &g_hpadc1priv);
@@ -1103,6 +1150,7 @@ int cxd56_adcinitialize(void)
       return ret;
     }
 
+  nxsem_init(&g_hpadc1priv.exclsem, 0, 1);
 #endif
 
   return ret;