STM32闪烁代码仅在进入调试模式时有效
STM32 blink code only works when stepping on debug mode
我正在尝试 运行 在基于 STM32F413RG 的 STM32 板上编写一个简单的 blink 程序。 LED 灯亮起,仅在单步执行时切换,而不是在没有断点的情况下继续或 运行在 Release 模式下自由切换。
我已经设置了 eclipse(4.11) 以使用 J-link 硬件调试器调试程序。代码上传,编程的 LED 灯亮起,但我只能在手动单步执行时看到它切换。它不会 运行 没有断点。
在下面分享我的代码,我将时钟设置为从 PLL 运行ning 以 32 MHz 获取时钟,并尝试每 0.5 秒 blink 连接到端口 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;
}
当程序 运行 没有断点或释放模式时,期望 blink 按照所需频率显示 LED,但 LED activity 仅在调试期间单步执行时可见模式。
启用 GPIO 时钟后需要稍作延迟。在启用时钟和访问 GPIO 寄存器之间进行 __DSB()
调用。
有关详细信息,请参阅产品勘误表文档。
保持一致。如果您直接使用寄存器设置时钟,请不要调用 HAL 立方体生成的函数,如 SystemCoreClockUpdate();
很可能 SystemCoreClock
将没有您认为的值
在执行阻塞延迟时,我建议使用 volatile 变量,因为它们不会被编译器删除。除非你想要很多分钟的延迟,否则不需要使用 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
我正在尝试 运行 在基于 STM32F413RG 的 STM32 板上编写一个简单的 blink 程序。 LED 灯亮起,仅在单步执行时切换,而不是在没有断点的情况下继续或 运行在 Release 模式下自由切换。
我已经设置了 eclipse(4.11) 以使用 J-link 硬件调试器调试程序。代码上传,编程的 LED 灯亮起,但我只能在手动单步执行时看到它切换。它不会 运行 没有断点。
在下面分享我的代码,我将时钟设置为从 PLL 运行ning 以 32 MHz 获取时钟,并尝试每 0.5 秒 blink 连接到端口 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;
}
当程序 运行 没有断点或释放模式时,期望 blink 按照所需频率显示 LED,但 LED activity 仅在调试期间单步执行时可见模式。
启用 GPIO 时钟后需要稍作延迟。在启用时钟和访问 GPIO 寄存器之间进行 __DSB()
调用。
有关详细信息,请参阅产品勘误表文档。
保持一致。如果您直接使用寄存器设置时钟,请不要调用 HAL 立方体生成的函数,如
SystemCoreClockUpdate();
很可能SystemCoreClock
将没有您认为的值在执行阻塞延迟时,我建议使用 volatile 变量,因为它们不会被编译器删除。除非你想要很多分钟的延迟,否则不需要使用 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