0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于 IAR Embedded Workbench 的自研 MCU 芯片软件函数与变量内存布局优化精控方法

安芯 ? 来源:jf_29981791 ? 作者:jf_29981791 ? 2025-04-30 16:38 ? 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

嵌入式软件开发领域,MCU芯片软件的架构设计与内存布局的精细规划对系统性能和稳定性起着关键作用。本文档聚焦于IAR Embedded Workbench环境下,为自研MCU芯片软件提供了一套详尽的函数和变量指定section放置方法与操作流程,兼具过程记录与详细说明,旨在打造一份实用的参考指南,助力开发者精准掌控程序的内存分布与执行逻辑。文档涵盖从默认section表的介绍,到多种放置手段的阐释,以及实际配置示例的展示,为后续的开发工作奠定坚实基础。

IAR Embedded Workbench作为一款广受认可的嵌入式开发工具,具备丰富的功能与灵活的配置选项。在该环境下,软件开发者可巧妙运用多种方法,将函数和变量精准放置于指定的section中。这一操作对于优化程序的内存使用效率、提升系统响应速度以及增强代码的可维护性具有重要意义。例如,通过将特定的代码或数据放置在合适的内存区域,可以充分利用MCU芯片的硬件特性,实现更高效的缓存利用、减少内存访问延迟等效果。

文档深入浅出地讲解了多种放置方式,包括使用@操作符、#pragma location命令、GCC风格的attribute属性以及#pragma default_variable_attributes和#pragma default_function_attributes命令等,开发者可根据实际需求灵活选择。同时,还提供了诸如as32x601_rom.icf、Port_MemMap.h和Port.c等实际配置示例,涵盖了从内存区域定义、section分配到函数与变量属性设置的完整流程,为开发者提供了直观且易于实践的参考。

默认section表

IAR Embedded Workbench中有很多默认的section用于放置对应的变量和函数:

除了用于您的应用程序的ELF部分之外,这些工具还出于多种目的使用许多其他ELF段:

  • 以.debug开头的段通常包含DWARF格式的调试信息。
  • 以.iar.debug开头的段包含IAR格式的补充调试信息
  • 以.comment开头的段包含用于构建文件的工具和命令行
  • 以.rel或.rela开头的段包含ELF重定位信息
  • 以.symtab开头的段包含文件的符号表
  • 以.strtab开头的段包含符号表中符号的名称
  • 以.shstrtab开头的段包含各段的名称。

将变量放到指定的section

使用@操作符

可以使用 @ 将变量放到指定的section:

staticuint32_t TaskCounter @".mcal_const_cfg" = 1;

使用 #pragma location 命令

可以使用 #pragma location命令将变量放到指定的section:

#pragma location = ".mcal_const_cfg"staticuint32_t TaskCounter = 1;

使用 GCC 风格的属性 attribute ((section ))

可以使用 GCC 风格的属性 attribute ((section ))将变量放到指定的section:

staticuint32_t TaskCounter attribute ((section (".mcal_const_cfg"))) = 1;

使用 #pragma default_variable_attributes 命令

上面的方法可以将单个变量放到指定的section,如果需要将多个变量放到指定的section,上面的方法会显得有点繁琐。可以使用 #pragma default_variable_attributes 命令将多个变量放到指定的section:

#pragma default_variable_attributes = @ ".mcal_const_cfg"staticuint32_t TaskCounter = 1; staticuint32_t TaskLedRedCounter = 2; #pragma default_variable_attributes =

将函数放到指定的section

使用@操作符

可以使用 @ 将函数放到指定的section:

voidStartTaskLedRed(void *argument) @ ".mcal_text";

使用 #pragma location 命令

可以使用 #pragma location命令将函数放到指定的section:

#pragma location = ".mcal_text"voidStartTaskLedRed(void *argument);

使用 GCC 风格的属性 attribute ((section ))

可以使用 GCC 风格的属性 attribute ((section ))将函数放到指定的section:

voidStartTaskLedRed(void *argument) attribute ((section (".mcal_text")));

使用 #pragma default_variable_attributes 命令

上面的方法可以将单个函数放到指定的section,如果需要将多个函数放到指定的section,上面的方法会显得有点繁琐。可以使用 #pragma default_function_attributes命令将多个函数放到指定的section:

#pragma default_function_attributes = @ ".mcal_text"voidStartTaskLedRed(void *argument); voidStartTaskLedGreen(void *argument); voidStartTaskLedBlue(void *argument); #pragma default_function_attributes =

使用示例

