czwartek, 16 lutego 2023

STM32H7 - STM32H725VGTx - Konfiguracja sprzętowa i pierwsze uruchomienie


W tym poście opiszę sposób przygotowania projektu oraz pierwsze uruchomienie projektu z układem STM32H725.


Programowanie:


Do programowania układu wykorzystałem ST-LinkV2. Opis wyprowadzeń programatora jest następujący:



Złącze do programowania zostało przygotowane w następujący sposób:


Interesuje nas podłączenie sygnałów VCC, SWDIO, SWCLK, SWO, RESET, GND.

Podłączenie powinno być następujące:

  • VCC - VCC
  • JTDO-SWO - SWO
  • JTCK-SWCLK - SWCLK
  • JTMS-SWDIO - SWDIO
  • NRST - RESET
  • GND - GND

Pin BOOT0 domyślnie jest podciągnięty to GND przez 10k rezystor. W razie konieczności można go podłączyć do VCC, gdyby był potrzebny podczas wgrywania danych, lub do uruchomienia zablokowanego układu.

Uruchomienie LDO:


Dobrym dokumentem dotyczącym projektowania płytki z układem STM32H7 jest AN5419 - Getting started with STM32H723/733, STM32H725/735 and STM32H730 Value Line hardware development.

Ogólne schematy konfiguracji SMPS oraz LDO wyglądają następująco:

W tym poście skupie się na rozwiązaniu pierwszym LDO Supply. 

STM32 Cube Programmer:


Na samym początku rozpoczynam podłączenie programatora z programem STM32 Cube Programmer. Jest to nowsza wersja programu ST-Link Utility. Dzięki niemu można zweryfikować czy podłączenie z układem jest rozpoznawane, i czy można się połączyć bez problemu z układem. 


Oprogramowanie pozwala na odczytanie danych z układu. 

Konfigurację oraz ustawienie rejestrów specjalnych:


W przypadku problemów z uruchomienie lub błędnej konfiguracji układu, program (z kilkukrotnym resetem zasilania i podłączeniem BOOT0) pozwoli na przywrócenie układu do początkowych ustawień.

Pierwsze uruchomienie:


Do pierwszego uruchomienia wykorzystam podstawową konfigurację. Z kwarcem wewnętrznym.


Konfiguracja zegara:


Na samym początku sprawdzam czy cały projekt będzie funkcjonował z zegarem wewnętrznym. Dodatkowo wprowadzam deklarację kilku pinów jako wyjścia. W celu sprawdzenia działania.

Pierwsze podłączenie:

Po podłączeniu programatora zgodnie z powyższym schematem, wykonałem pierwsze uruchomienie z uruchomionym jedynie układem LDO. Do tego celu wykorzystałem program STM32CubeProgrammer. 

W przypadku błędów sprzętowych, dotyczących konfiguracji zasilania, program podczas debugowania zawiesi się na samym początku:

  1. void SystemClock_Config(void)
  2. {
  3.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  4.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  5.  
  6.   /** Supply configuration update enable
  7.   */
  8.   //HAL_PWREx_ConfigSupply(PWR_DIRECT_SMPS_SUPPLY);
  9.   HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
  10.   /** Configure the main internal regulator output voltage
  11.   */
  12.   //__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
  13.   __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  14.  
  15.   while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
  16.   /** Initializes the RCC Oscillators according to the specified parameters
  17.   * in the RCC_OscInitTypeDef structure.
  18.   */

Dla funkcji SystemClock_Config (wygenerowanej z CubeMx) należy zmodyfikować źródło zasilania z PWR_DIRECT_SMPS_SUPPLY na PWR_LDO_SUPPLY. 

W przypadku błędnej konfiguracji źródła zasilania/lub błędnego wykonania podłączenia sprzętowego STM32 nie będzie mógł popranie przejść przez procedurę inicjalizacji i się nie uruchomi.

Błędy dostaniemy podczas debugowania np. w funkcji HAL_PWREx_ConfigSupply, a dokładniej tutaj:

  1. /* Wait till voltage level flag is set */
  2. while (__HAL_PWR_GET_FLAG (PWR_FLAG_ACTVOSRDY) == 0U)
  3. {
  4.     if ((HAL_GetTick () - tickstart) > PWR_FLAG_SETTING_DELAY)
  5.     {
  6.       return HAL_ERROR;
  7.     }
  8. }

Flaga nie zostanie poprawnie ustawiona. Przez co nie uda się popranie przejść przez procedurę uruchamiania. 

W drugiej wersji zmieniam konfigurację zegara na kwarc zewnętrzny. 


Konfiguracja kwarców polega na włączeniu kwarca głównego 25MHz oraz dodatkowego kwarca zegarkowego 32,768 KHz

W tym przypadku konfiguracja zegara będzie wyglądać nieco inaczej:

  1. void SystemClock_Config(void)
  2. {
  3.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  4.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  5.  
  6.   /** Supply configuration update enable
  7.   */
  8.   //HAL_PWREx_ConfigSupply(PWR_DIRECT_SMPS_SUPPLY);
  9.   HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
  10.   /** Configure the main internal regulator output voltage
  11.   */
  12.   __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  13.  
  14.   while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
  15.   /** Initializes the RCC Oscillators according to the specified parameters
  16.   * in the RCC_OscInitTypeDef structure.
  17.   */
  18.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48|RCC_OSCILLATORTYPE_HSE;
  19.   RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  20.   RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
  21.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  22.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  23.   RCC_OscInitStruct.PLL.PLLM = 2;
  24.   RCC_OscInitStruct.PLL.PLLN = 32;
  25.   RCC_OscInitStruct.PLL.PLLP = 1;
  26.   RCC_OscInitStruct.PLL.PLLQ = 2;
  27.   RCC_OscInitStruct.PLL.PLLR = 2;
  28.   RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
  29.   RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
  30.   RCC_OscInitStruct.PLL.PLLFRACN = 0;
  31.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  32.   {
  33.     Error_Handler();
  34.   }
  35.   /** Initializes the CPU, AHB and APB buses clocks
  36.   */
  37.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  38.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
  39.                               |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
  40.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  41.   RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
  42.   RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
  43.   RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
  44.   RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
  45.   RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
  46.   RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
  47.  
  48.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  49.   {
  50.     Error_Handler();
  51.   }
  52. }

Przykładowy projekt można pobrać z dysku Google pod tym linkiem.

Dokumentacja:


AN5419 - Getting started with STM32H723733, stm32h725735 and STM32H730. Value Line Hardware Development