解决gcc编译链接含weak函数的库文件出现的一些BUG_2019/03/13

2023-11-13

项目介绍

本项目包含IAP程序与APP程序。APP程序有部分共用代码(包括main\stm32标准库\RTOS\BSP)都编译进库中。另外部分特殊代码由其它程序生成后,连接共用代码库生成目标bin文件,通过IAP下载至FLASH中。

问题描述

1 使用keil编译生成的IAP程序
相同的APP代码,在keil工程中编译下载后可以正常执行(没有生成库,直接编译链接所有代码)。但是使用arm_none_eabi_gcc交叉编译工具链编译链接(先编译一部分代码生成库,再编译其它代码并与库链接生成目标bin文件。)则不能正常执行。
2 不使用IAP模式,直接编译APP程序
keil下仍一切正常,使用arm_none_eabi_gcc仍不正常。

开发环境

arm_none_eabi_gcc交叉编译工具链
自已开发的IAP下载工具
自己开发的图形化编译工具
自己开发的库文件生成工具

目标硬件

国霖电子生产的GPL-14MT工控板,板载stm32f103rbt6。

使用到的软件

STM32 ST-LINK Utility
keil rvmdk

使用到的调试工具

ST-Link V2

查阅的文档

《Cortex-M3权威指南》
《stm32用户手册》
《stm32f103RBT6芯片手册》

解决过程

1 确认一遍IAP工作要点(后方会提到,虽然做了这一步骤,但终究漏掉了一个致命问题点。)

修改中断向量表地址

   NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x6000);  // NVIC_VectTab_FLASH=0x08000000   

ld文件中设置FLASH基地址及长度

/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x20005000;    /* end of 20K RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200;      /* required amount of heap  */
_Min_Stack_Size = 0x800; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
  FLASH (rx)      : ORIGIN = 0x08006000, LENGTH = 104K
  RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 20K
  MEMORY_B1 (rx)  : ORIGIN = 0x60000000, LENGTH = 0K
}

2 排除IAP程序的错误

使用KEIL编译相同的代码,同样的IAP程序,跳转后却能正确执行,故可以认为IAP程序工作正常。(这个结果对我产生了误导,后文会提及)

3 怀疑是编译选项不正确

反复排查尝试了很多次,但是得到的是各种诡异的结果。在初始化IO口后立刻控制LED灯闪烁,程序工作正常。如果通过串口输出调试信息编码,有时候不能输出,有时候能正确输出,但输出几个就没有了。什么鬼?同样的APP程序使用keil编译出来明明工作正常的,但是使用gcc编出来,看上去程序执行了,证明IAP程序是正确的,为何功能代码却执行不成功?明明是非常简单的几乎不可能出错的代码呀,如果这都能写错,简直是对我这个资深老鸟的侮辱!是可忍孰不可忍!

4 不能忍还是要忍

做了无数个深呼吸,终于能够压抑住暴躁的内心,重新来审视代码。看上去编译选项应该没错,因为毕竟部分代码已经执行成功了,证明编译连接都没问题。我不得不怀疑是不是很久没写STM32的代码,能力退化,导致犯了什么低级错误。于是退出IAP状态,将APP改成正常的工作模式,连接文件也做了修改。使用ST-Link烧录下去,自然,仍然是不能正常工作。
这两步费时最多,整整折腾了一个白天两个晚上(周六晚上、周日全天、周一晚上),死盯着电脑,熬到很晚,人处于懵逼沮丧崩溃状态。

5 大受打击,暂时收手

(周二晚上没干活,早早睡觉)

6 养精蓄锐,卷土重来

周三项目正好交接,事情比较少,心情比较好,加上前一天休息比较好,晚上下班状态可以,继续奋斗!折腾了一会,想到STM32 ST-Link Utility可以查看寄存器状态,于是调出来看了一眼,马上看出点问题来了:
在这里插入图片描述
IPSR = 0x2c?
IPSR保存的是中断表项的地址偏移量,0x2c对应SVC中断。系统服务调用中断?我明明没有启动SVC中断,为什么会进这个中断?一定有问题!进了这个中断一定会执行SVC_Handler函数,既然我没有定义SVC_Handler函数,那么APP程序就是死在默认的中断处理函数的死循环里了!终于能够解释为何程序死机了!为了验证这点,我在stm32f10x_it.c中增加了一个SVC_Handler(),什么也不做,只让LED灯不断闪烁(之前调试LED灯是正常的)。执行后发现,居然什么都没发生,现象没变!这就更诡异了。为何?我查看了一下map文件(其实查看一下STM32 ST-Link Utility中的target memory也能发现,中断向量表中对应的几个地址值都是一样的),发现SVC、HardFault、 BusFault等异常的处理函数的入口地址都是一样的,但是我明明在stm32f10x_it.c中有定义相应的异常处理函数,为何没有链接到APP程序中?
到了这一步,问题已经显而易见了,我写的中断处理函数没有链接到程序中,导致中断处理不正常。暂时将startup_stm32f10x_md.s中几个weak标记的中断处理函数全部注释掉,重新编译,果然中断向量表看上去正常了,执行无IAP的程序,正常运行!

