AP_BoardConfig_CAN.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /*
  2. This program is free software: you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation, either version 3 of the License, or
  5. (at your option) any later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program. If not, see <http://www.gnu.org/licenses/>.
  12. */
  13. /*
  14. * AP_BoardConfig_CAN - board specific configuration for CAN interface
  15. */
  16. #include <AP_HAL/AP_HAL.h>
  17. #include <AP_Common/AP_Common.h>
  18. #include "AP_BoardConfig.h"
  19. #include "AP_BoardConfig_CAN.h"
  20. #if HAL_WITH_UAVCAN
  21. #if CONFIG_HAL_BOARD == HAL_BOARD_LINUX
  22. #include <AP_HAL_Linux/CAN.h>
  23. #elif CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS
  24. #include <AP_HAL_ChibiOS/CAN.h>
  25. #include <AP_HAL_ChibiOS/CANSerialRouter.h>
  26. #endif
  27. #include <AP_Vehicle/AP_Vehicle.h>
  28. #include <AP_UAVCAN/AP_UAVCAN_SLCAN.h>
  29. #include <AP_UAVCAN/AP_UAVCAN.h>
  30. #include <AP_KDECAN/AP_KDECAN.h>
  31. #include <AP_ToshibaCAN/AP_ToshibaCAN.h>
  32. #include <AP_SerialManager/AP_SerialManager.h>
  33. #include "../../ArduSub/UserCan.h"
  34. extern const AP_HAL::HAL& hal;
  35. // table of user settable parameters
  36. const AP_Param::GroupInfo AP_BoardConfig_CAN::var_info[] = {
  37. #if MAX_NUMBER_OF_CAN_INTERFACES > 0
  38. // @Group: P1_
  39. // @Path: ../AP_BoardConfig/canbus_interface.cpp
  40. AP_SUBGROUPINFO(_interfaces[0], "P1_", 1, AP_BoardConfig_CAN, AP_BoardConfig_CAN::Interface),
  41. #endif
  42. #if MAX_NUMBER_OF_CAN_INTERFACES > 1
  43. // @Group: P2_
  44. // @Path: ../AP_BoardConfig/canbus_interface.cpp
  45. AP_SUBGROUPINFO(_interfaces[1], "P2_", 2, AP_BoardConfig_CAN, AP_BoardConfig_CAN::Interface),
  46. #endif
  47. #if MAX_NUMBER_OF_CAN_INTERFACES > 2
  48. // @Group: P3_
  49. // @Path: ../AP_BoardConfig/canbus_interface.cpp
  50. AP_SUBGROUPINFO(_interfaces[2], "P3_", 3, AP_BoardConfig_CAN, AP_BoardConfig_CAN::Interface),
  51. #endif
  52. #if MAX_NUMBER_OF_CAN_DRIVERS > 0
  53. // @Group: D1_
  54. // @Path: ../AP_BoardConfig/canbus_driver.cpp
  55. AP_SUBGROUPINFO(_drivers[0], "D1_", 4, AP_BoardConfig_CAN, AP_BoardConfig_CAN::Driver),
  56. #endif
  57. #if MAX_NUMBER_OF_CAN_DRIVERS > 1
  58. // @Group: D2_
  59. // @Path: ../AP_BoardConfig/canbus_driver.cpp
  60. AP_SUBGROUPINFO(_drivers[1], "D2_", 5, AP_BoardConfig_CAN, AP_BoardConfig_CAN::Driver),
  61. #endif
  62. #if MAX_NUMBER_OF_CAN_DRIVERS > 2
  63. // @Group: D3_
  64. // @Path: ../AP_BoardConfig/canbus_driver.cpp
  65. AP_SUBGROUPINFO(_drivers[2], "D3_", 6, AP_BoardConfig_CAN, AP_BoardConfig_CAN::Driver),
  66. #endif
  67. #if AP_UAVCAN_SLCAN_ENABLED
  68. // @Group: SLCAN_
  69. // @Path: ../AP_BoardConfig/canbus_slcan.cpp
  70. AP_SUBGROUPINFO(_slcan, "SLCAN_", 7, AP_BoardConfig_CAN, AP_BoardConfig_CAN::SLCAN_Interface),
  71. #endif
  72. AP_GROUPEND
  73. };
  74. AP_BoardConfig_CAN *AP_BoardConfig_CAN::_singleton;
  75. AP_BoardConfig_CAN::AP_BoardConfig_CAN()
  76. {
  77. AP_Param::setup_object_defaults(this, var_info);
  78. #if CONFIG_HAL_BOARD == HAL_BOARD_SITL
  79. if (_singleton != nullptr) {
  80. AP_HAL::panic("AP_BoardConfig_CAN must be singleton");
  81. }
  82. #endif // CONFIG_HAL_BOARD == HAL_BOARD_SITL
  83. _singleton = this;
  84. }
  85. void AP_BoardConfig_CAN::init()
  86. {
  87. // Create all drivers that we need
  88. bool initret = true;
  89. #if AP_UAVCAN_SLCAN_ENABLED
  90. reset_slcan_serial();
  91. #endif
  92. for (uint8_t i = 0; i < MAX_NUMBER_OF_CAN_INTERFACES; i++) {
  93. // Check the driver number assigned to this physical interface
  94. uint8_t drv_num = _interfaces[i]._driver_number_cache = _interfaces[i]._driver_number;
  95. if (drv_num != 0 && drv_num <= MAX_NUMBER_OF_CAN_DRIVERS) {
  96. if (hal.can_mgr[drv_num - 1] == nullptr) {
  97. // CAN Manager is the driver
  98. // So if this driver was not created before for other physical interface - do it
  99. #if CONFIG_HAL_BOARD == HAL_BOARD_LINUX
  100. const_cast <AP_HAL::HAL&> (hal).can_mgr[drv_num - 1] = new Linux::CANManager;
  101. #elif CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS
  102. const_cast <AP_HAL::HAL&> (hal).can_mgr[drv_num - 1] = new ChibiOS::CANManager;
  103. #endif
  104. }
  105. // For this now existing driver (manager), start the physical interface
  106. if (hal.can_mgr[drv_num - 1] != nullptr) {
  107. initret = initret && hal.can_mgr[drv_num - 1]->begin(_interfaces[i]._bitrate, i);
  108. #if AP_UAVCAN_SLCAN_ENABLED
  109. if (_slcan._can_port == (i+1) && hal.can_mgr[drv_num - 1] != nullptr ) {
  110. ChibiOS_CAN::CanDriver* drv = (ChibiOS_CAN::CanDriver*)hal.can_mgr[drv_num - 1]->get_driver();
  111. ChibiOS_CAN::CanIface::slcan_router().init(drv->getIface(i), drv->getUpdateEvent());
  112. }
  113. #endif
  114. } else {
  115. printf("Failed to initialize can interface %d\n\r", i + 1);
  116. }
  117. }
  118. }
  119. if (initret) {
  120. for (uint8_t i = 0; i < MAX_NUMBER_OF_CAN_DRIVERS; i++) {
  121. Protocol_Type prot_type = _drivers[i]._protocol_type_cache = (Protocol_Type) _drivers[i]._protocol_type.get();
  122. if (hal.can_mgr[i] == nullptr) {
  123. continue;
  124. }
  125. _num_drivers = i + 1;
  126. hal.can_mgr[i]->initialized(true);
  127. printf("can_mgr %d initialized well\n\r", i + 1);
  128. if (prot_type == Protocol_Type_UAVCAN) {
  129. _drivers[i]._driver = _drivers[i]._uavcan = new AP_UAVCAN;
  130. if (_drivers[i]._driver == nullptr) {
  131. AP_HAL::panic("Failed to allocate uavcan %d\n\r", i + 1);
  132. continue;
  133. }
  134. AP_Param::load_object_from_eeprom(_drivers[i]._uavcan, AP_UAVCAN::var_info);
  135. } else if (prot_type == Protocol_Type_KDECAN) {
  136. // To be replaced with macro saying if KDECAN library is included
  137. #if APM_BUILD_TYPE(APM_BUILD_ArduCopter) || APM_BUILD_TYPE(APM_BUILD_ArduPlane) || APM_BUILD_TYPE(APM_BUILD_ArduSub)
  138. _drivers[i]._driver = _drivers[i]._kdecan = new AP_KDECAN;
  139. if (_drivers[i]._driver == nullptr) {
  140. AP_HAL::panic("Failed to allocate KDECAN %d\n\r", i + 1);
  141. continue;
  142. }
  143. AP_Param::load_object_from_eeprom(_drivers[i]._kdecan, AP_KDECAN::var_info);
  144. #endif
  145. } else if (prot_type == Protocol_Type_ToshibaCAN) {
  146. _drivers[i]._driver = _drivers[i]._tcan = new AP_ToshibaCAN;
  147. if (_drivers[i]._driver == nullptr) {
  148. AP_BoardConfig::sensor_config_error("ToshibaCAN init failed");
  149. continue;
  150. }
  151. } else if (prot_type == Protocol_Type_selfCAN) {
  152. _drivers[i]._driver = _drivers[i]._tcan = new UserCAN;
  153. if (_drivers[i]._driver == nullptr) {
  154. AP_BoardConfig::sensor_config_error("UserCAN init failed");
  155. continue;
  156. }
  157. } else {
  158. continue;
  159. }
  160. #if AP_UAVCAN_SLCAN_ENABLED
  161. if (_slcan._can_port == 0) {
  162. _drivers[i]._driver->init(i, true);
  163. } else {
  164. _drivers[i]._driver->init(i, false);
  165. }
  166. #endif
  167. }
  168. }
  169. }
  170. #if AP_UAVCAN_SLCAN_ENABLED
  171. AP_HAL::UARTDriver *AP_BoardConfig_CAN::get_slcan_serial()
  172. {
  173. if (_slcan._ser_port != -1) {
  174. return AP::serialmanager().get_serial_by_id(_slcan._ser_port);
  175. }
  176. AP_HAL::UARTDriver *ser_port = AP::serialmanager().find_serial(AP_SerialManager::SerialProtocol_SLCAN, 0);
  177. if (ser_port != nullptr) {
  178. if (ser_port->is_initialized()) {
  179. return ser_port;
  180. }
  181. }
  182. return nullptr;
  183. }
  184. #endif
  185. AP_BoardConfig_CAN& AP::can() {
  186. return *AP_BoardConfig_CAN::get_singleton();
  187. }
  188. #endif