STM32

STM32是STMicroelectronics(意法半导体)推出的一系列基于ARM Cortex-M内核的32位微控制器(MCU)产品。这些微控制器提供了广泛的产品系列,覆盖了多种不同的性能和功能需求,适用于各种应用领域,包括工业控制、汽车电子、消费类电子、医疗设备等。

STM32系列微控制器以其高性能、低功耗、丰富的外设接口和灵活的开发工具而闻名。它们通常具有丰富的存储器、多种通信接口(如UART、SPI、I2C、CAN等)、模拟数字转换器(ADC)、定时器、PWM输出等功能,以满足不同应用场景下的需求。

STM32微控制器通常使用标准的ARM Cortex-M内核,包括Cortex-M0、M0+、M3、M4和M7等,这些内核具有不同的性能和功耗特性,可根据具体应用的需求进行选择。此外,STM32系列还提供了多种封装和引脚配置,以满足不同尺寸和集成度的要求。

STMicroelectronics为STM32系列提供了丰富的开发工具和支持资源,包括基于ARM开发环境的集成开发环境(IDE)、调试器、评估板和参考设计等。这些工具和资源有助于开发人员快速开发和部署他们的应用,并提供了全面的技术支持和文档资料,帮助用户充分发挥STM32微控制器的性能和功能优势。

该视频分为3个部分,第1部分将介绍如何在STM32CubeMX中设置Octo-SPI外设。第2部分将介绍如何初始化Octo-SPI外设并在存储器映射模式下设置Octo-SPI外设。第3部分将介绍如何为IS25LX256 OCTOSPI Flash 构建外部Flash loader。

来源:STM32单片机

免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:demi@eetrend.com)。

围观 89

I-care 集团在Wi-care智能工业预测性维护系统中采用STM32WB5MMGH6无线模块

服务多重电子应用领域、全球排名前列的半导体公司意法半导体(STMicroelectronics,简称ST;纽约证券交易所代码:STM)通过开发智能无线模块帮助工业企业提高制造效率,减少资源浪费和环境污染。STM32WB5MMGH6无线模块是为工业4.0应用专门设计,可以降低用意法半导体创新的无线微控制器开发强大用例的难度,如,I-care 集团的智能设备状态监测。

该模块为使用Bluetooth Low Energy、Zigbee、Thread等主流标准开发无线通信应用提供了一个完整的子系统,并配备免费的通信协议栈,开发人员也可以选用其他的专有协议。该模块集成了几个基本组件,包括天线及其匹配电路、全部无源器件和时钟晶体。EMC、Bluetooth LE 5.3、Zigbee 3.0 和 OpenThread 标准预认证可以简化用户的强制性测试和产品级审批流程,从而节省开发成本,加快产品上市时间。

一些客户已经在使用意法半导体的 STM32WB5MMGH6 模块设计即将推出的新产品。全球机器健康市场的龙头企业I-care Group就是其中一例,其机器工况持续监测解决方案可以改善工业设备的维护,确保机器处于最佳性能状态,避免意外故障和停机。 该公司的 Wi-care 传感器是真正的即插即用的无线持续资产监测系统,与 I-care 的云计算人工智能分析平台 I-see配合使用时,Wi-care 传感器变成了维护 4.0整体解决方案,准许用户将设备状态可视化,并制定维护时间计划。有了I-care 解决方案,用户可以避免 99% 以上的工业故障,减少机器停机时间10-20%,降低维护成本35-45%。

I-care 首席执行官 Fabrice Brion 表示:“I-care 的目标是成为全球规范性和预测性维护市场的领导者。我们市场先进的 Wi-care 传感器的快速成功生产和推出,在我们的发展计划中起着至关重要的作用。其中,ST 的 STM32WB5MMGH6 无线模块在Wi-care 中的贡献不可或缺。”

意法半导体BLE/802.15.4 MCU 总经理 Hakim Jaafar 表示:选用无线模块开发系统,而不是从零开始设计,是帮助开发人员完成项目的最快方式。STM32WB5MMGH6 模块基于我们自己的 STM32WB55 无线 MCU,并有 ST开发资源的全面支持,让这种开发方法变得更快捷、更容易、更经济。

STM32WB5MMGH6TR现已投产,产品已经上市。 该产品属于意法半导体工业产品长期供货10 年产品寿命承诺范围内。

