Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

Ошибка при настройки тактирования STM32F030

Ср янв 17, 2024 23:14:17

ДОброго времени суток!
Наткнулся на странную проблему при инициализации контроллера от внешнего кварцевого резонатора 8МГц.

В функции void SystemClock_Config(void) при вызове HAL_RCC_OscConfig(&RCC_OscInitStruct возвращается HAL_ERROR
Код:
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL4;
  RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV1;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  {
    Error_Handler();
  }
}


При этом проблема наблюдается только при использование PLL Source Mux.
т.е. тактирования
HSI RC -> System Clock Mux
HSE -> System Clock Mux
Работают нормально....
Настраиваю все через CubeMX
Вот скриншоты рабочих настроек
Изображение Изображение

Как только тактирование проходит через PLL Source Mux при вызове HAL_RCC_OscConfig(&RCC_OscInitStruct возвращается HAL_ERROR
Опять же скрины настроек из CubeMX
Изображение Изображение

И что то я совсем не понимаю в какую сторону дальше копать?

Re: Ошибка при настройки тактирования STM32F030

Пт янв 19, 2024 00:20:00

Немного подробностей..... Похоже проблема только в режиме отладки.....
Прицепил к контроллеру свотодиод и вот так им моргаю
Код:
int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  while (1) {
        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_SET);
        HAL_Delay(5000);
        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET);
        HAL_Delay(5000);
    }
}

При обоих схемах настроки тактирования (с PLL и без) все работает, т.е. светодиод мигает....

Но при попытке походить отладчиком по коду в случае без PLL все получается, а вот если спользовать PLL, то получаю ошибку HAL_ERROR.

Вот void SystemClock_Config(void) с которым под отладчиком все работает.....
Код:
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}


А вот void SystemClock_Config(void) с которым под отладчиком все НЕ работает.....

Код:
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL2;
  RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV1;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}


в 11 строке HAL_RCC_OscConfig(&RCC_OscInitStruct) возвращает HAL_ERROR
Причем отладчиком до этой строки я дойти могу.... Ну а дальше попадаю в обработку ошибки и все на этом....

Почему так?

Добавлено after 2 hours 46 minutes 47 seconds:
Ну и еще чуть глубокие капания функции HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) показали что ошибка формируется вот здесь
Код:
       /* Do not return HAL_ERROR if request repeats the current configuration */
        pll_config  = RCC->CFGR;
        pll_config2 = RCC->CFGR2;
        if((READ_BIT(pll_config,  RCC_CFGR_PLLSRC)  != RCC_OscInitStruct->PLL.PLLSource) ||
           (READ_BIT(pll_config2, RCC_CFGR2_PREDIV) != RCC_OscInitStruct->PLL.PREDIV)    ||
           (READ_BIT(pll_config,  RCC_CFGR_PLLMUL)  != RCC_OscInitStruct->PLL.PLLMUL))
        {
          return HAL_ERROR;
        }


и ошибка формируется потому что условие (READ_BIT(pll_config2, RCC_CFGR2_PREDIV) != RCC_OscInitStruct->PLL.PREDIV) true.
остальные два false

Re: Ошибка при настройки тактирования STM32F030

Пт янв 19, 2024 07:07:09

В функции HAL_RCC_OscConfig должна быть запись регистра RCC->CFGR2 значением RCC_PREDIV_DIV1 (передается в функцию HAL_RCC_OscConfig в RCC_OscInitStruct->PLL.PREDIV)

Re: Ошибка при настройки тактирования STM32F030

Сб янв 20, 2024 10:57:51

В продолжение эпопеи..... В предыдущем сообщении был неправ относительно условия
HAL_ERROR возникает в блоке
Код:
 pll_config  = RCC->CFGR;
        pll_config2 = RCC->CFGR2;
        if(( READ_BIT(pll_config,  RCC_CFGR_PLLSRC) != RCC_OscInitStruct->PLL.PLLSource) ||
           (READ_BIT(pll_config2, RCC_CFGR2_PREDIV) != RCC_OscInitStruct->PLL.PREDIV)    ||
           (READ_BIT(pll_config,  RCC_CFGR_PLLMUL)  != RCC_OscInitStruct->PLL.PLLMUL))
        {
          return HAL_ERROR;
        }

