【TINY4412】LINUX移植笔记:(26)设备树 ADC驱动
宿主机 : 虚拟机 Ubuntu 16.04 LTS / X64
目标板[底板]: Tiny4412SDK - 1506
目标板[核心板]: Tiny4412 - 1412
LINUX内核: 4.12.0
交叉编译器: arm-none-linux-gnueabi-gcc(gcc version 4.8.3 20140320)
日期: 2017-9-9 20:30:09
作者: SY
简介
开发板自带 4
路 ADC
开发板将 ADC0
连接一个滑动变阻器。 ADC
为 12
位,最大码值为:4095
移植
设备树
参考设备树文件:
adc: adc@126C0000 {
compatible = "samsung,exynos-adc-v1";
reg = <0x126C0000 0x100>;
interrupt-parent = <&combiner>;
interrupts = <10 3>;
clocks = <&clock CLK_TSADC>;
clock-names = "adc";
#io-channel-cells = <1>;
io-channel-ranges;
samsung,syscon-phandle = <&pmu_system_controller>;
status = "disabled";
};
写自己的设备树:
&adc {
status = "okay";
};
menuconfig
Device Drivers --->
<*> Industrial I/O support --->
Analog to digital converters --->
<*> Exynos ADC driver support
烧录
[ 4.002206] exynos-adc 126c0000.adc: 126c0000.adc supply vdd not found, using dummy regulator
查看设备节点
[root@TINY4412:~]# ls /dev/iio\:device0
/dev/iio:device0
APP
/*
* adc driver for tiny4412
*
* Copyright (c) 2017
* Author: SY <1530454315@qq.com>
*
* 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.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <stdbool.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/epoll.h>
#define DEVICE_NAME "/sys/bus/iio/devices/iio\:device0/"
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
struct adc_dev {
uint8_t chn;
const char *dev;
};
const struct adc_dev adc_dev_table[] = {
{0, "in_voltage0_raw"},
{1, "in_voltage1_raw"},
{2, "in_voltage2_raw"},
{3, "in_voltage3_raw"},
};
#if 1
static void help(void)
{
printf("Usage: ./adc <chn>\n");
}
#endif
int adc_chn;
bool esc = false;
static void sigint_handler(int dunno)
{
switch (dunno) {
case SIGINT:
esc = true;
printf("< Ctrl+C > Press.\n");
break;
default:
break;
}
}
const char* match_adc_dev(uint8_t chn)
{
for (uint8_t i=0; i<ARRAY_SIZE(adc_dev_table); ++i) {
if (chn == adc_dev_table[i].chn) {
return adc_dev_table[i].dev;
}
}
return NULL;
}
static bool read_adc(char *dev, int32_t *code)
{
int fd = open(dev, O_RDONLY);
if (fd < 0) {
perror("open error");
return false;
}
char value[32];
int ret = read(fd, value, sizeof(value));
if (ret < 0) {
perror("read error");
return false;
}
int32_t adc = 0;
sscanf(value, "%d", &adc);
close(fd);
*code = adc;
return true;
}
static void* read_handler(void* data)
{
printf("thread run.\n");
char dev_name[64];
strcpy(dev_name, DEVICE_NAME);
const char *dev = match_adc_dev(adc_chn);
if (!dev) {
printf("it can't find device!\n");
return NULL;
}
strcat(dev_name, dev);
while (esc == false) {
int32_t code = 0;
if (read_adc(dev_name, &code) == false) {
printf("read_adc error!\n");
return NULL;
}
printf("[%d] %d\n", adc_chn, code);
usleep(20*1000);
}
pthread_exit(NULL);
return NULL;
}
int main(int argc, char **argv)
{
if (argc != 2) {
help();
exit(0);
}
adc_chn = atoi(argv[1]);
pthread_t thread_read;
int ret = pthread_create(&thread_read, NULL, read_handler, NULL);
if (ret) {
perror("[thread_create]");
return 1;
}
/* Register signal */
signal(SIGINT, sigint_handler);
pthread_join(thread_read, NULL);
printf("done!\n");
return 0;
}
使用 dev/iio:device0
读取数据有问题,因此使用 sysfs
读数据。
测试
[root@TINY4412:~]# ./tmp/adc 0
thread run.
[0] 0
[0] 0
[0] 0
[0] 5
[0] 20
[0] 38
[0] 81
[0] 135
[0] 181
[0] 225
[0] 263
[0] 284
[0] 311
[0] 347
[0] 362
[0] 396
[0] 433
[0] 453
[0] 484
[0] 513
[0] 531
[0] 543
[0] 567
[0] 606
[0] 621
[0] 640
[0] 662
[0] 696
[0] 724
[0] 748
[0] 798
[0] 820
[0] 845
[0] 875
[0] 893
[0] 925
[0] 946
[0] 997
[0] 1057
[0] 1097
[0] 1142
[0] 1232
[0] 1289
[0] 1368
[0] 1421
[0] 1478
[0] 1541
[0] 1601
[0] 1653
[0] 1724
[0] 1771
[0] 1800
[0] 1841
[0] 1875
[0] 1894
[0] 1942
[0] 1962
[0] 1986
[0] 2033
[0] 2062
[0] 2095
[0] 2120
[0] 2141
[0] 2162
[0] 2180
[0] 2213
[0] 2239
[0] 2273
[0] 2313
[0] 2342
[0] 2366
[0] 2391
[0] 2419
[0] 2448
[0] 2467
[0] 2496
[0] 2505
[0] 2554
[0] 2604
[0] 2623
[0] 2668
[0] 2723
[0] 2777
[0] 2836
[0] 2879
[0] 2951
[0] 3021
[0] 3046
[0] 3087
[0] 3113
[0] 3163
[0] 3211
[0] 3251
[0] 3296
[0] 3332
[0] 3377
[0] 3404
[0] 3457
[0] 3504
[0] 3561
[0] 3639
[0] 3691
[0] 3780
[0] 3854
[0] 3917
[0] 3968
[0] 4009
[0] 4064
[0] 4095
[0] 4095
[0] 4095
[0] 4095
^C< Ctrl+C > Press.
done!