cancel
Showing results for 
Search instead for 
Did you mean: 

USART2_IRQHandler not called when using SEGGER_SYSVIEW_PrintfTarget.

Kaveh
Associate III

Hello,

I am learning about RTOS and SEGGER tracing with a NucleoF7222ZE. For some reasons the UART2 IRQ handler is never called to get SEGGER continuous recoding. In the main I only call SEGGER_SYSVIEW_PrintfTarget like bellow.

int main(void)
{
  /* USER CODE BEGIN 1 */
	TaskHandle_t Task_RedLED_Handle;
 
	BaseType_t TaskStatus;
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART3_UART_Init();
  MX_USB_OTG_FS_PCD_Init();
  MX_USART2_UART_Init();
 
  // CYCLCNT enable
  DWT_CTRL |= ( 1 << 0);
 
  // Initializing SEGGER UART
  SEGGER_UART_init(115200);
 
  // Starting SEGGER SYSVIEW
  SEGGER_SYSVIEW_Conf();
 
  //  Creating Tasks
  TaskStatus = xTaskCreate(Task_RedLED_Handler, "RedLED", 100, "Red LED TASK", 1, &Task_RedLED_Handle);
  configASSERT(TaskStatus == pdPASS);
 
  // Start FreeRTOS scheduler
  vTaskStartScheduler();
 
  while (1)
  {
  }
}

static void Task_RedLED_Handler(void* parameters)
{
	while(1)
	{
		// Needed for SEGGER print function
		snprintf(user_msg, 100,"%s\n", (char*)parameters);
		// SEGGER print function
		SEGGER_SYSVIEW_PrintfTarget(user_msg);
 
		//SEGGER_SYSVIEW_PrintfTarget("Toggling Red LED");
		HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);
 
		// 800 system tickes -> needs to be converted to ms
		vTaskDelay(800);
		HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);
		vTaskDelay(800);
	}
}

Here is definition of UART2_IRQHandler.

void USART2_IRQHandler(void) {
  int UsartStatus;
  uint8_t v;
  int r;
 
  UsartStatus = USART_SR;                              // Examine status register
  if (UsartStatus & (1 << USART_RXNE)) {               // Data received?
    v = USART_RDR;                                     // Read data
    if ((UsartStatus & USART_RX_ERROR_FLAGS) == 0) {   // Only process data if no error occurred
      (void)v;                                         // Avoid warning in BTL
      if (_cbOnRx) {
        _cbOnRx(v);
      }
    }
  }
  if (UsartStatus & (1 << USART_TXE)) {                // Tx (data register) empty? => Send next character Note: Shift register may still hold a character that has not been sent yet.
    //
    // Under special circumstances, (old) BTL of Flasher does not wait until a complete string has been sent via UART,
    // so there might be an TxE interrupt pending *before* the FW had a chance to set the callbacks accordingly which would result in a NULL-pointer call...
    // Therefore, we need to check if the function pointer is valid.
    //
    if (_cbOnTx == NULL) {  // No callback set? => Nothing to do...
      return;
    }
    r = _cbOnTx(&v);
    if (r == 0) {                          // No more characters to send ?
      USART_CR1 &= ~(1UL << USART_TXEIE);  // Disable further tx interrupts
    } else {
      USART_SR;      // Makes sure that "transmission complete" flag in USART_SR is reset to 0 as soon as we write USART_DR. If USART_SR is not read before, writing USART_DR does not clear "transmission complete". See STM32F4 USART documentation for more detailed description.
      USART_TDR = v;  // Start transmission by writing to data register
    }
  }
}

1 ACCEPTED SOLUTION

Accepted Solutions
Kaveh
Associate III

My problem wasn't defining and using UART. It was using USART to print traces on SEGGER View. I managed to make it work for NucleF7222ZE by changing the segger_usart.c significantly. A lot of changes were required for using UART3. Few point: UART shouldn't be enabled in the pinout configuration. I can't attached complete code here, but pasting the sections I remember I made changes to.

#define OS_FSYS 168000000L   // MCU core frequency of Flasher ARM
 
 
 
#define RCC_BASE_ADDR       0x40023800
 
#define OFF_AHB1ENR         0x30        // AHB1 peripheral clock enable register
#define OFF_APB1ENR         0x40        // APB1 peripheral clock enable register
#define OFF_APB2ENR         0x44        // APB2 peripheral clock enable register
 
