kopia lustrzana https://github.com/cariboulabs/cariboulite
166 wiersze
4.2 KiB
C
166 wiersze
4.2 KiB
C
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <stdint.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <sys/ioctl.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <unistd.h>
|
||
|
#include <sched.h>
|
||
|
#include <errno.h>
|
||
|
#include <pthread.h>
|
||
|
#include "../caribou_smi.h"
|
||
|
#include "bcm2835_smi.h"
|
||
|
|
||
|
|
||
|
#define SMI_STREAM_IOC_GET_NATIVE_BUF_SIZE _IO(BCM2835_SMI_IOC_MAGIC, 3)
|
||
|
#define SMI_STREAM_IOC_SET_NON_BLOCK_READ _IO(BCM2835_SMI_IOC_MAGIC, 4)
|
||
|
#define SMI_STREAM_IOC_SET_NON_BLOCK_WRITE _IO(BCM2835_SMI_IOC_MAGIC, 5)
|
||
|
#define SMI_STREAM_IOC_SET_STREAM_STATUS _IO(BCM2835_SMI_IOC_MAGIC, 6)
|
||
|
|
||
|
static void setup_settings (struct smi_settings *settings)
|
||
|
{
|
||
|
settings->read_setup_time = 0;
|
||
|
settings->read_strobe_time = 5;
|
||
|
settings->read_hold_time = 0;
|
||
|
settings->read_pace_time = 0;
|
||
|
settings->write_setup_time = 0;
|
||
|
settings->write_hold_time = 0;
|
||
|
settings->write_pace_time = 0;
|
||
|
settings->write_strobe_time = 4;
|
||
|
settings->data_width = SMI_WIDTH_8BIT;
|
||
|
settings->dma_enable = 1;
|
||
|
settings->pack_data = 1;
|
||
|
settings->dma_passthrough_enable = 1;
|
||
|
}
|
||
|
|
||
|
pthread_t tid;
|
||
|
int fd = -1;
|
||
|
size_t native_batch_length_bytes = 0;
|
||
|
int thread_running = 0;
|
||
|
|
||
|
void* read_thread(void *arg)
|
||
|
{
|
||
|
fd_set set;
|
||
|
int rv;
|
||
|
int timeout_num_millisec = 500;
|
||
|
uint8_t *buffer = malloc(native_batch_length_bytes);
|
||
|
int size_of_buf = native_batch_length_bytes;
|
||
|
|
||
|
while (thread_running)
|
||
|
{
|
||
|
while (1)
|
||
|
{
|
||
|
struct timeval timeout = {0};
|
||
|
FD_ZERO(&set); // clear the set mask
|
||
|
FD_SET(fd, &set); // add our file descriptor to the set - and only it
|
||
|
int num_sec = timeout_num_millisec / 1000;
|
||
|
timeout.tv_sec = num_sec;
|
||
|
timeout.tv_usec = (timeout_num_millisec - num_sec*1000) * 1000;
|
||
|
|
||
|
rv = select(fd + 1, &set, NULL, NULL, &timeout);
|
||
|
if(rv == -1)
|
||
|
{
|
||
|
int error = errno;
|
||
|
switch(error)
|
||
|
{
|
||
|
case EINTR: // A signal was caught.
|
||
|
continue;
|
||
|
|
||
|
case EBADF: // An invalid file descriptor was given in one of the sets.
|
||
|
// (Perhaps a file descriptor that was already closed, or one on which an error has occurred.)
|
||
|
case EINVAL: // nfds is negative or the value contained within timeout is invalid.
|
||
|
case ENOMEM: // unable to allocate memory for internal tables.
|
||
|
default: goto exit;
|
||
|
};
|
||
|
}
|
||
|
else if (rv == 0)
|
||
|
{
|
||
|
printf("Read poll timeout\n");
|
||
|
break;
|
||
|
}
|
||
|
else if (FD_ISSET(fd, &set))
|
||
|
{
|
||
|
int num_read = read(fd, buffer, size_of_buf);
|
||
|
printf("Read %d bytes\n", num_read);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
exit:
|
||
|
free(buffer);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
int main()
|
||
|
{
|
||
|
char smi_file[] = "/dev/smi";
|
||
|
struct smi_settings settings = {0};
|
||
|
|
||
|
fd = open(smi_file, O_RDWR);
|
||
|
if (fd < 0)
|
||
|
{
|
||
|
printf("can't open smi driver file '%s'\n", smi_file);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
// Get the current settings
|
||
|
int ret = ioctl(fd, BCM2835_SMI_IOC_GET_SETTINGS, &settings);
|
||
|
if (ret != 0)
|
||
|
{
|
||
|
printf("failed reading ioctl from smi fd (settings)\n");
|
||
|
close (fd);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
// apply the new settings
|
||
|
setup_settings(&settings);
|
||
|
ret = ioctl(fd, BCM2835_SMI_IOC_WRITE_SETTINGS, &settings);
|
||
|
if (ret != 0)
|
||
|
{
|
||
|
printf("failed writing ioctl to the smi fd (settings)\n");
|
||
|
close (fd);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
// set the address to idle
|
||
|
ret = ioctl(fd, BCM2835_SMI_IOC_ADDRESS, caribou_smi_address_idle);
|
||
|
if (ret != 0)
|
||
|
{
|
||
|
printf("failed setting smi address (idle / %d) to device\n", caribou_smi_address_idle);
|
||
|
close (fd);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
// get the native batch length in bytes
|
||
|
ret = ioctl(fd, SMI_STREAM_IOC_GET_NATIVE_BUF_SIZE, &native_batch_length_bytes);
|
||
|
if (ret != 0)
|
||
|
{
|
||
|
printf("failed reading native batch length, setting default\n");
|
||
|
native_batch_length_bytes = (1024)*(1024)/2;
|
||
|
}
|
||
|
printf("Native batch size: %u\n", native_batch_length_bytes);
|
||
|
|
||
|
// start streaming data
|
||
|
ret = ioctl(fd, SMI_STREAM_IOC_SET_STREAM_STATUS, 1);
|
||
|
|
||
|
// start the reader thread
|
||
|
thread_running = 1;
|
||
|
int err = pthread_create(&tid, NULL, &read_thread, NULL);
|
||
|
if (err != 0)
|
||
|
{
|
||
|
printf("\ncan't create thread :[%s]", strerror(err));
|
||
|
}
|
||
|
|
||
|
getchar();
|
||
|
thread_running = 0;
|
||
|
|
||
|
pthread_join(tid, NULL);
|
||
|
|
||
|
ret = ioctl(fd, SMI_STREAM_IOC_SET_STREAM_STATUS, 0);
|
||
|
|
||
|
close (fd);
|
||
|
return 0;
|
||
|
}
|