walnux/arch/arm/src/stm32h5/stm32_pwr.c
stbenn 904b6ff85b H5 with NSH support for Nucleo-H563ZI.
Made fixes to issues from CI. Nxstyle and defconfig syntax.

This is a combination of 6 commits.

Adding STM32H5 arch files. With comments addressed.

Created stm32h5 directory to add support for the H5 chip, and used a Nucleo-H563ZI dev board during development. The goal was to get a working nutshell through the STLink connector on the board.

Remove board/docs changes for PR update.

Squash commits into one for PR guideline conformity.

trying to fix build issues

Fix format from review

Nucleo-H563ZI support for NSH.

Created stm32h5 directory to add support for the H5 chip, and used a Nucleo-H563ZI dev board during development. The goal was to get a working nutshell through the STLink connector on the board.

Fix switch default case placement.

NXstyle fixes

Renaming files

rename stm32h5_gpio.x files

rename h5 hsi48 files

Rename h5 idle file

rename stm32h5_irq.c

Rename some rcc functions and stm32h5_rcc.c

rename stm32h5_rcc.h

Rename stm32h5_pwr.x

lowputc renames

timerisr renames

uart renamed

rename serial file

rename start

Turn off the defines that enable DMA on serial

remove DMA Kconfig options

Remove H5 documentation. Will add in a future PR.

Fix styling and defconfig improper syntax.
2024-11-06 10:28:49 +08:00

309 lines
8.5 KiB
C

