14#if defined(STM32) && defined(HAL_CAN_MODULE_ENABLED)
42LinkedQueue<Stm32Can> Stm32Can::m_queue;
45: m_hwHandle(&hwHandle)
53 HAL_StatusTypeDef state = HAL_CAN_Init(m_hwHandle);
56 if (state == HAL_ERROR)
61 else if (state == HAL_BUSY)
66 else if (state == HAL_TIMEOUT)
78 HAL_StatusTypeDef state = HAL_CAN_DeInit(m_hwHandle);
81 if (state == HAL_ERROR)
86 else if (state == HAL_BUSY)
91 else if (state == HAL_TIMEOUT)
104 m_readDataSize = bufferSize;
128 return m_messageIdRead;
134 m_messageIdWrite = id;
147 SEMF_INFO(
"index: %u, messageId: %u, messageIdMask: %u", index,
messageId, messageIdMask);
148 CAN_FilterTypeDef rxFilter;
150 if (filterBank >= m_numOfFilterBanks)
156 rxFilter.FilterBank = filterBank;
157 rxFilter.FilterMode = CAN_FILTERMODE_IDMASK;
158 rxFilter.FilterFIFOAssignment = CAN_RX_FIFO0;
159 rxFilter.FilterScale = CAN_FILTERSCALE_32BIT;
160 rxFilter.FilterActivation = ENABLE;
162 if (messageIdMask <= 0x1FFFFFFF)
165 rxFilter.FilterIdLow = (
messageId >> (11 - 3)) & 0xFFF8;
167 rxFilter.FilterMaskIdHigh = ((messageIdMask << 5) | (messageIdMask >> (32 - 5))) & 0xFFFF;
168 rxFilter.FilterMaskIdLow = (messageIdMask >> (11 - 3)) & 0xFFF8;
172 SEMF_ERROR(
"invalid message id mask: %u", messageIdMask);
176 HAL_CAN_ConfigFilter(m_hwHandle, &rxFilter);
182 HAL_CAN_StateTypeDef canstate = HAL_CAN_GetState(m_hwHandle);
183 HAL_StatusTypeDef state;
186 case HAL_CAN_STATE_READY:
187 case HAL_CAN_STATE_LISTENING:
188 SEMF_INFO(
"state is ready or listening");
189 state = HAL_CAN_RequestSleep(m_hwHandle);
192 if (state == HAL_ERROR)
197 else if (state == HAL_BUSY)
202 else if (state == HAL_TIMEOUT)
211 case HAL_CAN_STATE_SLEEP_ACTIVE:
215 case HAL_CAN_STATE_RESET:
216 case HAL_CAN_STATE_SLEEP_PENDING:
217 SEMF_INFO(
"state is reset or sleep pending");
218 state = HAL_CAN_Init(m_hwHandle);
221 if (state == HAL_ERROR)
226 else if (state == HAL_BUSY)
231 else if (state == HAL_TIMEOUT)
238 state = HAL_CAN_Start(m_hwHandle);
241 if (state == HAL_ERROR)
246 else if (state == HAL_BUSY)
251 else if (state == HAL_TIMEOUT)
258 state = HAL_CAN_RequestSleep(m_hwHandle);
261 if (state == HAL_ERROR)
266 else if (state == HAL_BUSY)
271 else if (state == HAL_TIMEOUT)
279 case HAL_CAN_STATE_ERROR:
290 SEMF_INFO(
"release deep power down mode");
292 HAL_CAN_StateTypeDef canstate = HAL_CAN_GetState(m_hwHandle);
293 HAL_StatusTypeDef state;
296 case HAL_CAN_STATE_READY:
297 case HAL_CAN_STATE_LISTENING:
298 SEMF_INFO(
"state is ready or listening");
301 case HAL_CAN_STATE_SLEEP_ACTIVE:
302 state = HAL_CAN_WakeUp(m_hwHandle);
305 if (state == HAL_ERROR)
310 else if (state == HAL_BUSY)
315 else if (state == HAL_TIMEOUT)
324 case HAL_CAN_STATE_RESET:
325 case HAL_CAN_STATE_SLEEP_PENDING:
326 SEMF_INFO(
"state is reset or sleep pending");
327 state = HAL_CAN_Init(m_hwHandle);
330 if (state == HAL_ERROR)
335 else if (state == HAL_BUSY)
340 else if (state == HAL_TIMEOUT)
347 state = HAL_CAN_Start(m_hwHandle);
350 if (state == HAL_ERROR)
355 else if (state == HAL_BUSY)
360 else if (state == HAL_TIMEOUT)
368 case HAL_CAN_STATE_ERROR:
388 i.isrRead(can, fifoId);
394 i.isrWritten(can, mailboxId);
405 if (&can != m_hwHandle)
408 if (m_readData ==
nullptr)
416 if (fifoId > CAN_RX_FIFO1)
423 HAL_StatusTypeDef state = HAL_CAN_GetRxMessage(m_hwHandle, fifoId == 0 ? CAN_RX_FIFO0 : CAN_RX_FIFO1, &m_rxHeader, m_readData );
426 if (state == HAL_ERROR)
431 else if (state == HAL_BUSY)
436 else if (state == HAL_TIMEOUT)
444 if (m_rxHeader.IDE == CAN_ID_EXT)
445 m_messageIdRead = m_rxHeader.ExtId;
447 m_messageIdRead = m_rxHeader.StdId;
449 if (m_rxHeader.RTR == CAN_RTR_REMOTE)
458 if (&can != m_hwHandle)
461 m_writeDataIndex += m_txHeader.DLC;
462 if (m_writeDataIndex >= m_writeDataSize)
465 writeHardware(&m_writeData[m_writeDataIndex], m_writeDataSize - m_writeDataIndex);
470 if (&can != m_hwHandle)
479 SEMF_INFO(
"write data: %p, size %u", data, dataSize);
486 if (m_messageIdWrite <= 0x7FF)
488 m_txHeader.IDE = CAN_ID_STD;
489 m_txHeader.StdId = m_messageIdWrite & 0x7FF;
491 else if (m_messageIdWrite <= 0x1FFFFFFF)
493 m_txHeader.IDE = CAN_ID_EXT;
494 m_txHeader.ExtId = m_messageIdWrite & 0x1FFFFFFF;
498 SEMF_ERROR(
"invalid message id: %u", m_messageIdWrite);
505 SEMF_WARNING(
"The given dataSize is greater than 8, but this STM32-CAN implementation doesn't support CAN FD. The value is changed to 8");
508 size_t writeSize = std::min(dataSize, std::size_t{8});
511 m_writeDataIndex = 0;
512 m_writeDataSize = writeSize;
514 m_txHeader.DLC = writeSize;
515 m_txHeader.RTR = CAN_RTR_DATA;
516 m_txHeader.TransmitGlobalTime = FunctionalState::DISABLE;
518 HAL_StatusTypeDef state = HAL_CAN_AddTxMessage(m_hwHandle, &m_txHeader,
const_cast<uint8_t*
>(data), &m_usedTxMailbox);
521 if (state == HAL_ERROR)
526 else if (state == HAL_BUSY)
531 else if (state == HAL_TIMEOUT)
550 if (m_messageIdWrite <= 0x7FF)
552 m_txHeader.IDE = CAN_ID_STD;
553 m_txHeader.StdId = m_messageIdWrite & 0x7FF;
555 else if (m_messageIdWrite <= 0x1FFFFFFF)
557 m_txHeader.IDE = CAN_ID_EXT;
558 m_txHeader.ExtId = m_messageIdWrite & 0x1FFFFFFF;
562 SEMF_ERROR(
"invalid message id: %u", m_messageIdWrite);
568 m_txHeader.RTR = CAN_RTR_REMOTE;
571 m_txHeader.TransmitGlobalTime = FunctionalState::DISABLE;
573 HAL_StatusTypeDef state = HAL_CAN_AddTxMessage(m_hwHandle, &m_txHeader, m_requestData, &m_usedTxMailbox);
576 if (state == HAL_ERROR)
581 else if (state == HAL_BUSY)
586 else if (state == HAL_TIMEOUT)
597 HAL_StatusTypeDef state = HAL_CAN_Start(m_hwHandle);
601 if (state == HAL_ERROR)
609 HAL_StatusTypeDef notificationState =
610 HAL_CAN_ActivateNotification(m_hwHandle, CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_RX_FIFO1_MSG_PENDING | CAN_IT_TX_MAILBOX_EMPTY);
611 if (notificationState != HAL_OK)
613 if (notificationState == HAL_ERROR)
625 HAL_StatusTypeDef state = HAL_CAN_Stop(m_hwHandle);
628 if (state == HAL_ERROR)
void onError(Error thrown)
Is called if an error occurred by hardware read or write access. Will emit error signal.
Class for representing errors. Every error should have a unique source code. As a user feel encourage...
LinkedQueue is an managed single linked queue implementation.
Class for using CAN with Stm32.
@ EnterDeepPowerDownMode_StartStateResetSleepPendingHalTimeout
@ ReleaseDeepPowerDownMode_InitStateResetSleepPendingHalBusy
@ RequestHardware_HalTimeout
@ SetFilter_IndexOutOfBounds
@ ReleaseDeepPowerDownMode_InitStateResetSleepPendingHalTimeout
@ RequestHardware_HalError
@ ReleaseDeepPowerDownMode_StartStateResetSleepPendingHalTimeout
@ IsrRead_NullpointerReadBuffer
@ EnterDeepPowerDownMode_SleepStateReadyListeningHalError
@ RequestHardware_NotStarted
@ EnterDeepPowerDownMode_SleepStateResetSleepPendingHalError
@ ReleaseDeepPowerDownMode_WakeupStateSleepActiveHalBusy
@ ReleaseDeepPowerDownMode_StartStateResetSleepPendingHalError
@ ReleaseDeepPowerDownMode_InitStateResetSleepPendingHalError
@ EnterDeepPowerDownMode_SleepStateReadyListeningHalBusy
@ Start_HalNotInitialized
@ WriteHardware_HalTimeout
@ EnterDeepPowerDownMode_StartStateResetSleepPendingHalError
@ EnterDeepPowerDownMode_SleepStateResetSleepPendingHalTimeout
@ EnterDeepPowerDownMode_InitStateResetSleepPendingHalTimeout
@ EnterDeepPowerDownMode_InitStateResetSleepPendingHalBusy
@ RequestHardware_InvalidMessageId
@ EnterDeepPowerDownMode_SleepStateResetSleepPendingHalBusy
@ WriteHardware_NotStarted
@ EnterDeepPowerDownMode_StartStateResetSleepPendingHalBusy
@ ReleaseDeepPowerDownMode_StartStateInvalid
@ RequestHardware_HalBusy
@ EnterDeepPowerDownMode_InitStateResetSleepPendingHalError
@ WriteHardware_InvalidMessageId
@ ReleaseDeepPowerDownMode_StartStateError
@ SetFilter_MessageIdMaskInvalid
@ ReleaseDeepPowerDownMode_StartStateResetSleepPendingHalBusy
@ EnterDeepPowerDownMode_SleepStateReadyListeningHalTimeout
@ ReleaseDeepPowerDownMode_WakeupStateSleepActiveHalError
@ ReleaseDeepPowerDownMode_WakeupStateSleepActiveHalTimeout
uint32_t messageId() const override
Returns the message ID for reading data. Use this function after reading the data via read-function.
static void systemIsrWritten(CAN_HandleTypeDef &can, uint8_t mailboxId)
System-wide interrupt service routine for can transmit.
void stopWrite() override
void isrWritten(CAN_HandleTypeDef &can, uint8_t mailboxId)
Sending a readyWritten signal.
void setReadBuffer(uint8_t buffer[], size_t bufferSize) override
Sets the read buffer for having the possibility to handle the received data.
void requestHardware() override
void setFrequency(uint32_t hz) override
Sets the speed.
Stm32Can(CAN_HandleTypeDef &hwHandle)
Constructor.
void setFilter(uint32_t filterBank, uint32_t messageId, uint32_t messageIdMask) override
Sets a message hardware receive filter.
void writeHardware(const uint8_t data[], size_t dataSize) override
Hardware will write data.
static void systemIsrError(CAN_HandleTypeDef &can)
System-wide interrupt service routine for can error.
void setMessageId(uint32_t id) override
Sets the message ID for writing data. Use this function before writing the data via write-function.
void releaseDeepPowerDownMode()
Go to active mode.
void start()
Hardware driver will be started.
void stop()
Hardware driver will be stopped.
static LinkedQueue< Stm32Can > * queue()
Get the list with all cans.
void isrRead(CAN_HandleTypeDef &can, uint8_t fifoId)
Saves a received message and sends a readyRead or readyRequested signal.
void enterDeepPowerDownMode()
Go to deep power down mode.
void isrError(CAN_HandleTypeDef &can)
Sending a error signal.
bool isStarted() const
Get the state of the start of the CAN driver.
static void systemIsrRead(CAN_HandleTypeDef &can, uint8_t fifoId)
System-wide interrupt service routine for can receive.
#define SEMF_WARNING(...)
void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *can)
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *can)
void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *can)
void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *can)
void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *can)
void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *can)