396 lines
10 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "sys.h"
//////////////////////////////////////////////////////////////////////////////////
//STM32H7开发板
//系统时钟初始化
//STM32H7工程模板-HAL库函数版本
//DevEBox 大越创新
//淘宝店铺mcudev.taobao.com
//淘宝店铺shop389957290.taobao.com
/////////////////////////////////////////////////////////////////////////////////
/*******************************************************************************/
//使能CPU的L1-Cache
//STM32H7工程模板-HAL库函数版本
//DevEBox 大越创新
//淘宝店铺mcudev.taobao.com
//淘宝店铺shop389957290.taobao.com
/*******************************************************************************/
void Cache_Enable(void)
{
SCB_EnableICache();//使能I-Cache
SCB_EnableDCache();//使能D-Cache
SCB->CACR|=1<<2; //强制D-Cache透写,如不开启,实际使用中可能遇到各种问题
}
/*******************************************************************************/
//时钟设置函数
//Fvco=Fs*(plln/pllm);
//Fsys=Fvco/pllp=Fs*(plln/(pllm*pllp));
//Fq=Fvco/pllq=Fs*(plln/(pllm*pllq));
//Fvco:VCO频率
//Fsys:系统时钟频率,也是PLL1的p分频输出时钟频率
//Fq:PLL1的q分频输出时钟频率
//Fs:PLL输入时钟频率,可以是HSI,CSI,HSE等.
//plln:PLL1倍频系数(PLL倍频),取值范围:4~512.
//pllm:PLL1预分频系数(进PLL之前的分频),取值范围:2~63.
//pllp:PLL1的p分频系数(PLL之后的分频),分频后作为系统时钟,取值范围:2~128.(且必须是2的倍数)
//pllq:PLL1的q分频系数(PLL之后的分频),取值范围:1~128.
//CPU频率(rcc_c_ck)=sys_d1cpre_ck=400Mhz
//rcc_aclk=rcc_hclk3=200Mhz
//AHB1/2/3/4(rcc_hclk1/2/3/4)=200Mhz
//APB1/2/3/4(rcc_pclk1/2/3/4)=100Mhz
//FMC时钟频率=pll2_r_ck=((25/25)*512/2)=256Mhz
//外部晶振为25M的时候,推荐值:plln=160,pllm=5,pllp=2,pllq=2.
//得到:Fvco=25*(160/5)=800Mhz
// Fsys=800/2=400Mhz
// Fq=800/2=400Mhz
//返回值:0,成功;1,失败。
//STM32H7工程模板-HAL库函数版本
//DevEBox 大越创新
//淘宝店铺mcudev.taobao.com
//淘宝店铺shop389957290.taobao.com
/*******************************************************************************/
u8 Stm32_Clock_Init(u32 plln,u32 pllm,u32 pllp,u32 pllq)
{
HAL_StatusTypeDef ret=HAL_OK;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;
MODIFY_REG(PWR->CR3,PWR_CR3_SCUEN, 0);
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
while ((PWR->D3CR & (PWR_D3CR_VOSRDY)) != PWR_D3CR_VOSRDY) {}
RCC_OscInitStruct.OscillatorType=RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState=RCC_HSE_ON;
RCC_OscInitStruct.HSIState=RCC_HSI_OFF;
RCC_OscInitStruct.CSIState=RCC_CSI_OFF;
RCC_OscInitStruct.PLL.PLLState=RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource=RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLN=plln;
RCC_OscInitStruct.PLL.PLLM=pllm;
RCC_OscInitStruct.PLL.PLLP=pllp;
RCC_OscInitStruct.PLL.PLLQ=pllq;
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_2;
ret=HAL_RCC_OscConfig(&RCC_OscInitStruct);
if(ret!=HAL_OK) return 1;
//QSPI_Enable_Memmapmode(); //QSPI内存映射模式,需要在时钟初始化之前开启,否则会有各种问题
RCC_ClkInitStruct.ClockType=(RCC_CLOCKTYPE_SYSCLK|\
RCC_CLOCKTYPE_HCLK |\
RCC_CLOCKTYPE_D1PCLK1 |\
RCC_CLOCKTYPE_PCLK1 |\
RCC_CLOCKTYPE_PCLK2 |\
RCC_CLOCKTYPE_D3PCLK1);
RCC_ClkInitStruct.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.SYSCLKDivider=RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLKDivider=RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB1CLKDivider=RCC_APB1_DIV2;
RCC_ClkInitStruct.APB2CLKDivider=RCC_APB2_DIV2;
RCC_ClkInitStruct.APB3CLKDivider=RCC_APB3_DIV2;
RCC_ClkInitStruct.APB4CLKDivider=RCC_APB4_DIV4;
ret=HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
if(ret!=HAL_OK) return 1;
__HAL_RCC_CSI_ENABLE() ;
__HAL_RCC_SYSCFG_CLK_ENABLE() ;
HAL_EnableCompensationCell();
return 0;
}
#ifdef USE_FULL_ASSERT
//当编译提示出错的时候此函数用来报告错误的文件和所在行
//file指向源文件
//line指向在文件中的行数
void assert_failed(uint8_t* file, uint32_t line)
{
while (1)
{
}
}
#endif
/*******************************************************************************/
//判断I_Cache是否打开
//返回值:0 关闭1 打开
//STM32H7工程模板-HAL库函数版本
//DevEBox 大越创新
//淘宝店铺mcudev.taobao.com
//淘宝店铺shop389957290.taobao.com
/*******************************************************************************/
u8 Get_ICahceSta(void)
{
u8 sta;
sta=((SCB->CCR)>>17)&0X01;
return sta;
}
/*******************************************************************************/
//判断I_Dache是否打开
//返回值:0 关闭1 打开
//STM32H7工程模板-HAL库函数版本
//DevEBox 大越创新
//淘宝店铺mcudev.taobao.com
//淘宝店铺shop389957290.taobao.com
/*******************************************************************************/
u8 Get_DCahceSta(void)
{
u8 sta;
sta=((SCB->CCR)>>16)&0X01;
return sta;
}
/*******************************************************************************/
//QSPI进入内存映射模式执行QSPI代码必备前提为了减少引入的文件
//除了GPIO驱动外其他的外设驱动均采用寄存器形式
//STM32H7工程模板-HAL库函数版本
//DevEBox 大越创新
//淘宝店铺mcudev.taobao.com
//淘宝店铺shop389957290.taobao.com
/*******************************************************************************/
void QSPI_Enable_Memmapmode(void)
{
u32 tempreg=0;
vu32 *data_reg=&QUADSPI->DR;
GPIO_InitTypeDef qspi_gpio;
RCC->AHB4ENR|=1<<1; //使能PORTB时钟
RCC->AHB4ENR|=1<<5; //使能PORTF时钟
RCC->AHB3ENR|=1<<14; //QSPI时钟使能
qspi_gpio.Pin=GPIO_PIN_6; //PB6 AF10
qspi_gpio.Mode=GPIO_MODE_AF_PP;
qspi_gpio.Speed=GPIO_SPEED_FREQ_VERY_HIGH;
qspi_gpio.Pull=GPIO_NOPULL;
qspi_gpio.Alternate=GPIO_AF10_QUADSPI;
HAL_GPIO_Init(GPIOB,&qspi_gpio);
qspi_gpio.Pin=GPIO_PIN_2; //PB2 AF9
qspi_gpio.Alternate=GPIO_AF9_QUADSPI;
HAL_GPIO_Init(GPIOB,&qspi_gpio);
qspi_gpio.Pin=GPIO_PIN_6|GPIO_PIN_7; //PF6,7 AF9
qspi_gpio.Alternate=GPIO_AF9_QUADSPI;
HAL_GPIO_Init(GPIOF,&qspi_gpio);
qspi_gpio.Pin=GPIO_PIN_8|GPIO_PIN_9; //PF8,9 AF10
qspi_gpio.Alternate=GPIO_AF10_QUADSPI;
HAL_GPIO_Init(GPIOF,&qspi_gpio);
//QSPI设置参考QSPI实验的QSPI_Init函数
RCC->AHB3RSTR|=1<<14; //复位QSPI
RCC->AHB3RSTR&=~(1<<14); //停止复位QSPI
while(QUADSPI->SR&(1<<5)); //等待BUSY位清零
QUADSPI->CR=0X01000310; //设置CR寄存器,这些值怎么来的请参考QSPI实验/看H750参考手册寄存器描述分析
QUADSPI->DCR=0X00160401; //设置DCR寄存器
QUADSPI->CR|=1<<0; //使能QSPI
//注意:QSPI QE位的使能在QSPI烧写算法里面就已经设置了
//所以,这里可以不用设置QE位否则需要加入对QE位置1的代码
//不过,代码必须通过仿真器下载,直接烧录到外部QSPI FLASH,是不可用的
//如果想直接烧录到外部QSPI FLASH也可以用,则需要在这里添加QE位置1的代码
//W25QXX进入QPI模式0X38指令
while(QUADSPI->SR&(1<<5)); //等待BUSY位清零
QUADSPI->CCR=0X00000138; //发送0X38指令W25QXX进入QPI模式
while((QUADSPI->SR&(1<<1))==0); //等待指令发送完成
QUADSPI->FCR|=1<<1; //清除发送完成标志位
//W25QXX写使能0X06指令
while(QUADSPI->SR&(1<<5)); //等待BUSY位清零
QUADSPI->CCR=0X00000106; //发送0X06指令W25QXX写使能
while((QUADSPI->SR&(1<<1))==0); //等待指令发送完成
QUADSPI->FCR|=1<<1; //清除发送完成标志位
//W25QXX设置QPI相关读参数0XC0
while(QUADSPI->SR&(1<<5)); //等待BUSY位清零
QUADSPI->CCR=0X030003C0; //发送0XC0指令W25QXX读参数设置
QUADSPI->DLR=0;
while((QUADSPI->SR&(1<<2))==0); //等待FTF
*(vu8 *)data_reg=3<<4; //设置P4&P5=11,8个dummy clocks,104M
QUADSPI->CR|=1<<2; //终止传输
while((QUADSPI->SR&(1<<1))==0); //等待数据发送完成
QUADSPI->FCR|=1<<1; //清除发送完成标志位
while(QUADSPI->SR&(1<<5)); //等待BUSY位清零
//MemroyMap 模式设置
while(QUADSPI->SR&(1<<5)); //等待BUSY位清零
QUADSPI->ABR=0; //交替字节设置为0实际上就是W25Q 0XEB指令的,M0~M7=0
tempreg=0XEB; //INSTRUCTION[7:0]=0XEB,发送0XEB指令Fast Read QUAD I/O
tempreg|=3<<8; //IMODE[1:0]=3,四线传输指令
tempreg|=3<<10; //ADDRESS[1:0]=3,四线传输地址
tempreg|=2<<12; //ADSIZE[1:0]=2,24位地址长度
tempreg|=3<<14; //ABMODE[1:0]=3,四线传输交替字节
tempreg|=0<<16; //ABSIZE[1:0]=0,8位交替字节(M0~M7)
tempreg|=6<<18; //DCYC[4:0]=6,6个dummy周期
tempreg|=3<<24; //DMODE[1:0]=3,四线传输数据
tempreg|=3<<26; //FMODE[1:0]=3,内存映射模式
QUADSPI->CCR=tempreg; //设置CCR寄存器
//设置QSPI FLASH空间的MPU保护
SCB->SHCSR&=~(1<<16); //禁止MemManage
MPU->CTRL&=~(1<<0); //禁止MPU
MPU->RNR=0; //设置保护区域编号为0(1~7可以给其他内存用)
MPU->RBAR=0X90000000; //基地址为0X9000 000,即QSPI的起始地址
MPU->RASR=0X0303002D; //设置相关保护参数(禁止共用,允许cache,允许缓冲),详见MPU实验的解析
MPU->CTRL=(1<<2)|(1<<0); //使能PRIVDEFENA,使能MPU
SCB->SHCSR|=1<<16; //使能MemManage
}
/*******************************************************************************/
//STM32H7工程模板-HAL库函数版本
//DevEBox 大越创新
//淘宝店铺mcudev.taobao.com
//淘宝店铺shop389957290.taobao.com
/*******************************************************************************/
#if defined(__clang__) //使用V6编译器(clang)
//THUMB指令不支持汇编内联
//采用如下方法实现执行汇编指令WFI
void __attribute__((noinline)) WFI_SET(void)
{
__asm__("wfi");
}
//关闭所有中断(但是不包括fault和NMI中断)
void __attribute__((noinline)) INTX_DISABLE(void)
{
__asm__("cpsid i \t\n"
"bx lr");
}
//开启所有中断
void __attribute__((noinline)) INTX_ENABLE(void)
{
__asm__("cpsie i \t\n"
"bx lr");
}
//设置栈顶地址
//addr:栈顶地址
void __attribute__((noinline)) MSR_MSP(u32 addr)
{
__asm__("msr msp, r0 \t\n"
"bx r14");
}
#elif defined (__CC_ARM) //使用V5编译器(ARMCC)
//THUMB指令不支持汇编内联
//采用如下方法实现执行汇编指令WFI
__asm void WFI_SET(void)
{
WFI;
}
//关闭所有中断(但是不包括fault和NMI中断)
__asm void INTX_DISABLE(void)
{
CPSID I
BX LR
}
//开启所有中断
__asm void INTX_ENABLE(void)
{
CPSIE I
BX LR
}
//设置栈顶地址
//addr:栈顶地址
__asm void MSR_MSP(u32 addr)
{
MSR MSP, r0 //set Main Stack value
BX r14
}
#endif
/*******************************************************************************/
//STM32H7工程模板-HAL库函数版本
//DevEBox 大越创新
//淘宝店铺mcudev.taobao.com
//淘宝店铺shop389957290.taobao.com
/*******************************************************************************/