canard_stm32.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. /*
  2. * Copyright (c) 2017 UAVCAN Team
  3. *
  4. * Distributed under the MIT License, available in the file LICENSE.
  5. *
  6. * Author: Pavel Kirienko <pavel.kirienko@zubax.com>
  7. */
  8. #ifndef CANARD_STM32_H
  9. #define CANARD_STM32_H
  10. #include <canard.h>
  11. #include <string.h> // NOLINT
  12. #ifdef __cplusplus
  13. extern "C"
  14. {
  15. #endif
  16. /**
  17. * Set this build config macro to 1 to use CAN2 instead of CAN1, if available.
  18. * Setting this parameter when CAN2 is not available may not be detected at compile time!
  19. */
  20. #if !defined(CANARD_STM32_USE_CAN2)
  21. # define CANARD_STM32_USE_CAN2 0
  22. #endif
  23. /**
  24. * Trigger an assertion failure if inner priority inversion is detected at run time.
  25. * This setting has no effect in release builds, where NDEBUG is defined.
  26. */
  27. #if !defined(CANARD_STM32_DEBUG_INNER_PRIORITY_INVERSION)
  28. # define CANARD_STM32_DEBUG_INNER_PRIORITY_INVERSION 1
  29. #endif
  30. /**
  31. * Driver error codes.
  32. * These values are returned negated from API functions that return int.
  33. */
  34. #define CANARD_STM32_ERROR_UNSUPPORTED_BIT_RATE 1000
  35. #define CANARD_STM32_ERROR_MSR_INAK_NOT_SET 1001
  36. #define CANARD_STM32_ERROR_MSR_INAK_NOT_CLEARED 1002
  37. #define CANARD_STM32_ERROR_UNSUPPORTED_FRAME_FORMAT 1003
  38. /**
  39. * This is defined by the bxCAN hardware.
  40. * Devices with only one CAN interface have 14 filters (e.g. F103).
  41. * Devices with two CAN interfaces have 28 filters, which are shared between two interfaces (e.g. F105, F446).
  42. * The filters are distributed between CAN1 and CAN2 by means of the CAN2 start filter bank selection,
  43. * which is a number from 1 to 27 inclusive. Seeing as the start bank cannot be set to 0, CAN2 has one filter less
  44. * to use.
  45. */
  46. #define CANARD_STM32_NUM_ACCEPTANCE_FILTERS 14U
  47. /**
  48. * The interface can be initialized in either of these modes.
  49. *
  50. * The Silent mode is useful for automatic CAN bit rate detection, where the interface is initialized at an
  51. * arbitrarily guessed CAN bit rate (typically either 1 Mbps, 500 Kbps, 250 Kbps, or 125 Kbps, these are the
  52. * standard values defined by the UAVCAN specification), and the bus is then listened for 1 second in order to
  53. * determine whether the bit rate was guessed correctly. It is paramount to use the silent mode in this case so
  54. * as to not interfere with ongoing communications on the bus if the guess was incorrect.
  55. *
  56. * The automatic TX abort on error mode should be used during dynamic node ID allocation. The reason for that
  57. * is well explained in the UAVCAN specification, please read it.
  58. *
  59. * The normal mode should be used for all other use cases, particularly for the normal operation of the node,
  60. * hence the name.
  61. */
  62. typedef enum
  63. {
  64. CanardSTM32IfaceModeNormal, //!< Normal mode
  65. CanardSTM32IfaceModeSilent, //!< Do not affect the bus, only listen
  66. CanardSTM32IfaceModeAutomaticTxAbortOnError //!< Abort pending TX if a bus error has occurred
  67. } CanardSTM32IfaceMode;
  68. /**
  69. * Interface statistics; these values can be queried using a dedicated API call.
  70. */
  71. typedef struct
  72. {
  73. uint64_t rx_overflow_count;
  74. uint64_t error_count;
  75. } CanardSTM32Stats;
  76. /**
  77. * ID and Mask of a hardware acceptance filter.
  78. * The ID and Mask fields support flags @ref CANARD_CAN_FRAME_EFF and @ref CANARD_CAN_FRAME_RTR.
  79. */
  80. typedef struct
  81. {
  82. uint32_t id;
  83. uint32_t mask;
  84. } CanardSTM32AcceptanceFilterConfiguration;
  85. /**
  86. * These parameters define the timings of the CAN controller.
  87. * Please refer to the documentation of the bxCAN macrocell for explanation.
  88. * These values can be computed by the developed beforehand if ROM size is of a concern,
  89. * or they can be computed at run time using the function defined below.
  90. */
  91. typedef struct
  92. {
  93. uint16_t bit_rate_prescaler; /// [1, 1024]
  94. uint8_t bit_segment_1; /// [1, 16]
  95. uint8_t bit_segment_2; /// [1, 8]
  96. uint8_t max_resynchronization_jump_width; /// [1, 4] (recommended value is 1)
  97. } CanardSTM32CANTimings;
  98. /**
  99. * Initializes the CAN controller at the specified bit rate.
  100. * The mode can be either normal, silent, or auto-abort on error;
  101. * in silent mode the controller will be only listening, not affecting the state of the bus;
  102. * in the auto abort mode the controller will cancel the pending transmissions if a bus error is encountered.
  103. * The auto abort mode is needed for dynamic node ID allocation procedure; please refer to the UAVCAN specification
  104. * for more information about this topic.
  105. *
  106. * This function can be invoked any number of times; every invocation re-initializes everything from scratch.
  107. *
  108. * WARNING: The clock of the CAN module must be enabled before this function is invoked!
  109. * If CAN2 is used, CAN1 must be also enabled!
  110. *
  111. * WARNING: The driver is not thread-safe!
  112. * It does not use IRQ or critical sections though, so it is safe to invoke its API functions from the
  113. * IRQ context from the application.
  114. *
  115. * @retval 0 Success
  116. * @retval negative Error
  117. */
  118. int16_t canardSTM32Init(const CanardSTM32CANTimings* const timings,
  119. const CanardSTM32IfaceMode iface_mode);
  120. /**
  121. * Pushes one frame into the TX buffer, if there is space.
  122. * Note that proper care is taken to ensure that no inner priority inversion is taking place.
  123. * This function does never block.
  124. *
  125. * @retval 1 Transmitted successfully
  126. * @retval 0 No space in the buffer
  127. * @retval negative Error
  128. */
  129. int16_t canardSTM32Transmit(const CanardCANFrame* const frame);
  130. /**
  131. * Reads one frame from the hardware RX FIFO, unless all FIFO are empty.
  132. * This function does never block.
  133. *
  134. * @retval 1 Read successfully
  135. * @retval 0 The buffer is empty
  136. * @retval negative Error
  137. */
  138. int16_t canardSTM32Receive(CanardCANFrame* const out_frame);
  139. /**
  140. * Sets up acceptance filters according to the provided list of ID and masks.
  141. * Note that when the interface is reinitialized, hardware acceptance filters are reset.
  142. * Also note that during filter reconfiguration, some RX frames may be lost.
  143. *
  144. * Setting zero filters will result in rejection of all frames.
  145. * In order to accept all frames, set one filter with ID = Mask = 0, which is also the default configuration.
  146. *
  147. * @retval 0 Success
  148. * @retval negative Error
  149. */
  150. int16_t canardSTM32ConfigureAcceptanceFilters(const CanardSTM32AcceptanceFilterConfiguration* const filter_configs,
  151. const uint8_t num_filter_configs);
  152. /**
  153. * Returns the running interface statistics.
  154. */
  155. CanardSTM32Stats canardSTM32GetStats(void);
  156. /**
  157. * Given the rate of the clock supplied to the bxCAN macrocell (typically PCLK1) and the desired bit rate,
  158. * this function iteratively solves for the best possible timing settings. The CAN bus timing parameters,
  159. * such as the sample point location, the number of time quantas per bit, etc., are optimized according to the
  160. * recommendations provided in the specifications of UAVCAN, DeviceNet, and CANOpen.
  161. *
  162. * Unless noted otherwise, all units are SI units; particularly, frequency is specified in hertz.
  163. *
  164. * The implementation is adapted from libuavcan.
  165. *
  166. * This function is defined in the header in order to encourage the linker to discard it if it is not used.
  167. *
  168. * @retval 0 Success
  169. * @retval negative Solution could not be found for the provided inputs.
  170. */
  171. static inline
  172. int16_t canardSTM32ComputeCANTimings(const uint32_t peripheral_clock_rate,
  173. const uint32_t target_bitrate,
  174. CanardSTM32CANTimings* const out_timings)
  175. {
  176. if (target_bitrate < 1000)
  177. {
  178. return -CANARD_STM32_ERROR_UNSUPPORTED_BIT_RATE;
  179. }
  180. CANARD_ASSERT(out_timings != NULL); // NOLINT
  181. memset(out_timings, 0, sizeof(*out_timings));
  182. /*
  183. * Hardware configuration
  184. */
  185. static const uint8_t MaxBS1 = 16;
  186. static const uint8_t MaxBS2 = 8;
  187. /*
  188. * Ref. "Automatic Baudrate Detection in CANopen Networks", U. Koppe, MicroControl GmbH & Co. KG
  189. * CAN in Automation, 2003
  190. *
  191. * According to the source, optimal quanta per bit are:
  192. * Bitrate Optimal Maximum
  193. * 1000 kbps 8 10
  194. * 500 kbps 16 17
  195. * 250 kbps 16 17
  196. * 125 kbps 16 17
  197. */
  198. const uint8_t max_quanta_per_bit = (uint8_t)((target_bitrate >= 1000000) ? 10 : 17); // NOLINT
  199. CANARD_ASSERT(max_quanta_per_bit <= (MaxBS1 + MaxBS2));
  200. static const uint16_t MaxSamplePointLocationPermill = 900;
  201. /*
  202. * Computing (prescaler * BS):
  203. * BITRATE = 1 / (PRESCALER * (1 / PCLK) * (1 + BS1 + BS2)) -- See the Reference Manual
  204. * BITRATE = PCLK / (PRESCALER * (1 + BS1 + BS2)) -- Simplified
  205. * let:
  206. * BS = 1 + BS1 + BS2 -- Number of time quanta per bit
  207. * PRESCALER_BS = PRESCALER * BS
  208. * ==>
  209. * PRESCALER_BS = PCLK / BITRATE
  210. */
  211. const uint32_t prescaler_bs = peripheral_clock_rate / target_bitrate;
  212. /*
  213. * Searching for such prescaler value so that the number of quanta per bit is highest.
  214. */
  215. uint8_t bs1_bs2_sum = (uint8_t)(max_quanta_per_bit - 1); // NOLINT
  216. while ((prescaler_bs % (1U + bs1_bs2_sum)) != 0)
  217. {
  218. if (bs1_bs2_sum <= 2)
  219. {
  220. return -CANARD_STM32_ERROR_UNSUPPORTED_BIT_RATE; // No solution
  221. }
  222. bs1_bs2_sum--;
  223. }
  224. const uint32_t prescaler = prescaler_bs / (1U + bs1_bs2_sum);
  225. if ((prescaler < 1U) || (prescaler > 1024U))
  226. {
  227. return -CANARD_STM32_ERROR_UNSUPPORTED_BIT_RATE; // No solution
  228. }
  229. /*
  230. * Now we have a constraint: (BS1 + BS2) == bs1_bs2_sum.
  231. * We need to find such values so that the sample point is as close as possible to the optimal value,
  232. * which is 87.5%, which is 7/8.
  233. *
  234. * Solve[(1 + bs1)/(1 + bs1 + bs2) == 7/8, bs2] (* Where 7/8 is 0.875, the recommended sample point location *)
  235. * {{bs2 -> (1 + bs1)/7}}
  236. *
  237. * Hence:
  238. * bs2 = (1 + bs1) / 7
  239. * bs1 = (7 * bs1_bs2_sum - 1) / 8
  240. *
  241. * Sample point location can be computed as follows:
  242. * Sample point location = (1 + bs1) / (1 + bs1 + bs2)
  243. *
  244. * Since the optimal solution is so close to the maximum, we prepare two solutions, and then pick the best one:
  245. * - With rounding to nearest
  246. * - With rounding to zero
  247. */
  248. uint8_t bs1 = (uint8_t)(((7 * bs1_bs2_sum - 1) + 4) / 8); // Trying rounding to nearest first // NOLINT
  249. uint8_t bs2 = (uint8_t)(bs1_bs2_sum - bs1); // NOLINT
  250. CANARD_ASSERT(bs1_bs2_sum > bs1);
  251. {
  252. const uint16_t sample_point_permill = (uint16_t)(1000U * (1U + bs1) / (1U + bs1 + bs2)); // NOLINT
  253. if (sample_point_permill > MaxSamplePointLocationPermill) // Strictly more!
  254. {
  255. bs1 = (uint8_t)((7 * bs1_bs2_sum - 1) / 8); // Nope, too far; now rounding to zero
  256. bs2 = (uint8_t)(bs1_bs2_sum - bs1);
  257. }
  258. }
  259. const bool valid = (bs1 >= 1) && (bs1 <= MaxBS1) && (bs2 >= 1) && (bs2 <= MaxBS2);
  260. /*
  261. * Final validation
  262. * Helpful Python:
  263. * def sample_point_from_btr(x):
  264. * assert 0b0011110010000000111111000000000 & x == 0
  265. * ts2,ts1,brp = (x>>20)&7, (x>>16)&15, x&511
  266. * return (1+ts1+1)/(1+ts1+1+ts2+1)
  267. */
  268. if ((target_bitrate != (peripheral_clock_rate / (prescaler * (1U + bs1 + bs2)))) ||
  269. !valid)
  270. {
  271. // This actually means that the algorithm has a logic error, hence assert(0).
  272. CANARD_ASSERT(0); // NOLINT
  273. return -CANARD_STM32_ERROR_UNSUPPORTED_BIT_RATE;
  274. }
  275. out_timings->bit_rate_prescaler = (uint16_t) prescaler;
  276. out_timings->max_resynchronization_jump_width = 1; // One is recommended by UAVCAN, CANOpen, and DeviceNet
  277. out_timings->bit_segment_1 = bs1;
  278. out_timings->bit_segment_2 = bs2;
  279. return 0;
  280. }
  281. #ifdef __cplusplus
  282. }
  283. #endif
  284. #endif