#define RCC_AHB1ENR         *(volatile uint32_t*)(RCC_BASE_ADDR + OFF_AHB1ENR)
#define RCC_APB1ENR         *(volatile uint32_t*)(RCC_BASE_ADDR + OFF_APB1ENR)
#define RCC_APB2ENR         *(volatile uint32_t*)(RCC_BASE_ADDR + OFF_APB2ENR)
 
#define GPIOA_BASE_ADDR     0x40020000
#define GPIOD_BASE_ADDR     0x40020C00
 
#define OFF_MODER           0x00        // GPIOx_MODER    (GPIO port mode register)
#define OFF_OTYPER          0x04        // GPIOx_OTYPER   (GPIO port output type register)
#define OFF_OSPEEDR         0x08        // GPIOx_OSPEEDR  (GPIO port output speed register)
#define OFF_PUPDR           0x0C        // GPIOx_PUPDR    (GPIO port pull-up/pull-down register)
#define OFF_IDR             0x10        // GPIOx_IDR      (GPIO port input data register)
#define OFF_ODR             0x14        // GPIOx_ODR      (GPIO port output data register)
#define OFF_BSRR            0x18        // GPIOx_BSRR     (GPIO port bit set/reset register)
#define OFF_LCKR            0x1C        // GPIOx_LCKR     (GPIO port configuration lock register)
#define OFF_AFRL            0x20        // GPIOx_AFRL     (GPIO alternate function low register)
#define OFF_AFRH            0x24        // GPIOx_AFRH     (GPIO alternate function high register)
 
#define USART1_BASE_ADDR    0x40011000
#define USART2_BASE_ADDR    0x40004400
#define USART3_BASE_ADDR	0x40004800
 
#define OFF_SR              0x1C        // Status register
#define OFF_RDR             0x24        // Receive Data register
#define OFF_TDR             0x28        // Transmit Data register
#define OFF_BRR             0x0C        // Baudrate register
#define OFF_CR1             0x00        // Control register 1
#define OFF_CR2             0x04        // Control register 2
#define OFF_CR3             0x08        // Control register 3
 
 
#define UART_BASECLK        OS_FSYS / 4       // USART3 runs on APB1 clock
#define GPIO_BASE_ADDR      GPIOD_BASE_ADDR
#define USART_BASE_ADDR     USART3_BASE_ADDR
#define GPIO_UART_TX_BIT    9                // USART3 TX: Pin PD9
#define GPIO_UART_RX_BIT    8                 // USART3 RX: Pin PD8
#define USART_IRQn          USART3_IRQn
 
#define GPIO_MODER          *(volatile uint32_t*)(GPIO_BASE_ADDR + OFF_MODER)
#define GPIO_AFRH           *(volatile uint32_t*)(GPIO_BASE_ADDR + OFF_AFRH)
#define GPIO_AFRL           *(volatile uint32_t*)(GPIO_BASE_ADDR + OFF_AFRL)
 
