cancel
Showing results for 
Search instead for 
Did you mean: 

How can I display debug message in interrupt routine?

MKim.12
Associate II

Hello,

I use stm32l412b / FreeRTOS.

I use below function to display dubug message.

The MCU is halted and a watchdog reset occurs when the function below is called in interrupt routie.

​It works normally if not in interrupt

Would you let me know what is wrong?

Is there a way to display a debug message within an interrupt, even if it's not in the function below?

thanks.

*******************************************************​

int uart_debug_send(const char * fmt, ...)

{

 va_list ap;

 int rvalue;

 int retry = UART_RETRY;

 uint16_t queue_len = UART_QUEUE_SIZE;

 uint16_t item_num = 0;

 uint8_t* temp_arry;

 int is_isr = __get_IPSR();

 int re_err = 0;

 UBaseType_t uxSavedInterruptStatus;

// if (is_isr)

//  return 0;

 while (switching_lock_it_safe(uart_lock,UART_BUSY_WAIT_TIME) < 0)

 {

  if (retry <= 0)

   return -1;

  else

  {

   if(!is_isr)

    vTaskDelay(1);

   retry--;

  }

 }

 if (!is_isr)

 {

  taskENTER_CRITICAL();

  temp_arry = pvPortMalloc(sizeof(uint8_t) * UART_TX_BUF_LEN);

  taskEXIT_CRITICAL();

 }

 else

 {

  uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();

  temp_arry = pvPortMalloc(sizeof(uint8_t) * UART_TX_BUF_LEN);

  taskEXIT_CRITICAL_FROM_ISR(uxSavedInterruptStatus);

 }

 if(temp_arry <= 0)

 {

  switching_unlock_it_safe(uart_lock);

  return -1;

 }

 va_start(ap, fmt);

 rvalue = vsnprintf((char *) temp_arry,UART_TX_BUF_LEN, fmt, ap);

 va_end(ap);

  

 if(rvalue >= UART_TX_BUF_LEN)

  rvalue = UART_TX_BUF_LEN;

 do {

  queue_len = UART_QUEUE_SIZE;

  item_num = circ_buf_get_length(g_uart_queue);

  queue_len -= item_num;

  if( queue_len >= rvalue) {

   if(is_isr)

    re_err = circ_buf_put_fromISR(g_uart_queue, temp_arry, rvalue);

   else

    re_err = circ_buf_put(g_uart_queue, temp_arry, rvalue);

   if (re_err == 0) {

    vPortFree(temp_arry);

    switching_unlock_it_safe(uart_lock);

    xTimerStart(g_uart_timer, 0);

    return 0;

   }

  }

  else

  {

   // TODO.

   // Should check the uart TXE intr.

   //

   if(item_num > UART_TX_BUF_LEN) item_num = UART_TX_BUF_LEN;

   if(is_isr)

    re_err = circ_buf_pop_fromISR(g_uart_queue, g_uart->txb, item_num);

   else

    re_err = circ_buf_pop(g_uart_queue, g_uart->txb, item_num);

    

   g_uart_dev.send(g_uart, item_num);

    

   if(!is_isr)

    vTaskDelay(1);

   continue;  

  }

 }while (queue_len < rvalue);

 vPortFree(temp_arry);

 switching_unlock_it_safe(uart_lock);

 xTimerStart(g_uart_timer, 0);

 return -1;

}

1 ACCEPTED SOLUTION

Accepted Solutions
MKim.12
Associate II

Hello,

I modified my code.

It works well.

Thanks.

uint8_t temp_arry[UART_TX_BUF_LEN];

int uart_debug_send(const char * fmt, ...)

