CreatBotKlipper/src/spicmds.c
Grigori Goronzy ebd9035325 SPI: introduce spi_prepare function
The SPI interface needs to be enabled and configured to the correct
settings of a given oid before CS is asserted. The new function
spi_prepare() allows ports to do that.

This port only introduces the new function in all ports with no
implementation and adds the call to the Klipper generic firmware code.
That means everything still works as before. Ports need to be changed
to fix the underlying issue.

Discussion about the motivation here:
https://github.com/KevinOConnor/klipper/pull/453#issuecomment-403131149

Signed-off-by: Grigori Goronzy <greg@chown.ath.cx>
2018-07-08 09:25:11 -04:00

112 lines
3.4 KiB
C

// Commands for sending messages on an SPI bus
//
// Copyright (C) 2016-2018 Kevin O'Connor <kevin@koconnor.net>
//
// This file may be distributed under the terms of the GNU GPLv3 license.
#include <string.h> // memcpy
#include "board/gpio.h" // gpio_out_write
#include "basecmd.h" // oid_alloc
#include "command.h" // DECL_COMMAND
#include "sched.h" // DECL_SHUTDOWN
struct spidev_s {
struct spi_config spi_config;
struct gpio_out pin;
uint8_t flags;
uint8_t shutdown_msg_len;
uint8_t shutdown_msg[];
};
enum {
SF_HAVE_PIN = 1,
};
void
command_config_spi(uint32_t *args)
{
uint8_t shutdown_msg_len = args[5];
struct spidev_s *spi = oid_alloc(args[0], command_config_spi
, sizeof(*spi) + shutdown_msg_len);
spi->pin = gpio_out_setup(args[2], 1);
spi->flags = SF_HAVE_PIN;
spi->spi_config = spi_setup(args[1], args[3], args[4]);
spi->shutdown_msg_len = shutdown_msg_len;
uint8_t *shutdown_msg = (void*)(size_t)args[6];
memcpy(spi->shutdown_msg, shutdown_msg, shutdown_msg_len);
}
DECL_COMMAND(command_config_spi,
"config_spi oid=%c bus=%u pin=%u mode=%u rate=%u shutdown_msg=%*s");
void
command_config_spi_without_cs(uint32_t *args)
{
uint8_t shutdown_msg_len = args[4];
struct spidev_s *spi = oid_alloc(args[0], command_config_spi
, sizeof(*spi) + shutdown_msg_len);
spi->spi_config = spi_setup(args[1], args[2], args[3]);
spi->shutdown_msg_len = shutdown_msg_len;
uint8_t *shutdown_msg = (void*)(size_t)args[5];
memcpy(spi->shutdown_msg, shutdown_msg, shutdown_msg_len);
}
DECL_COMMAND(command_config_spi_without_cs,
"config_spi_without_cs oid=%c bus=%u mode=%u rate=%u"
" shutdown_msg=%*s");
static void
spidev_transfer(struct spidev_s *spi, uint8_t receive_data
, uint8_t data_len, uint8_t *data)
{
if (spi->flags & SF_HAVE_PIN) {
spi_prepare(spi->spi_config);
gpio_out_write(spi->pin, 0);
spi_transfer(spi->spi_config, receive_data, data_len, data);
gpio_out_write(spi->pin, 1);
} else {
spi_prepare(spi->spi_config);
spi_transfer(spi->spi_config, receive_data, data_len, data);
}
}
void
command_spi_transfer(uint32_t *args)
{
uint8_t oid = args[0];
struct spidev_s *spi = oid_lookup(oid, command_config_spi);
uint8_t data_len = args[1];
uint8_t *data = (void*)(size_t)args[2];
spidev_transfer(spi, 1, data_len, data);
sendf("spi_transfer_response oid=%c response=%*s", oid, data_len, data);
}
DECL_COMMAND(command_spi_transfer, "spi_transfer oid=%c data=%*s");
void
command_spi_send(uint32_t *args)
{
uint8_t oid = args[0];
struct spidev_s *spi = oid_lookup(oid, command_config_spi);
uint8_t data_len = args[1];
uint8_t *data = (void*)(size_t)args[2];
spidev_transfer(spi, 0, data_len, data);
}
DECL_COMMAND(command_spi_send, "spi_send oid=%c data=%*s");
void
spidev_shutdown(void)
{
// Cancel any transmissions that may be in progress
uint8_t oid;
struct spidev_s *spi;
foreach_oid(oid, spi, command_config_spi) {
if (spi->flags & SF_HAVE_PIN)
gpio_out_write(spi->pin, 1);
}
// Send shutdown messages
foreach_oid(oid, spi, command_config_spi) {
if (spi->shutdown_msg_len)
spidev_transfer(spi, 0, spi->shutdown_msg_len, spi->shutdown_msg);
}
}
DECL_SHUTDOWN(spidev_shutdown);