PX4模块设计之四十一:I2C/SPI Bus Instance基础知识
生活随笔
收集整理的這篇文章主要介紹了
PX4模块设计之四十一:I2C/SPI Bus Instance基础知识
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
PX4模塊設計之四十一:I2C/SPI Bus Instance基礎知識
- 1. 基礎知識
- 2. 基礎類和定義
- 2.1 ListNode類
- 2.2 List類
- 2.3 BusCLIArguments類
- 2.4 BusInstanceIterator類
- 2.5 I2CSPIInstance類
- 2.6 I2CSPIDriverBase類
- 2.7 I2CSPIDriver類
- 2.8 I2C/SPI總線選項
- 3. 總結
- 4. 參考資料
1. 基礎知識
2. 基礎類和定義
2.1 ListNode類
主要功能描述:
注:這個類類似于C語言單向鏈表的一個節點結構聲明。
class ListNode
template<class T> class ListNode { public:void setSibling(T sibling) { _list_node_sibling = sibling; }const T getSibling() const { return _list_node_sibling; }protected:T _list_node_sibling{nullptr};};2.2 List類
主要功能描述:
class List
template<class T> class List { public:void add(T newNode){if (_head == nullptr) {// list is empty, add as head_head = newNode;return;} else {// find last node and add to endT node = _head;while (node != nullptr) {if (node->getSibling() == nullptr) {// found last node, now add newNodenode->setSibling(newNode);return;}node = node->getSibling();}}}bool remove(T removeNode){if (removeNode == nullptr) {return false;}// base caseif (removeNode == _head) {if (_head != nullptr) {_head = _head->getSibling();}removeNode->setSibling(nullptr);return true;}for (T node = getHead(); node != nullptr; node = node->getSibling()) {// is sibling the node to remove?if (node->getSibling() == removeNode) {// replace siblingif (node->getSibling() != nullptr) {node->setSibling(node->getSibling()->getSibling());} else {node->setSibling(nullptr);}removeNode->setSibling(nullptr);return true;}}return false;}struct Iterator {T node;explicit Iterator(T v) : node(v) {}operator T() const { return node; }operator T &() { return node; }const T &operator* () const { return node; }Iterator &operator++ (){if (node) {node = node->getSibling();}return *this;}};Iterator begin() { return Iterator(getHead()); }Iterator end() { return Iterator(nullptr); }const T getHead() const { return _head; }bool empty() const { return getHead() == nullptr; }size_t size() const{size_t sz = 0;for (auto node = getHead(); node != nullptr; node = node->getSibling()) {sz++;}return sz;}void deleteNode(T node){if (remove(node)) {// only delete if node was successfully removeddelete node;}}void clear(){auto node = getHead();while (node != nullptr) {auto next = node->getSibling();delete node;node = next;}_head = nullptr;}protected:T _head{nullptr}; };2.3 BusCLIArguments類
命令行參數配置總線設備。
主要功能描述:
I2C Slave地址(i2c_address)
I2C默認頻率(default_i2c_frequency)
SPI芯片選擇(chipselect)
SPI工作模式(spi_mode)
SPI默認頻率(default_spi_frequency)
class BusCLIArguments
class BusCLIArguments { public:BusCLIArguments(bool i2c_support, bool spi_support) #if defined(CONFIG_I2C) || defined(CONFIG_SPI): #endif // CONFIG_I2C || CONFIG_SPI #if defined(CONFIG_I2C)_i2c_support(i2c_support) #endif // CONFIG_I2C #if defined(CONFIG_I2C) && defined(CONFIG_SPI), #endif // CONFIG_I2C && CONFIG_SPI #if defined(CONFIG_SPI)_spi_support(spi_support) #endif // CONFIG_SPI{}/*** Parse CLI arguments (for drivers that don't need any custom arguments, otherwise getopt() should be used)* @return command (e.g. "start") or nullptr on error or unknown argument*/const char *parseDefaultArguments(int argc, char *argv[]);/*** Like px4_getopt(), but adds and handles i2c/spi driver-specific arguments*/int getOpt(int argc, char *argv[], const char *options);/*** returns the current optional argument (for options like 'T:'), or the command (e.g. "start")* @return nullptr or argument/command*/const char *optArg() const { return _optarg; }I2CSPIBusOption bus_option{I2CSPIBusOption::All};int requested_bus{-1};int bus_frequency{0}; #if defined(CONFIG_SPI)int chipselect {-1};spi_mode_e spi_mode{SPIDEV_MODE3}; #endif // CONFIG_SPI #if defined(CONFIG_I2C)uint8_t i2c_address {0}; ///< I2C address (a driver must set the default address) #endif // CONFIG_I2Cbool quiet_start {false}; ///< do not print a message when startup failsbool keep_running{false}; ///< keep driver running even if no device is detected on startupRotation rotation{ROTATION_NONE}; ///< sensor rotation (MAV_SENSOR_ROTATION_* or distance_sensor_s::ROTATION_*)int custom1{0}; ///< driver-specific custom argumentint custom2{0}; ///< driver-specific custom argumentvoid *custom_data{nullptr}; ///< driver-specific custom argument// driver defaults, if not specified via CLI #if defined(CONFIG_SPI)int default_spi_frequency {-1}; ///< default spi bus frequency (driver needs to set this) [Hz] #endif // CONFIG_SPI #if defined(CONFIG_I2C)int default_i2c_frequency {-1}; ///< default i2c bus frequency (driver needs to set this) [Hz] #endif // CONFIG_I2Cbool support_keep_running{false}; ///< true if keep_running (see above) is supportedprivate:bool validateConfiguration();char _options[32] {};int _optind{1};const char *_optarg{nullptr}; #if defined(CONFIG_I2C)const bool _i2c_support; #endif // CONFIG_I2C #if defined(CONFIG_SPI)const bool _spi_support; #endif // CONFIG_SPI };2.4 BusInstanceIterator類
使用給定的過濾器選項迭代運行實例和/或配置的I2C/SPI總線。
主要功能描述:
class BusInstanceIterator
class BusInstanceIterator { public:BusInstanceIterator(const char *module_name, const BusCLIArguments &cli_arguments, uint16_t devid_driver_index);~BusInstanceIterator();I2CSPIBusOption configuredBusOption() const { return _bus_option; }int runningInstancesCount() const;bool next();I2CSPIInstance *instance() const;void removeInstance();board_bus_types busType() const;int bus() const;uint32_t devid() const;#if defined(CONFIG_SPI)spi_drdy_gpio_t DRDYGPIO() const; #endif // CONFIG_SPIbool external() const;int externalBusIndex() const;int busDeviceIndex() const;void addInstance(I2CSPIInstance *instance);#if defined(CONFIG_I2C)static I2CBusIterator::FilterType i2cFilter(I2CSPIBusOption bus_option); #endif // CONFIG_I2C #if defined(CONFIG_SPI)static SPIBusIterator::FilterType spiFilter(I2CSPIBusOption bus_option); #endif // CONFIG_SPIconst char *moduleName() const { return _module_name; }uint16_t devidDriverIndex() const { return _devid_driver_index; }private:const char *_module_name;const I2CSPIBusOption _bus_option;const uint16_t _devid_driver_index; #if defined(CONFIG_I2C)const uint8_t _i2c_address; #endif // CONFIG_I2C #if defined(CONFIG_SPI)SPIBusIterator _spi_bus_iterator; #endif // CONFIG_SPI #if defined(CONFIG_I2C)I2CBusIterator _i2c_bus_iterator; #endif // CONFIG_I2CList<I2CSPIInstance *>::Iterator _current_instance; };2.5 I2CSPIInstance類
I2CSPI實例類對象定義。
主要功能描述:
class I2CSPIInstance
class I2CSPIInstance : public ListNode<I2CSPIInstance *> { public:virtual ~I2CSPIInstance() = default; #if defined(CONFIG_I2C)virtual int8_t get_i2c_address() {return _i2c_address;} #endif // CONFIG_I2C private:I2CSPIInstance(const I2CSPIDriverConfig &config): _module_name(config.module_name), _bus_option(config.bus_option), _bus(config.bus),_devid_driver_index(config.devid_driver_index), _bus_device_index(config.bus_device_index) #if defined(CONFIG_I2C), _i2c_address(config.i2c_address) #endif // CONFIG_I2C{}friend class BusInstanceIterator;friend class I2CSPIDriverBase;const char *_module_name;const I2CSPIBusOption _bus_option;const int _bus;const uint16_t _devid_driver_index;const int8_t _bus_device_index; #if defined(CONFIG_I2C)const int8_t _i2c_address; ///< I2C address (optional) #endif // CONFIG_I2C };2.6 I2CSPIDriverBase類
I2CSPI驅動基礎功能類對象定義。
主要功能描述:
class I2CSPIDriverBase
class I2CSPIDriverBase : public px4::ScheduledWorkItem, public I2CSPIInstance { public:I2CSPIDriverBase(const I2CSPIDriverConfig &config): ScheduledWorkItem(config.module_name, config.wq_config),I2CSPIInstance(config) {}static int module_stop(BusInstanceIterator &iterator);static int module_status(BusInstanceIterator &iterator);static int module_custom_method(const BusCLIArguments &cli, BusInstanceIterator &iterator,bool run_on_work_queue = true);using instantiate_method = I2CSPIDriverBase * (*)(const I2CSPIDriverConfig &config, int runtime_instance); protected:virtual ~I2CSPIDriverBase() = default;virtual void print_status();virtual void custom_method(const BusCLIArguments &cli) {}/*** Exiting the module. A driver can override this, for example to unregister interrupt callbacks.* This will be called from the work queue.* A module overriding this, needs to call I2CSPIDriverBase::exit_and_cleanup() as the very last statement.*/virtual void exit_and_cleanup() { ScheduleClear(); _task_exited.store(true); }bool should_exit() const { return _task_should_exit.load(); }static int module_start(const BusCLIArguments &cli, BusInstanceIterator &iterator, void(*print_usage)(),instantiate_method instantiate);private:static void custom_method_trampoline(void *argument);void request_stop_and_wait();px4::atomic_bool _task_should_exit{false};px4::atomic_bool _task_exited{false}; };2.7 I2CSPIDriver類
I2CSPI驅動類對象定義。
主要功能描述:
class I2CSPIDriver
template<class T> class I2CSPIDriver : public I2CSPIDriverBase { public:static int module_start(const BusCLIArguments &cli, BusInstanceIterator &iterator){return I2CSPIDriverBase::module_start(cli, iterator, &T::print_usage, InstantiateHelper<T>::m);}protected:I2CSPIDriver(const I2CSPIDriverConfig &config): I2CSPIDriverBase(config) {}virtual ~I2CSPIDriver() = default;// *INDENT-OFF* remove once there's astyle >3.1 in CIvoid Run() final{static_cast<T *>(this)->RunImpl();if (should_exit()) {exit_and_cleanup();}}// *INDENT-ON* private:// SFINAE to use R::instantiate if it exists, and R::instantiate_default otherwisetemplate <typename R>class InstantiateHelper{template <typename C>static constexpr I2CSPIDriverBase::instantiate_method get(decltype(&C::instantiate)) { return &C::instantiate; }template <typename C>static constexpr I2CSPIDriverBase::instantiate_method get(...) { return &C::instantiate_default; }public:static constexpr I2CSPIDriverBase::instantiate_method m = get<R>(0);};static I2CSPIDriverBase *instantiate_default(const I2CSPIDriverConfig &config, int runtime_instance){T *instance = new T(config);if (!instance) {PX4_ERR("alloc failed");return nullptr;}if (OK != instance->init()) {delete instance;return nullptr;}return instance;} };2.8 I2C/SPI總線選項
PX4系統的I2C/SPI總線分為I2C內部和外部,以及SPI內部和外部四大類。
enum class I2CSPIBusOption : uint8_t {All = 0, ///< select all runnning instances #if defined(CONFIG_I2C)I2CInternal,I2CExternal, #endif // CONFIG_I2C #if defined(CONFIG_SPI)SPIInternal,SPIExternal, #endif // CONFIG_SPI };3. 總結
注:暫時先整理這些內容,后續隨著代碼閱讀的增加,再補充完善。
4. 參考資料
【1】PX4開源軟件框架簡明簡介
【2】PX4模塊設計之十二:High Resolution Timer設計
【3】PX4模塊設計之十三:WorkQueue設計
總結
以上是生活随笔為你收集整理的PX4模块设计之四十一:I2C/SPI Bus Instance基础知识的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大叔学编程,学的还是易语言
- 下一篇: sysbench简单使用