详细技术信息

STM32WB5MMGH6 供电的 STM32WB55 MCU 具有用于应用级处理的 Arm® Cortex®-M4 内核和专用于管理集成无线电的 Cortex-M0+,可确保两个域的实时性能。

MCU 包含大量的片上 RAM,这在运行 Thread 协议时特别有利。 流行的用例包括无线通信和设备控制,例如远程传感器、智能门锁、包括打印机在内的 PC 配件,以及网络网关和智能楼宇控制器等基础设施设备。 无线电的多协议技术提供了灵活性,并允许方便的设备管理和车队管理。

使用 STM32WB5MMGH6 模块的产品设计人员受益于广泛的 STM32 微控制器开发生态系统,其中包括 STM32CubeMX 配置器等免费工具和 STM32CubeWB MCU 软件包等软件。 该软件包提供基本的嵌入式开发资源,包括生产就绪的 MISRA C ISO/TS 16949 兼容的硬件抽象层 (HAL) 和低层 APIFatFS 文件系统、FreeRTOS、通信协议堆栈和代码示例。

关于意法半导体

意法半导体拥有48,000名半导体技术的创造者和创新者,掌握半导体供应链和先进的制造设备。作为一家半导体垂直整合制造商(IDM),意法半导体与二十多万家客户、数千名合作伙伴一起研发产品和解决方案,共同构建生态系统,帮助他们更好地应对各种挑战和新机遇,满足世界对可持续发展的更高需求。意法半导体的技术让人们的出行更智能,电力和能源管理更高效,物联网和互联技术应用更广泛。意法半导体承诺将于2027年实现碳中和。详情请浏览意法半导体公司网站:www.st.com

关于I-Care Group

I-care Group 是世界机器健康管理领域的先进企业,其人工智能和数据驱动解决方案可以在提前几个月甚至几年预测设备故障。I-care致力于让世界各地的机器变得更安全,生产效率更高,可持续性更强。2004 年在Mons成立,公司拥有近 700 名员工,在12个国家(美洲、欧洲和亚太地区)成立子公司,客户遍布55 个国家。I-care荣获 2020 年安永企业奖(比利时)

围观 10

意法半导体在GitHub网站上创建了 STM32 Hotspot社区,为开发者寻找专业开发的STM32 微控制器嵌入式软件项目提供了一个新场所。STM32 Hotspot 包含意法半导体内部工程师原本是为展品和概念验证模型等用途开发的非产品化代码。

srxYkHSAiw.jpg

意法半导体通常不会与外部分享此类代码示例。意法半导体已经为用户提供大量的 STM32 参考代码,现在STM32 Hotspot又将内部项目代码分享供给更广泛的开发者社区,助力他们创造更多的产品附加值。通过意法半导体GitHub社区获取软件资源,用户对软件的真实来源放心。

STM32 Hotspot 中的项目来自实际用例,有助于加快常用功能的开发,减少项目开发工作量和总体研发周期。这些代码可以免费下载,软件发行协议是意法半导体简化商贸手续的常规许可条款,方便客户直接集成到自己的应用程序中。

STM32 Hotspot 与意法半导体的GitHub主社区并存,后者让用户可以访问意法半导体官方发行的所有STM32开源软件,包括 STM32Cube平台和 STM32MPU 嵌入式软件发行版。这两个社区并立扩大了对 STM32 系列 1200 多款Arm® Cortex®-M 嵌入式内核和 Cortex-A7 MPU 内核微控制器的开发支持。

GitHub 用户可以在 https://github.com/stm32-hotspot 找到 STM32 Hotspot网页。了解更多信息,加入 ST GitHub 主社区,请访问 https://github.com/STMicroelectronics

了解详情还可以阅读我们的博文: https://blog.st.com/stm32-hotspot/

围观 18

机器学习 (ML) 在服务器和移动应用中已经风靡多年,现在这种趋势已蔓延到边缘设备,并且变得突出。由于边缘设备需要节能,因此开发人员需要学习和了解如何将ML模型部署到基于微控制器的系统中。

在微控制器上运行的ML模型通常被称为tinyML。然而,将模型部署到微控制器并非易事,但它正在变得越来越容易,没有经过任何专业培训的开发人员也能在规定时间完成部署。

