From 49c50f77cfcfce629156def67a74d2282e5e6e70 Mon Sep 17 00:00:00 2001 From: Frank Voorburg Date: Mon, 24 Jul 2017 10:31:53 +0000 Subject: [PATCH] Refs #316. Implemented framework for LibOpenBLT's generic CAN driver module. git-svn-id: https://svn.code.sf.net/p/openblt/code/trunk@309 5dc33758-31d5-4daf-9ae8-b24bf3d40d73 --- Host/Source/LibOpenBLT/CMakeLists.txt | 1 + Host/Source/LibOpenBLT/candriver.c | 208 ++++++++++++++++++++++++++ Host/Source/LibOpenBLT/candriver.h | 148 ++++++++++++++++++ Host/Source/LibOpenBLT/serialport.h | 2 +- 4 files changed, 358 insertions(+), 1 deletion(-) create mode 100644 Host/Source/LibOpenBLT/candriver.c create mode 100644 Host/Source/LibOpenBLT/candriver.h diff --git a/Host/Source/LibOpenBLT/CMakeLists.txt b/Host/Source/LibOpenBLT/CMakeLists.txt index e0ae05eb..7b0a8a8d 100644 --- a/Host/Source/LibOpenBLT/CMakeLists.txt +++ b/Host/Source/LibOpenBLT/CMakeLists.txt @@ -105,6 +105,7 @@ set( LIB_SRCS openblt.c session.c + candriver.c xcploader.c xcptpuart.c firmware.c diff --git a/Host/Source/LibOpenBLT/candriver.c b/Host/Source/LibOpenBLT/candriver.c new file mode 100644 index 00000000..b780839f --- /dev/null +++ b/Host/Source/LibOpenBLT/candriver.c @@ -0,0 +1,208 @@ +/************************************************************************************//** +* \file candriver.c +* \brief Generic CAN driver source file. +* \ingroup Session +* \internal +*---------------------------------------------------------------------------------------- +* C O P Y R I G H T +*---------------------------------------------------------------------------------------- +* Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved +* +*---------------------------------------------------------------------------------------- +* L I C E N S E +*---------------------------------------------------------------------------------------- +* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +* modify it under the terms of the GNU General Public License as published by the Free +* Software Foundation, either version 3 of the License, or (at your option) any later +* version. +* +* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +* PURPOSE. See the GNU General Public License for more details. +* +* You have received a copy of the GNU General Public License along with OpenBLT. It +* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy. +* +* \endinternal +****************************************************************************************/ + +/**************************************************************************************** +* Include files +****************************************************************************************/ +#include /* for assertions */ +#include /* for standard integer types */ +#include /* for NULL declaration */ +#include /* for boolean type */ +#include "candriver.h" /* Generic CAN driver module */ + + +/**************************************************************************************** +* Local data declarations +****************************************************************************************/ +/** \brief Pointer to the CAN interface that is linked. */ +static tCanInterface const * canIfPtr; + +/** \brief Flag to store the connection status. */ +static bool canConnected; + + +/************************************************************************************//** +** \brief Initializes the CAN module. Typically called once at program startup. +** \param settings Pointer to the CAN module settings. +** \param interface Pointer to the CAN interface to link. +** +****************************************************************************************/ +void CanInit(tCanSettings const * settings, tCanInterface const * const interface) +{ + /* Initialize locals. */ + canIfPtr = NULL; + canConnected = false; + + /* Check parameters. */ + assert(settings != NULL); + assert(interface != NULL); + + /* Only continue with valid parameters. */ + if ( (settings != NULL) && (interface != NULL) ) /*lint !e774 */ + { + /* Link the CAN interface. */ + canIfPtr = interface; + /* Initialize the CAN interface. */ + canIfPtr->Init(settings); + } +} /*** end of CanInit ***/ + + +/************************************************************************************//** +** \brief Terminates the CAN module. Typically called once at program cleanup. +** +****************************************************************************************/ +void CanTerminate(void) +{ + /* Make sure a valid CAN interface is linked. */ + assert(canIfPtr != NULL); + + /* Only continue with a valid CAN interface. */ + if (canIfPtr != NULL) /*lint !e774 */ + { + /* Make sure to disconnect first. */ + CanDisconnect(); + /* Terminate the CAN interface. */ + canIfPtr->Terminate(); + /* Unlink the CAN interface. */ + canIfPtr = NULL; + } +} /*** end of CanTerminate ***/ + + +/************************************************************************************//** +** \brief Connects the CAN module. +** \return True if connected, false otherwise. +** +****************************************************************************************/ +bool CanConnect(void) +{ + bool result = false; + + /* Make sure a valid CAN interface is linked. */ + assert(canIfPtr != NULL); + + /* Only continue with a valid CAN interface. */ + if (canIfPtr != NULL) /*lint !e774 */ + { + /* Make sure that the CAN module is in the disconnected state. */ + CanDisconnect(); + /* Connect the CAN interface. */ + result = canIfPtr->Connect(); + /* Update the connection state. */ + canConnected = result; + } + /* Give the result back to the caller. */ + return result; +} /*** end of CanConnect ***/ + + +/************************************************************************************//** +** \brief Disconnects the CAN module. +** +****************************************************************************************/ +void CanDisconnect(void) +{ + /* Make sure a valid CAN interface is linked. */ + assert(canIfPtr != NULL); + + /* Only continue with a valid CAN interface. */ + if (canIfPtr != NULL) /*lint !e774 */ + { + /* Only disconnect if actually connected. */ + if (canConnected) + { + /* Disconnect CAN interface. */ + canIfPtr->Disconnect(); + /* Update the connection state. */ + canConnected = false; + } + } +} /*** end of CanDisconnect ***/ + + +/************************************************************************************//** +** \brief Obtains the connection state of the CAN module. +** \return True if connected, false otherwise. +** +****************************************************************************************/ +bool CanIsConnected(void) +{ + /* Obtain and return the connection state to the caller. */ + return canConnected; +} /*** end of CanIsConnected ***/ + + +/************************************************************************************//** +** \brief Submits a message for transmission on the CAN bus. +** \param msg Pointer to CAN message structure. +** \return True if successful, false otherwise. +** +****************************************************************************************/ +bool CanTransmit(tCanMsg const * msg) +{ + bool result = false; + + /* Make sure a valid CAN interface is linked. */ + assert(canIfPtr != NULL); + + /* Only continue with a valid CAN interface. */ + if (canIfPtr != NULL) /*lint !e774 */ + { + /* Only transmit the message if connected. */ + if (canConnected) + { + result = canIfPtr->Transmit(msg); + } + } + /* Give the result back to the caller. */ + return result; +} /*** end of CanTransmit ***/ + + +/************************************************************************************//** +** \brief Registers the event callback functions that should be called by the CAN +** module. +** \param events Pointer to structure with event callback function pointers. +** +****************************************************************************************/ +void CanRegisterEvents(tCanEvents const * events) +{ + /* Make sure a valid CAN interface is linked. */ + assert(canIfPtr != NULL); + + /* Only continue with a valid CAN interface. */ + if (canIfPtr != NULL) /*lint !e774 */ + { + /* Register the events with the CAN interface. */ + canIfPtr->RegisterEvents(events); + } +} /*** end of CanRegisterEvents ***/ + + +/*********************************** end of candriver.c ********************************/ diff --git a/Host/Source/LibOpenBLT/candriver.h b/Host/Source/LibOpenBLT/candriver.h new file mode 100644 index 00000000..3119ecbf --- /dev/null +++ b/Host/Source/LibOpenBLT/candriver.h @@ -0,0 +1,148 @@ +/************************************************************************************//** +* \file candriver.h +* \brief Generic CAN driver header file. +* \ingroup Session +* \internal +*---------------------------------------------------------------------------------------- +* C O P Y R I G H T +*---------------------------------------------------------------------------------------- +* Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved +* +*---------------------------------------------------------------------------------------- +* L I C E N S E +*---------------------------------------------------------------------------------------- +* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or +* modify it under the terms of the GNU General Public License as published by the Free +* Software Foundation, either version 3 of the License, or (at your option) any later +* version. +* +* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +* PURPOSE. See the GNU General Public License for more details. +* +* You have received a copy of the GNU General Public License along with OpenBLT. It +* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy. +* +* \endinternal +****************************************************************************************/ +#ifndef CANDRIVER_H +#define CANDRIVER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/**************************************************************************************** +* Macro definitions +****************************************************************************************/ +/** \brief Maximum number of data bytes in a CAN message. */ +#define CAN_MSG_MAX_LEN (8u) + +/** Bit mask that configures a CAN message identifier as 29-bit extended as opposed to + * 11-bit standard. Whenever this bit is set in the CAN identifier field of tCanMsg, + * then the CAN identifier is configured for 29-bit CAN extended. + */ +#define CAN_MSG_EXT_ID_MASK (0x80000000u) + + +/**************************************************************************************** +* Type definitions +****************************************************************************************/ +/** \brief Enumeration of the supported baudrates. */ +typedef enum +{ + CAN_BR10K = 0, /**< 10 kbits/sec */ + CAN_BR20K = 1, /**< 20 kbits/sec */ + CAN_BR50K = 2, /**< 50 kbits/sec */ + CAN_BR100K = 3, /**< 100 kbits/sec */ + CAN_BR125K = 4, /**< 125 kbits/sec */ + CAN_BR250K = 5, /**< 250 kbits/sec */ + CAN_BR500K = 6, /**< 500 kbits/sec */ + CAN_BR800K = 7, /**< 800 kbits/sec */ + CAN_BR1M = 8 /**< 1 Mbits/sec */ +} tCanBaudrate; + +/** \brief Layout of a CAN message. Note that \ref CAN_MSG_EXT_ID_MASK can be used to + * configure the CAN message identifier as 29-bit extended. + */ +typedef struct t_can_msg +{ + uint32_t id; /**< CAN message identifier. */ + uint8_t dlc; /**< CAN message data length code. */ + uint8_t data[CAN_MSG_MAX_LEN]; /**< Array with CAN message data. */ +} tCanMsg; + +/** \brief Type to group of CAN interface related settings. The device name specifies + * the name of the CAN interface device. For some CAN interfaces this is don't + * care, but for other absolutely necessar, for example Linux SocketCAN. The + * channel specifies the channel on the CAN interface, in case it has multiple + * CAN channels. The baudrate specifies the communication speed on the CAN + * network. The code and mask values configure the message reception acceptance + * filter. A mask bit value of 0 means don't care. The code part of the filter + * determines what bit values to match in the received message identifier. + * Example 1: Receive all CAN identifiers + * .code = 0x00000000 + * .mask = 0x00000000 + * Example 2: Receive only CAN identifier 0x124 (11-bit or 29-bit) + * .code = 0x00000124 + * .mask = 0x00000124 + * Example 3: Receive only CAN identifier 0x124 (11-bit) + * .code = 0x00000124 + * .mask = 0x80000124 + * Example 4: Receive only CAN identifier 0x124 (29-bit) + * .code = 0x80000124 + * .mask = 0x80000124 + */ +typedef struct t_can_settings +{ + char const * devicename; /**< CAN interface device name (pcanusb, vcan0).*/ + uint32_t channel; /**< Zero based CAN channel index. */ + tCanBaudrate baudrate; /**< Communication speed. */ + uint32_t code; /**< Code of the reception acceptance filter. */ + uint32_t mask; /**< Mask of the reception acceptance filter. */ +} tCanSettings; + +/** \brief Structure with CAN event callback functions. */ +typedef struct t_can_events +{ + /** \brief Event function that should be called when a message was transmitted. */ + void (*MsgTxed) (tCanMsg const * msg); + /** \brief Event function that should be called when a message was received. */ + void (*MsgRxed) (tCanMsg const * msg); +} tCanEvents; + +/** \brief CAN interface type. */ +typedef struct t_can_interface +{ + /** \brief Initialization of the CAN interface. */ + void (*Init) (tCanSettings const * settings); + /** \brief Terminates the CAN interface. */ + void (*Terminate) (void); + /** \brief Connects the CAN interface to the CAN bus. */ + bool (*Connect) (void); + /** \brief Disconnects the CAN interface from the CAN bus. */ + void (*Disconnect) (void); + /** \brief Submits a CAN message for transmission. */ + bool (*Transmit) (tCanMsg const * msg); + /** \brief Registers the event callback functions. */ + void (*RegisterEvents) (tCanEvents const * events); +} tCanInterface; + + +/*************************************************************************************** +* Function prototypes +****************************************************************************************/ +void CanInit(tCanSettings const * settings, tCanInterface const * const interface); +void CanTerminate(void); +bool CanConnect(void); +void CanDisconnect(void); +bool CanIsConnected(void); +bool CanTransmit(tCanMsg const * msg); +void CanRegisterEvents(tCanEvents const * events); + +#ifdef __cplusplus +} +#endif + +#endif /* CANDRIVER_H */ +/*********************************** end of candriver.h ********************************/ diff --git a/Host/Source/LibOpenBLT/serialport.h b/Host/Source/LibOpenBLT/serialport.h index 0381958a..ea3156f2 100644 --- a/Host/Source/LibOpenBLT/serialport.h +++ b/Host/Source/LibOpenBLT/serialport.h @@ -35,7 +35,7 @@ extern "C" { /**************************************************************************************** * Type definitions ****************************************************************************************/ -/** \brief Enumaration of the supported baudrates. */ +/** \brief Enumeration of the supported baudrates. */ typedef enum { SERIALPORT_BR9600 = 0, /**< 9600 bits/sec */