STM32闪烁代码仅在进入调试模式时有效

时间:2019-07-02 19:31:05

标签: c eclipse debugging gdb stm32f4

我正在尝试在基于STM32F413RG的STM32板上运行一个简单的闪烁程序。 LED亮起,仅在单步执行时切换,而在没有断点的情况下继续运行或在“释放”模式下自由运行时则不会切换。

我已经设置了eclipse(4.11)以使用J-link硬件调试器调试程序。代码已上传,并且已编程的LED点亮,但我只能在手动执行时看到它切换。没有断点就无法运行。

在下面的代码中共享我的代码,其中我将时钟设置为运行在32 MHz的PLL上,并尝试每0.5秒使连接到端口B引脚1的LED闪烁一次。

更有趣的是,即使我能够设置一个断点以查看delay()方法内部,调试器也不会停止在它上面,单步执行时似乎会跳过该行代码。为什么会这样?

void setupClocks()
{
    // we want to use the 24000000 HSE clock (xtal) as the base
     RCC->CR |= RCC_CR_HSEON;
    // so wait for it to be ready
    while ((RCC->CR & RCC_CR_HSERDY) == 0) {}
    enter code here


    // now configure the PLL (HSE / 12 * 96 /6) gives 32 MHz
    RCC->PLLCFGR |= RCC_PLLCFGR_PLLSRC_HSE;
    RCC->PLLCFGR &= ~RCC_PLLCFGR_PLLM_Msk;
    RCC->PLLCFGR |= (12)<< RCC_PLLCFGR_PLLM_Pos;
    RCC->PLLCFGR &= ~RCC_PLLCFGR_PLLN_Msk;
    RCC->PLLCFGR |= (96)<< RCC_PLLCFGR_PLLN_Pos; // 32 MHz

    RCC->PLLCFGR &= ~RCC_PLLCFGR_PLLP_Msk;

    RCC->PLLCFGR |= RCC_PLLCFGR_PLLP_1; // 6

    RCC->CR |= RCC_CR_PLLON;

 // wait for PLL to be ready
    while ((RCC->CR & RCC_CR_PLLRDY) == 0) {}

    // now setup the AHB1
    // 1/2 of system clock (48 MHz)
    RCC->CFGR |= RCC_CFGR_PPRE1_2;

    // select PLL (clocked from HSE)
    RCC->CFGR |= RCC_CFGR_SW_1;

    //reset the ones we use
    RCC->AHB1RSTR = RCC_AHB1RSTR_GPIOARST;
    RCC->AHB1RSTR = RCC_AHB1RSTR_GPIOBRST;
    RCC->AHB1RSTR = RCC_AHB1RSTR_GPIOCRST;
    RCC->AHB1RSTR = RCC_AHB1RSTR_GPIODRST;
    RCC->AHB1RSTR = 0;

    SystemCoreClockUpdate();
}

void initLED()
{
    // enable port B clock
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;

    // set as output for Port B pin 1
    GPIOB->MODER |= GPIO_MODER_MODER1_0;

   // start with MP10 LED on

   GPIOB->ODR = GPIO_ODR_ODR_1;
}

void delay(uint32_t microsec)
{
    // wait a bit
    uint32_t counter =  (microsec * (SystemCoreClock / 1000000U));
    while(counter != 0U)
    {
      counter--;
    }
}
void blinkCount(int count)
{
    for (int i = 0; i < count; ++i)
    {
        GPIOB->ODR = ~GPIO_ODR_ODR_1 ;
        delay(500000);
        GPIOB->ODR = GPIO_ODR_ODR_1;
        delay(500000);
    }
    delay(1000000);
}

int main()
{
     setupClocks();
     initLED();

     while(1)
     {
         blinkCount(1);
         delay(1000000);
     }

    return 0;
}

期望在没有断点或释放模式的情况下运行程序时,LED会按照所需的频率闪烁,但是LED活动仅在调试模式下逐步显示时可见。

2 个答案:

答案 0 :(得分:0)

  1. 保持一致。如果您使用直接寄存器设置时钟,请不要调用SystemCoreClockUpdate();之类的HAL多维数据集生成的函数,很有可能SystemCoreClock不会具有您认为的值

  2. 在执行阻塞延迟时,我建议使用易失性变量,因为它们不会被编译器删除。除非您需要很多分钟的延迟,否则无需使用64位变量。尽量不要阻塞。使用SysTick(或其他任何计时器)中断来实现延迟。

示例

void delay(volatile uint32_t delay)
{
    while(delay--);
}

或者为了更精确地控制内联汇编:

void delay1(uint32_t delay)
{
    while(delay--)
    {
        asm volatile("" : : "r"(delay) : "memory");
    }
}

导致代码:

delay:
  sub sp, sp, #8
  str r0, [sp, #4]
.L2:
  ldr r3, [sp, #4]
  sub r2, r3, #1
  cmp r3, #0
  str r2, [sp, #4]
  bne .L2
  add sp, sp, #8
  bx lr
delay1:
.L6:
  subs r0, r0, #1
  bxcc lr
  b .L6

答案 1 :(得分:-1)

启用GPIO时钟后,您需要一个小的延迟。在启用时钟和访问GPIO寄存器之间进行一次__DSB()调用。

有关详细信息,请参见产品勘误表文档。