#define USART_SR            *(volatile uint32_t*)(USART_BASE_ADDR + OFF_SR)
#define USART_RDR           *(volatile uint32_t*)(USART_BASE_ADDR + OFF_RDR)
#define USART_TDR           *(volatile uint32_t*)(USART_BASE_ADDR + OFF_TDR)
#define USART_BRR           *(volatile uint32_t*)(USART_BASE_ADDR + OFF_BRR)
#define USART_CR1           *(volatile uint32_t*)(USART_BASE_ADDR + OFF_CR1)
#define USART_CR2           *(volatile uint32_t*)(USART_BASE_ADDR + OFF_CR2)
#define USART_CR3           *(volatile uint32_t*)(USART_BASE_ADDR + OFF_CR3)
void USART3_IRQHandler(void) {
  int UsartStatus;
  uint8_t v;
  int r;
 
  UsartStatus = USART_SR;                              // Examine status register
  if (UsartStatus & (1 << USART_RXNE)) {               // Data received?
    v = USART_RDR;                                     // Read data
    if ((UsartStatus & USART_RX_ERROR_FLAGS) == 0) {   // Only process data if no error occurred
      (void)v;                                         // Avoid warning in BTL
      if (_cbOnRx) {
        _cbOnRx(v);
      }
    }
  }
  if (UsartStatus & (1 << USART_TXE)) {                // Tx (data register) empty? => Send next character Note: Shift register may still hold a character that has not been sent yet.
    //
    // Under special circumstances, (old) BTL of Flasher does not wait until a complete string has been sent via UART,
    // so there might be an TxE interrupt pending *before* the FW had a chance to set the callbacks accordingly which would result in a NULL-pointer call...
    // Therefore, we need to check if the function pointer is valid.
    //
    if (_cbOnTx == NULL) {  // No callback set? => Nothing to do...
      return;
    }
    r = _cbOnTx(&v);
    if (r == 0) {                          // No more characters to send ?
      USART_CR1 &= ~(1UL << USART_TXEIE);  // Disable further tx interrupts
    } else {
      USART_SR;      // Makes sure that "transmission complete" flag in USART_SR is reset to 0 as soon as we write USART_DR. If USART_SR is not read before, writing USART_DR does not clear "transmission complete". See STM32F4 USART documentation for more detailed description.
      USART_TDR = v;  // Start transmission by writing to data register
    }
  }
}
void HIF_UART_Init(uint32_t Baudrate, UART_ON_TX_FUNC_P cbOnTx, UART_ON_RX_FUNC_P cbOnRx) {
  uint32_t v;
  uint32_t Div;
  //
  // Configure USART RX/TX pins for alternate function AF7
  //
  RCC_APB1ENR |= (1 <<  18);        // Enable USART3 clock
  RCC_AHB1ENR |= (1 <<  3);        // Enable IO port A clock
  v  = GPIO_AFRL;
  v &= ~((15UL << ((GPIO_UART_TX_BIT) << 2)) | (15UL << ((GPIO_UART_RX_BIT) << 2)));
  v |=   ((7UL << ((GPIO_UART_TX_BIT) << 2)) | (7UL << ((GPIO_UART_RX_BIT) << 2)));
  GPIO_AFRL = v;
  //
  // Configure USART RX/TX pins for alternate function usage
  //
  v  = GPIO_MODER;
  v &= ~((3UL << (GPIO_UART_TX_BIT << 1)) | (3UL << (GPIO_UART_RX_BIT << 1)));
  v |=  ((2UL << (GPIO_UART_TX_BIT << 1)) | (2UL << (GPIO_UART_RX_BIT << 1)));         // PA10: alternate function
  GPIO_MODER = v;
  //
  // Initialize USART
  //
  USART_CR1 = 0
            | (1 << 15)                         // OVER8  = 1; Oversampling by 8
            | (1 << 0)                         	// UE     = 1; USART enabled
            | (0 << 12)                         // M      = 0; Word length is 1 start bit, 8 data bits
			| (0 << 28)
            | (0 << 10)                         // PCE    = 0; No parity control
            | (1 <<  5)                         // RXNEIE = 1; RXNE interrupt enabled
            | (1 <<  3)                         // TE     = 1; Transmitter enabled
            | (1 <<  2)                         // RE     = 1; Receiver enabled
            ;
  USART_CR2 = 0
            | (0 << 12)                         // STOP = 00b; 1 stop bit
			| (0 << 13)
            ;
  USART_CR3 = 0
            | (0 << 11)                         // ONEBIT = 0; Three sample bit method
            | (1 <<  7)                         // DMAT   = 1; DMA for transmitter enabled
            ;
  //
  // Set baudrate
  //
  Div = Baudrate * 8;                       // We use 8x oversampling.
  Div = ((2 * (UART_BASECLK)) / Div) + 1;   // Calculate divider for baudrate and round it correctly. This is necessary to get a tolerance as small as possible.
  Div = Div / 2;
  if (Div > 0xFFF) {
    Div = 0xFFF;        // Limit to 12 bit (mantissa in BRR)
  }
  if (Div >= 1) {
    USART_BRR = 0xFFF0 & (Div << 4);    // Use only mantissa of fractional divider
  }
  //
  // Setup callbacks which are called by ISR handler and enable interrupt in NVIC
  //
  _cbOnRx = cbOnRx;
  _cbOnTx = cbOnTx;
  NVIC_SetPriority(USART_IRQn, 6);  // Highest prio, so it is not disabled by embOS
  NVIC_EnableIRQ(USART_IRQn);
}

View solution in original post

3 REPLIES 3

Hello @Kaveh​ ,

You can refer to this example and check the configuration of the UART.

As well, make sure you have configured the NVIC correctly, this may be the reason why the IRQ handler of the UART2 is never called.

BeST Regards,

Walid

Kaveh
Associate III

My problem wasn't defining and using UART. It was using USART to print traces on SEGGER View. I managed to make it work for NucleF7222ZE by changing the segger_usart.c significantly. A lot of changes were required for using UART3. Few point: UART shouldn't be enabled in the pinout configuration. I can't attached complete code here, but pasting the sections I remember I made changes to.