as32x601_rom.icf

/****************************************************************************** * FILE VERSION / define exported symbol _link_file_version_2 = 1; / * SPECIALS // * * MEMORY REGIONS / define symbol ICFEDIT_region_FLASH_start = 0x10000000; define symbol ICFEDIT_region_FLASH_end = 0x11FFFFFF; define symbol ICFEDIT_region_SRAM0_start = 0x20000000; define symbol ICFEDIT_region_SRAM0_end = 0x2001FFFF; define symbol ICFEDIT_region_SRAM1_start = 0x20020000; define symbol ICFEDIT_region_SRAM1_end = 0x2003FFFF; define symbol ICFEDIT_region_SRAM2_start = 0x20040000; define symbol ICFEDIT_region_SRAM2_end = 0x2005FFFF; define symbol ICFEDIT_region_SRAM3_start = 0x20060000; define symbol ICFEDIT_region_SRAM3_end = 0x2007FFFF; / * * SIZES / define symbol ICFEDIT_size_cstack = 0x2000; define symbol ICFEDIT_size_proc_stack = 0x0; define symbol ICFEDIT_size_heap = 0x2000; / * * BUILD FOR ROM *****************************************************************************/ keep symbol __iar_cstart_init_gp; define memory mem with size = 4G; define region ROM_region = mem:[from ICFEDIT_region_FLASH_start to ICFEDIT_region_FLASH_end ]; define region RAMCODE_region = mem:[from ICFEDIT_region_SRAM0_start to ICFEDIT_region_SRAM0_end ]; define region RAM_region = mem:[from ICFEDIT_region_SRAM1_start to ICFEDIT_region_SRAM1_end ] | mem:[from ICFEDIT_region_SRAM2_start to ICFEDIT_region_SRAM2_end ]; initialize by copy { readwrite }; do not initialize { section .noinit }; define block CSTACK with alignment = 16, size = CSTACK_SIZE { }; define block HEAP with alignment = 16, size = HEAP_SIZE { }; define block RW_DATA { rw section .data}; define block RW_DATA_INIT { ro section .data_init}; define block RW_BSS {rw section .bss}; define block RW_DATA_ALL with static base GPREL { block RW_DATA, block RW_BSS }; "STARTUP" : place at start of ROM_region { readonly section .init }; place in ROM_region { readonly, block RW_DATA_INIT }; place in ROM_region { readonly section .text, section .mcal_text, section .access_code_rom}; place in ROM_region { readonly section .rodata, section .mcal_const_cfg, section .mcal_const, section .mcal_const_no_cacheable}; place in RAMCODE_region { readwrite section .text, section .ramcode, block RW_DATA_ALL }; place in RAM_region { readwrite, block CSTACK, block HEAP }; place in RAM_region { section .mcal_data, section .dma_dest_buffer, section .mcal_shared_data }; place in RAM_region { section .mcal_bss, section .mcal_bss_no_cacheable, section .dma_dest_buffer_bss, section .mcal_shared_bss };

第13、14行:定义FLASH,起始地址和结束地址。 第41行:定义了ROM_region区域,起始地址和结束地址。 第63行:定义一个名为 ROM_region 的内存区域,并将三个只读代码段 .text、.mcal_text 和 .access_code_rom 放置在这个区域内。。

Port_MemMap.h

#define MEMMAP_MISSMATCH_CHECKER#if defined (_IAR_C_AS32x601_)#ifdef PORT_START_SEC_CODE#undef PORT_START_SEC_CODE#undef MEMMAP_MISSMATCH_CHECKER#pragma default_function_attributes = @ ".mcal_text"#endif#ifdef PORT_STOP_SEC_CODE#undef PORT_STOP_SEC_CODE#undef MEMMAP_MISSMATCH_CHECKER#pragma default_function_attributes =#endif#endif#ifdef MEMMAP_MISSMATCH_CHECKER#error"MemMap.h, No valid section define found."#endif

第1行:定义了一个宏 MEMMAP_MISSMATCH_CHECKER,用于检查包含的正确的符号。 第3行:定义了一个ifdef,当定义了 IAR_C_AS32x601 时,会执行下面的代码。 第5行:定义了一个ifdef,当定义了 PORT_START_SEC_CODE 时,会执行下面的代码。 第11行:定义了一个ifdef,当定义了 PORT_STOP_SEC_CODE 时,会执行下面的代码。 第19行:定义了一个ifdef,当定义了 MEMMAP_MISSMATCH_CHECKER 时,说明输入定义错误,将会抛出一个错误。

