См. Справочное руководство (pdf), раздел 6.2.3 «Часы MSI», «Аппаратная автоматическая калибровка с LSE (режим PLL)» и раздел 6.4.1 «Регистр управления часами (RCC_CR).) "
В вашем коде есть:
RCC->CR |= RCC_CR_MSIPLLEN;
Но перед тем, как включить режим PLL на часах MSI, нужно сделать две вещи:
- Внешнийдолжен быть установлен низкочастотный резонатор или генератор (например, тактовый кварц 32768 Гц)
- Как сказано в описании Бит 2 MSIPLLEN : MSIPLLEN должен быть включен после включения LSE (LSEON включен)) и готово (LSERDY устанавливается аппаратно). Существует аппаратная защита, позволяющая избежать включения MSIPLLEN, если LSE не готов.
Итак, если у вас установлена LSE, сначала вы должны включитьвключите его и подождите, пока он не будет готов:
RCC->BDCR |= (RCC_BDCR_LSEON);
/*Make sure LSE is ready*/
while(!(RCC->BDCR & RCC_BDCR_LSERDY));
Но, вероятно, вам не нужно использовать функцию PLL от MSI, потому что USART гораздо более устойчив к отклонениям частоты.Тогда режим MSI-PLL должен быть отключен.
Микроконтроллеры STM32 имеют некоторые защитные механизмы, чтобы избежать неправильного переключения источника синхронизации.Некоторые биты не могут быть установлены, пока источник синхронизации не будет готов, или не могут быть очищены, если источник синхронизации используется.Они описаны в справочном руководстве в битовых описаниях.
Поэтому, пожалуйста, внимательно сравните все шаги, которые вы делаете с руководством.
UPD Как указано вдругой ответ
/*Turn off PLL to allow to make changes*/
RCC->CR &= ~(RCC_CR_PLLON_Msk);
/*Make sure PLL is locked*/
while(!(RCC->CR & RCC_CR_PLLRDY));
Вы не можете заблокировать PLL, когда он отключен.Итак, цикл while будет работать вечно.
UPD2
Перед включением PLL вы забудете установить его источник (биты PLLSRC в PLLCFGR).Т.е.:
// set MSI as the source for PLL
RCC->PLLCFGR = (RCC->PLLCFGR & ~RCC_PLLCFGR_PLLSRC_Msk) | RCC_PLLCFGR_PLLSRC_MSI;