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

Резервирование LSE LSI

Чт май 18, 2023 08:46:48

Здравствуйте коты
Как при невозможности запуска RTC от низкочастотного внешнего (LSE) (часового кварца), перейти на работу от внутреннего LSI

Как я понял первая проверка при запуске контроллера в HAL осуществляется в void SystemClock_Config(void) и на невозможность тактов уходит в бесконечный цикл в Error_Handler();
Как назло в void SystemClock_Config(void) нет места для пользовательского кода /* USER CODE BEGIN 3 */
а отказываться от IDE и кода ею формируемого я не хочу (свой код я пишу только в предназначенных для этого местах)

я бы сделал так (опишу кратко): сконфигурировал с RCC_OscInitStruct.LSEState = RCC_LSE_ON;
если неудача то попробовал с RCC_OscInitStruct.LSIState = RCC_LSI_ON;
а зависать если ни один генератор не запустился

Как это сделать? IDE STM32CubeIDE плата BlackPill
Может в среде есть возможность поставить в нужном месте галочку всего то..
Идея возникла после того как плата с МК пришла с нерабочим LSE кварцем, я его заменил на другой, и чтобы предотвратить такое в дальнейшем, для и вообще для увеличения надёжности

поглядел код генерируемый IDE - там ещё различия(для LSE/LSI) в коде идут в void HAL_RTC_MspInit(RTC_HandleTypeDef* hrtc)
но там есть места для пользовательского кода и можно написать как надо

в догонку, а вот интересно, а можно ли в принципе несколько раз вызвать функции подобные HAL_RCC_OscConfig
в одни и те же регистры конфигурации (отвечающие за тактирование) писать разные значения подряд,

Сумбурно, но думаю поймёте что хотел спросить

Re: Резервирование LSE LSI

Чт май 18, 2023 11:01:25

Как при невозможности запуска RTC от низкочастотного внешнего (LSE) (часового кварца), перейти на работу от внутреннего LSI

После установки бита RCC_CR_HSEON ждать выставления RCC_CR_HSERDY не до посинения, а какое-то разумное время (у меня это просто счетчик до 0x0FFF), после чего в зависимости от успешности RCC_CR_HSERDY выставлять или не выставлять RCC_CFGR_PLLSRC а также делители.
Вообще, странный вопрос, в даташите же приведены все флаги.
Как я понял первая проверка при запуске контроллера в HAL

А вот кактус сами ешьте.

Re: Резервирование LSE LSI

Чт май 18, 2023 14:51:52

Откушу как я кактусу..
получилось сделать так
Код:
void HAL_RTC_MspInit(RTC_HandleTypeDef* hrtc)
{
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
  if(hrtc->Instance==RTC)
  {
  /* USER CODE BEGIN RTC_MspInit 0 */

  //КОД КОТОРЫЙ ГЕНЕРИРУЕТ КУБ НЕ ТРОГАЕМ А делаем по своему:
     //этот глобальный флаг придуман мной и устанавливается в stm32f4xx_hal_rcc.c в функции  __weak HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef  *RCC_OscInitStruct) в коде /* Set the new LSE configuration ----------*/ вместо return HAL_TIMEOUT;
     //при обновлении проекта не забыть исправить
                                         //_LSE_FAILURE = 1;//флаг что незапустился LSE низкочастотный кварц для RTC
                                        //break;
                                            //return HAL_TIMEOUT; - закомментировать

  if (_LSE_FAILURE==1) { //не смогли запустить внешний часовой кварц - запустим от внутреннего гена
                        PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
                        PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;//ВНУТРЕНН�?Й ГЕН
                        if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)  Error_Handler();//ЗАВ�?САЕМ - Н�? ОД�?Н ГЕНЕРАТОР ДЛЯ ЧАСОВ НЕ ЗАПУСТ�?Л�?
                       }

  else {//запустим внешним кварцем
       PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
       PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
       if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)   Error_Handler();//ЗАВ�?САЕМ
       }

  __HAL_RCC_RTC_ENABLE();
  return;// не дадим выполниться такому же коду куба далее

  /* USER CODE END RTC_MspInit 0 */

  /** Initializes the peripherals clock
  */
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
    PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    {
      Error_Handler();
    }

    /* Peripheral clock enable */
    __HAL_RCC_RTC_ENABLE();
  /* USER CODE BEGIN RTC_MspInit 1 */

  /* USER CODE END RTC_MspInit 1 */
  }

}


ну и в __weak HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) меняем кусочек
Код:
    /* Set the new LSE configuration ----------*/
    __HAL_RCC_LSE_CONFIG(RCC_OscInitStruct->LSEState);
    /* Check the LSE State */
    if((RCC_OscInitStruct->LSEState) != RCC_LSE_OFF)
    {
      /* Get Start Tick*/
      tickstart = HAL_GetTick();

      /* Wait till LSE is ready */
      while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
      {
        if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)//
        {
            _LSE_FAILURE = 1;//флаг что незапустился LSE низкочастотный кварц для RTC
            break;
            //return HAL_TIMEOUT;
        }
      }
    }
    else


Недостаток этого способа, что IDE переписывает функцию при вызове (как его правильно назвать то) Pinout & Configuration
надо каждый раз незабыть вставить две строчки да extern ... (неиспользование HAL не рассматриваю)

кварц выпаивать лишний раз не хочу - проверял работоспособность идеи так:
включаю питание, запускается программа(вижу по индикации светодиодом работы главного цикла) (RTC в это время видимо работает от LSE)
если включаю питание с замкнутыми выводами кварца, то примерно через секунду тоже запускается программа (это время похоже на время ожидания пока заработает кварц)
(RTC в это время видимо работает от LSI, так как HAL повесил бы программу при чтении и записи времени в часы)

Вопрос у меня поменялся поэтому, вопрос для того, кто глубоко анализировал код HAL и кому не жалко времени и может мне подсказать, не заставляя читать тщательно и долго даташит...
НЕ БУДЕТ ЛИ в таком решении каких то неучтенных мной багов, так как во все хитросплетениях регистров и порядка в них записи я глубоко влезать не хочу
Спасибо.
Ответить