#define OS_FSYS 168000000L   // MCU core frequency of Flasher ARM
 
 
 
#define RCC_BASE_ADDR       0x40023800
 
#define OFF_AHB1ENR         0x30        // AHB1 peripheral clock enable register
#define OFF_APB1ENR         0x40        // APB1 peripheral clock enable register
#define OFF_APB2ENR         0x44        // APB2 peripheral clock enable register
 
#define RCC_AHB1ENR         *(volatile uint32_t*)(RCC_BASE_ADDR + OFF_AHB1ENR)
#define RCC_APB1ENR         *(volatile uint32_t*)(RCC_BASE_ADDR + OFF_APB1ENR)
#define RCC_APB2ENR         *(volatile uint32_t*)(RCC_BASE_ADDR + OFF_APB2ENR)
 
#define GPIOA_BASE_ADDR     0x40020000
#define GPIOD_BASE_ADDR     0x40020C00
 
#define OFF_MODER           0x00        // GPIOx_MODER    (GPIO port mode register)
#define OFF_OTYPER          0x04        // GPIOx_OTYPER   (GPIO port output type register)
#define OFF_OSPEEDR         0x08        // GPIOx_OSPEEDR  (GPIO port output speed register)
#define OFF_PUPDR           0x0C        // GPIOx_PUPDR    (GPIO port pull-up/pull-down register)
#define OFF_IDR             0x10        // GPIOx_IDR      (GPIO port input data register)
#define OFF_ODR             0x14        // GPIOx_ODR      (GPIO port output data register)
#define OFF_BSRR            0x18        // GPIOx_BSRR     (GPIO port bit set/reset register)
#define OFF_LCKR            0x1C        // GPIOx_LCKR     (GPIO port configuration lock register)
#define OFF_AFRL            0x20        // GPIOx_AFRL     (GPIO alternate function low register)
#define OFF_AFRH            0x24        // GPIOx_AFRH     (GPIO alternate function high register)
 
#define USART1_BASE_ADDR    0x40011000
#define USART2_BASE_ADDR    0x40004400
#define USART3_BASE_ADDR	0x40004800
 
#define OFF_SR              0x1C        // Status register
#define OFF_RDR             0x24        // Receive Data register
#define OFF_TDR             0x28        // Transmit Data register
#define OFF_BRR             0x0C        // Baudrate register
#define OFF_CR1             0x00        // Control register 1
#define OFF_CR2             0x04        // Control register 2
#define OFF_CR3             0x08        // Control register 3
 
 
#define UART_BASECLK        OS_FSYS / 4       // USART3 runs on APB1 clock
#define GPIO_BASE_ADDR      GPIOD_BASE_ADDR
#define USART_BASE_ADDR     USART3_BASE_ADDR
#define GPIO_UART_TX_BIT    9                // USART3 TX: Pin PD9
#define GPIO_UART_RX_BIT    8                 // USART3 RX: Pin PD8
#define USART_IRQn          USART3_IRQn
 
#define GPIO_MODER          *(volatile uint32_t*)(GPIO_BASE_ADDR + OFF_MODER)
#define GPIO_AFRH           *(volatile uint32_t*)(GPIO_BASE_ADDR + OFF_AFRH)
#define GPIO_AFRL           *(volatile uint32_t*)(GPIO_BASE_ADDR + OFF_AFRL)
 
