Sync betaflight to Gitea

This commit is contained in:
2026-08-03 16:37:10 +08:00
commit ad3163cf91
4712 changed files with 3301380 additions and 0 deletions
+4
View File
@@ -0,0 +1,4 @@
*.bin
*.elf
*.o
*.map
+4
View File
@@ -0,0 +1,4 @@
#Opt Id Name Type IP Offset Binary
P 0x1 fsbl-openbl Binary none 0x0 ../../STM32N6/Projects/STM32N6570-DK/Applications/OpenBootloader/Binaries/NOR_Binary/OpenBootloader_STM32N6570-DK-trusted.stm32
P 0x3 fsbl-extfl Binary none 0x0 ../../STM32N6/Projects/STM32N6570-DK/Applications/OpenBootloader/Binaries/NOR_Binary/MX66UW1G45G_STM32N6570-DK-OBL.bin
P 0x4 combined Binary nor0 0x0 prebuilt/combined.bin
1 #Opt Id Name Type IP Offset Binary
2 P 0x1 fsbl-openbl Binary none 0x0 ../../STM32N6/Projects/STM32N6570-DK/Applications/OpenBootloader/Binaries/NOR_Binary/OpenBootloader_STM32N6570-DK-trusted.stm32
3 P 0x3 fsbl-extfl Binary none 0x0 ../../STM32N6/Projects/STM32N6570-DK/Applications/OpenBootloader/Binaries/NOR_Binary/MX66UW1G45G_STM32N6570-DK-OBL.bin
4 P 0x4 combined Binary nor0 0x0 prebuilt/combined.bin
@@ -0,0 +1,4 @@
#Opt Id Name Type IP Offset Binary
P 0x1 fsbl-openbl Binary none 0x0 ../../STM32N6/Projects/STM32N6570-DK/Applications/OpenBootloader/Binaries/NOR_Binary/OpenBootloader_STM32N6570-DK-trusted.stm32
P 0x3 fsbl-extfl Binary none 0x0 ../../STM32N6/Projects/STM32N6570-DK/Applications/OpenBootloader/Binaries/NOR_Binary/MX66UW1G45G_STM32N6570-DK-OBL.bin
P 0x4 bf-fsbl Binary nor0 0x0 prebuilt/bf_as_fsbl.stm32
1 #Opt Id Name Type IP Offset Binary
2 P 0x1 fsbl-openbl Binary none 0x0 ../../STM32N6/Projects/STM32N6570-DK/Applications/OpenBootloader/Binaries/NOR_Binary/OpenBootloader_STM32N6570-DK-trusted.stm32
3 P 0x3 fsbl-extfl Binary none 0x0 ../../STM32N6/Projects/STM32N6570-DK/Applications/OpenBootloader/Binaries/NOR_Binary/MX66UW1G45G_STM32N6570-DK-OBL.bin
4 P 0x4 bf-fsbl Binary nor0 0x0 prebuilt/bf_as_fsbl.stm32
@@ -0,0 +1,4 @@
#Opt Id Name Type IP Offset Binary
P 0x1 fsbl-openbl Binary none 0x0 ../../STM32N6/Projects/STM32N6570-DK/Applications/OpenBootloader/Binaries/NOR_Binary/OpenBootloader_STM32N6570-DK-trusted.stm32
P 0x3 fsbl-extfl Binary none 0x0 ../../STM32N6/Projects/STM32N6570-DK/Applications/OpenBootloader/Binaries/NOR_Binary/MX66UW1G45G_STM32N6570-DK-OBL.bin
P 0x4 obl-bf Binary nor0 0x0 /tmp/obl_bf_combined.bin
1 #Opt Id Name Type IP Offset Binary
2 P 0x1 fsbl-openbl Binary none 0x0 ../../STM32N6/Projects/STM32N6570-DK/Applications/OpenBootloader/Binaries/NOR_Binary/OpenBootloader_STM32N6570-DK-trusted.stm32
3 P 0x3 fsbl-extfl Binary none 0x0 ../../STM32N6/Projects/STM32N6570-DK/Applications/OpenBootloader/Binaries/NOR_Binary/MX66UW1G45G_STM32N6570-DK-OBL.bin
4 P 0x4 obl-bf Binary nor0 0x0 /tmp/obl_bf_combined.bin
@@ -0,0 +1,4 @@
#Opt Id Name Type IP Offset Binary
P 0x1 fsbl-openbl Binary none 0x0 ../../../modules/STM32N6/Projects/STM32N6570-DK/Applications/OpenBootloader/Binaries/NOR_Binary/OpenBootloader_STM32N6570-DK-trusted.stm32
P 0x3 fsbl-extfl Binary none 0x0 ../../../modules/STM32N6/Projects/STM32N6570-DK/Applications/OpenBootloader/Binaries/NOR_Binary/MX66UW1G45G_STM32N6570-DK-OBL.bin
P 0x4 obl-only Binary nor0 0x0 ../n6_obl/prebuilt/obl_only_combined.bin
1 #Opt Id Name Type IP Offset Binary
2 P 0x1 fsbl-openbl Binary none 0x0 ../../../modules/STM32N6/Projects/STM32N6570-DK/Applications/OpenBootloader/Binaries/NOR_Binary/OpenBootloader_STM32N6570-DK-trusted.stm32
3 P 0x3 fsbl-extfl Binary none 0x0 ../../../modules/STM32N6/Projects/STM32N6570-DK/Applications/OpenBootloader/Binaries/NOR_Binary/MX66UW1G45G_STM32N6570-DK-OBL.bin
4 P 0x4 obl-only Binary nor0 0x0 ../n6_obl/prebuilt/obl_only_combined.bin
+186
View File
@@ -0,0 +1,186 @@
# STM32N6 FSBL stub — standalone build. Not invoked by betaflight's main
# build; the signed blob in prebuilt/ is what gets bundled into the combined
# image.
#
# Usage:
# make # produce n6_fsbl.elf and n6_fsbl.bin
# make signed # also re-sign the .bin into prebuilt/
# make combined # rebuild prebuilt/combined.bin = signed FSBL padded
# # to 1 MiB + RAM_ONLY betaflight .bin (read by the
# # FSBL stub from 0x70100000 and shadow-copied into
# # AXISRAM1 at 0x24000000)
# make clean
#
# `combined` requires CONFIG and CONFIG_DIR for the betaflight build:
# make combined CONFIG=STM32N657DK_DSK320 CONFIG_DIR=$$HOME/src/config
ROOT := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))/../../../..)
TOOLCHAIN_BIN := $(ROOT)/tools/arm-gnu-toolchain-13.3.rel1-x86_64-arm-none-eabi/bin
PREFIX := $(if $(wildcard $(TOOLCHAIN_BIN)/arm-none-eabi-gcc),$(TOOLCHAIN_BIN)/,)arm-none-eabi-
CC := $(PREFIX)gcc
AS := $(PREFIX)gcc -x assembler-with-cpp
LD := $(PREFIX)gcc
OBJCOPY := $(PREFIX)objcopy
SIZE := $(PREFIX)size
HAL_DIR := $(ROOT)/lib/modules/STM32N6/Drivers/STM32N6xx_HAL_Driver
CMSIS_ST := $(ROOT)/lib/modules/STM32N6/Drivers/CMSIS/Device/ST/STM32N6xx/Include
CMSIS := $(ROOT)/lib/modules/STM32N6/Drivers/CMSIS/Include
INCLUDES := \
-I. \
-I$(HAL_DIR)/Inc \
-I$(CMSIS_ST) \
-I$(CMSIS)
# Match the betaflight main build: no -mcmse and no CPU_IN_SECURE_STATE, so
# peripheral macros resolve to the NS (0x4xxxxxxx) aliases that the boot
# ROM's RIFSC defaults allow. Defining CPU_IN_SECURE_STATE pulls in
# HAL_MPU_*_NS variants that need -mcmse.
DEFINES := \
-DSTM32N657xx \
-DUSE_HAL_DRIVER \
-DHSE_VALUE=48000000
ARCH_FLAGS := -mthumb -mcpu=cortex-m55 -mfloat-abi=hard -mfpu=fpv5-d16
CFLAGS := \
$(ARCH_FLAGS) \
-Os -g3 \
-ffunction-sections -fdata-sections \
-Wall -Wextra \
-Wno-unused-parameter \
-std=gnu11 \
$(INCLUDES) $(DEFINES)
ASFLAGS := $(ARCH_FLAGS) -g3 $(INCLUDES) $(DEFINES)
LDSCRIPT := STM32N657XX_FSBL.ld
LDFLAGS := \
$(ARCH_FLAGS) \
-T$(LDSCRIPT) \
-nostartfiles \
-specs=nano.specs -specs=nosys.specs \
-Wl,--gc-sections \
-Wl,-Map=n6_fsbl.map \
-Wl,--print-memory-usage
LOCAL_C_SRCS := \
main.c \
stm32n6xx_hal_msp.c \
stm32n6xx_it.c \
system_stm32n6xx_fsbl.c
HAL_C_SRCS := \
stm32n6xx_hal.c \
stm32n6xx_hal_cortex.c \
stm32n6xx_hal_rcc.c \
stm32n6xx_hal_rcc_ex.c \
stm32n6xx_hal_pwr.c \
stm32n6xx_hal_pwr_ex.c \
stm32n6xx_hal_gpio.c \
stm32n6xx_hal_xspi.c \
stm32n6xx_hal_dma.c \
stm32n6xx_hal_dma_ex.c
LOCAL_OBJS := $(LOCAL_C_SRCS:.c=.o) startup_stm32n657xx_fsbl.o
HAL_OBJS := $(HAL_C_SRCS:.c=.hal.o)
OBJS := $(LOCAL_OBJS) $(HAL_OBJS)
ELF := n6_fsbl.elf
BIN := n6_fsbl.bin
# Override SIGNING_TOOL on the make command line if STM32CubeProgrammer's bin
# directory isn't on $PATH, e.g.:
# make signed SIGNING_TOOL=/path/to/STM32_SigningTool_CLI
SIGNING_TOOL ?= STM32_SigningTool_CLI
SIGNED_BLOB := prebuilt/n6_fsbl_signed.stm32
# Combined-image inputs. The signed FSBL stub + XIP-linked betaflight
# image (linked at 0x70100000, runs in-place from XSPI). The stub brings
# XSPI memory-mapped + jumps to 0x70100000 without copying or deinit'ing
# the peripheral.
CONFIG ?= STM32N657DK_DSK320
COMBINED := prebuilt/combined.bin
FSBL_SLOT := 1048576 # 1 MiB — XSPI offset where the BF XIP slot starts
BF_OBJ := $(ROOT)/obj
BF_BIN := $(BF_OBJ)/betaflight_2026.6.0-alpha_STM32N657_$(CONFIG).bin
BF_HEX := $(BF_OBJ)/betaflight_2026.6.0-alpha_STM32N657_$(CONFIG).hex
.PHONY: all signed combined bf-ram bf-ram-elf clean
all: $(BIN)
$(BIN): $(ELF)
$(OBJCOPY) -O binary $< $@
$(SIZE) $<
$(ELF): $(OBJS) $(LDSCRIPT)
$(LD) $(LDFLAGS) $(OBJS) -o $@
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
%.o: %.s
$(AS) $(ASFLAGS) -c $< -o $@
%.hal.o: $(HAL_DIR)/Src/%.c
$(CC) $(CFLAGS) -c $< -o $@
# Re-sign and overwrite the committed blob. Run only after verifying the
# rebuilt stub on hardware. -t ssbl produces Binary type 0x0 in the v2.3
# header, which is what the N6 boot ROM accepts; -t fsbl produces type
# 0x10 and is rejected.
signed: $(SIGNED_BLOB)
$(SIGNED_BLOB): $(BIN) | prebuilt
$(SIGNING_TOOL) -bin $< -nk -of 0x80000000 -t ssbl -hv 2.3 -align -o $@ -s
prebuilt:
mkdir -p $@
# Build the betaflight XIP ELF/BIN via the main build. bf-xip-elf is phony
# so the recursive make is always invoked (it handles its own incremental
# dependency tracking).
bf-xip: $(BF_BIN)
bf-xip-elf:
$(MAKE) -C $(ROOT) CONFIG_DIR=$(CONFIG_DIR) CONFIG=$(CONFIG) XIP=1 binary
$(BF_BIN): bf-xip-elf
# Combined flash image: signed FSBL padded to FSBL_SLOT, then the XIP
# betaflight image at offset 0x100000. cp --no-preserve=mode strips the
# read-only bit on the signed source so truncate can grow it.
combined: $(COMBINED)
$(COMBINED): $(SIGNED_BLOB) $(BF_BIN) | prebuilt
cp --no-preserve=mode $(SIGNED_BLOB) $@.tmp
truncate -s $(FSBL_SLOT) $@.tmp
cat $(BF_BIN) >> $@.tmp
mv $@.tmp $@
# BF-as-FSBL debug variant: build the entire betaflight image with
# BF_AS_FSBL=1 (link via STM32N657XX_FSBL_FULL.ld), sign the resulting .bin
# with the same SSBL recipe used for the stub, and write it directly to
# nor0 0x0 via the OpenBootloader-staged TSV. Replaces the
# stub→XSPI-memory-map→memcpy→jump handoff for bring-up debug.
BF_FSBL_BIN := $(BF_OBJ)/../betaflight_2026.6.0-alpha_STM32N657_$(CONFIG).bin
BF_FSBL_SIGNED := prebuilt/bf_as_fsbl.stm32
BF_FSBL_TSV := FlashLayout_BF_AS_FSBL.tsv
bf-as-fsbl: $(BF_FSBL_SIGNED)
bf-as-fsbl-elf:
$(MAKE) -C $(ROOT) CONFIG=$(CONFIG) BF_AS_FSBL=1 binary
$(BF_FSBL_BIN): bf-as-fsbl-elf
$(BF_FSBL_SIGNED): $(BF_FSBL_BIN) | prebuilt
$(SIGNING_TOOL) -bin $< -nk -of 0x80000000 -t ssbl -hv 2.3 -align -o $@ -s
bf-as-fsbl-flash: $(BF_FSBL_SIGNED)
STM32_Programmer_CLI -c port=USB1 mode=HotPlug -d $(BF_FSBL_TSV)
.PHONY: bf-as-fsbl bf-as-fsbl-elf bf-as-fsbl-flash
clean:
rm -f $(OBJS) $(ELF) $(BIN) n6_fsbl.map
+103
View File
@@ -0,0 +1,103 @@
/*
* Linker script for the Betaflight N6570-DK FSBL stub.
*
* Boot ROM loads the signed FSBL into AXISRAM2 secure starting at 0x34180400
* (the 0x400 offset matches `STM32_SigningTool_CLI -align`). All sections
* live in this single region — the boot ROM populates .data alongside
* .text during load, so .data LMA == VMA and the startup .data copy is a
* no-op. 256 KiB sits within the system DFU FSBL slot's payload cap and
* well below AXISRAM2's 1 MiB limit.
*/
ENTRY(Reset_Handler)
_Min_Stack_Size = 0x1000;
MEMORY
{
RAM (rwx) : ORIGIN = 0x34180400, LENGTH = 256K
}
_estack = ORIGIN(RAM) + LENGTH(RAM);
_sstack = _estack - _Min_Stack_Size;
SECTIONS
{
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector))
. = ALIGN(4);
} > RAM
.text :
{
. = ALIGN(4);
*(.text)
*(.text.*)
*(.glue_7)
*(.glue_7t)
*(.eh_frame)
. = ALIGN(4);
} > RAM
.rodata :
{
. = ALIGN(4);
*(.rodata)
*(.rodata.*)
. = ALIGN(4);
} > RAM
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > RAM
.ARM :
{
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} > RAM
_sidata = LOADADDR(.data);
.data :
{
. = ALIGN(4);
_sdata = .;
*(.data)
*(.data.*)
. = ALIGN(4);
_edata = .;
} > RAM
.bss :
{
. = ALIGN(4);
_sbss = .;
__bss_start__ = .;
*(.bss)
*(.bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
__bss_end__ = .;
} > RAM
/* Reserve stack at the top of RAM. Linker fails the build if we
* overflow into .bss. */
._stack_reservation :
{
. = ALIGN(8);
. = . + _Min_Stack_Size;
. = ALIGN(8);
} > RAM
/DISCARD/ :
{
*(.ARM.attributes)
*(.comment)
}
}
+320
View File
@@ -0,0 +1,320 @@
/*
* STM32N6 FSBL stub for the Betaflight N6 platform.
*
* Boot flow (BOOT0=USER, BOOT1=2):
* 1. Boot ROM verifies the signed FSBL header at XSPI 0x70000000,
* copies the payload to AXISRAM2 secure (0x34180400), branches to
* Reset_Handler.
* 2. Reset_Handler -> SystemInit -> .data copy / .bss zero -> main().
* 3. main() initialises XSPI2, walks MX66UW1G45G into 1S-1S-1S
* 4-byte addressing, engages memory-mapped mode, then jumps directly
* to the betaflight XIP entry at 0x70100000 (vector table SP / PC
* validated against the AXI-mapped flash window). Betaflight is
* linked execute-in-place via STM32N657XX_XIP.ld; only initialised
* data and explicit RAM-resident sections are copied to AXISRAM by
* Reset_Handler. The stub leaves XSPI2 fully configured + memory-
* mapped and does NOT deinit the peripheral before jumping.
*
* Signing recipe (output is committed under prebuilt/):
*
* STM32_SigningTool_CLI \
* -bin n6_fsbl.bin \
* -nk -of 0x80000000 -t ssbl -hv 2.3 -align \
* -o prebuilt/n6_fsbl_signed.stm32 -s
*
* -nk : empty signature, accepted by boot ROM on dev chips.
* -align : pad payload to start at 0x400 in the .stm32.
* -t ssbl: emits Binary type 0x0 in the v2.3 header. -t fsbl emits
* type 0x10 which the N6 boot ROM rejects.
*/
#include <string.h>
#include "main.h"
#define APP_XIP_BASE 0x70100000U
#define MX66_RETRIES 3
/* Inter-XSPI-step delay so the MX66 leaves the controller cleanly idle
* between commands. Empirically 250-600 ms is enough; keep generous. */
#define SETTLE_DELAY_MS 600
/* MX66UW1G45G command set (1S-1S-1S, post-reset state). */
#define MX66_CMD_RESET_ENABLE 0x66U
#define MX66_CMD_RESET 0x99U
/* 4-byte FAST_READ + 8 dummy cycles. Plain 0x13 4READ at 0 dummy only
* specs to 86 MHz; the XSPI2 kernel comes out of the boot ROM faster
* than that and 0x13 mis-samples the first data byte after the address
* phase. 0x0C with 8 dummy cycles is reliable to 133 MHz. */
#define MX66_CMD_READ_4B 0x0CU
#define MX66_CMD_READ_4B_DUMMY 8U
#define MX66_CMD_RDSR 0x05U /* Read Status Register */
#define MX66_SR_WIP 0x01U /* Write In Progress bit */
XSPI_HandleTypeDef hxspi2;
/*
* Poll the flash status register until the WIP bit is cleared.
*/
static HAL_StatusTypeDef mx66_wait_ready(uint32_t timeout_ms)
{
XSPI_RegularCmdTypeDef sCommand = {0};
uint8_t status;
uint32_t tickstart = HAL_GetTick();
sCommand.OperationType = HAL_XSPI_OPTYPE_COMMON_CFG;
sCommand.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE;
sCommand.InstructionWidth = HAL_XSPI_INSTRUCTION_8_BITS;
sCommand.Instruction = MX66_CMD_RDSR;
sCommand.DataMode = HAL_XSPI_DATA_1_LINE;
sCommand.DataLength = 1;
sCommand.AddressMode = HAL_XSPI_ADDRESS_NONE;
sCommand.AlternateBytesMode = HAL_XSPI_ALT_BYTES_NONE;
sCommand.DummyCycles = 0;
do {
if (HAL_XSPI_Command(&hxspi2, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK){
return HAL_ERROR;
}
if (HAL_XSPI_Receive(&hxspi2, &status, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
return HAL_ERROR;
}
if ((status & MX66_SR_WIP) == 0) {
return HAL_OK;
}
} while ((HAL_GetTick() - tickstart) < timeout_ms);
return HAL_TIMEOUT;
}
/* Bring up XSPI2 in 1S-1S-1S 4-byte addressing mode. MSP_Init enables
* peripheral + XSPIM + GPION clocks and configures GPIO N pins to AF11
* (XSPIM_P2). */
static void MX_XSPI2_Init(void)
{
XSPIM_CfgTypeDef sXspiManagerCfg = {0};
hxspi2.Instance = XSPI2;
hxspi2.Init.FifoThresholdByte = 4;
hxspi2.Init.MemoryMode = HAL_XSPI_SINGLE_MEM;
hxspi2.Init.MemoryType = HAL_XSPI_MEMTYPE_MACRONIX;
hxspi2.Init.MemorySize = HAL_XSPI_SIZE_1GB;
hxspi2.Init.ChipSelectHighTimeCycle = 2;
hxspi2.Init.FreeRunningClock = HAL_XSPI_FREERUNCLK_DISABLE;
hxspi2.Init.ClockMode = HAL_XSPI_CLOCK_MODE_0;
hxspi2.Init.WrapSize = HAL_XSPI_WRAP_NOT_SUPPORTED;
hxspi2.Init.ClockPrescaler = 0;
hxspi2.Init.SampleShifting = HAL_XSPI_SAMPLE_SHIFT_NONE;
hxspi2.Init.DelayHoldQuarterCycle = HAL_XSPI_DHQC_DISABLE;
hxspi2.Init.ChipSelectBoundary = HAL_XSPI_BONDARYOF_NONE;
hxspi2.Init.MaxTran = 0;
hxspi2.Init.Refresh = 0;
hxspi2.Init.MemorySelect = HAL_XSPI_CSSEL_NCS1;
if (HAL_XSPI_Init(&hxspi2) != HAL_OK) {
Error_Handler();
}
sXspiManagerCfg.nCSOverride = HAL_XSPI_CSSEL_OVR_NCS1;
sXspiManagerCfg.IOPort = HAL_XSPIM_IOPORT_2;
sXspiManagerCfg.Req2AckTime = 1;
if (HAL_XSPIM_Config(&hxspi2, &sXspiManagerCfg, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
Error_Handler();
}
}
/* Send a single 1S-1S-1S no-data command. */
static HAL_StatusTypeDef mx66_cmd_1s(uint8_t opcode)
{
XSPI_RegularCmdTypeDef cmd = {0};
cmd.OperationType = HAL_XSPI_OPTYPE_COMMON_CFG;
cmd.IOSelect = HAL_XSPI_SELECT_IO_7_0;
cmd.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE;
cmd.InstructionWidth = HAL_XSPI_INSTRUCTION_8_BITS;
cmd.InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_DISABLE;
cmd.Instruction = opcode;
cmd.AddressMode = HAL_XSPI_ADDRESS_NONE;
cmd.AlternateBytesMode = HAL_XSPI_ALT_BYTES_NONE;
cmd.DataMode = HAL_XSPI_DATA_NONE;
cmd.DummyCycles = 0;
cmd.DQSMode = HAL_XSPI_DQS_DISABLE;
return HAL_XSPI_Command(&hxspi2, &cmd, HAL_XSPI_TIMEOUT_DEFAULT_VALUE);
}
/* Send a single 8-line DTR no-data command. The chip in 8D-DTR mode
* expects a 16-bit instruction = opcode | (~opcode << 8) on all eight
* IOs; harmless if the chip is currently in 1S mode (IO[7:1] aren't
* being watched), required if it isn't. */
static HAL_StatusTypeDef mx66_cmd_8dtr(uint8_t opcode)
{
XSPI_RegularCmdTypeDef cmd = {0};
cmd.OperationType = HAL_XSPI_OPTYPE_COMMON_CFG;
cmd.IOSelect = HAL_XSPI_SELECT_IO_7_0;
cmd.InstructionMode = HAL_XSPI_INSTRUCTION_8_LINES;
cmd.InstructionWidth = HAL_XSPI_INSTRUCTION_16_BITS;
cmd.InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_ENABLE;
cmd.Instruction = ((uint16_t)opcode << 8) | (uint8_t)(~opcode);
cmd.AddressMode = HAL_XSPI_ADDRESS_NONE;
cmd.AlternateBytesMode = HAL_XSPI_ALT_BYTES_NONE;
cmd.DataMode = HAL_XSPI_DATA_NONE;
cmd.DummyCycles = 0;
cmd.DQSMode = HAL_XSPI_DQS_DISABLE;
return HAL_XSPI_Command(&hxspi2, &cmd, HAL_XSPI_TIMEOUT_DEFAULT_VALUE);
}
/* Walk MX66UW1G45G to a known 1S-1S-1S state regardless of how the boot
* ROM left it. The 8D-DTR pair drops the chip to 1S if it's there, then
* the 1S pair issues the actual reset. Datasheet requires >= 30 us
* between RESET and the next command. */
static HAL_StatusTypeDef mx66_software_reset(void)
{
for (int i = 0; i < MX66_RETRIES; i++) {
(void)mx66_cmd_8dtr(MX66_CMD_RESET_ENABLE);
(void)mx66_cmd_8dtr(MX66_CMD_RESET);
HAL_Delay(1);
if (mx66_cmd_1s(MX66_CMD_RESET_ENABLE) == HAL_OK) {
if (mx66_cmd_1s(MX66_CMD_RESET) == HAL_OK) {
HAL_Delay(1);
return mx66_wait_ready(100);
}
}
}
return HAL_ERROR;
}
/* Latch the READ_CFG and a placeholder WRITE_CFG into the XSPI handle.
* Both sides are required to advance the handle's state to CMD_CFG;
* without the write side HAL_XSPI_MemoryMapped() returns
* INVALID_SEQUENCE. The write opcode is never issued — memory-mapped
* XSPI is read-only here — so 0x12 (4-byte PAGE PROGRAM) is just a
* legal placeholder. */
static HAL_StatusTypeDef xspi2_latch_read_cmd(void)
{
XSPI_RegularCmdTypeDef cmd = {0};
cmd.IOSelect = HAL_XSPI_SELECT_IO_7_0;
cmd.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE;
cmd.InstructionWidth = HAL_XSPI_INSTRUCTION_8_BITS;
cmd.InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_DISABLE;
cmd.AddressMode = HAL_XSPI_ADDRESS_1_LINE;
cmd.AddressWidth = HAL_XSPI_ADDRESS_32_BITS;
cmd.AddressDTRMode = HAL_XSPI_ADDRESS_DTR_DISABLE;
cmd.AlternateBytesMode = HAL_XSPI_ALT_BYTES_NONE;
cmd.DataMode = HAL_XSPI_DATA_1_LINE;
cmd.DataDTRMode = HAL_XSPI_DATA_DTR_DISABLE;
cmd.DummyCycles = 0;
cmd.DQSMode = HAL_XSPI_DQS_DISABLE;
cmd.OperationType = HAL_XSPI_OPTYPE_READ_CFG;
cmd.Instruction = MX66_CMD_READ_4B; /* 4-byte FAST_READ */
cmd.DummyCycles = MX66_CMD_READ_4B_DUMMY;
if (HAL_XSPI_Command(&hxspi2, &cmd, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
return HAL_ERROR;
}
cmd.DummyCycles = 0;
cmd.OperationType = HAL_XSPI_OPTYPE_WRITE_CFG;
cmd.Instruction = 0x12U; /* 4-byte PAGE PROGRAM (placeholder) */
return HAL_XSPI_Command(&hxspi2, &cmd, HAL_XSPI_TIMEOUT_DEFAULT_VALUE);
}
static HAL_StatusTypeDef xspi2_engage_mem_mapped(void)
{
XSPI_MemoryMappedTypeDef memMappedCfg = {0};
memMappedCfg.TimeOutActivation = HAL_XSPI_TIMEOUT_COUNTER_DISABLE;
/* Disable prefetch — speculative reads against a chip in an
* unexpected mode (e.g. still 8D-DTR while we use 1S) would stall
* the AXI bus indefinitely. With prefetch off, stalls are bounded
* to a single explicit CPU read. */
memMappedCfg.NoPrefetchData = HAL_XSPI_AUTOMATIC_PREFETCH_DISABLE;
memMappedCfg.NoPrefetchAXI = HAL_XSPI_AXI_PREFETCH_DISABLE;
return HAL_XSPI_MemoryMapped(&hxspi2, &memMappedCfg);
}
static __attribute__((noreturn)) void jump_to_app(uint32_t app_base)
{
const uint32_t app_sp = *(volatile uint32_t *)(app_base);
const uint32_t app_pc = *(volatile uint32_t *)(app_base + 4U);
/* Sanity gate: SP must point into AXISRAM (0x2xxxxxxx). An erased flash
* slot reads 0xFFFFFFFF and would fail this check. */
if ((app_sp & 0xF8000000U) != 0x20000000U) {
Error_Handler();
}
HAL_SuspendTick();
__disable_irq();
/* Leave XSPI2 fully configured + memory-mapped. The app runs XIP from
* 0x70100000 — any DeInit / FORCE_RESET here would un-map the window
* and the next instruction fetch would bus-fault. */
SCB_DisableICache();
SCB_DisableDCache();
SCB->VTOR = app_base;
__DSB();
__ISB();
__set_MSP(app_sp);
/* Re-enable IRQs so the app inherits PRIMASK=0. App startup_*.s files
* that don't call cpsie would otherwise run with interrupts masked
* and SysTick never fires (HAL_Delay / PLL-lock waits would hang). */
__enable_irq();
((void (*)(void))app_pc)();
while (1) {
__NOP();
}
}
int main(void)
{
HAL_Init();
/* Leave RIFSC alone. The boot ROM has already set up master/slave
* tagging for the OPEN-lifecycle dev path; the registers are
* clamped immediately after that and any writes here would either
* clobber working tagging or silently drop. */
MX_XSPI2_Init();
HAL_Delay(SETTLE_DELAY_MS);
if (mx66_software_reset() != HAL_OK) {
Error_Handler();
}
HAL_Delay(SETTLE_DELAY_MS);
if (xspi2_latch_read_cmd() != HAL_OK) {
Error_Handler();
}
HAL_Delay(SETTLE_DELAY_MS);
if (xspi2_engage_mem_mapped() != HAL_OK) {
Error_Handler();
}
/* "STM2" little-endian = 0x324D5453. */
if (*(volatile uint32_t *)0x70000000U != 0x324D5453U) {
Error_Handler();
}
/* The app at APP_XIP_BASE is XIP-linked: vector table SP/PC are read
* straight from the memory-mapped XSPI window. Validate the head of
* the table before handing off — SP in AXISRAM (0x2xxxxxxx),
* Reset_Handler within the 0x70100000 XIP slot with thumb bit set.
* An erased slot reads 0xFFFFFFFF and fails the SP check. */
const uint32_t app_sp = *(volatile uint32_t *)APP_XIP_BASE;
const uint32_t app_pc = *(volatile uint32_t *)(APP_XIP_BASE + 4U);
if ((app_sp & 0xF8000000U) != 0x20000000U
|| (app_pc & 0xFFF00000U) != APP_XIP_BASE
|| (app_pc & 1U) == 0U) {
Error_Handler();
}
jump_to_app(APP_XIP_BASE);
}
void Error_Handler(void)
{
__disable_irq();
while (1) {
}
}
+13
View File
@@ -0,0 +1,13 @@
/*
* STM32N6 FSBL stub — public include hub.
*
* Mirrors ST's Template_FSBL_XIP/FSBL/Inc/main.h pattern: the HAL config
* is the single user-visible header that pulls in the rest of the HAL via
* stm32n6xx.h.
*/
#pragma once
#include "stm32n6xx_hal.h"
void Error_Handler(void);
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,120 @@
/*
* STM32N6 FSBL stub Cortex-M55 startup for the GCC toolchain.
*
* The boot ROM loads the entire payload (incl. .text + .data) into AXISRAM2
* at the address in the FSBL header, so only a .data LMA->VMA copy is
* required (no flash-to-RAM .text copy).
*
* .data copy and .bss zero must run BEFORE SystemInit, otherwise SystemInit
* writes to HAL globals (uwTick, SystemCoreClock) land in uninitialised
* memory and HAL_GetTick() reads garbage on the first HAL timeout.
*
* The default exception handlers are stub infinite loops. SysTick_Handler
* is overridden by stm32n6xx_it.c which calls HAL_IncTick.
*/
.syntax unified
.arch armv8.1-m.main
.fpu softvfp
.thumb
.global g_pfnVectors
.global Default_Handler
/* Linker symbols used below */
.word _sidata
.word _sdata
.word _edata
.word _sbss
.word _ebss
.section .text.Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
ldr r0, =_sstack
msr MSPLIM, r0
ldr r0, =_estack
mov sp, r0
/* Copy .data from LMA (end of .text in ROM region) to VMA (RAM). */
ldr r0, =_sdata
ldr r1, =_edata
ldr r2, =_sidata
movs r3, #0
b LoopCopyDataInit
CopyDataInit:
ldr r4, [r2, r3]
str r4, [r0, r3]
adds r3, r3, #4
LoopCopyDataInit:
adds r4, r0, r3
cmp r4, r1
bcc CopyDataInit
/* Zero-fill .bss. */
ldr r2, =_sbss
ldr r4, =_ebss
movs r3, #0
b LoopFillZerobss
FillZerobss:
str r3, [r2]
adds r2, r2, #4
LoopFillZerobss:
cmp r2, r4
bcc FillZerobss
bl SystemInit
bl main
LoopForever:
b LoopForever
.size Reset_Handler, .-Reset_Handler
.section .text.Default_Handler, "ax", %progbits
Default_Handler:
b Default_Handler
.size Default_Handler, .-Default_Handler
/* Cortex-M55 vector table only the system vectors are populated.
* IRQ handlers default to Default_Handler via .weak aliases. */
.section .isr_vector, "a", %progbits
.type g_pfnVectors, %object
g_pfnVectors:
.word _estack
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.word MemManage_Handler
.word BusFault_Handler
.word UsageFault_Handler
.word SecureFault_Handler
.word 0
.word 0
.word 0
.word SVC_Handler
.word DebugMon_Handler
.word 0
.word PendSV_Handler
.word SysTick_Handler
.size g_pfnVectors, .-g_pfnVectors
.weak NMI_Handler
.thumb_set NMI_Handler, Default_Handler
.weak HardFault_Handler
.thumb_set HardFault_Handler, Default_Handler
.weak MemManage_Handler
.thumb_set MemManage_Handler, Default_Handler
.weak BusFault_Handler
.thumb_set BusFault_Handler, Default_Handler
.weak UsageFault_Handler
.thumb_set UsageFault_Handler, Default_Handler
.weak SecureFault_Handler
.thumb_set SecureFault_Handler, Default_Handler
.weak SVC_Handler
.thumb_set SVC_Handler, Default_Handler
.weak DebugMon_Handler
.thumb_set DebugMon_Handler, Default_Handler
.weak PendSV_Handler
.thumb_set PendSV_Handler, Default_Handler
.weak SysTick_Handler
.thumb_set SysTick_Handler, Default_Handler
@@ -0,0 +1,77 @@
/*
* Trimmed HAL configuration for the FSBL stub. Only the modules required to
* bring up XSPI2 in memory-mapped mode are enabled — anything that would
* pull in extra .c files we don't compile stays disabled.
*/
#ifndef STM32N6xx_HAL_CONF_H
#define STM32N6xx_HAL_CONF_H
#ifdef __cplusplus
extern "C" {
#endif
#define HAL_MODULE_ENABLED
#define HAL_CORTEX_MODULE_ENABLED
#define HAL_RCC_MODULE_ENABLED
#define HAL_PWR_MODULE_ENABLED
#define HAL_GPIO_MODULE_ENABLED
#define HAL_DMA_MODULE_ENABLED
#define HAL_XSPI_MODULE_ENABLED
#if !defined(HSE_VALUE)
#define HSE_VALUE 48000000UL
#endif
#if !defined(HSE_STARTUP_TIMEOUT)
#define HSE_STARTUP_TIMEOUT 100UL
#endif
#if !defined(LSE_VALUE)
#define LSE_VALUE 32768UL
#endif
#if !defined(LSE_STARTUP_TIMEOUT)
#define LSE_STARTUP_TIMEOUT 5000UL
#endif
#if !defined(MSI_VALUE)
#define MSI_VALUE 4000000UL
#endif
#if !defined(HSI_VALUE)
#define HSI_VALUE 64000000UL
#endif
#if !defined(LSI_VALUE)
#define LSI_VALUE 32000UL
#endif
#define VDD_VALUE 3300UL
#define TICK_INT_PRIORITY 15U
#define USE_RTOS 0U
#define USE_HAL_XSPI_REGISTER_CALLBACKS 0U
#define USE_HAL_PWR_REGISTER_CALLBACKS 0U
#define USE_SPI_CRC 0U
#ifdef HAL_RCC_MODULE_ENABLED
#include "stm32n6xx_hal_rcc.h"
#endif
#ifdef HAL_GPIO_MODULE_ENABLED
#include "stm32n6xx_hal_gpio.h"
#endif
#ifdef HAL_CORTEX_MODULE_ENABLED
#include "stm32n6xx_hal_cortex.h"
#endif
#ifdef HAL_PWR_MODULE_ENABLED
#include "stm32n6xx_hal_pwr.h"
#endif
#ifdef HAL_DMA_MODULE_ENABLED
#include "stm32n6xx_hal_dma.h"
#endif
#ifdef HAL_XSPI_MODULE_ENABLED
#include "stm32n6xx_hal_xspi.h"
#endif
#define assert_param(expr) ((void)0U)
#ifdef __cplusplus
}
#endif
#endif /* STM32N6xx_HAL_CONF_H */
@@ -0,0 +1,45 @@
/*
* Minimal HAL MSP for the FSBL stub. Only XSPI2's MSP is non-trivial: it
* enables the peripheral + XSPIM + GPION clocks and configures the eleven
* GPIO N pins for XSPIM_P2. The boot ROM already picked a working XSPI2
* clock source; we don't reconfigure it. 1S-1S-1S READ at the boot-ROM rate
* is sufficient for XIP and works regardless of HSLV fuse state, so no BSEC
* read is needed.
*/
#include "main.h"
void HAL_MspInit(void)
{
HAL_PWREx_EnableVddIO3();
}
void HAL_XSPI_MspInit(XSPI_HandleTypeDef *hxspi)
{
if (hxspi->Instance != XSPI2) {
return;
}
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* PWR clock is left on by the boot ROM. __HAL_RCC_PWR_CLK_ENABLE
* lives behind CPU_IN_SECURE_STATE in stm32n6xx_hal_rcc.h, which pulls
* in HAL_MPU_*_NS variants that require -mcmse. */
HAL_PWREx_EnableVddIO3();
HAL_PWREx_ConfigVddIORange(PWR_VDDIO3, PWR_VDDIO_RANGE_1V8);
__HAL_RCC_XSPIM_CLK_ENABLE();
__HAL_RCC_XSPI2_CLK_ENABLE();
__HAL_RCC_GPION_CLK_ENABLE();
/* PN0 -> DQS0, PN1 -> NCS1, PN2..PN5 -> IO0..IO3, PN6 -> CLK,
* PN8..PN11 -> IO4..IO7. AF9 = XSPIM_P2 on every pin in this bank. */
GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3
| GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_8
| GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_XSPIM_P2;
HAL_GPIO_Init(GPION, &GPIO_InitStruct);
}
+13
View File
@@ -0,0 +1,13 @@
/*
* Interrupt handlers for the FSBL stub. Only SysTick is wired up — HAL_Init
* starts a 1 ms tick that HAL_XSPI_Command and friends use for timeout
* accounting. Everything else stays defaulted to the spin-loops in the
* startup file (the FSBL doesn't enable any interrupts beyond SysTick).
*/
#include "main.h"
void SysTick_Handler(void)
{
HAL_IncTick();
}
@@ -0,0 +1,221 @@
/*
* CMSIS system file for the FSBL stub. The stub does not build with
* -mcmse and never transitions to non-secure state, so the usual
* TrustZone bring-up (SAU region clear, SCB_NS->CPACR, CMSE_NS_ENTRY
* exports) is omitted.
*/
#include "stm32n6xx.h"
#include <math.h>
#if !defined(HSE_VALUE)
#define HSE_VALUE 48000000UL
#endif
#if !defined(HSI_VALUE)
#define HSI_VALUE 64000000UL
#endif
#if !defined(MSI_VALUE)
#define MSI_VALUE 4000000UL
#endif
#if !defined(EXTERNAL_I2S_CLOCK_VALUE)
#define EXTERNAL_I2S_CLOCK_VALUE 12288000UL
#endif
uint32_t SystemCoreClock = HSI_VALUE;
extern void *g_pfnVectors;
#define INTVECT_START ((uint32_t)&g_pfnVectors)
void SystemInit(void)
{
SCB->VTOR = INTVECT_START;
/* Hold the debug subsystem clock on first thing so SWD is attachable
* even if a later init step faults. The boot ROM closes AP1 on
* BOOT0=USER paths; DBGCLKEN reopens it on OPEN-lifecycle silicon
* without going through Debug Authentication. DBG_SLEEP/STOP/STANDBY
* keep the core debuggable across low-power transitions too. */
RCC->MISCENSR = RCC_MISCENSR_DBGENS;
(void)RCC->MISCENR;
DBGMCU->CR |= DBGMCU_CR_DBGCLKEN
| DBGMCU_CR_DBG_SLEEP
| DBGMCU_CR_DBG_STOP
| DBGMCU_CR_DBG_STANDBY;
(void)DBGMCU->CR;
/* RNG reset + clock-disable. The boot ROM may have left it ticking. */
RCC->AHB3RSTSR = RCC_AHB3RSTSR_RNGRSTS;
RCC->AHB3RSTCR = RCC_AHB3RSTCR_RNGRSTC;
RCC->AHB3ENCR = RCC_AHB3ENCR_RNGENC;
/* SYSCFG clock + VDDIOx supply rails (errata ES0620). */
RCC->APB4ENSR2 = RCC_APB4ENSR2_SYSCFGENS;
(void)RCC->APB4ENR2;
SYSCFG->INITSVTORCR = SCB->VTOR;
PWR->SVMCR1 |= PWR_SVMCR1_VDDIO4SV;
PWR->SVMCR2 |= PWR_SVMCR2_VDDIO5SV;
PWR->SVMCR3 |= PWR_SVMCR3_VDDIO2SV | PWR_SVMCR3_VDDIO3SV;
SYSCFG->VDDIO2CCCR = 0x00000287UL;
SYSCFG->VDDIO3CCCR = 0x00000287UL;
SYSCFG->VDDIO4CCCR = 0x00000287UL;
SYSCFG->VDDIO5CCCR = 0x00000287UL;
SYSCFG->VDDCCCR = 0x00000287UL;
/* VDDADC clamp + VREF buffer. */
PWR->SVMCR3 |= PWR_SVMCR3_ASV;
PWR->SVMCR3 |= PWR_SVMCR3_AVMEN;
(void)PWR->SVMCR3;
RCC->APB4ENR1 |= RCC_APB4ENR1_VREFBUFEN;
/* RCC fix per ST template — pulse a reserved bit to lower power. */
RCC->APB4ENR2 |= 0x00000010UL;
(void)RCC->APB4ENR2;
RCC->APB4ENR2 &= ~(0x00000010UL);
/* Reset XSPI2 + XSPIM so we start from a known state regardless of how
* boot ROM left them after loading us. */
RCC->AHB5RSTSR = RCC_AHB5RSTSR_XSPIMRSTS | RCC_AHB5RSTSR_XSPI2RSTS;
RCC->AHB5RSTCR = RCC_AHB5RSTCR_XSPIMRSTC | RCC_AHB5RSTCR_XSPI2RSTC;
/* TIM2 reset + clock-disable. */
RCC->APB1RSTSR1 = RCC_APB1RSTSR1_TIM2RSTS;
RCC->APB1RSTCR1 = RCC_APB1RSTCR1_TIM2RSTC;
RCC->APB1ENCR1 = RCC_APB1ENCR1_TIM2ENC;
/* Boot ROM left GPIOG clocked; we'll re-enable in xspi MSP if needed. */
RCC->AHB4ENCR = RCC_AHB4ENCR_GPIOGENC;
/* Enable AXISRAM1..6 clocks. Boot ROM only clocks AXISRAM2; the rest
* (notably AXISRAM1 where the app's stack and .text live) must be
* brought up here or the first store from the app's Reset_Handler
* busfaults silently. */
RCC->MEMENSR = RCC_MEMENSR_AXISRAM1ENS | RCC_MEMENSR_AXISRAM2ENS
| RCC_MEMENSR_AXISRAM3ENS | RCC_MEMENSR_AXISRAM4ENS
| RCC_MEMENSR_AXISRAM5ENS | RCC_MEMENSR_AXISRAM6ENS;
(void)RCC->MEMENR;
(void)SYSCFG->INITSVTORCR;
RCC->APB4ENCR2 = RCC_APB4ENCR2_SYSCFGENC;
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 20U) | (3UL << 22U)); /* CP10/CP11 full access */
#endif
}
void SystemCoreClockUpdate(void)
{
uint32_t sysclk = 0;
uint32_t pllm = 0;
uint32_t plln = 0;
uint32_t pllfracn = 0;
uint32_t pllp1 = 0;
uint32_t pllp2 = 0;
uint32_t pllcfgr;
uint32_t pllsource = 0;
uint32_t pllbypass = 0;
uint32_t ic_divider;
float_t pllvco;
switch (RCC->CFGR1 & RCC_CFGR1_CPUSWS) {
case 0:
sysclk = HSI_VALUE >> ((RCC->HSICFGR & RCC_HSICFGR_HSIDIV) >> RCC_HSICFGR_HSIDIV_Pos);
break;
case RCC_CFGR1_CPUSWS_0:
sysclk = (READ_BIT(RCC->MSICFGR, RCC_MSICFGR_MSIFREQSEL) == 0UL) ? MSI_VALUE : 16000000UL;
break;
case RCC_CFGR1_CPUSWS_1:
sysclk = HSE_VALUE;
break;
case (RCC_CFGR1_CPUSWS_1 | RCC_CFGR1_CPUSWS_0):
switch (READ_BIT(RCC->IC1CFGR, RCC_IC1CFGR_IC1SEL)) {
case 0:
pllcfgr = READ_REG(RCC->PLL1CFGR1);
pllsource = pllcfgr & RCC_PLL1CFGR1_PLL1SEL;
pllbypass = pllcfgr & RCC_PLL1CFGR1_PLL1BYP;
if (pllbypass == 0U) {
pllm = (pllcfgr & RCC_PLL1CFGR1_PLL1DIVM) >> RCC_PLL1CFGR1_PLL1DIVM_Pos;
plln = (pllcfgr & RCC_PLL1CFGR1_PLL1DIVN) >> RCC_PLL1CFGR1_PLL1DIVN_Pos;
pllfracn = READ_BIT(RCC->PLL1CFGR2, RCC_PLL1CFGR2_PLL1DIVNFRAC) >> RCC_PLL1CFGR2_PLL1DIVNFRAC_Pos;
pllcfgr = READ_REG(RCC->PLL1CFGR3);
pllp1 = (pllcfgr & RCC_PLL1CFGR3_PLL1PDIV1) >> RCC_PLL1CFGR3_PLL1PDIV1_Pos;
pllp2 = (pllcfgr & RCC_PLL1CFGR3_PLL1PDIV2) >> RCC_PLL1CFGR3_PLL1PDIV2_Pos;
}
break;
case RCC_IC1CFGR_IC1SEL_0:
pllcfgr = READ_REG(RCC->PLL2CFGR1);
pllsource = pllcfgr & RCC_PLL2CFGR1_PLL2SEL;
pllbypass = pllcfgr & RCC_PLL2CFGR1_PLL2BYP;
if (pllbypass == 0U) {
pllm = (pllcfgr & RCC_PLL2CFGR1_PLL2DIVM) >> RCC_PLL2CFGR1_PLL2DIVM_Pos;
plln = (pllcfgr & RCC_PLL2CFGR1_PLL2DIVN) >> RCC_PLL2CFGR1_PLL2DIVN_Pos;
pllfracn = READ_BIT(RCC->PLL2CFGR2, RCC_PLL2CFGR2_PLL2DIVNFRAC) >> RCC_PLL2CFGR2_PLL2DIVNFRAC_Pos;
pllcfgr = READ_REG(RCC->PLL2CFGR3);
pllp1 = (pllcfgr & RCC_PLL2CFGR3_PLL2PDIV1) >> RCC_PLL2CFGR3_PLL2PDIV1_Pos;
pllp2 = (pllcfgr & RCC_PLL2CFGR3_PLL2PDIV2) >> RCC_PLL2CFGR3_PLL2PDIV2_Pos;
}
break;
case RCC_IC1CFGR_IC1SEL_1:
pllcfgr = READ_REG(RCC->PLL3CFGR1);
pllsource = pllcfgr & RCC_PLL3CFGR1_PLL3SEL;
pllbypass = pllcfgr & RCC_PLL3CFGR1_PLL3BYP;
if (pllbypass == 0U) {
pllm = (pllcfgr & RCC_PLL3CFGR1_PLL3DIVM) >> RCC_PLL3CFGR1_PLL3DIVM_Pos;
plln = (pllcfgr & RCC_PLL3CFGR1_PLL3DIVN) >> RCC_PLL3CFGR1_PLL3DIVN_Pos;
pllfracn = READ_BIT(RCC->PLL3CFGR2, RCC_PLL3CFGR2_PLL3DIVNFRAC) >> RCC_PLL3CFGR2_PLL3DIVNFRAC_Pos;
pllcfgr = READ_REG(RCC->PLL3CFGR3);
pllp1 = (pllcfgr & RCC_PLL3CFGR3_PLL3PDIV1) >> RCC_PLL3CFGR3_PLL3PDIV1_Pos;
pllp2 = (pllcfgr & RCC_PLL3CFGR3_PLL3PDIV2) >> RCC_PLL3CFGR3_PLL3PDIV2_Pos;
}
break;
default:
pllcfgr = READ_REG(RCC->PLL4CFGR1);
pllsource = pllcfgr & RCC_PLL4CFGR1_PLL4SEL;
pllbypass = pllcfgr & RCC_PLL4CFGR1_PLL4BYP;
if (pllbypass == 0U) {
pllm = (pllcfgr & RCC_PLL4CFGR1_PLL4DIVM) >> RCC_PLL4CFGR1_PLL4DIVM_Pos;
plln = (pllcfgr & RCC_PLL4CFGR1_PLL4DIVN) >> RCC_PLL4CFGR1_PLL4DIVN_Pos;
pllfracn = READ_BIT(RCC->PLL4CFGR2, RCC_PLL4CFGR2_PLL4DIVNFRAC) >> RCC_PLL4CFGR2_PLL4DIVNFRAC_Pos;
pllcfgr = READ_REG(RCC->PLL4CFGR3);
pllp1 = (pllcfgr & RCC_PLL4CFGR3_PLL4PDIV1) >> RCC_PLL4CFGR3_PLL4PDIV1_Pos;
pllp2 = (pllcfgr & RCC_PLL4CFGR3_PLL4PDIV2) >> RCC_PLL4CFGR3_PLL4PDIV2_Pos;
}
break;
}
switch (pllsource) {
case 0:
sysclk = HSI_VALUE >> ((RCC->HSICFGR & RCC_HSICFGR_HSIDIV) >> RCC_HSICFGR_HSIDIV_Pos);
break;
case RCC_PLL1CFGR1_PLL1SEL_0:
sysclk = (READ_BIT(RCC->MSICFGR, RCC_MSICFGR_MSIFREQSEL) == 0UL) ? MSI_VALUE : 16000000UL;
break;
case RCC_PLL1CFGR1_PLL1SEL_1:
sysclk = HSE_VALUE;
break;
case (RCC_PLL1CFGR1_PLL1SEL_1 | RCC_PLL1CFGR1_PLL1SEL_0):
sysclk = EXTERNAL_I2S_CLOCK_VALUE;
break;
default:
break;
}
if (pllbypass == 0U) {
pllvco = ((float_t)sysclk * ((float_t)plln + ((float_t)pllfracn / (float_t)0x1000000UL))) / (float_t)pllm;
sysclk = (uint32_t)((float_t)(pllvco / (((float_t)pllp1) * ((float_t)pllp2))));
}
ic_divider = (READ_BIT(RCC->IC1CFGR, RCC_IC1CFGR_IC1INT) >> RCC_IC1CFGR_IC1INT_Pos) + 1UL;
sysclk = sysclk / ic_divider;
break;
default:
break;
}
SystemCoreClock = sysclk;
}