libuav original
Dependents: UAVCAN UAVCAN_Subscriber
can_acceptance_filter_configurator.hpp
00001 /* 00002 * Copyright (C) 2015 Pavel Kirienko <pavel.kirienko@gmail.com>, 00003 * Ilia Sheremet <illia.sheremet@gmail.com> 00004 */ 00005 00006 #ifndef UAVCAN_TRANSPORT_CAN_ACCEPTANCE_FILTER_CONFIGURATOR_HPP_INCLUDED 00007 #define UAVCAN_TRANSPORT_CAN_ACCEPTANCE_FILTER_CONFIGURATOR_HPP_INCLUDED 00008 00009 #include <cassert> 00010 #include <uavcan/data_type.hpp> 00011 #include <uavcan/error.hpp> 00012 #include <uavcan/transport/dispatcher.hpp> 00013 #include <uavcan/node/abstract_node.hpp> 00014 #include <uavcan/build_config.hpp> 00015 #include <uavcan/util/multiset.hpp> 00016 00017 namespace uavcan 00018 { 00019 /** 00020 * This class configures hardware acceptance filters (if this feature is present on the particular CAN driver) to 00021 * preclude reception of irrelevant CAN frames on the hardware level. 00022 * 00023 * Configuration starts by creating an object of class @ref CanAcceptanceFilterConfigurator on the stack. 00024 * By means of computeConfiguration() method the class determines the number of available HW filters and the number 00025 * of listeners. In case if custom configuration required, it is possible to add it through addFilterConfig(). 00026 * Subsequently obtained configurations are then loaded into the CAN driver by calling the applyConfiguration() method. 00027 * If the cumulative number of configurations obtained by computeConfiguration() and addFilterConfig() is higher than 00028 * the number of available HW filters, configurations will be merged automatically in the most efficient way. 00029 * 00030 * Note that if the application adds additional server or subscriber objects after the filters have been configured, 00031 * the configuration procedure will have to be performed again. 00032 * 00033 * The maximum number of CAN acceptance filters is predefined in uavcan/build_config.hpp through a constant 00034 * @ref MaxCanAcceptanceFilters. The algorithm doesn't allow to have higher number of HW filters configurations than 00035 * defined by MaxCanAcceptanceFilters. You can change this value according to the number specified in your CAN driver 00036 * datasheet. 00037 */ 00038 class CanAcceptanceFilterConfigurator 00039 { 00040 public: 00041 /** 00042 * These arguments defines whether acceptance filter configuration has anonymous messages or not 00043 */ 00044 enum AnonymousMessages 00045 { 00046 AcceptAnonymousMessages, 00047 IgnoreAnonymousMessages 00048 }; 00049 00050 private: 00051 /** 00052 * Below constants based on UAVCAN transport layer specification. Masks and ID's depends on message 00053 * TypeID, TransferID (RequestNotResponse - for service types, ServiceNotMessage - for all types of messages). 00054 * For more details refer to uavcan.org/CAN_bus_transport_layer_specification. 00055 * For clarity let's represent "i" as Data Type ID and "d" as Destination Node Id 00056 * DefaultFilterMsgMask = 00000 11111111 11111111 10000000 00057 * DefaultFilterMsgID = 00000 iiiiiiii iiiiiiii 00000000, no need to explicitly define, since MsgID initialized 00058 * as 0. 00059 * DefaultFilterServiceMask = 00000 00000000 01111111 10000000 00060 * DefaultFilterServiceID = 00000 00000000 0ddddddd 10000000, all Service Response Frames are accepted by 00061 * HW filters. 00062 * DefaultAnonMsgMask = 00000 00000000 00000000 11111111 00063 * DefaultAnonMsgID = 00000 00000000 00000000 00000000, by default the config is added to accept all anonymous 00064 * frames. In case there are no anonymous messages, invoke computeConfiguration(IgnoreAnonymousMessages). 00065 */ 00066 static const unsigned DefaultFilterMsgMask = 0xFFFF80; 00067 static const unsigned DefaultFilterServiceMask = 0x7F80; 00068 static const unsigned DefaultFilterServiceID = 0x80; 00069 static const unsigned DefaultAnonMsgMask = 0xFF; 00070 static const unsigned DefaultAnonMsgID = 0x0; 00071 00072 typedef uavcan::Multiset<CanFilterConfig> MultisetConfigContainer; 00073 00074 static CanFilterConfig mergeFilters(CanFilterConfig& a_, CanFilterConfig& b_); 00075 static uint8_t countBits(uint32_t n_); 00076 uint16_t getNumFilters() const; 00077 00078 /** 00079 * Fills the multiset_configs_ to proceed it with mergeConfigurations() 00080 */ 00081 int16_t loadInputConfiguration(AnonymousMessages load_mode); 00082 00083 /** 00084 * This method merges several listeners's filter configurations by predetermined algorithm 00085 * if number of available hardware acceptance filters less than number of listeners 00086 */ 00087 int16_t mergeConfigurations(); 00088 00089 INode& node_; //< Node reference is needed for access to ICanDriver and Dispatcher 00090 MultisetConfigContainer multiset_configs_; 00091 uint16_t filters_number_; 00092 00093 public: 00094 /** 00095 * @param node Libuavcan node whose subscribers/servers/etc will be used to configure the filters. 00096 * 00097 * @param filters_number Allows to override the maximum number of hardware filters to use. 00098 * If set to zero (which is default), the class will obtain the number of available 00099 * filters from the CAN driver via @ref ICanIface::getNumFilters(). 00100 */ 00101 explicit CanAcceptanceFilterConfigurator (INode& node, uint16_t filters_number = 0) 00102 : node_(node) 00103 , multiset_configs_(node.getAllocator()) 00104 , filters_number_(filters_number) 00105 { } 00106 00107 /** 00108 * This method invokes loadInputConfiguration() and mergeConfigurations() consequently 00109 * in order to comute optimal filter configurations for the current hardware. 00110 * 00111 * It can only be invoked when all of the subscriber and server objects are initialized. 00112 * If new subscriber or server objects are added later, the filters will have to be reconfigured again. 00113 * 00114 * @param mode Either: AcceptAnonymousMessages - the filters will accept all anonymous messages (this is default) 00115 * IgnoreAnonymousMessages - anonymous messages will be ignored 00116 * @return 0 = success, negative for error. 00117 */ 00118 int computeConfiguration(AnonymousMessages mode = AcceptAnonymousMessages); 00119 00120 /** 00121 * Add an additional filter configuration. 00122 * This method must not be invoked after @ref computeConfiguration(). 00123 * @return 0 = success, negative for error. 00124 */ 00125 int addFilterConfig(const CanFilterConfig& config); 00126 00127 /** 00128 * This method loads the configuration computed with mergeConfigurations() or explicitly added by addFilterConfig() 00129 * to the CAN driver. Must be called after computeConfiguration() and addFilterConfig(). 00130 * @return 0 = success, negative for error. 00131 */ 00132 int applyConfiguration(); 00133 00134 /** 00135 * Returns the configuration computed with mergeConfigurations() or added by addFilterConfig(). 00136 * If mergeConfigurations() or addFilterConfig() have not been called yet, an empty configuration will be returned. 00137 */ 00138 const MultisetConfigContainer & getConfiguration() const 00139 { 00140 return multiset_configs_; 00141 } 00142 }; 00143 00144 /** 00145 * This function is a shortcut for @ref CanAcceptanceFilterConfigurator. 00146 * It allows to compute filter configuration and then apply it in just one step. 00147 * It implements only the most common use case; if you have special requirements, 00148 * use @ref CanAcceptanceFilterConfigurator directly. 00149 * 00150 * @param node Refer to @ref CanAcceptanceFilterConfigurator constructor for explanation. 00151 * @param mode Refer to @ref CanAcceptanceFilterConfigurator::computeConfiguration() for explanation. 00152 * @return non-negative on success, negative error code on error. 00153 */ 00154 static inline int configureCanAcceptanceFilters(INode& node, 00155 CanAcceptanceFilterConfigurator::AnonymousMessages mode 00156 = CanAcceptanceFilterConfigurator::AcceptAnonymousMessages) 00157 { 00158 CanAcceptanceFilterConfigurator cfger(node); 00159 00160 const int compute_res = cfger.computeConfiguration(mode); 00161 if (compute_res < 0) 00162 { 00163 return compute_res; 00164 } 00165 00166 return cfger.applyConfiguration(); 00167 } 00168 00169 } 00170 00171 #endif
Generated on Tue Jul 12 2022 17:17:30 by 1.7.2