{

 va_list ap;

 int rvalue;

 int retry = UART_RETRY;

 uint16_t queue_len = UART_QUEUE_SIZE;

 uint16_t item_num = 0;

 int is_isr = __get_IPSR();

 int re_err = 0;

 BaseType_t xHigherPriorityTaskWoken = pdFALSE;

 #if defined(DEBUG_CRITICAL_SECTION_USE)

  UBaseType_t uxSavedInterruptStatus;

 #endif

 while (switching_lock_it_safe(uart_lock,UART_BUSY_WAIT_TIME) < 0)

 {

  if (retry <= 0)

   return -1;

  else

  {

   if(!is_isr)

    vTaskDelay(1);

   retry--;

  }

 }

 #if defined(DEBUG_CRITICAL_SECTION_USE)

  if (!is_isr)

  {

   taskENTER_CRITICAL();

//   taskEXIT_CRITICAL();

  }

  else

  {

   uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();

//   taskEXIT_CRITICAL_FROM_ISR(uxSavedInterruptStatus);

  }

 #endif

#if 0

 if(temp_arry <= 0)

 {

  switching_unlock_it_safe(uart_lock);

  return -1;

 }

#endif

 va_start(ap, fmt);

 rvalue = vsnprintf((char *) temp_arry,UART_TX_BUF_LEN, fmt, ap);

 va_end(ap);

  

 if(rvalue >= UART_TX_BUF_LEN)

  rvalue = UART_TX_BUF_LEN;

 do {

  queue_len = UART_QUEUE_SIZE;

  item_num = circ_buf_get_length(g_uart_queue);

  queue_len -= item_num;

  if( queue_len >= rvalue) {

   if(is_isr)

    re_err = circ_buf_put_fromISR(g_uart_queue, temp_arry, rvalue);

   else

    re_err = circ_buf_put(g_uart_queue, temp_arry, rvalue);

   if (re_err == 0) {

    switching_unlock_it_safe(uart_lock);

    if (!is_isr)

     xTimerStart(g_uart_timer, 0);

    else

     xTimerStartFromISR(g_uart_timer, &xHigherPriorityTaskWoken);

    #if defined(DEBUG_CRITICAL_SECTION_USE)

     if (!is_isr)

      taskEXIT_CRITICAL();

     else

      taskEXIT_CRITICAL_FROM_ISR(uxSavedInterruptStatus);

    #endif

    return 0;

   }

  }

  else

  {

   // TODO.

   // Should check the uart TXE intr.

   //

   if(item_num > UART_TX_BUF_LEN) item_num = UART_TX_BUF_LEN;

   if(is_isr)

    re_err = circ_buf_pop_fromISR(g_uart_queue, g_uart->txb, item_num);

   else

    re_err = circ_buf_pop(g_uart_queue, g_uart->txb, item_num);

    

   g_uart_dev.send(g_uart, item_num);

    

   if(!is_isr)

    vTaskDelay(1);

   continue;  

  }

 }while (queue_len < rvalue);

 switching_unlock_it_safe(uart_lock);

 if (!is_isr)

  xTimerStart(g_uart_timer, 0);

 else

  xTimerStartFromISR(g_uart_timer, &xHigherPriorityTaskWoken);

 #if defined(DEBUG_CRITICAL_SECTION_USE)

  if (!is_isr)

   taskEXIT_CRITICAL();

  else

   taskEXIT_CRITICAL_FROM_ISR(uxSavedInterruptStatus);

 #endif

 return -1;

}

View solution in original post

6 REPLIES 6
hs2
Senior

The code is broken in many ways. For example pvPortMalloc and vPortFree have to be implemented internally to be thread-safe. Wrapping the calls just in this function doesn't help.

In addition usually those heap functions can not be used in ISRs because usually they are not protected by a critical section disabling interrupts way too long.

Critical section are intended to be used for very short pieces of code.

In ISRs you've to use the 'FromISR' FreeRTOS API calls e.g. xTimerStartFromISR (because they can't/shouldn't block in ISRs for obvious reasons).

In general fully blown logging in ISRs (if possible at all) is often a problem and not done because of the serious runtime impact changing the behavior of application.

0693W000008xsqBQAQ.png

MKim.12
Associate II

Hello,

I modified my code.

It works well.

Thanks.

uint8_t temp_arry[UART_TX_BUF_LEN];

