DAP之FLM算法研究

  目录

玩过自制DAP工具的一定都知道通过MDK目录的FLM文件,通过工具可以获取一段FLASH的操作算法文件,算法文件由一串HEX字符串组成,但这算法的内容相信大多数的人都没有研究过。由于本人尽来因为服务的客户令人十分糟心,也想搞个刷写器的项目,因此本着好奇的心,研究了了该HEX文本的算法内容,并将汇编反译成了C。

以下记录下过程:

FlashAlgo生成C文件

FlashAlgo压缩文件内有两个FLM文件,一个EXE文件
FlashAlgo压缩文件内容

而FLM文件通过搜索MDK的安装目录大约可以找到90多个,因此对于不同的芯片,如果想要制作不同的DAP的话,通过更换FLM文件即可制作算法文件。
MDK安装目录的FLM

flash_algo生成的C代码

 以下以STM32F10X的芯片为例,使用flash_algo生成的C代码如下

/* Flash OS Routines (Automagically Generated)
 * Copyright (c) 2009-2015 ARM Limited
 */
#include "flash_blob.h"

/******************************************
*              stm32F1系列的下载算法
*其作用就是在下载主程序之前,给目标MCU的SRAM下载一段引导代码
*然后调用这段代码里面的flash读取和擦除函数对目标芯片编程
*不同芯片的下载算法不同,其下载算法可以在MDK的FLM文件中提取
*/
static const uint32_t flash_code[] = {
    0xE00ABE00, 0x062D780D, 0x24084068, 0xD3000040, 0x1E644058, 0x1C49D1FA, 0x2A001E52, 0x4770D1F2,
    0x4603B510, 0x4C442000, 0x48446020, 0x48446060, 0x46206060, 0xF01069C0, 0xD1080F04, 0x5055F245,
    0x60204C40, 0x60602006, 0x70FFF640, 0x200060A0, 0x4601BD10, 0x69004838, 0x0080F040, 0x61104A36,
    0x47702000, 0x69004834, 0x0004F040, 0x61084932, 0x69004608, 0x0040F040, 0xE0036108, 0x20AAF64A,
    0x60084930, 0x68C0482C, 0x0F01F010, 0x482AD1F6, 0xF0206900, 0x49280004, 0x20006108, 0x46014770,
    0x69004825, 0x0002F040, 0x61104A23, 0x61414610, 0xF0406900, 0x61100040, 0xF64AE003, 0x4A2120AA,
    0x481D6010, 0xF01068C0, 0xD1F60F01, 0x6900481A, 0x0002F020, 0x61104A18, 0x47702000, 0x4603B510,
    0xF0201C48, 0xE0220101, 0x69004813, 0x0001F040, 0x61204C11, 0x80188810, 0x480FBF00, 0xF01068C0,
    0xD1FA0F01, 0x6900480C, 0x0001F020, 0x61204C0A, 0x68C04620, 0x0F14F010, 0x4620D006, 0xF04068C0,
    0x60E00014, 0xBD102001, 0x1C921C9B, 0x29001E89, 0x2000D1DA, 0x0000E7F7, 0x40022000, 0x45670123,
    0xCDEF89AB, 0x40003000, 0x00000000
};

const program_target_t flash_algo = {
    0x20000021,  // Init
    0x20000053,  // UnInit
    0x20000065,  // EraseChip
    0x2000009F,  // EraseSector
    0x200000DD,  // ProgramPage

    // BKPT : start of blob + 1
    // RSB  : address to access global/static data
    // RSP  : stack pointer
    {
        0x20000001,
        0x20000C00,
        0x20001000
    },

    0x20000400,  // mem buffer location
    0x20000000,  // location to write prog_blob in target RAM
    sizeof(flash_code),  // prog_blob size
    flash_code,  // address of prog_blob
    0x00000400,  // ram_to_flash_bytes_to_be_written
};

将其中的flash_code写入到一个TXT文件中,并使用自制的工具将其转换为HEX文件
flash_codel转HEX

反汇编的ASM文件

