‎2022-05-02 09:14 AM
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
}
}
}
Solved! Go to Solution.
‎2022-05-31 06:50 AM
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);
}
‎2022-05-04 06:44 AM
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
‎2022-05-31 06:50 AM
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);
}
‎2022-05-31 07:22 AM
Good news! Thank you for sharing the solution :smiling_face_with_smiling_eyes: