diff --git a/can-manager/README.md b/can-manager/README.md new file mode 100644 index 0000000..71d3337 --- /dev/null +++ b/can-manager/README.md @@ -0,0 +1,4 @@ +# CAN-MANAGER + +[comment]: <> (EXPLANATION OF THE LIBRARY HERE) + diff --git a/can-manager/can_manager.c b/can-manager/can_manager.c deleted file mode 100644 index 0743a5e..0000000 --- a/can-manager/can_manager.c +++ /dev/null @@ -1,235 +0,0 @@ -/** - * Can Manager library - * - * @author Giacomo Mazzucchi - * @author Alessandro Conforti - * -*/ - -#include "can_manager.h" - -int _n_active_can = 0; -int can_manager_error_code = 0; -HAL_StatusTypeDef can_manager_hal_status_retval = HAL_OK; -generic_queue_t _rx_queues[CAN_MGR_MAX_CAN_BUSES]; -generic_queue_t _tx_queues[CAN_MGR_MAX_CAN_BUSES]; -uint8_t _rx_queues_data[CAN_MGR_MAX_QUEUE_ELEMENTS * sizeof(can_manager_message_t) * CAN_MGR_MAX_CAN_BUSES]; -uint8_t _tx_queues_data[CAN_MGR_MAX_QUEUE_ELEMENTS * sizeof(can_manager_message_t) * CAN_MGR_MAX_CAN_BUSES]; -void (*can_rx_msg_handlers[CAN_MGR_MAX_CAN_BUSES])(can_manager_message_t *); - - -#if FDCAN_MGR_ENABLED == 1 - -FDCAN_HandleTypeDef *fdcan_buses[MAX_CAN_BUSES]; - -int fdcan_init( - FDCAN_HandleTypeDef *hcan, void(can_rx_msg_handler)(can_manager_message_t *), uint32_t activation_interrupt, - FDCAN_FilterTypeDef *filter) { - if (_n_active_can >= MAX_CAN_BUSES) { - return -1; - } - - int assigned_id = _n_active_can; - can_rx_msg_handlers[assigned_id] = can_rx_msg_handler; - - GENQ_init( - &_rx_queues[assigned_id], sizeof(can_manager_message_t), CAN_MGR_MAX_QUEUE_ELEMENTS, - &_rx_queues_data[assigned_id]); - GENQ_init( - &_tx_queues[assigned_id], sizeof(can_manager_message_t), CAN_MGR_MAX_QUEUE_ELEMENTS, - &_tx_queues_data[assigned_id]); - - fdcan_buses[assigned_id] = hcan; - - _n_active_can++; - - if ((can_manager_hal_status_retval = HAL_FDCAN_ConfigFilter(hcan, filter)) != HAL_OK) { - can_manager_hal_status_retval = CAN_MGR_FILTER_ERROR_CODE; - return -1; - } - if ((can_manager_hal_status_retval = HAL_FDCAN_ActivateNotification(hcan, activation_interrupt, 0)) != HAL_OK) { - can_manager_hal_status_retval = CAN_MGR_CAN_INIT_IT_ERROR_CODE; - return -1; - } - return assigned_id; -} - -int fdcan_start(int can_id) { - if ((can_manager_hal_status_retval = HAL_FDCAN_Start(fdcan_buses[can_id])) != HAL_OK) { - can_manager_hal_status_retval = CAN_MGR_CAN_START_ERROR_CODE; - return 0; - } - return 1; -} - -void _fdcan_wait(FDCAN_HandleTypeDef *hcan) { - uint32_t start_timestamp = HAL_GetTick(); - while (HAL_FDCAN_GetTxFifoFreeLevel(hcan) == 0) { - if (HAL_GetTick() > start_timestamp + 5) { - return; - } - } -} - -int fdcan_send(int can_id, can_manager_message_t *msg) { - CAN_MGR_ID_CHECK(can_id); - FDCAN_HandleTypeDef *hcan = fdcan_buses[can_id]; - - uint32_t dlc_len = 0; - switch (msg->size) { - case 0: - dlc_len = FDCAN_DLC_BYTES_0; - break; - case 1: - dlc_len = FDCAN_DLC_BYTES_1; - break; - case 2: - dlc_len = FDCAN_DLC_BYTES_2; - break; - case 3: - dlc_len = FDCAN_DLC_BYTES_3; - break; - case 4: - dlc_len = FDCAN_DLC_BYTES_4; - break; - case 5: - dlc_len = FDCAN_DLC_BYTES_5; - break; - case 6: - dlc_len = FDCAN_DLC_BYTES_6; - break; - case 7: - dlc_len = FDCAN_DLC_BYTES_7; - break; - case 8: - dlc_len = FDCAN_DLC_BYTES_8; - break; - } - - FDCAN_TxHeaderTypeDef header = { - .Identifier = msg->id, - .IdType = FDCAN_STANDARD_ID, - .TxFrameType = FDCAN_DATA_FRAME, - .DataLength = dlc_len, - .ErrorStateIndicator = FDCAN_ESI_ACTIVE, - .BitRateSwitch = FDCAN_BRS_OFF, - .FDFormat = FDCAN_CLASSIC_CAN, - .TxEventFifoControl = FDCAN_STORE_TX_EVENTS, - .MessageMarker = 0, - }; - -#if CAN_WAIT_ENABLED == 1 - _fdcan_wait(hcan); -#endif - - if ((can_manager_hal_status_retval = HAL_FDCAN_AddMessageToTxFifoQ(hcan, &header, msg->data)) != HAL_OK) { - return 0; - } - return 1; -} - -#else - -CAN_HandleTypeDef *can_buses[CAN_MGR_MAX_CAN_BUSES]; - -int can_init( - CAN_HandleTypeDef *hcan, void(can_rx_msg_handler)(can_manager_message_t *), uint32_t activation_interrupt, - CAN_FilterTypeDef *filter) { - if (_n_active_can >= CAN_MGR_MAX_CAN_BUSES) { - return -1; - } - - int assigned_id = _n_active_can; - can_rx_msg_handlers[assigned_id] = can_rx_msg_handler; - - GENQ_init( - &_rx_queues[assigned_id], CAN_MGR_MAX_QUEUE_ELEMENTS * sizeof(can_manager_message_t), - sizeof(can_manager_message_t), &_rx_queues_data[assigned_id]); - GENQ_init( - &_tx_queues[assigned_id], CAN_MGR_MAX_QUEUE_ELEMENTS * sizeof(can_manager_message_t), - sizeof(can_manager_message_t), &_tx_queues_data[assigned_id]); - - can_buses[assigned_id] = hcan; - _n_active_can++; - - if ((can_manager_hal_status_retval = HAL_CAN_ConfigFilter(hcan, filter)) != HAL_OK) { - can_manager_error_code = CAN_MGR_FILTER_ERROR_CODE; - return -1; - } - if ((can_manager_hal_status_retval = HAL_CAN_ActivateNotification(hcan, activation_interrupt)) != HAL_OK) { - can_manager_error_code = CAN_MGR_CAN_INIT_IT_ERROR_CODE; - return -1; - } - return assigned_id; -} - -int can_start(int can_id) { - if ((can_manager_hal_status_retval = HAL_CAN_Start(can_buses[can_id])) != HAL_OK) { - can_manager_error_code = CAN_MGR_CAN_START_ERROR_CODE; - return 0; - } - return 1; -} - -void _can_wait(CAN_HandleTypeDef *hcan) { - uint32_t start_timestamp = HAL_GetTick(); - while (HAL_CAN_GetTxMailboxesFreeLevel(hcan) == 0) - if (HAL_GetTick() > start_timestamp + 5) - return; -} - -int can_send(int can_id, can_manager_message_t *msg) { - CAN_MGR_ID_CHECK(can_id); - CAN_HandleTypeDef *hcan = can_buses[can_id]; - CAN_TxHeaderTypeDef header = { - .StdId = msg->id, .IDE = CAN_ID_STD, .RTR = CAN_RTR_DATA, .DLC = msg->size, .TransmitGlobalTime = DISABLE}; - -#if CAN_WAIT_ENABLED == 1 - _can_wait(hcan); -#endif - uint32_t mlb = CAN_TX_MAILBOX0; - if (HAL_CAN_AddTxMessage(hcan, &header, msg->data, &mlb) != HAL_OK) { - return 0; - } - return 1; -} -#endif - -int add_to_rx_queue(int can_id, can_manager_message_t *msg) { - CAN_MGR_ID_CHECK(can_id); - return GENQ_push(&_rx_queues[can_id], (uint8_t *)msg); -} - -int add_to_tx_queue(int can_id, can_manager_message_t *msg) { - CAN_MGR_ID_CHECK(can_id); - return GENQ_push(&_tx_queues[can_id], (uint8_t *)msg); -} - -int consume_rx_queue(int can_id) { - CAN_MGR_ID_CHECK(can_id); - can_manager_message_t msg; - if (GENQ_pop(&_rx_queues[can_id], (uint8_t *)&msg)) { - (*can_rx_msg_handlers[can_id])(&msg); - return 1; - } - return 0; -} - -int flush_tx_queue(int can_id) { - CAN_MGR_ID_CHECK(can_id); - can_manager_message_t msg; - int sent_messages = 0; - while (GENQ_pop(&_tx_queues[can_id], (uint8_t *)&msg)) { -#ifdef FDCAN_MGR - if (!fdcan_send(can_id, &msg)) { - return -1; - } -#else - if (!can_send(can_id, &msg)) { - return -1; - } -#endif - ++sent_messages; - } - return sent_messages; -} diff --git a/can-manager/can_manager.h b/can-manager/can_manager.h deleted file mode 100644 index 786d00d..0000000 --- a/can-manager/can_manager.h +++ /dev/null @@ -1,116 +0,0 @@ -/**** - * Instruction to use the can manager library. - * - * @author Giacomo Mazzucchi - * @author Alessandro Conforti - * @date 20th November 2023 - * - * Declare those extern variables to access the error codes. - * - * extern HAL_StatusTypeDef can_manager_hal_status_retval; - * extern int can_manager_error_code; - * - * The can_manager_error_code is used in the init function - * to find which HAL_CAN function failed. - * The can_manager_hal_status_retval retrieves the status - * of the last failed HAL_CAN function. - * - * This is a template for a standard CAN filter. - * - * CAN_FilterTypeDef filter = { - * .FilterMode = CAN_FILTERMODE_IDMASK, - * .FilterIdLow = 0, - * .FilterIdHigh = 0xFFFF, - * .FilterMaskIdHigh = 0, - * .FilterMaskIdLow = 0, - * .FilterFIFOAssignment = CAN_FILTER_FIFO0, - * .FilterBank = 0, - * .FilterScale = CAN_FILTERSCALE_16BIT, - * .FilterActivation = ENABLE}; - * - * This is a template for a standard FDCAN filter. - * - * FDCAN_FilterTypeDef filter = { - * .IdType = FDCAN_STANDARD_ID, - * .FilterIndex = 0, - * .FilterType = FDCAN_FILTER_RANGE, - * .FilterConfig = FDCAN_FILTER_TO_RXFIFO0, - * .FilterID1 = 0, - * .FilterID2 = ((1U << 11) - 1) << 8, - * .IsCalibrationMsg = 0, - * .RxBufferIndex = 0}; - * - * This is instead a template for the standard CAN interrupt - * - * CAN_IT_TX_MAILBOX_EMPTY | CAN_IT_ERROR_WARNING | CAN_IT_ERROR_PASSIVE | CAN_IT_BUSOFF | CAN_IT_LAST_ERROR_CODE | CAN_IT_ERROR - * - * with also the correct fifo assignment - * - * CAN_IT_RX_FIFO0_MSG_PENDING - * - * ++++++++++++++++++++++++ - * *** EXAMPLE CODE - * ++++++++++++++++++++++++ - * - * int primary_can_id = -1; - * int secondary_can_id = -1; - * - * void f() { - * can_manager_message_t msg = { - * // compose your message - * }; - * add_to_tx_queue(primary_can_id, &msg); - * } - * - * void handle_primary(can_manager_message_t* msg) { - * // your handler - * } - * - * // Example for message handler callback - * void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) { - * CAN_RxHeaderTypeDef header = {}; - * can_manager_message_t msg = {}; - * HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &header, msg.data); - * msg.id = header.StdId; - * msg.size = header.DLC; - * add_to_rx_queue(primary_can_id, &msg) - * } - * - * int main() { - * // hcan, handler, configs - * int primary_can_id = can_init(&hcan1, handle_primary, config, ...); - * int secondary_can_id = can_init(&hcan2, handle_secondary, config, ...); - * while(1) { - * consume_rx_queue(primary_can_id); - * consume_rx_queue(secondary_can_id); - * flush_tx_queue(primary_can_id); - * flush_tx_queue(secondary_can_id); - * } - * } - * -*/ - -#ifndef CAN_MGR_H -#define CAN_MGR_H - -#include "can_types.h" -#include "generic_queue.h" -#include - -#include "main.h" - -#define CAN_MGR_ID_CHECK(can_id) \ - if (can_id < 0 || can_id >= CAN_MGR_MAX_CAN_BUSES) \ - return 0 - -#ifdef FDCAN_MGR -int fdcan_init( - FDCAN_HandleTypeDef *hcan, void(can_rx_msg_handler)(can_manager_message_t *), uint32_t activation_interrupt, - FDCAN_FilterTypeDef *filter); -#else -int can_init( - CAN_HandleTypeDef *hcan, void(can_rx_msg_handler)(can_manager_message_t *), uint32_t activation_interrupt, - CAN_FilterTypeDef *filter); -#endif - -#endif // CAN_MGR_H diff --git a/can-manager/can_types.h b/can-manager/can_types.h deleted file mode 100644 index b685e17..0000000 --- a/can-manager/can_types.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef CAN_TYPES_H -#define CAN_TYPES_H - -#include - -#define CAN_MGR_MAX_CAN_BUSES 2 -#define CAN_MGR_MAX_QUEUE_ELEMENTS 10 -#define CAN_MGR_CAN_WAIT_ENABLED 1 -#define CAN_MGR_FILTER_ERROR_CODE 2 -#define CAN_MGR_CAN_INIT_IT_ERROR_CODE 3 -#define CAN_MGR_CAN_START_ERROR_CODE 4 - -typedef struct { - uint16_t id; - uint8_t size; - uint8_t data[8]; -} can_manager_message_t; - -#ifdef FDCAN_MGR -int fdcan_send(int can_id, can_manager_message_t *msg); -int fdcan_start(int can_id); -#else -int can_send(int can_id, can_manager_message_t *msg); -int can_start(int can_id); -#endif -int consume_rx_queue(int can_id); -int flush_tx_queue(int can_id); -int add_to_rx_queue(int can_id, can_manager_message_t *msg); -int add_to_tx_queue(int can_id, can_manager_message_t *msg); - -#endif // #ifndef CAN_TYPES_H diff --git a/can-manager/inc/can_manager.h b/can-manager/inc/can_manager.h new file mode 100644 index 0000000..d1b0e4c --- /dev/null +++ b/can-manager/inc/can_manager.h @@ -0,0 +1,31 @@ +/** + * @file can_manager.h + * @brief It is recommended to include this header file only in can.c (in a + * STM32 CubeMX based project) + * + * @date 15 Feb 2024 + * @author Giacomo Mazzucchi [giacomo.mazzucchi@protonmail.com] + */ + +#ifndef CAN_MANAGER_H +#define CAN_MANAGER_H + +#include "can_manager_config.h" +#include "can_manager_can_types.h" + +#ifndef CAN_MGR_STM32_APPLICATION +#include "can_manager_type_mocking.h" +#else +#include "main.h" +#endif + +extern can_mgr_msg_t *can_mgr_msg_states[CAN_MGR_N_CAN]; +extern int can_mgr_error_code; +extern HAL_StatusTypeDef can_mgr_hal_code; + +int can_mgr_init(CAN_HandleTypeDef *hcan); +int can_mgr_config_filter(int can_id, CAN_FilterTypeDef *hfilter, uint32_t rx_fifo_assignment, can_mgr_msg_t *msg_states, size_t n_msg); +int can_mgr_activate_its(int can_id, uint32_t its); +int can_mgr_start(int can_id); + +#endif // CAN_MANAGER_H diff --git a/can-manager/inc/can_manager_can_types.h b/can-manager/inc/can_manager_can_types.h new file mode 100644 index 0000000..e68f60d --- /dev/null +++ b/can-manager/inc/can_manager_can_types.h @@ -0,0 +1,24 @@ +/** + * @file can_manager_can_types.h + * @brief Hardware independent header file + * + * @date 15 Feb 2024 + * @author Giacomo Mazzucchi [giacomo.mazzucchi@protonmail.com] + */ + +#ifndef CAN_MANAGER_CANTYPES_H +#define CAN_MANAGER_CANTYPES_H + +#include +#include +#include + +typedef struct { + uint16_t id; + uint8_t size; + uint8_t *data; +} can_mgr_msg_t; + +int can_mgr_send(int can_id, can_mgr_msg_t *msg); + +#endif // CAN_MANAGER_CANTYPES_H diff --git a/can-manager/inc/can_manager_type_mocking.h b/can-manager/inc/can_manager_type_mocking.h new file mode 100644 index 0000000..37c9b66 --- /dev/null +++ b/can-manager/inc/can_manager_type_mocking.h @@ -0,0 +1,147 @@ +#ifndef CAN_MANAGER_TYPE_MOCKING_H +#define CAN_MANAGER_TYPE_MOCKING_H + +#include "can_manager_can_types.h" + +#define CAN_RX_FIFO0 (0x00000000U) /*!< CAN receive FIFO 0 */ +#define CAN_RX_FIFO1 (0x00000001U) /*!< CAN receive FIFO 1 */ +#define CAN_RX_FIFO2 (0x00000002U) /*!< CAN receive FIFO 2 */ + +typedef enum { + HAL_OK = 0x00U, + HAL_ERROR = 0x01U, + HAL_BUSY = 0x02U, + HAL_TIMEOUT = 0x03U +} HAL_StatusTypeDef; + +typedef struct { + uint8_t dummy; +} CAN_HandleTypeDef; + +typedef struct { + uint32_t FilterIdHigh; /*!< Specifies the filter identification number (MSBs + for a 32-bit configuration, first one for a 16-bit + configuration). This parameter must be a number + between Min_Data = 0x0000 and Max_Data = 0xFFFF. */ + + uint32_t FilterIdLow; /*!< Specifies the filter identification number (LSBs + for a 32-bit configuration, second one for a 16-bit + configuration). This parameter must be a number + between Min_Data = 0x0000 and Max_Data = 0xFFFF. */ + + uint32_t + FilterMaskIdHigh; /*!< Specifies the filter mask number or identification + number, according to the mode (MSBs for a 32-bit + configuration, first one for a 16-bit configuration). + This parameter must be a number between Min_Data = + 0x0000 and Max_Data = 0xFFFF. */ + + uint32_t + FilterMaskIdLow; /*!< Specifies the filter mask number or identification + number, according to the mode (LSBs for a 32-bit + configuration, second one for a 16-bit configuration). + This parameter must be a number between Min_Data = + 0x0000 and Max_Data = 0xFFFF. */ + + uint32_t FilterFIFOAssignment; /*!< Specifies the FIFO (0 or 1U) which will be + assigned to the filter. This parameter can + be a value of @ref CAN_filter_FIFO */ + + uint32_t FilterBank; /*!< Specifies the filter bank which will be initialized. + For single CAN instance(14 dedicated filter banks), + this parameter must be a number between Min_Data = 0 + and Max_Data = 13. For dual CAN instances(28 filter + banks shared), this parameter must be a number between + Min_Data = 0 and Max_Data = 27. */ + + uint32_t + FilterMode; /*!< Specifies the filter mode to be initialized. + This parameter can be a value of @ref CAN_filter_mode */ + + uint32_t FilterScale; /*!< Specifies the filter scale. + This parameter can be a value of @ref + CAN_filter_scale */ + + uint32_t FilterActivation; /*!< Enable or disable the filter. + This parameter can be a value of @ref + CAN_filter_activation */ + + uint32_t + SlaveStartFilterBank; /*!< Select the start filter bank for the slave CAN + instance. For single CAN instances, this + parameter is meaningless. For dual CAN instances, + all filter banks with lower index are assigned to + master CAN instance, whereas all filter banks + with greater index are assigned to slave CAN + instance. This parameter must be a number between + Min_Data = 0 and Max_Data = 27. */ + +} CAN_FilterTypeDef; + +typedef struct { + uint32_t StdId; /*!< Specifies the standard identifier. + This parameter must be a number between Min_Data = 0 and + Max_Data = 0x7FF. */ + + uint32_t ExtId; /*!< Specifies the extended identifier. + This parameter must be a number between Min_Data = 0 and + Max_Data = 0x1FFFFFFF. */ + + uint32_t IDE; /*!< Specifies the type of identifier for the message that will + be transmitted. This parameter can be a value of @ref + CAN_identifier_type */ + + uint32_t RTR; /*!< Specifies the type of frame for the message that will be + transmitted. This parameter can be a value of @ref + CAN_remote_transmission_request */ + + uint32_t DLC; /*!< Specifies the length of the frame that will be transmitted. + This parameter must be a number between Min_Data = 0 and + Max_Data = 8. */ + + uint32_t Timestamp; /*!< Specifies the timestamp counter value captured on + start of frame reception. + @note: Time Triggered Communication Mode must be + enabled. This parameter must be a number between + Min_Data = 0 and Max_Data = 0xFFFF. */ + + uint32_t FilterMatchIndex; /*!< Specifies the index of matching acceptance + filter element. This parameter must be a number + between Min_Data = 0 and Max_Data = 0xFF. */ + +} CAN_RxHeaderTypeDef; + +typedef int FunctionalState; + +typedef struct { + uint32_t StdId; /*!< Specifies the standard identifier. + This parameter must be a number between Min_Data = 0 and + Max_Data = 0x7FF. */ + + uint32_t ExtId; /*!< Specifies the extended identifier. + This parameter must be a number between Min_Data = 0 and + Max_Data = 0x1FFFFFFF. */ + + uint32_t IDE; /*!< Specifies the type of identifier for the message that will + be transmitted. This parameter can be a value of @ref + CAN_identifier_type */ + + uint32_t RTR; /*!< Specifies the type of frame for the message that will be + transmitted. This parameter can be a value of @ref + CAN_remote_transmission_request */ + + uint32_t DLC; /*!< Specifies the length of the frame that will be transmitted. + This parameter must be a number between Min_Data = 0 and + Max_Data = 8. */ + + FunctionalState + TransmitGlobalTime; /*!< Specifies whether the timestamp counter value + captured on start of frame transmission, is sent in DATA6 and + DATA7 replacing pData[6] and pData[7]. + @note: Time Triggered Communication Mode must be enabled. + @note: DLC must be programmed as 8 bytes, in order these 2 bytes + are sent. This parameter can be set to ENABLE or DISABLE. */ + +} CAN_TxHeaderTypeDef; + +#endif // CAN_MANAGER_TYPE_MOCKING_H diff --git a/can-manager/inc/default_can_manager_config.h b/can-manager/inc/default_can_manager_config.h new file mode 100644 index 0000000..1b97e83 --- /dev/null +++ b/can-manager/inc/default_can_manager_config.h @@ -0,0 +1,8 @@ +#ifndef CAN_MANAGER_CONFIG_H +#define CAN_MANAGER_CONFIG_H + +#define CAN_MGR_N_CAN 2 +#define CAN_MGR_TOTAL_CAN_RX_FIFOS 2 +#define CAN_MGR_CAN_WAIT_ENABLED 0 + +#endif // CAN_MANAGER_CONFIG_H diff --git a/can-manager/src/can_manager.c b/can-manager/src/can_manager.c new file mode 100644 index 0000000..0254af8 --- /dev/null +++ b/can-manager/src/can_manager.c @@ -0,0 +1,160 @@ +/** + * @file can_manager.c + * @brief + * + * @date 15 Feb 2024 + * @author Giacomo Mazzucchi [giacomo.mazzucchi@protonmail.com] + */ + +#include "can_manager.h" + +#define CAN_MGR_NO_ERROR 0 +#define CAN_MGR_TOO_MANY_PERIPHERALS_ERROR 1 +#define CAN_MGR_HAL_ERROR 2 +#define CAN_MGR_INVALID_MSG_INDEX 3 +#define CAN_MGR_INDEX_OUT_OF_BOUND 4 + +CAN_HandleTypeDef *_can_mgr_peripherals[CAN_MGR_N_CAN]; +int _can_mgr_fifo_assignment[CAN_MGR_TOTAL_CAN_RX_FIFOS]; +can_mgr_msg_t *can_mgr_msg_states[CAN_MGR_N_CAN]; +int *_can_mgr_message_maps[CAN_MGR_N_CAN]; +size_t _can_mgr_msg_states_size[CAN_MGR_N_CAN]; +int _can_mgr_current_can_counter = 0; + +int can_mgr_error_code = CAN_MGR_NO_ERROR; +HAL_StatusTypeDef can_mgr_hal_code; + +/** + * TODO: every function check of can_id real + */ +int can_mgr_init(CAN_HandleTypeDef *hcan) { + if (_can_mgr_current_can_counter == CAN_MGR_N_CAN) { + can_mgr_error_code = CAN_MGR_TOO_MANY_PERIPHERALS_ERROR; + return -1; + } + _can_mgr_peripherals[_can_mgr_current_can_counter] = hcan; + int assigned_id = _can_mgr_current_can_counter; + _can_mgr_current_can_counter++; + return assigned_id; +} + +int can_mgr_config_filter(int can_id, CAN_FilterTypeDef *hfilter, + uint32_t rx_fifo_assignment, + can_mgr_msg_t *msg_states, + size_t n_msg) { + can_mgr_msg_states[can_id] = msg_states; + _can_mgr_msg_states_size[can_id] = n_msg; + _can_mgr_fifo_assignment[rx_fifo_assignment] = can_id; + +#ifdef CAN_MGR_STM32_APPLICATION + can_mgr_hal_code = + HAL_CAN_ConfigFilter(_can_mgr_peripherals[can_id], hfilter); + if (can_mgr_hal_code != HAL_OK) { + can_mgr_error_code = CAN_MGR_HAL_ERROR; + return -1; + } +#endif + return 0; +} + +int can_mgr_activate_its(int can_id, uint32_t its) { +#ifdef CAN_MGR_STM32_APPLICATION + can_mgr_error_code = + HAL_CAN_ActivateNotification(_can_mgr_peripherals[can_id], its); + if (can_mgr_hal_code != HAL_OK) { + can_mgr_error_code = CAN_MGR_HAL_ERROR; + return -1; + } +#endif + return 0; +} + +int can_mgr_start(int can_id) { +#ifdef CAN_MGR_STM32_APPLICATION + can_mgr_error_code = HAL_CAN_Start(_can_mgr_peripherals[can_id]); + if (can_mgr_hal_code != HAL_OK) { + can_mgr_error_code = CAN_MGR_HAL_ERROR; + return -1; + } +#endif + return 0; +} + +void _can_mgr_wait(CAN_HandleTypeDef *hcan) { +#ifdef CAN_MGR_STM32_APPLICATION + uint32_t start_timestamp = HAL_GetTick(); + while (HAL_CAN_GetTxMailboxesFreeLevel(hcan) == 0) + if (HAL_GetTick() > (start_timestamp + 5)) + return; +#endif +} + +int can_mgr_send(int can_id, can_mgr_msg_t *msg) { +#ifdef CAN_MGR_STM32_APPLICATION + // CAN_MGR_ID_CHECK(can_id); + CAN_HandleTypeDef *hcan = _can_mgr_peripherals[can_id]; + CAN_TxHeaderTypeDef header = {.StdId = msg->id, + .IDE = CAN_ID_STD, + .RTR = CAN_RTR_DATA, + .DLC = msg->size, + .TransmitGlobalTime = DISABLE}; +#if CAN_MGR_CAN_WAIT_ENABLED == 1 + _can_wait(hcan); +#endif + uint32_t mlb = CAN_TX_MAILBOX0; + can_mgr_hal_code = HAL_CAN_AddTxMessage(hcan, &header, msg->data, &mlb); + if (can_mgr_hal_code != HAL_OK) { + return 0; + } +#endif + return 0; +} + +// User-defined function +int can_mgr_from_id_to_index(int can_id, int msg_id); + +void _can_mgr_it_callback(CAN_HandleTypeDef *hcan, + uint32_t rx_fifo_assignment, can_mgr_msg_t* mock_msg) { + int msg_id; + int msg_dlc; + uint8_t msg_data[8] = {0}; +#ifdef CAN_MGR_STM32_APPLICATION + CAN_RxHeaderTypeDef header; + HAL_CAN_GetRxMessage(hcan, rx_fifo_assignment, &header, msg_data); + msg_id = header.StdId; + msg_dlc = header.DLC; +#else + msg_id = mock_msg->id; + msg_dlc = mock_msg->size; + memcpy(msg_data, mock_msg->data, msg_dlc); +#endif + int can_id = _can_mgr_fifo_assignment[rx_fifo_assignment]; + int index = can_mgr_from_id_to_index(can_id, msg_id); + if (index < 0) { + can_mgr_error_code = CAN_MGR_INVALID_MSG_INDEX; + } else if (index >= _can_mgr_msg_states_size[can_id]) { + can_mgr_error_code = CAN_MGR_INDEX_OUT_OF_BOUND; + } else { + can_mgr_msg_states[index]->id = msg_id; + can_mgr_msg_states[index]->size = msg_dlc; + memcpy(can_mgr_msg_states[index]->data, msg_data, msg_dlc); + } +} + +#if TOTAL_CAN_RX_FIFOS > 0 +void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) { + _can_mgr_it_callback(hcan, CAN_RX_FIFO0, NULL); +} +#endif + +#if TOTAL_CAN_RX_FIFOS > 1 +void HAL_CAN_RxFifo10MsgPendingCallback(CAN_HandleTypeDef *hcan) { + _can_mgr_it_callback(hcan, CAN_RX_FIFO1, NULL); +} +#endif + +#if TOTAL_CAN_RX_FIFOS > 2 +void HAL_CAN_RxFifo2MsgPendingCallback(CAN_HandleTypeDef *hcan) { + _can_mgr_it_callback(hcan, CAN_RX_FIFO2, NULL); +} +#endif diff --git a/can-manager/test/Makefile b/can-manager/test/Makefile new file mode 100644 index 0000000..32aaf9b --- /dev/null +++ b/can-manager/test/Makefile @@ -0,0 +1,73 @@ +.PHONY: all test_all clear + +# Build directories +BUILD_DIR=build +BUILD_DEPS_DIR=$(BUILD_DIR)/deps + +# Source and include directories +SRC_DIR=../src +INC_DIR=../inc +UNITY_DIR=../../Unity/src + +# Tools +CC=$(shell command -v gcc || command -v clang || echo /bin/gcc) +SZ=$(shell command -v size) + +# Sources +C_SOURCES=$(wildcard *.c) +DEPS_SOURCES=$(wildcard $(SRC_DIR)/*.c $(UNITY_DIR)/unity.c) +SOURCES=$(C_SOURCES) $(DEPS_SOURCES) + +# Include directories +C_INCLUDES= \ +$(UNITY_DIR) \ +$(INC_DIR) + +# Executables +TARGETS=$(addprefix $(BUILD_DIR)/, $(basename $(C_SOURCES))) + +OPT=-Og + +C_DEFINES= \ +UNITY_OUTPUT_COLOR=1 + + +CFLAGS=$(addprefix -I,$(C_INCLUDES)) $(OPT) -Wall $(addprefix -D,$(C_DEFINES)) + +# List of object files +C_OBJECTS=$(addprefix $(BUILD_DIR)/, $(notdir $(C_SOURCES:.c=.o))) +DEPS_OBJECTS=$(addprefix $(BUILD_DIR)/, $(notdir $(DEPS_SOURCES:.c=.o) $(UNITY_SOURCES:.c=.o))) +OBJECTS=$(C_OBJECTS) $(DEPS_OBJECTS) +vpath %.c $(sort $(dir $(SOURCES))) + +# File with the final test results +TEST_RESULTS=$(BUILD_DIR)/result.txt + +all: $(TARGETS) + +# Build +$(TARGETS): $(OBJECTS) Makefile + $(CC) $@.o $(DEPS_OBJECTS) -o $@ + +$(BUILD_DEPS_DIR)/%.o: %.c Makefile | $(BUILD_DIR) + $(CC) -c $(CFLAGS) $< -o $@ + +$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR) + $(CC) -c $(CFLAGS) $< -o $@ + +$(BUILD_DIR): $(BUILD_DEPS_DIR) + +$(BUILD_DEPS_DIR): + mkdir -p $@ + +# Run all tests +test_all: $(TARGETS) + @echo -n "" > $(TEST_RESULTS) + @for target in $?; do \ + ./$$target | tee -a $(TEST_RESULTS); \ + done + +# Clean all +clean: + rm -rf $(BUILD_DIR) + diff --git a/can-manager/test/test-can-manager.c b/can-manager/test/test-can-manager.c new file mode 100644 index 0000000..e2d1742 --- /dev/null +++ b/can-manager/test/test-can-manager.c @@ -0,0 +1,28 @@ +/** + * @file test-can-manager.c + * @brief + * + * @date 15 Feb 2024 + * @author Giacomo Mazzucchi [giacomo.mazzucchi@protonmail.com] + */ + +#include "can_manager.h" +#include "unity.h" + +int can_manager_from_id_to_index(int can_id, int msg_id) { + return 1; +} + +void setUp(void) {} + +void tearDown(void) {} + +void test_unity(void) { TEST_ASSERT(1); } + +int main() { + UNITY_BEGIN(); + + RUN_TEST(test_unity); + + UNITY_END(); +} diff --git a/can-manager/test/test.c b/can-manager/test/test.c deleted file mode 100644 index 2868e3e..0000000 --- a/can-manager/test/test.c +++ /dev/null @@ -1,43 +0,0 @@ -#include "../can_manager.h" - -void consume_primary_rx_queue(can_manager_message_t *msg) { - printf("RECEIVED can: primary, "); - print_message(msg); -} - -void consume_secondary_rx_queue(can_manager_message_t *msg) { - printf("RECEIVED can: secondary, "); - print_message(msg); -} - -int main() { - CAN_HandleTypeDef primary_can_handle; - CAN_HandleTypeDef secondary_can_handle; - primary_can_handle.name = "primary"; - secondary_can_handle.name = "secondary"; - - int can_primary_id = can_init(&primary_can_handle, consume_primary_rx_queue, 0, 0); - int can_secondary_id = can_init(&secondary_can_handle, consume_secondary_rx_queue, 0, 0); - - can_manager_message_t msg1 = {.id = 1, .size = 8, .data = {4, 6, 2, 8, 2, 4, 8, 6}}; - can_manager_message_t msg2 = {.id = 2, .size = 3, .data = {9, 1, 0, 0, 3, 2, 5, 4}}; - can_manager_message_t msg3 = {.id = 3, .size = 7, .data = {8, 2, 3, 4, 5, 6, 7, 1}}; - can_manager_message_t msg4 = {.id = 4, .size = 5, .data = {3, 7, 3, 6, 9, 5, 8, 5}}; - - add_to_tx_queue(can_primary_id, &msg1); - add_to_rx_queue(can_secondary_id, &msg2); - add_to_tx_queue(can_primary_id, &msg3); - add_to_rx_queue(can_secondary_id, &msg4); - - while (consume_rx_queue(can_primary_id)) - ; - - printf("sent %d messages primary\n", flush_tx_queue(can_primary_id)); - - while (consume_rx_queue(can_secondary_id)) - ; - - printf("sent %d messages secondary\n", flush_tx_queue(can_secondary_id)); - - return 0; -} \ No newline at end of file diff --git a/docs/.pages b/docs/.pages index 71527a3..8608734 100644 --- a/docs/.pages +++ b/docs/.pages @@ -3,3 +3,4 @@ nav: - micro-libs.md - blinky - bms-monitor + - can-manager diff --git a/docs/can-manager/.pages b/docs/can-manager/.pages new file mode 100644 index 0000000..ea41a2a --- /dev/null +++ b/docs/can-manager/.pages @@ -0,0 +1,3 @@ +title: Can manager +nav: + - can-manager.md diff --git a/docs/can-manager/can-manager.md b/docs/can-manager/can-manager.md new file mode 100644 index 0000000..b6006f1 --- /dev/null +++ b/docs/can-manager/can-manager.md @@ -0,0 +1,3 @@ +# Can manager + +This library ha