int uart_debug_send(const char * fmt, ...)

{

 va_list ap;

 int rvalue;

 int retry = UART_RETRY;

 uint16_t queue_len = UART_QUEUE_SIZE;

 uint16_t item_num = 0;

 int is_isr = __get_IPSR();

 int re_err = 0;

 BaseType_t xHigherPriorityTaskWoken = pdFALSE;

 #if defined(DEBUG_CRITICAL_SECTION_USE)

  UBaseType_t uxSavedInterruptStatus;

 #endif

 while (switching_lock_it_safe(uart_lock,UART_BUSY_WAIT_TIME) < 0)

 {

  if (retry <= 0)

   return -1;

  else

  {

   if(!is_isr)

    vTaskDelay(1);

   retry--;

  }

 }

 #if defined(DEBUG_CRITICAL_SECTION_USE)

  if (!is_isr)

  {

   taskENTER_CRITICAL();

//   taskEXIT_CRITICAL();

  }

  else

  {

   uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();

//   taskEXIT_CRITICAL_FROM_ISR(uxSavedInterruptStatus);

  }

 #endif

#if 0

 if(temp_arry <= 0)

 {

  switching_unlock_it_safe(uart_lock);

  return -1;

 }

#endif

 va_start(ap, fmt);

 rvalue = vsnprintf((char *) temp_arry,UART_TX_BUF_LEN, fmt, ap);

 va_end(ap);

  

 if(rvalue >= UART_TX_BUF_LEN)

  rvalue = UART_TX_BUF_LEN;

 do {

  queue_len = UART_QUEUE_SIZE;

  item_num = circ_buf_get_length(g_uart_queue);

  queue_len -= item_num;

  if( queue_len >= rvalue) {

   if(is_isr)

    re_err = circ_buf_put_fromISR(g_uart_queue, temp_arry, rvalue);

   else

    re_err = circ_buf_put(g_uart_queue, temp_arry, rvalue);

   if (re_err == 0) {

    switching_unlock_it_safe(uart_lock);

    if (!is_isr)

     xTimerStart(g_uart_timer, 0);

    else

     xTimerStartFromISR(g_uart_timer, &xHigherPriorityTaskWoken);

    #if defined(DEBUG_CRITICAL_SECTION_USE)

     if (!is_isr)

      taskEXIT_CRITICAL();

     else

      taskEXIT_CRITICAL_FROM_ISR(uxSavedInterruptStatus);

    #endif

    return 0;

   }

  }

  else

  {

   // TODO.

   // Should check the uart TXE intr.

   //

   if(item_num > UART_TX_BUF_LEN) item_num = UART_TX_BUF_LEN;

   if(is_isr)

    re_err = circ_buf_pop_fromISR(g_uart_queue, g_uart->txb, item_num);

   else

    re_err = circ_buf_pop(g_uart_queue, g_uart->txb, item_num);

    

   g_uart_dev.send(g_uart, item_num);

    

   if(!is_isr)

    vTaskDelay(1);

   continue;  

  }

 }while (queue_len < rvalue);

 switching_unlock_it_safe(uart_lock);

 if (!is_isr)

  xTimerStart(g_uart_timer, 0);

 else

  xTimerStartFromISR(g_uart_timer, &xHigherPriorityTaskWoken);

 #if defined(DEBUG_CRITICAL_SECTION_USE)

  if (!is_isr)

   taskEXIT_CRITICAL();

  else

   taskEXIT_CRITICAL_FROM_ISR(uxSavedInterruptStatus);

 #endif

 return -1;

}

gregstm
Senior III

In general, try to keep your code in an ISR as short and as simple as possible. I would set simple codes/flags in the ISR and monitor/report the messages in the main code.

MKim.12
Associate II

Of course, many messages are not printed.

It is intended to be used as a degree to understand the overall flow.

Thanks.

@MKim.12​  You forgot:

0693W000008xsqBQAQ.png"It works well"

Good news.

Now please mark the solution:

0693W000008y9fZQAQ.png