This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

SPRUFI7 ADC Guide

Hello

I'm trying to use the ADC of dm36x using the following guide:

SPRUFI7 - TMS320DM36x DMSoC Analog to Digital Converter User's Guide

But I have no way to configure and get the data ADxDAT.

Someone can help me. I'm using the example IPNC, and appears not to have the drivers of the ADC. Is this possible?

Thanks

  • Josep,

    This question seems to be a duplicate of your previous ADC driver posts.  Where you able you leverage the ADC driver code reference in the following post:

    http://e2e.ti.com/support/embedded/int-embedded_software/f/126/p/14669/57047.aspx#57047

     

    Marcus

  • Hello Marcus:

    I had already seen your answer, but the link that you pass me says "Group not found. "

    I do not find, where is the post. Please, you can review the link of the post.


    Thanks

     

    --Josep--

  •  

    I've attached the source file

    Hi,
    
    I attach a simple standalone driver for the for the dm365 ADC in the
    hope that it might prove useful.
    
    Shlomo
    
    ----
    adc_driver.c
    
    #include <linux/types.h>
     #include <linux/errno.h>
     #include <linux/miscdevice.h>
     #include <linux/slab.h>
     #include <linux/ioport.h>
     #include <linux/fcntl.h>
     #include <linux/mc146818rtc.h>
     #include <linux/init.h>
     #include <linux/proc_fs.h>
     #include <linux/seq_file.h>
     #include <linux/spinlock.h>
     #include <linux/io.h>
     #include <linux/uaccess.h>
     
     #include "adc.h"
     #define ADC_VERSION "1.0"
     
     void *dm365_adc_base;
     
     int adc_single(unsigned int channel)
     {
       if (channel >= ADC_MAX_CHANNELS)
         return -1;
     
       //select channel
       iowrite32(1 << channel,dm365_adc_base + DM365_ADC_CHSEL);
     
       //start coversion
       iowrite32(DM365_ADC_ADCTL_BIT_START,dm365_adc_base +
    DM365_ADC_ADCTL);
     
       // Wait for conversion to start
       while (!(ioread32(dm365_adc_base + DM365_ADC_ADCTL) &
    DM365_ADC_ADCTL_BIT_BUSY)){
         cpu_relax();
       }
     
       // Wait for conversion to be complete.
       while ((ioread32(dm365_adc_base + DM365_ADC_ADCTL) &
    DM365_ADC_ADCTL_BIT_BUSY)){
         cpu_relax();
       }
     
       return ioread32(dm365_adc_base + DM365_ADC_AD0DAT + 4 * channel);
     }
     
     static spinlock_t adc_lock = SPIN_LOCK_UNLOCKED;
     
     static void adc_read_block(unsigned short *data, size_t length)
     {
       int i;
       spin_lock_irq(&adc_lock);
         for(i = 0; i < length; i++) {
           data [i] = adc_single(i);
         }
       spin_unlock_irq(&adc_lock);
     }
     
     #ifndef CONFIG_PROC_FS
     static int adc_add_proc_fs(void)
     {
       return 0;
     }
     
     #else
     static int adc_proc_read(struct seq_file *seq, void *offset)
     {
       int i;
       unsigned short data [ADC_MAX_CHANNELS];
     
       adc_read_block(data,ADC_MAX_CHANNELS);  
      
       for(i = 0; i < ADC_MAX_CHANNELS; i++) {
         seq_printf(seq, "0x%04X\n", data[i]);
       }
     
       return 0;
     }
     
     static int adc_proc_open(struct inode *inode, struct file *file)
     {
       return single_open(file, adc_proc_read, NULL);
     }
     
     static const struct file_operations adc_proc_fops = {
       .owner    = THIS_MODULE,
       .open   = adc_proc_open,
       .read   = seq_read,
       .release  = single_release,
     };
     
     static int adc_add_proc_fs(void)
     {
       if (!proc_create("driver/adc", 0, NULL, &adc_proc_fops))
         return -ENOMEM;
       return 0;
     }
     
     #endif /* CONFIG_PROC_FS */
     
     static ssize_t adc_read(struct file *file, char __user *buf,
                 size_t count, loff_t *ppos)
     {
       unsigned short data [ADC_MAX_CHANNELS];
       
       if (count < sizeof(unsigned short))
         return -ETOOSMALL;
     
       adc_read_block(data,ADC_MAX_CHANNELS);
     
       if (copy_to_user(buf, data, count))
         return -EFAULT;
     
       return count;
     
     }
     static int adc_open(struct inode *inode, struct file *file)
     {
       return 0;
     }
     static int adc_release(struct inode *inode, struct file *file)
     {
       return 0;
     }
     static const struct file_operations adc_fops = {
       .owner    = THIS_MODULE,
       .read   = adc_read,
       .open   = adc_open,
       .release  = adc_release,
     };
     
     static struct miscdevice adc_dev = {
       NVRAM_MINOR,
       "adc",
       &adc_fops
     };
     
     
     static int adc_init_module(void)
     {
       int ret;
       ret = misc_register(&adc_dev);
       if (ret) {
         printk(KERN_ERR "adc: can't misc_register on minor=%d\n",
             NVRAM_MINOR);
         return ret;
       }
       ret = adc_add_proc_fs();
       if (ret) {
         misc_deregister(&adc_dev);
         printk(KERN_ERR "adc: can't create /proc/driver/adc\n");
         return ret;
       }
       if (!devm_request_mem_region(adc_dev.this_device,
    DM365_ADC_BASE,64,"adc"))
          return -EBUSY;
     
       dm365_adc_base =
    devm_ioremap_nocache(adc_dev.this_device,DM365_ADC_BASE, 64);// Physical
    address,Number of bytes to be mapped.
       if (!dm365_adc_base)
         return -ENOMEM;
     
       printk(KERN_INFO "TI Davinci ADC v" ADC_VERSION "\n");
       return 0;
     }
     
     static void adc_exit_module(void)
     {
       remove_proc_entry("driver/adc", NULL);
       misc_deregister(&adc_dev);
     	printk( KERN_DEBUG "Module adc exit\n" );
     }
     
     module_init(adc_init_module);
     module_exit(adc_exit_module);
     MODULE_DESCRIPTION("TI Davinci Dm365 ADC");
     MODULE_AUTHOR("Shlomo Kut,,, (shlomo at infodraw.com)");
     MODULE_LICENSE("GPL");
    
    --
    
    --
    adc.h
    
    /***************************************************************************
     *   Copyright (C) 2009 by Shlomo Kut,,,   *
     *   shlomo at shlomo-desktop   *
     *
    *
     *   This program is free software; you can redistribute it and/or
    modify  *
     *   it under the terms of the GNU General Public License as published
    by  *
     *   the Free Software Foundation; either version 2 of the License, or
    *
     *   (at your option) any later version.
    *
     *
    *
     *   This program is distributed in the hope that it will be useful,
    *
     *   but WITHOUT ANY WARRANTY; without even the implied warranty of
    *
     *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    *
     *   GNU General Public License for more details.
    *
     *
    *
     *   You should have received a copy of the GNU General Public License
    *
     *   along with this program; if not, write to the
    *
     *   Free Software Foundation, Inc.,
    *
     *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    *
    
    ***************************************************************************/
    #ifndef _ADC_h
    #define _ADC_H
    
    #define ADC_MAX_CHANNELS 6
    
    int adc_single(unsigned int channel);
    
    #define DM365_ADC_BASE      (0x01C23C00)
    
    #define DM365_ADC_ADCTL     0x0
      #define DM365_ADC_ADCTL_BIT_BUSY    (1 << 7)
      #define DM365_ADC_ADCTL_BIT_CMPFLG  (1 << 6)
      #define DM365_ADC_ADCTL_BIT_CMPIEN  (1 << 5)
      #define DM365_ADC_ADCTL_BIT_CMPMD   (1 << 4)
      #define DM365_ADC_ADCTL_BIT_SCNFLG  (1 << 3)
      #define DM365_ADC_ADCTL_BIT_SCNIEN  (1 << 2)
      #define DM365_ADC_ADCTL_BIT_SCNMD   (1 << 1)
      #define DM365_ADC_ADCTL_BIT_START   (1 << 0)
    
    #define DM365_ADC_CMPTGT    0x4
    
    #define DM365_ADC_CMPLDAT   0x8
    
    #define DM365_ADC_CMPHDAT   0xC
    
    #define DM365_ADC_SETDIV    0x10
    
    #define DM365_ADC_CHSEL     0x14
    
    #define DM365_ADC_AD0DAT    0x18
    
    #define DM365_ADC_AD1DAT    0x1C
    
    #define DM365_ADC_AD2DAT    0x20
    #define DM365_ADC_AD3DAT    0x24
    #define DM365_ADC_AD4DAT    0x28
    #define DM365_ADC_AD5DAT    0x2C
    #define DM365_ADC_EMUCTRL   0x30
    
    
    
    #endif //_ADC_H
    
    ----
    test.c
    
    //
    //test program for adc driver
    //
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    
    
    #include "../driver/adc.h"
    
    
    int main (int argc, char **argv)
    {
      int res,i,fd;
      unsigned short data [ADC_MAX_CHANNELS];
    
      printf("testing adc driver..\n");
      
      fd = open("/dev/adc",O_RDONLY);
      if (fd < 0) {
        perror("open /dev/fdc");
        return 1;
      }
    
      res = read(fd,data,sizeof(data));
      if (res != sizeof(data)) {
        perror("read failed");
        close(fd);
        return 1;
      }
      printf("raw data:");
      for( i = 0; i < ADC_MAX_CHANNELS; i++){
        printf("0x%08X ",data [i]);
      }
      printf("\n");
    
      printf("converted data:");
      for( i = 0; i < ADC_MAX_CHANNELS; i++){
        double vref = 1.8;
        double max_raw = 1 << 10;
        double volts = (double) data [i] * vref / max_raw;
        printf("%1.3fV ",volts);
      }
      printf("\n");
    
      close(fd);
      
      
      return 0;  
    }
    
    
    

  • Thanks Markus

    I will try the code, and I will comment you

    Thank you very much again

  • Hello:

    I have some problems with the library that you pass to me. The problem is opening "dev / adc. I believe the problem is that the driver is not added correctly.

    Where I have include "adc_driver.c" and "adc_driver.h? I'm using the example IPNC, and I do not know exactly where to register the drivers.

    Thank you very much

  • Josep,

    You may need to install the driver  using insmod and create the file (mknod) if it's not built into the kernel.  do you see the driver present in the /proc/devices file?

    Please keep in mind this is of course is not an official driver from TI, but was passed along through the development community,  

    Marcus

  • Marcus:

    I don't have this process in / proc

    My problem is I don't know exactly, where I have to add the library to create the process.

    P.D. I have these processes:

    1 660 davinci_clocks modules

    10 666 devices mounts

    11 7 diskstats mtd

    12 75 driver net

    13 76 execdomains partitions

    14 77 filesystems self

    170 78 fs slabinfo

    2 8 gio stat

    206 9 interrupts swaps

    209 asound iomem sys

    26 buddyinfo ioports sysrq-trigger

    280 bus irq sysvipc

    3 cmdline kallsyms tty

    4 cmem kmsg uptime

    5 config.gz loadavg version

    586 cpu locks vmstat

    6 cpuinfo meminfo yaffs

    658 crypto misc zoneinfo

     

  • Hello Marcus:

    Please you can pass to me the file .ko?
    I have problems compiling the module. I can not set the makefile

    I will appreciate it

    Greetings

  • You don't necessarily need to build the driver as a kernel module.  It can also be built into the Kernel

     

    * Create directory below and add your source and Makefile (use <linux_base_dir>/input/Makefile> as an example makefile)

    <linux_base_dir>/drivers/adc

    * Update the following file to include you adc driver

    <linux_base_dir>/drivers/Makefile => add line obj-y    += adc/

    The adc driver will be include when the kernel is built (you should see /dev/adc handle)

  • Hello Marcus:

    I do what you say, but when compiling there are no references to the following functions:

    proc_create
    devm_ioremap_nocache
    devm_request_mem_region

    Seems to be a problem with the libraries.

    Thanks for everything and sorry for the inconvenience

  • You'll need to find the header files where these routines are defined and include them in your file.