STM32CubeIDE的STM32H750XB下载算法

STM32CubeIDE 的 STM32H750XB STLDR下载算法

#STM32CubeIDE下载算法原理
#创建下载算法工程
#修改代码
#测试算法
#结束

STM32CubeIDE下载算法原理

  • STM32CubeIDE的下载算法和STM32CubeProg是一样的,通过创建与地址信息无关的算法文件,实现
    初始化 int Init(void);
    读 int Read (uint32_t Address, uint32_t Size, uint8_t* buffer);
    写 int Write (uint32_t Address, uint32_t Size, uint8_t* buffer);
    擦除全部Flash int MassErase (void);
    扇区擦除int SectorErase (uint32_t EraseStartAddress ,uint32_t EraseEndAddress)
    校验 uint64_t Verify (uint32_t MemoryAddr, uint32_t RAMBufferAddr, uint32_t Size, uint32_t missalignement)

  • ST的下载算法模板在STLINK安装目录下的STMicroelectronics\STM32 ST-LINK Utility\ST-LINK Utility\ExternalLoader里,我这里用的是STM32H750和W25Q64,所以选择用N25Q512A_STM32F769I-EVAL这个模板

  • 算法的大致流程:
    图片中为MDK的下载算法,STM32CubeIDE基本上一样(没有Uninit函数)

擦除:

STM32CubeIDE的STM32H750XB下载算法_第1张图片
– 加载算法到芯片RAM
– 执行初始化函数 int Init(void) 初始化芯片时钟和外设等。
– 执行擦除函数(擦除扇区或整个Flash)
– 执行Uinit函数
– 完成

写Flash
STM32CubeIDE的STM32H750XB下载算法_第2张图片
– 加载算法到芯片RAM
– 执行初始化函数 int Init(void) 初始化芯片时钟和外设等。
– 加载要写的数据到RAM缓冲
– 执行Flash写函数
– 执行Uinit函数
– 完成

校验
校验这部分没写,因为STM32CubeIDE在下载中如果没有校验函数,会用Read函数将数据读出后进行CRC计算和RAM中加载的程序文件数据进行比较。

创建下载工程

复制 N25Q512A_STM32F769I-EVAL 文件到自己的文件夹下,打开MDK文件,修改器件为STM32H750XB

然后给生成的算法文件换个名
STM32CubeIDE的STM32H750XB下载算法_第3张图片
做如下图修改
STM32CubeIDE的STM32H750XB下载算法_第4张图片
STM32CubeIDE的STM32H750XB下载算法_第5张图片

如果程序的所有只读段都与位置无关,则该程序为只读位置无关(ROPI, Read-only position independence)。ROPI段通常是位置无关代码(PIC,position-independent code),但可以是只读数据,也可以是PIC和只读数据的组合。选择“ ROPI”选项,可以避免不得不将代码加载到内存中的特定位置。使用Read-Write position independence同理,表示的可读可写数据段。

修改Linker选项如图所示,修改 .sct文件(没有就自己创建一个空的)为:

FLASH_LOADER 0x20000004 PI   ; FlashLoader Functions
{
  PrgCode +0           ; Code
  {
    * (+RO)
  }
  PrgData +0           ; Data
  {
    * (+RW,+ZI)
  }
}

DEVICE_INFO +0               ; Device Info
{
  DevInfo +0           ; Info structure
  {
    dev_inf.o
  }
}

其中 PI 是指与地址无关码,详见MDK的sct文件详解。
STM32CubeIDE的STM32H750XB下载算法_第6张图片
Misc controls 里要填写 --diag_suppress L6305用于屏蔽L6503类型警告信息。
算法的加载地址由自己根据自己的芯片定义,我定义在了0x20000000,毕竟速度快。

在User中做如下修改,用来生成stldr文件
STM32CubeIDE的STM32H750XB下载算法_第7张图片

将HAL库替换为自己用到的库文件(可以在STM32CubeMX里生成)STM32CubeIDE的STM32H750XB下载算法_第8张图片
我自己添加的有些多,其实好多可以删掉。

在模板里有的Loader_Src.c里有

HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
  return HAL_OK;
}

函数和

void HAL_Delay(__IO uint32_t Delay)
{
  for(int i=0;i<Delay*480000;i++);
}

函数
这是因为在下载算法中无法使用使用Systick时钟,所有给这个函数做了重定向。

在模板里将SystemClock_Config替换为自己的时钟配置
STM32CubeIDE的STM32H750XB下载算法_第9张图片
修改Dev_Inf.c为
STM32CubeIDE的STM32H750XB下载算法_第10张图片
其中“STM32H750_W25Q64”是在STM32CubeIDE或STM32CubeProg识别的算法名字,把他改成自己喜欢的名字。

修改代码

初始化函数Init
完成工程的创建后,开始修改Loader_Src.c中关于下载相关的代码

int Init (void)
{

SystemInit();
  /* Zero Init structs */
SystemClock_Config();//STM32CubeMX生成的时钟配置
//Stm32_Clock_Init(192,5,2,4);	//设置时钟,400Mhz
  /* Initialize QuadSPI ------------------------------------------------------ */
MX_GPIO_Init();//LED GPIO配置
	
W25QXX_Init();//W25Q64初始化函数


//QUADSPI_MappedMode();//下载代码,就不要用到内存映射模式了,不太好用
  return 1; 
}

