如何获得 180 Mhz 的 STM32F446 运行?
How to get STM32F446 running at 180 Mhz?
我正在尝试让 STM32F446 运行 全速运行,遵循本教程:https://www.youtube.com/watch?v=GJ_LFAlOlSk&t=826s 我做了他所做的一切,但我的定时器的时钟速度非常慢,就像字面意思一样,当预标量为 9 且 ARR 为 20 的 LED 闪烁时,肉眼很容易看到它。Wt* 我做错了吗?
void setup_clock(void)
{
// Enables HSE and waits until it is ready
*RCC_CR |= (1 << RCC_CR_HSEON);
while (!(*RCC_CR & (1 << RCC_CR_HSERDY)));
// Set the power enable clock and voltage regulator
*RCC_APB1ENR |= (1 << RCC_APB1ENR_PWREN);
*PWR_CR |= PWR_CR_VOS(PWR_CR_VOS_SCALEM1);
// Configure flash
*FLASH_ACR = (1 << FLASH_ACR_DCEN) | (1 << FLASH_ACR_ICEN) | (1 << FLASH_ACR_PRFTEN);
*FLASH_ACR |= FLASH_ACR_LATENCY(5);
// Configures HCLK, PCLK1, PCLK2
*RCC_CFGR &= ~RCC_CFGR_HPRE_MASK;
*RCC_CFGR |= RCC_CFGR_HPRE(RCC_CFGR_HPRE_NODIV); // HCLK 180Mhz
*RCC_CFGR &= ~RCC_CFGR_PPRE1_MASK;
*RCC_CFGR |= RCC_CFGR_PPRE1(RCC_CFGR_PPRE1_DIV4); // PCLK1 45Mhz
*RCC_CFGR &= ~RCC_CFGR_PPRE2_MASK;
*RCC_CFGR |= RCC_CFGR_PPRE2(RCC_CFGR_PPRE2_DIV2); // PCLK2 90Mhz
// Configures the main PLL
*RCC_PLLCFGR = RCC_PLLCFGR_PLLN(180) |
RCC_PLLCFGR_PLLP(RCC_PLLCFGR_PLLP_2) |
RCC_PLLCFGR_PLLR(2) |
RCC_PLLCFGR_PLLM(4) |
(1 << RCC_PLLCFGR_PLLSRC);
// Enable PLL
*RCC_CR |= (1 << RCC_CR_PLLON);
while (!(*RCC_CR & (1 << RCC_CR_PLLRDY)));
// Use PLL as clock source
*RCC_CFGR &= ~RCC_CFGR_SW_MASK;
*RCC_CFGR |= RCC_CFGR_SW(RCC_CFGR_SW_PLL_P);
while ((*RCC_CFGR & RCC_CFGR_SWS_MASK) != RCC_CFGR_SWS(RCC_CFGR_SWS_PLL));
// Sets the CLOCK Ready status LED
*GPIO_ODR(STATUS_BASE) |= (1 << STATUS_CLKREADY);
}
下面是 NUCLEO_F44RE 使用 gnu 工具的完整工作项目,包括构建所需的一切和 运行。
差异。
我在默认功率模式下启动(看起来像你是吗?),所以保守地将闪存除数设置为 8(9 个时钟)。 (之后可以试试这个,我个人会先设置为 8,然后再设置为 5)。
我既不使用 I 也不使用 D 缓存。
我将系统设置为 HSE,然后将 PLL 也设置为使用它。你跳过它,这可能很好,因为 HSE 已启动并准备就绪(供 PLL 使用)。
这一行
*RCC_CFGR &= ~RCC_CFGR_SW_MASK;
将时钟切换到 HSI,然后
*RCC_CFGR |= RCC_CFGR_SW(RCC_CFGR_SW_PLL_P);
将时钟切换到 PLL。需要下定决心,不要像 Lundin 评论的那样 use/abuse 以这种方式注册。您应该进行干净的读取-修改-写入、读取、将需要清零的位(或字段中的所有位)置零,然后设置要设置的位,然后写入寄存器。为此使用临时变量。或者
的一些味道
reg = (reg&this) | that;
但肯定不是
reg &= this;
reg |= that;
一般。我怀疑这是你的问题...只是我们 couple/few 的评论。
您的 PLLQ 处于无效状态。可能有问题,试试吧。
我正在用 habit/portability 代码构建 cortex-m0,可以轻松更改它。
在 PJ 提出这个问题之前
*RCC_APB1ENR |= (1 << RCC_APB1ENR_PWREN);
*PWR_CR |= PWR_CR_VOS(PWR_CR_VOS_SCALEM1);
有风险,您需要检查编译后的输出,它可能因编译器、版本、月相而异。如果到 RCC_APB1ENR 的 str 紧接着是 PWR_CR 的 LDR,那可能不起作用。我确实看到根据 PJ 对另一张票的评论做实验的是,那里的 gpio,你可以出于某种原因在外围设备关闭的情况下读取 MODER 寄存器,这样 MODER 的启用和 ldr 的 str 工作,那么进行修改和写入的指令对于写入来说已经绰绰有余了。但是如果你堵塞现代寄存器,具体取决于你的编译器和设置,它可以将它们优化为两个背靠背存储,我能够用一个编译器而不是另一个编译器来解决这个问题。 (尽管更改设置,但它们会修复并失败,等等)。我所做的 GET32/PUT32 确保在启用有时间稳定之前触摸外围设备没有问题。 YMMV.
flash.s
.cpu cortex-m0
.thumb
.thumb_func
.global _start
_start:
.word 0x20001000
.word reset
.thumb_func
reset:
bl notmain
b hang
.thumb_func
hang: b .
.thumb_func
.globl PUT32
PUT32:
str r1,[r0]
bx lr
.thumb_func
.globl GET32
GET32:
ldr r0,[r0]
bx lr
flash.ld
MEMORY
{
rom : ORIGIN = 0x08000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom
}
notmain.c
void PUT32 ( unsigned int, unsigned int );
unsigned int GET32 ( unsigned int );
void dummy ( unsigned int );
#define RCCBASE 0x40023800
#define RCC_AHB1ENR (RCCBASE+0x30)
#define RCC_CR (RCCBASE+0x00)
#define RCC_PLLCFGR (RCCBASE+0x08)
#define RCC_CFGR (RCCBASE+0x08)
#define FLASH_ACR 0x40023C00
#define GPIOABASE 0x40020000
#define GPIOA_MODER (GPIOABASE+0x00)
#define GPIOA_BSRR (GPIOABASE+0x18)
//PA5
#define STK_CSR 0xE000E010
#define STK_RVR 0xE000E014
#define STK_CVR 0xE000E018
static void clock_init ( void )
{
unsigned int ra;
//switch to external clock.
ra=GET32(RCC_CR);
ra|=1<<16;
PUT32(RCC_CR,ra);
while(1) if(GET32(RCC_CR)&(1<<17)) break;
if(1)
{
ra=GET32(RCC_CFGR);
ra&=~3;
ra|=1;
PUT32(RCC_CFGR,ra);
while(1) if(((GET32(RCC_CFGR)>>2)&3)==1) break;
}
//HSE ready
}
static void pll_init ( void )
{
unsigned int ra;
//clock_init();
ra=GET32(FLASH_ACR);
ra&=(~(0xF<<0));
ra|=( 8<<0);
PUT32(FLASH_ACR,ra);
//poll this?
ra=GET32(RCC_CFGR);
ra&=(~(0x3<<13));
ra|=( 4<<13); //180/90 = 2
ra&=(~(0x3<<10));
ra|=( 5<<10); //180/45 = 4
PUT32(RCC_CFGR,ra);
//HSE 8Mhz
//PLLM It is recommended to select a frequency of 2 MHz to limit
// PLL jitter.
//PLLN input is 2, want >=50 and <=432 so between 25 and 216
//PLLM 4, PLLN 180, VCO 360, PLLP 2
//PLLM 8/4 = 2
//PLLN 2 * 180 = 360
//PLLP 360 / 2 = 180
//PLLR 2?
//PLLQ 180 / 48 = 3.75 so 4.
ra=0;
ra|=2<<28; //PLLR
ra|=4<<24; //PLLQ dont care
ra|=1<<22; //PLLSRC HSE
ra|=2<<16; //PLLP
ra|=180<<6; //PLLN
ra|=4<<0; //PLLM
PUT32(RCC_PLLCFGR,ra);
ra=GET32(RCC_CR);
ra|=1<<24;
PUT32(RCC_CR,ra);
while(1) if(GET32(RCC_CR)&(1<<25)) break;
ra=GET32(RCC_CFGR);
ra&=~3;
ra|=2;
PUT32(RCC_CFGR,ra);
while(1) if(((GET32(RCC_CFGR)>>2)&3)==2) break;
}
static void led_init ( void )
{
unsigned int ra;
ra=GET32(RCC_AHB1ENR);
ra|=1<<0; //enable GPIOA
PUT32(RCC_AHB1ENR,ra);
ra=GET32(GPIOA_MODER);
ra&=~(3<<(5<<1)); //PA5
ra|= (1<<(5<<1)); //PA5
PUT32(GPIOA_MODER,ra);
}
static void led_on ( void )
{
PUT32(GPIOA_BSRR,((1<<5)<< 0));
}
static void led_off ( void )
{
PUT32(GPIOA_BSRR,((1<<5)<<16));
}
void do_delay ( unsigned int sec )
{
unsigned int ra,rb,rc,rd;
rb=GET32(STK_CVR);
for(rd=0;rd<sec;)
{
ra=GET32(STK_CVR);
rc=(rb-ra)&0x00FFFFFF;
if(rc>=16000000)
{
rb=ra;
rd++;
}
}
}
int notmain ( void )
{
unsigned int rx;
led_init();
PUT32(STK_CSR,0x00000004);
PUT32(STK_RVR,0xFFFFFFFF);
PUT32(STK_CSR,0x00000005);
for(rx=0;rx<5;rx++)
{
led_on();
while(1) if((GET32(STK_CVR)&0x200000)!=0) break;
led_off();
while(1) if((GET32(STK_CVR)&0x200000)==0) break;
}
clock_init();
for(rx=0;rx<5;rx++)
{
led_on();
while(1) if((GET32(STK_CVR)&0x200000)!=0) break;
led_off();
while(1) if((GET32(STK_CVR)&0x200000)==0) break;
}
pll_init();
while(1)
{
led_on();
while(1) if((GET32(STK_CVR)&0x200000)!=0) break;
led_off();
while(1) if((GET32(STK_CVR)&0x200000)==0) break;
}
return(0);
}
建设
arm-linux-gnueabi-as --warn --fatal-warnings -mcpu=cortex-m0 flash.s -o flash.o
arm-linux-gnueabi-gcc -Wall -O2 -ffreestanding -mcpu=cortex-m0 -mthumb -c notmain.c -o notmain.o
arm-linux-gnueabi-ld -nostdlib -nostartfiles -T flash.ld flash.o notmain.o -o notmain.elf
arm-linux-gnueabi-objdump -D notmain.elf > notmain.list
arm-linux-gnueabi-objcopy -O binary notmain.elf notmain.bin
(当然可以把cortex-m0s改成cortex-m4s)
复制 notmain.bin 到核卡并观察用户 led 改变速度。快一点,慢一半,快很多。
嗯...
when VOS[1:0] = '0x11, the maximum value of f HCLK is 168 MHz. It can be extended to 180 MHz by activating the over-drive mode. The over-drive mode is not available when VDD ranges from 1.8 to 2.1 V (refer to Section 5.1.3: Voltage regulator for details on how to activate the over-drive mode).
和
11: Scale 1 mode (reset value)
(所以没必要纠结)
和
Entering Over-drive mode
It is recommended to enter Over-drive mode when the application is not running critical
tasks and when the system clock source is either HSI or HSE. To optimize the configuration
time, enable the Over-drive mode during the PLL lock phase.
To enter Over-drive mode, follow the sequence below:
Note:
1. Select HSI or HSE as system clock.
2. Configure RCC_PLLCFGR register and set PLLON bit of RCC_CR register.
3. Set ODEN bit of PWR_CR register to enable the Over-drive mode and wait for the
ODRDY flag to be set in the PWR_CSR register.
4. Set the ODSW bit in the PWR_CR register to switch the voltage regulator from Normal
mode to Over-drive mode. The System will be stalled during the switch but the PLL
clock system will be still running during locking phase.
5. Wait for the ODSWRDY flag in the PWR_CSR to be set.
6. Select the required Flash latency as well as AHB and APB prescalers.
7. Wait for PLL lock.
8. Switch the system clock to the PLL.
9. Enable the peripherals that are not generated by the System PLL (I2S clock, SAI1 and
SAI2 clocks, USB_48MHz clock....).
所以我 运行 在室温下,芯片远未接近最高温度,所以很可能为什么它可以像我在这里所做的那样超频工作。 (从技术上讲,它并不完整,需要为 168 或设置为超速)。
如果您想要 180 和 168,您应该按照文档执行这些步骤。
我怀疑你也没有运行将你的部分设置在最高温度附近,所以你也应该能够摆脱 180。尝试删除您的 pwr 寄存器内容,看看是否有帮助,让您的闪存延迟更长等。更改为 168mhz 等。
您是否尝试了 180 度,或者您是否首先尝试了一些不推动任何边缘的更合理的速度,例如低于 45mhz 的速度,然后是 45 到 90 之间的速度,然后是 90 以上,然后达到 180?
编辑
The Flash memory interface accelerates code execution with a system of instruction prefetch and cache lines.
Main features
• Flash memory read operations
• Flash memory program/erase operations
• Read / write protections
• Prefetch on I-Code
• 64 cache lines of 128 bits on I-Code
• 8 cache lines of 128 bits on D-Code
CubeMx 有一个非常方便的时钟配置工具。我不使用 HAL,但这个工具可以节省很多时间。
正如我所见,您试图通过使用自己的寄存器定义来重新发明轮子。使用标准的 CMSIS,因为创建自己的没有任何意义。
无法同时拥有 180MHz 时钟和使用 USB,因为您无法获得 USB 外设所需的 48MHz。
这里有一些可能的设置:
25MHz 外部振荡器:
8Mhz 外部振荡器:
18MHz 内部振荡器
我正在尝试让 STM32F446 运行 全速运行,遵循本教程:https://www.youtube.com/watch?v=GJ_LFAlOlSk&t=826s 我做了他所做的一切,但我的定时器的时钟速度非常慢,就像字面意思一样,当预标量为 9 且 ARR 为 20 的 LED 闪烁时,肉眼很容易看到它。Wt* 我做错了吗?
void setup_clock(void)
{
// Enables HSE and waits until it is ready
*RCC_CR |= (1 << RCC_CR_HSEON);
while (!(*RCC_CR & (1 << RCC_CR_HSERDY)));
// Set the power enable clock and voltage regulator
*RCC_APB1ENR |= (1 << RCC_APB1ENR_PWREN);
*PWR_CR |= PWR_CR_VOS(PWR_CR_VOS_SCALEM1);
// Configure flash
*FLASH_ACR = (1 << FLASH_ACR_DCEN) | (1 << FLASH_ACR_ICEN) | (1 << FLASH_ACR_PRFTEN);
*FLASH_ACR |= FLASH_ACR_LATENCY(5);
// Configures HCLK, PCLK1, PCLK2
*RCC_CFGR &= ~RCC_CFGR_HPRE_MASK;
*RCC_CFGR |= RCC_CFGR_HPRE(RCC_CFGR_HPRE_NODIV); // HCLK 180Mhz
*RCC_CFGR &= ~RCC_CFGR_PPRE1_MASK;
*RCC_CFGR |= RCC_CFGR_PPRE1(RCC_CFGR_PPRE1_DIV4); // PCLK1 45Mhz
*RCC_CFGR &= ~RCC_CFGR_PPRE2_MASK;
*RCC_CFGR |= RCC_CFGR_PPRE2(RCC_CFGR_PPRE2_DIV2); // PCLK2 90Mhz
// Configures the main PLL
*RCC_PLLCFGR = RCC_PLLCFGR_PLLN(180) |
RCC_PLLCFGR_PLLP(RCC_PLLCFGR_PLLP_2) |
RCC_PLLCFGR_PLLR(2) |
RCC_PLLCFGR_PLLM(4) |
(1 << RCC_PLLCFGR_PLLSRC);
// Enable PLL
*RCC_CR |= (1 << RCC_CR_PLLON);
while (!(*RCC_CR & (1 << RCC_CR_PLLRDY)));
// Use PLL as clock source
*RCC_CFGR &= ~RCC_CFGR_SW_MASK;
*RCC_CFGR |= RCC_CFGR_SW(RCC_CFGR_SW_PLL_P);
while ((*RCC_CFGR & RCC_CFGR_SWS_MASK) != RCC_CFGR_SWS(RCC_CFGR_SWS_PLL));
// Sets the CLOCK Ready status LED
*GPIO_ODR(STATUS_BASE) |= (1 << STATUS_CLKREADY);
}
下面是 NUCLEO_F44RE 使用 gnu 工具的完整工作项目,包括构建所需的一切和 运行。
差异。
我在默认功率模式下启动(看起来像你是吗?),所以保守地将闪存除数设置为 8(9 个时钟)。 (之后可以试试这个,我个人会先设置为 8,然后再设置为 5)。
我既不使用 I 也不使用 D 缓存。
我将系统设置为 HSE,然后将 PLL 也设置为使用它。你跳过它,这可能很好,因为 HSE 已启动并准备就绪(供 PLL 使用)。
这一行
*RCC_CFGR &= ~RCC_CFGR_SW_MASK;
将时钟切换到 HSI,然后
*RCC_CFGR |= RCC_CFGR_SW(RCC_CFGR_SW_PLL_P);
将时钟切换到 PLL。需要下定决心,不要像 Lundin 评论的那样 use/abuse 以这种方式注册。您应该进行干净的读取-修改-写入、读取、将需要清零的位(或字段中的所有位)置零,然后设置要设置的位,然后写入寄存器。为此使用临时变量。或者
的一些味道reg = (reg&this) | that;
但肯定不是
reg &= this;
reg |= that;
一般。我怀疑这是你的问题...只是我们 couple/few 的评论。
您的 PLLQ 处于无效状态。可能有问题,试试吧。
我正在用 habit/portability 代码构建 cortex-m0,可以轻松更改它。
在 PJ 提出这个问题之前
*RCC_APB1ENR |= (1 << RCC_APB1ENR_PWREN);
*PWR_CR |= PWR_CR_VOS(PWR_CR_VOS_SCALEM1);
有风险,您需要检查编译后的输出,它可能因编译器、版本、月相而异。如果到 RCC_APB1ENR 的 str 紧接着是 PWR_CR 的 LDR,那可能不起作用。我确实看到根据 PJ 对另一张票的评论做实验的是,那里的 gpio,你可以出于某种原因在外围设备关闭的情况下读取 MODER 寄存器,这样 MODER 的启用和 ldr 的 str 工作,那么进行修改和写入的指令对于写入来说已经绰绰有余了。但是如果你堵塞现代寄存器,具体取决于你的编译器和设置,它可以将它们优化为两个背靠背存储,我能够用一个编译器而不是另一个编译器来解决这个问题。 (尽管更改设置,但它们会修复并失败,等等)。我所做的 GET32/PUT32 确保在启用有时间稳定之前触摸外围设备没有问题。 YMMV.
flash.s
.cpu cortex-m0
.thumb
.thumb_func
.global _start
_start:
.word 0x20001000
.word reset
.thumb_func
reset:
bl notmain
b hang
.thumb_func
hang: b .
.thumb_func
.globl PUT32
PUT32:
str r1,[r0]
bx lr
.thumb_func
.globl GET32
GET32:
ldr r0,[r0]
bx lr
flash.ld
MEMORY
{
rom : ORIGIN = 0x08000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom
}
notmain.c
void PUT32 ( unsigned int, unsigned int );
unsigned int GET32 ( unsigned int );
void dummy ( unsigned int );
#define RCCBASE 0x40023800
#define RCC_AHB1ENR (RCCBASE+0x30)
#define RCC_CR (RCCBASE+0x00)
#define RCC_PLLCFGR (RCCBASE+0x08)
#define RCC_CFGR (RCCBASE+0x08)
#define FLASH_ACR 0x40023C00
#define GPIOABASE 0x40020000
#define GPIOA_MODER (GPIOABASE+0x00)
#define GPIOA_BSRR (GPIOABASE+0x18)
//PA5
#define STK_CSR 0xE000E010
#define STK_RVR 0xE000E014
#define STK_CVR 0xE000E018
static void clock_init ( void )
{
unsigned int ra;
//switch to external clock.
ra=GET32(RCC_CR);
ra|=1<<16;
PUT32(RCC_CR,ra);
while(1) if(GET32(RCC_CR)&(1<<17)) break;
if(1)
{
ra=GET32(RCC_CFGR);
ra&=~3;
ra|=1;
PUT32(RCC_CFGR,ra);
while(1) if(((GET32(RCC_CFGR)>>2)&3)==1) break;
}
//HSE ready
}
static void pll_init ( void )
{
unsigned int ra;
//clock_init();
ra=GET32(FLASH_ACR);
ra&=(~(0xF<<0));
ra|=( 8<<0);
PUT32(FLASH_ACR,ra);
//poll this?
ra=GET32(RCC_CFGR);
ra&=(~(0x3<<13));
ra|=( 4<<13); //180/90 = 2
ra&=(~(0x3<<10));
ra|=( 5<<10); //180/45 = 4
PUT32(RCC_CFGR,ra);
//HSE 8Mhz
//PLLM It is recommended to select a frequency of 2 MHz to limit
// PLL jitter.
//PLLN input is 2, want >=50 and <=432 so between 25 and 216
//PLLM 4, PLLN 180, VCO 360, PLLP 2
//PLLM 8/4 = 2
//PLLN 2 * 180 = 360
//PLLP 360 / 2 = 180
//PLLR 2?
//PLLQ 180 / 48 = 3.75 so 4.
ra=0;
ra|=2<<28; //PLLR
ra|=4<<24; //PLLQ dont care
ra|=1<<22; //PLLSRC HSE
ra|=2<<16; //PLLP
ra|=180<<6; //PLLN
ra|=4<<0; //PLLM
PUT32(RCC_PLLCFGR,ra);
ra=GET32(RCC_CR);
ra|=1<<24;
PUT32(RCC_CR,ra);
while(1) if(GET32(RCC_CR)&(1<<25)) break;
ra=GET32(RCC_CFGR);
ra&=~3;
ra|=2;
PUT32(RCC_CFGR,ra);
while(1) if(((GET32(RCC_CFGR)>>2)&3)==2) break;
}
static void led_init ( void )
{
unsigned int ra;
ra=GET32(RCC_AHB1ENR);
ra|=1<<0; //enable GPIOA
PUT32(RCC_AHB1ENR,ra);
ra=GET32(GPIOA_MODER);
ra&=~(3<<(5<<1)); //PA5
ra|= (1<<(5<<1)); //PA5
PUT32(GPIOA_MODER,ra);
}
static void led_on ( void )
{
PUT32(GPIOA_BSRR,((1<<5)<< 0));
}
static void led_off ( void )
{
PUT32(GPIOA_BSRR,((1<<5)<<16));
}
void do_delay ( unsigned int sec )
{
unsigned int ra,rb,rc,rd;
rb=GET32(STK_CVR);
for(rd=0;rd<sec;)
{
ra=GET32(STK_CVR);
rc=(rb-ra)&0x00FFFFFF;
if(rc>=16000000)
{
rb=ra;
rd++;
}
}
}
int notmain ( void )
{
unsigned int rx;
led_init();
PUT32(STK_CSR,0x00000004);
PUT32(STK_RVR,0xFFFFFFFF);
PUT32(STK_CSR,0x00000005);
for(rx=0;rx<5;rx++)
{
led_on();
while(1) if((GET32(STK_CVR)&0x200000)!=0) break;
led_off();
while(1) if((GET32(STK_CVR)&0x200000)==0) break;
}
clock_init();
for(rx=0;rx<5;rx++)
{
led_on();
while(1) if((GET32(STK_CVR)&0x200000)!=0) break;
led_off();
while(1) if((GET32(STK_CVR)&0x200000)==0) break;
}
pll_init();
while(1)
{
led_on();
while(1) if((GET32(STK_CVR)&0x200000)!=0) break;
led_off();
while(1) if((GET32(STK_CVR)&0x200000)==0) break;
}
return(0);
}
建设
arm-linux-gnueabi-as --warn --fatal-warnings -mcpu=cortex-m0 flash.s -o flash.o
arm-linux-gnueabi-gcc -Wall -O2 -ffreestanding -mcpu=cortex-m0 -mthumb -c notmain.c -o notmain.o
arm-linux-gnueabi-ld -nostdlib -nostartfiles -T flash.ld flash.o notmain.o -o notmain.elf
arm-linux-gnueabi-objdump -D notmain.elf > notmain.list
arm-linux-gnueabi-objcopy -O binary notmain.elf notmain.bin
(当然可以把cortex-m0s改成cortex-m4s)
复制 notmain.bin 到核卡并观察用户 led 改变速度。快一点,慢一半,快很多。
嗯...
when VOS[1:0] = '0x11, the maximum value of f HCLK is 168 MHz. It can be extended to 180 MHz by activating the over-drive mode. The over-drive mode is not available when VDD ranges from 1.8 to 2.1 V (refer to Section 5.1.3: Voltage regulator for details on how to activate the over-drive mode).
和
11: Scale 1 mode (reset value)
(所以没必要纠结)
和
Entering Over-drive mode
It is recommended to enter Over-drive mode when the application is not running critical
tasks and when the system clock source is either HSI or HSE. To optimize the configuration
time, enable the Over-drive mode during the PLL lock phase.
To enter Over-drive mode, follow the sequence below:
Note:
1. Select HSI or HSE as system clock.
2. Configure RCC_PLLCFGR register and set PLLON bit of RCC_CR register.
3. Set ODEN bit of PWR_CR register to enable the Over-drive mode and wait for the
ODRDY flag to be set in the PWR_CSR register.
4. Set the ODSW bit in the PWR_CR register to switch the voltage regulator from Normal
mode to Over-drive mode. The System will be stalled during the switch but the PLL
clock system will be still running during locking phase.
5. Wait for the ODSWRDY flag in the PWR_CSR to be set.
6. Select the required Flash latency as well as AHB and APB prescalers.
7. Wait for PLL lock.
8. Switch the system clock to the PLL.
9. Enable the peripherals that are not generated by the System PLL (I2S clock, SAI1 and
SAI2 clocks, USB_48MHz clock....).
所以我 运行 在室温下,芯片远未接近最高温度,所以很可能为什么它可以像我在这里所做的那样超频工作。 (从技术上讲,它并不完整,需要为 168 或设置为超速)。
如果您想要 180 和 168,您应该按照文档执行这些步骤。
我怀疑你也没有运行将你的部分设置在最高温度附近,所以你也应该能够摆脱 180。尝试删除您的 pwr 寄存器内容,看看是否有帮助,让您的闪存延迟更长等。更改为 168mhz 等。
您是否尝试了 180 度,或者您是否首先尝试了一些不推动任何边缘的更合理的速度,例如低于 45mhz 的速度,然后是 45 到 90 之间的速度,然后是 90 以上,然后达到 180?
编辑
The Flash memory interface accelerates code execution with a system of instruction prefetch and cache lines.
Main features
• Flash memory read operations
• Flash memory program/erase operations
• Read / write protections
• Prefetch on I-Code
• 64 cache lines of 128 bits on I-Code
• 8 cache lines of 128 bits on D-Code
CubeMx 有一个非常方便的时钟配置工具。我不使用 HAL,但这个工具可以节省很多时间。
正如我所见,您试图通过使用自己的寄存器定义来重新发明轮子。使用标准的 CMSIS,因为创建自己的没有任何意义。
无法同时拥有 180MHz 时钟和使用 USB,因为您无法获得 USB 外设所需的 48MHz。
这里有一些可能的设置:
25MHz 外部振荡器: