0
\$\begingroup\$

I'm working on UART using interrupts on Stm32F030 controller. I have done the following init.

void fnUart_Init(void)
{
 USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;

/* USART1 For Debug */
/* Enable GPIO clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA , ENABLE);
/* Enable USART clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);


/* USART1 Pins configuration */

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1); 
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);    

/* Configure pins as AF pushpull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);  

/* USARTx configured as follow:
- BaudRate = 115200 baud  
- Word Length = 8 Bits
- Stop Bit = 1 Stop Bit
- Parity = No Parity
- Hardware flow control disabled (RTS and CTS signals)
- Receive and transmit enabled
*/
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = 
USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);


/* NVIC configuration */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);


USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); 
/* Enable USART */
USART_Cmd(USART1, ENABLE);
}

UART2 Init

 void fnUart2_Init(void)
{
 USART_InitTypeDef USART_InitStructure;
 NVIC_InitTypeDef NVIC_InitStructure;
 GPIO_InitTypeDef GPIO_InitStructure;

 /* USART1 For Debug */
 /* Enable GPIO clock */
 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA , ENABLE);
/* Enable USART clock */
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);


 /* USART1 Pins configuration 
 /* Connect pin to Periph */
 GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_1); 
 GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_1);    

 /* Configure pins as AF pushpull */
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
 GPIO_Init(GPIOA, &GPIO_InitStructure);  

 /* USARTx configured as follow:
 -  BaudRate = 115200 baud  
 - Word Length = 8 Bits
 - Stop Bit = 1 Stop Bit
 - Parity = No Parity
 - Hardware flow control disabled (RTS and CTS signals)
 - Receive and transmit enabled
 */
  USART_InitStructure.USART_BaudRate = 115200;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No;
  USART_InitStructure.USART_HardwareFlowControl = 
  USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  USART_Init(USART2, &USART_InitStructure);

/* NVIC configuration */
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
 NVIC_Init(&NVIC_InitStructure);

USART_ITConfig(USART2,USART_IT_RXNE,ENABLE); 
/* Enable USART */
USART_Cmd(USART2, ENABLE);
  }

The IrqHandler is as follows

void USART1_IRQHandler(void)
{
  printf("\n\r Inside ISR1");
}

I have the following printf function which prints data on UART2 when printf is called.

#define PUTCHAR_PROTOTYPE int std::fputc(int ch, FILE *f)
PUTCHAR_PROTOTYPE
{
/* Place your implementation of fputc here */
/* e.g. write a character to the USART */
USART_SendData(USART2, (uint8_t) ch);

/* Loop until transmit data register is empty */
while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET)
{}
return ch;
}

While loop has nothing running in it as of now. Both the UART's are Initialized properly. This is verified by using printf for both UART1 and UART2. Now wrote this minimal code to test the interrupts. I'm sending any data via UART1 via Realterm software and USB-TTL converter and checking on UART2 whether USART1_IRQHandler() is getting called or not. No response.

Also i was reading about the status and the interrupt flags. They are a bit confusing. When to use and clear those flags? But first i'm not getting why the execution is not entering the ISR? Did i miss something in the init? I do not have a debugger with me so using breakpoints and checking the execution is not applicable in my case. My goal is to send data received on UART1 to UART2 and data from UART2 to UART1. I'm using the standard periph libraries and not HAL libraries. Any suggestions?

\$\endgroup\$
9
  • 1
    \$\begingroup\$ You can't do a printf() inside an ISR!!! \$\endgroup\$
    – brhans
    Commented Feb 6, 2018 at 12:08
  • \$\begingroup\$ Okay. I removed the printf() from the ISR and called another function instead of it. And in that function i'm writing the code which is intended for the printf(). Also noticed one more thing. In the while loop i kept printing Hello on UART2 and as soon as i pressed the send button via the Terminal software on UART1, the printing stopped indefinitely. What could be the reason? \$\endgroup\$ Commented Feb 6, 2018 at 12:23
  • 2
    \$\begingroup\$ I'm not following what you're saying. It seems like all you did was put the printf() in a different function and then call that function from the ISR. IF that is the case then you've changed nothing - you're still calling printf() from the ISR. \$\endgroup\$
    – brhans
    Commented Feb 6, 2018 at 12:30
  • 1
    \$\begingroup\$ The problem isn't calling 'a function' from an ISR. The problem is calling 'printf' from an ISR. ISRs typically need to be short and quick so that your micro can get out of the interrupt state and back into normal state ASAP. Unless you've enabled (and know how to manage) nested interrupts, no other interrupt can occur if you're still handling the previous one. Not only is printf a potentially long and complicated function call - it leads to you trying to transmit from your UART when you haven't completed handling the interrupt yet! You need to do some reading about how to write an ISR. \$\endgroup\$
    – brhans
    Commented Feb 6, 2018 at 13:37
  • 1
    \$\begingroup\$ If you want to know that you are inside the ISR, light up a LED or plug an oscilloscope at a pin that you toggle when entering the ISR. \$\endgroup\$
    – Blup1980
    Commented Feb 6, 2018 at 13:41

1 Answer 1

1
\$\begingroup\$

I am strongly guessing it comes in the USART1_ISR just once,

you need to clear the relevant USART1 pending Receive not empty (RXNE) bit by calling this USART_ClearITPendingBit(USART1, USART_IT_RXNE); inside the ISR.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.