daxiong

daxiong

0个粉丝

1

问答

0

专栏

0

资料

daxiong  发布于  2018-05-02 18:22:59
采纳率 0%
1个问答
4113

hi3516 adc源码

 
hi3516夜视功能中,需要使用3516的adc功能,但官方SDK中并未提供相应的用例。于是,自己编写了一个,提供给大家参考学习。其中包含adc驱动和测试代码。

[code]/* hi_adc.c
*[code]#include
#include
#include
#include
#include

#define OSDRV_MODULE_VERSION_STRING "HISI_adc @HiMPP"

extern int adc_init(void);
extern void adc_exit(void);

extern unsigned int adc_irq;
extern volatile void *pAdcRegBase;

static int hi_adc_probe(struct platform_device *pdev)
{   
    struct resource *mem;
    adc_irq = platform_get_irq(pdev, 0);
    if (adc_irq <= 0) {
            dev_err(&pdev->dev, "cannot find adc IRQ\n");
    }
   
    mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    /* 物理地址映射为虚拟地址 */
    pAdcRegBase = devm_ioremap_resource(&pdev->dev, mem);
    if (IS_ERR((const void*)pAdcRegBase))
    {
        return PTR_ERR((const void*)pAdcRegBase);
    }

    return adc_init();
}

static int hi_adc_remove(struct platform_device *pdev)
{
    adc_exit();
    return 0;
}

static const struct of_device_id hi_adc_match[] = {
    { .compatible = "hisilicon,hi_adc" },
    {},
};

static struct platform_driver hi_adc_driver = {
    .probe  = hi_adc_probe,
    .remove = hi_adc_remove,
    .driver =  { .name = "hi_adc",
                .of_match_table = hi_adc_match,
               },
};
module_platform_driver(hi_adc_driver);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Hisilicon/Cmiot");
MODULE_DESCRIPTION("Hisilicon Infrared remoter(HIIR11) Device Driver");
MODULE_VERSION("HI_VERSION=" OSDRV_MODULE_VERSION_STRING);

[code]#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv)
{
        int fd  = -1;
        const char *dev_name = "/dev/adc";
    int len;
    char buffer[4]= {0};
   
    fd = open("/dev/adc", 0);
    if (fd < 0)
    {
                perror("open ADC device:");
                return -1;
        }

        for(;;)
    {
            len = read(fd, buffer, sizeof(buffer));
            if (len > 0)
        {
                    buffer[len] = '\0';
                    int value = -1;
                    sscanf(buffer, "%d", &value);
                    printf("ADC Value: %d\n", value);
            }
        else
        {
                    perror("read ADC device:");
                    return 1;
            }
            usleep(500* 1000);
   }
       
        close(fd);
    return 0;
}

[/code][/code]
* Copyright (c) 2012 Hisilicon Co., Ltd.
*
* 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;
*
* History:
*      2012.05.15 create this file <[email]pengkang@huawei.com[/email]>
*      2012.11.20 add temp select method  <[email]sunny.liucan@huawei.com[/email]>
*/

#include "hi_osal.h"
#include
#include
#include
#include
#define HIADC_DEVICE_NAME "adc"
//#define HIDEBUG
#define ADC_IRQ                (19)

#ifndef NULL
#define NULL  ((void *)0)
#endif
#define ADC_TIME_OUT  HZ * 5    // 队列等待时间

#define OSDRV_MODULE_VERSION_STRING "HISI_ADC @Hi3516CV100"

#define LSADC_REG_BASE_ADDR             0x120E0000
#define LSADC_CTRL0              0x0000
#define LSADC_CTRL4              0x0010    /* 中断控制寄存器 */
#define LSADC_CTRL5              0x0014    /* 中断状态寄存器 */
#define LSADC_CTRL6              0x0018    /* 中断清除寄存器 */
#define LSADC_CTRL7              0x001C    /* start配置寄存器 */
#define LSADC_CTRL9              0x0024    /* 精度控制寄存器,初始值为3ff,10位 */
#define LSADC_CTRL11             0x002C    /* LSADC数据保存寄存器1 */

static osal_spinlock_t adc_spin_lock;
static osal_mutex_t hiadc_lock;
static osal_dev_t *adc_dev  = 0;
static int flag = 0;
volatile void *pAdcRegBase = NULL;
unsigned int adc_irq = 0;
osal_wait_t adc_irq_wait;

#define HIADC_REG(x)        (LSADC_REG_BASE_ADDR + (x))
#define IO_ADC_ADDRESS(x)   ((unsigned long)(pAdcRegBase) + ((x)-(LSADC_REG_BASE_ADDR)))
#define hiadc_readl(x)      osal_readl(IO_ADC_ADDRESS(HIADC_REG(x)))
#define hiadc_writel(v,x)   osal_writel(v, IO_ADC_ADDRESS(HIADC_REG(x)))

static int hi_adc_open(void *private_data)
{
    osal_wait_init(&adc_irq_wait);
    /* 设置扫描精度10位,单通道 */
    hiadc_writel(0xff0201ff, LSADC_CTRL0);
    /* 使能中断adc中断       */
    hiadc_writel(0x1, LSADC_CTRL4);
        return 0;
}

static int hi_adc_close(void *private_data)
{
    osal_wait_destory(&adc_irq_wait);
        return 0;
}

int hiadc_WaitConditionCallBack(void *pParam)
{
    return (flag == 1);
}

