Reading huge amount of data throught i2c - c

I am trying to receive huge amount of data throught i2c. Here is my code. The main problem is that it takes more than 2 seconds when i need to let it be done in less than 0.5 sec. Here is the device: https://www.st.com/resource/en/datasheet/lsm6ds33.pdf
image with i2c interface
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#include <time.h>
#include <sys/time.h>
#include <fcntl.h>
#include <stdint.h>
#include <stddef.h>
#define FIFO_DATA_OUT_L 0x3E
#define FIFO_DATA_OUT_H 0X3F
struct timeval stop, start;
int main()
{
uint8_t addressL = FIFO_DATA_OUT_L;
uint8_t addressH = FIFO_DATA_OUT_H;
uint8_t resultL;
uint8_t resultH;
int16_t result;
gettimeofday(&start,NULL);
int fd;
if ((fd = open("/dev/i2c-0",O_RDWR))< 0)
{
perror("failed to connect to i2c");
exit(0);
}
ioctl(fd,I2C_SLAVE,0x6b);// Setting slave address
long i;
for (i=0; i< 2499; i++)
{
write(fd,&addressL,1);
read(fd,&resultL,1);
write(fd,&addressH,1);
read(fd,&resultH,1);
result = (resultH << 8) | resultL;
}
gettimeofday(&stop,NULL);
printf("Time elapsed: %d \n",stop.tv_sec-start.tv_sec);
return;
}
I am wondering if there is some possibility to make things faster. Cheers.

I think your FIFO size is 2 Byte then you can write/read 2 Byte each time instead of 1.
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#include <time.h>
#include <sys/time.h>
#include <fcntl.h>
#include <stdint.h>
#include <stddef.h>
#define FIFO_DATA_OUT_L 0x3E
#define FIFO_DATA_OUT_H 0X3F
struct timeval stop, start;
int main()
{
uint8_t addressL = FIFO_DATA_OUT_L;
uint8_t addressH = FIFO_DATA_OUT_H;
uint16_t result;
gettimeofday(&start,NULL);
int fd;
if ((fd = open("/dev/i2c-0",O_RDWR))< 0)
{
perror("failed to connect to i2c");
exit(0);
}
ioctl(fd,I2C_SLAVE,0x6b);// Setting slave address
long i;
for (i=0; i< 1250; i++)
{
write(fd,&addressL,2);
read(fd,&result,2);
}
gettimeofday(&stop,NULL);
printf("Time elapsed: %d \n",stop.tv_sec-start.tv_sec);
return;
}

Related

Not able to pass strings through named pipes (FIFOs) in multithreaded processes

I am trying to use 'FIFOs' and 'popen()' function for communication between multiple processes. Also, the first process is multithreaded for reading and writing operations.
Following is the C code for the processes:
P1 process (Q1.c)
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
void* reader()
{
char string[64];
int rfd = open("FIFO",O_RDONLY);
while(1)
{
read(rfd,string,sizeof(string));
sleep(10);
printf("%s\n",string);
}
}
void* writer()
{
char string[64];
FILE *wfd = popen("./Q1_1","w");
int fd = fileno(wfd);
while(1)
{
scanf("%s",string);
write(fd,string,sizeof(string));
}
pclose(wfd);
}
int main()
{
if(mkfifo("FIFO",0666)==-1)
{
if(errno!=EEXIST)
{
return 1;
}
}
pthread_t r_thread,s_thread;
pthread_create(&r_thread,NULL,reader,NULL);
pthread_create(&s_thread,NULL,writer,NULL);
pthread_join(r_thread,NULL);
pthread_join(s_thread,NULL);
return 0;
}
P2 Process (Q1_1.c)
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
int main()
{
FILE *fd = popen("./Q1_2","w");
char string[64];
int ffd = fileno(fd);
printf("P2Check");
while(1)
{
scanf("%s",string);
write(ffd,string,sizeof(string));
}
return 0;
}
P3 Process (Q1_2.c)
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
int main()
{
char string[64];
if(mkfifo("FIFO",0666)==-1)
{
if(errno!=EEXIST)
{
return 1;
}
}
int wfd = open("FIFO",O_WRONLY);
printf("P3Check");
while(1)
{
scanf("%s",string);
write(wfd,string,sizeof(string));
}
}
However, after executing process P1 and providing input, there is no output as if the process is stuck. I suspect there is some issue with the multithreading but not sure.

How to capture raw keyboard input on Windows