Port.c

#define PORT_START_SEC_CODE#include"Port_MemMap.h" FUNC(void, PORT_CODE) Port_Init(P2CONST(Port_ConfigType, AUTOMATIC, PORT_APPL_CONST) ConfigPtr) { #if (PORT_ENABLE_DEV_ERROR_DETECT == STD_ON)/* When PostBuild is used and #(Variants) > 1, the input parameter 'ConfigPtr' is mandatory to be different than NULL_PTR. * In case of error, return immediately and report DET errors. */#if (PORT_PRECOMPILE_SUPPORT == STD_ON)if (NULL_PTR != ConfigPtr) { #elseif (NULL_PTR == ConfigPtr) { #endif/* (PORT_PRECOMPILE_SUPPORT == STD_ON) *//* If development error detection for the Port module is enabled: * The function shall raise the error PORT_E_INIT_FAILED if the parameter ConfigPtr is Null Pointer.*/ (void)Det_ReportError((uint16)PORT_MODULE_ID, PORT_INSTANCE_ID, PORT_INIT_ID, PORT_E_INIT_FAILED); } else { #endif/* (PORT_ENABLE_DEV_ERROR_DETECT == STD_ON) */#if (PORT_PRECOMPILE_SUPPORT == STD_ON) l_PortConfig_ptr = &Port_PreCompileConfig_st; /* Avoid compiler warning */ (void)ConfigPtr; #else/* (PORT_PRECOMPILE_SUPPORT == STD_OFF) */ l_PortConfig_ptr = ConfigPtr; #endif/* (PORT_PRECOMPILE_SUPPORT == STD_ON) *//* Initializes the Port driver with the given configuration */ Port_LLDriver_Init(l_PortConfig_ptr); #if (PORT_ENABLE_DEV_ERROR_DETECT == STD_ON) } #endif/* (PORT_ENABLE_DEV_ERROR_DETECT == STD_ON) */ } #define PORT_STOP_SEC_CODE#include"Port_MemMap.h"

第1行:定义了一个宏 PORT_START_SEC_CODE,将会执行#pragma default_function_attributes = @ ".mcal_text",会将函数放置在.mcal_text区域。 第32行:定义了一个宏 PORT_STOP_SEC_CODE,会结束函数的默认属性设置。

