mirror of https://github.com/rusefi/openblt.git
Refs #316. Implemented critical section utility functions with port for Windows.
git-svn-id: https://svn.code.sf.net/p/openblt/code/trunk@315 5dc33758-31d5-4daf-9ae8-b24bf3d40d73
This commit is contained in:
parent
d1a746f454
commit
d9c14b5393
|
@ -66,7 +66,7 @@ if(WIN32)
|
|||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPLATFORM_WIN32 -D_CRT_SECURE_NO_WARNINGS")
|
||||
elseif(UNIX)
|
||||
set(PROJECT_PORT_DIR ${PROJECT_SOURCE_DIR}/port/linux)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPLATFORM_LINUX")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPLATFORM_LINUX -pthread")
|
||||
endif(WIN32)
|
||||
|
||||
# Set the output directory
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/************************************************************************************//**
|
||||
* \file port/linux/critutil.c
|
||||
* \brief Critical section utility source file.
|
||||
* \ingroup Utility
|
||||
* \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 <stdint.h> /* for standard integer types */
|
||||
#include <stdbool.h> /* for boolean type */
|
||||
#include <pthread.h> /* for posix threads */
|
||||
#include "util.h" /* Utility module */
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Local data declarations
|
||||
****************************************************************************************/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Enters a critical section. The functions UtilCriticalSectionEnter and
|
||||
** UtilCriticalSectionExit should always be used in a pair.
|
||||
**
|
||||
****************************************************************************************/
|
||||
void UtilCriticalSectionEnter(void)
|
||||
{
|
||||
} /*** end of UtilCriticalSectionEnter ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Leaves a critical section. The functions UtilCriticalSectionEnter and
|
||||
** UtilCriticalSectionExit should always be used in a pair.
|
||||
**
|
||||
****************************************************************************************/
|
||||
void UtilCriticalSectionExit(void)
|
||||
{
|
||||
} /*** end of UtilCriticalSectionExit ***/
|
||||
|
||||
|
||||
/*********************************** end of critutil.c *********************************/
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
/************************************************************************************//**
|
||||
* \file port/windows/critutil.c
|
||||
* \brief Critical section utility source file.
|
||||
* \ingroup Utility
|
||||
* \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 <assert.h> /* for assertions */
|
||||
#include <stdint.h> /* for standard integer types */
|
||||
#include <stdbool.h> /* for boolean type */
|
||||
#include <windows.h> /* for windows library */
|
||||
#include "util.h" /* Utility module */
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Local data declarations
|
||||
****************************************************************************************/
|
||||
/** \brief Flag to determine if the critical section object was already initialized. */
|
||||
static volatile bool criticalSectionInitialized = false;
|
||||
|
||||
/** \brief Crital section nesting counter. ***/
|
||||
static volatile uint32_t criticalSectionNesting;
|
||||
|
||||
/** \brief Critical section object. */
|
||||
static volatile CRITICAL_SECTION criticalSection;
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Initializes the critical section module. Should be called before the
|
||||
** Enter/Exit functions are used. It is okay to call this initialization
|
||||
** multiple times from different modules.
|
||||
**
|
||||
****************************************************************************************/
|
||||
void UtilCriticalSectionInit(void)
|
||||
{
|
||||
/* Only initialize if not yet done so previously. */
|
||||
if (!criticalSectionInitialized)
|
||||
{
|
||||
/* Initialize the critical section object. */
|
||||
InitializeCriticalSection(&criticalSection);
|
||||
/* Reset nesting counter. */
|
||||
criticalSectionNesting = 0;
|
||||
/* Set initialized flag. */
|
||||
criticalSectionInitialized = true;
|
||||
}
|
||||
} /*** end of UtilCriticalSectionInit ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Terminates the critical section module. Should be called once critical
|
||||
** sections are no longer needed. Typically called from another module's
|
||||
** termination function that also initialized it. It is okay to call this
|
||||
** termination multiple times from different modules.
|
||||
**
|
||||
****************************************************************************************/
|
||||
void UtilCriticalSectionTerminate(void)
|
||||
{
|
||||
/* Only terminate if it was initialized. */
|
||||
if (criticalSectionInitialized)
|
||||
{
|
||||
/* Reset the initialized flag. */
|
||||
criticalSectionInitialized = false;
|
||||
/* Reset nesting counter. */
|
||||
criticalSectionNesting = 0;
|
||||
/* Delete the critical section object. */
|
||||
DeleteCriticalSection(&criticalSection);
|
||||
}
|
||||
} /*** end of UtilCriticalSectionTerminate ***/
|
||||
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Enters a critical section. The functions UtilCriticalSectionEnter and
|
||||
** UtilCriticalSectionExit should always be used in a pair.
|
||||
**
|
||||
****************************************************************************************/
|
||||
void UtilCriticalSectionEnter(void)
|
||||
{
|
||||
/* Check initialization. */
|
||||
assert(criticalSectionInitialized);
|
||||
|
||||
/* Only continue if actually initialized. */
|
||||
if (criticalSectionInitialized)
|
||||
{
|
||||
/* Enter the critical section if not already entered. */
|
||||
if (criticalSectionNesting == 0)
|
||||
{
|
||||
EnterCriticalSection(&criticalSection);
|
||||
}
|
||||
/* Increment nesting counter. */
|
||||
criticalSectionNesting++;
|
||||
}
|
||||
} /*** end of UtilCriticalSectionEnter ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Leaves a critical section. The functions UtilCriticalSectionEnter and
|
||||
** UtilCriticalSectionExit should always be used in a pair.
|
||||
**
|
||||
****************************************************************************************/
|
||||
void UtilCriticalSectionExit(void)
|
||||
{
|
||||
/* Check initialization. */
|
||||
assert(criticalSectionInitialized);
|
||||
|
||||
/* Only continue if actually initialized. */
|
||||
if (criticalSectionInitialized)
|
||||
{
|
||||
/* Sanity check. */
|
||||
assert(criticalSectionNesting > 0);
|
||||
|
||||
/* Decrement nesting counter if it is valid. */
|
||||
if (criticalSectionNesting > 0)
|
||||
{
|
||||
criticalSectionNesting--;
|
||||
/* Leave the critical section. */
|
||||
if (criticalSectionNesting == 0)
|
||||
{
|
||||
LeaveCriticalSection(&criticalSection);
|
||||
}
|
||||
}
|
||||
}
|
||||
} /*** end of UtilCriticalSectionExit ***/
|
||||
|
||||
|
||||
/*********************************** end of critutil.c *********************************/
|
||||
|
|
@ -49,6 +49,10 @@ uint32_t UtilChecksumCrc32Calculate(uint8_t const * data, uint32_t len);
|
|||
bool UtilFileExtractFilename(char const * fullFilename, char * filenameBuffer);
|
||||
uint32_t UtilTimeGetSystemTimeMs(void);
|
||||
void UtilTimeDelayMs(uint16_t delay);
|
||||
void UtilCriticalSectionInit(void);
|
||||
void UtilCriticalSectionTerminate(void);
|
||||
void UtilCriticalSectionEnter(void);
|
||||
void UtilCriticalSectionExit(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -237,16 +237,16 @@ static bool XcpLoaderStart(void)
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Check if a connection with the target could be made within the finite amount
|
||||
* of retries.
|
||||
*/
|
||||
if (!xcpConnected)
|
||||
{
|
||||
/* Disconnect the transport layer again. */
|
||||
xcpSettings.transport->Disconnect();
|
||||
/* Update the result. */
|
||||
result = false;
|
||||
/* Check if a connection with the target could be made within the finite amount
|
||||
* of retries.
|
||||
*/
|
||||
if (!xcpConnected)
|
||||
{
|
||||
/* Disconnect the transport layer again. */
|
||||
xcpSettings.transport->Disconnect();
|
||||
/* Update the result. */
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Place the target in programming mode if connected. */
|
||||
|
|
|
@ -48,12 +48,16 @@
|
|||
/****************************************************************************************
|
||||
* Function prototypes
|
||||
****************************************************************************************/
|
||||
/* Transport layer module functions. */
|
||||
static void XcpTpCanInit(void const * settings);
|
||||
static void XcpTpCanTerminate(void);
|
||||
static bool XcpTpCanConnect(void);
|
||||
static void XcpTpCanDisconnect(void);
|
||||
static bool XcpTpCanSendPacket(tXcpTransportPacket const * txPacket,
|
||||
tXcpTransportPacket * rxPacket, uint16_t timeout);
|
||||
/* CAN event functions. */
|
||||
static void XcpTpCanEventMessageTransmitted(tCanMsg const * msg);
|
||||
static void XcpTpCanEventMessageReceived(tCanMsg const * msg);
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
|
@ -69,6 +73,20 @@ static const tXcpTransport canTransport =
|
|||
XcpTpCanSendPacket
|
||||
};
|
||||
|
||||
/** \brief CAN driver event functions. */
|
||||
static const tCanEvents canEvents =
|
||||
{
|
||||
XcpTpCanEventMessageTransmitted,
|
||||
XcpTpCanEventMessageReceived
|
||||
};
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Local data declarations
|
||||
****************************************************************************************/
|
||||
/** \brief The settings to use in this transport layer. */
|
||||
static tXcpTpCanSettings tpCanSettings;
|
||||
|
||||
|
||||
/***********************************************************************************//**
|
||||
** \brief Obtains a pointer to the transport layer structure, so that it can be
|
||||
|
@ -90,15 +108,103 @@ tXcpTransport const * XcpTpCanGetTransport(void)
|
|||
****************************************************************************************/
|
||||
static void XcpTpCanInit(void const * settings)
|
||||
{
|
||||
char * canDeviceName;
|
||||
tCanInterface const * canInterface = NULL;
|
||||
tCanSettings canSettings;
|
||||
|
||||
/* Reset transport layer settings. */
|
||||
tpCanSettings.device = NULL;
|
||||
tpCanSettings.channel = 0;
|
||||
tpCanSettings.baudrate = 500000;
|
||||
tpCanSettings.transmitId = 0x667;
|
||||
tpCanSettings.receiveId = 0x7e1;
|
||||
tpCanSettings.useExtended = false;
|
||||
|
||||
/* This module uses critical sections so initialize them. */
|
||||
UtilCriticalSectionInit();
|
||||
|
||||
/* Check parameters. */
|
||||
assert(settings != NULL);
|
||||
|
||||
/* Only continue with valid parameters. */
|
||||
if (settings != NULL) /*lint !e774 */
|
||||
{
|
||||
/* ##Vg TODO Extract and set the pointer to the CAN interface to link. */
|
||||
/* Shallow copy the transport layer settings for layer usage. */
|
||||
tpCanSettings = *((tXcpTpCanSettings *)settings);
|
||||
/* The device name is a pointer and it is not gauranteed that it stays valid so we need
|
||||
* to deep copy this one. note the +1 for '\0' in malloc.
|
||||
*/
|
||||
assert(((tXcpTpCanSettings *)settings)->device != NULL);
|
||||
if (((tXcpTpCanSettings *)settings)->device != NULL) /*lint !e774 */
|
||||
{
|
||||
canDeviceName = malloc(strlen(((tXcpTpCanSettings *)settings)->device) + 1);
|
||||
assert(canDeviceName != NULL);
|
||||
if (canDeviceName != NULL) /*lint !e774 */
|
||||
{
|
||||
strcpy(canDeviceName, ((tXcpTpCanSettings *)settings)->device);
|
||||
tpCanSettings.device = canDeviceName;
|
||||
|
||||
/* Determine the pointer to the correct CAN interface, based on the specified
|
||||
* device name.
|
||||
*/
|
||||
#if defined(PLATFORM_WIN32)
|
||||
if (strcmp(tpCanSettings.device, "peak_pcanusb") == 0)
|
||||
{
|
||||
canInterface = PCanUsbGetInterface();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ##Vg TODO Implement CAN module initialization. */
|
||||
|
||||
/* Convert the transport layer settings to CAN driver settings. */
|
||||
canSettings.devicename = tpCanSettings.device;
|
||||
canSettings.channel = tpCanSettings.channel;
|
||||
switch (tpCanSettings.baudrate)
|
||||
{
|
||||
case 1000000:
|
||||
canSettings.baudrate = CAN_BR1M;
|
||||
break;
|
||||
case 800000:
|
||||
canSettings.baudrate = CAN_BR800K;
|
||||
break;
|
||||
case 500000:
|
||||
canSettings.baudrate = CAN_BR500K;
|
||||
break;
|
||||
case 250000:
|
||||
canSettings.baudrate = CAN_BR250K;
|
||||
break;
|
||||
case 125000:
|
||||
canSettings.baudrate = CAN_BR125K;
|
||||
break;
|
||||
case 100000:
|
||||
canSettings.baudrate = CAN_BR100K;
|
||||
break;
|
||||
case 50000:
|
||||
canSettings.baudrate = CAN_BR50K;
|
||||
break;
|
||||
case 20000:
|
||||
canSettings.baudrate = CAN_BR20K;
|
||||
break;
|
||||
case 10000:
|
||||
canSettings.baudrate = CAN_BR10K;
|
||||
break;
|
||||
default:
|
||||
/* Default to 500 kbits/sec in case an unsupported baudrate was specified. */
|
||||
canSettings.baudrate = CAN_BR500K;
|
||||
break;
|
||||
}
|
||||
/* Configure the reception acceptance filter to receive only one CAN identifier. */
|
||||
canSettings.code = tpCanSettings.receiveId;
|
||||
if (tpCanSettings.useExtended)
|
||||
{
|
||||
canSettings.code |= CAN_MSG_EXT_ID_MASK;
|
||||
}
|
||||
canSettings.mask = 0x9fffffff;
|
||||
/* Initialize the CAN driver. */
|
||||
CanInit(&canSettings, canInterface);
|
||||
/* Register CAN event functions. */
|
||||
CanRegisterEvents(&canEvents);
|
||||
} /*** end of XcpTpCanInit ***/
|
||||
|
||||
|
||||
|
@ -108,7 +214,22 @@ static void XcpTpCanInit(void const * settings)
|
|||
****************************************************************************************/
|
||||
static void XcpTpCanTerminate(void)
|
||||
{
|
||||
/* ##Vg TODO Implement. */
|
||||
/* Terminate the CAN driver. */
|
||||
CanTerminate();
|
||||
/* Release memory that was allocated for storing the device name. */
|
||||
if (tpCanSettings.device != NULL)
|
||||
{
|
||||
free((char *)tpCanSettings.device);
|
||||
}
|
||||
/* Reset transport layer settings. */
|
||||
tpCanSettings.device = NULL;
|
||||
tpCanSettings.channel = 0;
|
||||
tpCanSettings.baudrate = 500000;
|
||||
tpCanSettings.transmitId = 0x667;
|
||||
tpCanSettings.receiveId = 0x7e1;
|
||||
tpCanSettings.useExtended = false;
|
||||
/* This module used critical sections so terminate them. */
|
||||
UtilCriticalSectionTerminate();
|
||||
} /*** end of XcpTpCanTerminate ***/
|
||||
|
||||
|
||||
|
@ -121,7 +242,11 @@ static bool XcpTpCanConnect(void)
|
|||
{
|
||||
bool result = false;
|
||||
|
||||
/* ##Vg TODO Implement. */
|
||||
/* Connect to the CAN driver. */
|
||||
if (CanConnect())
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
|
@ -134,7 +259,8 @@ static bool XcpTpCanConnect(void)
|
|||
****************************************************************************************/
|
||||
static void XcpTpCanDisconnect(void)
|
||||
{
|
||||
/* ##Vg TODO Disconnect from the CAN bus. */
|
||||
/* Disconnect from the CAN driver. */
|
||||
CanDisconnect();
|
||||
} /*** end of XcpTpCanDisconnect ***/
|
||||
|
||||
|
||||
|
@ -152,7 +278,9 @@ static bool XcpTpCanSendPacket(tXcpTransportPacket const * txPacket,
|
|||
tXcpTransportPacket * rxPacket, uint16_t timeout)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
tCanMsg canMsg;
|
||||
uint32_t responseTimeoutTime = 0;
|
||||
|
||||
/* Check parameters. */
|
||||
assert(txPacket != NULL);
|
||||
assert(rxPacket != NULL);
|
||||
|
@ -160,11 +288,85 @@ static bool XcpTpCanSendPacket(tXcpTransportPacket const * txPacket,
|
|||
/* Only continue with valid parameters. */
|
||||
if ( (txPacket != NULL) && (rxPacket != NULL) ) /*lint !e774 */
|
||||
{
|
||||
/* ##Vg TODO Implement. */
|
||||
/* Only continue if data length fits in a CAN message and the CAN bus is not in error
|
||||
* state.
|
||||
*/
|
||||
if ( ((txPacket->len <= CAN_MSG_MAX_LEN)) && (!CanIsBusError()) )
|
||||
{
|
||||
/* Set result value to okay and only change it from now on if an error occurred. */
|
||||
result = true;
|
||||
/* Store the packet data into a CAN message. */
|
||||
canMsg.id = tpCanSettings.transmitId;
|
||||
if (tpCanSettings.useExtended)
|
||||
{
|
||||
canMsg.id |= CAN_MSG_EXT_ID_MASK;
|
||||
}
|
||||
canMsg.dlc = txPacket->len;
|
||||
for (uint8_t idx = 0; idx < canMsg.dlc; idx++)
|
||||
{
|
||||
canMsg.data[idx] = txPacket->data[idx];
|
||||
}
|
||||
/* Submit the packet for transmission on the CAN bus. */
|
||||
if (!CanTransmit(&canMsg))
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
/* Only continue if the transmission was successful. */
|
||||
if (result)
|
||||
{
|
||||
/* Determine timeout time for the response packet. */
|
||||
responseTimeoutTime = UtilTimeGetSystemTimeMs() + timeout;
|
||||
/* Poll with timeout detection to receive the response packet as a CAN message
|
||||
* on the CAN bus.
|
||||
*/
|
||||
while (UtilTimeGetSystemTimeMs() < responseTimeoutTime)
|
||||
{
|
||||
/* ##Vg TODO Implement packet reception. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of XcpTpCanSendPacket ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief CAN driver event callback function that gets called each time a CAN
|
||||
** message was transmitted.
|
||||
** \param msg Pointer to the transmitted CAN message.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static void XcpTpCanEventMessageTransmitted(tCanMsg const * msg)
|
||||
{
|
||||
(void)msg;
|
||||
|
||||
/* Nothing needs to be done here for now. Added for possible future expansions. */
|
||||
} /*** end of XcpTpCanEventMessageTransmitted ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief CAN driver event callback function that gets called each time a CAN
|
||||
** message was received.
|
||||
** \param msg Pointer to the received CAN message.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static void XcpTpCanEventMessageReceived(tCanMsg const * msg)
|
||||
{
|
||||
/* Determine CAN identifier for receiving XCP commands via CAN. */
|
||||
uint32_t tpCanRxId = tpCanSettings.receiveId;
|
||||
if (tpCanSettings.useExtended)
|
||||
{
|
||||
tpCanRxId |= CAN_MSG_EXT_ID_MASK;
|
||||
}
|
||||
|
||||
/* Check if the identifier matches the one for XCP on CAN. */
|
||||
if (msg->id == tpCanRxId)
|
||||
{
|
||||
/* ##Vg TODO process CAN message reception. */
|
||||
}
|
||||
} /*** end of XcpTpCanEventMessageReceived ***/
|
||||
|
||||
|
||||
/*********************************** end of xcptpcan.c *********************************/
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue