cancel
Showing results for 
Search instead for 
Did you mean: 

stm32wb55 printf redirect not functional with WPAN debugging enabled

Richard Lowe
Senior III

Struggling with an issue with the WB55. I'm attempting to see BLE stack debugging through the UART. I've tested the redirect without WPAN being enabled and found the hardware is functional. When I enable WPAN debugging, redirect function is never called.

main.c

int __io_putchar(int ch);

int __io_putchar(int ch)
{
	/* e.g. write a character to the USART1 and Loop until the end of transmission */
	HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);

	return ch;
}

 Setting up the debugging for WPAN has been done to setup guide:
Screenshot-1.png

MX_USART1_UART_Init() isn't called in the main() function but called in the DbgOutputInit() function:

/* USER CODE BEGIN APPE_Init_1 */
#ifdef DEBUG
  DbgOutputInit();
#endif
/* USER CODE END APPE_Init_1 */

I've verified the initialization code is being called:

void MX_USART1_UART_Init(void)
{

  /* USER CODE BEGIN USART1_Init 0 */

  /* USER CODE END USART1_Init 0 */

  /* USER CODE BEGIN USART1_Init 1 */

  /* USER CODE END USART1_Init 1 */
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_8;
  huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART1_Init 2 */
  HAL_UART_Transmit(&huart1, "Start\r\n", 7, 0xff); // Works
  printf("System Start\r\n");                       // Does not work
  /* USER CODE END USART1_Init 2 */

}

Output is seen from the HAL_UART_Transmit() function but nothing from the printf call.
If I disable WPAN debugging, then printf does work.

So strange. Hoping that others might have seen this issue as well.

1 ACCEPTED SOLUTION

Accepted Solutions
Richard Lowe
Senior III

Getting a little closer, the WPAN library overrides the standard lib function for redirect:

#if (( CFG_DEBUG_TRACE_FULL != 0 ) || ( CFG_DEBUG_TRACE_LIGHT != 0 ))
#if defined(__GNUC__)  /* SW4STM32 (GCC) */
/**
 * @brief	_write: override the __write standard lib function to redirect printf to USART.
 * @PAram	handle output handle (STDIO, STDERR...)
 * @PAram	buf buffer to write
 * @PAram	bufsize buffer size
 * @PAram	...: arguments to be formatted in format string
 * @retval none
 */
size_t _write(int handle, const unsigned char * buf, size_t bufSize)
{
  return ( DbgTraceWrite(handle, buf, bufSize) );
}

Found in dbg_trace.c. It is called, but it appears that the buffer used for the CircularQueue is returning a null address:

size_t DbgTraceWrite(int handle, const unsigned char * buf, size_t bufSize)
{
  size_t chars_written = 0;
  uint8_t* buffer;

  BACKUP_PRIMASK();

  /* Ignore flushes */
  if ( handle == -1 )
  {
    chars_written = ( size_t ) 0;
  }
  /* Only allow stdout/stderr output */
  else if ( ( handle != 1 ) && ( handle != 2 ) )
  {
    chars_written = ( size_t ) - 1;
  }
  /* Parameters OK, call the low-level character output routine */
  else if (bufSize != 0)
  {
    chars_written = bufSize;
    /* If queue emepty and TX free, send directly */
    /* CS Start */

#if (DBG_TRACE_USE_CIRCULAR_QUEUE != 0)
    DISABLE_IRQ();      /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
    buffer=CircularQueue_Add(&MsgDbgTraceQueue,(uint8_t*)buf, bufSize,1);
    if (buffer && DbgTracePeripheralReady)
    {
      DbgTracePeripheralReady = RESET;
      RESTORE_PRIMASK();
      DbgOutputTraces((uint8_t*)buffer, bufSize, DbgTrace_TxCpltCallback);
    }
    else
    {
      RESTORE_PRIMASK();
    }


Should the circular queue be initialized somewhere?

View solution in original post

4 REPLIES 4
KKIM.6
Senior

if you correctly set in CubeMX, HAL_UART_Transmit() function is not neccesary.
Is there any reason to use HAL_UART_Transmit() function?

HAL_UART_Transmit() was put in place for testing. When calling HAL_UART_Transmit() it works flawlessly. When trying to use a printf redirect, while WPAN is enabled, then the redirect fails. The HAL_UART_Transmit() works either with or without WPAN being enabled.

Richard Lowe
Senior III

Getting a little closer, the WPAN library overrides the standard lib function for redirect:

#if (( CFG_DEBUG_TRACE_FULL != 0 ) || ( CFG_DEBUG_TRACE_LIGHT != 0 ))
#if defined(__GNUC__)  /* SW4STM32 (GCC) */
/**
 * @brief	_write: override the __write standard lib function to redirect printf to USART.
 * @PAram	handle output handle (STDIO, STDERR...)
 * @PAram	buf buffer to write
 * @PAram	bufsize buffer size
 * @PAram	...: arguments to be formatted in format string
 * @retval none
 */
size_t _write(int handle, const unsigned char * buf, size_t bufSize)
{
  return ( DbgTraceWrite(handle, buf, bufSize) );
}

Found in dbg_trace.c. It is called, but it appears that the buffer used for the CircularQueue is returning a null address:

size_t DbgTraceWrite(int handle, const unsigned char * buf, size_t bufSize)
{
  size_t chars_written = 0;
  uint8_t* buffer;

  BACKUP_PRIMASK();

  /* Ignore flushes */
  if ( handle == -1 )
  {
    chars_written = ( size_t ) 0;
  }
  /* Only allow stdout/stderr output */
  else if ( ( handle != 1 ) && ( handle != 2 ) )
  {
    chars_written = ( size_t ) - 1;
  }
  /* Parameters OK, call the low-level character output routine */
  else if (bufSize != 0)
  {
    chars_written = bufSize;
    /* If queue emepty and TX free, send directly */
    /* CS Start */

#if (DBG_TRACE_USE_CIRCULAR_QUEUE != 0)
    DISABLE_IRQ();      /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
    buffer=CircularQueue_Add(&MsgDbgTraceQueue,(uint8_t*)buf, bufSize,1);
    if (buffer && DbgTracePeripheralReady)
    {
      DbgTracePeripheralReady = RESET;
      RESTORE_PRIMASK();
      DbgOutputTraces((uint8_t*)buffer, bufSize, DbgTrace_TxCpltCallback);
    }
    else
    {
      RESTORE_PRIMASK();
    }


Should the circular queue be initialized somewhere?

Richard Lowe
Senior III

Success! Queue and hw_huart needs to be initialized. This can be done by calling:

 

/* USER CODE BEGIN APPE_Init_1 */
  APPD_Init();
/* USER CODE END APPE_Init_1 */

 

app_entry.c

 

void MX_APPE_Init(void)
{
  System_Init();       /**< System initialization */

  SystemPower_Config(); /**< Configure the system Power Mode */

  HW_TS_Init(hw_ts_InitMode_Full, &hrtc); /**< Initialize the TimerServer */

/* USER CODE BEGIN APPE_Init_1 */
  APPD_Init();
/* USER CODE END APPE_Init_1 */
  appe_Tl_Init();	/* Initialize all transport layers */

  /**
   * From now, the application is waiting for the ready event (VS_HCI_C2_Ready)
   * received on the system channel before starting the Stack
   * This system event is received with APPE_SysUserEvtRx()
   */
/* USER CODE BEGIN APPE_Init_2 */

/* USER CODE END APPE_Init_2 */

   return;
}