效果示例

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • mcu
    mcu
    +关注

    关注

    146

    文章

    18035

    浏览量

    369490
  • IAR
    IAR
    +关注

    关注

    5

    文章

    383

    浏览量

    37605
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    Arm CEO:公司正在芯片

    据外媒路透社报道,Arm CEO Rene Haas透露,Arm正在投资开发自有芯片,并计划将部分利润投资于制造自己的芯片和其他组件。与之对应的是Arm预测的下一财季经营业绩也会因为
    的头像 发表于 07-31 11:49 ?148次阅读

    「芯生态」杰发科技AC7870携手IAR开发工具链,助推汽车电子全栈全域智能化落地

    IAR Embedded Workbench for Arm已全面支持杰发科技AutoChips车规级MCU AC7870,为其提供涵盖开发、调试、
    的头像 发表于 07-22 12:06 ?205次阅读
    「芯生态」杰发科技AC7870携手<b class='flag-5'>IAR</b>开发工具链,助推汽车电子全栈全域智能化落地

    MCU芯片闪存驱动的实现:OpenOCD详细过程记录与操作指南

    功能强大的开源调试工具,广泛应用于嵌入式系统开发中,为系统调试与程序烧录提供了重要支持。 随着MCU芯片项目的不断推进,如何实现其与OpenOCD的无缝对接成为关键问题之一。而闪存
    的头像 发表于 05-08 10:51 ?1188次阅读
    <b class='flag-5'>自</b><b class='flag-5'>研</b><b class='flag-5'>MCU</b><b class='flag-5'>芯片</b>闪存驱动的实现:OpenOCD详细过程记录与操作指南

    IAR全面支持芯驰科技车规MCU芯片E3650

    2025年4月22日,全场景智能车芯引领者芯驰科技与全球嵌入式软件开发解决方案领导者IAR正式宣布,IAR Embedded Workbench
    的头像 发表于 04-23 15:45 ?802次阅读

    如何将项目从IAR迁移到Embedded Studio

    本文描述如何将IAR EWARM项目迁移到SEGGER Embedded Studio(简称SES)中。
    的头像 发表于 02-25 17:11 ?657次阅读
    如何将项目从<b class='flag-5'>IAR</b>迁移到<b class='flag-5'>Embedded</b> Studio

    传DeepSeek芯片,厂商们要把AI成本打下来

    电子发烧友网报道(文/黄晶晶)日前业界消息称,DeepSeek正广泛招募芯片设计人才,加速芯片布局,其
    的头像 发表于 02-16 00:09 ?3255次阅读
    传DeepSeek<b class='flag-5'>自</b><b class='flag-5'>研</b><b class='flag-5'>芯片</b>,厂商们要把AI成本打下来

    IAR与紫光同芯合作,全面支持THA6系列汽车芯片

    近日,全球领先的嵌入式系统开发软件解决方案提供商IAR与业内知名的芯片及解决方案提供商紫光同芯携手宣布,最新版本的IAR Embedded
    的头像 发表于 12-27 11:46 ?1344次阅读

    苹果计划2025年起采用蓝牙Wi-Fi芯片

    近日,据最新报道,苹果公司为了减少对博通(Broadcom)的依赖,并进一步提升其设备的性能和能效,已经制定了一项重要的芯片计划。据悉,从2025年开始,苹果将正式启用
    的头像 发表于 12-18 14:22 ?1109次阅读

    IAR Systems最新版开发环境全面赋能芯海科技32位MCU芯片

    随着IAR Embedded Workbench for Arm 9.32版本对芯海科技MCU系列的全面支持,双方将携手为开发者提供更加高效、便捷的开发体验,共同推动物联网、工业控制、
    的头像 发表于 11-14 14:47 ?1005次阅读
    <b class='flag-5'>IAR</b> Systems最新版开发环境全面赋能芯海科技32位<b class='flag-5'>MCU</b><b class='flag-5'>芯片</b>

    苹果5G芯片或于明年亮相

    苹果公司正加速推进其5G芯片的研发进程,有望最快在明年推出首款5G调制解调器。这一举措对高通而言,无疑构成了巨大的挑战。
    的头像 发表于 11-12 15:24 ?1060次阅读

    IAR支持旗芯微车规级MCU,助力汽车行业智能化发展

    在全球汽车电子产业迅猛发展的背景下,IAR与苏州旗芯微半导体有限公司(简称“旗芯微”)携手宣布了一项重大合作成果:IAR Embedded Workbench for Arm 9.60
    的头像 发表于 10-23 11:09 ?1323次阅读

    比亚迪最快于11月实现算法量产,推进智驾芯片进程

    10月21日市场传出消息,比亚迪正计划整合其新技术院下的智能驾驶团队,目标是在今年11月实现智能驾驶算法的量产,并持续推进智能驾驶芯片
    的头像 发表于 10-22 15:57 ?1519次阅读

    小鹏智驾芯片:面向L4+AI大模型,集成40核+NPU+ISP

    电子发烧友网报道(文/梁浩斌)新能源汽车时代,车企芯片的路线,尽管目的各不相同,但已经成为新势力车企的共识。最早从比亚迪为了供应链自主化而
    的头像 发表于 09-06 00:17 ?1.1w次阅读
    小鹏<b class='flag-5'>自</b><b class='flag-5'>研</b>智驾<b class='flag-5'>芯片</b>:面向L4+AI大模型,集成40核+NPU+ISP

    【GD32 MCU 入门教程】一、GD32 MCU 开发环境搭建(3)使用 Embedded Builder 开发 GD32

    GD32系列为通用型MCU,所以开发环境也可以使用通用型的IDE,目前使用较多的是KEIL、IAR、 GCC和Embedded Builder,客户可以根据个人喜好来选择相应的开发环境。
    的头像 发表于 08-08 16:03 ?2936次阅读
    【GD32 <b class='flag-5'>MCU</b> 入门教程】一、GD32 <b class='flag-5'>MCU</b> 开发环境搭建(3)使用 <b class='flag-5'>Embedded</b> Builder 开发 GD32

    【GD32 MCU 入门教程】一、GD32 MCU 开发环境搭建(2)使用 IAR 开发 GD32

    GD32系列为通用型MCU,所以开发环境也可以使用通用型的IDE,目前使用较多的是KEIL、IAR、 GCC和Embedded Builder,客户可以根据个人喜好来选择相应的开发环境。
    的头像 发表于 08-08 15:40 ?1565次阅读
    【GD32 <b class='flag-5'>MCU</b> 入门教程】一、GD32 <b class='flag-5'>MCU</b> 开发环境搭建(2)使用 <b class='flag-5'>IAR</b> 开发 GD32