/** * @file hal_system.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 SYSTEM module. * - The system reset cause such as : * 1. Software reset * 2. Watchdog reset * 3. Power on reset * 4. Optional byte load reset * 5. Low power reset * 6. Pin reset * - The NVIC enable/disable interrupts. * - The serial number of the MCU. */ /****************************************************************************** * Include Header Files ******************************************************************************/ #include "hal_system.h" #include "string.h" /* cubeMX */ #include "main.h" /****************************************************************************** * Macro Constant Declarations ******************************************************************************/ #define HAL_SYSTEM_STACK_GUARD 0xCDu /****************************************************************************** * Module Global Variable Declarations ******************************************************************************/ static uint64 systemStepCounter_gu64; static uint64 systemPeriodMsToUs_gu64; static uint64 systemTickLoadValue_gu64; static uint32 resetStatusRegister_gu32; /****************************************************************************** * Static Function Declarations ******************************************************************************/ /****************************************************************************** * Extern Function Definitions ******************************************************************************/ uint32 HalSystemInit(void) { uint32 error_u32 = NMS_ERR_NONE; resetStatusRegister_gu32 = RCC->CSR; RCC->CSR |= RCC_CSR_RMVF; /* RMVF = ReMoVe Flag. Reset the reset cause register for the next reboot. */ systemPeriodMsToUs_gu64 = HAL_GetTickFreq() * 1000uLL; systemTickLoadValue_gu64 = (uint64)(SysTick->LOAD); systemStepCounter_gu64 = 0uLL; return error_u32; } uint32 HalSystemGetRunTimeUs(uint64 * resultUs_pu64) { static uint64 previousTimeUs_u64 = 0uLL; uint32 error_u32 = NMS_ERR_NONE; uint64 timeUs_u64 = 0uLL; /* Make a copy in case of multiple function instance at the same time */ uint64 copySystemStepCounter_u64 = systemStepCounter_gu64; /* First make a copy of the systemStepCounter to be able to check rollback further on. * Also copy current value of the System Tick Timer to avoid any dynamic update during calculation. * Then translate in microsecond & sum both timing information (step counter + tick value) to get the most * accurate resolution of the system runtime. */ uint64 copyPreviousTimeUs_u64 = previousTimeUs_u64; uint64 tickValue_u64 = (uint64)(SysTick->VAL); timeUs_u64 = copySystemStepCounter_u64 * systemPeriodMsToUs_gu64; timeUs_u64 += ((systemTickLoadValue_gu64 - tickValue_u64) * systemPeriodMsToUs_gu64) / systemTickLoadValue_gu64; /* We check here if the interruption of the systick happened during our operations and correct it accordingly */ if(timeUs_u64 <= (uint64)(systemStepCounter_gu64 * systemPeriodMsToUs_gu64)) { copySystemStepCounter_u64 = systemStepCounter_gu64; tickValue_u64 = (uint64)(SysTick->VAL); timeUs_u64 = copySystemStepCounter_u64 * systemPeriodMsToUs_gu64; timeUs_u64 += ((systemTickLoadValue_gu64 - tickValue_u64) * systemPeriodMsToUs_gu64) / systemTickLoadValue_gu64; /* The timer interruption is too fast, no time to process */ if(timeUs_u64 <= (uint64)(systemStepCounter_gu64 * systemPeriodMsToUs_gu64)) { error_u32 = NMS_ERR_OVERRUN; } } /* Should never happen if this timer interruption is set to highest priority */ if(copyPreviousTimeUs_u64 > timeUs_u64) { error_u32 = NMS_ERR_UNKNOWN; } else { *resultUs_pu64 = previousTimeUs_u64; } /* This condition has been added to prevent trouble overflow with interruptions on the medium and high optimizations options */ *resultUs_pu64 = (timeUs_u64 > previousTimeUs_u64) ? timeUs_u64 : *resultUs_pu64; return error_u32; } /* This function should not call the log, since it uses the system runtime. */ uint32 HalSystemGetRunTimeMs(uint64 * resultMs_pu64) { *resultMs_pu64 = systemStepCounter_gu64; return NMS_ERR_NONE; } void HalSystemGetSerialId(uint8 * serialIdBuffer_pu8) { uint32 serialIdW0_u32, serialIdW1_u32, serialIdW2_u32; /* Get the three parts of the UID */ serialIdW0_u32 = HAL_GetUIDw0(); serialIdW1_u32 = HAL_GetUIDw1(); serialIdW2_u32 = HAL_GetUIDw2(); /* Copy the values into the serial ID buffer */ memcpy(&serialIdBuffer_pu8[0], &serialIdW0_u32, sizeof(serialIdW0_u32)); memcpy(&serialIdBuffer_pu8[4], &serialIdW1_u32, sizeof(serialIdW1_u32)); memcpy(&serialIdBuffer_pu8[8], &serialIdW2_u32, sizeof(serialIdW2_u32)); } uint32 HalSystemGetResetCause( HalSystemResetCauseEn resetCauseSelector_en, uint32 * causes_pu32 ) { uint32 error_u32 = NMS_ERR_DEFAULT; uint32 mask_u32 = 0uL; if (causes_pu32 == NULL) { error_u32 = NMS_ERR_INVALID_POINTER; } else { switch(resetCauseSelector_en) { case HAL_SYSTEM_RESET_CAUSE_OPTION_BYTE_LOADER: mask_u32 = RCC_CSR_OBLRSTF_Msk; error_u32 = NMS_ERR_NONE; break; case HAL_SYSTEM_RESET_CAUSE_EXTERNAL_PIN_RESET: mask_u32 = RCC_CSR_PINRSTF_Msk; error_u32 = NMS_ERR_NONE; break; case HAL_SYSTEM_RESET_CAUSE_BROWNOUT_RESET: mask_u32 = RCC_CSR_BORRSTF_Msk; error_u32 = NMS_ERR_NONE; break; case HAL_SYSTEM_RESET_CAUSE_SOFTWARE_RESET: mask_u32 = RCC_CSR_SFTRSTF_Msk; error_u32 = NMS_ERR_NONE; break; case HAL_SYSTEM_RESET_CAUSE_WATCH_DOG_TIMER: mask_u32 = RCC_CSR_IWDGRSTF_Msk; error_u32 = NMS_ERR_NONE; break; case HAL_SYSTEM_RESET_CAUSE_WINDOW_WATCH_DOG: mask_u32 = RCC_CSR_WWDGRSTF_Msk; error_u32 = NMS_ERR_NONE; break; case HAL_SYSTEM_RESET_CAUSE_LOW_POWER: mask_u32 = RCC_CSR_LPWRRSTF_Msk; error_u32 = NMS_ERR_NONE; break; case HAL_SYSTEM_RESET_CAUSE_ALL_CAUSES: mask_u32 = RCC_CSR_IWDGRSTF_Msk | RCC_CSR_WWDGRSTF_Msk | RCC_CSR_SFTRSTF_Msk | RCC_CSR_PINRSTF_Msk | RCC_CSR_LPWRRSTF_Msk | RCC_CSR_BORRSTF_Msk; error_u32 = NMS_ERR_NONE; break; default: error_u32 = NMS_ERR_UNKNOWN; break; } *causes_pu32 = resetStatusRegister_gu32 & mask_u32; } return error_u32; } void HalSystemDisableInterrupts(void) { __disable_irq(); } void HalSystemEnableInterrupts(void) { __enable_irq(); } void HalSystemReset(void) { HAL_NVIC_SystemReset(); } /****************************************************************************** * Callback Function Definitions ******************************************************************************/ /** * @brief Count the number of milliseconds that elapsed since the start * * @note Function called by low-level functions of cubeMX */ void HAL_IncTick(void) { systemStepCounter_gu64++; } /** * @brief Provides a tick value in millisecond. * * @return The number of elapsed tick. */ uint32 HAL_GetTick(void) { return (uint32)systemStepCounter_gu64; }