关于W25Q64使用内存映射模式,就不需要 Read 函数了,IDE会自动从总线读出flash的内容,不过每个函数最后都需要把QSPI设置为内存映射模式。用内存映射模式,STM32CubeProg 每次上电连接后,读取0X90000000(W25Q64)处的数据只能读取一次,然后就会出错误,暂时没有找到原因。

整个芯片擦除函数MassErase

int MassErase(void)
{

W25QXX_Init();

  W25QXX_ChipErase();
//W25Q_Memory_Mapped_Enable();
	return 1;

}

扇区擦除函数SectorErase

int SectorErase (uint32_t EraseStartAddress ,uint32_t EraseEndAddress)
{ 
 
    uint32_t BlockAddr;
		
EraseStartAddress -= 0x90000000;
EraseEndAddress   -= 0x90000000;

    EraseStartAddress = EraseStartAddress - (EraseStartAddress % 0x1000);
W25QXX_Init();
    while (EraseEndAddress >= EraseStartAddress)
    {
//防止超过256M空间
        BlockAddr = EraseStartAddress & 0x0FFFFFFF;

        W25QXX_SectorErase(BlockAddr);
        EraseStartAddress +=0x1000;
    }
//		W25Q_Memory_Mapped_Enable();
    return 1;
}

这个函数传入的地址是带有基地址(0x90000000)的,所以要减去这个基地址
在上文中定义了Dev_Inf.c中扇区大小为0x1000,所以这里每次擦除后地址要加上0x1000。

写函数 int Write

int Write(uint32_t Address, uint32_t Size, uint8_t* buffer)
{

    if (Address < 0x90000000 || Address >= 0x90000000 + 8*1024*1024)
    {
        return 0;
    }
    
    Address -= 0x90000000;
		W25QXX_Init();
		W25QXX_Write_NoCheck(buffer,Address,Size);
		
    /* 内存映射 */    
 //   W25Q_Memory_Mapped_Enable();


    return 1;  
}

读函数 int Write

int Read(uint32_t Address, uint32_t Size, uint8_t* buffer)
{ 
 uint32_t i;
uint32_t Adr;

HAL_GPIO_TogglePin(LED_R_GPIO_Port,LED_R_Pin);
Adr = Address - 0x90000000;
	W25QXX_Init();
	//W25Q_Memory_Mapped_Enable();

//	for(i=0;i

//    {

//			*buffer++ = *(uint8_t*)Adr++;

//    }
W25QXX_Read(buffer, Adr, Size);

	//W25QXX_Init();
  return 1;
} 

校验函数 uint64 Verify()

//uint64_t Verify (uint32_t MemoryAddr, uint32_t RAMBufferAddr, uint32_t Size, uint32_t missalignement)
//{
//    uint32_t VerifiedData = 0, InitVal = 0;
//    uint64_t checksum;
//    Size *= 4;
//		
//		
//		W25QXX_Init();
//		QUADSPI_MappedMode();
//  checksum = CheckSum((uint32_t)MemoryAddr + (missalignement & 0xF), Size - ((missalignement >> 16) & 0xF), InitVal);
//  while (Size>VerifiedData)
//  {
//    if ( *(uint8_t*)MemoryAddr++ != *((uint8_t*)RAMBufferAddr + VerifiedData))
//      return ((checksum<<32) + (MemoryAddr + VerifiedData));  
//   
//    VerifiedData++;  
//  }
//  
//  return (checksum<<32);

//}

全部注释掉就行,反正用不到

QSPI初始化以及W25Q64的初始化

代码搬运……就不放了

测试算法

将生成的stldr文件放在

C:\ST\STM32CubeIDE_1.4.0\STM32CubeIDE\plugins\com.st.stm32cube.ide.mcu.externaltools.cubeprogrammer.win32_1.5.0.202011040924\tools\bin\ExternalLoader

文件夹下……太长了

打开STM32CubeIDE中工程的Debug_Configurations,选择调试器,添加下载算法,如图
STM32CubeIDE的STM32H750XB下载算法_第11张图片
看那个下载算法的名字,和我在Dev_Inf.c中定义的内容一样。

在工程文件的 STM32H750XBHX_FLASH.ld文件中添加代码
STM32CubeIDE的STM32H750XB下载算法_第12张图片
因为我开启的TouchGFX工程,所以在最后添加
STM32CubeIDE的STM32H750XB下载算法_第13张图片
编译工程,可以看到QSPIFLASH中占用了一些空间
STM32CubeIDE的STM32H750XB下载算法_第14张图片
点击下载,出现STM32CubeIDE的STM32H750XB下载算法_第15张图片
并且 main函数中的LED也开始闪烁,表示下载成功,也可以用STM32CubeProg查看0x90000000中的内容与elf文件中的是一样的。

结束

本文部分内容来自https://blog.csdn.net/Simon223/article/details/109772910

你可能感兴趣的:(STM32CubeIDE的STM32H750XB下载算法)