本文探讨了嵌入式环境开发人员如何通过STMicroelectronics的STM32微控制器开始使用ML。为此,文中展示了如何通过X-CUBE-AITensorFlow Lite for Microcontrollers模型转换用于STM32CubeIDE,来创建“Hello World”应用。

tinyML用例介绍

tinyML是一个不断发展的领域,它将ML功能整合到微控制器等资源和功耗受限的设备中,通常采用深度神经网络。然后,这些微控制器设备可以运行ML模型,在边缘进行有价值的工作。以下几个用例中的tinyML非常值得关注。

第一个用例常见于许多移动设备和家庭自动化设备,即关键词识别。通过关键词识别,嵌入式设备可以使用麦克风捕获语音并检测预先训练的关键词。tinyML模型使用表示语音的时间序列输入,将其转换为语音特征,通常为频谱图,其中包含随时间变化的频率信息。然后,将频谱图输入经过训练的神经网络,以检测特定的字词,结果就是检测到特定字词的概率。图1显示了这个过程的示例。

“图1:关键词识别是tinyML的有趣用例。输入的语音被转换为频谱图,然后输入经过训练的神经网络,以确定是否有预先训练的字词。(图片来源:Arm®)"
图1:关键词识别是tinyML的有趣用例。输入的语音被转换为频谱图,然后输入经过训练的神经网络,以确定是否有预先训练的字词。(图片来源:Arm®)

许多嵌入式环境开发人员感兴趣的另一个tinyML用例为图像识别。微控制器从摄像头捕获图像,然后将其输入预先训练的模型。模型可以辨别图中的内容。例如,模型可以确定是否有猫、狗或者鱼等等。图像识别用于边缘的一个很好的例子是视频门铃。视频门铃通常可以检测门口是否有人,或者是否有放下的包裹。

最后一个非常常见的用例是用tinyML进行预见性维护。预见性维护使用ML基于异常检测、分类算法和预测模型来预测设备状态。同样,从HVAC系统到工厂车间设备,应用非常广泛。

尽管上述三个用例是目前常见的tinyML,但开发人员无疑还可以找到更多潜在的用例。以下是相关应用的列表:

  • 手势分类
  • 异常检测
  • 模拟量表读取器
  • 指导和控制 (GNC)
  • 包装检测

无论哪个用例,开始熟悉tinyML的最好方法是使用“Hello World”应用,它可以帮助开发人员学习和理解实现并运行一个最基础的系统所遵循的基本流程。在STM32微控制器上运行tinyML模型,有5个必要步骤:

1、捕获数据
2、标记数据
3、训练神经网络
4、转换模型
5、在微控制器上运行模型

捕获、标记和训练“Hello World”模型

关于捕获和标记用于训练模型所需的数据,开发人员通常有许多选择。首先,有大量的线上训练数据库。开发人员可以搜索他人收集和标记的数据。例如,对于基本的图像检测,有CIFAR-10或ImageNet。如需训练模型来检测照片中的微笑,也有一个图像集。从在线数据存储库开始显然是不错的选择。

如果所需的数据尚未在互联网上公开,开发人员也可以生成自己的数据。可以使用Matlab或其他工具来生成数据集。如果不能自动生成数据,也可以手动完成。最后,如果觉得这些都太耗时,也可在互联网上购买数据集。收集数据往往是最令人兴奋和有趣的选择,但也最费事。

这里探讨的“Hello World”示例展示了如何训练模型来生成正弦波并将其部署到STM32上。这个示例由Pete Warden和Daniel Situnayake整理,当时他们在谷歌开展TensorFlow Lite for Microcontrollers工作。这样一来,工作变得更容易,因为他们已经整理出了简单的捕获、标记和训练模型的公开教程。可以在Github上找到(点击此处);打开链接后,开发人员应点击“Run in Google Colab”(在Google Colab中运行)按钮。Google Colab是Google Collaboratory的简称,它允许开发人员在浏览器中编写和执行Python,无需配置,并提供对Google GPU的免费访问。

浏览训练示例将输出两个不同的模型文件;一个是为微控制器量化的model.tflite TensorFlow模型,一个是没有量化的model_no_quant.tflite模型。量化可以表明如何以数字方式存储模型的激活和偏置。量化后可以得到更小的模型,更适合于微控制器。好奇的读者可以在图2中查看训练过的模型结果与实际正弦波结果的对比。模型的输出以红色显示。正弦波输出并不完美,但对“Hello World”程序而言,其效果已经很好了。

