这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » 【IAR】通过C-SPY和flashloader之间传递参数

共2条 1/1 1 跳转至

【IAR】通过C-SPY和flashloader之间传递参数

工程师
2025-02-19 17:52:28     打赏

简介

      在上一篇(【IAR】 基于GD32F427的flashloader下载算法实现)我们已经实现了个可以更新flash的flashloader 算法程序,我们在此基础上继续修改代码支持IAR(C-SPY) 传递参数给到flashloader 来控制flashloader,实现IAR 和 flashloader的交互功能。

IAR IDE 可以在该路径下添加参数,我们可以在此处添加参数,C-SPY 会将参数写入RAM中,然后调用flashloader 的接口函数时把地址传递到函数,从而完成IDE 和 flashloader 的参数传递过程。

image.png

如果flashloader 支持多种下载参数配置,我们即可通过此处来设置参数,本次试验使用的开发板GD32VF427 的flash 的编程方式支持1/2/4/8字节的写入方式,我们可以通过--x8/--x16/--x32 的参数来配置编程的字节默认使用8byte的写入方式。同时为了查看运行中的内存状态添加--dumpram 参数来dump 内存信息,用于查看flash loader 运行期间的信息,在IAR 中添加参数配置如下。

image.png

在IAR 端我们已经配置好了参数,我们继续修改flashloader 程序,在初始化时加入参数的解析处理,对应修改如下。

#if USE_ARGC_ARGV
uint32_t FlashInit(void *base_of_flash, uint32_t image_size,
                   uint32_t link_address, uint32_t flags,
                   int argc, char const *argv[])
#else
uint32_t FlashInit(void *base_of_flash, uint32_t image_size,
                   uint32_t link_address, uint32_t flags)
#endif
{
    uint32_t temp = 0;
    uint8_t memdump = 0; 
    parallelism = 3;
#ifdef USE_ARGC_ARGV
  for(int i = 0; i < argc; i++)
  {
    /* Parallelism flag*/
    if(strcmp("--x8", argv[i]) == 0)
    {
      parallelism = 0;
    }
    else if (strcmp("--x16", argv[i]) == 0)
    {
      parallelism = 1;
    }
    else if (strcmp("--x32", argv[i]) == 0)
    {
      parallelism = 2;
    }
    else if(strcmp("--dumpram",argv[i]) == 0)
    {
      memdump = 1;
    }
  }
#endif

#ifdef DEBUG_MESS
    /* enable GPIO clock */
    RCU_AHB1EN |= 0x01u << 1;
    /* enable USART clock */
    RCU_APB2EN |= 0x01u <<4;

    GPIO_CTL(GPIOB) &= ~(0x03u << (2*6));
    GPIO_CTL(GPIOB) |= (2 << (2*6));

    GPIO_PUD(GPIOB) &= ~(0x03u << (2*6));
    GPIO_PUD(GPIOB) |= (1u << (2*6));
    GPIO_OMODE(GPIOB) &= ~(0x01u << 6);

    GPIO_OSPD(GPIOB) &= ~(0x03u << (2*6));
    GPIO_OSPD(GPIOB) |= (0x01u << (2*6));

    GPIO_AFSEL0(GPIOB) &= ~(0xf << (4*6));
    GPIO_AFSEL0(GPIOB) |= (0x7 << (4*6));

    /* config uart0 */
    uint32_t uclk = 0U, intdiv = 0U, fradiv = 0U, udiv = 0U;
    uclk = rcu_clock_freq_get(CK_APB2);

    if(USART_CTL0(USART0) & USART_CTL0_OVSMOD) {
        /* when oversampling by 8, configure the value of USART_BAUD */
        udiv = ((2U * uclk) + 115200 / 2U) / 115200;
        intdiv = udiv & 0xfff0U;
        fradiv = (udiv >> 1U) & 0x7U;
        USART_BAUD(USART0) = ((USART_BAUD_FRADIV | USART_BAUD_INTDIV) & (intdiv | fradiv));
    } else {
        /* when oversampling by 16, configure the value of USART_BAUD */
        udiv = (uclk + 115200 / 2U) / 115200;
        intdiv = udiv & 0xfff0U;
        fradiv = udiv & 0xfU;
        USART_BAUD(USART0) = ((USART_BAUD_FRADIV | USART_BAUD_INTDIV) & (intdiv | fradiv));
    }

    USART_CTL0(USART0) &= ~(0x01u << 10);
    USART_CTL0(USART0) &= ~(0x01u << 12);

    USART_CTL1(USART0) &= ~(0x03u << 12);

    USART_CTL0(USART0) |= (0x01u << 3);
    USART_CTL0(USART0) |= (0x01u << 13);


    mini_printf("\r\nuart init ok.\r\n");
    mini_printf("CLK info\r\n");
    mini_printf("sys rate %d\r\n",rcu_clock_freq_get(CK_SYS));
    mini_printf("AHB rate %d\r\n",rcu_clock_freq_get(CK_AHB));
    mini_printf("APB1 rate %d\r\n",rcu_clock_freq_get(CK_APB1));
    mini_printf("APB2 rate %d\r\n",rcu_clock_freq_get(CK_APB2));

    if(argc > 0)
        mini_printf("Argc %d\r\n",argc);
    for(temp = 0;temp < argc;temp++)
        mini_printf("Argv[%d] = %s %p\r\n",temp,argv[temp],&argv[temp]);
    
    if(memdump)
    {
        trace_byte_stream((uint8_t *)0x20000000,0x18000,0); 
    }

#endif

    FMC_WS = 0x00000000;
    temp = FMC_CTL;
    temp &= ~(0x3u << 8);
    temp |= (parallelism << 8);
    FMC_CTL = temp;

    return 0;
}

添加参数的解析处理,同时在flash write 的时候根据配置的参数大小进行写入处理。

uint32_t FlashWrite(void *block_start,
                    uint32_t offset_into_block,
                    uint32_t count,
                    char const *buffer)
{
    uint8_t * dst = (uint8_t *)((unsigned char *)block_start + offset_into_block);
    uint8_t * src = (uint8_t *)buffer;

    mini_printf("[FlashWrite] flash write dst %p %d %d.\r\n",dst,offset_into_block,count);

    FMC_CTL |= 0x01u;
    FMC_STAT = 0x1d2;

    for ( ; count; count -= 8)
    {

        switch (parallelism)
        {
        case 0:
            while (FMC_STAT & (0x01u<<16));
            *dst++ = *src++;
            while (FMC_STAT & (0x01u<<16));
            *dst++ = *src++;
            while (FMC_STAT & (0x01u<<16));
            *dst++ = *src++;
            while (FMC_STAT & (0x01u<<16));
            *dst++ = *src++;
            while (FMC_STAT & (0x01u<<16));
            *dst++ = *src++;
            while (FMC_STAT & (0x01u<<16));
            *dst++ = *src++;
            while (FMC_STAT & (0x01u<<16));
            *dst++ = *src++;
            while (FMC_STAT & (0x01u<<16));
            *dst++ = *src++;
            break;
        case 1:
            while (FMC_STAT & (0x01u<<16));
            *((uint16_t *)dst) = *((uint16_t *)src);
            src += 2;
            dst += 2;
            while (FMC_STAT & (0x01u<<16));
            *((uint16_t *)dst) = *((uint16_t *)src);
            src += 2;
            dst += 2;
            while (FMC_STAT & (0x01u<<16));
            *((uint16_t *)dst) = *((uint16_t *)src);
            src += 2;
            dst += 2;
            while (FMC_STAT & (0x01u<<16));
            *((uint16_t *)dst) = *((uint16_t *)src);
            src += 2;
            dst += 2;
            break;

        case 2:
            while (FMC_STAT & (0x01u<<16));
            *((uint32_t *)dst) = *((uint32_t *)src);
            src += 4;
            dst += 4;
            while (FMC_STAT & (0x01u<<16));
            *((uint32_t *)dst) = *((uint32_t *)src);
            src += 4;
            dst += 4;
            break;

        default:
            while (FMC_STAT & (0x01u<<16));
            *((uint64_t *)dst) = *((uint64_t *)src);
            src += 8;
            dst += 8;
            break;
    }
  }

    while (FMC_STAT & (0x01u<<16));
    FMC_CTL &= ~0x01;

    if(FMC_STAT & 0x1d2)
        return 1;

    return 0;
}

使用新修改的flash loader 程序运行时可以将传入的参数进行打印,打印发现跟预期的一致 --x32  --dumpram  参数C-SPY 已经正确传递给flashloader  下载算法,并且也将内存数据dump 至串口。

image.png   

Flash loader 调试信息解析

在IAR 的工程目录下创建flash0.trace 文件,C-SPY 会把flashloader 的下载过程log 写入到flash0.trace中。

image.png

创建后生成的log文件如下,从中获取flashlloader 的信息及下载过程。

661.477: File generated Wed Feb 19 18:42:32 2025

  0.000: Pass 1 of 1
  0.000: Starting fragment-style flashloader pass.
  0.000: Device: E:\gd32_gitee\gd32f427v_start\GD32F4xx_Demo_Suites_V2.6.1\GD32427V_START_Demo_Suites\Projects\02_GPIO_Key_Polling_mode\EWARM\flashloader\FlashGD32F4xxxK.flash
  0.000: Flash loader: E:\gd32_gitee\gd32f427v_start\GD32F4xx_Demo_Suites_V2.6.1\GD32427V_START_Demo_Suites\Projects\02_GPIO_Key_Polling_mode\EWARM/flashloader/FlashGd32f4xx.out
  2.391: FlashInitEntry is at 0x2000'0f0c
  2.391: FlashWriteEntry is at 0x2000'0f14
  2.391: FlashEraseWriteEntry is at 0x2000'0f1c
  2.391: FlashBreak is at 0x2000'0ef2
  2.391: FlashBufferStart is at 0x2000'1000
  2.391: FlashBufferEnd is at 0x2001'6f90
  2.391: theFlashParams is at 0x2001'6f94
  2.391: FlashPreInitEntry not found
  2.391: FlashChecksumEntry not found
  2.391: FlashSignoffEntry not found
  2.391: page size is 4 (0x4)
  2.391: filler is 0xff
  2.391: buffer size is 90000 (0x1'5f90)
  2.391: Base of flash at 0x800'0000
  2.391: SimpleCode records (after offset):
  2.391:   Record 0: @ 0x800'0000 [81172 (0x1'3d14) bytes] 0x800'0000 - 0x801'3d13 [a0 7e 01 20 ... ]
  2.391:   Record 1: @ 0x801'3d14 [443112 (0x6'c2e8) bytes] 0x801'3d14 - 0x807'fffb [ff ff ff ff ... ]
  2.391:   Record 2: @ 0x807'fffc [4 (0x4) bytes] 0x807'fffc - 0x807'ffff [58 3d ae 4b ]
  2.391: ->init       : base @ 0x800'0000, image size 0x8'0000
  2.422:       Args: (argc = 2)
  2.422:           --x32
  2.422:           --dumpram
  2.422: Store TargetParams to 0x2001'6f94
  2.428: Setting PC to 0x2000'0f0c (FlashInitEntry)
 47.216:   timing(init): 0.8125 (CPU) 44.7780 (elapsed)
 47.216: Load TargetParams from 0x2001'6f94
 47.222: Transaction list:
 47.222:   Transaction 0: @ 0x800'0000 + 0x0 (0x1'0000=65536 bytes) 4 packet(s).
 47.222:     Will erase 4 block(s):
 47.222:       0: 0x800'0000 (0x4000 bytes)
 47.222:       1: 0x800'4000 (0x4000 bytes)
 47.222:       2: 0x800'8000 (0x4000 bytes)
 47.222:       3: 0x800'c000 (0x4000 bytes)
 47.222:   Transaction 1: @ 0x801'0000 + 0x0 (0x1'0000=65536 bytes) 1 packet(s).
 47.222:     Will erase 1 block(s):
 47.222:       0: 0x801'0000 (0x1'0000 bytes)
 47.222:   Transaction 2: @ 0x802'0000 + 0x0 (0x1'5f90=90000 bytes) 1 packet(s).
 47.222:     Will erase 1 block(s):
 47.222:       0: 0x802'0000 (0x2'0000 bytes)
 47.222:   Transaction 3: @ 0x802'0000 + 0x1'5f90 (0xa070=41072 bytes) 1 packet(s).
 47.222:   Transaction 4: @ 0x804'0000 + 0x0 (0x1'5f90=90000 bytes) 1 packet(s).
 47.222:     Will erase 1 block(s):
 47.222:       0: 0x804'0000 (0x2'0000 bytes)
 47.222:   Transaction 5: @ 0x804'0000 + 0x1'5f90 (0xa070=41072 bytes) 1 packet(s).
 47.222:   Transaction 6: @ 0x806'0000 + 0x0 (0x1'5f90=90000 bytes) 1 packet(s).
 47.222:     Will erase 1 block(s):
 47.222:       0: 0x806'0000 (0x2'0000 bytes)
 47.222:   Transaction 7: @ 0x806'0000 + 0x1'5f90 (0xa070=41072 bytes) 1 packet(s).
 47.226: ->multi_erase: 4 blocks (0x20 bytes in buffer) [00 00 00 08 ... ]
 47.233: Store TargetParams to 0x2001'6f94
 47.239: Setting PC to 0x2000'0f1c (FlashEraseWriteEntry)
 47.796:   timing(erase): 0.0312 (CPU) 0.5470 (elapsed)
 47.796: Load TargetParams from 0x2001'6f94
 47.802: ->write      : @ 0x800'0000 (0x1'0000 bytes, offset 0x0 into block @ 0x800'0000) [a0 7e 01 20 ... ]
 47.802: Writing 0x1'0000 bytes to FlashBuffer @ 0x2000'1000
 49.342: Store TargetParams to 0x2001'6f94
 49.348: Setting PC to 0x2000'0f14 (FlashWriteEntry)
 50.276:   timing(write): 0.0625 (CPU) 0.9180 (elapsed)
 50.276: Load TargetParams from 0x2001'6f94
 50.282: ->multi_erase: 1 blocks (0x8 bytes in buffer) [00 00 01 08 ... ]
 50.288: Store TargetParams to 0x2001'6f94
 50.294: Setting PC to 0x2000'0f1c (FlashEraseWriteEntry)
 50.519:   timing(erase): 0.0000 (CPU) 0.2150 (elapsed)
 50.519: Load TargetParams from 0x2001'6f94
 50.525: ->write      : @ 0x801'0000 (0x1'0000 bytes, offset 0x0 into block @ 0x801'0000) [ff f7 fe bf ... ]
 50.525: Writing 0x1'0000 bytes to FlashBuffer @ 0x2000'1000
 52.065: Store TargetParams to 0x2001'6f94
 52.071: Setting PC to 0x2000'0f14 (FlashWriteEntry)
 52.821:   timing(write): 0.0000 (CPU) 0.7390 (elapsed)
 52.821: Load TargetParams from 0x2001'6f94
 52.827: ->multi_erase: 1 blocks (0x8 bytes in buffer) [00 00 02 08 ... ]
 52.833: Store TargetParams to 0x2001'6f94
 52.839: Setting PC to 0x2000'0f1c (FlashEraseWriteEntry)
 53.013:   timing(erase): 0.0156 (CPU) 0.1640 (elapsed)
 53.013: Load TargetParams from 0x2001'6f94
 53.019: ->write      : @ 0x802'0000 (0x1'5f90 bytes, offset 0x0 into block @ 0x802'0000) [ff ff ff ff ... ]
 53.019: Writing 0x1'5f90 bytes to FlashBuffer @ 0x2000'1000
 55.136: Store TargetParams to 0x2001'6f94
 55.142: Setting PC to 0x2000'0f14 (FlashWriteEntry)
 56.070:   timing(write): 0.0625 (CPU) 0.9180 (elapsed)
 56.070: Load TargetParams from 0x2001'6f94
 56.076: ->write      : @ 0x803'5f90 (0xa070 bytes, offset 0x1'5f90 into block @ 0x802'0000) [ff ff ff ff ... ]
 56.076: Writing 0xa070 bytes to FlashBuffer @ 0x2000'1000
 57.048: Store TargetParams to 0x2001'6f94
 57.055: Setting PC to 0x2000'0f14 (FlashWriteEntry)
 57.537:   timing(write): 0.0156 (CPU) 0.4720 (elapsed)
 57.537: Load TargetParams from 0x2001'6f94
 57.543: ->multi_erase: 1 blocks (0x8 bytes in buffer) [00 00 04 08 ... ]
 57.549: Store TargetParams to 0x2001'6f94
 57.555: Setting PC to 0x2000'0f1c (FlashEraseWriteEntry)
 57.728:   timing(erase): 0.0000 (CPU) 0.1630 (elapsed)
 57.728: Load TargetParams from 0x2001'6f94
 57.734: ->write      : @ 0x804'0000 (0x1'5f90 bytes, offset 0x0 into block @ 0x804'0000) [ff ff ff ff ... ]
 57.734: Writing 0x1'5f90 bytes to FlashBuffer @ 0x2000'1000
 59.853: Store TargetParams to 0x2001'6f94
 59.859: Setting PC to 0x2000'0f14 (FlashWriteEntry)
 60.788:   timing(write): 0.0625 (CPU) 0.9190 (elapsed)
 60.788: Load TargetParams from 0x2001'6f94
 60.794: ->write      : @ 0x805'5f90 (0xa070 bytes, offset 0x1'5f90 into block @ 0x804'0000) [ff ff ff ff ... ]
 60.794: Writing 0xa070 bytes to FlashBuffer @ 0x2000'1000
 61.762: Store TargetParams to 0x2001'6f94
 61.768: Setting PC to 0x2000'0f14 (FlashWriteEntry)
 62.250:   timing(write): 0.0312 (CPU) 0.4720 (elapsed)
 62.250: Load TargetParams from 0x2001'6f94
 62.256: ->multi_erase: 1 blocks (0x8 bytes in buffer) [00 00 06 08 ... ]
 62.262: Store TargetParams to 0x2001'6f94
 62.268: Setting PC to 0x2000'0f1c (FlashEraseWriteEntry)
 62.525:   timing(erase): 0.0156 (CPU) 0.2470 (elapsed)
 62.525: Load TargetParams from 0x2001'6f94
 62.531: ->write      : @ 0x806'0000 (0x1'5f90 bytes, offset 0x0 into block @ 0x806'0000) [ff ff ff ff ... ]
 62.531: Writing 0x1'5f90 bytes to FlashBuffer @ 0x2000'1000
 64.645: Store TargetParams to 0x2001'6f94
 64.651: Setting PC to 0x2000'0f14 (FlashWriteEntry)
 65.580:   timing(write): 0.0312 (CPU) 0.9190 (elapsed)
 65.580: Load TargetParams from 0x2001'6f94
 65.586: ->write      : @ 0x807'5f90 (0xa070 bytes, offset 0x1'5f90 into block @ 0x806'0000) [ff ff ff ff ... ]
 65.586: Writing 0xa070 bytes to FlashBuffer @ 0x2000'1000
 66.554: Store TargetParams to 0x2001'6f94
 66.560: Setting PC to 0x2000'0f14 (FlashWriteEntry)
 67.041:   timing(write): 0.0312 (CPU) 0.4710 (elapsed)
 67.041: Load TargetParams from 0x2001'6f94
 67.095: Duration:   1.83 (CPU)  67.10 (elapsed)
 67.095:   of which on target: 1.1719 (CPU) 51.9420 (elapsed)
 67.095: Flash loading pass finished

image.png

从这段log 也可以看出在调用flashinit 前C-SPY 将参数先写入到0x20016f94 这个地址,然后设置PC指针到flashinit 函数处执行初始化处理,前面我们已经dump 了内存的数据,我们去查看对应的内存地址发现该地址的数据和传递的参数信息,从地址上看并不是完全匹配值。

image.png

查看IAR 的手册发现0x20016f94  存放的是参事结构体,加上这个结构的大小后地址就是吻合的0x20016f94   + 0x14(sizeof(FlashParamsHolder)) = 0x20016fa8 就合上述内存的数据匹配上了。
image.png  

此处的用法相当于边长的结构体,将固定长度的固定在前面,后面跟上argc argv的字符串来获取参数信息,这些不需要我么来解析,传递到flashinit 函数的时候我们只需要根据参数来处理即可,不需要做额外的特殊处理。 




专家
2025-02-19 20:05:02     打赏
2楼

感谢分享


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]