cancel
Showing results for 
Search instead for 
Did you mean: 

For some reason SysTick gets freezed in the USART_RxCpltCallback() even when systick priority is lower than USART priority, why?

VRami.1
Associate III

Hi all, how are you?, I'm adapting some libraries for nextion HMI's to use with STM32F4 MCUs, then one of them uses the MCU timer which in my case is systick to determine if time has expired, the function is the following

/*
 * Receive string data.
 *
 * @param buffer - save string data.
 * @param len - string buffer length.
 * @param timeout - set timeout time.
 *
 * @return the length of string buffer.
 *
 */
uint16_t recvRetString(char *buffer, uint32_t len, uint32_t timeout)
{
	uint16_t ret = 0;
	_Bool str_start_flag = false;
	uint8_t cnt_0xff = 0;
	char temp[30] = {0};
	uint8_t c = 0;
	long start;
 
	uint8_t indice = 0;
 
	if(!buffer || len == 0)
	{
		sprintf(temp, "RecvRetString[%d, %s]\r\n", strlen(temp), temp);
		dbSerialPrint((uint8_t *) temp);
		return c;
	}
	start = HAL_GetTick();
	while((HAL_GetTick() - start) <= timeout)
	{
		while(indice < len)
		{
			c = buffer[indice];
			if(str_start_flag)
			{
				if(0xff == c)
				{
					cnt_0xff++;
					if(cnt_0xff >= 3)
					{
						break;
					}
				}
				else
				{
					temp[c] = (char) c;
				}
			}
			else if(NEX_RET_STRING_HEAD == c)
			{
				str_start_flag = true;
			}
			indice++;
		}
		if(cnt_0xff >= 3)
		{
			break;
		}
	}
	ret = strlen(temp);
	ret = ret > len ? len : ret;
	strncpy(buffer, temp, ret);
	sprintf((char *) temp, "RecvRetString[%d, %s]\r\n", strlen(temp), temp);
	dbSerialPrint((uint8_t *) temp);
    return ret;
}

now, I want to use that function which breaks down the content of a buffer and after that it prints it over the debug port, the problem here is that I'm calling the above function inside the HAL_UART_RxCpltCallback(...), when I use that function inside the callback then systick freezes and I think this shouldn't be happening because systick priority is -1 and USART priority is 37. In fact systick should be able to preempt the USART priority.

The priority group is configured for priority group 4 as you can see in the following code

HAL_StatusTypeDef HAL_Init(void)
{
  /* Configure Flash prefetch, Instruction cache, Data cache */ 
#if (INSTRUCTION_CACHE_ENABLE != 0U)
  __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
#endif /* INSTRUCTION_CACHE_ENABLE */
 
#if (DATA_CACHE_ENABLE != 0U)
  __HAL_FLASH_DATA_CACHE_ENABLE();
#endif /* DATA_CACHE_ENABLE */
 
#if (PREFETCH_ENABLE != 0U)
  __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
#endif /* PREFETCH_ENABLE */
 
  /* Set Interrupt Group Priority */
  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
 
  /* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */
  HAL_InitTick(TICK_INT_PRIORITY);
 
  /* Init the low level hardware */
  HAL_MspInit();
 
  /* Return function status */
  return HAL_OK;
}

so I don't know whats happening or to be more clear, what I'm doing wrong?.

Thanks in advance for all the help.

1 ACCEPTED SOLUTION

Accepted Solutions

Looks like both interrupts have a priority of 0, so they can't pre-empt each other.

USART1_IRQn (37) is the number of the interrupt, not the priority level. The second argument is the priority level.

HAL_Delay works in the main loop since it's not within an interrupt.

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

View solution in original post

6 REPLIES 6

-1 and 37 ??

Not sure it has a negative number space, and its only 4-bits. Check what gets into the NVIC register. Want Preempt/Priority to be zero.

That's some fugly code.. the self referencing sprintf()s particularly so. Not even clear why you'd need a time out.​

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Ok I made a mistake by reading -1, in HAL_Init() the  HAL_InitTick(TICK_INT_PRIORITY) has as argument TICK_INT_PRIORITY which is defined as zero, thanks for the clarification.

Following that the priority of systick is lower than the USART priority then I think systick should be preempting the rxclptcallback but it doesn't, so why?.

About the fugly code that is the way in that the library came written so I simply wanted to let it in the same form that they was writen but changing the code not compatible. The timeout is related to the arduino method "serial.available" which is used originally in those libraries, I could remove the timeout part but I need to know why systick is getting freezed inside a ISR of upper priority than it, I know there is something that I'm not seeing and I need to know what it is. To know that will avoid problems in the future.

Thanks again in advance for the help.

TDK
Guru

> Following that the priority of systick is lower than the USART priority then I think systick should be preempting the rxclptcallback but it doesn't, so why?.

Not sure you've actually determined that. As clive1 says, neither -1 and 37 are valid priority levels.

SysTick will pre-empt UART if it's a higher (numerically lower) priority. Ensure that's the case and that interrupts are enabled.

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

Hi @TDK​ , I've checked that I made a mistake about the systick interrupt number is not "-1" but 0, about the interrupt number I've checked this in the initialization code made by STMCube IDE (please see the images):

The image bellow is the systick interrupt number

0693W0000059ESqQAM.pngthe image bellow is the USART1 interrupt number

0693W0000059ESvQAM.pngthe code expander of the STM32Cube IDE shows that those interrupts are 0 and 37 for systick and usart1 interrupts, in addition, the code in the main loop has several HAL_Delay() calls and those are working correctly which means that systick interrupt is working but is not preempting the usart1 IRQ handler, so I don't know what I'm missing here.

Looks like both interrupts have a priority of 0, so they can't pre-empt each other.

USART1_IRQn (37) is the number of the interrupt, not the priority level. The second argument is the priority level.

HAL_Delay works in the main loop since it's not within an interrupt.

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

Thanks again @TDK​ , I was confused about the arguments of the Set_Priority function and yes, now I see that both interrupt has the same priority so none of them can interrupt the other, I've changed the interrupt preempt priority of the usart1 to 1 and now is working as expected.