срабатывает условие READ_BIT(pll_config, RCC_CFGR_PLLSRC) != RCC_OscInitStruct->PLL.PLLSource
т.е. бит PLLSRC в регистре CFGR должен быть 1, а реально он 0. Получается что PLL тактируется от HSI а не HSE как в конфигурации.
Ниже полный фрагмент кода инициализирующего PLL в функции HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct)

Собственно конфигурирование происходит в 32 строке вот так
Код:
    /* Configure the main PLL clock source, predivider and multiplication factor. */
        __HAL_RCC_PLL_CONFIG(RCC_OscInitStruct->PLL.PLLSource,
                             RCC_OscInitStruct->PLL.PREDIV,
                             RCC_OscInitStruct->PLL.PLLMUL);


Но реально этого не происходит, потому что выше стоит условие (7 строка)
Код:
    /* Check if the PLL is used as system clock or not */
    if( __HAL_RCC_GET_SYSCLK_SOURCE() != RCC_SYSCLKSOURCE_STATUS_PLLCLK)

т.е. если тактирование system clock от PLL, то его конфигурирование не выполняется..... В действиетельности так и есть.
И вот теперь я совсем не понимаю как это работает... Причем эта проблема только в режиме отладки..... При простом запуске HAL_ERROR нет...

Спойлер
Код:
/*---------- PLL Configuration ----------*/
  /* Check the parameters */
  assert_param(IS_RCC_PLL(RCC_OscInitStruct->PLL.PLLState));
  if ((RCC_OscInitStruct->PLL.PLLState) != RCC_PLL_NONE)
  {
    /* Check if the PLL is used as system clock or not */
    if( __HAL_RCC_GET_SYSCLK_SOURCE() != RCC_SYSCLKSOURCE_STATUS_PLLCLK)
    {
      if((RCC_OscInitStruct->PLL.PLLState) == RCC_PLL_ON)
      {
        /* Check the parameters */
        assert_param(IS_RCC_PLLSOURCE(RCC_OscInitStruct->PLL.PLLSource));
        assert_param(IS_RCC_PLL_MUL(RCC_OscInitStruct->PLL.PLLMUL));
        assert_param(IS_RCC_PREDIV(RCC_OscInitStruct->PLL.PREDIV));
 
        /* Disable the main PLL. */
        __HAL_RCC_PLL_DISABLE();
       
        /* Get Start Tick */
        tickstart = HAL_GetTick();
       
        /* Wait till PLL is disabled */
        while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY)  != RESET)
        {
          if((HAL_GetTick() - tickstart ) > PLL_TIMEOUT_VALUE)
          {
            return HAL_TIMEOUT;
          }
        }

        /* Configure the main PLL clock source, predivider and multiplication factor. */
        __HAL_RCC_PLL_CONFIG(RCC_OscInitStruct->PLL.PLLSource,
                             RCC_OscInitStruct->PLL.PREDIV,
                             RCC_OscInitStruct->PLL.PLLMUL);
        /* Enable the main PLL. */
        __HAL_RCC_PLL_ENABLE();
       
        /* Get Start Tick */
        tickstart = HAL_GetTick();
       
        /* Wait till PLL is ready */
        while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY)  == RESET)
        {
          if((HAL_GetTick() - tickstart ) > PLL_TIMEOUT_VALUE)
          {
            return HAL_TIMEOUT;
          }
        }
      }
      else
      {
        /* Disable the main PLL. */
        __HAL_RCC_PLL_DISABLE();
 
        /* Get Start Tick */
        tickstart = HAL_GetTick();
       
        /* Wait till PLL is disabled */ 
        while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY)  != RESET)
        {
          if((HAL_GetTick() - tickstart ) > PLL_TIMEOUT_VALUE)
          {
            return HAL_TIMEOUT;
          }
        }
      }
    }
    else
    {
      /* Check if there is a request to disable the PLL used as System clock source */
      if((RCC_OscInitStruct->PLL.PLLState) == RCC_PLL_OFF)
      {
        return HAL_ERROR;
      }
      else
      {
        /* Do not return HAL_ERROR if request repeats the current configuration */
        pll_config  = RCC->CFGR;
        pll_config2 = RCC->CFGR2;
        if(( READ_BIT(pll_config,  RCC_CFGR_PLLSRC) != RCC_OscInitStruct->PLL.PLLSource) ||
           (READ_BIT(pll_config2, RCC_CFGR2_PREDIV) != RCC_OscInitStruct->PLL.PREDIV)    ||
           (READ_BIT(pll_config,  RCC_CFGR_PLLMUL)  != RCC_OscInitStruct->PLL.PLLMUL))
        {
          return HAL_ERROR;
        }
      }
    }
  }