8 最终胜利

重新下载IAP程序,进入IAP模式,相应修改APP,通过IAP下载到FLASH,执行,仍然不正常。但是排除了上面几个问题后,信心大增,斗志昂扬,已经预感胜利近在眼前了。这种状态下思路特别清晰,仔细回想梳理一下整个过程,猛然想到,虽然明明知道IAP跳转前应该关闭所有中断,但是我偏偏忘记了关闭SysTick中断!这个中断1ms触发一次,必然会出问题。马上关闭它,在跳转前添加一句:

SysTick->CTRL  &= ~SysTick_CTRL_ENABLE_Msk;                    /* Disable  SysTick Timer */

编译下载,然后再通过IAP下载一次APP程序,开关切换,跳转!果然,期待已久的灯亮起来了,程序运行成功!

最终定位问题点汇总

1 编译生成库时没有把stm32f10x_it.c中的函数包含进去,因为该文件中只有异常和中断处理函数,没有任何地方显式地调用了该文件中的任何函数,而startup_stm32f10x_md.s中又提供了相应的异常与中断处理函数,虽然被声明为weak属性,但没有被正确覆盖,即使用.global声明存在这些外部函数都不行。
2 IAP程序跳转至APP程序入口前,没有将SysTick中断关闭,导致进入APP后未重新配置SysTick前又进入了老的中断处理函数,流程全乱了。

总结及心得体会

1 如果用到了IAP程序,则在跳转至APP程序前,一定要把IAP所有开启的中断全部关闭,任何一个没关闭都是隐患,看起来现象非常诡异,各种异常情况都可能出现,导致调试时各种被误导,浪费大量时间。
2 gcc编译器对于weak属性的函数似乎支持得不好。
3 坚信不会出问题的地方也是有可能出问题的~~~~不要偷懒,一个个验证吧。我一直在想生成库的环节不会有问题,所以下意识地偷懒,一直没有去验证它。如果早一点直接把所有代码一起编译,可能早就定位到问题了。(有时间要验证一下)
3 要了解工具,善用工具。工具结合文档手册,再加上大脑分析综合,才是正确的debug之道。
4 不要相信眼睛看到的表象(Keil编译生成的IAP与APP程序都能工作正常,所以IAP程序应该没问题,APP应该也没问题) ,要深入灵魂,也就是寄存器和存储器,才可以精确定位问题,而不是应该如何如何。
5 张驰有度、劳逸结合,工作效率更高!休息好了脑子更活跃,想法更多,更容易迸发灵感,找出问题所在。
6 不要轻易否定自己,也不要急于求成,保持沉着冷静很重要。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

解决gcc编译链接含weak函数的库文件出现的一些BUG_2019/03/13 的相关文章

  • 牛客小白月赛76

    牛客小白月赛76 ACM NOI CSP CCPC ICPC算法编程高难度练习赛 牛客竞赛OJ A 猜拳游戏 AC代码 include
  • COCO数据集的使用笔记

    一 简介 官方网站 http cocodataset org 全称 Microsoft Common Objects in Context MS COCO 支持任务 Detection Keypoints Stuff Panoptic Ca

