Мигание кода STM32 работает только при переходе в режим отладки - PullRequest
1 голос
/ 02 июля 2019

Я пытаюсь запустить простую мигающую программу на плате STM32 на основе STM32F413RG. Светодиод загорается и переключается только при переходе, а не при продолжении без точки останова или при свободном движении в режиме разблокировки.

Я настроил eclipse (4.11) для отладки программы с использованием аппаратного отладчика J-link. Код загружается, и светодиод запрограммирован, но я вижу, что он переключается только при ручном переходе. Он не работает без точек останова.

Я делюсь своим кодом ниже, где я настроил часы для получения из PLL, работающего на 32 МГц и пытающегося мигать светодиодом, подключенным к выводу 1 порта B, каждые 0,5 секунды.

Еще одна интересная вещь: даже если я могу установить точку останова, чтобы увидеть внутри метода 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;
}

Ожидается мигание светодиода в соответствии с требуемой частотой, когда программа запускается без точек останова или режима разблокировки, но активность светодиода видна только при переходе в режиме отладки.

Ответы [ 2 ]

0 голосов
/ 03 июля 2019
  1. Будьте последовательны.Если вы устанавливаете часы, используя прямые регистры, не вызывайте функции, генерируемые кубом HAL, такие как SystemCoreClockUpdate();, очень вероятно, что 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
0 голосов
/ 02 июля 2019

Вам нужна небольшая задержка после включения часов GPIO. Сделайте вызов __DSB() между включением часов и доступом к регистрам GPIO.

Подробнее см. Документ об ошибках продукта.

...