cancel
Showing results for 
Search instead for 
Did you mean: 

xTimerChangePeriodFromISR is not working as expected in UART interrupt callback

npatil15
Associate III

Hello,

I have modbus master application (Free RTOS using CMSIS lib), in which modbus constructure init the timer_ with osTimer.

osTimerId_t ModbusMaster::createTimer_(const char* name)
{
  osTimerAttr_t attr{};
  attr.name = name;
  auto t = osTimerNew(responseReady_, osTimerOnce, this, &attr);
  return t;
}

So Modbus master send request to slave and start timer to wait for response, at start stagingLength_ = 0

__HAL_UART_ENABLE_IT(uart_, UART_IT_RXNE);
HAL_UART_Receive_IT(uart_, &mbMsg_.payload.rawResponse.rawData[stagingLength_], 1);
osStatus_t stat = osTimerStart(timer_,1500);

Now as soon as I got first character received, I will change the period of timer to 3.5 character silence time and once that silence time is expire, the time will invoke its callback as responseReady(). Here below the value 1000 is not match with silence time but keep as big as possible.

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART2)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if( xTimerChangePeriodFromISR((TimerHandle_t) timer_, pdMS_TO_TICKS( 1000 ), &xHigherPriorityTaskWoken ) != pdPASS )
{
    //this code doesnt come here, so call is not failing here
}
stagingLength_++;
__HAL_UART_ENABLE_IT(uart_, UART_IT_RXNE);
HAL_UART_Receive_IT(uart_, &mbMsg_.payload.rawResponse.rawData[stagingLength_], 1);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}

Now, ideally for modbus slave it doesnt take more than 10ms to respond. but the real issue is, if I remove the xTimerChangePeriodFromISR() then I will receive all correct data, as previously I have initialize timer with big value which give good bandwidth to receive all bytes. but if I keep the function xTimerChangePeriodFromISR() then I get random data, like, 3/6/ or 0 bytes sometime. 

Looks like the call xTimerChangePeriodFromISR() is disturbing the timer.

I have also tried below but still very inconsistence behaviour, didnt able to implement at least silence time logic.

  xTimerResetFromISR((TimerHandle_t)timer_, &xHigherPriorityTaskWoken);
  xTimerStopFromISR( (TimerHandle_t)timer_, &xHigherPriorityTaskWoken );
//////////////////////////////////////////////
// These both function passed but disturb the timer and not get complete data
  if(xTimerStopFromISR( (TimerHandle_t)timer_, &xHigherPriorityTaskWoken) != pdPASS)
  {
    int test = 0;
  }
  if(xTimerStartFromISR( (TimerHandle_t)timer_, &xHigherPriorityTaskWoken) != pdPASS)
  {
    int test = 0;
  }
//////////////////////////////////////////
  xTimerResetFromISR(timer_, &xHigherPriorityTaskWoken);
//////////////////////////////////////////
/// These below function both fails so ideally not efect on current timer and then it works///////
  osStatus_t stat;
  stat = osTimerStop(timer_);  // Stop the timer
  if(stat != osOK)
  {
    int test = 0;
  }
  stat = osTimerStart(timer_, 1/*silenceTimeoutTicks_*/);
  if(stat != osOK)
  {
    int test = 0;
  }
/////////////////////////////////

 

Help me with suggestion whats make it wrong, does it is possible that reducing timer value is not possible and which creates issue with the logic ?

Thanks,

Nitin 

3 REPLIES 3
TDK
Super User

If ARR is preloaded, which is the default behavior, you need to generate an update event after writing to ARR before the update to the timer period (ARR) takes place.

If you feel a post has answered your question, please click "Accept as Solution".

Hello,


@TDK wrote:

If ARR is preloaded, which is the default behavior, you need to generate an update event after writing to ARR before the update to the timer period (ARR) takes place.


He's speaking about the Timer service in the FreeRTOS and not about the GP timer ;)

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
avburmel
Associate III

Hello @npatil15
Try to reset timer (call xTimerResetFromISR) before changing the period.