firmware/controllers/can/can.h
| Line | Branch | Decision | Exec | Source |
|---|---|---|---|---|
| 1 | /** | |||
| 2 | * @file can.h | |||
| 3 | * | |||
| 4 | * @date Mar 19, 2020 | |||
| 5 | * @author Matthew Kennedy, (c) 2020 | |||
| 6 | */ | |||
| 7 | ||||
| 8 | #pragma once | |||
| 9 | ||||
| 10 | #define HAS_CAN_FRAME (EFI_SIMULATOR || HAL_USE_CAN || EFI_UNIT_TEST) | |||
| 11 | ||||
| 12 | #if EFI_UNIT_TEST || !EFI_CAN_SUPPORT | |||
| 13 | #include "can_mocks.h" | |||
| 14 | #endif // EFI_PROD_CODE | |||
| 15 | ||||
| 16 | #if !EFI_UNIT_TEST | |||
| 17 | #include "hal.h" | |||
| 18 | #endif // EFI_UNIT_TEST | |||
| 19 | ||||
| 20 | #include "periodic_thread_controller.h" | |||
| 21 | ||||
| 22 | // Try to recover CAN after following timeout | |||
| 23 | #define CAN_RX_TIMEOUT TIME_MS2I(100) | |||
| 24 | ||||
| 25 | //can tx periodic task cycle time in frequency, 200hz -> 5ms period | |||
| 26 | #define CAN_CYCLE_FREQ (200.0f) | |||
| 27 | //can tx periodic task cycle time in ms | |||
| 28 | #define CAN_CYCLE_PERIOD (CH_CFG_ST_FREQUENCY / CAN_CYCLE_FREQ) | |||
| 29 | ||||
| 30 | enum class CanInterval : uint16_t { | |||
| 31 | None = 0, | |||
| 32 | _5ms = 1 << 0, | |||
| 33 | _10ms = 1 << 1, | |||
| 34 | _20ms = 1 << 2, | |||
| 35 | _50ms = 1 << 3, | |||
| 36 | _100ms = 1 << 4, | |||
| 37 | _200ms = 1 << 5, | |||
| 38 | _250ms = 1 << 6, | |||
| 39 | _500ms = 1 << 7, | |||
| 40 | _1000ms = 1 << 8, | |||
| 41 | _MAX_Cycle = _1000ms, | |||
| 42 | }; | |||
| 43 | ||||
| 44 | void resetCanWriteCycle(); | |||
| 45 | ||||
| 46 | // 11 bit (CAN 2.0A) | |||
| 47 | #define IS_EXT_RANGE_ID(id) ((id) >= 2048) | |||
| 48 | ||||
| 49 | class CanListener; | |||
| 50 | class CanSensorBase; | |||
| 51 | ||||
| 52 | #if EFI_CAN_SUPPORT | |||
| 53 | void processCanRxMessage(const size_t busIndex, const CANRxFrame& msg, efitick_t nowNt); | |||
| 54 | #endif // EFI_CAN_SUPPORT | |||
| 55 | ||||
| 56 | void registerCanListener(CanListener& listener); | |||
| 57 | void unregisterCanListener(CanListener& listener); | |||
| 58 | ||||
| 59 | void registerCanSensor(CanSensorBase& sensor); | |||
| 60 | // TODO: unregisterCanSensor()? | |||
| 61 | ||||
| 62 | class CanWrite final : public PeriodicController</*TStackSize*/512> { | |||
| 63 | public: | |||
| 64 | CanWrite(); | |||
| 65 | void PeriodicTask(efitick_t nowNt) override; | |||
| 66 | }; | |||
| 67 | ||||
| 68 | // allow using shorthand CI | |||
| 69 | using CI = CanInterval; | |||
| 70 | ||||
| 71 | // logical and/or operators so we can use our enum like an int | |||
| 72 | 8 | constexpr CI operator |(CI lhs, CI rhs) { | ||
| 73 | using T = std::underlying_type_t<CI>; | |||
| 74 | 8 | return static_cast<CI>(static_cast<T>(lhs) | static_cast<T>(rhs)); | ||
| 75 | } | |||
| 76 | ||||
| 77 | 1 | constexpr CI operator &(CI lhs, CI rhs) { | ||
| 78 | using T = std::underlying_type_t<CI>; | |||
| 79 | 1 | return static_cast<CI>(static_cast<T>(lhs) & static_cast<T>(rhs)); | ||
| 80 | } | |||
| 81 | ||||
| 82 | 8 | constexpr CI& operator |=(CI& lhs, CI rhs) { | ||
| 83 | 8 | lhs = lhs | rhs; | ||
| 84 | 8 | return lhs; | ||
| 85 | } | |||
| 86 | ||||
| 87 | class CanCycle { | |||
| 88 | public: | |||
| 89 | 1 | explicit CanCycle(uint32_t cycleCounter200hz) | ||
| 90 | 1 | : m_cycleFlags(computeFlags(cycleCounter200hz)) | ||
| 91 | { | |||
| 92 | 1 | } | ||
| 93 | ||||
| 94 | 1 | bool isInterval(CanInterval interval) { | ||
| 95 | 1 | return CanInterval::None != (m_cycleFlags & interval); | ||
| 96 | } | |||
| 97 | ||||
| 98 | private: | |||
| 99 | static CanInterval computeFlags(uint32_t cycleCount); | |||
| 100 | ||||
| 101 | const CanInterval m_cycleFlags; | |||
| 102 | }; | |||
| 103 | ||||
| 104 | // We need these helpers because the frame layout is different on STM32H7 | |||
| 105 | #ifdef STM32H7XX | |||
| 106 | #define CAN_SID(f) ((f).std.SID) | |||
| 107 | #define CAN_EID(f) ((f).ext.EID) | |||
| 108 | #define CAN_ISX(f) ((f).common.XTD) | |||
| 109 | #else | |||
| 110 | #define CAN_SID(f) ((f).SID) | |||
| 111 | #define CAN_EID(f) ((f).EID) | |||
| 112 | #define CAN_ISX(f) ((f).IDE) | |||
| 113 | #endif | |||
| 114 | ||||
| 115 | #define CAN_ID(f) (CAN_ISX(f) ? CAN_EID(f) : CAN_SID(f)) | |||
| 116 | ||||
| 117 |