Skip to content

Instantly share code, notes, and snippets.

@eliaskanelis
Created May 26, 2024 22:33
Show Gist options
  • Save eliaskanelis/1e9a8f4aad8ec7686a753fc51af64a47 to your computer and use it in GitHub Desktop.
Save eliaskanelis/1e9a8f4aad8ec7686a753fc51af64a47 to your computer and use it in GitHub Desktop.
// ------------------------------------------------------------------------
#include "CddTemplate.h"
#include "Std_Types.h"
// ------------------------------------------------------------------------
/** Uncomment to enable debugging aid */
//#define CDDTEMPLATE_ENABLE_DEBUG
// ------------------------------------------------------------------------
/** \brief States for the FSM. */
typedef enum
{
/** \brief Initialisation FSM state. */
CDDTEMPLATE_STATE_INIT = 0u,
/** \brief Idle FSM state. */
CDDTEMPLATE_STATE_IDLE,
/** \brief Error FSM state. */
CDDTEMPLATE_STATE_ERROR,
/** \brief How many FSM states are there? */
CDDTEMPLATE_STATE_HOWMANY
} CddTemplate_State;
/** \brief Typedef to the runtime data. */
typedef struct CddTemplate_RunTimeData CddTemplate_RunTimeData;
/**
* \brief A function pointer type for the processing the states.
*
* \param[in,out]: pRtData The runtime data.
* \param[out]: nextState The next state.
*
* \retval True Success.
* \retval False Failure.
*/
typedef boolean( *StateFunction )( CddTemplate_RunTimeData *pRtData,
CddTemplate_State *nextState );
/** \brief Group of data with protected access. */
typedef struct
{
uint32 forcePhyDisabled;
} CddTemplate_ProtectedData;
/** \brief The runtime data. */
struct CddTemplate_RunTimeData
{
/** \brief FSM state. */
CddTemplate_State state;
/** \brief Runtime data with protected access. */
CddTemplate_ProtectedData protected;
/** \brief Pointer to the FSM state function callback list. */
const StateFunction *pStateFunctionCBList;
/** \brief Error counter. */
uint8 errCnt;
};
// ------------------------------------------------------------------------
/**
* \brief Check whether PHY is enabled.
* The check is on shared SRAM with sequencer
*
* \retval True PHY is enabled.
* \retval False PHY is disabled.
*/
static boolean HardwareIsPhyEnabled( void );
/**
* \brief Enable APIX PHY.
* The operation takes place via shared SRAM with sequencer.
*/
static void HardwareEnablePhy( void );
/**
* \brief Disable APIX PHY.
* The operation takes place via shared SRAM with sequencer.
*/
static void HardwareDisablePhy( void );
/**
* \brief Acquire/Lock shared resources.
*
* \param[in,out]: pRtData The runtime data.
*
* \retval True Success.
* \retval False Failure.
*/
static boolean Lock( CddTemplate_RunTimeData *pRtData );
/**
* \brief Release/Unlock shared resources.
* \retval True Success.
* \retval False Failure.
*/
static boolean Unlock( CddTemplate_RunTimeData *pRtData );
/**
* \brief Initialise the runtime data to default values.
*
* \param[out]: pRtData The runtime data.
*
* \retval True Success.
* \retval False Failure.
*/
static boolean InitRunTimeData( CddTemplate_RunTimeData *pRtData );
/**
* \brief Callback for processing the initialisation state.
*
* \param[in,out]: pRtData The runtime data.
* \param[out]: nextState The next state.
*
* \retval True Success.
* \retval False Failure.
*/
static boolean ProcessInitStateCB( CddTemplate_RunTimeData *pRtData,
CddTemplate_State *nextState );
/**
* \brief Callback for processing the idle state.
*
* \param[in,out]: pRtData The runtime data.
* \param[out]: nextState The next state.
*
* \retval True Success.
* \retval False Failure.
*/
static boolean ProcessIdleStateCB( CddTemplate_RunTimeData *pRtData,
CddTemplate_State *nextState );
/**
* \brief Callback for processing the error state.
*
* \param[in,out]: pRtData The runtime data.
* \param[out]: nextState The next state.
*
* \retval True Success.
* \retval False Failure.
*/
static boolean ProcessErrorStateCB( CddTemplate_RunTimeData *pRtData,
CddTemplate_State *nextState );
/**
* \brief Print information for aiding during debugging.
*
* \param[in,out]: pRtData The runtime data.
*
* \retval True Success.
* \retval False Failure.
*/
#if defined CDDTEMPLATE_ENABLE_DEBUG
static boolean PrintDebugInfo( CddTemplate_RunTimeData *pRtData );
#endif /* CDDTEMPLATE_ENABLE_DEBUG */
/**
* \brief Process the FSM.
*
* \param[in,out]: pRtData The runtime data.
*
* \retval True Success.
* \retval False Failure.
*/
static boolean ProcessStateMachine( CddTemplate_RunTimeData *pRtData );
// ------------------------------------------------------------------------
/** \brief FSM state function callback list. */
static const StateFunction g_StateFunctionCBList[CDDTEMPLATE_STATE_HOWMANY] =
{
ProcessInitStateCB, /**< State function for CDDTEMPLATE_STATE_INIT */
ProcessIdleStateCB, /**< State function for CDDTEMPLATE_STATE_IDLE */
ProcessErrorStateCB /**< State function for CDDTEMPLATE_STATE_ERROR */
};
// ------------------------------------------------------------------------
/** \brief Runtime data. */
static CddTemplate_RunTimeData cddTemplateRtData;
/** \brief Is component initialised? */
static boolean isInitialised = FALSE;
static boolean SRAM_isPHYTxEnabled = TRUE; // TODO(elias): Delete
// ------------------------------------------------------------------------
void CddTemplate_Init( void )
{
CddTemplate_RunTimeData *pRtData = &cddTemplateRtData;
boolean success = ( !isInitialised );
if( success )
{
success = InitRunTimeData( pRtData );
}
if( success )
{
isInitialised = TRUE;
}
else
{
if( pRtData->errCnt < MAX_UINT8 )
{
pRtData->errCnt++;
}
}
}
void CddTemplate_MainFunction( void )
{
CddTemplate_RunTimeData *pRtData = &cddTemplateRtData;
boolean success = ( isInitialised );
if( success )
{
success = ProcessStateMachine( pRtData );
}
if( !success )
{
if( pRtData->errCnt < MAX_UINT8 )
{
pRtData->errCnt++;
}
}
}
void CddTemplate_Deinit( void )
{
CddTemplate_RunTimeData *pRtData = &cddTemplateRtData;
boolean success = ( isInitialised );
if( success )
{
success = InitRunTimeData( pRtData );
}
if( success )
{
isInitialised = FALSE;
}
else
{
if( pRtData->errCnt < MAX_UINT8 )
{
pRtData->errCnt++;
}
}
}
Std_ReturnType CddTemplate_EnablePhy( void )
{
CddTemplate_RunTimeData *pRtData = &cddTemplateRtData;
boolean success = isInitialised;
if( success )
{
success = Lock( pRtData );
}
if( success )
{
pRtData->protected.forcePhyDisabled = FALSE;
success = Unlock( pRtData );
}
return success;
}
Std_ReturnType CddTemplate_DisablePhy( void )
{
CddTemplate_RunTimeData *pRtData = &cddTemplateRtData;
Std_ReturnType returnCode = E_NOT_OK;
if( isInitialised )
{
returnCode = E_OK;
}
if( returnCode == E_OK )
{
const boolean lockSuccess = Lock( pRtData );
if( !lockSuccess )
{
returnCode = E_NOT_OK;
}
}
if( returnCode == E_OK )
{
pRtData->protected.forcePhyDisabled = TRUE;
const boolean unlockSuccess = Unlock( pRtData );
if( !unlockSuccess )
{
returnCode = E_NOT_OK;
}
}
return returnCode;
}
Std_ReturnType CddTemplate_GetLinkStatus( boolean *isLinkUp )
{
Std_ReturnType returnCode = E_NOT_OK;
if( isInitialised && ( isLinkUp != NULL ) )
{
returnCode = E_OK;
}
if( returnCode == E_OK )
{
*isLinkUp = TRUE; // TODO(elias): Read from memory mapped register
}
return returnCode;
}
// ------------------------------------------------------------------------
static boolean HardwareIsPhyEnabled( void )
{
// TODO(elias): Check the TX PHY from SRAM variables.
boolean isPhyEnabled = SRAM_isPHYTxEnabled;
return isPhyEnabled;
}
static void HardwareEnablePhy( void )
{
// TODO(elias): Enable the TX PHY from SRAM variables.
printf( "Hardware Enable\n" );
SRAM_isPHYTxEnabled = TRUE;
}
static void HardwareDisablePhy( void )
{
// TODO(elias): Disable the TX PHY from SRAM variables.
printf( "Hardware Disable\n" );
SRAM_isPHYTxEnabled = FALSE;
}
static boolean Lock( CddTemplate_RunTimeData *pRtData )
{
boolean success = ( pRtData != NULL );
if( success )
{
// TODO(): Implement lock mechanism.
}
return success;
}
static boolean Unlock( CddTemplate_RunTimeData *pRtData )
{
boolean success = ( pRtData != NULL );
if( success )
{
// TODO(): Implement unlock mechanism.
}
return success;
}
static boolean InitRunTimeData( CddTemplate_RunTimeData *pRtData )
{
boolean success = ( pRtData != NULL );
if( success )
{
pRtData->errCnt = 0ul;
pRtData->state = CDDTEMPLATE_STATE_INIT;
pRtData->pStateFunctionCBList = g_StateFunctionCBList;
success = TRUE; // TODO(): Status from mutex init
}
if( success )
{
success = Lock( pRtData );
}
if( success )
{
/* Init the protected part of runtime data */
pRtData->protected.forcePhyDisabled = FALSE;
success = Unlock( pRtData );
}
return success;
}
static boolean ProcessInitStateCB( CddTemplate_RunTimeData *pRtData,
CddTemplate_State *nextState )
{
boolean success = ( ( pRtData != NULL ) && ( nextState != NULL ) );
if( success )
{
*nextState = CDDTEMPLATE_STATE_IDLE;
}
return success;
}
static boolean ProcessIdleStateCB( CddTemplate_RunTimeData *pRtData,
CddTemplate_State *nextState )
{
boolean success = ( ( pRtData != NULL ) && ( nextState != NULL ) );
if( success )
{
/* Rule #1: */
const boolean shouldDisablePhy = pRtData->protected.forcePhyDisabled;
if( shouldDisablePhy )
{
if( HardwareIsPhyEnabled() )
{
HardwareDisablePhy();
}
}
else
{
if( !HardwareIsPhyEnabled() )
{
HardwareEnablePhy();
}
}
*nextState = CDDTEMPLATE_STATE_IDLE;
}
return success;
}
static boolean ProcessErrorStateCB( CddTemplate_RunTimeData *pRtData,
CddTemplate_State *nextState )
{
boolean success = ( ( pRtData != NULL ) && ( nextState != NULL ) );
if( success )
{
/* TODO(elias): No logs here. Should not pollute. */
*nextState = CDDTEMPLATE_STATE_ERROR;
}
return success;
}
#if defined CDDTEMPLATE_ENABLE_DEBUG
#include <stdio.h>
static boolean PrintDebugInfo( CddTemplate_RunTimeData *pRtData )
{
boolean success = ( pRtData != NULL );
if( success )
{
printf( "---------------------------\n" );
printf( "\tState: %d\n", pRtData->state );
printf( "\tforcePhyDisabled: %d\n", pRtData->protected.forcePhyDisabled );
printf( "\terrCnt: %d\n", pRtData->errCnt );
printf( "\tisPHYEnabled SRAM %d\n", HardwareIsPhyEnabled() );
}
return success;
}
#endif /* CDDTEMPLATE_ENABLE_DEBUG */
static boolean ProcessStateMachine( CddTemplate_RunTimeData *pRtData )
{
boolean success = ( pRtData != NULL );
CddTemplate_State nextState = CDDTEMPLATE_STATE_ERROR;
if( success )
{
success = Lock( pRtData );
}
#if 1 // TODO(elias): Not feeling confident about using a function pointer when system is not stable.
StateFunction stateFunc = NULL;
if( success )
{
/* We get the state function from a list given the state */
if( pRtData->state < CDDTEMPLATE_STATE_HOWMANY )
{
stateFunc = pRtData->pStateFunctionCBList[pRtData->state];
}
/* We need to be extra sure that the function pointer is valid */
if( stateFunc == NULL )
{
success = FALSE;
}
}
if( success )
{
success = stateFunc( pRtData, &nextState );
}
#else
if( success )
{
switch( pRtData->state )
{
case CDDTEMPLATE_STATE_INIT:
{
success = ProcessInitStateCB( pRtData, &nextState );
break;
}
case CDDTEMPLATE_STATE_IDLE:
{
success = ProcessIdleStateCB( pRtData, &nextState );
break;
}
case CDDTEMPLATE_STATE_ERROR:
{
success = ProcessErrorStateCB( pRtData, &nextState );
break;
}
default:
{
success = FALSE;
break;
}
}
}
#endif
#if defined CDDTEMPLATE_ENABLE_DEBUG
if( success )
{
success = PrintDebugInfo( pRtData );
}
#endif /* CDDTEMPLATE_ENABLE_DEBUG */
if( success )
{
pRtData->state = nextState;
success = Unlock( pRtData );
}
return success;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment