自制脱机烧录器(二)

(二)SWD协议移植


前言

IO口模拟的SWD时序,我参考的是这位大神的文章。基于CMSIS-DAP,实现通过DAP读写目标芯片的内存、内核寄存器,这部分功能已经由ARM公司的CMSIS-DAP代码实现。我把主要移植到STM32G070RB上,把标准库改成了HAL库。


一、将下载算法加载到目标芯片SRAM

uint8_t swd_flash_syscall_exec(const program_syscall_t *sysCallParam, uint32_t entry, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4)

那么,我们只要把编程算法(一段在目标芯片上执行的代码,里面有Flash_Erase、Flash_Write两个函数)通过SWD写入目标芯片的SRAM,然后再通过SWD调用目标芯片SRAM里面的Flash_Erase、Flash_Write两个函数,不就能实现通过SWD给目标芯片编程了吗?

/*-------------------------------------------------*/
/*函数名:SWD下载                                  */
/*参  数:无                                       */
/*返回值:返回1下载成功,返回0下载失败              */
/*-------------------------------------------------*/
uint8_t Program_Target(void)
{
			if(swd_init_debug())                                                             //初始化下载端口
		{
			  //初始化
				if(user_target_flash_init(Flash_Start_Addr,Fire_Info.Fire_ver) != ERROR_SUCCESS)                       //初始化目标MCU的FLASH
				{
					printf("FLASH Init Error!\r\n");
					return 0;
				}
				     //擦除
						for(uint32_t addr = 0; addr < Fire_Info.Firelen[SelectFlash]; addr += 1024)   //擦除MCU的目标FLASH
						{
								if(user_target_flash_erase_sector(0x08000000 + addr,Fire_Info.Fire_ver) != ERROR_SUCCESS)
								{
									printf("Erase FLASH Error!\r\n");
									return 0;
								}
						}
						if(Fire_Info.Firelen[SelectFlash] %1024 != 0){                  //判断是否还有不满1扇区1024字节的数据,如果有进入if擦除
							  if( user_target_flash_erase_sector(0x08000000 + (Fire_Info.Firelen[SelectFlash]/1024)*1024,Fire_Info.Fire_ver) != ERROR_SUCCESS)
								{
											printf("Erase FLASH Error!\r\n");
									    return 0;
								}
						}
						#if DEBUG_INFO 
						// 读取擦除后的FLASH
						for(uint32_t addr = 0; addr < Fire_Info.Firelen[SelectFlash]; addr += 1024)
						{
								if(swd_read_memory(0x08000000 + addr, readbuff, 1024) == ERROR_SUCCESS){
									printf("Read FLASH Error!\r\n");
							    return 0;
								}        								
								for(uint32_t i = 0; i < 1024; i++) printf("%02X ", readbuff[i]);
								printf("\r\n\r\n\r\n");		
						}
						#endif /*DEBUG_INFO*/
						//将程序下载到目标MCU
						for(uint32_t addr = 0; addr < Fire_Info.Firelen[SelectFlash]; addr += 1024)
						{
								 W25QXX_Read(DataSta.databuff,FLASH_CAP * SelectFlash + addr,1024);   //从W25Q32中读取程序
								 if(user_target_flash_program_page(0x08000000 + addr, DataSta.databuff, 1024,Fire_Info.Fire_ver) != ERROR_SUCCESS){		//下载到目标MCU
									 printf("Program FLASH1 Error!\r\n");
							     return 0;
								 }
						}
						//再次读取MCU观察程序是否正确
						for(uint32_t addr = 0; addr < Fire_Info.Firelen[SelectFlash]; addr += 1024)
						{
								if(swd_read_memory(0x08000000 + addr, readbuff, 1024) == ERROR_SUCCESS){
									printf("Read FLASH Error!\r\n");
							    return 0;
								}
						#if DEBUG_INFO  								
								for(uint32_t i = 0; i < 1024; i++) printf("%02X ", readbuff[i]);
								 printf("\r\n\r\n\r\n");
						#endif /*DEBUG_INFO*/
						}
						#if DEBUG_INFO 
						if(Fire_Info.Firelen[SelectFlash] %1024 != 0){
							  if(swd_read_memory(0x08000000 +(Fire_Info.Firelen[SelectFlash]/1024)*1024, readbuff, Fire_Info.Firelen[SelectFlash]%1024) == ERROR_SUCCESS) {
									printf("Read FLASH Error!\r\n");
							    return 0;
								}			
							for(uint32_t j = 0; j < Fire_Info.Firelen[SelectFlash]%1024; j++)
                printf("%02X ",DataSta.databuff[j]);
						}
						#endif /*DEBUG_INFO*/
				swd_set_target_reset(0);//复位运行
			}
		else{
			printf("SWD Init Error!\r\n");
			return 0;
		}
		return 1;    //成功返回1
}

以上是下载步骤,在FLASH初始化中把下载算法加载到目标的SRAM,然后通过SWD的擦除,写入函数进行编程,下载完成后对目标芯片进行复位。

二、SWD的移植

1.改变移植芯片的主频

在这里插入图片描述
首先将源文件SW_DP.c,DAP.c,SWD_flash.c,SWD_host.c,error.c加入到工程中,然后将头文件DAP.h,DAP_config.h,error.h,SWD_flash.h,SWD_host.h,也加入到工程中,然后打开DAP_config.h文件,如下图所示:
在这里插入图片描述
CPU_CLOCK对应的是你移植芯片的主频,是多少就改成多少,我用的是STM32G070RB主频是64M,剩下的都搞成一样。

2.更改SWD下载引脚

在这里插入图片描述
GPIOC的GPIO_PIN_0对应的是SWDIO,GPIOC的GPIO_PIN_1对应的是SWCLK,这个自己想换成什么引脚都可以。如果是移植到标准库可能要改的东西多点,SWD协议目前已经移植完毕,这部分主要是DAP已经开源了。


三、下载算法的实现

既然下载程序需要目标芯片的下载算法,而每个芯片的算法都不一样,所以我们该怎么得到下载算法呢?我们知道,Keil针对每一颗芯片都有一个Flash编程算法,这个算法存在一个后缀为.FLM的文件里面,要是我们能把.FLM文件里面的算法内容抽取出来给我们用,那不就完美了吗其实这个功能也已经有国外大神给实现了,GitHub上的FlashAlgo项目里面有个flash_algo.py文件,它就是用来实现这个功能的,我已经把常用芯片的算法已经提取出来了放到这里下载算法
自己去提取想要的算法只需要把.FLM文件放在和FlashAlgo放在同一路径下,双击FlashAlgo即可生成对应的芯片.c文件下载算法

在这里插入图片描述


总结

整个编程烧写过程占用了目标芯片4K SRAM,其中SRAM起始地址为0x20000000,栈顶指向4K SRAM的末尾,,编程算法占用4K SRAM的前1K,,待烧写数据占用4K SRAM的中间2K,,静态变量和栈共用4K SRAM的最后1K这种设计对绝大多数Cortex-M芯片是没有问题的,所以对于有些比较特殊的芯片,,需要先修改一下flash_algo.py和c_blob.tmpl,然后再生成算法文件对应的.c文件,不过还好,生成是一次行的。最后将介绍若何使用上位机传输程序。
上位机操作(三)

  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值