Skip to main content
Visitor II
June 30, 2022
Solved

How can I display debug message in interrupt routine?

  • June 30, 2022
  • 5 replies
  • 1714 views

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;

}

    This topic has been closed for replies.
    Best answer by MKim.12

    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;

    }

    5 replies

    Visitor II
    June 30, 2022

    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.

    Super User
    June 30, 2022

    0693W000008xsqBQAQ.png

    MKim.12AuthorAnswer
    Visitor II
    July 6, 2022

    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;

    }

    Super User
    July 6, 2022

    @MKim.12​  You forgot:

    0693W000008xsqBQAQ.png"It works well"

    Good news.

    Now please mark the solution:

    0693W000008y9fZQAQ.png

    Graduate
    July 6, 2022

    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.12Author
    Visitor II
    July 6, 2022

    Of course, many messages are not printed.

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

    Thanks.