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

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Родился
Сообщения: 6
Зарегистрирован: Ср фев 15, 2023 07:34:11

Сообщение userstm2023 »

Здравствуйте коты
Как при невозможности запуска 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
в одни и те же регистры конфигурации (отвечающие за тактирование) писать разные значения подряд,

Сумбурно, но думаю поймёте что хотел спросить
Реклама
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Сообщение COKPOWEHEU »

Как при невозможности запуска RTC от низкочастотного внешнего (LSE) (часового кварца), перейти на работу от внутреннего LSI
После установки бита RCC_CR_HSEON ждать выставления RCC_CR_HSERDY не до посинения, а какое-то разумное время (у меня это просто счетчик до 0x0FFF), после чего в зависимости от успешности RCC_CR_HSERDY выставлять или не выставлять RCC_CFGR_PLLSRC а также делители.
Вообще, странный вопрос, в даташите же приведены все флаги.
Как я понял первая проверка при запуске контроллера в HAL
А вот кактус сами ешьте.
Реклама
Родился
Сообщения: 6
Зарегистрирован: Ср фев 15, 2023 07:34:11

Сообщение userstm2023 »

Откушу как я кактусу..
получилось сделать так

Код: Выделить всё

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 и кому не жалко времени и может мне подсказать, не заставляя читать тщательно и долго даташит...
НЕ БУДЕТ ЛИ в таком решении каких то неучтенных мной багов, так как во все хитросплетениях регистров и порядка в них записи я глубоко влезать не хочу
Спасибо.
Ответить

Вернуться в «ARM»