Hi Jaski,
you want more code? Here it is.
spitest-rt.c:
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <pthread.h>
#include "spi.h"
#include "gpio.h"
#define SPI_SPEED 8312500
#define SPI_BITS_PER_WORD 32
#define BUFF_SIZE 256
#define GPIO_PIN_NO 7
#define SLEEP_NSECS 200000
#define NSECS_PER_SEC 1000000000
//#define PERIOD_NSECS 1000000 // 1ms
#define PERIOD_NSECS 500000 // 500us
#define THREAD_PRIORITY 50
int add_nsecs(struct timespec *ts, long nsec)
{
ts->tv_nsec+=nsec;
while(ts->tv_nsec > NSECS_PER_SEC)
{
ts->tv_nsec-=NSECS_PER_SEC;
ts->tv_sec++;
}
return 0;
}
void *spi_thread(void *par)
{
int fd;
char buff_tx[BUFF_SIZE];
char buff_rx[BUFF_SIZE];
GPIO_PIN_DAT gpio_pin;
struct timespec req;
fd=spi_open("/dev/spidev3.0", 0, SPI_BITS_PER_WORD, SPI_SPEED);
if(fd < 0)
{
fprintf(stderr,"failed to open device\n");
return (void *)-1;
}
gpio_pin.gpio_pin_no=GPIO_PIN_NO;
gpio_pin.gpio_set_dir=GPIO_DIR_OUT;
gpio_setup(&gpio_pin);
memset(buff_tx, 0xaa, BUFF_SIZE);
gpio_write_pin(&gpio_pin, LOW);
clock_gettime(CLOCK_MONOTONIC, &req);
while(1)
{
gpio_write_pin(&gpio_pin, HIGH);
if(spi_transfer(fd, buff_tx, buff_rx, BUFF_SIZE) < 0)
fprintf(stderr,"failed to transfer\n");
gpio_write_pin(&gpio_pin, LOW);
add_nsecs(&req, PERIOD_NSECS);
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &req, NULL);
}
gpio_close(&gpio_pin);
spi_close(fd);
return NULL;
}
int main(int argc, char **argv)
{
pthread_attr_t attr;
struct sched_param sched;
pthread_t thread;
// set somethread attributes
pthread_attr_init(&attr);
pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
sched.sched_priority=THREAD_PRIORITY;
pthread_attr_setschedparam(&attr, &sched);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
// start the thread
pthread_create(&thread, &attr, spi_thread, NULL);
// wait for thread to terminate
pthread_join(thread, NULL);
return 0;
}
spi.h:
#ifndef SPI_H
#include <stdint.h>
#include <unistd.h>
int spi_open(char *, uint32_t, uint8_t, uint32_t);
ssize_t spi_transfer(int , void *, void *, size_t);
int spi_close(int);
#endif
spi.c:
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
#include <string.h>
#include "spi.h"
int spi_open(char *name, uint32_t mode, uint8_t bits, uint32_t speed)
{
int fd;
int err;
fd=open(name, O_RDWR | O_NONBLOCK);
if(fd < 0)
return -1;
err=ioctl(fd, SPI_IOC_RD_MODE32, &mode);
if(!err)
err=ioctl(fd, SPI_IOC_WR_MODE32, &mode);
if(!err)
err=ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if(!err)
err=ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if(!err)
err=ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if(!err)
err=ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if(!err)
return fd;
close(fd);
return -1;
}
ssize_t spi_transfer(int fd, void *out, void *in, size_t len)
{
struct spi_ioc_transfer buff;
memset(&buff, 0, sizeof(buff));
buff.tx_buf=(__u64)out;
buff.rx_buf=(__u64)in;
buff.len=len;
buff.delay_usecs=0;
if(ioctl(fd, SPI_IOC_MESSAGE(1), &buff) < 0)
return -1;
return len;
}
int spi_close(int fd)
{
return close(fd);
}
gpio.h:
#ifndef GPIO_H
#define GPIO_H
#include <stdint.h>
// maybe enum
#define GPIO_DIR_OUT 1
#define GPIO_DIR_IN 0
// enum
#ifndef HIGH
#define HIGH (1)
#endif
#ifndef LOW
#define LOW (0)
#endif
#ifndef BOOL
typedef int BOOL;
#endif
#ifndef TRUE
#define FALSE 0
#define TRUE (!FALSE)
#endif
typedef struct
{
uint32_t gpio_value;
uint32_t gpio_pin_no; // number of the pin
int gpio_pin_fd; // filedescriptor of the value file of the pin
uint32_t gpio_pin_mask; // only for backward compatibility
// because it is frequently used in the code
uint32_t gpio_set_dir;
} GPIO_PIN_DAT;
uint32_t gpio_setup( GPIO_PIN_DAT *); // better use BOOL
void gpio_write( GPIO_PIN_DAT *);
int32_t gpio_read( GPIO_PIN_DAT *); // negative return indicates an error
void gpio_write_pin( GPIO_PIN_DAT *, uint32_t);
// additional functions
void gpio_close( GPIO_PIN_DAT *);
#endif
gpio.c:
#include <stdio.h>
#include <limits.h>
#include <fcntl.h>
#include <unistd.h>
#include "gpio.h"
static const char *gpio_file_templ="/sys/class/gpio/gpio%d/%s";
//*----------------------------------------------------------------------------
//* Function Name : gpio_setup
//* Object : define a direction for a pin and open the value file
//* Input Parameters : p_dat: pointer to pin data
//*
//* :
//* Output Parameters : FALSE on error
//+ Date : 25.07.2018 Dietmar Muscholik
//*----------------------------------------------------------------------------
uint32_t gpio_setup( GPIO_PIN_DAT *p_dat)
{
uint32_t ret = FALSE;
char path[PATH_MAX];
int fd;
snprintf(path, sizeof(path), gpio_file_templ, p_dat->gpio_pin_no, "direction");
fd=open(path, O_WRONLY);
if(fd > 0)
{
switch(p_dat->gpio_set_dir)
{
case GPIO_DIR_IN:
if(write(fd, "in", 2) > 0)
ret = TRUE;
break;
case GPIO_DIR_OUT:
if(write(fd, "out", 3) > 0)
ret = TRUE;
break;
}
close(fd);
if(ret)
{
snprintf(path, sizeof(path), gpio_file_templ, p_dat->gpio_pin_no, "value");
p_dat->gpio_pin_fd=open(path, O_RDWR);
if(p_dat->gpio_pin_fd < 0)
ret=FALSE;
}
}
return ret;
}
//*----------------------------------------------------------------------------
//* Function Name : gpio_write
//* Object : backward compatibility, better use gpio_write_pin
//* Input Parameters : p_dat: pointer to pin data
//*
//* :
//* Output Parameters : none
//+ Date : 25.07.2018 Dietmar Muscholik
//*----------------------------------------------------------------------------
void gpio_write( GPIO_PIN_DAT *p_dat)
{
if(p_dat->gpio_value)
write(p_dat->gpio_pin_fd, "1", 1);
else
write(p_dat->gpio_pin_fd, "0", 1);
}
//*----------------------------------------------------------------------------
//* Function Name : gpio_read
//* Object : read the state of a pin
//* Input Parameters : p_dat: pointer to pin data
//*
//* :
//* Output Parameters : state of the pin (HIGH or LOW)
//+ Date : 25.07.2018 Dietmar Muscholik
//*----------------------------------------------------------------------------
int32_t gpio_read( GPIO_PIN_DAT *p_dat)
{
char buff[2];
lseek(p_dat->gpio_pin_fd,0, SEEK_SET);
if(read(p_dat->gpio_pin_fd, buff, sizeof(buff)) > 0)
return *buff=='1' ? HIGH : LOW;
return -1;
}
//*----------------------------------------------------------------------------
//* Function Name : gpio_write
//* Object : write to a pin
//* Input Parameters : p_dat: pointer to pin data
//* state: either HIGH or LOW
//* :
//* Output Parameters : none
//+ Date : 25.07.2018 Dietmar Muscholik
//*----------------------------------------------------------------------------
void gpio_write_pin( GPIO_PIN_DAT *p_dat, uint32_t state)
{
if(state) // everything but LOW is HIGH
write(p_dat->gpio_pin_fd, "1", 1);
else
write(p_dat->gpio_pin_fd, "0", 1);
}
//*----------------------------------------------------------------------------
//* Function Name : gpio_close
//* Object : close the value file
//* Input Parameters : none
//*
//* :
//* Output Parameters : none
//+ Date : 25.07.2018 Dietmar Muscholik
//*----------------------------------------------------------------------------
void gpio_close( GPIO_PIN_DAT *p_dat)
{
close(p_dat->gpio_pin_fd);
}
Makefile:
CFLAGS=-I$(SYSROOT)/usr/include -O2 -Wall
LDFLAGS=-L$(SYSROOT)/usr/lib -lpthread -lrt
spitest-rt: spitest-rt.o spi.o gpio.o
clean:
-rm spitest-rt spitest-rt.o spi.o gpio.o
That’s all I have.
Best regards,
Grimme