Re: Ошибка при настройки тактирования STM32F030

Сб янв 20, 2024 11:45:24

Вы прикалываетесь? Там два с половиной регистра надо записать чтобы тактирование настроить.

Re: Ошибка при настройки тактирования STM32F030

Сб янв 20, 2024 12:40:44

Вы прикалываетесь? Там два с половиной регистра надо записать чтобы тактирование настроить.
Это для тех, кто не имеет кубо-зависимости - 2 регистра. не путайте. :wink:
Для кубо-зависимых - "целая эпопея". :facepalm:

Re: Ошибка при настройки тактирования STM32F030

Сб янв 20, 2024 20:38:03

2 регистра. не путайте.
FLASH_ACR, RCC_CR два раза по четвертинке и RCC_CFGR два раза. Так что, тут как считать. Всего 2,5 регистра, но один два раза :)))

Спойлер
Код:
  FLASH->ACR = FLASH_ACR_PRFTBE | _VAL2FLD(FLASH_ACR_LATENCY,1); // Настройка тактов ожидания Flash
 
  *((volatile uint8_t *)&RCC->CR+2) = RCC_CR_HSEON>>16;          // Включить HSE 
  while(!(RCC->CR&RCC_CR_HSERDY));                               // Жадать пока запустится HSE
 
  const uint32_t cfgr = RCC_CFGR_PLLSRC_HSE_PREDIV               // Конфигурация PLL и делителей
                      | RCC_CFGR_PLLMUL6                                           
                      | RCC_CFGR_HPRE_DIV1
                      | RCC_CFGR_PPRE_DIV1                       
                      | RCC_CFGR_ADCPRE_DIV4
                      | RCC_CFGR_MCO_NOCLOCK ;
 
  RCC->CFGR =  cfgr | RCC_CFGR_SW_HSI;
 
  *((volatile uint8_t *)&RCC->CR+3) = RCC_CR_PLLON>>24;          // Включить PLL 
  while(!(RCC->CR&RCC_CR_PLLRDY));                               // Жадать пока запустится PLL
     
  RCC->CFGR =  cfgr | RCC_CFGR_SW_PLL;                           // Переключиться на PLL

Re: Ошибка при настройки тактирования STM32F030

Сб янв 20, 2024 21:00:40

Вы так пишите, чтобы вопросы задавали?
Код:
*((volatile uint8_t *)&RCC->CR+2) = RCC_CR_HSEON>>16;          // Включить HSE

*((volatile uint8_t *)&RCC->CR+3) = RCC_CR_PLLON>>24;          // Включить PLL 

Да, и неважно.

Re: Ошибка при настройки тактирования STM32F030

Сб янв 20, 2024 21:02:47

HAl то еще маразм, ошибок море. Вы используете не последнею версию, может в последней устранили ошибку.
Скорее всего время маленькое ожидания когда запуститься PLL или установиться кварц......нужно увеличивать :).

Re: Ошибка при настройки тактирования STM32F030

Сб янв 20, 2024 21:11:26

Ну да, проще выставить в настройках код-генератор LL, всё будет понятнее.
Но, мне кажется, возникающая у ТС ошибка связана скорее с использованием код-генератора, чем с HAL.

Re: Ошибка при настройки тактирования STM32F030

Сб янв 20, 2024 21:16:25

