From 90f7bc1d1900f198779151a7846ba5e8761b691d Mon Sep 17 00:00:00 2001 From: Anton Degtyarov Date: Thu, 19 Dec 2019 07:53:56 +0200 Subject: [PATCH 1/2] mpu6050: Fix errors, add DTS, increase precision for temperature Fix the errors in kernel module sources and developed dts. Provide precision 0.001 C for temperature. Add reading sysfs attributes log. Signed-off-by: Anton Degtyarov --- mpu6050/Makefile | 29 +------ mpu6050/logs/log_read_attributes.txt | 22 +++++ mpu6050/mpu6050.c | 119 +++++++++++++++++++++----- mpu6050/overlays/mpu6050_overlay.dtsi | 21 +++++ 4 files changed, 144 insertions(+), 47 deletions(-) create mode 100644 mpu6050/logs/log_read_attributes.txt create mode 100644 mpu6050/overlays/mpu6050_overlay.dtsi diff --git a/mpu6050/Makefile b/mpu6050/Makefile index c2abd90..1979bb0 100644 --- a/mpu6050/Makefile +++ b/mpu6050/Makefile @@ -1,32 +1,11 @@ # # mpu6050 accelerometer & gyroscope # -ifneq ($(KERNELRELEASE),) - -obj-m := mpu6050.o - -else - - -ifeq ($(KERNELDIR),) -ifeq ($(BBB_KERNEL),) - $(error Path to kernel tree - KERNELDIR or BBB_KERNEL variable is not defined!) -endif -endif - -KERNELDIR ?= $(BBB_KERNEL) - -export ARCH = arm -export CROSS_COMPILE ?= arm-linux-gnueabihf- - - -.PHONY: all clean +obj-m += mpu6050.o all: - $(MAKE) -C $(KERNELDIR) M=$(CURDIR) modules + make -C ${BUILD_KERNEL} M=$(PWD) ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules clean: - $(MAKE) -C $(KERNELDIR) M=$(CURDIR) clean - - -endif + make -C ${BUILD_KERNEL} M=$(PWD) ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- clean + \ No newline at end of file diff --git a/mpu6050/logs/log_read_attributes.txt b/mpu6050/logs/log_read_attributes.txt new file mode 100644 index 0000000..aa09648 --- /dev/null +++ b/mpu6050/logs/log_read_attributes.txt @@ -0,0 +1,22 @@ +root@orangepione:~# lsmod +Module Size Used by +mpu6050 16384 0 +auto_loadable_module 16384 0 +root@orangepione:~# cd /sys/class/mpu6050/ +root@orangepione:/sys/class/mpu6050# ls +accel_x accel_y accel_z gyro_x gyro_y gyro_z temp +root@orangepione:/sys/class/mpu6050# cat accel_x +-10812 +root@orangepione:/sys/class/mpu6050# cat accel_y +-7096 +root@orangepione:/sys/class/mpu6050# cat accel_z +11000 +root@orangepione:/sys/class/mpu6050# cat gyro_x +566 +root@orangepione:/sys/class/mpu6050# cat gyro_y +82 +root@orangepione:/sys/class/mpu6050# cat gyro_z +-369 +root@orangepione:/sys/class/mpu6050# cat temp +22.364 + diff --git a/mpu6050/mpu6050.c b/mpu6050/mpu6050.c index b6ef64b..3ee33aa 100644 --- a/mpu6050/mpu6050.c +++ b/mpu6050/mpu6050.c @@ -12,32 +12,43 @@ struct mpu6050_data { struct i2c_client *drv_client; int accel_values[3]; int gyro_values[3]; - int temperature; + int tempInt; + int tempFract; }; static struct mpu6050_data g_mpu6050_data; static int mpu6050_read_data(void) { - int temp; + int tmp; struct i2c_client *drv_client = g_mpu6050_data.drv_client; if (drv_client == 0) return -ENODEV; /* accel */ - g_mpu6050_data.accel_values[0] = (s16)((u16)i2c_smbus_read_word_swapped(drv_client, REG_ACCEL_XOUT_H)); - g_mpu6050_data.accel_values[1] = (s16)((u16)i2c_smbus_read_word_swapped(drv_client, REG_ACCEL_YOUT_H)); - g_mpu6050_data.accel_values[2] = (s16)((u16)i2c_smbus_read_word_swapped(drv_client, REG_ACCEL_ZOUT_H)); + g_mpu6050_data.accel_values[0] = + (s16)((u16)i2c_smbus_read_word_swapped(drv_client, REG_ACCEL_XOUT_H)); + g_mpu6050_data.accel_values[1] = + (s16)((u16)i2c_smbus_read_word_swapped(drv_client, REG_ACCEL_YOUT_H)); + g_mpu6050_data.accel_values[2] = + (s16)((u16)i2c_smbus_read_word_swapped(drv_client, REG_ACCEL_ZOUT_H)); + /* gyro */ - g_mpu6050_data.gyro_values[0] = (s16)((u16)i2c_smbus_read_word_swapped(drv_client, REG_GYRO_XOUT_H)); - g_mpu6050_data.gyro_values[1] = (s16)((u16)i2c_smbus_read_word_swapped(drv_client, REG_GYRO_YOUT_H)); - g_mpu6050_data.gyro_values[2] = (s16)((u16)i2c_smbus_read_word_swapped(drv_client, REG_GYRO_ZOUT_H)); + g_mpu6050_data.gyro_values[0] = + (s16)((u16)i2c_smbus_read_word_swapped(drv_client, REG_GYRO_XOUT_H)); + g_mpu6050_data.gyro_values[1] = + (s16)((u16)i2c_smbus_read_word_swapped(drv_client, REG_GYRO_YOUT_H)); + g_mpu6050_data.gyro_values[2] = + (s16)((u16)i2c_smbus_read_word_swapped(drv_client, REG_GYRO_ZOUT_H)); /* Temperature in degrees C = * (TEMP_OUT Register Value as a signed quantity)/340 + 36.53 */ - temp = (s16)((u16)i2c_smbus_read_word_swapped(drv_client, REG_TEMP_OUT_H)); - g_mpu6050_data.temperature = (temp + 12420 + 170) / 340; + tmp = (s16)((u16)i2c_smbus_read_word_swapped(drv_client, + REG_TEMP_OUT_H)); + tmp += 12420; + g_mpu6050_data.tempInt = tmp / 340; + g_mpu6050_data.tempFract = (tmp % 340) * 100 / 34; dev_info(&drv_client->dev, "sensor data read:\n"); dev_info(&drv_client->dev, "ACCEL[X,Y,Z] = [%d, %d, %d]\n", @@ -49,7 +60,7 @@ static int mpu6050_read_data(void) g_mpu6050_data.gyro_values[1], g_mpu6050_data.gyro_values[2]); dev_info(&drv_client->dev, "TEMP = %d\n", - g_mpu6050_data.temperature); + g_mpu6050_data.tempInt); return 0; } @@ -106,6 +117,12 @@ static int mpu6050_remove(struct i2c_client *drv_client) return 0; } +static const struct of_device_id mpu6050_ids[] = { + { .compatible = "mpu6050 i2c driver", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mpu6050_ids); + static const struct i2c_device_id mpu6050_idtable[] = { { "mpu6050", 0 }, { } @@ -115,6 +132,8 @@ MODULE_DEVICE_TABLE(i2c, mpu6050_idtable); static struct i2c_driver mpu6050_i2c_driver = { .driver = { .name = "gl_mpu6050", + .of_match_table = of_match_ptr(mpu6050_ids), + .owner = THIS_MODULE, }, .probe = mpu6050_probe, @@ -181,17 +200,45 @@ static ssize_t temp_show(struct class *class, { mpu6050_read_data(); - sprintf(buf, "%d\n", g_mpu6050_data.temperature); + sprintf(buf, "%i.%03i\n", g_mpu6050_data.tempInt, + g_mpu6050_data.tempFract); return strlen(buf); } -CLASS_ATTR(accel_x, 0444, &accel_x_show, NULL); -CLASS_ATTR(accel_y, 0444, &accel_y_show, NULL); -CLASS_ATTR(accel_z, 0444, &accel_z_show, NULL); -CLASS_ATTR(gyro_x, 0444, &gyro_x_show, NULL); -CLASS_ATTR(gyro_y, 0444, &gyro_y_show, NULL); -CLASS_ATTR(gyro_z, 0444, &gyro_z_show, NULL); -CLASS_ATTR(temperature, 0444, &temp_show, NULL); +struct class_attribute class_attr_accel_x = { + .attr = { .name = "accel_x", .mode = 0666 }, + .show = accel_x_show, +}; + +struct class_attribute class_attr_accel_y = { + .attr = { .name = "accel_y", .mode = 0666 }, + .show = accel_y_show, +}; + +struct class_attribute class_attr_accel_z = { + .attr = { .name = "accel_z", .mode = 0666 }, + .show = accel_z_show, +}; + +struct class_attribute class_attr_gyro_x = { + .attr = { .name = "gyro_x", .mode = 0666 }, + .show = gyro_x_show, +}; + +struct class_attribute class_attr_gyro_y = { + .attr = { .name = "gyro_y", .mode = 0666 }, + .show = gyro_y_show, +}; + +struct class_attribute class_attr_gyro_z = { + .attr = { .name = "gyro_z", .mode = 0666 }, + .show = gyro_z_show, +}; + +struct class_attribute class_attr_temp = { + .attr = { .name = "temp", .mode = 0666 }, + .show = temp_show, +}; static struct class *attr_class; @@ -219,42 +266,70 @@ static int mpu6050_init(void) /* Create accel_x */ ret = class_create_file(attr_class, &class_attr_accel_x); if (ret) { - pr_err("mpu6050: failed to create sysfs class attribute accel_x: %d\n", ret); + class_destroy(attr_class); + pr_err("mpu6050: failed to create sysfs class attribute accel_x:%d\n", ret); return ret; } /* Create accel_y */ ret = class_create_file(attr_class, &class_attr_accel_y); if (ret) { + class_remove_file(attr_class, &class_attr_accel_x); + class_destroy(attr_class); pr_err("mpu6050: failed to create sysfs class attribute accel_y: %d\n", ret); return ret; } /* Create accel_z */ ret = class_create_file(attr_class, &class_attr_accel_z); if (ret) { + class_remove_file(attr_class, &class_attr_accel_y); + class_remove_file(attr_class, &class_attr_accel_x); + class_destroy(attr_class); pr_err("mpu6050: failed to create sysfs class attribute accel_z: %d\n", ret); return ret; } /* Create gyro_x */ ret = class_create_file(attr_class, &class_attr_gyro_x); if (ret) { + class_remove_file(attr_class, &class_attr_accel_z); + class_remove_file(attr_class, &class_attr_accel_y); + class_remove_file(attr_class, &class_attr_accel_x); + class_destroy(attr_class); pr_err("mpu6050: failed to create sysfs class attribute gyro_x: %d\n", ret); return ret; } /* Create gyro_y */ ret = class_create_file(attr_class, &class_attr_gyro_y); if (ret) { + class_remove_file(attr_class, &class_attr_gyro_x); + class_remove_file(attr_class, &class_attr_accel_z); + class_remove_file(attr_class, &class_attr_accel_y); + class_remove_file(attr_class, &class_attr_accel_x); + class_destroy(attr_class); pr_err("mpu6050: failed to create sysfs class attribute gyro_y: %d\n", ret); return ret; } /* Create gyro_z */ ret = class_create_file(attr_class, &class_attr_gyro_z); if (ret) { + class_remove_file(attr_class, &class_attr_gyro_y); + class_remove_file(attr_class, &class_attr_gyro_x); + class_remove_file(attr_class, &class_attr_accel_z); + class_remove_file(attr_class, &class_attr_accel_y); + class_remove_file(attr_class, &class_attr_accel_x); + class_destroy(attr_class); pr_err("mpu6050: failed to create sysfs class attribute gyro_z: %d\n", ret); return ret; } /* Create temperature */ - ret = class_create_file(attr_class, &class_attr_temperature); + ret = class_create_file(attr_class, &class_attr_temp); if (ret) { + class_remove_file(attr_class, &class_attr_gyro_z); + class_remove_file(attr_class, &class_attr_gyro_y); + class_remove_file(attr_class, &class_attr_gyro_x); + class_remove_file(attr_class, &class_attr_accel_z); + class_remove_file(attr_class, &class_attr_accel_y); + class_remove_file(attr_class, &class_attr_accel_x); + class_destroy(attr_class); pr_err("mpu6050: failed to create sysfs class attribute temperature: %d\n", ret); return ret; } @@ -274,7 +349,7 @@ static void mpu6050_exit(void) class_remove_file(attr_class, &class_attr_gyro_x); class_remove_file(attr_class, &class_attr_gyro_y); class_remove_file(attr_class, &class_attr_gyro_z); - class_remove_file(attr_class, &class_attr_temperature); + class_remove_file(attr_class, &class_attr_temp); pr_info("mpu6050: sysfs class attributes removed\n"); class_destroy(attr_class); diff --git a/mpu6050/overlays/mpu6050_overlay.dtsi b/mpu6050/overlays/mpu6050_overlay.dtsi new file mode 100644 index 0000000..4ef98dc --- /dev/null +++ b/mpu6050/overlays/mpu6050_overlay.dtsi @@ -0,0 +1,21 @@ +/dts-v1/; +/plugin/; + +/ { + compatible = "allwinner,sun8i-h3"; + + fragment@0 { + target = <&i2c0>; + __overlay__ { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + mpu6050@68 { + compatible = "mpu6050 i2c driver"; + reg = <0x68>; + status = "okay"; + }; + }; + }; +}; \ No newline at end of file From b5af482da8a63887f6f307a5e6adcb64aebd7bf4 Mon Sep 17 00:00:00 2001 From: Anton Degtyarov Date: Thu, 19 Dec 2019 09:01:33 +0200 Subject: [PATCH 2/2] mpu6050: Add solution for measuring the performance and improve it Add userspace program for measure the performance by getting all values in cycle during 1 second. Improve the performance and measure it. Add log of measuring the performance before and after improvment. Signed-off-by: Anton Degtyarov --- mpu6050/logs/measuring_performance_log.txt | 41 +++++++++++ mpu6050/mpu6050.c | 71 +++++++++++++------ mpu6050/user_measuring_performance/Makefile | 10 +++ .../user_measuring_performance/meas_perform.c | 62 ++++++++++++++++ 4 files changed, 162 insertions(+), 22 deletions(-) create mode 100644 mpu6050/logs/measuring_performance_log.txt create mode 100644 mpu6050/user_measuring_performance/Makefile create mode 100644 mpu6050/user_measuring_performance/meas_perform.c diff --git a/mpu6050/logs/measuring_performance_log.txt b/mpu6050/logs/measuring_performance_log.txt new file mode 100644 index 0000000..8f9b275 --- /dev/null +++ b/mpu6050/logs/measuring_performance_log.txt @@ -0,0 +1,41 @@ + +/*Before the performance improvement*/ + +root@orangepione:/storage# ./meas_perform.exe +Amount of readings per second: 40 +root@orangepione:/storage# ./meas_perform.exe +Amount of readings per second: 40 +root@orangepione:/storage# ./meas_perform.exe +Amount of readings per second: 40 +root@orangepione:/storage# ./meas_perform.exe +Amount of readings per second: 39 +root@orangepione:/storage# ./meas_perform.exe +Amount of readings per second: 39 + +/*After the performance improvement*/ + +root@orangepione:/storage# ./meas_perform.exe +Amount of readings per second: 256 +root@orangepione:/storage# ./meas_perform.exe +Amount of readings per second: 258 +root@orangepione:/storage# ./meas_perform.exe +Amount of readings per second: 265 +root@orangepione:/storage# ./meas_perform.exe +Amount of readings per second: 265 +root@orangepione:/storage# ./meas_perform.exe +Amount of readings per second: 265 +root@orangepione:/storage# ./meas_perform.exe +Amount of readings per second: 265 +root@orangepione:/storage# ./meas_perform.exe +Amount of readings per second: 265 +root@orangepione:/storage# ./meas_perform.exe +Amount of readings per second: 265 +root@orangepione:/storage# ./meas_perform.exe +Amount of readings per second: 265 +root@orangepione:/storage# ./meas_perform.exe +Amount of readings per second: 265 +root@orangepione:/storage# ./meas_perform.exe +Amount of readings per second: 265 +root@orangepione:/storage# ./meas_perform.exe +Amount of readings per second: 265 + diff --git a/mpu6050/mpu6050.c b/mpu6050/mpu6050.c index 3ee33aa..ac5e574 100644 --- a/mpu6050/mpu6050.c +++ b/mpu6050/mpu6050.c @@ -16,9 +16,19 @@ struct mpu6050_data { int tempFract; }; +enum SYSFS_ATTR { +ATTR_ACCEL_X = 0, +ATTR_ACCEL_Y, +ATTR_ACCEL_Z, +ATTR_GYRO_X, +ATTR_GYRO_Y, +ATTR_GYRO_Z, +ATTR_TEMP, +}; + static struct mpu6050_data g_mpu6050_data; -static int mpu6050_read_data(void) +static int mpu6050_read_data(int attrNum) { int tmp; struct i2c_client *drv_client = g_mpu6050_data.drv_client; @@ -26,41 +36,58 @@ static int mpu6050_read_data(void) if (drv_client == 0) return -ENODEV; + switch (attrNum) { /* accel */ + case 0: g_mpu6050_data.accel_values[0] = (s16)((u16)i2c_smbus_read_word_swapped(drv_client, REG_ACCEL_XOUT_H)); + dev_info(&drv_client->dev, "ACCEL_X = %d\n", + g_mpu6050_data.accel_values[0]); + break; + case 1: g_mpu6050_data.accel_values[1] = (s16)((u16)i2c_smbus_read_word_swapped(drv_client, REG_ACCEL_YOUT_H)); + dev_info(&drv_client->dev, "ACCEL_Y = %d\n", + g_mpu6050_data.accel_values[1]); + break; + case 2: g_mpu6050_data.accel_values[2] = (s16)((u16)i2c_smbus_read_word_swapped(drv_client, REG_ACCEL_ZOUT_H)); - + dev_info(&drv_client->dev, "ACCEL_Z = %d\n", + g_mpu6050_data.accel_values[2]); + break; /* gyro */ + case 3: g_mpu6050_data.gyro_values[0] = (s16)((u16)i2c_smbus_read_word_swapped(drv_client, REG_GYRO_XOUT_H)); + dev_info(&drv_client->dev, "GYRO_X = %d\n", + g_mpu6050_data.gyro_values[0]); + break; + case 4: g_mpu6050_data.gyro_values[1] = (s16)((u16)i2c_smbus_read_word_swapped(drv_client, REG_GYRO_YOUT_H)); + dev_info(&drv_client->dev, "GYRO_Y = %d\n", + g_mpu6050_data.gyro_values[1]); + break; + case 5: g_mpu6050_data.gyro_values[2] = (s16)((u16)i2c_smbus_read_word_swapped(drv_client, REG_GYRO_ZOUT_H)); + dev_info(&drv_client->dev, "GYRO_Z = %d\n", + g_mpu6050_data.gyro_values[2]); + break; /* Temperature in degrees C = * (TEMP_OUT Register Value as a signed quantity)/340 + 36.53 */ - tmp = (s16)((u16)i2c_smbus_read_word_swapped(drv_client, + case 6: + + tmp = (s16)((u16)i2c_smbus_read_word_swapped(drv_client, REG_TEMP_OUT_H)); tmp += 12420; g_mpu6050_data.tempInt = tmp / 340; g_mpu6050_data.tempFract = (tmp % 340) * 100 / 34; - - dev_info(&drv_client->dev, "sensor data read:\n"); - dev_info(&drv_client->dev, "ACCEL[X,Y,Z] = [%d, %d, %d]\n", - g_mpu6050_data.accel_values[0], - g_mpu6050_data.accel_values[1], - g_mpu6050_data.accel_values[2]); - dev_info(&drv_client->dev, "GYRO[X,Y,Z] = [%d, %d, %d]\n", - g_mpu6050_data.gyro_values[0], - g_mpu6050_data.gyro_values[1], - g_mpu6050_data.gyro_values[2]); - dev_info(&drv_client->dev, "TEMP = %d\n", - g_mpu6050_data.tempInt); + dev_info(&drv_client->dev, "TEMP = %d\n", g_mpu6050_data.tempInt); + break; + } return 0; } @@ -144,7 +171,7 @@ static struct i2c_driver mpu6050_i2c_driver = { static ssize_t accel_x_show(struct class *class, struct class_attribute *attr, char *buf) { - mpu6050_read_data(); + mpu6050_read_data(ATTR_ACCEL_X); sprintf(buf, "%d\n", g_mpu6050_data.accel_values[0]); return strlen(buf); @@ -153,7 +180,7 @@ static ssize_t accel_x_show(struct class *class, static ssize_t accel_y_show(struct class *class, struct class_attribute *attr, char *buf) { - mpu6050_read_data(); + mpu6050_read_data(ATTR_ACCEL_Y); sprintf(buf, "%d\n", g_mpu6050_data.accel_values[1]); return strlen(buf); @@ -162,7 +189,7 @@ static ssize_t accel_y_show(struct class *class, static ssize_t accel_z_show(struct class *class, struct class_attribute *attr, char *buf) { - mpu6050_read_data(); + mpu6050_read_data(ATTR_ACCEL_Z); sprintf(buf, "%d\n", g_mpu6050_data.accel_values[2]); return strlen(buf); @@ -171,7 +198,7 @@ static ssize_t accel_z_show(struct class *class, static ssize_t gyro_x_show(struct class *class, struct class_attribute *attr, char *buf) { - mpu6050_read_data(); + mpu6050_read_data(ATTR_GYRO_X); sprintf(buf, "%d\n", g_mpu6050_data.gyro_values[0]); return strlen(buf); @@ -180,7 +207,7 @@ static ssize_t gyro_x_show(struct class *class, static ssize_t gyro_y_show(struct class *class, struct class_attribute *attr, char *buf) { - mpu6050_read_data(); + mpu6050_read_data(ATTR_GYRO_Y); sprintf(buf, "%d\n", g_mpu6050_data.gyro_values[1]); return strlen(buf); @@ -189,7 +216,7 @@ static ssize_t gyro_y_show(struct class *class, static ssize_t gyro_z_show(struct class *class, struct class_attribute *attr, char *buf) { - mpu6050_read_data(); + mpu6050_read_data(ATTR_GYRO_Z); sprintf(buf, "%d\n", g_mpu6050_data.gyro_values[2]); return strlen(buf); @@ -198,7 +225,7 @@ static ssize_t gyro_z_show(struct class *class, static ssize_t temp_show(struct class *class, struct class_attribute *attr, char *buf) { - mpu6050_read_data(); + mpu6050_read_data(ATTR_TEMP); sprintf(buf, "%i.%03i\n", g_mpu6050_data.tempInt, g_mpu6050_data.tempFract); diff --git a/mpu6050/user_measuring_performance/Makefile b/mpu6050/user_measuring_performance/Makefile new file mode 100644 index 0000000..3737075 --- /dev/null +++ b/mpu6050/user_measuring_performance/Makefile @@ -0,0 +1,10 @@ + +output: meas_perform.o + arm-linux-gnueabihf-gcc meas_perform.o -o meas_perform.exe + +meas_perform.o: meas_perform.c + arm-linux-gnueabihf-gcc meas_perform.c -c + +clean: + rm *.o meas_perform.exe + diff --git a/mpu6050/user_measuring_performance/meas_perform.c b/mpu6050/user_measuring_performance/meas_perform.c new file mode 100644 index 0000000..3ceb4d0 --- /dev/null +++ b/mpu6050/user_measuring_performance/meas_perform.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include +#include + +#define ATTR_AMOUNT 7 +#define CLASS_PATH "/sys/class/mpu6050/" + +char *sysAttrPath[] = { + CLASS_PATH"accel_x", + CLASS_PATH"accel_y", + CLASS_PATH"accel_z", + CLASS_PATH"gyro_x", + CLASS_PATH"gyro_y", + CLASS_PATH"gyro_z", + CLASS_PATH"temp" +}; + +int measureReadFreq(int *counter) +{ + struct timespec tStart, tCurrent; + *counter = 0; + + // get start measuring time + clock_gettime(CLOCK_REALTIME, &tStart); + + do { + for (int i = 0; i < ATTR_AMOUNT; i++) { + int fd = 0, ret = 0; + char str[32] = {0}; + + fd = open(sysAttrPath[i], O_RDONLY); + if (fd < 0) + return 0; + + ret = read(fd, str, sizeof(str)); + if (ret < 0) + return 0; + + close(fd); + } + + (*counter)++; + clock_gettime(CLOCK_REALTIME, &tCurrent); + + } while (tCurrent.tv_sec == tStart.tv_sec || + tCurrent.tv_nsec < tStart.tv_nsec); +} + +int main(void) +{ + int counter; + + if (measureReadFreq(&counter)) + printf("Amount of readings per second: %d\n", counter); + else + printf("Error\n"); + + return 0; +}