commit 3cdd6da05182863540edb6d81e224d6e40ec36bf Author: Stefano Calabretti Date: Sun Nov 28 12:12:27 2021 +0100 First commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8c76af6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +!.vscode/settings.json +.vscode \ No newline at end of file diff --git a/Inc/mmr_can.h b/Inc/mmr_can.h new file mode 100644 index 0000000..0587b9c --- /dev/null +++ b/Inc/mmr_can.h @@ -0,0 +1,77 @@ +#ifndef INC_MMR_CAN_H_ +#define INC_MMR_CAN_H_ + +#include +#include +#include "mmr_can_includes.h" +#include "mmr_can_types.h" +#include "mmr_can_optimize.h" + +#define MMR_CAN_RX_FIFO CAN_RX_FIFO0 + + +#if MMR_CAN_RX_FIFO == CAN_RX_FIFO0 +#define MMR_CAN_RX_INTERRUPT CAN_IT_RX_FIFO0_MSG_PENDING +#else +#define MMR_CAN_RX_INTERRUPT CAN_IT_RX_FIFO1_MSG_PENDING +#endif + +#define MMR_CAN_ID 0x103 +#define MMR_CAN_BUFFER_LEN 8 + +typedef uint8_t CanRxBuffer[MMR_CAN_BUFFER_LEN]; + + +typedef struct { + bool enabled; + + /** + * The fifo that the filter should operate + * on + */ + CanFilterFifo fifo; + + /** + * The filter bank to use + * + * In systems with more than one CAN interface, + * this must go from 0 to slaveBankStart. + */ + CanFilterBank bank; + + /** + * The start of the slave filter banks. + * This value is ignored for single-CAN boards. + */ + CanFilterBank slaveBankStart; + + /** + * The mask to use with this filter. + */ + CanFilterMask idMask; +} MmrCanFilterSettings; + +typedef struct { + /** + * The id of the CAN interface that will receive the packet. + * + * If you are using the CANbus in loopback mode, it can be the + * id that the sender is using. + */ + CanId remoteId; + CanMailbox *mailbox; + uint8_t *data; + uint8_t length; +} MmrCanPacket; + + +#define MMR_CAN_FilterConfigDefault(phcan) \ + MMR_CAN_FilterConfig(phcan, MMR_CAN_GetDefaultFilterSettings()) + +HalStatus MMR_CAN_FilterConfig(CanHandle *hcan, MmrCanFilterSettings settings); +CanFilterMask MMR_CAN_AlignStandardMask(CanFilterMask baseMask); +MmrCanFilterSettings MMR_CAN_GetDefaultFilterSettings(); + +HalStatus MMR_CAN_Send(CanHandle *hcan, MmrCanPacket packet); + +#endif /* INC_MMR_CAN_H_ */ diff --git a/Inc/mmr_can_incudes.h b/Inc/mmr_can_incudes.h new file mode 100644 index 0000000..b299c3e --- /dev/null +++ b/Inc/mmr_can_incudes.h @@ -0,0 +1,11 @@ +#ifndef INC_MMR_CAN_INCLUDES_H_ +#define INC_MMR_CAN_INCLUDES_H_ + +#include "stm32f3xx_hal.h" + +#ifndef CAN +#define CAN +#endif + + +#endif /* INC_MMR_CAN_INCLUDES_H_ */ diff --git a/Inc/mmr_can_optimize.h b/Inc/mmr_can_optimize.h new file mode 100644 index 0000000..5f04c9a --- /dev/null +++ b/Inc/mmr_can_optimize.h @@ -0,0 +1,10 @@ +#ifndef INC_MMR_CAN_OPTIMIZE_H_ +#define INC_MMR_CAN_OPTIMIZE_H_ + +#ifdef __GNUC__ +#define always_inline inline __attribute__((always_inline)) +#else +#define always_inline inline +#endif + +#endif /* INC_OPTIMIZE_H_ */ diff --git a/Inc/mmr_can_types.h b/Inc/mmr_can_types.h new file mode 100644 index 0000000..5752109 --- /dev/null +++ b/Inc/mmr_can_types.h @@ -0,0 +1,37 @@ +#ifndef INC_MMR_CAN_TYPES_H_ +#define INC_MMR_CAN_TYPES_H_ + +#include +#include "mmr_can_incudes.h" + +typedef uint32_t CanId; +typedef uint32_t CanMailbox; + +/** + * A filter mask for the CANbus. + * It acts like a subnet mask, filtering the ids that + * do not match it. + * + * The value 0 can be used to let any message pass through. + * + * You should use the MMR_CAN_AlignStandardMask function + * to align the mask when using standard masks. + */ +typedef uint32_t CanFilterMask; + +/** + * Stores a value from CAN_filter_FIFO + * That is, CAN_FILTER_FIFOx + */ +typedef uint8_t CanFilterFifo; + +/** + * Represents a filter bank. + * The values must be in the range [0, 27] + */ +typedef uint8_t CanFilterBank; + +typedef HAL_StatusTypeDef HalStatus; +typedef CAN_HandleTypeDef CanHandle; + +#endif /* INC_MMR_TYPES_H_ */ diff --git a/Inc/mmr_can_util.h b/Inc/mmr_can_util.h new file mode 100644 index 0000000..95cbbe8 --- /dev/null +++ b/Inc/mmr_can_util.h @@ -0,0 +1,14 @@ +#ifndef INC_MMR_CAN_UTIL_H_ +#define INC_MMR_CAN_UTIL_H_ + +#include +#include + +#define stringArrayLength(array) \ + stringBufferLength((array), sizeof(array)) + +size_t stringBufferLength(uint8_t *buffer, size_t maxLen) { + return strnlen((const char*)buffer, maxLen); +} + +#endif /* INC_UTIL_H_ */ diff --git a/Src/mmr_can.c b/Src/mmr_can.c new file mode 100644 index 0000000..df89cd8 --- /dev/null +++ b/Src/mmr_can.c @@ -0,0 +1,66 @@ +#include "mmr_can.h" + + +HalStatus MMR_CAN_FilterConfig(CanHandle *hcan, MmrCanFilterSettings settings) { + CAN_FilterTypeDef filter = { + .FilterActivation = settings.enabled + ? CAN_FILTER_ENABLE + : CAN_FILTER_DISABLE, + + .FilterIdHigh = settings.idMask, + .FilterMaskIdHigh = settings.idMask, + .FilterFIFOAssignment = settings.fifo, + .FilterBank = settings.bank, + .SlaveStartFilterBank = settings.slaveBankStart, + .FilterMode = CAN_FILTERMODE_IDMASK, + .FilterScale = CAN_FILTERSCALE_32BIT, + }; + + return HAL_CAN_ConfigFilter(hcan, &filter); +} + +CanFilterMask MMR_CAN_AlignStandardMask(CanFilterMask baseMask) { + static const uint8_t extendedMaskSurplusBytes = 5; + return baseMask << extendedMaskSurplusBytes; +} + +MmrCanFilterSettings MMR_CAN_GetDefaultFilterSettings() { + return (MmrCanFilterSettings) { + .enabled = true, + .fifo = MMR_CAN_RX_FIFO, + .idMask = 0, + .bank = 0, + .slaveBankStart = 14, + }; +} + + +HalStatus MMR_CAN_Send(CanHandle *hcan, MmrCanPacket packet) { + CAN_TxHeaderTypeDef header = { + .IDE = CAN_ID_STD, + .RTR = CAN_RTR_DATA, + .DLC = packet.length, + .StdId = packet.slaveId, + .TransmitGlobalTime = DISABLE, + }; + + return HAL_CAN_AddTxMessage(hcan, &header, packet.data, packet.mailbox); +} + + +static void __handleCanRxInterrupt(CAN_HandleTypeDef *hcan) { + static CAN_RxHeaderTypeDef rxHeader = {}; + static CanRxBuffer rxData = {}; + + HAL_CAN_GetRxMessage(hcan, MMR_CAN_RX_FIFO, &rxHeader, rxData); +} + +#if MMR_CAN_RX_FIFO == CAN_RX_FIFO0 +void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) { + __handleCanRxInterrupt(hcan); +} +#elif MMR_CAN_RX_FIFO == CAN_RX_FIFO1 +void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan) { + __handleCanRxInterrupt(hcan); +} +#endif