随机推荐

  • 【C语言】关键字

    1 定义 声明的关键字 关键字 说明 int 声明整型变量或函数返回值类型 signed 声明有符号类型变量或函数 unsigned 声明无符号类型变量或函数 short 声明短整型变量或函数 long 声明长整型变量或函数返回值类型 fl
  • Seaborn lineplot图例标题设置

    详细版本见个人博客 Seaborn lineplot图例标题设置 一 问题描述 下面是我的lineplot 代码 如果此方法用了hue参数同时绘制多个类别图 这时候seaborn会把这个hue的标签当做子标题 sns lineplot x
  • 【BATJ面试必会】Jvm 虚拟机篇

    一 运行时数据区域 程序计数器 Java 虚拟机栈 本地方法栈 堆 方法区 运行时常量池 直接内存 二 垃圾收集 判断一个对象是否可被回收 引用类型 垃圾收集算法 垃圾收集器 三 内存分配与回收策略 Minor GC 和 Full GC 内
  • 网络层——IP协议及IP地址总结

    基本概念 在复杂的网络环境中确定一个合适的路径 主机 配有IP地址 但是不进行路由控制的设备 路由器 既然 配有IP地址 又能进行路由控制 节点 主机和路由器的统称 IP协议的功能 寻址和路由 根据对方的IP地址 寻找出最佳的路径传输信息
  • 数组下标的别致用法

    数组常识 common sense 当一个数组被创建 数组下标都是从0开始计数的 例如 创建了一个名为 arr 的数组 可以通过 arr i 来读取数据 arr 为数组名 i 为数组下标 arr i 在编译器内部会被读取转换为另外一种形式
  • 清华 NLP 团队推荐:必读的77篇机器阅读理解论文

    https mp weixin qq com s 2VhgEieBwXymAv2qxO3MPw 导读 机器阅读理解 Machine Reading Comprehension 是指让机器阅读文本 然后回答和阅读内容相关的问题 阅读理解是自然
  • C语言 学生成绩管理 txt存储数据

    include
  • SQL注入基础知识

    1 注入分类 1 根据注入点分 数值型注入 不需要考虑闭合 和字符型注入 搜索型注入 即文本框注入 2 根据注入方式分 联合注入 报错注入 盲注 二次注入 堆叠注入 宽字节注入 3 根据请求方式注入分 GET型注入 POST型注入 HEAD
  • 麦克风阵列波束形成

    我的书 淘宝购买链接 当当购买链接 京东购买链接 波束形成 beamforming 体现的是声源信号的空域选择性 许多传统波束形成方法具有线性处理结构 波束形成需要考虑三个方面 1 麦克风阵列个数 2 性能 3 鲁棒性 在麦克风较少时 波束
  • Redis实现投票功能

    一 背景介绍 投票功能是一个非常常见的Web应用场景 SpringBoot作为当今流行的Web开发框架 为了提高开发效率和性能 通常需要整合一些第三方组件 Redis是一种高性能的键值对存储数据库 而Mybatis plus则是Mybati
  • Kubernetes资源对象Pod、ReplicaSet、Deployment、Service之间的关系

    docker k8s教程 Pod ReplicaSet Deployment Service之间的关系如下图 Pod Pod是一个或多个容器的组合 这些容器共享存储 网络和命名空间 以及如何运行的规范 Pod是Kubernetes的最小可部
  • 关于新光源建设的一些想法

    表格里颜色没法调 建议的飞书版本有颜色 一些建议 对大批量使用的设备 模块 器件 材料以及基础软件架构等不要对进口产生依赖 尽可能选用国产 助力产业 方案公开评价提意见 要让我们做的每个系统拿出去都可以当个标杆推广才好 依赖进口的部分是硬伤
  • 使用自动化工具saltstack编译安装lnmp环境

    使用自动化工具saltstack编译安装lnmp环境
  • html转义字符和选择器(详)

    目录 转义字符 伪类选择器 代码解析 伪元素选择器 转义字符 转义字符 某些字符具有特殊意义 无法直接显示 需要转义 nbsp 不断行的空格 ensp 半方大的空格 emsp 全方大的空格 lt 小于 lt gt 大于 gt amp 符号
  • 安达发

    近几年来 企业对生产效率和管理水平的要求越来越高 为了提高生产效率 降低生产成本 许多企业开始引入先进的生产计划与调度系统 APS 实现生产过程的自动化 智能化管理 APS排产软件是一种能够根据企业的生产任务 资源状况 交货期等因素 自动生
  • Android开发错误——Android Studio中遇到过的错误问题与解决方案汇总

    1 编译时发生 Error 25 0 Gradle DSL method not found compile Possible causes ul li The project AP may be using a version of Gr
  • Mybatis代码生成器——让Java开发更高效

    Mybatis是一款优秀的ORM框架 在Java开发中广泛应用 然而 手写Mybatis代码工作量大 效率低 而Mybatis代码生成器可以帮助开发人员自动生成基本的CRUD代码 极大地提高了开发效率 本文将介绍如何使用Mybatis代码生
  • Modelling Uncertainty in Deep Learning for Relocaliz基于不确定性建模的DL相机重定位

    本博客仅为作者记笔记之用 不对之处 望见谅 欢迎批评指正 更多相关博客请查阅 http blog csdn net weixin 39779106 如需转载 请附上本文链接 http blog csdn net weixin 3977910
  • Calico介绍

    Calico 是一个基于 BGP 的纯三层的网络方案 与 OpenStack Kubernetes AWS GCE 等云平台都能够良好地集成 Calico 在每个计算节点都利用 Linux Kernel 实现了一个高效的 vRouter 来
  • 解决gcc编译链接含weak函数的库文件出现的一些BUG_2019/03/13

    项目介绍 本项目包含IAP程序与APP程序 APP程序有部分共用代码 包括main stm32标准库 RTOS BSP 都编译进库中 另外部分特殊代码由其它程序生成后 连接共用代码库生成目标bin文件 通过IAP下载至FLASH中 问题描述