146 lines
4.4 KiB
C++
146 lines
4.4 KiB
C++
#include "pch.h"
|
|
|
|
#include "hal.h"
|
|
|
|
#include "can_hw.h"
|
|
|
|
extern "C" {
|
|
#include "boot.h"
|
|
}
|
|
|
|
// CAN1 PB8+PB9 and CAN2 PB5+PB6 pins are commonly used by Hellen.
|
|
// CAN2 PB5+PB13 pins can be used for ST-bootloader compatibility.
|
|
//
|
|
// Other STM32 CAN pin combinations:
|
|
// CAN1_RX: { PI9, PA11, PH14, PD0, PB8 }, CAN1_TX: { PA12, PH13, PD1, PB9 }
|
|
// CAN2_RX: { PB5, PB12 }, CAN2_TX: { PB6, PB13 }
|
|
|
|
#ifndef BOOT_COM_CAN_CHANNEL_INDEX
|
|
#error BOOT_COM_CAN_CHANNEL_INDEX is not defined.
|
|
#elif (BOOT_COM_CAN_CHANNEL_INDEX == 0)
|
|
#ifndef STM32_CAN_USE_CAN1
|
|
#error STM32_CAN_USE_CAN1 is not enabled for CAN index 0
|
|
#endif
|
|
#undef OPENBLT_CAND
|
|
#define OPENBLT_CAND CAND1
|
|
#elif (BOOT_COM_CAN_CHANNEL_INDEX == 1)
|
|
#ifndef STM32_CAN_USE_CAN2
|
|
#error STM32_CAN_USE_CAN2 is not enabled for CAN index 1
|
|
#endif
|
|
#undef OPENBLT_CAND
|
|
#define OPENBLT_CAND CAND2
|
|
#else
|
|
#error Unknown BOOT_COM_CAN_CHANNEL_INDEX.
|
|
#endif
|
|
|
|
#if !defined(OPENBLT_CAN_RX_PIN) || !defined(OPENBLT_CAN_RX_PORT) || !defined(OPENBLT_CAN_TX_PIN) || !defined(OPENBLT_CAN_TX_PORT)
|
|
#if (BOOT_COM_CAN_CHANNEL_INDEX == 0)
|
|
// default pins for CAN1 (compatible with Hellen)
|
|
#define OPENBLT_CAN_RX_PORT GPIOB
|
|
#define OPENBLT_CAN_RX_PIN 8
|
|
#define OPENBLT_CAN_TX_PORT GPIOB
|
|
#define OPENBLT_CAN_TX_PIN 9
|
|
#elif (BOOT_COM_CAN_CHANNEL_INDEX == 1)
|
|
// default pins for CAN2 (compatible with ST-bootloader)
|
|
#define OPENBLT_CAN_RX_PORT GPIOB
|
|
#define OPENBLT_CAN_RX_PIN 5
|
|
#define OPENBLT_CAN_TX_PORT GPIOB
|
|
#define OPENBLT_CAN_TX_PIN 13
|
|
#endif
|
|
#endif
|
|
|
|
extern const CANConfig *findCanConfig(can_baudrate_e rate);
|
|
|
|
/************************************************************************************//**
|
|
** \brief Initializes the CAN controller and synchronizes it to the CAN bus.
|
|
** \return none.
|
|
**
|
|
****************************************************************************************/
|
|
extern "C" void CanInit(void) {
|
|
// init pins
|
|
palSetPadMode(OPENBLT_CAN_TX_PORT, OPENBLT_CAN_TX_PIN, PAL_MODE_ALTERNATE(EFI_CAN_TX_AF));
|
|
palSetPadMode(OPENBLT_CAN_RX_PORT, OPENBLT_CAN_RX_PIN, PAL_MODE_ALTERNATE(EFI_CAN_RX_AF));
|
|
|
|
auto cfg = findCanConfig(B500KBPS);
|
|
canStart(&OPENBLT_CAND, cfg);
|
|
}
|
|
|
|
|
|
/************************************************************************************//**
|
|
** \brief Transmits a packet formatted for the communication interface.
|
|
** \param data Pointer to byte array with data that it to be transmitted.
|
|
** \param len Number of bytes that are to be transmitted.
|
|
** \return none.
|
|
**
|
|
****************************************************************************************/
|
|
extern "C" void CanTransmitPacket(blt_int8u *data, blt_int8u len)
|
|
{
|
|
blt_int32u txMsgId = BOOT_COM_CAN_TX_MSG_ID;
|
|
CANTxFrame frame;
|
|
|
|
if ((txMsgId & 0x80000000) == 0)
|
|
{
|
|
/* set the 11-bit CAN identifier. */
|
|
frame.SID = txMsgId;
|
|
frame.IDE = CAN_IDE_STD;
|
|
}
|
|
else
|
|
{
|
|
txMsgId &= ~0x80000000;
|
|
/* set the 29-bit CAN identifier. */
|
|
frame.EID = txMsgId;
|
|
frame.IDE = CAN_IDE_EXT;
|
|
}
|
|
|
|
// Copy data/DLC
|
|
frame.DLC = len;
|
|
memcpy(frame.data8, data, len);
|
|
|
|
canTransmitTimeout(&OPENBLT_CAND, CAN_ANY_MAILBOX, &frame, TIME_MS2I(100));
|
|
}
|
|
|
|
/************************************************************************************//**
|
|
** \brief Receives a communication interface packet if one is present.
|
|
** \param data Pointer to byte array where the data is to be stored.
|
|
** \param len Pointer where the length of the packet is to be stored.
|
|
** \return BLT_TRUE is a packet was received, BLT_FALSE otherwise.
|
|
**
|
|
****************************************************************************************/
|
|
extern "C" blt_bool CanReceivePacket(blt_int8u *data, blt_int8u *len)
|
|
{
|
|
constexpr blt_int32u rxMsgId = BOOT_COM_CAN_RX_MSG_ID;
|
|
blt_bool result = BLT_FALSE;
|
|
CANRxFrame frame;
|
|
|
|
if (MSG_OK != canReceiveTimeout(&OPENBLT_CAND, CAN_ANY_MAILBOX, &frame, TIME_IMMEDIATE)) {
|
|
// no message was waiting
|
|
return BLT_FALSE;
|
|
}
|
|
|
|
// Check that the ID type matches this frame (std vs ext)
|
|
constexpr bool configuredAsExt = (rxMsgId & 0x80000000) != 0;
|
|
if (configuredAsExt != frame.IDE) {
|
|
// Wrong frame type
|
|
return BLT_FALSE;
|
|
}
|
|
|
|
// Check that the frame's ID matches
|
|
if (frame.IDE) {
|
|
if (frame.EID != (rxMsgId & ~0x80000000)) {
|
|
// Wrong ID
|
|
return BLT_FALSE;
|
|
}
|
|
} else {
|
|
if (frame.SID != rxMsgId) {
|
|
// Wrong ID
|
|
return BLT_FALSE;
|
|
}
|
|
}
|
|
|
|
// Copy data and length out
|
|
*len = frame.DLC;
|
|
memcpy(data, frame.data8, frame.DLC);
|
|
|
|
return BLT_TRUE;
|
|
}
|