更改函数调用的位置会中断uart上的通信

问题描述

今天,我陷入了一个非常令人困惑的问题。我通过UART将数据从PC发送到MCU,反之亦然。 我正在使用中断。 我有两个不同版本的代码。它们看起来几乎相同,但是其中一个不能正常工作-数据未发送回PC(第一个版本正常)。我不知道为什么,但是我想知道,以便将来更快地发现这种问题。

完整版代码-> https://gitlab.com/bielu000/stm32-libopencm3 分支机构:

  • uart_not_working_version
  • uart_working_version

重要文件位于:src / app / src。

我可以将其保留为工作版本,但我想了解该问题的性质,以便将来避免此类问题。

这两个版本之间的主要区别:

  • 版本1->我经常调用(从主循环中的)函数server_check(),该函数检查MCU是否已接收到64kb,如果是,则将这些字节复制到write_buffer,然后发送回pc
  • 版本2->我不使用功能server_check,因为它的功能已移至server_run(从main调用一次),然后使用其自己的循环永不停止,并且在该循环中几乎完全相同类似于版本1中的server_check函数中的代码

MCU:STM32F103 我正在使用g ++ 8.2

Compliation标志:

set(COMPILER_CXX_FLAGS“ -fno-use-cxa-atexit -O1 -fno-exceptions -g”)

set(COMPILER_FLAGS“ -fdata-sections -ffunction-sections -DNDEBUG -Wall -Werror -g“)

改变函数调用的位置通常会破坏MCU的功能吗?

版本1。 //main.cpp

int main()
{
  //init clock etc

  server_init();
  server_run();

  while(true)
  {
    server_check();
  }
}

// server.cpp

extern "C" {
  #include <libopencm3/stm32/usart.h> 
  #include <libopencm3/stm32/gpio.h>
  #include <libopencm3/stm32/rcc.h>
  #include <libopencm3/cm3/nvic.h>
}

#include <server.hpp>
#include <stdint.h>
#include <ring_buffer.hpp>
#include <target.h>

static uint8_t w_buffer[1024]; // write buffer
static uint8_t r_buffer[1024]; // read buffer

utils::containers::RingBuffer write_rb{w_buffer,sizeof(w_buffer)};
utils::containers::RingBuffer read_rb{r_buffer,sizeof(r_buffer)};

static void sendData()
{
  if (write_rb.capacity() != 0)
  {
    usart_send(USART1,write_rb.read());
    usart_enable_tx_interrupt(USART1);
  }
  else 
  {
    usart_disable_tx_interrupt(USART1);
  }
}

static void readData()
{
  auto data = usart_recv(USART1);
  read_rb.write(static_cast<uint8_t>(data));

  // usart_enable_rx_interrupt(USART1);
}

void server_init()
{
  //RCC
  rcc_periph_clock_enable(RCC_USART1);

  //GPIO
  gpio_set_mode(GPIO_BANK_USART1_TX,GPIO_MODE_OUTPUT_50_MHZ,GPIO_CNF_OUTPUT_ALTFN_PUSHPULL,GPIO_USART1_TX);

  gpio_set_mode(GPIO_BANK_USART1_RX,GPIO_MODE_INPUT,GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN,GPIO_USART1_RX);

  //USART
  usart_set_mode(USART1,USART_MODE_TX_RX);
  usart_set_baudrate(USART1,9600);
  usart_set_parity(USART1,USART_PARITY_NONE);
  usart_set_databits(USART1,8);
  usart_set_stopbits(USART1,1);
  usart_set_flow_control(USART1,USART_FLOWCONTROL_NONE);
  usart_enable_rx_interrupt(USART1);

  //ISR
  nvic_enable_irq(NVIC_USART1_IRQ);
  
  //Enable 
  usart_enable(USART1);
}


void server_run()
{
}

void server_check()
{
    if (read_rb.capacity() == 64)
    {
      while (read_rb.capacity() != 0)
      {
        write_rb.write(read_rb.read());
      }

      sendData();
    }
}

void usart1_isr()
{
  if (usart_get_flag(USART1,USART_FLAG_TXE) != 0) 
  {
    sendData();
  }

  if (usart_get_flag(USART1,USART_FLAG_RXNE) != 0) // when data is ready to read
  {
    readData(); 
  }
} 

版本2

main.cpp
int main()
{
  //init clock etc

  server_init();
  server_run();

  while(true)
  {

  }
}

server.cpp

extern "C" {
  #include <libopencm3/stm32/usart.h> 
  #include <libopencm3/stm32/gpio.h>
  #include <libopencm3/stm32/rcc.h>
  #include <libopencm3/cm3/nvic.h>
}

#include <server.hpp>
#include <stdint.h>
#include <ring_buffer.hpp>
#include <Os.hpp>
#include <target.h>

/**
 * 
 *  | MSG_TYPE | |
 * 
 */

static uint8_t w_buffer[1024]; // write buffer
static uint8_t r_buffer[1024]; // read buffer

utils::containers::RingBuffer write_rb{w_buffer,USART_FLOWCONTROL_NONE);
  usart_enable_rx_interrupt(USART1);

  //ISR
  nvic_enable_irq(NVIC_USART1_IRQ);
  
  //Enable 
  usart_enable(USART1);



}


void server_run()
{
  while(true)
  {
    if (read_rb.capacity() == 64)
    {
      while (read_rb.capacity() != 0)
      {
        write_rb.write(read_rb.read());
      }

      sendData();
    }
  }
  
}

void server_check()
{
 
}

void usart1_isr()
{
  if (usart_get_flag(USART1,USART_FLAG_RXNE) != 0) // when data is ready to read
  {
    readData(); 
  }
} 

解决方法

您应该使用第2版代码尝试以下提示:

  • while(true)函数中删除main()
  • ==64替换为>=64以确保即使跳过一个值且容量变为65,缓冲区也已处理:if (read_rb.capacity() >= 64)

此外,应避免在main函数之外的其他函数中放入无限循环。