Folks Looking for a sanity check and perhaps looking to see how others are dealing with this issue
So I had fault with a peripheral on a stm32F1xx where basically it would never timed out so that the PC would end up caught in a while() loop it effectively killed an RTOS task and caused the system to fail in a bad way.
Looking at the ST provided CMSIS HAL Driver code eg SPI transmit receive code you see references to
/* Init tickstart for timeout management*/ tickstart = HAL_GetTick();
and its used later in
if((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick()-tickstart) >= Timeout)) { errorcode = HAL_TIMEOUT; goto error; }
so in stm32f1xx_hal.c you find the systick timer code e.g.
/** * @brief Provides a tick value in millisecond. * @note This function is declared as __weak to be overwritten in case of other * implementations in user file. * @retval tick value */ __weak uint32_t HAL_GetTick(void) { return uwTick; }
I started my project using ST MXCube and in the stm32f1xx_it.c because I knew I was be going to use an RTOS eg from the Keil runtime commented out the SysTick_Handler because its also declared in the rtx libraries
/** * @brief This function handles System tick timer. */ void SysTick_Handler(void) { /* USER CODE BEGIN SysTick_IRQn 0 */ /* USER CODE END SysTick_IRQn 0 */ HAL_IncTick(); HAL_SYSTICK_IRQHandler(); /* USER CODE BEGIN SysTick_IRQn 1 */ /* USER CODE END SysTick_IRQn 1 */ }
So going back to the HAL_GetTick() function I quickly wrote this in main.c of the ST MxCube produced code
#include "RTX_Config.h" static osKernelState_t mosKernalState = osKernelInactive; static uint32_t mlFakeTick = 0; static uint32_t muwTick = 0; static uint32_t muwTickTarget = 0; uint32_t HAL_GetTick(void) { if(osKernelRunning == mosKernalState) { muwTick = osKernelGetTickCount(); return muwTick; } else { if(0 == muwTickTarget) { muwTickTarget = (SystemCoreClock/OS_TICK_FREQ); mlFakeTick = 20; // give 10 cycles or so for first starting off } else { mlFakeTick + =20; // swag at cycle count from being here last time if(mlFakeTick > muwTickTarget) { muwTick ++; mlFakeTick = 0; } } } return muwTick; }
extern SystemCoreClock in declared in system_stm32f1xx.c
OS_TICK_FREQ is declared in "RTX_Config.h"
then in the main() function
if (osKernelReady == osKernelGetState()) { mosKernalState = osKernelRunning; osKernelStart(); // Start thread execution }
So now the Perpherials now timeout if theres a fault.
Has anyone else come across this problem when using HAL CMSIS code and an RTOS where the system tick interrupt has been redirected from the HAL CMSIS code?
Anyone got any suggestions for a better work around ? eg using pointer to functions for things like osKernelGetTickCount()
Following up
If you use the RTOS get tick call it does introduce a delay on fast SPI transfers on low end micros
So after digging through the MxCube options , different micros and freeRtos implementations
I have ended up using a hardware timer as the timebase for the perpherials
eg on Cube select the pinout option find the SYS election on the Timebase option select and unused hardware timer ( I chose TIM4)
The delay between SPI transfers was reduced from 10uS to less than 2uS
On a high end device this may not be an issue.
live and learn