STM32L1 USART interrupt problem

armstm32uart

I am trying to use stm32l152 discovery kit to communicate by using usart. Although I can send data on tx (I check this via pc), I couldn't get in interrupt function when data come (I send via pc and also make tx and rx short circuit and debug). main.c file is like below. I tried and examine a lot of example on the internet (even not related directly stm32l1 to understand what is going on with arm) but I couldn't find the problem. What could be the problem?

By the way, I am using IAR as IDE. When I add breakpoint inside to interrupt function (USART3_IRQHandler) and run, IAR alert -One or more breakpoints could not be set and have been disabled- and disable breakpoint inside interrupt function.

#include "main.h"


void DelaySW(uint32_t delay);
void RCC_Config(void);
GPIO_InitTypeDef GPIO_InitStructure; 
USART_InitTypeDef USART_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;   
USART_ClockInitTypeDef USART_ClockInitstructure;    
uint16_t receivedData;


void USART3_IRQHandler(void)
{
  while(1)
  {
    while (USART_GetFlagStatus(USART3,USART_FLAG_TXE) == RESET);
    USART_SendData(USART3, 'c');
  }    
}


int main(void)
{
  RCC_Config();

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

  /* Alternate function conf */
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3 );
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_USART3 );
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_USART3 );
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_USART3 );
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_USART3 );


  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
  GPIO_Init(GPIOB, &GPIO_InitStructure);


  NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  USART_ClockInitstructure.USART_Clock   = USART_Clock_Disable ;
  USART_ClockInitstructure.USART_CPOL    = USART_CPOL_Low ;
  USART_ClockInitstructure.USART_LastBit = USART_LastBit_Enable;
  USART_ClockInitstructure.USART_CPHA    = USART_CPHA_1Edge;


  /* USART conf */

  USART_InitStructure.USART_BaudRate = 9600;
  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(USART3, &USART_InitStructure);
  USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); 
  USART_ClockInit(USART3, &USART_ClockInitstructure);
  NVIC_Init(&NVIC_InitStructure); 


  USART_Cmd(USART3, ENABLE);

  while (USART_GetFlagStatus(USART3,USART_FLAG_TXE) == RESET);
  USART_SendData(USART3, 'c');
  while (USART_GetFlagStatus(USART3,USART_FLAG_TXE) == RESET);
  USART_SendData(USART3, 'c');
  while (USART_GetFlagStatus(USART3,USART_FLAG_TXE) == RESET);
  USART_SendData(USART3, 'c');
  while (USART_GetFlagStatus(USART3,USART_FLAG_TXE) == RESET);
  USART_SendData(USART3, 'c');
  while (USART_GetFlagStatus(USART3,USART_FLAG_TXE) == RESET);
  USART_SendData(USART3, 'c');
    while(1);
}

void DelaySW(uint32_t delay)
{
  uint32_t i=10000;

  for(;delay > 0; delay--){
  for(;i>0;i--)
  ;
  }
}

void RCC_Config(void)
{ 
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);

  /* Allow access to the RTC */
  PWR_RTCAccessCmd(ENABLE);

  /* Reset Backup Domain */
  RCC_RTCResetCmd(ENABLE);
  RCC_RTCResetCmd(DISABLE);

  /*!< LSE Enable */
  RCC_LSEConfig(RCC_LSE_ON);

  /*!< Wait till LSE is ready */
  while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
  {}
  /*!< LCD Clock Source Selection */
  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
}

#ifdef  USE_FULL_ASSERT

  /**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
  void assert_failed(uint8_t* file, uint32_t line)
  {
    /* User can add his own implementation to report the file name and line number,
    ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
    /* Infinite loop */
    while (1);
  }

#endif

Best Answer

I suspect that the linker is not behaving properly.

Each IDE has its own way of dealing with interrupts, but usually there is a file somewhere named "something_that_contains_interrupts.c" with all the declarations of the interrupt functions. The programmer just need to fill in his/her own code and the linker takes care of the rest.

Giving the function the correct name is certainly a good start, but seeing that you only included "main.h" I'm pretty sure that's not eonugh.

What is happening now is that the compiler is smart enough to understand that "USART3_IRQHandler" is never called, so it does not actually compile it, so it is clearly impossible to add a breakpoint in a piece of code that does not exist.

Just try to call the ISR once in your main, if IAR stops complaining I am probably right. Keep in mind that you have a while(1); statement in the function, so nothing else is gonna work, you'll just have your working breakpoint.