Вы так пишите, чтобы вопросы задавали?
Нет, чтобы включить HSE и PLL соответственно. Для себя у меня С++ код, но вам это сильно не понравится, поверьте. А для форума всё подробно на православном С.
Изображение
изображение_2024-01-20_211751009.png
(22.65 KiB) Скачиваний: 493

Re: Ошибка при настройки тактирования STM32F030

Сб янв 20, 2024 21:20:12

Я верю, т.к. давно читаю форум.
Только, смысла не вижу в добавлении к исходному коду неподъёмного числа строк.

Re: Ошибка при настройки тактирования STM32F030

Пн янв 22, 2024 07:49:01

А не могли бы показать, как вы бы написали "подъёмный вариант"?

Re: Ошибка при настройки тактирования STM32F030

Вт янв 23, 2024 19:45:40

Могу.
Взять Ваш вариант c регистрами, только:
Код:
RCC->CFGR =  cfgr | RCC_CFGR_SW_HSI;

заменить на
Код:
RCC->CFGR =  cfgr | RCC_CFGR_SW_HSE;

Ваш вариант неверен.

Добавлено after 1 hour 12 minutes 29 seconds:
Я на Ваш вопрос ответил.
Вы мне не ответили на мой вопрос.
Я у Вас спрашивал,
Вы так пишите, чтобы вопросы задавали?

Re: Ошибка при настройки тактирования STM32F030

Вт янв 23, 2024 20:01:19

Могу.
Взять Ваш вариант c регистрами, только:
Код:
RCC->CFGR =  cfgr | RCC_CFGR_SW_HSI;

заменить на
Код:
RCC->CFGR =  cfgr | RCC_CFGR_SW_HSE;

Ваш вариант неверен.
И чем же он не верен? Зачем переключать тактирование на кварцевый резонатор, если его всё равно тут же на PLL переключать? Какой в этом смысл?

Я на Ваш вопрос ответил.
Я вообще-то не об этом спрашивал. Как бы вы написали вот это?
Код:
*((volatile uint8_t *)&RCC->CR+3) = RCC_CR_PLLON>>24;


Вы мне не ответили на мой вопрос.
Я у Вас спрашивал,
Вы так пишите, чтобы вопросы задавали?
Странно, вроде в этом сообщении русским по жёлтому написано НЕТ, да ещё и с пояснением почему.

Re: Ошибка при настройки тактирования STM32F030

Вт янв 23, 2024 20:15:37

Я вообще-то не об этом спрашивал. Как бы вы написали вот это?
Код:
*((volatile uint8_t *)&RCC->CR+3) = RCC_CR_PLLON>>24;

Код:
SET_BIT(RCC->CR, RCC_CR_PLLON);

или
Код:
LL_RCC_PLL_Enable();

Re: Ошибка при настройки тактирования STM32F030

Вт янв 23, 2024 20:55:58

Как говорится, почувствуйте разницу.
Изображение

И что там насчёт переключения на HSE? Будут обоснования?

изображение_2024-01-23_205409887.png
(20.49 KiB) Скачиваний: 297

Re: Ошибка при настройки тактирования STM32F030

Вт янв 23, 2024 21:01:13

Да, я ошибся. Извините.

Re: Ошибка при настройки тактирования STM32F030

Пн фев 05, 2024 22:45:30

Я бы тоже все на себя взял если бы мне показали картинку с надписями на асме, фиг знает что это, но очень страшно выглядит.
Жутко охота разобратся, но не знаю с чего начать, вот у меня есть же иар и стмки я же могу попробовать освоить азы асма или совсем не подходит?
И может есть хорошие статитьи или книга проверянная про асм для чайников?

Re: Ошибка при настройки тактирования STM32F030

Вт фев 06, 2024 08:43:59

Среднестатистическому программисту сейчас достаточно уметь читать ассемблерный код. IAR для этого, пожалуй, лучший инструмент.
Ставите пару галок и изучаете что компилятор сделал из вашего кода. Ну и любое обучение в XXI веке начинается с изучения гугления.
Изображение
изображение_2024-02-06_084244213.png
(23.91 KiB) Скачиваний: 145
Ответить