add proj
This commit is contained in:
92
B-G474E-DPOW1_Keil/Core/Inc/app_config.h
Normal file
92
B-G474E-DPOW1_Keil/Core/Inc/app_config.h
Normal file
@@ -0,0 +1,92 @@
|
||||
#ifndef APP_CONFIG_H
|
||||
#define APP_CONFIG_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* B-G474E-DPOW1 quick configuration.
|
||||
*
|
||||
* SAFETY:
|
||||
* - The project configures the buck half-bridge on PB12/PB13.
|
||||
* - Keep DCDC_POWER_STAGE_ENABLE at 0 until VIN, load and oscilloscope
|
||||
* probes are ready. With 0 the firmware prints ADC values and prepares
|
||||
* HRTIM, but does not enable HRTIM outputs.
|
||||
* - If VIN comes from USB-C/USB-PD through JP1, set
|
||||
* DCDC_CONNECT_USBPD_INPUT to 1 only after checking the board jumpers.
|
||||
*/
|
||||
#define DCDC_POWER_STAGE_ENABLE 0U
|
||||
#define DCDC_CONNECT_USBPD_INPUT 0U
|
||||
|
||||
/*
|
||||
* Clock startup.
|
||||
* 0 = safest rescue mode: run directly from HSI16, no PLL switch.
|
||||
* 1 = normal performance mode: HSI16 -> PLL -> 170 MHz.
|
||||
*
|
||||
* If the debugger hangs inside SystemClock_Config(), keep this at 0 until
|
||||
* the board is recovered and ST-LINK connects reliably.
|
||||
*/
|
||||
#define CLOCK_USE_PLL_170MHZ 1U
|
||||
|
||||
#define SYSCLK_HZ 170000000UL
|
||||
#define HSI16_HZ 16000000UL
|
||||
#define USART3_BAUDRATE 115200UL
|
||||
#define DEBUG_ATTACH_DELAY_LOOPS 8000000UL
|
||||
|
||||
/*
|
||||
* HRTIM Timer C drives the onboard buck leg:
|
||||
* PB12 = BUCKBOOST_P1_DRIVE = HRTIM1_CHC1, high-side buck MOSFET
|
||||
* PB13 = BUCKBOOST_N1_DRIVE = HRTIM1_CHC2, low-side buck MOSFET
|
||||
*
|
||||
* fHRCK = fHRTIM * 32. The firmware calculates the actual period from
|
||||
* SystemCoreClock, so rescue HSI16 mode still works.
|
||||
*/
|
||||
#define DCDC_HRTIM_PERIOD_TICKS 27200U
|
||||
#define DCDC_PWM_FREQUENCY_HZ 200000UL
|
||||
#define DCDC_MIN_DUTY_TICKS 0U
|
||||
#define DCDC_MAX_DUTY_TICKS 24000U
|
||||
#define DCDC_START_DUTY_TICKS 400U
|
||||
|
||||
/*
|
||||
* Dead-time values are expressed in HRTIM dead-time ticks.
|
||||
* They are intentionally conservative starter values; verify PB12/PB13
|
||||
* with an oscilloscope before enabling the power stage.
|
||||
*/
|
||||
#define DCDC_DEADTIME_RISING_TICKS 110U
|
||||
#define DCDC_DEADTIME_FALLING_TICKS 350U
|
||||
|
||||
/*
|
||||
* ADC measurement pins on B-G474E-DPOW1:
|
||||
* PA1 = BUCKBOOST_VIN (ADC1_IN2)
|
||||
* PA2 = BUCKBOOST_I_IN_AVG (ADC1_IN3)
|
||||
* PA3 = BUCKBOOST_VOUT (ADC1_IN4)
|
||||
*
|
||||
* ST X-CUBE-DPower reference values for this board use:
|
||||
* Vout_Scaling = 0.198795180 -> ADC pin voltage = VOUT * 0.198795180
|
||||
* Iin_Scaling = 0.721543408 -> ADC pin voltage = IIN * 0.721543408 V/A
|
||||
*
|
||||
* VIN uses the same divider value by default here. If your hardware revision
|
||||
* or solder bridge setup differs, adjust DCDC_VIN_SCALE_PPM after measuring.
|
||||
*/
|
||||
#define ADC_REFERENCE_MV 3300U
|
||||
#define ADC_FULL_SCALE_COUNTS 4095U
|
||||
#define DCDC_VOUT_SCALE_PPM 198795UL
|
||||
#define DCDC_VIN_SCALE_PPM 198795UL
|
||||
#define DCDC_IIN_UV_PER_MA 721UL
|
||||
|
||||
/* Starter setpoints and protection thresholds. */
|
||||
#define DCDC_TARGET_VOUT_MV 3300U
|
||||
#define DCDC_MIN_VIN_MV 4500U
|
||||
#define DCDC_MAX_VOUT_MV 3800U
|
||||
#define DCDC_MAX_INPUT_CURRENT_MA 300U
|
||||
#define DCDC_HARD_INPUT_CURRENT_MA 450U
|
||||
|
||||
/*
|
||||
* Simple voltage loop gains for the starter firmware.
|
||||
* Duty command = feed-forward + proportional + integral - current limiting.
|
||||
* Tune these gently with a current-limited supply and a scope.
|
||||
*/
|
||||
#define DCDC_KP_TICKS_PER_100MV 90
|
||||
#define DCDC_KI_TICKS_PER_100MV 3
|
||||
#define DCDC_CURRENT_LIMIT_KP 60
|
||||
|
||||
#endif
|
||||
11
B-G474E-DPOW1_Keil/Core/Inc/board.h
Normal file
11
B-G474E-DPOW1_Keil/Core/Inc/board.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef BOARD_H
|
||||
#define BOARD_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void Board_Init(void);
|
||||
uint32_t Board_Millis(void);
|
||||
void Board_DelayMs(uint32_t delay_ms);
|
||||
void Board_FatalError(void);
|
||||
|
||||
#endif
|
||||
48
B-G474E-DPOW1_Keil/Core/Inc/dcdc.h
Normal file
48
B-G474E-DPOW1_Keil/Core/Inc/dcdc.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef DCDC_H
|
||||
#define DCDC_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t vin_raw;
|
||||
uint16_t iin_raw;
|
||||
uint16_t vout_raw;
|
||||
uint32_t vin_mv;
|
||||
uint32_t iin_ma;
|
||||
uint32_t vout_mv;
|
||||
} DCDC_Measurements;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DCDC_STATE_STOPPED = 0,
|
||||
DCDC_STATE_READY,
|
||||
DCDC_STATE_RUNNING,
|
||||
DCDC_STATE_FAULT
|
||||
} DCDC_State;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DCDC_FAULT_NONE = 0,
|
||||
DCDC_FAULT_UNDERVOLTAGE,
|
||||
DCDC_FAULT_OVERVOLTAGE,
|
||||
DCDC_FAULT_OVERCURRENT,
|
||||
DCDC_FAULT_HRTIM
|
||||
} DCDC_Fault;
|
||||
|
||||
void DCDC_Init(void);
|
||||
void DCDC_Start(void);
|
||||
void DCDC_Stop(void);
|
||||
void DCDC_ControlStep(void);
|
||||
void DCDC_ReadMeasurements(DCDC_Measurements *out);
|
||||
|
||||
DCDC_State DCDC_GetState(void);
|
||||
DCDC_Fault DCDC_GetFault(void);
|
||||
bool DCDC_IsHrtimReady(void);
|
||||
uint32_t DCDC_GetDutyTicks(void);
|
||||
uint32_t DCDC_GetPeriodTicks(void);
|
||||
const char *DCDC_StateText(DCDC_State state);
|
||||
const char *DCDC_FaultText(DCDC_Fault fault);
|
||||
|
||||
#endif
|
||||
9
B-G474E-DPOW1_Keil/Core/Inc/retarget.h
Normal file
9
B-G474E-DPOW1_Keil/Core/Inc/retarget.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef RETARGET_H
|
||||
#define RETARGET_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void Retarget_Init(uint32_t baudrate);
|
||||
void Retarget_PutChar(char ch);
|
||||
|
||||
#endif
|
||||
189
B-G474E-DPOW1_Keil/Core/Src/board.c
Normal file
189
B-G474E-DPOW1_Keil/Core/Src/board.c
Normal file
@@ -0,0 +1,189 @@
|
||||
#include "board.h"
|
||||
|
||||
#include "app_config.h"
|
||||
#include <stdbool.h>
|
||||
#include "stm32g474xx.h"
|
||||
|
||||
#define CLOCK_STARTUP_TIMEOUT 1000000UL
|
||||
|
||||
static volatile uint32_t s_ms_ticks;
|
||||
|
||||
static void SystemClock_Config(void);
|
||||
static bool wait_mask_set(volatile uint32_t *reg, uint32_t mask);
|
||||
static bool wait_mask_clear(volatile uint32_t *reg, uint32_t mask);
|
||||
static bool wait_mask_value(volatile uint32_t *reg, uint32_t mask, uint32_t value);
|
||||
static bool Flash_SetLatency(uint32_t latency);
|
||||
static void Clock_UseHsi16(void);
|
||||
|
||||
void Board_Init(void)
|
||||
{
|
||||
SystemClock_Config();
|
||||
|
||||
if (SysTick_Config(SystemCoreClock / 1000U) != 0U)
|
||||
{
|
||||
Board_FatalError();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Board_Millis(void)
|
||||
{
|
||||
return s_ms_ticks;
|
||||
}
|
||||
|
||||
void Board_DelayMs(uint32_t delay_ms)
|
||||
{
|
||||
uint32_t start = Board_Millis();
|
||||
while ((Board_Millis() - start) < delay_ms)
|
||||
{
|
||||
__NOP();
|
||||
}
|
||||
}
|
||||
|
||||
void Board_FatalError(void)
|
||||
{
|
||||
__disable_irq();
|
||||
while (1)
|
||||
{
|
||||
__NOP();
|
||||
}
|
||||
}
|
||||
|
||||
void SysTick_Handler(void)
|
||||
{
|
||||
s_ms_ticks++;
|
||||
}
|
||||
|
||||
static void SystemClock_Config(void)
|
||||
{
|
||||
Clock_UseHsi16();
|
||||
|
||||
#if CLOCK_USE_PLL_170MHZ
|
||||
/* Enable PWR and switch the STM32G474 regulator to Range 1 boost. */
|
||||
RCC->APB1ENR1 |= RCC_APB1ENR1_PWREN;
|
||||
(void)RCC->APB1ENR1;
|
||||
|
||||
PWR->CR1 = (PWR->CR1 & ~PWR_CR1_VOS) | PWR_CR1_VOS_0;
|
||||
PWR->CR5 &= ~PWR_CR5_R1MODE;
|
||||
if (!wait_mask_clear(&PWR->SR2, PWR_SR2_VOSF))
|
||||
{
|
||||
Clock_UseHsi16();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* ST G474 power examples use FLASH_LATENCY_4 for 170 MHz.
|
||||
* Set only the latency field first, then switch SYSCLK, then enable cache.
|
||||
*/
|
||||
if (!Flash_SetLatency(FLASH_ACR_LATENCY_4WS))
|
||||
{
|
||||
Clock_UseHsi16();
|
||||
return;
|
||||
}
|
||||
|
||||
RCC->CR |= RCC_CR_HSION;
|
||||
if (!wait_mask_set(&RCC->CR, RCC_CR_HSIRDY))
|
||||
{
|
||||
Clock_UseHsi16();
|
||||
return;
|
||||
}
|
||||
|
||||
/* HSI16 / 4 * 85 / 2 = 170 MHz. */
|
||||
RCC->CR &= ~RCC_CR_PLLON;
|
||||
if (!wait_mask_clear(&RCC->CR, RCC_CR_PLLRDY))
|
||||
{
|
||||
Clock_UseHsi16();
|
||||
return;
|
||||
}
|
||||
|
||||
RCC->PLLCFGR =
|
||||
RCC_PLLCFGR_PLLSRC_HSI |
|
||||
(3UL << RCC_PLLCFGR_PLLM_Pos) |
|
||||
(85UL << RCC_PLLCFGR_PLLN_Pos) |
|
||||
RCC_PLLCFGR_PLLREN;
|
||||
|
||||
RCC->CR |= RCC_CR_PLLON;
|
||||
if (!wait_mask_set(&RCC->CR, RCC_CR_PLLRDY))
|
||||
{
|
||||
Clock_UseHsi16();
|
||||
return;
|
||||
}
|
||||
|
||||
RCC->CFGR =
|
||||
RCC_CFGR_HPRE_DIV1 |
|
||||
RCC_CFGR_PPRE1_DIV1 |
|
||||
RCC_CFGR_PPRE2_DIV1 |
|
||||
RCC_CFGR_SW_PLL;
|
||||
|
||||
if (!wait_mask_value(&RCC->CFGR, RCC_CFGR_SWS, RCC_CFGR_SWS_PLL))
|
||||
{
|
||||
Clock_UseHsi16();
|
||||
return;
|
||||
}
|
||||
|
||||
FLASH->ACR |= FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_PRFTEN;
|
||||
SystemCoreClockUpdate();
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool wait_mask_set(volatile uint32_t *reg, uint32_t mask)
|
||||
{
|
||||
uint32_t timeout = CLOCK_STARTUP_TIMEOUT;
|
||||
while (((*reg & mask) != mask) && (timeout > 0U))
|
||||
{
|
||||
timeout--;
|
||||
}
|
||||
|
||||
return timeout > 0U;
|
||||
}
|
||||
|
||||
static bool wait_mask_clear(volatile uint32_t *reg, uint32_t mask)
|
||||
{
|
||||
uint32_t timeout = CLOCK_STARTUP_TIMEOUT;
|
||||
while (((*reg & mask) != 0U) && (timeout > 0U))
|
||||
{
|
||||
timeout--;
|
||||
}
|
||||
|
||||
return timeout > 0U;
|
||||
}
|
||||
|
||||
static bool wait_mask_value(volatile uint32_t *reg, uint32_t mask, uint32_t value)
|
||||
{
|
||||
uint32_t timeout = CLOCK_STARTUP_TIMEOUT;
|
||||
while (((*reg & mask) != value) && (timeout > 0U))
|
||||
{
|
||||
timeout--;
|
||||
}
|
||||
|
||||
return timeout > 0U;
|
||||
}
|
||||
|
||||
static bool Flash_SetLatency(uint32_t latency)
|
||||
{
|
||||
uint32_t timeout = CLOCK_STARTUP_TIMEOUT;
|
||||
|
||||
FLASH->ACR = (FLASH->ACR & ~FLASH_ACR_LATENCY) | latency;
|
||||
while (((FLASH->ACR & FLASH_ACR_LATENCY) != latency) && (timeout > 0U))
|
||||
{
|
||||
timeout--;
|
||||
}
|
||||
|
||||
return timeout > 0U;
|
||||
}
|
||||
|
||||
static void Clock_UseHsi16(void)
|
||||
{
|
||||
RCC->CR |= RCC_CR_HSION;
|
||||
(void)wait_mask_set(&RCC->CR, RCC_CR_HSIRDY);
|
||||
|
||||
(void)Flash_SetLatency(FLASH_ACR_LATENCY_0WS);
|
||||
|
||||
RCC->CFGR =
|
||||
RCC_CFGR_HPRE_DIV1 |
|
||||
RCC_CFGR_PPRE1_DIV1 |
|
||||
RCC_CFGR_PPRE2_DIV1 |
|
||||
RCC_CFGR_SW_HSI;
|
||||
|
||||
(void)wait_mask_value(&RCC->CFGR, RCC_CFGR_SWS, RCC_CFGR_SWS_HSI);
|
||||
SystemCoreClockUpdate();
|
||||
}
|
||||
462
B-G474E-DPOW1_Keil/Core/Src/dcdc.c
Normal file
462
B-G474E-DPOW1_Keil/Core/Src/dcdc.c
Normal file
@@ -0,0 +1,462 @@
|
||||
#include "dcdc.h"
|
||||
|
||||
#include "app_config.h"
|
||||
#include "board.h"
|
||||
#include "stm32g474xx.h"
|
||||
|
||||
#define HRTIM_TIMER_C_INDEX 2U
|
||||
#define ADC_SAMPLE_TIME_47CYCLES 5U
|
||||
#define HRTIM_DLL_READY_TIMEOUT 1000000UL
|
||||
|
||||
static DCDC_State s_state = DCDC_STATE_STOPPED;
|
||||
static DCDC_Fault s_fault = DCDC_FAULT_NONE;
|
||||
static uint32_t s_duty_ticks = DCDC_START_DUTY_TICKS;
|
||||
static uint32_t s_period_ticks = DCDC_HRTIM_PERIOD_TICKS;
|
||||
static int32_t s_integrator_ticks;
|
||||
static bool s_hrtim_ready;
|
||||
|
||||
static void gpio_init_for_dcdc(void);
|
||||
static void adc1_init(void);
|
||||
static uint16_t adc1_read_channel(uint32_t channel);
|
||||
static bool hrtim1_timer_c_init(void);
|
||||
static bool hrtim1_wait_dll_ready(void);
|
||||
static void hrtim1_outputs_enable(bool enable);
|
||||
static void hrtim1_set_duty(uint32_t duty_ticks);
|
||||
static uint32_t hrtim_period_from_clock(void);
|
||||
static uint32_t hrtim_max_duty_ticks(void);
|
||||
static uint32_t adc_raw_to_mv(uint16_t raw);
|
||||
static uint32_t sense_mv_to_voltage_mv(uint32_t sense_mv, uint32_t scale_ppm);
|
||||
static uint32_t sense_mv_to_current_ma(uint32_t sense_mv);
|
||||
static void set_usbpd_input_switch(bool enable);
|
||||
static void set_loads_off(void);
|
||||
static void latch_fault(DCDC_Fault fault);
|
||||
|
||||
void DCDC_Init(void)
|
||||
{
|
||||
gpio_init_for_dcdc();
|
||||
set_usbpd_input_switch(false);
|
||||
set_loads_off();
|
||||
|
||||
adc1_init();
|
||||
s_hrtim_ready = hrtim1_timer_c_init();
|
||||
if (s_hrtim_ready)
|
||||
{
|
||||
hrtim1_outputs_enable(false);
|
||||
}
|
||||
|
||||
s_state = DCDC_STATE_READY;
|
||||
s_fault = DCDC_FAULT_NONE;
|
||||
}
|
||||
|
||||
void DCDC_Start(void)
|
||||
{
|
||||
if (s_fault != DCDC_FAULT_NONE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!s_hrtim_ready)
|
||||
{
|
||||
latch_fault(DCDC_FAULT_HRTIM);
|
||||
return;
|
||||
}
|
||||
|
||||
#if DCDC_CONNECT_USBPD_INPUT
|
||||
set_usbpd_input_switch(true);
|
||||
#endif
|
||||
|
||||
s_integrator_ticks = 0;
|
||||
hrtim1_set_duty(DCDC_START_DUTY_TICKS);
|
||||
HRTIM1->sMasterRegs.MCR |= HRTIM_MCR_TCCEN;
|
||||
hrtim1_outputs_enable(true);
|
||||
s_state = DCDC_STATE_RUNNING;
|
||||
}
|
||||
|
||||
void DCDC_Stop(void)
|
||||
{
|
||||
hrtim1_outputs_enable(false);
|
||||
hrtim1_set_duty(DCDC_MIN_DUTY_TICKS);
|
||||
HRTIM1->sMasterRegs.MCR &= ~HRTIM_MCR_TCCEN;
|
||||
set_usbpd_input_switch(false);
|
||||
s_state = DCDC_STATE_STOPPED;
|
||||
}
|
||||
|
||||
void DCDC_ControlStep(void)
|
||||
{
|
||||
DCDC_Measurements m;
|
||||
int32_t error_mv;
|
||||
int32_t feed_forward;
|
||||
int32_t duty;
|
||||
|
||||
DCDC_ReadMeasurements(&m);
|
||||
|
||||
if (s_state != DCDC_STATE_RUNNING)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m.vin_mv < DCDC_MIN_VIN_MV)
|
||||
{
|
||||
latch_fault(DCDC_FAULT_UNDERVOLTAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m.vout_mv > DCDC_MAX_VOUT_MV)
|
||||
{
|
||||
latch_fault(DCDC_FAULT_OVERVOLTAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m.iin_ma > DCDC_HARD_INPUT_CURRENT_MA)
|
||||
{
|
||||
latch_fault(DCDC_FAULT_OVERCURRENT);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Starter buck controller:
|
||||
* 1. feed-forward estimates duty from Vout/Vin,
|
||||
* 2. PI term removes static voltage error,
|
||||
* 3. current term pulls duty down before hard over-current trips.
|
||||
*
|
||||
* This is deliberately readable, not a final compensated SMPS loop.
|
||||
*/
|
||||
feed_forward = (int32_t)(((uint64_t)DCDC_TARGET_VOUT_MV * s_period_ticks) / m.vin_mv);
|
||||
error_mv = (int32_t)DCDC_TARGET_VOUT_MV - (int32_t)m.vout_mv;
|
||||
|
||||
s_integrator_ticks += (error_mv * DCDC_KI_TICKS_PER_100MV) / 100;
|
||||
if (s_integrator_ticks > 3000)
|
||||
{
|
||||
s_integrator_ticks = 3000;
|
||||
}
|
||||
else if (s_integrator_ticks < -3000)
|
||||
{
|
||||
s_integrator_ticks = -3000;
|
||||
}
|
||||
|
||||
duty = feed_forward +
|
||||
((error_mv * DCDC_KP_TICKS_PER_100MV) / 100) +
|
||||
s_integrator_ticks;
|
||||
|
||||
if (m.iin_ma > DCDC_MAX_INPUT_CURRENT_MA)
|
||||
{
|
||||
duty -= (int32_t)((m.iin_ma - DCDC_MAX_INPUT_CURRENT_MA) * DCDC_CURRENT_LIMIT_KP);
|
||||
}
|
||||
|
||||
if (duty < (int32_t)DCDC_MIN_DUTY_TICKS)
|
||||
{
|
||||
duty = (int32_t)DCDC_MIN_DUTY_TICKS;
|
||||
}
|
||||
else if (duty > (int32_t)hrtim_max_duty_ticks())
|
||||
{
|
||||
duty = (int32_t)hrtim_max_duty_ticks();
|
||||
}
|
||||
|
||||
hrtim1_set_duty((uint32_t)duty);
|
||||
}
|
||||
|
||||
void DCDC_ReadMeasurements(DCDC_Measurements *out)
|
||||
{
|
||||
uint32_t vin_sense_mv;
|
||||
uint32_t iin_sense_mv;
|
||||
uint32_t vout_sense_mv;
|
||||
|
||||
out->vin_raw = adc1_read_channel(2U);
|
||||
out->iin_raw = adc1_read_channel(3U);
|
||||
out->vout_raw = adc1_read_channel(4U);
|
||||
|
||||
vin_sense_mv = adc_raw_to_mv(out->vin_raw);
|
||||
iin_sense_mv = adc_raw_to_mv(out->iin_raw);
|
||||
vout_sense_mv = adc_raw_to_mv(out->vout_raw);
|
||||
|
||||
out->vin_mv = sense_mv_to_voltage_mv(vin_sense_mv, DCDC_VIN_SCALE_PPM);
|
||||
out->iin_ma = sense_mv_to_current_ma(iin_sense_mv);
|
||||
out->vout_mv = sense_mv_to_voltage_mv(vout_sense_mv, DCDC_VOUT_SCALE_PPM);
|
||||
}
|
||||
|
||||
DCDC_State DCDC_GetState(void)
|
||||
{
|
||||
return s_state;
|
||||
}
|
||||
|
||||
DCDC_Fault DCDC_GetFault(void)
|
||||
{
|
||||
return s_fault;
|
||||
}
|
||||
|
||||
bool DCDC_IsHrtimReady(void)
|
||||
{
|
||||
return s_hrtim_ready;
|
||||
}
|
||||
|
||||
uint32_t DCDC_GetDutyTicks(void)
|
||||
{
|
||||
return s_duty_ticks;
|
||||
}
|
||||
|
||||
uint32_t DCDC_GetPeriodTicks(void)
|
||||
{
|
||||
return s_period_ticks;
|
||||
}
|
||||
|
||||
const char *DCDC_StateText(DCDC_State state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case DCDC_STATE_STOPPED: return "stopped";
|
||||
case DCDC_STATE_READY: return "ready";
|
||||
case DCDC_STATE_RUNNING: return "running";
|
||||
case DCDC_STATE_FAULT: return "fault";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
const char *DCDC_FaultText(DCDC_Fault fault)
|
||||
{
|
||||
switch (fault)
|
||||
{
|
||||
case DCDC_FAULT_NONE: return "none";
|
||||
case DCDC_FAULT_UNDERVOLTAGE: return "vin undervoltage";
|
||||
case DCDC_FAULT_OVERVOLTAGE: return "vout overvoltage";
|
||||
case DCDC_FAULT_OVERCURRENT: return "input overcurrent";
|
||||
case DCDC_FAULT_HRTIM: return "hrtim dll timeout";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static void gpio_init_for_dcdc(void)
|
||||
{
|
||||
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN | RCC_AHB2ENR_GPIOBEN | RCC_AHB2ENR_GPIOCEN;
|
||||
(void)RCC->AHB2ENR;
|
||||
|
||||
/* PA1/PA2/PA3 are analog feedback signals: VIN, input current, VOUT. */
|
||||
GPIOA->MODER |= (3UL << (1U * 2U)) | (3UL << (2U * 2U)) | (3UL << (3U * 2U));
|
||||
GPIOA->PUPDR &= ~((3UL << (1U * 2U)) | (3UL << (2U * 2U)) | (3UL << (3U * 2U)));
|
||||
|
||||
/* PB12/PB13 are HRTIM1 Timer C outputs for the synchronous buck leg. */
|
||||
GPIOB->MODER &= ~((3UL << (12U * 2U)) | (3UL << (13U * 2U)));
|
||||
GPIOB->MODER |= ((2UL << (12U * 2U)) | (2UL << (13U * 2U)));
|
||||
GPIOB->OTYPER &= ~((1UL << 12U) | (1UL << 13U));
|
||||
GPIOB->OSPEEDR |= ((3UL << (12U * 2U)) | (3UL << (13U * 2U)));
|
||||
GPIOB->PUPDR &= ~((3UL << (12U * 2U)) | (3UL << (13U * 2U)));
|
||||
GPIOB->AFR[1] &= ~((0xFUL << ((12U - 8U) * 4U)) | (0xFUL << ((13U - 8U) * 4U)));
|
||||
GPIOB->AFR[1] |= ((13UL << ((12U - 8U) * 4U)) | (13UL << ((13U - 8U) * 4U)));
|
||||
|
||||
/* PC3 controls USBPD_VBUS to VIN switch. PC14/PC15 switch onboard loads. */
|
||||
GPIOC->MODER &= ~((3UL << (3U * 2U)) | (3UL << (14U * 2U)) | (3UL << (15U * 2U)));
|
||||
GPIOC->MODER |= ((1UL << (3U * 2U)) | (1UL << (14U * 2U)) | (1UL << (15U * 2U)));
|
||||
GPIOC->OTYPER &= ~((1UL << 3U) | (1UL << 14U) | (1UL << 15U));
|
||||
GPIOC->OSPEEDR |= ((2UL << (3U * 2U)) | (2UL << (14U * 2U)) | (2UL << (15U * 2U)));
|
||||
GPIOC->PUPDR &= ~((3UL << (3U * 2U)) | (3UL << (14U * 2U)) | (3UL << (15U * 2U)));
|
||||
}
|
||||
|
||||
static void adc1_init(void)
|
||||
{
|
||||
RCC->AHB2ENR |= RCC_AHB2ENR_ADC12EN;
|
||||
(void)RCC->AHB2ENR;
|
||||
|
||||
/* Synchronous ADC clock HCLK/4 = 42.5 MHz. */
|
||||
ADC12_COMMON->CCR = (ADC12_COMMON->CCR & ~ADC_CCR_CKMODE) |
|
||||
(ADC_CCR_CKMODE_1 | ADC_CCR_CKMODE_0);
|
||||
|
||||
ADC1->CR &= ~ADC_CR_DEEPPWD;
|
||||
ADC1->CR |= ADC_CR_ADVREGEN;
|
||||
Board_DelayMs(1U);
|
||||
|
||||
ADC1->CR |= ADC_CR_ADCAL;
|
||||
while ((ADC1->CR & ADC_CR_ADCAL) != 0U)
|
||||
{
|
||||
__NOP();
|
||||
}
|
||||
|
||||
ADC1->CFGR = ADC_CFGR_OVRMOD;
|
||||
ADC1->SMPR1 =
|
||||
(ADC_SAMPLE_TIME_47CYCLES << ADC_SMPR1_SMP2_Pos) |
|
||||
(ADC_SAMPLE_TIME_47CYCLES << ADC_SMPR1_SMP3_Pos) |
|
||||
(ADC_SAMPLE_TIME_47CYCLES << ADC_SMPR1_SMP4_Pos);
|
||||
|
||||
ADC1->ISR = ADC_ISR_ADRDY;
|
||||
ADC1->CR |= ADC_CR_ADEN;
|
||||
while ((ADC1->ISR & ADC_ISR_ADRDY) == 0U)
|
||||
{
|
||||
__NOP();
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t adc1_read_channel(uint32_t channel)
|
||||
{
|
||||
ADC1->SQR1 = (channel << ADC_SQR1_SQ1_Pos);
|
||||
ADC1->ISR = ADC_ISR_EOC | ADC_ISR_EOS;
|
||||
ADC1->CR |= ADC_CR_ADSTART;
|
||||
|
||||
while ((ADC1->ISR & ADC_ISR_EOC) == 0U)
|
||||
{
|
||||
__NOP();
|
||||
}
|
||||
|
||||
return (uint16_t)(ADC1->DR & 0x0FFFU);
|
||||
}
|
||||
|
||||
static bool hrtim1_timer_c_init(void)
|
||||
{
|
||||
HRTIM_Timerx_TypeDef *timer = &HRTIM1->sTimerxRegs[HRTIM_TIMER_C_INDEX];
|
||||
|
||||
RCC->APB2ENR |= RCC_APB2ENR_HRTIM1EN;
|
||||
(void)RCC->APB2ENR;
|
||||
|
||||
HRTIM1->sCommonRegs.ODISR = HRTIM_ODISR_TC1ODIS | HRTIM_ODISR_TC2ODIS;
|
||||
s_period_ticks = hrtim_period_from_clock();
|
||||
|
||||
HRTIM1->sCommonRegs.ICR = HRTIM_ICR_DLLRDYC;
|
||||
HRTIM1->sCommonRegs.DLLCR = HRTIM_DLLCR_CALEN |
|
||||
HRTIM_DLLCR_CALRTE_1 |
|
||||
HRTIM_DLLCR_CAL;
|
||||
/* In rescue clock mode DLLRDY may never rise; keep diagnostics alive. */
|
||||
if (!hrtim1_wait_dll_ready())
|
||||
{
|
||||
HRTIM1->sCommonRegs.ODISR = HRTIM_ODISR_TC1ODIS | HRTIM_ODISR_TC2ODIS;
|
||||
HRTIM1->sMasterRegs.MCR &= ~HRTIM_MCR_TCCEN;
|
||||
return false;
|
||||
}
|
||||
|
||||
timer->TIMxCR = HRTIM_TIMCR_CONT;
|
||||
timer->PERxR = s_period_ticks;
|
||||
timer->REPxR = 0U;
|
||||
timer->CMP1xR = DCDC_MIN_DUTY_TICKS;
|
||||
timer->CMP2xR = hrtim_max_duty_ticks();
|
||||
timer->CMP3xR = 1000U;
|
||||
|
||||
timer->DTxR =
|
||||
((DCDC_DEADTIME_RISING_TICKS & 0x1FFUL) << HRTIM_DTR_DTR_Pos) |
|
||||
((DCDC_DEADTIME_FALLING_TICKS & 0x1FFUL) << HRTIM_DTR_DTF_Pos) |
|
||||
(HRTIM_DTR_DTPRSC_1 | HRTIM_DTR_DTPRSC_0);
|
||||
|
||||
/*
|
||||
* Complementary buck PWM:
|
||||
* CHC1 goes active at period event and inactive at CMP1.
|
||||
* CHC2 goes active at CMP1 and inactive at period event.
|
||||
* HRTIM dead-time block delays transitions to avoid shoot-through.
|
||||
*/
|
||||
timer->SETx1R = HRTIM_SET1R_PER;
|
||||
timer->RSTx1R = HRTIM_RST1R_CMP1;
|
||||
timer->SETx2R = HRTIM_SET2R_CMP1;
|
||||
timer->RSTx2R = HRTIM_RST2R_PER;
|
||||
timer->OUTxR = HRTIM_OUTR_DTEN | HRTIM_OUTR_FAULT1_1 | HRTIM_OUTR_FAULT2_1;
|
||||
|
||||
/* Trigger point for future synchronized ADC sampling. */
|
||||
HRTIM1->sCommonRegs.ADC1R = HRTIM_ADC1R_AD1TCC3;
|
||||
|
||||
HRTIM1->sMasterRegs.MCR &= ~HRTIM_MCR_TCCEN;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool hrtim1_wait_dll_ready(void)
|
||||
{
|
||||
uint32_t timeout = HRTIM_DLL_READY_TIMEOUT;
|
||||
|
||||
while (((HRTIM1->sCommonRegs.ISR & HRTIM_ISR_DLLRDY) == 0U) && (timeout > 0U))
|
||||
{
|
||||
timeout--;
|
||||
}
|
||||
|
||||
return timeout > 0U;
|
||||
}
|
||||
|
||||
static void hrtim1_outputs_enable(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
HRTIM1->sCommonRegs.OENR = HRTIM_OENR_TC1OEN | HRTIM_OENR_TC2OEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
HRTIM1->sCommonRegs.ODISR = HRTIM_ODISR_TC1ODIS | HRTIM_ODISR_TC2ODIS;
|
||||
}
|
||||
}
|
||||
|
||||
static void hrtim1_set_duty(uint32_t duty_ticks)
|
||||
{
|
||||
if (duty_ticks < DCDC_MIN_DUTY_TICKS)
|
||||
{
|
||||
duty_ticks = DCDC_MIN_DUTY_TICKS;
|
||||
}
|
||||
else if (duty_ticks > hrtim_max_duty_ticks())
|
||||
{
|
||||
duty_ticks = hrtim_max_duty_ticks();
|
||||
}
|
||||
|
||||
HRTIM1->sTimerxRegs[HRTIM_TIMER_C_INDEX].CMP1xR = duty_ticks;
|
||||
s_duty_ticks = duty_ticks;
|
||||
}
|
||||
|
||||
static uint32_t hrtim_period_from_clock(void)
|
||||
{
|
||||
uint64_t ticks = (((uint64_t)SystemCoreClock * 32ULL) + (DCDC_PWM_FREQUENCY_HZ / 2ULL)) /
|
||||
DCDC_PWM_FREQUENCY_HZ;
|
||||
|
||||
if (ticks < 100ULL)
|
||||
{
|
||||
ticks = 100ULL;
|
||||
}
|
||||
else if (ticks > 0xFFFFULL)
|
||||
{
|
||||
ticks = 0xFFFFULL;
|
||||
}
|
||||
|
||||
return (uint32_t)ticks;
|
||||
}
|
||||
|
||||
static uint32_t hrtim_max_duty_ticks(void)
|
||||
{
|
||||
uint32_t max_ticks = DCDC_MAX_DUTY_TICKS;
|
||||
|
||||
if (s_period_ticks > 10U && max_ticks >= (s_period_ticks - 1U))
|
||||
{
|
||||
max_ticks = s_period_ticks - 1U;
|
||||
}
|
||||
|
||||
return max_ticks;
|
||||
}
|
||||
|
||||
static uint32_t adc_raw_to_mv(uint16_t raw)
|
||||
{
|
||||
return ((uint32_t)raw * ADC_REFERENCE_MV) / ADC_FULL_SCALE_COUNTS;
|
||||
}
|
||||
|
||||
static uint32_t sense_mv_to_voltage_mv(uint32_t sense_mv, uint32_t scale_ppm)
|
||||
{
|
||||
return (uint32_t)(((uint64_t)sense_mv * 1000000ULL) / scale_ppm);
|
||||
}
|
||||
|
||||
static uint32_t sense_mv_to_current_ma(uint32_t sense_mv)
|
||||
{
|
||||
return (sense_mv * 1000UL) / DCDC_IIN_UV_PER_MA;
|
||||
}
|
||||
|
||||
static void set_usbpd_input_switch(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
GPIOC->BSRR = (1UL << 3U);
|
||||
}
|
||||
else
|
||||
{
|
||||
GPIOC->BRR = (1UL << 3U);
|
||||
}
|
||||
}
|
||||
|
||||
static void set_loads_off(void)
|
||||
{
|
||||
GPIOC->BRR = (1UL << 14U) | (1UL << 15U);
|
||||
}
|
||||
|
||||
static void latch_fault(DCDC_Fault fault)
|
||||
{
|
||||
hrtim1_outputs_enable(false);
|
||||
hrtim1_set_duty(DCDC_MIN_DUTY_TICKS);
|
||||
HRTIM1->sMasterRegs.MCR &= ~HRTIM_MCR_TCCEN;
|
||||
set_usbpd_input_switch(false);
|
||||
|
||||
s_fault = fault;
|
||||
s_state = DCDC_STATE_FAULT;
|
||||
}
|
||||
70
B-G474E-DPOW1_Keil/Core/Src/main.c
Normal file
70
B-G474E-DPOW1_Keil/Core/Src/main.c
Normal file
@@ -0,0 +1,70 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "app_config.h"
|
||||
#include "board.h"
|
||||
#include "dcdc.h"
|
||||
#include "retarget.h"
|
||||
#include "stm32g474xx.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
uint32_t last_control_ms = 0U;
|
||||
uint32_t last_print_ms = 0U;
|
||||
volatile uint32_t debug_attach_delay;
|
||||
|
||||
/*
|
||||
* Short rescue window after reset. It lets ST-LINK attach before the
|
||||
* firmware reconfigures clocks and power peripherals.
|
||||
*/
|
||||
for (debug_attach_delay = 0U; debug_attach_delay < DEBUG_ATTACH_DELAY_LOOPS; debug_attach_delay++)
|
||||
{
|
||||
__NOP();
|
||||
}
|
||||
|
||||
Board_Init();
|
||||
Retarget_Init(USART3_BAUDRATE);
|
||||
DCDC_Init();
|
||||
|
||||
printf("\nB-G474E-DPOW1 DCDC starter project\n");
|
||||
printf("USART3 retarget printf: %lu baud\n", (unsigned long)USART3_BAUDRATE);
|
||||
printf("SystemCoreClock: %lu Hz\n", (unsigned long)SystemCoreClock);
|
||||
printf("PWM: %lu Hz, period=%lu HRTIM ticks\n",
|
||||
(unsigned long)DCDC_PWM_FREQUENCY_HZ,
|
||||
(unsigned long)DCDC_GetPeriodTicks());
|
||||
printf("HRTIM DLL: %s\n", DCDC_IsHrtimReady() ? "ready" : "not ready");
|
||||
|
||||
#if DCDC_POWER_STAGE_ENABLE
|
||||
printf("Power stage: ENABLED. Check VIN/current limit before flashing.\n");
|
||||
DCDC_Start();
|
||||
#else
|
||||
printf("Power stage: disabled in app_config.h; ADC monitor only.\n");
|
||||
#endif
|
||||
|
||||
while (1)
|
||||
{
|
||||
uint32_t now = Board_Millis();
|
||||
|
||||
if ((now - last_control_ms) >= 1U)
|
||||
{
|
||||
last_control_ms = now;
|
||||
DCDC_ControlStep();
|
||||
}
|
||||
|
||||
if ((now - last_print_ms) >= 500U)
|
||||
{
|
||||
DCDC_Measurements m;
|
||||
last_print_ms = now;
|
||||
DCDC_ReadMeasurements(&m);
|
||||
|
||||
printf("state=%s fault=%s hrtim=%s vin=%lumV iin=%lumA vout=%lumV duty=%lu/%lu\n",
|
||||
DCDC_StateText(DCDC_GetState()),
|
||||
DCDC_FaultText(DCDC_GetFault()),
|
||||
DCDC_IsHrtimReady() ? "ready" : "not-ready",
|
||||
(unsigned long)m.vin_mv,
|
||||
(unsigned long)m.iin_ma,
|
||||
(unsigned long)m.vout_mv,
|
||||
(unsigned long)DCDC_GetDutyTicks(),
|
||||
(unsigned long)DCDC_GetPeriodTicks());
|
||||
}
|
||||
}
|
||||
}
|
||||
101
B-G474E-DPOW1_Keil/Core/Src/retarget.c
Normal file
101
B-G474E-DPOW1_Keil/Core/Src/retarget.c
Normal file
@@ -0,0 +1,101 @@
|
||||
#include "retarget.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "app_config.h"
|
||||
#include "stm32g474xx.h"
|
||||
|
||||
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 6000000)
|
||||
#pragma import(__use_no_semihosting)
|
||||
|
||||
struct __FILE
|
||||
{
|
||||
int handle;
|
||||
};
|
||||
#elif defined(__ARMCC_VERSION)
|
||||
__asm(".global __use_no_semihosting\n");
|
||||
#endif
|
||||
|
||||
FILE __stdout;
|
||||
FILE __stdin;
|
||||
|
||||
static void gpio_pc10_pc11_to_usart3(void)
|
||||
{
|
||||
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOCEN;
|
||||
(void)RCC->AHB2ENR;
|
||||
|
||||
/* PC10 = USART3_TX, PC11 = USART3_RX, AF7: ST-LINK VCP on CN3. */
|
||||
GPIOC->MODER &= ~((3UL << (10U * 2U)) | (3UL << (11U * 2U)));
|
||||
GPIOC->MODER |= ((2UL << (10U * 2U)) | (2UL << (11U * 2U)));
|
||||
|
||||
GPIOC->OTYPER &= ~((1UL << 10U) | (1UL << 11U));
|
||||
GPIOC->OSPEEDR |= ((3UL << (10U * 2U)) | (3UL << (11U * 2U)));
|
||||
GPIOC->PUPDR &= ~((3UL << (10U * 2U)) | (3UL << (11U * 2U)));
|
||||
|
||||
GPIOC->AFR[1] &= ~((0xFUL << ((10U - 8U) * 4U)) | (0xFUL << ((11U - 8U) * 4U)));
|
||||
GPIOC->AFR[1] |= ((7UL << ((10U - 8U) * 4U)) | (7UL << ((11U - 8U) * 4U)));
|
||||
}
|
||||
|
||||
void Retarget_Init(uint32_t baudrate)
|
||||
{
|
||||
gpio_pc10_pc11_to_usart3();
|
||||
|
||||
RCC->APB1ENR1 |= RCC_APB1ENR1_USART3EN;
|
||||
(void)RCC->APB1ENR1;
|
||||
|
||||
USART3->CR1 = 0U;
|
||||
USART3->CR2 = 0U;
|
||||
USART3->CR3 = 0U;
|
||||
|
||||
/* APB1 is not prescaled; use the clock that really started. */
|
||||
USART3->BRR = (SystemCoreClock + (baudrate / 2U)) / baudrate;
|
||||
USART3->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE;
|
||||
}
|
||||
|
||||
void Retarget_PutChar(char ch)
|
||||
{
|
||||
while ((USART3->ISR & USART_ISR_TXE_TXFNF) == 0U)
|
||||
{
|
||||
__NOP();
|
||||
}
|
||||
USART3->TDR = (uint8_t)ch;
|
||||
}
|
||||
|
||||
int fputc(int ch, FILE *f)
|
||||
{
|
||||
(void)f;
|
||||
|
||||
if (ch == '\n')
|
||||
{
|
||||
Retarget_PutChar('\r');
|
||||
}
|
||||
|
||||
Retarget_PutChar((char)ch);
|
||||
return ch;
|
||||
}
|
||||
|
||||
int fgetc(FILE *f)
|
||||
{
|
||||
(void)f;
|
||||
|
||||
while ((USART3->ISR & USART_ISR_RXNE_RXFNE) == 0U)
|
||||
{
|
||||
__NOP();
|
||||
}
|
||||
|
||||
return (int)(USART3->RDR & 0xFFU);
|
||||
}
|
||||
|
||||
void _ttywrch(int ch)
|
||||
{
|
||||
Retarget_PutChar((char)ch);
|
||||
}
|
||||
|
||||
void _sys_exit(int return_code)
|
||||
{
|
||||
(void)return_code;
|
||||
while (1)
|
||||
{
|
||||
__NOP();
|
||||
}
|
||||
}
|
||||
56
B-G474E-DPOW1_Keil/Core/Src/system_stm32g4xx.c
Normal file
56
B-G474E-DPOW1_Keil/Core/Src/system_stm32g4xx.c
Normal file
@@ -0,0 +1,56 @@
|
||||
#include "stm32g474xx.h"
|
||||
#include "app_config.h"
|
||||
|
||||
uint32_t SystemCoreClock = 16000000UL;
|
||||
|
||||
const uint8_t AHBPrescTable[16] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 2, 3, 4, 6, 7, 8, 9
|
||||
};
|
||||
|
||||
const uint8_t APBPrescTable[8] =
|
||||
{
|
||||
0, 0, 0, 0, 1, 2, 3, 4
|
||||
};
|
||||
|
||||
void SystemInit(void)
|
||||
{
|
||||
/* Enable FPU access before C runtime starts. */
|
||||
SCB->CPACR |= (0xFU << 20);
|
||||
|
||||
#if defined(VECT_TAB_SRAM)
|
||||
SCB->VTOR = SRAM_BASE;
|
||||
#else
|
||||
SCB->VTOR = FLASH_BASE;
|
||||
#endif
|
||||
}
|
||||
|
||||
void SystemCoreClockUpdate(void)
|
||||
{
|
||||
uint32_t sysclk = 16000000UL;
|
||||
uint32_t sws = RCC->CFGR & RCC_CFGR_SWS;
|
||||
|
||||
if (sws == RCC_CFGR_SWS_PLL)
|
||||
{
|
||||
uint32_t pllsrc_hz = 16000000UL;
|
||||
uint32_t pllcfgr = RCC->PLLCFGR;
|
||||
uint32_t pllm = ((pllcfgr & RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U;
|
||||
uint32_t plln = ((pllcfgr & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos);
|
||||
uint32_t pllr_bits = ((pllcfgr & RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos);
|
||||
uint32_t pllr = (pllr_bits + 1U) * 2U;
|
||||
|
||||
if ((pllcfgr & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSE)
|
||||
{
|
||||
pllsrc_hz = 8000000UL;
|
||||
}
|
||||
|
||||
sysclk = (pllsrc_hz / pllm) * plln / pllr;
|
||||
}
|
||||
else if (sws == RCC_CFGR_SWS_HSE)
|
||||
{
|
||||
sysclk = 8000000UL;
|
||||
}
|
||||
|
||||
SystemCoreClock = sysclk >> AHBPrescTable[(RCC->CFGR & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos];
|
||||
}
|
||||
Reference in New Issue
Block a user