NorthStar-Endurance-TestBench/EnduranceTestBench/nms_hal/hal_timer.c

549 lines
16 KiB
C

/**
* @file hal_timer.c
*
* @copyright Nehemis SARL reserves all rights even in the event of industrial
* property rights. We reserve all rights of disposal such as
* copying and passing on to third parties.
*
* @brief HAL layer for the TIMER module.
*
*/
/******************************************************************************
* Include Header Files
******************************************************************************/
#include "map_hal.h"
#include "hal_timer.h"
/* CubeMX */
#include "tim.h"
/******************************************************************************
* Macro constant declarations
******************************************************************************/
#define HAL_TIMER_SEC_TO_MSEC 1000000uLL /**< Number of microseconds within a second */
/******************************************************************************
* Type declarations
******************************************************************************/
typedef struct
{
uint64 timerPeriod_u64;
uint64 downCounter_u64;
} HalTimerInstance_tst;
/******************************************************************************
* Module Global Variable Declarations
******************************************************************************/
static HalTimerInstance_tst instance_gast[MAP_HAL_TIMER_NUMBER] = {0};
static void (*halTimerCallbacks[MAP_HAL_TIMER_NUMBER])(void);
/******************************************************************************
* Static Function Declarations
******************************************************************************/
static uint32 HalTimerComputeTimerPeriod(MapHalTimerModule_en timerModule_en, uint64 * timerPeriod_u64);
/******************************************************************************
* Extern Function Definition
******************************************************************************/
uint32 HalTimerInit(void)
{
uint32 error_u32 = NMS_ERR_NONE;
for(uint8 i_u8 = 0u; i_u8 < MAP_HAL_TIMER_NUMBER; i_u8++)
{
uint64 timerPeriod_u64 = 0uLL;
error_u32 = HalTimerComputeTimerPeriod((MapHalTimerModule_en)(i_u8), &timerPeriod_u64);
if (error_u32 == NMS_ERR_NONE)
{
instance_gast[i_u8].timerPeriod_u64 = timerPeriod_u64;
instance_gast[i_u8].downCounter_u64 = 0uLL;
}
}
return error_u32;
}
uint32_t HalTimerGetCounter(MapHalTimerModule_en timerModule_en)
{
TIM_HandleTypeDef *targetModule_pst = NULL;
/* Get the timer handle using MapHalTimerModule */
if (MapHalTimerModule(timerModule_en, &targetModule_pst) != NMS_ERR_NONE || targetModule_pst == NULL)
{
return 0;
}
return (uint32)(targetModule_pst->Instance->CNT);
}
void HalTimerSetCounter(MapHalTimerModule_en timerModule_en, uint32 counter_u32)
{
TIM_HandleTypeDef *targetModule_pst = NULL;
if (MapHalTimerModule(timerModule_en, &targetModule_pst) != NMS_ERR_NONE || targetModule_pst == NULL)
{
return;
}
targetModule_pst->Instance->CNT = counter_u32;
}
void HalTimerSetCompare(MapHalTimerModule_en timerModule_en, uint32 channel_u32, uint32 compareValue_32)
{
TIM_HandleTypeDef *targetModule_pst = NULL;
if (MapHalTimerModule(timerModule_en, &targetModule_pst) != NMS_ERR_NONE || targetModule_pst == NULL)
{
/* Handle the error (e.g., log it or return early) */
return;
}
switch (channel_u32)
{
case TIM_CHANNEL_1:
targetModule_pst->Instance->CCR1 = compareValue_32; break;
case TIM_CHANNEL_2:
targetModule_pst->Instance->CCR2 = compareValue_32; break;
case TIM_CHANNEL_3:
targetModule_pst->Instance->CCR3 = compareValue_32; break;
case TIM_CHANNEL_4:
targetModule_pst->Instance->CCR4 = compareValue_32; break;
#ifdef TIM_CHANNEL_5
case TIM_CHANNEL_5:
targetModule_pst->Instance->CCR5 = compareValue_32; break;
#endif
#ifdef TIM_CHANNEL_6
case TIM_CHANNEL_6:
targetModule_pst->Instance->CCR6 = compareValue_32; break;
#endif
default:
/* Invalid channel case (log or handle the error) */
break;
}
}
uint32 HalTimerGetAutoReload(MapHalTimerModule_en timerModule_en)
{
TIM_HandleTypeDef *targetModule_pst = NULL;
if (MapHalTimerModule(timerModule_en, &targetModule_pst) != NMS_ERR_NONE || targetModule_pst == NULL)
{
/* Error */
}
return (uint32)(targetModule_pst->Instance->ARR);
}
uint32 HalTimerEncoderStart(MapHalTimerModule_en timerModule_en)
{
uint32 error_u32 = NMS_ERR_DEFAULT;
HAL_StatusTypeDef halTimerStatus_en = NMS_ERR_NONE;
TIM_HandleTypeDef * targetModule_pst;
error_u32 = MapHalTimerModule(timerModule_en, &targetModule_pst);
if(error_u32 == NMS_ERR_NONE)
{
/* Start the requested timer */
halTimerStatus_en = HAL_TIM_Encoder_Start(targetModule_pst, TIM_CHANNEL_ALL);
switch(halTimerStatus_en)
{
case HAL_BUSY: error_u32 = NMS_ERR_BUSY; break;
case HAL_TIMEOUT: error_u32 = NMS_ERR_TIMEOUT; break;
case HAL_ERROR: error_u32 = NMS_ERR_UNKNOWN; break;
case HAL_OK: error_u32 = NMS_ERR_NONE; break;
default: error_u32 = NMS_ERR_UNKNOWN; break;
}
}
return error_u32;
}
uint32 HalTimerEncoderStop(MapHalTimerModule_en timerModule_en)
{
uint32 error_u32 = NMS_ERR_DEFAULT;
HAL_StatusTypeDef halTimerStatus_en = NMS_ERR_NONE;
TIM_HandleTypeDef * targetModule_pst;
error_u32 = MapHalTimerModule(timerModule_en, &targetModule_pst);
if(error_u32 == NMS_ERR_NONE)
{
/* Start the requested timer */
halTimerStatus_en = HAL_TIM_Encoder_Stop(targetModule_pst, TIM_CHANNEL_ALL);
switch(halTimerStatus_en)
{
case HAL_BUSY: error_u32 = NMS_ERR_BUSY; break;
case HAL_TIMEOUT: error_u32 = NMS_ERR_TIMEOUT; break;
case HAL_ERROR: error_u32 = NMS_ERR_UNKNOWN; break;
case HAL_OK: error_u32 = NMS_ERR_NONE; break;
default: error_u32 = NMS_ERR_UNKNOWN; break;
}
}
return error_u32;
}
uint32 HalTimerPwmStart(MapHalTimerModule_en timerModule_en, uint32 Channel_u32)
{
uint32 error_u32 = NMS_ERR_DEFAULT;
HAL_StatusTypeDef halTimerStatus_en = NMS_ERR_NONE;
TIM_HandleTypeDef * targetModule_pst;
error_u32 = MapHalTimerModule(timerModule_en, &targetModule_pst);
if(error_u32 == NMS_ERR_NONE)
{
/* Start the requested timer */
halTimerStatus_en = HAL_TIM_PWM_Start(targetModule_pst, Channel_u32);
switch(halTimerStatus_en)
{
case HAL_BUSY: error_u32 = NMS_ERR_BUSY; break;
case HAL_TIMEOUT: error_u32 = NMS_ERR_TIMEOUT; break;
case HAL_ERROR: error_u32 = NMS_ERR_UNKNOWN; break;
case HAL_OK: error_u32 = NMS_ERR_NONE; break;
default: error_u32 = NMS_ERR_UNKNOWN; break;
}
}
return error_u32;
}
uint32 HalTimerPwmStop(MapHalTimerModule_en timerModule_en, uint32 Channel_u32)
{
uint32 error_u32 = NMS_ERR_DEFAULT;
HAL_StatusTypeDef halTimerStatus_en = NMS_ERR_NONE;
TIM_HandleTypeDef * targetModule_pst;
error_u32 = MapHalTimerModule(timerModule_en, &targetModule_pst);
if(error_u32 == NMS_ERR_NONE)
{
/* Stop the requested timer */
halTimerStatus_en = HAL_TIM_PWM_Stop(targetModule_pst, Channel_u32);
switch(halTimerStatus_en)
{
case HAL_BUSY: error_u32 = NMS_ERR_BUSY; break;
case HAL_TIMEOUT: error_u32 = NMS_ERR_TIMEOUT; break;
case HAL_ERROR: error_u32 = NMS_ERR_UNKNOWN; break;
case HAL_OK: error_u32 = NMS_ERR_NONE; break;
default: error_u32 = NMS_ERR_UNKNOWN; break;
}
}
return error_u32;
}
uint32 HalTimerStart(MapHalTimerModule_en timerModule_en)
{
uint32 error_u32 = NMS_ERR_DEFAULT;
HAL_StatusTypeDef halTimerStatus_en = NMS_ERR_NONE;
TIM_HandleTypeDef * targetModule_pst;
error_u32 = MapHalTimerModule(timerModule_en, &targetModule_pst);
if(error_u32 == NMS_ERR_NONE)
{
/* Start the requested timer */
halTimerStatus_en = HAL_TIM_Base_Start_IT(targetModule_pst);
switch(halTimerStatus_en)
{
case HAL_BUSY: error_u32 = NMS_ERR_BUSY; break;
case HAL_TIMEOUT: error_u32 = NMS_ERR_TIMEOUT; break;
case HAL_ERROR: error_u32 = NMS_ERR_UNKNOWN; break;
case HAL_OK: error_u32 = NMS_ERR_NONE; break;
default: error_u32 = NMS_ERR_UNKNOWN; break;
}
}
return error_u32;
}
uint32 HalTimerStop(MapHalTimerModule_en timerModule_en)
{
uint32 error_u32 = NMS_ERR_DEFAULT;
HAL_StatusTypeDef halTimerStatus_en = NMS_ERR_NONE;
TIM_HandleTypeDef * targetModule_pst;
error_u32 = MapHalTimerModule(timerModule_en, &targetModule_pst);
if(error_u32 == NMS_ERR_NONE)
{
/* Stop the requested timer */
halTimerStatus_en = HAL_TIM_Base_Stop_IT(targetModule_pst);
switch(halTimerStatus_en)
{
case HAL_BUSY: error_u32 = NMS_ERR_BUSY; break;
case HAL_TIMEOUT: error_u32 = NMS_ERR_TIMEOUT; break;
case HAL_ERROR: error_u32 = NMS_ERR_UNKNOWN; break;
case HAL_OK: error_u32 = NMS_ERR_NONE; break;
default: error_u32 = NMS_ERR_UNKNOWN; break;
}
}
return error_u32;
}
uint32 HalTimerReloadUs(MapHalTimerModule_en timerModule_en, uint64 period_u64)
{
uint32 error_u32 = NMS_ERR_DEFAULT;
TIM_HandleTypeDef * targetModule_pst;
error_u32 = MapHalTimerModule(timerModule_en, &targetModule_pst);
if(error_u32 == NMS_ERR_NONE)
{
if(period_u64 == 0uLL)
{
error_u32 = NMS_ERR_UNKNOWN;
}
else
{
/* Compute the number of step that we need to count */
instance_gast[timerModule_en].downCounter_u64 = period_u64 / instance_gast[timerModule_en].timerPeriod_u64;
if((instance_gast[timerModule_en].downCounter_u64 * instance_gast[timerModule_en].timerPeriod_u64) < period_u64)
{
instance_gast[timerModule_en].downCounter_u64++;
}
else
{
error_u32 = NMS_ERR_UNKNOWN;
}
}
}
return error_u32;
}
uint32 HalTimerGetRemainingTimeUs(MapHalTimerModule_en timerModule_en, uint64 * remainingTime_pu64)
{
uint32 error_u32 = NMS_ERR_DEFAULT;
TIM_HandleTypeDef * targetModule_pst;
error_u32 = MapHalTimerModule(timerModule_en, &targetModule_pst);
if(error_u32 == NMS_ERR_NONE)
{
/* Add the time corresponding to the number of interruption left for this timer */
*remainingTime_pu64 = instance_gast[timerModule_en].downCounter_u64;
*remainingTime_pu64 *= instance_gast[timerModule_en].timerPeriod_u64;
}
else
{
error_u32 = NMS_ERR_UNKNOWN;
}
return error_u32;
}
uint32 HalTimerConfigureCallback(MapHalTimerModule_en timerModule_en, void (*callback_pfn)(void))
{
uint32 error_u32 = NMS_ERR_DEFAULT;
if (timerModule_en < MAP_HAL_TIMER_NUMBER )
{
halTimerCallbacks[timerModule_en] = callback_pfn;
error_u32 = NMS_ERR_NONE;
}
else
{
error_u32 = NMS_ERR_UNKNOWN;
}
return error_u32;
}
void HalTimerDeinit(MapHalTimerModule_en timerModule_en)
{
uint32 error_u32 = NMS_ERR_DEFAULT;
TIM_HandleTypeDef * targetModule_pst;
uint8 index_u8;
uint8 startIndex_u8;
uint8 iteration_u8 = 1u; /* Default to 1 loop iteration (deinit one module) */
if(timerModule_en == MAP_HAL_TIMER_NUMBER)
{
iteration_u8 = timerModule_en;
startIndex_u8 = 0u;
}
else
{
iteration_u8 += timerModule_en;
startIndex_u8 = timerModule_en;
}
for(index_u8 = startIndex_u8; index_u8 < iteration_u8; index_u8++)
{
error_u32 = MapHalTimerModule((MapHalTimerModule_en)index_u8, &targetModule_pst);
if(error_u32 == NMS_ERR_NONE)
{
HAL_TIM_Base_DeInit(targetModule_pst);
}
}
}
/******************************************************************************
* Static Function Definitions
******************************************************************************/
/**
* @brief Compute the timerPeriod of the requested timer
*
* @param timerModule_en The timer module to use
*
* @return The value of the timer period. If the timer module is invalid, the
* value returned will be 0.
*
* @note CAUTION : The part to compute the actual time frequency is target
* dependant, do not forget to update it to fit your needs.
* This affects the calculation of the timerPeriod and so
* can change the resolution that has been computed by the
* user in cubeMX
*/
static uint32 HalTimerComputeTimerPeriod(MapHalTimerModule_en timerModule_en, uint64 * timerPeriod_u64)
{
uint32 error_u32 = NMS_ERR_DEFAULT;
uint32 timerFrequency_u32 = 0uL;
TIM_HandleTypeDef * targetModule_pst;
error_u32 = MapHalTimerModule(timerModule_en, &targetModule_pst);
if(error_u32 == NMS_ERR_NONE)
{
*timerPeriod_u64 = HAL_TIMER_SEC_TO_MSEC;
*timerPeriod_u64 *= (targetModule_pst->Instance->PSC + 1UL);
*timerPeriod_u64 *= (targetModule_pst->Instance->ARR + 1UL);
*timerPeriod_u64 /= timerFrequency_u32;
}
else
{
timerPeriod_u64 = 0uLL;
error_u32 = NMS_ERR_UNKNOWN;
}
return error_u32;
}
/******************************************************************************
* Callback Function Definitions
******************************************************************************/
/**
* @brief CubeMX timer period elapsed callback
*
* @param[in] htim pointer to a TIM_HandleTypeDef structure that contains
* the configuration information for the specified TIMER.
* @return Error code in case there is one during the process.
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
MapHalTimerModule_en timerModule_en;
uint32 error_u32 = NMS_ERR_DEFAULT;
error_u32 = MapHalTimerCallback(&htim, &timerModule_en);
if (error_u32 == NMS_ERR_NONE)
{
/* Check if we reach the interrupt enough to reach the goal counter */
if(instance_gast[timerModule_en].downCounter_u64 == 0uLL)
{
if(halTimerCallbacks[timerModule_en] != NULL)
{
/* Call the user callback */
halTimerCallbacks[timerModule_en]();
}
else
{
error_u32 = NMS_ERR_UNKNOWN;
}
}
else
{
instance_gast[timerModule_en].downCounter_u64--;
}
}
else
{
error_u32 = NMS_ERR_UNKNOWN;
}
}
/**
* @brief CubeMX timer error callback
*
* @param[in] htim pointer to a TIM_HandleTypeDef structure that contains
* the configuration information for the specified TIMER.
* @return Error code in case there is one during the process.
*/
void HAL_TIM_ErrorCallback(TIM_HandleTypeDef * htim)
{
uint32 error_u32 = NMS_ERR_DEFAULT;
MapHalTimerModule_en timerModule_en;
error_u32 = MapHalTimerCallback(&htim, &timerModule_en);
if(error_u32 == NMS_ERR_NONE)
{
switch(htim->State)
{
case HAL_TIM_STATE_RESET:
error_u32 = NMS_ERR_NOT_INITIALIZED; break;
case HAL_TIM_STATE_BUSY:
error_u32 = NMS_ERR_BUSY;
break;
case HAL_TIM_STATE_TIMEOUT:
error_u32 = NMS_ERR_TIMEOUT; break;
case HAL_TIM_STATE_ERROR:
error_u32 = NMS_ERR_UNEXPECTED; break;
case HAL_TIM_STATE_READY:
error_u32 = NMS_ERR_NOT_RUNNING; break;
default:
error_u32 = NMS_ERR_UNKNOWN; break;
}
}
else
{
error_u32 = NMS_ERR_INVALID_ARGUMENT;
}
}