;-------------------------------------------------------------------------------
;---- DISASSEMBLE INFORMATION :
;---- File Name: flash_blob.hex
;---- CPU Family:STM32F10x
;---- CPU Factory:STMicroelectronics
;---- CPU Model: STM32F103C8T6
;---- Time Stamp: 621073228816300
;----
;----   Writen by: beacon_light@163.com
;----      Wechat: 18676693732
;----          QQ: 19263826
;-------------------------------------------------------------------------------
                PRESERVE8
                THUMB

                AREA    RESET, DATA, READONLY
                DCD 0
__Vectors       DCD Reset_Handler
                
				;ALIGN 0X200
; Segment type: Pure code

                AREA    |.text|, CODE, READONLY
				;AREA    RAMCODE, CODE, READONLY

; =============== S U B R O U T I N E =======================================

Reset_Handler
;BKPT_20000000
                BKPT    0
                B       loc_2000001A

loc_20000004
                LDRB    R5, [R1]
                LSLS    R5, R5, #0x18
                EORS    R0, R5
                MOVS    R4, #8

loc_2000000C
                LSLS    R0, R0, #1
                BCC     loc_20000012
                EORS    R0, R3

loc_20000012
                SUBS    R4, R4, #1
                BNE     loc_2000000C
                ADDS    R1, R1, #1
                SUBS    R2, R2, #1

loc_2000001A
                CMP     R2, #0
                BNE     loc_20000004
                BX      LR
; End of function BKPT_20000000


