/*
* codrv_threadx.c - contains OS specific function definitions
*
* Copyright (c) 2012-2020 emotas embedded communication GmbH
*-------------------------------------------------------------------
* $Id: codrv_threadx.c 38101 2021-10-01 14:41:30Z hil $
*
*
*-------------------------------------------------------------------
*
*
*/

/********************************************************************/
/**
* \file
* \brief OS specific function definitions
*
*/

/* header of standard C - libraries
---------------------------------------------------------------------------*/

/* header of project specific types
---------------------------------------------------------------------------*/
#include <gen_define.h>
#ifdef CODRV_USE_THREADX
#include <co_canopen.h>
#include <codrv_threadx.h>

/* constant definitions
---------------------------------------------------------------------------*/
#define pdMS_TO_TICKS( xTimeInMs ) ( (ULONG) ( ( (ULONG) ( xTimeInMs ) * TX_TIMER_TICKS_PER_SECOND ) / (ULONG) 1000 ))

/* local defined data types
---------------------------------------------------------------------------*/

/* list of external used functions, if not in headers
--------------------------------------------------------------------------*/
extern void codrvTimerISR(void);			/* Timer interrupt routine */

/* list of global defined functions
---------------------------------------------------------------------------*/

/* list of local defined functions
---------------------------------------------------------------------------*/
static VOID timerCallback(ULONG value);
static RET_T codrvCreateLockObjects(void);

/* external variables
---------------------------------------------------------------------------*/

/* global variables
---------------------------------------------------------------------------*/
TX_SEMAPHORE semphCANopen; 						/* CANopen task lock */
TX_SEMAPHORE semphObjDir;						/* object dictionary lock */

/* local defined variables
---------------------------------------------------------------------------*/
static TX_TIMER CANopenTimer;					/* CANopen timer object */


/***************************************************************************/
/**
* \brief codrvOSConfig - OS specific setup
*
* creates and starts the CANopen timer and
* creates objects to lock object directory and CANopen thread
*
* \returns RET_T
*/
RET_T codrvOSConfig(void)
{
RET_T retVal = RET_DRV_ERROR;

	/* create objects to lock object directory and CANopen thread */
	retVal = codrvCreateLockObjects();
	if (retVal != RET_OK)  {
		return(retVal);
	}

	/* create and setup CANopen timer */
	retVal = codrvTimerSetup(CO_TIMER_INTERVAL);
	if (retVal != RET_OK)  {
		return(retVal);
	}

	return(RET_OK);
}


/***************************************************************************/
/**
* \brief codrvTimerSetup - initialize timer
*
* Start a cyclic hardware timer to provide timing interval.
* alternatively it can be derived from an other system timer
* with the interval given from the DeviceDesigner.
*
* \returns RET_T
*/
RET_T codrvTimerSetup(
		UNSIGNED32 timerInterval
	)
{
UINT retVal = TX_TIMER_ERROR;

	/* create CANopenTimer */
	retVal = tx_timer_create(
			&CANopenTimer,
			"CANopen Timer",
			timerCallback,
			0,
			pdMS_TO_TICKS(timerInterval/1000),
			pdMS_TO_TICKS(timerInterval/1000),
			TX_NO_ACTIVATE);
	if (retVal != TX_SUCCESS)  {
		return(RET_DRV_ERROR);
	}

	/* start CANopenTimer */
	retVal = tx_timer_activate(&CANopenTimer);
	if (retVal != TX_SUCCESS)  {
		return(RET_DRV_ERROR);
	}

	return(RET_OK);
}


/***************************************************************************/
/**
* \brief timerCallback - call timer interrupt service routine
*
* \returns void
*/
static VOID timerCallback(ULONG value)
{
	(void)value;

	/* call timer interrupt service routine */
	codrvTimerISR();
}


/***************************************************************************/
/**
* \brief codrvCreateLockObjects - create lock objects
*
* Create objects to lock CANopen thread and CANopen object dictionary
*
* \returns RET_T
*/
static RET_T codrvCreateLockObjects(
		void
	)
{
UINT status;

	/* Create the semaphore used by CANopen thread.  */
	status = tx_semaphore_create(&semphCANopen, "CANopen Semaphore", 1u);
	if (status != TX_SUCCESS)  {
		return(RET_DRV_ERROR);
	}

	/* create a semaphore to lock the CANopen Thread */
	status = tx_semaphore_create(&semphObjDir, "Object Directory Semaphore", 1u);
	if (status != TX_SUCCESS)  {
		return(RET_DRV_ERROR);
	}

	return(RET_OK);
}


/***************************************************************************/
/**
* \brief codrvWaitForEvent - wait for timer or CAN event
*
* \returns void
*/
void codrvWaitForEvent(UNSIGNED32 msecTimeout)
{
	/* wait until semaphore is unlocked */
	tx_semaphore_get(&semphCANopen, msecTimeout);
}
#endif /* CODRV_USE_THREADX */
