spi.h
6.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/****************************************************************************
*
* Copyright (c) 2020 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#pragma once
#include <stdint.h>
#include <board_config.h>
/*
* Helper macros to handle device ID's. They are used to match drivers against SPI buses and chip-select signals.
* They match with corresponding definitions in NuttX.
* 'type' is typically PX4_SPI_DEVICE_ID for PX4 drivers, and 'index' is used for the driver (DRV_*) or chip-select index.
*/
#define PX4_SPIDEV_ID(type, index) ((((type) & 0xffff) << 16) | ((index) & 0xffff))
#define PX4_SPI_DEVICE_ID (1 << 12)
#define PX4_SPI_DEV_ID(devid) ((devid) & 0xffff)
#define PX4_SPIDEVID_TYPE(devid) (((uint32_t)(devid) >> 16) & 0xffff)
typedef uint32_t spi_drdy_gpio_t;
#define SPI_BUS_MAX_DEVICES 6
struct px4_spi_bus_device_t {
uint32_t cs_gpio; ///< chip-select GPIO (0 if this device is not used)
spi_drdy_gpio_t drdy_gpio; ///< data ready GPIO (0 if not set)
uint32_t devid; ///< SPIDEV_ID(type,index). For PX4 devices on NuttX: index is the device type, and for external buses the CS index
uint16_t devtype_driver; ///< driver device type, e.g. DRV_IMU_DEVTYPE_ICM20689 (on NuttX: PX4_SPI_DEV_ID(devid) == devtype_driver)
};
struct px4_spi_bus_devices_t {
px4_spi_bus_device_t devices[SPI_BUS_MAX_DEVICES];
};
struct px4_spi_bus_t {
px4_spi_bus_device_t devices[SPI_BUS_MAX_DEVICES];
int bus{-1}; ///< physical bus number (1, ...) (-1 means this is unused)
uint32_t power_enable_gpio{0}; ///< GPIO (if non-zero) to control the power of the attached devices on this bus (0 means power is off)
bool is_external; ///< static external configuration. Use px4_spi_bus_external() to check if a bus is really external
bool requires_locking; ///< whether the bus should be locked during transfers (true if NuttX drivers access the bus)
};
struct px4_spi_bus_all_hw_t {
px4_spi_bus_t buses[SPI_BUS_MAX_BUS_ITEMS];
int board_hw_version_revision{-1}; ///< 0=default, >0 for a specific revision (see board_get_hw_version & board_get_hw_revision), -1=unused
};
#if BOARD_NUM_SPI_CFG_HW_VERSIONS > 1
/**
* initialze px4_spi_buses from px4_spi_buses_all_hw and the hardware version.
* Call this on early boot before anything else accesses px4_spi_buses (e.g. from stm32_spiinitialize).
*/
__EXPORT void px4_set_spi_buses_from_hw_version();
__EXPORT extern const px4_spi_bus_all_hw_t
px4_spi_buses_all_hw[BOARD_NUM_SPI_CFG_HW_VERSIONS]; ///< board-specific SPI bus configuration all hw versions
__EXPORT extern const px4_spi_bus_t *px4_spi_buses; ///< board-specific SPI bus configuration for current board revision
#else
static inline void px4_set_spi_buses_from_hw_version() {}
__EXPORT extern const px4_spi_bus_t px4_spi_buses[SPI_BUS_MAX_BUS_ITEMS]; ///< board-specific SPI bus configuration
#endif
/**
* Find a SPI bus given a device ID. Note: only internal buses are checked.
* @return the bus or -1
*/
__EXPORT int px4_find_spi_bus(uint32_t devid);
/**
* Check if a bus requires locking during a SPI transfer (because it is potentially accessed by different threads)
*/
__EXPORT bool px4_spi_bus_requires_locking(int bus);
/**
* runtime-check if a board has a specific bus as external.
* This can be overridden by a board to add run-time checks.
*/
__EXPORT bool px4_spi_bus_external(const px4_spi_bus_t &bus);
/**
* runtime-check if a board has a specific bus as external.
*/
static inline bool px4_spi_bus_external(int bus)
{
for (int i = 0; i < SPI_BUS_MAX_BUS_ITEMS; ++i) {
if (px4_spi_buses[i].bus == bus) {
return px4_spi_bus_external(px4_spi_buses[i]);
}
}
return true;
}
/**
* @class SPIBusIterator
* Iterate over configured SPI buses by the board
*/
class SPIBusIterator
{
public:
enum class FilterType {
InternalBus, ///< specific or all internal buses
ExternalBus, ///< specific external bus + CS index
};
/**
* Constructor
* Note: only for devices of type PX4_SPI_DEVICE_ID
* @param filter
* @param devid_driver_index DRV_* or chip-select index starting from 1
* @param bus starts with 1 (-1=all, but only for internal). Numbering for internal is arch-specific, for external
* it is the n-th external bus.
*/
SPIBusIterator(FilterType filter, uint16_t devid_driver_index, int bus = -1)
: _filter(filter), _devid_driver_index(devid_driver_index),
_bus(filter == FilterType::ExternalBus && bus == -1 ? 1 : bus) {}
bool next();
const px4_spi_bus_t &bus() const { return px4_spi_buses[_index]; }
spi_drdy_gpio_t DRDYGPIO() const { return px4_spi_buses[_index].devices[_bus_device_index].drdy_gpio; }
uint32_t devid() const { return px4_spi_buses[_index].devices[_bus_device_index].devid; }
int externalBusIndex() const { return _external_bus_counter; }
bool external() const { return px4_spi_bus_external(bus()); }
private:
const FilterType _filter;
const uint16_t _devid_driver_index;
const int _bus;
int _index{-1};
int _external_bus_counter{0};
int _bus_device_index{0};
};