; =============== S U B R O U T I N E =======================================
Init_20000020
                PUSH    {R4,LR}
                MOV     R3, R0
                MOVS    R0, #0
                LDR     R4, off_20000138 ; 0x40022000
                STR     R0, [R4]
                LDR     R0, dword_2000013C ; 0x45670123
                STR     R0, [R4,#4]
                LDR     R0, dword_20000140 ; 0xCDEF89AB
                STR     R0, [R4,#4]
                MOV     R0, R4
                LDR     R0, [R0,#0x1C]
                TST.W   R0, #4
                BNE     loc_2000004E
                MOVW    R0, #0x5555
                LDR     R4, off_20000144 ; 0x40003000
                STR     R0, [R4]
                MOVS    R0, #6
                STR     R0, [R4,#4]
                MOVW    R0, #0xFFF
                STR     R0, [R4,#8]

loc_2000004E
                MOVS    R0, #0
                POP     {R4,PC}
; End of function Init_20000020


; =============== S U B R O U T I N E =======================================
UnInit_20000052
                MOV     R1, R0
                LDR     R0, off_20000138 ; 0x40022000
                LDR     R0, [R0,#0x10]
                ORR.W   R0, R0, #0x80
                LDR     R2, off_20000138 ; 0x40022000
                STR     R0, [R2,#0x10]
                MOVS    R0, #0
                BX      LR
; End of function UnInit_20000052


; =============== S U B R O U T I N E =======================================
EraseChip_20000064
                LDR     R0, off_20000138 ; 0x40022000
                LDR     R0, [R0,#0x10]
                ORR.W   R0, R0, #4
                LDR     R1, off_20000138 ; 0x40022000
                STR     R0, [R1,#0x10]
                MOV     R0, R1
                LDR     R0, [R0,#0x10]
                ORR.W   R0, R0, #0x40
                STR     R0, [R1,#0x10]
                B       loc_20000084
; ---------------------------------------------------------------------------

loc_2000007C
                MOVW    R0, #0xAAAA
                LDR     R1, off_20000144 ; 0x40003000
                STR     R0, [R1]

loc_20000084
                LDR     R0, off_20000138 ; 0x40022000
                LDR     R0, [R0,#0xC]
                TST.W   R0, #1
                BNE     loc_2000007C
                LDR     R0, off_20000138 ; 0x40022000
                LDR     R0, [R0,#0x10]
                BIC.W   R0, R0, #4
                LDR     R1, off_20000138 ; 0x40022000
                STR     R0, [R1,#0x10]
                MOVS    R0, #0
                BX      LR
; End of function EraseChip_20000064


; =============== S U B R O U T I N E =======================================
EraseSector_2000009E
                MOV     R1, R0
                LDR     R0, off_20000138 ; 0x40022000
                LDR     R0, [R0,#0x10]
                ORR.W   R0, R0, #2
                LDR     R2, off_20000138 ; 0x40022000
                STR     R0, [R2,#0x10]
                MOV     R0, R2
                STR     R1, [R0,#0x14]
                LDR     R0, [R0,#0x10]
                ORR.W   R0, R0, #0x40
                STR     R0, [R2,#0x10]
                B       loc_200000C2
; ---------------------------------------------------------------------------

loc_200000BA
                MOVW    R0, #0xAAAA
                LDR     R2, off_20000144 ; 0x40003000
                STR     R0, [R2]

loc_200000C2
                LDR     R0, off_20000138 ; 0x40022000
                LDR     R0, [R0,#0xC]
                TST.W   R0, #1
                BNE     loc_200000BA
                LDR     R0, off_20000138 ; 0x40022000
                LDR     R0, [R0,#0x10]
                BIC.W   R0, R0, #2
                LDR     R2, off_20000138 ; 0x40022000
                STR     R0, [R2,#0x10]
                MOVS    R0, #0
                BX      LR
; End of function EraseSector_2000009E


; =============== S U B R O U T I N E =======================================
ProgramPage_200000DC
                PUSH    {R4,LR}
                MOV     R3, R0
                ADDS    R0, R1, #1
                BIC.W   R1, R0, #1
                B       loc_2000012E
; ---------------------------------------------------------------------------

loc_200000E8
                LDR     R0, off_20000138 ; 0x40022000
                LDR     R0, [R0,#0x10]
                ORR.W   R0, R0, #1
                LDR     R4, off_20000138 ; 0x40022000
                STR     R0, [R4,#0x10]
                LDRH    R0, [R2]
                STRH    R0, [R3]
                NOP

loc_200000FA
                LDR     R0, off_20000138 ; 0x40022000
                LDR     R0, [R0,#0xC]
                TST.W   R0, #1
                BNE     loc_200000FA
                LDR     R0, off_20000138 ; 0x40022000
                LDR     R0, [R0,#0x10]
                BIC.W   R0, R0, #1
                LDR     R4, off_20000138 ; 0x40022000
                STR     R0, [R4,#0x10]
                MOV     R0, R4
                LDR     R0, [R0,#0xC]
                TST.W   R0, #0x14
                BEQ     loc_20000128
                MOV     R0, R4
                LDR     R0, [R0,#0xC]
                ORR.W   R0, R0, #0x14
                STR     R0, [R4,#0xC]
                MOVS    R0, #1

locret_20000126
                POP     {R4,PC}
; ---------------------------------------------------------------------------

loc_20000128
                ADDS    R3, R3, #2
                ADDS    R2, R2, #2
                SUBS    R1, R1, #2

loc_2000012E
                CMP     R1, #0
                BNE     loc_200000E8
                MOVS    R0, #0
                B       locret_20000126
; End of function ProgramPage_200000DC

; ---------------------------------------------------------------------------
                ALIGN 4
off_20000138    DCD 0x40022000
dword_2000013C  DCD 0x45670123
dword_20000140  DCD 0xCDEF89AB
off_20000144    DCD 0x40003000
                DCD 0
; seg000        ends

                END

重构的C代码

#include "stm32f10x_flash.h"

/* Flash Access Control Register bits */
#define ACR_LATENCY_Mask         ((uint32_t)0x00000038)
#define ACR_HLFCYA_Mask          ((uint32_t)0xFFFFFFF7)
#define ACR_PRFTBE_Mask          ((uint32_t)0xFFFFFFEF)

/* Flash Access Control Register bits */
#define ACR_PRFTBS_Mask          ((uint32_t)0x00000020) 

/* Flash Control Register bits */
#define CR_PG_Set                ((uint32_t)0x00000001)
#define CR_PG_Reset              ((uint32_t)0x00001FFE) 
#define CR_PER_Set               ((uint32_t)0x00000002)
#define CR_PER_Reset             ((uint32_t)0x00001FFD)
#define CR_MER_Set               ((uint32_t)0x00000004)
#define CR_MER_Reset             ((uint32_t)0x00001FFB)
#define CR_OPTPG_Set             ((uint32_t)0x00000010)
#define CR_OPTPG_Reset           ((uint32_t)0x00001FEF)
#define CR_OPTER_Set             ((uint32_t)0x00000020)
#define CR_OPTER_Reset           ((uint32_t)0x00001FDF)
#define CR_STRT_Set              ((uint32_t)0x00000040)
#define CR_LOCK_Set              ((uint32_t)0x00000080)

/* FLASH Mask */
#define RDPRT_Mask               ((uint32_t)0x00000002)
#define WRP0_Mask                ((uint32_t)0x000000FF)
#define WRP1_Mask                ((uint32_t)0x0000FF00)
#define WRP2_Mask                ((uint32_t)0x00FF0000)
#define WRP3_Mask                ((uint32_t)0xFF000000)
#define OB_USER_BFB2             ((uint16_t)0x0008)

/* FLASH Keys */
#define RDP_Key                  ((uint16_t)0x00A5)
#define FLASH_KEY1               ((uint32_t)0x45670123)
#define FLASH_KEY2               ((uint32_t)0xCDEF89AB)

/* FLASH BANK address */
#define FLASH_BANK1_END_ADDRESS   ((uint32_t)0x807FFFF)

/* Delay definition */   
#define EraseTimeout          ((uint32_t)0x000B0000)
#define ProgramTimeout        ((uint32_t)0x00002000)

#define BKPT(v) __asm { BKPT v }

void BreakPoint(int r0, char* r1, int len, int r3)
{ 
   int c, temp;
   
   BKPT(0) 
   for(; len; len--,r1++) {
      temp = *r1<<24;
      r0 ^= temp;
      for(c=8; c; c--) { 
          temp = r0; 
          r0 <<= 1; 
          if(temp&0x80000000) { 
              r0 ^= r3; 
          }
      }
   }
}

int Init()
{ 
    FLASH->ACR = 0; // 0x40022000
    FLASH->KEYR = FLASH_KEY1; // 0x45670123, unlock Flash 1/2
    FLASH->KEYR = FLASH_KEY2; // 0xCDEF89AB, unlock Flash 2/2
    if(FLASH->OBR&4) {        // User Option: IWDG_SW(Bit0) is Set
        IWDG->KR = 0x5555; 
        IWDG->PR = 6; 
        IWDG->RLR = 0xFFF; 
    }
    return 0; 
}

int UnInit(void) 
{
    FLASH->CR |= CR_LOCK_Set; 
    return 0; 
} 

int EraseChip(void)
{
    FLASH->CR |= CR_MER_Set;  // 0x04
    FLASH->CR |= CR_STRT_Set; // 0x40
    while(FLASH->SR&FLASH_FLAG_BSY) { 
        IWDG->KR = 0xAAAA; 
    }
    FLASH->CR &= CR_MER_Reset; 
    return 0; 
}

int EraseSector(int sectorNum) 
{
    FLASH->CR |= CR_PER_Set; // 0x02 
    FLASH->AR = sectorNum; 
    FLASH->CR |= CR_STRT_Set; // 0x40
    while(FLASH->SR&FLASH_FLAG_BSY) { 
        IWDG->KR = 0xAAAA; 
    }
    FLASH->CR &= CR_PER_Reset; 
    return 0; 
}

int ProgramPage(char* dst, int size, char* src, int len) 
{ 
    // Align 2 bytes
    size += 1; 
    size &= ~1; 
    
    for(; size; size-=2) { 
        FLASH->CR |= CR_PG_Set; // 0x01 
        *((uint16_t*)dst) = *((uint16_t*)src); 
        __NOP();
        while(FLASH->SR&FLASH_FLAG_BSY); 
        FLASH->CR &= CR_PG_Reset;  
        if(FLASH->SR&(FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR)) { 
            FLASH->SR |= FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR; 
            return 1; 
        }
        dst += 2; 
        src += 2; 
    }
    return 0; 
}

一个未知问题

由文中可见BreakPoint函数中的操作,联系DAP的上下文,该段代码并没有什么的用途 ,不知具体何用
swd_falsh_syscall_exec调用

 breakpoint是做为完成函数调用后的返回,里面正常应该是一个死循环,但实际上的操作做了一些数据的运算,实在不知其义

源代码

flash_blob.zip

参考资料

关于STM32Flash详解_stmflash_涂路的博客-CSDN博客
STM32的IWDG(独立看门狗)详细用法_stm32 iwdg_魏波.的博客-CSDN博客
STM32 进阶教程 11 - RAM中运行程序_stm32程序在ram中运行_张十三的博客的博客-CSDN博客


文章作者: 改变世界
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 改变世界 !
评论