-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Thread Safe CAN for all platforms + STM CAN Interrupt fix (#341)
* Add extended frame support to CanMessage * stm32 can driver, remove mutex on bus for now * Merge to hpp * Convert shared and stm mcal CMake libaries to Interface so they link properly * Move Linux to Interface library, fix headers & CMake bindings * atomic buffer * Update Nucleo Docs for Demo/CAN and CANGEn docs * remove unused imports * Remove unused imports * Abstract out AtomicBuffer and use in CAN bus. * Rename Register function * Add forware declare comment * Inclusion guard * feat: Move `pack` and `unpack`. Moved out of templates / generated code into `shared/comms/can/msg.hpp`. Prevents redefinition if multiple `_messages.hpp` files exist (eg. Veh and Pt CAN) * fix: Fix GetTimestamp calculation. We should not multiply by `HAL_GetTickFreq()`. The `HAL_GetTick()` method "Provides a tick value in millisecond." according to the HAL guide UM 1905. Also, multiplying by freq would give the wrong units since its 1/second
- Loading branch information
1 parent
cdc1af3
commit c10c596
Showing
36 changed files
with
396 additions
and
320 deletions.
There are no files selected for viewing
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
add_library(mcal-linux STATIC) | ||
add_library(mcal-linux INTERFACE) | ||
|
||
target_include_directories(mcal-linux PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../..) | ||
target_include_directories(mcal-linux INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/../..) | ||
|
||
add_subdirectory(periph) | ||
target_link_libraries(mcal-linux INTERFACE shared) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,10 @@ | ||
target_sources(mcal-linux | ||
PRIVATE | ||
INTERFACE | ||
adc.cc | ||
can.cc | ||
digital_input.cc | ||
digital_output.cc | ||
) | ||
|
||
add_subdirectory(vcan) | ||
target_link_libraries(mcal-linux PUBLIC vcan pthread) | ||
target_link_libraries(mcal-linux INTERFACE vcan pthread) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
# Empty file - implicitly adds this folder as an include directory | ||
target_sources(mcal-stm32f767 INTERFACE can.cc) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
#include "stm32f7xx_hal.h" | ||
#ifdef HAL_CAN_MODULE_ENABLED | ||
|
||
#include <cstdint> | ||
|
||
#include "can.hpp" | ||
|
||
// FIFO0 is the "high priority" queue on stm32f7. We do not use FIFO1 | ||
constexpr uint32_t kCanFifo = CAN_RX_FIFO0; | ||
constexpr uint32_t kCanInterrupt = CAN_IT_RX_FIFO0_MSG_PENDING; | ||
|
||
namespace { // InterruptHandler is private to this file | ||
|
||
/// Prior to this class, we spent several hours debugging an issue where the | ||
/// interrupt was activated but the handler was not being called, causing the | ||
/// program to get repeatedly executed the interupt callback and stall the rest | ||
/// of the program. | ||
/// This class ensures that interrupts activated and handled together. | ||
class InterruptHandler { | ||
using CanBase = mcal::stm32f767::periph::CanBase; | ||
|
||
public: | ||
void RegisterCanBase(CAN_HandleTypeDef* hcan, CanBase* can_base) { | ||
int index = HandleToIndex(hcan); | ||
if (index == -1) return; | ||
|
||
can_bases[index] = can_base; | ||
HAL_CAN_ActivateNotification(hcan, kCanInterrupt); | ||
} | ||
|
||
void Handle(CAN_HandleTypeDef* hcan) { | ||
int index = HandleToIndex(hcan); | ||
if (index == -1) return; | ||
|
||
auto can_base = can_bases[index]; | ||
if (can_base != nullptr) { | ||
can_bases[index]->Receive(); | ||
} | ||
} | ||
|
||
private: | ||
CanBase* can_bases[3] = {nullptr, nullptr, nullptr}; | ||
|
||
int HandleToIndex(CAN_HandleTypeDef* hcan) { | ||
// CANx are not contiguous in memory, so we can't use a simple array | ||
if (hcan->Instance == CAN1) { | ||
return 0; | ||
} else if (hcan->Instance == CAN2) { | ||
return 1; | ||
} else if (hcan->Instance == CAN3) { | ||
return 2; | ||
} else { | ||
return -1; | ||
} | ||
} | ||
}; | ||
} // namespace | ||
|
||
static InterruptHandler interrupt_handler; | ||
|
||
extern "C" { | ||
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef* hcan) { | ||
// Overrides the "weak" callback defined by CubeMX | ||
interrupt_handler.Handle(hcan); | ||
} | ||
} | ||
|
||
namespace mcal::stm32f767::periph { | ||
|
||
CanBase::CanBase(CAN_HandleTypeDef* hcan) : hcan_{hcan} {} | ||
|
||
void CanBase::Setup() { | ||
ConfigFilters(); | ||
interrupt_handler.RegisterCanBase(hcan_, this); | ||
HAL_CAN_Start(hcan_); | ||
} | ||
|
||
void CanBase::Send(const shared::can::RawMessage& msg) { | ||
uint32_t tx_mailboxes_free_level = HAL_CAN_GetTxMailboxesFreeLevel(hcan_); | ||
if (tx_mailboxes_free_level < 1) { | ||
dropped_tx_frames_ += 1; | ||
return; | ||
} | ||
|
||
CAN_TxHeaderTypeDef stm_tx_header; | ||
stm_tx_header.RTR = CAN_RTR_DATA; // we only support data frames currently | ||
stm_tx_header.DLC = msg.data_length; | ||
|
||
if (msg.is_extended_frame) { | ||
stm_tx_header.IDE = CAN_ID_EXT; | ||
stm_tx_header.ExtId = msg.id; | ||
} else { | ||
stm_tx_header.IDE = CAN_ID_STD; | ||
stm_tx_header.StdId = msg.id; | ||
} | ||
|
||
HAL_CAN_AddTxMessage(hcan_, &stm_tx_header, msg.data, &tx_mailbox_addr_); | ||
} | ||
|
||
void CanBase::Receive() { | ||
shared::can::RawMessage rx_msg; | ||
|
||
CAN_RxHeaderTypeDef stm_rx_header; | ||
HAL_CAN_GetRxMessage(hcan_, kCanFifo, &stm_rx_header, rx_msg.data); | ||
|
||
rx_msg.is_extended_frame = stm_rx_header.IDE == CAN_ID_EXT; | ||
rx_msg.data_length = static_cast<uint8_t>(stm_rx_header.DLC); | ||
if (rx_msg.is_extended_frame) { | ||
rx_msg.id = stm_rx_header.ExtId; | ||
} else { | ||
rx_msg.id = stm_rx_header.StdId; | ||
} | ||
|
||
AddToBus(rx_msg); | ||
} | ||
|
||
inline uint32_t CanBase::GetTimestamp() const { | ||
return HAL_GetTick(); | ||
} | ||
|
||
void CanBase::ConfigFilters() { | ||
// Currently we don't support filtering - all messages are accepted | ||
CAN_FilterTypeDef filter_config{ | ||
.FilterIdHigh = 0x0000, | ||
.FilterIdLow = 0x0000, | ||
.FilterMaskIdHigh = 0x0000, | ||
.FilterMaskIdLow = 0x0000, | ||
.FilterFIFOAssignment = kCanFifo, | ||
.FilterBank = 0, | ||
.FilterMode = CAN_FILTERMODE_IDMASK, | ||
.FilterScale = CAN_FILTERSCALE_32BIT, | ||
.FilterActivation = CAN_FILTER_ENABLE, | ||
.SlaveStartFilterBank = 14, | ||
}; | ||
|
||
HAL_CAN_ConfigFilter(hcan_, &filter_config); | ||
} | ||
|
||
} // namespace mcal::stm32f767::periph | ||
|
||
#endif // HAL_CAN_MODULE_ENABLED |
Oops, something went wrong.