I have a device that acts like a HID (keyboard). I was able to capture and grab the raw input of the device on Linux. I needed to get exclusive rights to the device so that no other application could receive input from it. I accomplished this using ioctl and EVIOCGRAB
But it doesn't compile under Windows. I have found that there is a RegisterRawInputDevices function but it doesn't seem to provide exclusive rights to the device. What could be used on Windows to achieve the same effect?
Here is my code that works on Linux
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <dirent.h>
#include <linux/input.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <sys/time.h>
#include <termios.h>
#include <signal.h>
int main(int argc, char* argv[])
{
struct input_event ev[64];
int fevdev = -1;
int result = 0;
int size = sizeof(struct input_event);
int rd;
int value;
char name[256] = "Unknown";
char *device = "/dev/input/event16";
fevdev = open(device, O_RDONLY);
ioctl(fevdev, EVIOCGRAB, 1);
while (1)
{
read(fevdev, ev, size * 64);
value = ev[0].value;
printf ("code - %d \n", ev[1].code);
}
ioctl(fevdev, EVIOCGRAB, 0);
close(fevdev);
}

Updating shared memory by different process

I'm writing some code for a project and I have an issue when I try to update an area of shared memory with another process.
Basically one process create a shared memory, then it creates one child that, using execve, execute a process the aim of which is to update that shared memory knowing its key.
At the end the main process prints all the datas from the shm to stdout.
At that point I have noticed that shm has not been updated.
I can't understand why. I've tried with regular assignment (=) or assigning every field with a function (updatef), but it doesn't work.
(Of course in the real program I used semaphores to regulate the access to shm, i wrote this code to minimize the code to see the problem)
Process t:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/signal.h>
#include <fcntl.h>
#include <stdarg.h>
#include <errno.h>
#include <time.h>
#define mykey 100
#define maxname 100
#define shmsz 5
#define perms 0666
struct pdata{
pid_t ppid;
char ptype;
char pname[maxname];
unsigned long pgenome;
};
void updatef(struct pdata a, struct pdata p){
a.ppid = p.ppid;
a.ptype = p.ptype;
strcpy(a.pname, p.pname);
a.pgenome = p.pgenome;
}
int main(){
int shmid;
struct pdata *addr;
shmid = shmget(mykey, sizeof(struct pdata) * shmsz, IPC_CREAT | perms);
addr = (struct pdata*) shmat(shmid, NULL, 0);
for(int i=0; i<shmsz; i++){
addr[i].ppid = -1;
}
switch(fork()){
case 0:
{
char *args[] = {"u", NULL};
execve("u", args, NULL);
}
break;
}
sleep(2);
for(int i=0; i<shmsz; i++){
printf("%d %c %s %lu\n", addr[i].ppid, addr[i].ptype, addr[i].pname, addr[i].pgenome);
}
shmdt(addr);
shmctl(shmid, IPC_RMID, 0);
return 0;
}
Process u:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/signal.h>
#include <fcntl.h>
#include <stdarg.h>
#include <errno.h>
#include <time.h>
#define mykey 100
#define maxname 100
#define shmsz 5
#define perms 0666
struct pdata{
pid_t ppid;
char ptype;
char pname[maxname];
unsigned long pgenome;
};
void updatef(struct pdata a, struct pdata p){
a.ppid = p.ppid;
a.ptype = p.ptype;
strcpy(a.pname, p.pname);
a.pgenome = p.pgenome;
}
int main(){
int shmid;
struct pdata *addr;
struct pdata p;
shmid = shmget(mykey, sizeof(struct pdata) * shmsz, perms);
addr = (struct pdata*) shmat(shmid, NULL, 0);
p.ppid = getpid();
p.ptype = 'A';
strncpy(p.pname, "PIPPO", maxname);
p.pgenome = 10;
for(int i=0; i<shmsz; i++){
updatef(addr[i], p);
}
shmdt(addr);
return 0;
}
Short answer is of course passing pointer instead of value and that'll do
updatef(&arr[i], p);
Long answer lies in pass by value and pass by reference, when updatef is called with addr[i] as in
updatef(arr[i], p);
essentially the value is copied to calling function and never gets reflected to attached pointer viz addr as a result the original addr pointer get unchanged on the other hand when we pass the address like
updatef(&addr[i], p);
//or
updatef(addr+i, p);
reference is passed which inturn will update the contents pointed to by addr+i pointer
to add on IMO splitting the code will make this more presentable and readable and maintainable and bla bla bla here is a bit
File 1 - s.h, keep shared and global data here
#ifndef S_H_INCLUDED
#define S_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/signal.h>
#include <fcntl.h>
#include <stdarg.h>
#include <errno.h>
#include <time.h>
#define mykey 100
#define maxname 100
#define shmsz 5
#define perms 0666
struct pdata{
pid_t ppid;
char ptype;
char pname[maxname];
unsigned long pgenome; };
#endif
t.c
#include "s.h" // include global header here
int main(){
int shmid;
struct pdata *addr;
shmid = shmget(mykey, sizeof(struct pdata) * shmsz, IPC_CREAT | perms);
addr = (struct pdata*) shmat(shmid, NULL, 0);
for(int i=0; i<shmsz; i++){
addr[i].ppid = -1;
}
switch(fork()){
case 0:
{
char *args[] = {"u", NULL};
execve("u", args, NULL);
}
break;
}
sleep(2);
for(int i=0; i<shmsz; i++){
printf("%d %c %s %lu\n", addr[i].ppid, addr[i].ptype, addr[i].pname, addr[i].pgenome);
}
shmdt(addr);
shmctl(shmid, IPC_RMID, 0);
return 0;
}
u.c
#include "s.h" // common included here
static void updatef(struct pdata *a, struct pdata p){
a->ppid = p.ppid;
a->ptype = p.ptype;
strcpy(a->pname, p.pname);
a->pgenome = p.pgenome;
}
int main(){
int shmid;
struct pdata *addr;
struct pdata p;
shmid = shmget(mykey, sizeof(struct pdata) * shmsz, perms);
addr = (struct pdata*) shmat(shmid, NULL, 0);
p.ppid = getpid();
p.ptype = 'A';
strncpy(p.pname, "PIPPO", maxname);
p.pgenome = 10;
for(int i=0; i<shmsz; i++){
updatef(addr+i, p);
}
shmdt(addr);
return 0;
}
and the final build step
gcc t.c -o t
gcc u.c -o u

