From 8213f78a78de7d6618bc6b1c9c1a34db3cb5e52c Mon Sep 17 00:00:00 2001 From: "Jasper v. Blanckenburg" Date: Tue, 14 Mar 2023 16:22:58 +0100 Subject: [PATCH] Basic implementation for STM32F3 --- FT_CAN_AL.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++ FT_CAN_AL.h | 26 ++++++++++++++++++ README.md | 17 ++++++++++++ 3 files changed, 121 insertions(+) create mode 100644 FT_CAN_AL.c create mode 100644 FT_CAN_AL.h diff --git a/FT_CAN_AL.c b/FT_CAN_AL.c new file mode 100644 index 0000000..2b1501f --- /dev/null +++ b/FT_CAN_AL.c @@ -0,0 +1,78 @@ +#include "FT_CAN_AL.h" + +#ifdef FTCAN_IS_BXCAN +static CAN_HandleTypeDef *hcan; + +HAL_StatusTypeDef ftcan_init(CAN_HandleTypeDef *handle) { + hcan = handle; + + HAL_StatusTypeDef status = + HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING); + if (status != HAL_OK) { + return status; + } + + return HAL_CAN_Start(hcan); +} + +HAL_StatusTypeDef ftcan_transmit(uint8_t id, const uint8_t *data, + size_t datalen) { + static CAN_TxHeaderTypeDef header; + header.StdId = id; + header.IDE = CAN_ID_STD; + header.RTR = CAN_RTR_DATA; + header.DLC = datalen; + uint32_t mailbox; + return HAL_CAN_AddTxMessage(hcan, &header, data, &mailbox); +} + +HAL_StatusTypeDef ftcan_add_filter(uint8_t id, uint8_t mask) { + static uint32_t next_filter_no = 0; + static CAN_FilterTypeDef filter; + if (next_filter_no % 2 == 0) { + filter.FilterIdHigh = id; + filter.FilterMaskIdHigh = mask; + filter.FilterIdLow = 0; + filter.FilterMaskIdLow = 0xFFFF; + } else { + // Leave high filter untouched from the last configuration + filter.FilterIdLow = id; + filter.FilterMaskIdLow = mask; + } + filter.FilterFIFOAssignment = CAN_FILTER_FIFO0; + filter.FilterBank = next_filter_no / 2; + if (filter.FilterBank > FTCAN_MAX_FILTER_NO) { + return HAL_ERROR; + } + filter.FilterMode = CAN_FILTERMODE_IDMASK; + filter.FilterScale = CAN_FILTERSCALE_16BIT; + filter.FilterActivation = CAN_FILTER_ENABLE; + + // Disable slave filters + // TODO: Some STM32 have multiple CAN peripherals, and one uses the slave + // filter bank + filter.SlaveStartFilterBank = FTCAN_MAX_FILTER_NO + 1; + + return HAL_CAN_ConfigFilter(hcan, &filter); +} + +void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *handle) { + if (handle != hcan) { + return; + } + CAN_RxHeaderTypeDef header; + uint8_t data[8]; + if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &header, data) != HAL_OK) { + return; + } + + if (header.IDE != CAN_ID_STD) { + return; + } + + ftcan_msg_received_cb(header.StdId, header.DLC, data); +} +#endif // CAN_IS_BXCAN + +__weak void ftcan_msg_received_cb(uint8_t id, size_t datalen, + const uint8_t *data) {} diff --git a/FT_CAN_AL.h b/FT_CAN_AL.h new file mode 100644 index 0000000..1e17eac --- /dev/null +++ b/FT_CAN_AL.h @@ -0,0 +1,26 @@ +#ifndef FT_CAN_AL_H +#define FT_CAN_AL_H + +#if defined(STM32F3) +#include "stm32f3xx_hal.h" +#define FTCAN_IS_BXCAN +#define FTCAN_MAX_FILTER_NO 13 +#else +#error "Couldn't detect STM family" +#endif // STM32F3 + +#ifdef FTCAN_IS_BXCAN +HAL_StatusTypeDef ftcan_init(CAN_HandleTypeDef *handle); +#endif // CAN_IS_BXCAN + +HAL_StatusTypeDef ftcan_transmit(uint8_t id, const uint8_t *data, + size_t datalen); + +HAL_StatusTypeDef ftcan_add_filter(uint8_t id, uint8_t mask); + +/** + * Define this function to be notified of incoming CAN messages + */ +void ftcan_msg_received_cb(uint8_t id, size_t datalen, const uint8_t *data); + +#endif // FT_CAN_AL_H diff --git a/README.md b/README.md index 2f8006d..d189681 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ This repository contains an abstraction layer to provide a simplified & unified interface to the STM32 bxCAN and FDCAN peripherals. +**Warning**: Currently, only bxCAN (for the STM32F3 series) is supported. + ## Installation Simply add the repository to your `Core/Lib` directory. You can also add it as a @@ -11,3 +13,18 @@ git submodule: mkdir -p Core/Lib cd Core/Lib git submodule add ssh://git@git.fasttube.de:313/FaSTTUBe/FT_CAN_AL.git + +The library needs to be told what STM family you're using, so make sure one of +the following symbols is defined when `FT_CAN_AL.c` is compiled or `FT_CAN_AL.h` +is included: + +- STM32F3 + +## Usage + +1. Include `FT_CAN_AL.h` +2. Call `ftcan_init()` with the appropriate handle +3. Call `ftcan_add_filter()` with all your filters +4. To transmit messages, call `ftcan_transmit()` +5. When a message is received, `ftcan_msg_received_cb()` is called. It has a + default empty implementation, which you can simply override.