linux: Add support for spidev devices

Add support for sending SPI messages to devices via the standard Linux
SPI interface.  This can be used to configure the shift registers on
Replicape boards.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2017-08-13 21:06:14 -04:00
parent 73a1c9d249
commit 4d60567bc6
2 changed files with 69 additions and 1 deletions

View File

@ -3,7 +3,7 @@
dirs-y += src/linux src/generic
src-y += linux/main.c linux/timer.c linux/console.c linux/watchdog.c
src-y += linux/pca9685.c
src-y += linux/pca9685.c linux/spidev.c
src-y += generic/crc16_ccitt.c generic/alloc.c
CFLAGS_klipper.elf += -lutil

68
src/linux/spidev.c Normal file
View File

@ -0,0 +1,68 @@
// Communicating with an SPI device via linux spidev
//
// Copyright (C) 2017 Kevin O'Connor <kevin@koconnor.net>
//
// This file may be distributed under the terms of the GNU GPLv3 license.
#include <fcntl.h> // open
#include <stdio.h> // snprintf
#include <unistd.h> // write
#include "command.h" // DECL_COMMAND
#include "internal.h" // report_errno
#include "sched.h" // shutdown
struct spi_s {
uint32_t bus, dev;
int fd;
};
static struct spi_s devices[16];
static int devices_count;
static int
spi_open(uint32_t bus, uint32_t dev)
{
// Find existing device (if already opened)
int i;
for (i=0; i<devices_count; i++)
if (devices[i].bus == bus && devices[i].dev == dev)
return devices[i].fd;
// Setup new SPI device
if (devices_count >= ARRAY_SIZE(devices))
shutdown("Too many spi devices");
char fname[256];
snprintf(fname, sizeof(fname), "/dev/spidev%d.%d", bus, dev);
int fd = open(fname, O_RDWR|O_CLOEXEC);
if (fd < 0) {
report_errno("open spi", fd);
shutdown("Unable to open spi device");
}
int ret = set_non_blocking(fd);
if (ret < 0)
shutdown("Unable to set non-blocking on spi device");
devices[devices_count].bus = bus;
devices[devices_count].dev = dev;
devices[devices_count].fd = fd;
return fd;
}
static void
spi_write(int fd, char *data, int len)
{
int ret = write(fd, data, len);
if (ret < 0) {
report_errno("write spi", ret);
shutdown("Unable to write to spi");
}
}
void
command_send_spi(uint32_t *args)
{
int fd = spi_open(args[0], args[1]);
uint8_t len = args[2];
char *msg = (void*)(size_t)args[3];
spi_write(fd, msg, len);
}
DECL_COMMAND(command_send_spi, "send_spi bus=%u dev=%u msg=%*s");