/****************************************************************************
* arch/arm/src/stm32h5/stm32_pwr.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/arch.h>
#include <assert.h>
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include "arm_internal.h"
#include "stm32_pwr.h"
#include "stm32_rcc.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define PWR_TIMEOUT (10 * CONFIG_BOARD_LOOPSPERMSEC)
/****************************************************************************
* Private Functions
****************************************************************************/
static inline uint32_t stm32h5_pwr_getreg(uint16_t offset)
{
return getreg32(STM32_PWR_BASE + (uint32_t)offset);
}
static inline void stm32h5_pwr_putreg(uint16_t offset, uint16_t value)
{
putreg32(value, STM32_PWR_BASE + (uint32_t)offset);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: stm32_pwr_enablebkp
*
* Description:
* Enables access to the backup domain (RTC registers, RTC backup data
* registers and backup SRAM).
*
* Input Parameters:
* writable True: enable ability to write to backup domain registers
*
* Returned Value:
* True: The backup domain was previously writable.
*
****************************************************************************/
bool stm32_pwr_enablebkp(bool writable)
{
uint16_t regval;
bool waswritable;
/* Get the current state of the PWR disable Backup domain register */
regval = stm32h5_pwr_getreg(STM32_PWR_DBPCR_OFFSET);
waswritable = ((regval & PWR_DBPCR_DBP) != 0);
/* Enable or disable the ability to write */
if (waswritable && !writable)
{
/* Disable backup domain access */
regval &= ~PWR_DBPCR_DBP;
stm32h5_pwr_putreg(STM32_PWR_DBPCR_OFFSET, regval);
}
else if (!waswritable && writable)
{
/* Enable backup domain access */
regval |= PWR_DBPCR_DBP;
stm32h5_pwr_putreg(STM32_PWR_DBPCR_OFFSET, regval);
/* Enable does not happen right away */
up_udelay(4);
}
return waswritable;
}
/****************************************************************************
* Name stm32_pwr_adjustvcore
*
* Description:
* Adjusts the voltage used for digital peripherals (V_CORE) before
* raising or after decreasing the system clock frequency. Compare
* [RM0481], section 10.7 Dynamic voltage scaling management.
*
* Note: Use only for VCore supplied with internal LDO or SMPS.
* For supplying VCore externally, use stm32_pwr_adjustvos_ext.
*
* Input Parameters:
* sysclock - The frequency in Hertz the system clock will or has been set
* to.
*
****************************************************************************/
void stm32_pwr_adjustvcore(unsigned sysclock)
{
volatile int timeout;
uint32_t vos_range;
uint32_t actvos;
/* Select the applicable V_CORE voltage range depending on the new system
* clock frequency.
*/
DEBUGASSERT(sysclock <= 250000000);
if (sysclock > 200000000)
{
vos_range = PWR_VOSCR_VOS_RANGE0;
}
else if (sysclock > 150000000)
{
vos_range = PWR_VOSCR_VOS_RANGE1;
}
else if (sysclock > 100000000)
{
vos_range = PWR_VOSCR_VOS_RANGE2;
}
else
{
vos_range = PWR_VOSCR_VOS_RANGE3;
}
actvos = (getreg32(STM32_PWR_VOSSR) & PWR_VOSSR_ACTVOS_MASK);
modreg32(vos_range, PWR_VOSCR_VOS_MASK, STM32_PWR_VOSCR);
if (vos_range > actvos)
{
/* Wait until the new V_CORE voltage range has been applied. */
for (timeout = PWR_TIMEOUT; timeout; timeout--)
{
if (getreg32(STM32_PWR_VOSSR) & PWR_VOSSR_VOSRDY)
{
break;
}
}
DEBUGASSERT(timeout > 0);
}
else if (vos_range < actvos)
{
/* Wait until the voltage level for the currently used VOS is ready. */
for (timeout = PWR_TIMEOUT; timeout; timeout--)
{
if (getreg32(STM32_PWR_VOSSR) & PWR_VOSSR_ACTVOSRDY)
{
break;
}
}
DEBUGASSERT(timeout > 0);
}
else
{
/* actvos == vos_range. Do nothing. */
return;
}
}
/****************************************************************************
* Name stm32_pwr_adjustvos_ext
*
* Description:
* When changing VCore with an external supply, VOS must
* incrementally select intermediate levels.
*
* When increasing the performance:
* 1. First, voltage scaling must be incremented (for example when
* changing from VOS3 to VOS0, lower levels must be selected in the
* VOS[1:0] bits: VOS2, VOS1, and then VOS0).
* 2. The external voltage can be increased.
* 3. The system frequency can be increased.
*
* When decreasing the performance:
* 1. The system frequency MUST be decreased.
* 2. The external voltage MUST be decreased.
* 3. The voltage scaling can be decremented (for example when changing
* from VOS1 to VOS3, lower levels must be selected in the VOS[1:0]
* bits: VOS2, and then VOS3)
*
* Input Parameters:
* sysclock - The frequency in Hertz the system clock will or has been set
* to.
*
****************************************************************************/
void stm32_pwr_adjustvos_ext(unsigned sysclock)
{
uint32_t vos_range;
uint32_t vos_range_val;
uint32_t vos_range_set;
uint32_t actvos_val;
/* Select the applicable V_CORE voltage range depending on the new system
* clock frequency.
*/
DEBUGASSERT(sysclock <= 250000000);
if (sysclock > 200000000)
{
vos_range = PWR_VOSCR_VOS_RANGE0;
}
else if (sysclock > 150000000)
{
vos_range = PWR_VOSCR_VOS_RANGE1;
}
else if (sysclock > 100000000)
{
vos_range = PWR_VOSCR_VOS_RANGE2;
}
else
{
vos_range = PWR_VOSCR_VOS_RANGE3;
}
vos_range_val = (vos_range & PWR_VOSCR_VOS_MASK) >> PWR_VOSCR_VOS_SHIFT;
actvos_val = ((getreg32(STM32_PWR_VOSSR) & PWR_VOSSR_ACTVOS_MASK) >>
PWR_VOSSR_ACTVOS_SHIFT);
if (vos_range_val > actvos_val)
{
/* Gradually Increase VOS Scale */
for (int i = actvos_val; i < vos_range_val; ++i)
{
if (i == 0)
{
vos_range_set = PWR_VOSCR_VOS_RANGE2;
}
else if (i == 1)
{
vos_range_set = PWR_VOSCR_VOS_RANGE1;
}
else /* (i == 2) */
{
vos_range_set = PWR_VOSCR_VOS_RANGE0;
}
modreg32(vos_range_set, PWR_VOSCR_VOS_MASK, STM32_PWR_VOSCR);
up_udelay(1);
}
}
else if (vos_range_val < actvos_val)
{
/* Gradually Decrease VOS Scale */
for (int i = actvos_val; i > vos_range_val; --i)
{
if (i == 1)
{
vos_range_set = PWR_VOSCR_VOS_RANGE3;
}
else if (i == 2)
{
vos_range_set = PWR_VOSCR_VOS_RANGE2;
}
else /* (i == 3) */
{
vos_range_set = PWR_VOSCR_VOS_RANGE1;
}
modreg32(vos_range_set, PWR_VOSCR_VOS_MASK, STM32_PWR_VOSCR);
up_udelay(1);
}
}
else
{
/* actvos == new vos. Do nothing. */
return;
}
}