22 #include <linux/spi/spidev.h> 26 #include <sys/types.h> 44 #define MHZ (1000U*1000U) 46 #define SPI_CS_KERNEL -1 49 SPIDesc(
const char *name_, uint16_t bus_, uint16_t subdev_, uint8_t mode_,
50 uint8_t bits_per_word_, int16_t cs_pin_, uint32_t lowspeed_,
69 #if CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_PXF || CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_ERLEBOARD 78 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_MINLURE 79 SPIDesc SPIDeviceManager::_device[] = {
82 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_NAVIO || CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_NAVIO2 83 SPIDesc SPIDeviceManager::_device[] = {
86 #if CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_NAVIO2 90 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_ERLEBRAIN2 || \ 91 CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_PXFMINI 92 SPIDesc SPIDeviceManager::_device[] = {
96 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BBBMINI 97 SPIDesc SPIDeviceManager::_device[] = {
102 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_POCKET 103 SPIDesc SPIDeviceManager::_device[] = {
107 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_OCPOC_ZYNQ 108 SPIDesc SPIDeviceManager::_device[] = {
113 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BH 114 SPIDesc SPIDeviceManager::_device[] = {
118 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_DARK 119 SPIDesc SPIDeviceManager::_device[] = {
122 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BEBOP || CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_DISCO 123 SPIDesc SPIDeviceManager::_device[] = {
126 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_AERO 127 SPIDesc SPIDeviceManager::_device[] = {
131 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_EDGE 132 SPIDesc SPIDeviceManager::_device[] = {
137 #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_RST_ZYNQ 138 SPIDesc SPIDeviceManager::_device[] = {
146 SPIDesc SPIDeviceManager::_device[] = {
149 #define LINUX_SPI_DEVICE_NUM_DEVICES 1 152 #ifndef LINUX_SPI_DEVICE_NUM_DEVICES 153 #define LINUX_SPI_DEVICE_NUM_DEVICES ARRAY_SIZE(SPIDeviceManager::_device) 168 void start_cb()
override;
169 void end_cb()
override;
171 int open(uint16_t bus_, uint16_t kernel_cs_);
179 int16_t last_mode = -1;
202 char path[
sizeof(
"/dev/spidevXXXXX.XXXXX")];
208 snprintf(path,
sizeof(path),
"/dev/spidev%u.%u", bus_, kernel_cs_);
209 fd =
::open(path, O_RDWR | O_CLOEXEC);
216 kernel_cs = kernel_cs_;
264 uint8_t *recv, uint32_t recv_len)
266 struct spi_ioc_transfer msgs[2] = { };
271 if (send && send_len != 0) {
272 msgs[nmsgs].tx_buf = (uint64_t) send;
273 msgs[nmsgs].rx_buf = 0;
274 msgs[nmsgs].len = send_len;
275 msgs[nmsgs].speed_hz =
_speed;
276 msgs[nmsgs].delay_usecs = 0;
278 msgs[nmsgs].cs_change = 0;
282 if (recv && recv_len != 0) {
283 msgs[nmsgs].tx_buf = 0;
284 msgs[nmsgs].rx_buf = (uint64_t) recv;
285 msgs[nmsgs].len = recv_len;
286 msgs[nmsgs].speed_hz =
_speed;
287 msgs[nmsgs].delay_usecs = 0;
289 msgs[nmsgs].cs_change = 0;
307 uint8_t current_mode;
308 if (ioctl(
_bus.
fd, SPI_IOC_RD_MODE, ¤t_mode) < 0) {
309 hal.
console->
printf(
"SPIDevice: error on getting mode fd=%d (%s)\n",
313 hal.
console->
printf(
"SPIDevice: bus mode conflict fd=%d mode=%u/%u\n",
321 hal.
console->
printf(
"SPIDevice: error on setting mode fd=%d (%s)\n",
329 r = ioctl(
_bus.
fd, SPI_IOC_MESSAGE(nmsgs), &msgs);
333 hal.
console->
printf(
"SPIDevice: error transferring data fd=%d (%s)\n",
344 struct spi_ioc_transfer msgs[1] = { };
348 if (!send || !recv || len == 0) {
352 msgs[0].tx_buf = (uint64_t) send;
353 msgs[0].rx_buf = (uint64_t) recv;
355 msgs[0].speed_hz =
_speed;
356 msgs[0].delay_usecs = 0;
358 msgs[0].cs_change = 0;
362 hal.
console->
printf(
"SPIDevice: error on setting mode fd=%d (%s)\n",
368 r = ioctl(
_bus.
fd, SPI_IOC_MESSAGE(1), &msgs);
372 hal.
console->
printf(
"SPIDevice: error transferring data fd=%d (%s)\n",
405 uint32_t period_usec, AP_HAL::Device::PeriodicCb cb)
437 for (uint8_t i = 0; i < _n_device_desc; i++) {
438 if (!strcmp(_device[i].name, name)) {
445 printf(
"SPI: Invalid device name: %s\n", name);
450 for (uint8_t i = 0, n = _buses.size(); i < n; i++) {
451 if (_buses[i]->bus == desc->
bus &&
452 _buses[i]->kernel_cs == desc->
subdev) {
453 return _create_device(*_buses[i], *desc);
459 if (!b || b->open(desc->
bus, desc->
subdev) < 0) {
463 auto dev = _create_device(*b, *desc);
468 _buses.push_back(b.leak());
474 return _n_device_desc;
479 return _device[idx].name;
496 if (b.
ref == 0 || --b.
ref > 0) {
500 for (
auto it = _buses.begin(); it != _buses.end(); it++) {
501 if ((*it)->bus == b.
bus && (*it)->kernel_cs == b.
kernel_cs) {
511 for (
auto it = _buses.begin(); it != _buses.end(); it++) {
513 (*it)->thread.stop();
516 for (
auto it = _buses.begin(); it != _buses.end(); it++) {
518 (*it)->thread.join();
int printf(const char *fmt,...)
int open(uint16_t bus_, uint16_t kernel_cs_)
static SPIDeviceManager * from(AP_HAL::SPIDeviceManager *spi_mgr)
AP_HAL::Semaphore * get_semaphore() override
int open(const char *pathname, int flags)
POSIX Open a file with integer mode flags.
static const uint8_t _n_device_desc
AP_HAL::UARTDriver * console
char * strerror(int errnum)
POSIX strerror() - convert POSIX errno to text with user message.
bool set_speed(AP_HAL::Device::Speed speed) override
void set_device_bus(uint8_t bus)
bool transfer_fullduplex(const uint8_t *send, uint8_t *recv, uint32_t len) override
bool adjust_timer(TimerPollable *p, uint32_t timeout_usec)
#define HAL_SEMAPHORE_BLOCK_FOREVER
AP_HAL::OwnPtr< AP_HAL::SPIDevice > _create_device(SPIBus &b, SPIDesc &device_desc) const
virtual void mode(uint8_t output)=0
bool adjust_periodic_callback(AP_HAL::Device::PeriodicHandle h, uint32_t period_usec) override
const char * get_device_name(uint8_t idx)
SPIDesc(const char *name_, uint16_t bus_, uint16_t subdev_, uint8_t mode_, uint8_t bits_per_word_, int16_t cs_pin_, uint32_t lowspeed_, uint32_t highspeed_)
bool transfer(const uint8_t *send, uint32_t send_len, uint8_t *recv, uint32_t recv_len) override
virtual void printf(const char *,...) FMT_PRINTF(2
#define LINUX_SPI_DEVICE_NUM_DEVICES
static AP_HAL::OwnPtr< AP_HAL::Device > dev
static const AP_HAL::HAL & hal
int close(int fileno)
POSIX Close a file with fileno handel.
virtual AP_HAL::DigitalSource * channel(uint16_t n)=0
AP_HAL::Device::PeriodicHandle register_periodic_callback(uint32_t period_usec, AP_HAL::Device::PeriodicCb) override
AP_HAL::SPIDeviceManager * spi
AP_HAL::DigitalSource * _cs
AP_HAL::OwnPtr< AP_HAL::SPIDevice > get_device(const char *name)
#define AP_LINUX_SENSORS_SCHED_PRIO
TimerPollable * add_timer(TimerPollable::PeriodicCb cb, TimerPollable::WrapperCb *wrapper, uint32_t timeout_usec)
#define AP_LINUX_SENSORS_STACK_SIZE
bool set_stack_size(size_t stack_size)
void _unregister(SPIBus &b)
int errno
Note: fdevopen assigns stdin,stdout,stderr.
int snprintf(char *str, size_t size, const char *fmt,...)
bool start(const char *name, int policy, int prio)
void panic(const char *errormsg,...) FMT_PRINTF(1
#define AP_LINUX_SENSORS_SCHED_POLICY
void set_device_address(uint8_t address)
virtual void write(uint8_t value)=0