Kill() function between two processes

Can I use the kill() function to send a signal to another process? It should be possible, but kill() fails and I can't understand why.
I have two programs (process_1 and process_2). The first one should set a signal handler to increase a variable, than create a child that uses execve and loads process_2. The other program should send the signal using kill(). I used the shared memory to share process_1's pid through a struct (because I have other variables to share). The code of the first program is as follows:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <signal.h>
#include <errno.h>
#include <time.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/wait.h>
#define KEY_SM 1234
static int value_to_change=0;
typedef struct keys{
pid_t pid_process;
}keynote;
static void test_handler(int signo){
if(signo=SIGUSR1){
printf("received SIGUSR1\n");
value_to_change++;
}
}
int main(){
if((signal(SIGUSR1, test_handler))==SIG_ERR) perror("Errore allocazione SIGUSR1");
int flags = S_IRUSR|S_IWUSR|IPC_CREAT;
size_t shm_size = sizeof(keynote);
int shm_id = shmget(KEY_MC, shm_size, flags);
keynote *chv = shmat(shm_id, NULL, 0);
chv->pid_process=getpid();
printf("%d\n",chv->pid_process);
int process_2;
process_2=fork();
if(process_2==0){
char* argv[]={"process_1", "process_2", NULL};
if((execve("process_2", argv, NULL))<0) perror("execve error");
exit(0);
}else if(process_2<0)perror("fork error");
return 0;
}
The second program code is:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <signal.h>
#include <errno.h>
#include <time.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/wait.h>
#define KEY_SM 1234
typedef struct keys{
pid_t pid_process;
}keynote;
static void signal_to_send(pid_t process){
int ret=kill(process, SIGUSR1);
printf("%d", ret);
}
}
int main(int argc, char **argv){
int pid_of_process_1;
int flags = S_IRUSR|S_IWUSR|IPC_CREAT;
size_t shm_size = sizeof(keynote);
int shm_id = shmget(KEY_MC, shm_size, flags);
keynote *chv = shmat(shm_id, NULL, 0);
signal_to_send(chv->pid_process);
return 0;
}
process_1 does not wait for process_2. It just exits immediately. At which point process_2 may not even have started. So when process_2 sends the signal, process_1 is likely to not exist anymore.
– kaylum

problem with O_DIRECT IO with aligned stack buffer

The following code fails when the buffer is on the stack, but succeeds when it's allocated on the heap. I tested it on RHEL 5.3 with a Raid drive. Is it possible to use O_DIRECT with stack buffers?
#define _GNU_SOURCE
#include <stdio.h>
#include <assert.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#include <malloc.h>
#define K 1024
#define ALIGNMENT (4*K)
#define RDSIZE (16*K)
#define BLOCKSIZE (512*K)
int main()
{
int flags = O_RDONLY | O_LARGEFILE;
int n = 0;
int fd = 0;
char* buf = (char *) memalign(ALIGNMENT, BLOCKSIZE);
//char buf[BLOCKSIZE] __attribute__((__aligned__(ALIGNMENT)));
assert(((long)buf) % ALIGNMENT == 0);
fd = open("test", flags | O_DIRECT);
if (fd < 0) {
perror("file open");
return -1;
}
n = read(fd, buf, RDSIZE);
if (n < 0) {
perror("file read");
return -1;
}
printf("%d\n", n);
close(fd);
}
UPDATE: Same code when compiled with Intel CC succeeds.
Check your stack size 512K is quite a lot.
If the problem is gcc misaligning buf, try this portable version instead:
char x_buf[BLOCKSIZE+PAGE_SIZE];
char *buf = buf + (PAGE_SIZE-1 & -(uintptr_t)x_buf);

Resources