static int hi_adc_read(char *buf, int count, long *f_pos, void *private_data)
{
    int adc_value = 0;
    int result = 0;
    int len = 0;
    char adc_str[20];

    /* 开始转换 */
    hiadc_writel(0xf, LSADC_CTRL7);
   
    /* 等待转换完成 */
    result = osal_wait_event(&adc_irq_wait,hiadc_WaitConditionCallBack, NULL);
    if (result != 0)
    {
        osal_printk("convert timeout. \n");
        return -EFAULT;
    }
    /* 读取保存adc结果 */
    adc_value = hiadc_readl(LSADC_CTRL11);
    osal_printk("adc value is:%d.\n", adc_value);

    len = sprintf(adc_str, "%d\n", adc_value);
    osal_memcpy((void*)buf, (void*)adc_str, len);

    /* 清中断 */
    hiadc_writel(0x1, LSADC_CTRL6);
    flag = 0;
    return len;
   
}

static struct osal_fileops hi_adc_fops =
{
    .read = hi_adc_read,
    .open = hi_adc_open,
    .release = hi_adc_close,
};

static int sar_adc_interrupt(int irq, void *dev_id)
{
    /* 读取一次中断标志 */
    flag = hiadc_readl(LSADC_CTRL5) | (1 << 0);
    osal_printk("adc convert finish,flag is %d. \n", flag);

    /* 清中断 */
    hiadc_writel(0x1, LSADC_CTRL6);

    /* 唤醒读操作 */
    osal_wakeup(&adc_irq_wait);
    return OSAL_IRQ_HANDLED;
}

int adc_init(void)
{
    int ret = 0;
    /* 如果未定义中断号,直接使用默认LSADC中断 */
    if (adc_irq <= 0)
    {
        adc_irq = ADC_IRQ;   
    }

    /* 如果未设置物理地址,则直接映射IO端口 */
    if (pAdcRegBase == NULL)
    {
        pAdcRegBase = (volatile void *)osal_ioremap_nocache(LSADC_REG_BASE_ADDR, 0x100);
        if (!pAdcRegBase)
        {
            osal_printk("osal_ioremap_nocache err. \n");
            return -1;
        }
    }

    ret = osal_spin_lock_init(&adc_spin_lock);
        if (0 != ret)
        {
                osal_printk("failed to init spin lock.\n");
        return -1;
    }

        ret = osal_mutex_init(&hiadc_lock);
        if (0 != ret)
        {
                osal_printk("failed to init mutex.\n");
        goto ADC_INIT_FAIL0;
    }

    /* 分配设备节点内存 */
    adc_dev = osal_createdev(HIADC_DEVICE_NAME);
    if (NULL == adc_dev)
        {
            osal_printk("cretate adc device failed.\n");
        goto ADC_INIT_FAIL1;
        }

    /* 注册设备 */
        adc_dev->fops = &hi_adc_fops;
    adc_dev->minor = 255;
        ret = osal_registerdevice(adc_dev);
        if (0 != ret)
        {
                osal_printk("adc device register failed!\n");
        goto ADC_INIT_FAIL2;
    }

    /* 申请adc中断 */
        ret = osal_request_irq(adc_irq, sar_adc_interrupt, NULL, HIADC_DEVICE_NAME,  &sar_adc_interrupt);
        if (ret != 0)
        {
                osal_printk("hi3516CV300 adc: failed to register irq %d, (ret %d)\n", adc_irq, ret);
                goto ADC_INIT_FAIL3;
        }
        osal_printk("hi_adc init sucess, adc irq is:%d\n", adc_irq);
    return 0;
       
ADC_INIT_FAIL3:
        osal_deregisterdevice(adc_dev);
       
ADC_INIT_FAIL2:
    osal_destroydev(adc_dev);

ADC_INIT_FAIL1:
    osal_mutex_destory(&hiadc_lock);

ADC_INIT_FAIL0:
    osal_spin_lock_destory(&adc_spin_lock);
    return -1;
}

void adc_exit(void)
{
    osal_free_irq(adc_irq, &sar_adc_interrupt);
        osal_deregisterdevice(adc_dev);
        osal_destroydev(adc_dev);
        osal_mutex_destory(&hiadc_lock);
        osal_spin_lock_destory(&adc_spin_lock);
    osal_printk("hi_adc exit sucess.\n");
    return;
}

[/code]
我来回答
回答5个
时间排序
认可量排序

qn1525783135

0个粉丝

0

问答

0

专栏

0

资料

qn1525783135 2018-05-08 22:06:56
认可0
我帮不上忙,但是多谢分享

qn1533691443

0个粉丝

0

问答

0

专栏

0

资料

qn1533691443 2018-10-23 13:30:28
认可0
非常感谢分享

nightwishny

0个粉丝

4

问答

0

专栏

0

资料

nightwishny 2018-12-10 17:29:45
认可0
非常感谢,学习了!

mt_glass

0个粉丝

5

问答

1

专栏

0

资料

mt_glass 2020-03-03 16:09:19
认可0
多谢分享,刚好能参考一下。

沉成林

0个粉丝

0

问答

0

专栏

0

资料

沉成林 2020-03-10 16:07:50
认可0
谢谢分享,学习学习:)
或将文件直接拖到这里
悬赏:
E币
网盘
* 网盘链接:
* 提取码:
悬赏:
E币

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
+ 添加网盘链接/附件

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
相关问答
无更多相似问答 去提问
举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

易百纳技术社区