#define USART_SR            *(volatile uint32_t*)(USART_BASE_ADDR + OFF_SR)
#define USART_RDR           *(volatile uint32_t*)(USART_BASE_ADDR + OFF_RDR)
#define USART_TDR           *(volatile uint32_t*)(USART_BASE_ADDR + OFF_TDR)
#define USART_BRR           *(volatile uint32_t*)(USART_BASE_ADDR + OFF_BRR)
#define USART_CR1           *(volatile uint32_t*)(USART_BASE_ADDR + OFF_CR1)
#define USART_CR2           *(volatile uint32_t*)(USART_BASE_ADDR + OFF_CR2)
#define USART_CR3           *(volatile uint32_t*)(USART_BASE_ADDR + OFF_CR3)
void USART3_IRQHandler(void) {
  int UsartStatus;
  uint8_t v;
  int r;
 
  UsartStatus = USART_SR;                              // Examine status register
  if (UsartStatus & (1 << USART_RXNE)) {               // Data received?
    v = USART_RDR;                                     // Read data
    if ((UsartStatus & USART_RX_ERROR_FLAGS) == 0) {   // Only process data if no error occurred
      (void)v;                                         // Avoid warning in BTL
      if (_cbOnRx) {
        _cbOnRx(v);
      }
    }
  }
  if (UsartStatus & (1 << USART_TXE)) {                // Tx (data register) empty? => Send next character Note: Shift register may still hold a character that has not been sent yet.
    //
    // Under special circumstances, (old) BTL of Flasher does not wait until a complete string has been sent via UART,
    // so there might be an TxE interrupt pending *before* the FW had a chance to set the callbacks accordingly which would result in a NULL-pointer call...
    // Therefore, we need to check if the function pointer is valid.
    //
    if (_cbOnTx == NULL) {  // No callback set? => Nothing to do...
      return;
    }
    r = _cbOnTx(&v);
    if (r == 0) {                          // No more characters to send ?
      USART_CR1 &= ~(1UL << USART_TXEIE);  // Disable further tx interrupts
    } else {
      USART_SR;      // Makes sure that "transmission complete" flag in USART_SR is reset to 0 as soon as we write USART_DR. If USART_SR is not read before, writing USART_DR does not clear "transmission complete". See STM32F4 USART documentation for more detailed description.
      USART_TDR = v;  // Start transmission by writing to data register
    }
  }
}
void HIF_UART_Init(uint32_t Baudrate, UART_ON_TX_FUNC_P cbOnTx, UART_ON_RX_FUNC_P cbOnRx) {
  uint32_t v;
  uint32_t Div;
  //
  // Configure USART RX/TX pins for alternate function AF7
  //
  RCC_APB1ENR |= (1 <<  18);        // Enable USART3 clock
  RCC_AHB1ENR |= (1 <<  3);        // Enable IO port A clock
  v  = GPIO_AFRL;
  v &= ~((15UL << ((GPIO_UART_TX_BIT) << 2)) | (15UL << ((GPIO_UART_RX_BIT) << 2)));
  v |=   ((7UL << ((GPIO_UART_TX_BIT) << 2)) | (7UL << ((GPIO_UART_RX_BIT) << 2)));
  GPIO_AFRL = v;
  //
  // Configure USART RX/TX pins for alternate function usage
  //
  v  = GPIO_MODER;
  v &= ~((3UL << (GPIO_UART_TX_BIT << 1)) | (3UL << (GPIO_UART_RX_BIT << 1)));
  v |=  ((2UL << (GPIO_UART_TX_BIT << 1)) | (2UL << (GPIO_UART_RX_BIT << 1)));         // PA10: alternate function
  GPIO_MODER = v;
  //
  // Initialize USART
  //
  USART_CR1 = 0
            | (1 << 15)                         // OVER8  = 1; Oversampling by 8
            | (1 << 0)                         	// UE     = 1; USART enabled
            | (0 << 12)                         // M      = 0; Word length is 1 start bit, 8 data bits
			| (0 << 28)
            | (0 << 10)                         // PCE    = 0; No parity control
            | (1 <<  5)                         // RXNEIE = 1; RXNE interrupt enabled
            | (1 <<  3)                         // TE     = 1; Transmitter enabled
            | (1 <<  2)                         // RE     = 1; Receiver enabled
            ;
  USART_CR2 = 0
            | (0 << 12)                         // STOP = 00b; 1 stop bit
			| (0 << 13)
            ;
  USART_CR3 = 0
            | (0 << 11)                         // ONEBIT = 0; Three sample bit method
            | (1 <<  7)                         // DMAT   = 1; DMA for transmitter enabled
            ;
  //
  // Set baudrate
  //
  Div = Baudrate * 8;                       // We use 8x oversampling.
  Div = ((2 * (UART_BASECLK)) / Div) + 1;   // Calculate divider for baudrate and round it correctly. This is necessary to get a tolerance as small as possible.
  Div = Div / 2;
  if (Div > 0xFFF) {
    Div = 0xFFF;        // Limit to 12 bit (mantissa in BRR)
  }
  if (Div >= 1) {
    USART_BRR = 0xFFF0 & (Div << 4);    // Use only mantissa of fractional divider
  }
  //
  // Setup callbacks which are called by ISR handler and enable interrupt in NVIC
  //
  _cbOnRx = cbOnRx;
  _cbOnTx = cbOnTx;
  NVIC_SetPriority(USART_IRQn, 6);  // Highest prio, so it is not disabled by embOS
  NVIC_EnableIRQ(USART_IRQn);
}

Good news! Thank you for sharing the solution 😊