“图2:TensorFlow模型正弦波预测与实际值的对比。(图片来源:Beningo
图2:TensorFlow模型正弦波预测与实际值的对比。(图片来源:Beningo Embedded Group)

选择开发板

在研究如何转换TensorFlow模型以便在微控制器上运行之前,需要选择该模型中部署的微控制器。本文将重点介绍STM32微控制器,因为STMicroelectronics公司有许多tinyML/ML工具,可以很好地转换和运行模型。此外,STMicroelectronics有多种与其ML工具兼容的元器件(图3)。

“图3:图示为STMicroelectronics
图3:图示为STMicroelectronics AI生态系统目前支持的微控制器和微处理器单元(MPU)。(图片来源:STMicroelectronics)

如果办公室里有这样一块开发板,就非常适合启动和运行“Hello World”应用。然而,如果对本例之外的应用感兴趣,想要了解手势控制或关键词识别,可以选择STM32 B-L4S5I-IOT01A开发套件物联网节点(图4)。

该开发板带有STM32L4+系列Arm Cortex®-M4处理器。该处理器有2MB闪存和640KB RAM,为tinyML模型提供了充足的空间。该模块还带有STMicroelectronics的MP34DT01微机电系统 (MEMS) 麦克风,可用于关键词识别的应用开发,适用于tinyML用例实验。此外,同样来自STMicroelectronics的板载LIS3MDLTR三轴加速计,可用于基于tinyML的手势检测。

“图4:STM32
图4:STM32 B-L4S5I-IOT01A开发套件物联网节点搭载Arm Cortex-M4处理器、MEMS麦克风和三轴加速计,是适应性tinyML实验平台。(图片来源:STMicroelectronics)

使用STM32Cube.AI转换和运行TensorFlow Lite模型

凭借可以运行tinyML模型的开发板,开发人员现在可以开始对TensorFlow Lite模型进行转换,以便在微控制器上运行。TensorFlow Lite模型可以直接在微控制器上运行,但需要一个运行时环境来处理它。

运行模型时,需要执行一系列的功能。这些功能首先收集传感器数据,然后筛选,提取必要特征,并反馈给模型。该模型输出结果,然后对结果进一步筛选,通常还会再进行一些操作。图5显示了该过程的概况。

“图5:数据如何从传感器流向运行时,再到tinyML应用的输出。(图片来源:Beningo
图5:数据如何从传感器流向运行时,再到tinyML应用的输出。(图片来源:Beningo Embedded Group)

STM32CubeMx的X-CUBE-AI插件提供了解释TensorFlow Lite模型的运行时环境,并提供了开发人员可以利用的替代运行时和转换工具。X-CUBE-AI插件在项目中默认不启用。然而,在创建新项目并初始化电路板后,在Software Packs-> Select Components(软件包-> 选择组件)下,有一个启用AI运行时的选项。这里有几个选项;确保本例中使用的是Application模板,如图6所示。

“图6:X-CUBE-AI插件需要使用本例的应用模板来启用。(图片来源:Beningo
图6:X-CUBE-AI插件需要使用本例的应用模板来启用。(图片来源:Beningo Embedded Group)

启用X-CUBE-AI后,STMicroelectronics X-CUBE-AI类别将出现在工具链中。点击该类别,开发人员能选择自己创建的模型文件并设置模型参数,如图7所示。可通过分析按钮对模型进行分析,并为开发人员提供RAM、ROM和执行周期信息。强烈建议开发人员比较Keras和TFLite模型选项。在较小的正弦波模型示例中,没有显著差异,但却可以发现其中的区别。点击“Generate code”(生成代码)可生成该项目。

“图7:分析按钮为开发人员提供RAM、ROM和执行周期信息。(图片来源:Beningo
图7:分析按钮为开发人员提供RAM、ROM和执行周期信息。(图片来源:Beningo Embedded Group)

代码生成器将初始化项目,并为tinyML模型构建运行时环境。但默认情况下,不会为模型提供输入。开发人员需要添加代码,为模型提供输入值 — x值,模型将解释该值并生成正弦y值。如图8所示,需要在acquisition_and_process_data和post_process函数中增加几段代码。

“图8:所示代码将连接伪输入传感器值到正弦波模型。(图片来源:Beningo
图8:所示代码将连接伪输入传感器值到正弦波模型。(图片来源:Beningo Embedded Group)

此时,本例运行就绪。注意:添加一些printf语句来获取模型输出,以便快速验证。快速编译和部署能让“Hello World”tinyML 模型运行。获取整个周期的模型输出得到图9所示的正弦波。它并不完美,但对于首个tinyML应用来说非常优秀。由此,开发人员可以将输出与脉冲宽度调制器 (PWM) 联结起来,并产生正弦波。

“图9:在
图9:在 STM32上运行时的“Hello World”正弦波模型输出。(图片来源:Beningo Embedded Group)

嵌入式系统上的ML技巧和窍门

开发人员若要在基于微控制器的系统上开始使用ML,需要做相当多的工作,才能让自己的首个tinyML应用运行起来。然而,记住几个“技巧和窍门”,可以简化和加快其开发:

  • 浏览TensorFlow Lite for Microcontrollers的“Hello World”示例,包括Google Colab文件。花点儿时间调整参数,了解这些参数对经过训练的模型的影响。
  • 在微控制器应用中使用量化模型。量化模型经过压缩,可以使用uint8_t而非32位浮点数。因此,该模型更小,执行速度更快。
  • 了解TensorFlow Lite for Microcontrollers资源库中的其他示例。其他示例包括手势检测和关键词检测。
  • 以“Hello World”为例,将模型输出连接到PWM和低通滤波器上,以查看产生的正弦波。执行运行时实验,增加和减少正弦波频率。
  • 选择包括“额外”传感器的开发板,以便尝试广泛的ML应用。
  • 尽管收集数据很有趣,但一般来说,购买或使用开源数据库来训练模型更容易。

开发人员遵循这些“技巧和窍门”,可以在确保应用安全的同时节省更多的时间并省去更多的麻烦。

本文小结

机器学习已经蔓延至网络边缘,而基于资源受限微控制器的系统是其主要目标。最新的工具可以转换和优化机器学习模型,以在实时系统上运行。如图所示,在STM32开发板上实现和运行模型相对容易,但也会涉及复杂性问题。虽然只探讨了产生正弦波的简单模型,但也可以实现更复杂的模型,如手势检测和关键词识别。

来源:得捷电子DigiKey
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 929

本应用笔记描述如何在基于 Arm® Cortex®‑M33 处理器的 Arm® TrustZone® STM32 微控制器上获得安全启动和安全固件更新流程解决方案。该应用笔记还提供此解决方案与 X-CUBE-SBSFU 解决方案的顶层比较结果,后者适用于基于 Arm® Cortex®‑M0、Cortex®‑M3、Cortex®‑M4、或 Cortex®‑M7 处理器的非 TrustZone®STM32 微控制器。它还为安全启动和安全固件更新流程解决方案提供顶层集成指南。

对于 Arm® TrustZone® STM32 微控制器,安全启动和安全固件更新流程解决方案在相应的 TM32Cube MCU 包中提供。与 X-CUBE-SBSFU STM32Cube 扩展包中提出的解决方案不同,该解决方案基于开源 TF‑M(可信固件面向 Arm® Cortex®‑M)参考实现。

本应用笔记适用于所有 TrustZone® STM32 微控制器。然而,本文档中将 STM32L5 系列作为示例。
STM32Cube MCU 包中可用的基于 TF‑M 的应用可能会不同,具体取决于 TrustZone®STM32 微控制器。参照公认的 Arm®TrustZone® STM32 微控制器(第 2 节 参考)的 TFM 应用(TF‑M 的完整实现)的用户手册,获取对解决方案的精确描述。

详阅请点击下载《Arm® TrustZone® STM32 微控制器的安全启动和安全固件更新解决方案概述》

来源:STM32
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 85

1、前言

最近有客户询问,能否使用 STM32CubeIDE 在编译时通过设置某个编译选项,让STM32 应用与存储位置无关。这样的优势是能使同一个固件被烧在 STM32 Flash 里的不同位置, 而在系统 Bootloader 里只需要跳到相应的位置就可以正常执行固件代码。客户希望STM32 代码从 Flash 里执行,不复制到 RAM 里;客户希望是一个完整的映像,而不仅仅是其中某个函数做到了位置无关。

2、分析

在嵌入式场景下,不一定有操作系统。即使有操作系统,一般也是 RTOS。一般 RTOS没有一个通用的程序加载器。因此,存储位置无关的需求,在这时可以说无关紧要。但是,如果客户需要进行在线固件更新,例如 IoT 应用的固件升级,那么位置无关就存在价值了。位置无关之后,对于不同的软件版本,不需要频繁的为烧写位置的反复改变而修改编译链接脚本。也不需要在代码里显式的在两个 Bank 之间进行切换。

最简单的情况是所有的代码都复制到内存执行。因为 Flash 的功能只是进行存储,自然对 Flash 的位置没有任何要求。但大部分 MCU 用户面临的真实案例都是 Flash 比较大,例如 ,1M 字节 ;RAM 比较小,例如,128K 字节。在这种情况下,代码在 Flash 原地执行就是一个必须的选择。Flash 位置改变,会影响从 Bootloader 跳转之后的固件执行时的 PC 指针,也就是 PC指针值会发生相应的变化。位置无关的原理,是让应用程序经过编译后所生成的映像,其中的代码和数据,都是基于相对代码的位置进行引用。那么,当应用被搬到不同位置时,他们的相对位置不变,从而执行不受影响。

代码和数据基于绝对地址还是基于相对地址,是由编译器所决定。以客户要求的

STM32CubeIDE 编译工具为例,我们可以看到在[Project]->[Properties]->[C/C++ Build]->[Settings]->[Tool Settings]->[MCU GCC Compiler]->[Miscellaneous]已经有一项[Position Independent Code (-fPIC)]。

是否只要选一下-fPIC 选项就大功告成了呢?答案是没有那么简单。

“如何开发与存储位置无关的STM32应用?"

事实上,对于完整应用程序工程,用户应该经过这些步骤将其变成位置无关:• 选择正确的编译器选项

• 去掉或者替换掉那些包含绝对位置的库文件

• 修改代码中的 Flash 绝对地址(这里以 STM32H7 的 CRC_Example 例程为例,其他情况下有可能要修改更多)

• 在 startup_xxx.s 汇编代码里的 sidata

• 在 system_xxx.c 里的 SCB->VTOR 以及中断向量表内容

• GOT

对于完整工程,要正确的跳转到应用程序进行执行,还需要由 Bootloader 向应用程序提供或者由应用程序在链接时自身解析计算,得到以下信息:

• Flash 偏移量

• 中断向量表的开始以及结束地址

• GOT 的开始以及结束地址

我们接下来就举例说明这些步骤。

3、步骤

3.1. 选择正确的编译器选项

如果我们不使用任何编译选项,编出来的代码会怎么样?我们可以通过.list 文件进行查看。.list 文件在 STM32 例程中默认生成,如果没有请勾选如下选项, 在 [Project]->[Properties]->[C/C++ Build]->[Settings]->[Tool Settings]->[MCU Post Build outputs]->[Generate list file],可参考下图。

“如何开发与存储位置无关的STM32应用?"

“如何开发与存储位置无关的STM32应用?"

“如何开发与存储位置无关的STM32应用?"

我们看到代码中直接使用了变量的绝对地址,例如 0x2000 0028。我们不要被 literal pool 文字池的使用所迷惑,那个基于 PC 的操作只是为了取变量的绝对地址,例如, 0x2000 0028,并没有将绝对地址变成相对地址。

当然大家说这里是 RAM 地址,没有关系。我们选择这个函数来说明,是因为位置无关的编译器选项是不区分 RAM 还是 Flash 里的变量,而这个函数最简单容易理解。如果我们查看另外一个复杂一点的函数,例如,HAL_RCC_ClockConfig,我们可以看到以下对Flash 里变量的直接使用。这就不妙了,因为一旦改变了 Flash 下载的位置,在绝对地址处就取不出变量的真实内容了。

“如何开发与存储位置无关的STM32应用?"

我们没有办法一个一个查找修改所有的变量。当然这里的变量是指全局变量。如果要修改,我们希望编译器能把他们集中在一起。对于此,编译器提供了多个编译选项。例如,PIC 是位置无关代码, PIE 是位置无关执行。PIC 和 PIE 这两者类似,但是存在一个显著的差异是 PIE 会对部分全局变量优化。我们可以观察到用两种不同编译选项的效果。

“如何开发与存储位置无关的STM32应用?"

其中 80004C0 地址处包含的是 GOT 自身的偏移量,存在 r2 里,要在两次取全局变量 uwTickFreq 和 uwTick 时引用。GCC 编译器引入 GOT 全局偏移量表来解决全局变量的绝对地址的问题。在之前对绝对地址的直接使用,现在被转化成先取得 GOT 入口相对于 PC 的偏移,再获得实际变量相对于 GOT 入口的偏移,从而得到实际变量的地址。计算公式如下:

实际变量的绝对地址=PC + GOT 相对于 PC 的偏移 + 变量地址相对于 GOT 的偏移

GOT 只有一个,如果代码放在不同的位置,代码自身就可以根据 Bootloader 传递过来的信息,或者自行计算来对 GOT 进行更新。这样变量的地址就和新的 Flash 偏移相匹配。

“如何开发与存储位置无关的STM32应用?"

这里可以看到 80004c0 对应的 uwTick(可以从 str 指令结合 C 语言源代码快速知道它对应于 uwTick)不再使用 GOT 偏移,而是相对于 PC 的偏移(与前文相比,多了一条指令 “add r3,pc”)。换句话说,PIE 对局部的全局变量做了优化。这个优化显然不是我们所需要的。因为如此以来,RAM 变量的地址就会随着 PC 的不同而不同。而我们则希望所有对RAM 的用法不发生变化。

为了能够修改 GOT 内容,我们选择将 GOT 最终存放在 RAM 中,导致代码中对 GOT的寻址也是使用了相对于 PC 的偏移。而因为 RAM 有限,或者因为没有虚拟内存的缘故,我们不希望 RAM 的用法有所不同,否则,可能代价很大。这时,一旦 Flash 代码位置发生变化引起 PC 指针变化,GOT 就无法找到。因此,即使我们不使用 PIE,PIC 也没有办法单独使用。为了确保没有任何存放在 RAM 里的变量的位置是相对于 PC 的偏移。我们应该使用如下所有编译选项,single-pic-base 让系统只使用一个 PIC 基址,就是下文反汇编中看到r9;no-pic-data-is-text-relative 则让编译器不要让任何变量相对于 PC 寻址。

“如何开发与存储位置无关的STM32应用?"

“如何开发与存储位置无关的STM32应用?"

这样实际变量的绝对地址,就变成实际变量的绝对地址=PIC 基址 + GOT 相对于 PIC 基址的偏移 + 变量地址相对于 GOT的偏移使用以上编译选项,这样我们看到 HAL_IncTick 就如下所示:

“如何开发与存储位置无关的STM32应用?"

这样所有在 RAM 里的全局变量都是相对于 GOT 的偏移。注意,这个时候你编译出来的代码现在没有办法进行测试,尽管你只是改了编译选项。这是因为 PIC 的基址需要你通过寄存器 r9 显式指定。在本例中,我们在链接脚本里如下定义 GOT 的位置:

“如何开发与存储位置无关的STM32应用?"

因此,我们可以很容易的从.map 文件中获得 GOT_START 的 RAM 地址,0x2000 0000,它就是 PIC 的基址。如果想测试编译器选项是否如我们所期望,我们可以在Reset_Handler 开始部分加上如下语句(参考后文内存布局的代码):

“如何开发与存储位置无关的STM32应用?"

经过测试,我们可以确信,编译器选项的改动对我们最终执行结果没有影响。

值得注意的是,STM32 用户的代码,例如 RTOS 的移植, 也可能使用寄存器 r9。在这种情况,用户应当解决冲突。一般情况寄存器 r9 对应用程序并不是必要的。

3.2. 去掉或者替换掉那些包含绝对位置的库文件

我们要将位置无关的库去掉或者替换掉。在 STM32 参考代码里,我们需要

startup_xxx.s 里 C 库调用去掉。示例如下:

“如何开发与存储位置无关的STM32应用?"

3.3. 修改 Flash 绝对地址

3.3.1. 内存布局

如果要对代码中的 Flash 绝对地址进行修改,我们需要知道存放 Flash 绝对地址的 RAM起始和结束地址,以及需要增加或减少的 Flash 偏移量。存放 Flash 绝对地址的 RAM 起始和结束地址,在编译时可以让应用代码本身借助自身链接脚本在链接时导出的变量得到,然后由应用程序在运行时存放在 RAM 中的固定位置;也可以在编译后从.map 文件或使用工具解析 elf 文件获得,然后作为应用程序一部分的元信息,例如,给应用程序加个头部存放元信息,由 Bootloader 下载并解析,将其放入到 RAM 固定位置。

我们规划在一段 RAM 里按如下顺序存放如下元信息,它可以是应用程序本身在最初阶段自我存放在这里,也可以简单的由 Bootloader 解析元信息后,跳转到应用程序之前就存放在这里。

“如何开发与存储位置无关的STM32应用?"

我们在前文已经在链接脚本中定义了 GOT_START 和 GOT_END,我们还需要在链接脚本中定义 VT_START 和 VT_END。如下图所示:

“如何开发与存储位置无关的STM32应用?"

如果我们希望 Bootloader 仅仅是做简单的跳转,我们可以将规划这段内存的工作,交给应用程序的初始化部分(在 “ldr sp, =_estack”之前)。假定 0x0 处对应为 0x2400 0000,参考代码如下:

“如何开发与存储位置无关的STM32应用?"

3.3.2. 汇编代码

3.3.2.1. _sidata

在默认的 STM32 工程中,还有一些对变量绝对地址的使用。在 startup_xxx.s 有许多地方使用绝对地址,它们不能被编译器收集到 GOT 中。其中,默认在链接脚本里的_sidata,标志 flash 里 RAM 数据区的 Flash 位置,需要修改。

“如何开发与存储位置无关的STM32应用?"

注意,变量绝对地址本身不是个问题,而对它解应用,取它的内容才会发生错误。而这里的 _sidata 是要被初始化代码使用,目的是将 Flash 的内容搬移到 RAM 里。我们显然要对_sidata 进行修改,否则无法取得正确的内容到 RAM 里。

根据前文的内存布局,我们可以把 Flash 的偏移量从内存中放置在寄存器 r8 里,例如:

“如何开发与存储位置无关的STM32应用?"

则我们只需要一行简单的代码 “add r3,r8” 就可以修正_sidata 的地址。

“如何开发与存储位置无关的STM32应用?"

3.3.3. C 代码

3.3.3.1. 公共函数

如果一段内存的数据都是硬编码,我们只需要一个公共函数就可以对其循环进行修正。我们需要知道什么样的地址之外不是 Flash 地址,那么就对这样的值不做修改。例如,我们定义 0x1fff ffff 之外的就不是 Falsh 地址,相应的宏定义如下:

“如何开发与存储位置无关的STM32应用?"

3.3.3.2. SCB->VTOR

在 C 语言中如果使用赋值语句进行硬编码,编译器也无法进行收集。例如在

system_stm32xxxx.c 中的 SystemInit 有如下语句:

“如何开发与存储位置无关的STM32应用?"

中断向量表相关的内容需要修改,包括两部分:

• 中断向量表的内存位置

• 中断向量表的内容

我们应该将中断向量表复制到 RAM 里,通过 UpdateOffset 函数修正其中包含的所有Flash 绝对地址的值,同时通过对 SCB->VTOR 赋值来将中断向量表的位置指向我们修改过内容的 RAM 地址。注意,VTOR 所指向的地址 VT_RAM_START 要按照 ARM 要求,根据中断总大小向上进行 2 的幂次对齐,例如,37 个字大小要使用 64 个字对齐。另外,中断向量表的内容,也包含有 RAM 地址,对此,我们并不需要修改。当然,UpdateOffset 函数已

经考虑到这一点,所以我们可以直接使用它。更新中断向量表以及 VTOR 的参考代码如下:

“如何开发与存储位置无关的STM32应用?"

3.3.3.3. GOT

编译器已经将 C 语言中所有全局变量的地址都收集到 GOT 中,因此我们很容易对其Flash 地址的内容进行修正,参考代码如下:

“如何开发与存储位置无关的STM32应用?"

4、总结

除非你仅仅是运行一小块代码,否则开发位置无关的 STM32 完整工程,不仅仅要设置正确的编译器选项,还要保证它所链接的预编译的库不含有绝对地址引用,要保证所有源代码里没有对绝对地址的硬编码,包括修改 data 区的 Flash 起始地址,中断向量表的内容与位置,以及 GOT 的内容。

来源:STM32单片机
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 248

页面

订阅 RSS - STM32