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微控制器的性能和功能优势。

一、引言

在 STM32 TrustZone 开发调试技巧 | 地址安全区及资源安全属性配置文章中,我们介绍了内核的 SAU/IDAU,地址的安全属性配置,资源的安全属性配置,以及内核访问资源的安全规则等内容,这部分作为 TrustZone S/NS 工程开发的基础,让 S 和 NS 工程代码能够基本运行起来。

在此基础上,S/NS App 还需要使用片上外设等资源,实现应用程序的业务逻辑和功能,这时候往往会遇到一些与外设使用相关的问题。

在这一篇中,我们将把重点放在 Trust Zone 架构下应用开发中使用外设的环节,从外设中断、DMA、GPIO 及其与 IO 连接的外设等几个方面,介绍这些部分与传统的不带TrustZone 的 STM32 开发相比有哪些变化,同时会列举一些相关开发中的常见问题,并给出问题的分析与解决方法,供开发者参考。

二、关于外设中断

2.1 CM33 内核 TrustZone 架构下的中断

2.11 中断向量表 Vector Table

传统的 ARM V6/V7 内核,例如 CM4、CM7,都只有一套中断向量表,而带 SecurityExtension 的 CM33 内核有两套中断向量表,分别对应 CPU 的 S 和 NS 两种状态,如图 1所示。在 TrustZone 的双工程开发中,S 工程和 NS 工程都会有各自的中断处理程序(interrupt handler)。他们也有各自的 VTOR,即 VTOR_S 和 VTOR_NS。体现在 linker 文件中,也都有各自的 initial vector 的地址和向量表部分。

系统上电复位后,CPU 总是处于安全状态,因此一定首先从 Secure 的 Reset Handler开始执行代码。当 S 代码完成相关的初始化和系统配置之后,通常会跳转至 NS 代码的Reset Handler 开始执行 NS 代码。但是这里的 NS Reset Handler 其实并不是真正意义上的 interrupt handler,因为没有任何中断会直接进入这个 Handler,它仅仅是 S 代码跳转NS 代码时候的跳转入口。当发生系统复位时,硬件会忽略 NS 的 reset handler 和初始SP。系统永远都是复位到 Secure,加载 Secure 的初始 SP,并从 Secure 的 ResetHandler 开始执行。图 2 给出了 TrustZone 环境下的代码执行顺序示例。

1.png

▲ 图1 带 TrustZone 的 CM33 内核的两个中断向量表

2.png

▲ 图2 TrustZone 环境下的 S/NS 代码运行顺序示例

内核的两个 Vector table 中都包括系统中断和外设中断两个部分,系统中断里有一部分是 bank 的,也就是说 S 和 NS 各有一套,互不相干,例如 Systick,PendSV,SVCall,MemoryFault,Usage Fault,这些中断的 handler 可以在 S/NS 中被各自触发,各自有各自的处理程序。有些中断只会出现在 S 侧,例如 SecureFault,而 HardFault,NMI,BusFault 则默认在 S 侧,但可以通过寄存器配置,允许 NS 侧触发相关的异常。

2.12 外设中断

中断表中的最后一类则是外设中断,即图 1 中 IRQx。这类中断属于目标二选一的中断。上电复位缺省所有 IRQx 都是 target 到 S 的,即任何一个 IRQx 都只会触发 Vectortable S 里面的中断句柄,NS 侧虽然也有同样的 IRQx 和对应的 handler,但是并不会被触发。为了能够选择 IRQx 的 target 目标世界,NVIC 中增加了一组寄存器 NVIC_ITNS0 -NVIC_ITNS15,用于指定某个 IRQx 是否 target 到 NS。上电复位后,ITNSx 寄存器默认值总是 0,也就是所有 IRQ 都 target 到 S,如果需要让某个 IRQ 触发 NS 侧的中断句柄,则需要将对应的 ITNSx 的 bit 设置为 1。

具体设置方法有两种:

  • 调用函数NVIC_SetTargetState(IRQn)设置某个 IRQ 为 target 到 NS;

  • 直接操作 NVIC 的 ITNS 寄存器,例如 NVIC->ITNS[x] = xxx,这种方式比较便捷,且可以一次设置多个 IRQ 的不同 target 目标。

在 STM32 CubeFW 软件包的 TrustZone Template 工程中通常我们会看到一个与TrustZone 有关的配置文件,文件名类似 partition_xxxx.h,这个文件里面会包含 SAU 的配置,中断的 Target 配置等等。其中,中断 target 的配置就是通过直接写 NVIC->ITNS[x]寄存器的方式完成的。需要修改配置的时候只需要定义相关的 NVIC_INIT_ITNSx 宏并修改 NVIC_INIT_ITNSx_VAL 的值即可。例如

#define NVIC_INIT_ITNS0 1 
#define NVIC_INIT_ITNS0_VAL 0xFFFFFC7F

2.2 NS App 中 IRQ Handler 无法进入问题

有很多时候,客户可能是将原有其他 STM32 系列的平台上已经开发过的应用移植到CM33 内核带 TrustZone 的 STM32 产品上,通常原有的业务逻辑会放在 NS 非安全侧,安全侧则主要实现一些与信息安全相关的功能。也有可能项目本身就是在支持 TrustZone 的STM32 MCU 上进行的开发,但是刚开始并没有使能 TrustZone 功能,后面再把TrustZone 使能起来,进行完整的开发和集成。这时候,开发者往往会遇到 NS App 的外设中断无法触发的问题。

【问题现象】NS App 外设中断在不使能 TrustZone 的环境下都能够正常工作,但是移到 TrustZone使能的环境之后,发现 NS App 的外设中断总是无法被触发,例如 UART 中断,GPIO EXTI 中断,DMA 中断等等。如果在调试器中将断点设置在中断句柄函数中,则会发现本来硬件应当触发中断的时候,NS App 的 IRQ handler 却从未进入。

【分析】CM33 TrustZone 架构下,内核有两套中断向量表,上电复位所有的 IRQ 都缺省Target 到 S,也就是说,不做特别配置的话,外设中断只会触发 S 侧的 IRQ Handler,因此 NS App 的 IRQ Handler 一定不会有响应。通常在 Trust Zone 开发中发现 IRQ 中断句柄应当被触发却并未被触发,应当首先检查该 IRQ 的安全目标配置是否正确。

【解决方法】在 S 工程的初始化代码中,将需要被 NS App 处理的 IRQ 都配置为 target 到 NS,可以参考 2.1.2 小节的相关说明。

这种问题往往出现在开发者直接手写代码(或者从 STM32CubeFW 软件包的TrustZone 模板工程开始)进行 TrustZone 配置的时候,因为需要配置的点可能比较多,又未必是集中在同一个代码文件中,有可能忽略了某个配置,造成问题。如果选择使用STM32CubeMX 工具生成相关的工程框架和初始化代码,用 GUI 界面的方式进行配置,则会更加简单明了,相对来说会降低出错几率。在第 5 章节中将对这部分加以简要介绍。

三、关于 DMA

3.1  DMA 的 TrustZone aware 特性

STM32 MCU 中的 DMA 单元(例如 GPDMA, LPDMA)在 Trust Zone 框架下属于 TZaware IP,DMA 能够直接支持 AHB5 总线。

作为总线主设备,DMA 可以发出 S 安全或者 NS 非安全的 transaction。以 STM32U5GPDMA 为例,通过 GPDMA_SECCFGR.SECx 寄存器,可以将 DMA 的 Channel 设置为安全或者非安全通道。

如果一个 Channel 具有安全属性,那么它就是一个安全 DMA 通道,Secure DMAChannel 有能力发出 S 安全或者 NS 非安全访问,同时,S 安全代码还可以配置安全 DMA通道的 source 和 destination 数据传输的安全访问属性,安全通道对 source 和 destination的安全访问属性配置是独立的,互相之间没有依赖关系,因此配置为安全的 DMA 通道可以任意地在安全或者非安全资源之间做数据搬移,如图 3 所示。红色表示非安全访问/非安全资源,绿色表示安全访问/安全资源,从图中可以看到安全 DMA 可以访问所有不同安全属性的 source 和 destination,包括 Flash,SRAM,外设等。

这里要注意一点,如果安全 DMA 通道访问的资源是存储器,那么安全通道配置的source 和 destination 的安全属性应当与目标资源的安全属性一致,否则无法正常访问资源的数据,会出现 RAZ/WI 的效果。

3.png
▲ 图3 安全 DMA Channel 可以访问安全或者非安全资源

注意:当使用 DMA 的 link list 模式时,从 memory 中读取 link list 表数据结构时的安全访问属性与 Channel 的安全属性一致。所以 Secure Channel 加载 link list 表时,读取memory 也使用安全访问模式。

如果一个 Channel 配置为非安全属性(这也是上电复位后 DMA 的缺省状态),那么非安全 DMA Channel 只能发出 NS transaction,只能在 NS 属性的资源之间做数据搬移,

如图 3 所示。如果非安全 DMA 通道试图访问安全资源,将无法正常读写数据,通常效果是 RAZ/WI。


4.png

▲ 图4 非安全 DMA Channel 只能访问非安全资源

作为总线从设备,DMA 的寄存器被访问时,也能够识别总线上的安全访问标志信号HNONSEC,根据 Channel 的安全、非安全属性会允许或者阻止对某些寄存器的访问。

当某个 Channel 被设置为 Secure,NS 代码尝试读取 Secure Channel 的寄存器会返回 0,某些寄存器除外,例如 GPDMA 的 GPDMA_SECCFGR,GPDMA_PRIVCFGR 和GPDMA_RCFGLOCKR 可以被非安全代码读取。NS 代码尝试写 S DAM Channel 的寄存器将没有任何效果。

除了安全、非安全属性,DMA Channel 还可以配置其 PRIV/NPRIV 属性(特权/非特权模式访问)。依旧以 STM32U5 GPDMA 为例,GPDMA_PRIVCFGR.PRIVx 寄存器用于配置某个 Channel 的特权模式访问属性。当某个 Channel 配置为特权模式时,这个Channel 的寄存器也只能被特权模式访问,包括读和写。某些寄存器可能存在例外,例如GPMDA 的 GPDMA_PRIVCFGR, GPDMA_SECCFGR,GPDMA_RCFGLOCKR 可以被NPRIV 模式读取。

PRIV 属性的 Channel 发出的访问都是 PRIV 特权模式访问,NPRIV 属性的 Channel发出的访问都是 NPRIV 非特权模式访问。

注意:当使用 link list 模式时,从 memory 加载 link list 表数据结构时候的访问模式与Channel 的 PRIV/NPRIV 属性一致。

当 DMA 对资源进行读写的时候,任何一个访问都会带有 S/NS 以及 PRIV/NPRIV 属性,因此 DMA 通道的 Secure 属性和 PRIV 属性配置是共同起作用的,他们会同时体现在DMA 对资源访问的 transaction 中。图 5 给出了两种 Channel 以及 Channel 对source/destination 访问可能携带的 Secure 和 PRIV 标记的例子。Channel1 是 S+PRIV 通道,Channel2 是 NS+NPRIV 通道。当然还有可能出现其他的组合,例如 S+NPRIV 通道和 NS+PRIV 通道。DMA 访问 source 和 destination 时的 PRIV/NPRIV 属性直接遵循Channel 自身的 PRIV/NPRIV 属性,所以无论对 source 还是 destination,DMA 发出访问的 PRIV/NPRIV 属性一定是相同的;访问的 S/NS 属性在 NS Channel 中只能是 NS 访问,对 source 和 destination 都一样,而在 S Channel 中可能出现 S 或者 NS 访问,且source 和 destination 访问的安全属性可能不一样。


5.png
▲ 图5 DMA Channel 的 Secure+PRIV 属性组合示例

3.2 TrustZone 架构下带有 DMA 的 Securable 外设

STM32 MCU 中可能含多个具有 DMA 功能的硬件单元,并不是所有的带 DMA 功能的硬件都是 TrustZone aware 外设。系统中除了有作为独立的总线主设备出现的GPDMA/LPDMA 等之外,还可能包含其他一些带有 DMA 功能的总线主设备,例如SDMMC、Ethernet、DMA2D 等。这些设备在使用过程中也有可能通过自身的 DMA 进行数据搬移。但是他们并不是 TZ aware 外设。

在 TrustZone 使能的环境中,这类主线主设备一般是 Securable 外设,他们并不具备像 GPDMA/LPDMA 那样的对 TrustZone AHB5 总线及 HNONSEC 信号直接支持的能力。

作为 Securable 总线主设备,他们的 TrustZone 特性通过 GTZC TZSC 的 PPC(Peripheral Protection Controller)来支持。具体说就是通过配置 TZSC 的 SECCFGRx寄存器可以让某个 Securable 外设具有安全或者非安全属性,通过配置 TSZC 的PRIVCFGRx 寄存器可以设置 Securable 外设的 PRIV/NPRIV 属性。

具体到这些总线主设备,当使用他们的 DMA 功能做数据搬移时,DMA 发出的读写操作在总线上的访问方式就取决于 SECCFGRx、PRIVCFGRx 对这个 IP 的配置。

以 SDMMC 举例

  • SDMMC 被配置为 NS+NPRIV 属性(一般这是外设上电默认所具有的安全属性),那么它的 DMA 访问就都是 NS+NPRIV 属性的。

  • SDMMC 被配置为 S+PRIV 属性,那么它的 DMA 访问都是 S+PRIV 的。

  • 当然也可以是另外的两种组合:NS+PRIV,S+NPRIV。

当这类 IP 的寄存器作为总线从设备被访问的时候,它的一般访问规则是:Secure IP只允许 Secure 访问,NonSecure IP 允许 Secure 或者 NonSecure 访问;PRIV IP 只允许PRIV 访问,NPRIV IP 允许 PRIV 或者 NPRIV 访问。图 6 给出了带 DMA 功能的Securable IP 的寄存器的安全访问规则,以及他们的 DMA 发出的 transaction 与 IP 自身的Secure/PRIV 属性的关系。类似于 TZ aware 的 DMA,当使用 link list 模式时,DMA 从memory 加载 link list 表项数据结构的时候,对 memory 的 Secure/PRIV 访问属性与 IP 自身的 Secure/PRIV 属性配置也一致。

6.png
▲ 图6 Securable IP 的 Secure/PRIV 属性及 DMA 访问具有的安全属性

3.3 TrustZone 环境下使用 DMA 的常见问题

本小节总结了几个在 TrustZone 项目中使用 DMA 遇到的问题,可能也是比较常见的一类问题,给开发者做参考。

3.3.1. 问题 1:NS App 无法驱动 DMA Channel

【问题现象】NS App 需要使用 DMA,用于 SPI 数据传输,应用中已经有相关初始化代码,但是代码运行后 App 无法控制 GPDMA Channel0。

【分析】初始化配置后观察 DMA Channel 的寄存器,发现 GPDMA_SECCFGR 的 bit0 为 1,也就是说 DMA Channel0 被设置为了 S 安全通道。这样 NS App 肯定就无法控制Channel0 的寄存器,肯定不能正常驱动 DMA Channel0。

进一步查看 S App 的代码,客户使用了 TF-M 用来提供安全侧的一系列服务。在 TF-M代码中缺省使能了针对 TrustZone 隔离的一些测试功能,其中包括 DMA Channel 访问的测试,而这部分代码会在初始化阶段将 DMA Channle0 配置为 S+PRIV 属性,这导致了NS App 无法驱动 DMA Channel0。

【解决方法】由于 S App 实际并不使用 DMA 实现应用功能,仅仅是为了测试目的,因此可以关闭这段与测试相关的置 DMA Channel0 为 Secure Channel 的初始化代码,保持 DMA Channel0 的 NonSecure 属性,这样 NS App 就可以正常操作这个 DMA 通道了。

3.3.2. 问题 2:NS App 中 DMA link list 模式无法正常工作

【问题现象】NS App 需要使用 SRAM1,片外 PSRAM,DCMI 以及 DMA 等。DMA 需要对PSRAM 数据进行搬移,并且使用了链表结构。在 S 工程中已经将需要的资源配置为NonSecure,且 NS App 能够正常运行起来。但是 DMA 无法按照 link list 的数据定义完成数据搬移。

【分析】通过调试发现,初始化后,DMA 的配置都可以正常完成,SRAM1 中也有正确的 link list 链表数据,但是当 DMA 完成第一组搬移后,需要从链表数据结构中加载下一组搬移配置时,链表数据加载完成后,对应 DMA 寄存器的值是 0。这说明 DMA 没有从 SRAM1 中正确加载链表数据。

由于 NS App 本身需要使用 SRAM1,而 NS App 是可以正常执行的,这说明 SRAM1已经配置为 NS 属性,允许 NS 访问。进一步查看代码发现,S 工程中对 SRAM1 的GTZC MPCBB 配置中,仅仅配置了 NS 属性,而 SRAM 上电默认具有 S+PRIV 属性,也就是说,经过 GTZC MPCBB 对 SRAM1 的配置,SRAM1 的属性为 NS+PRIV,因此不允许 NPRIV 的访问。而 GPDMA Channel 上电默认属性为 NS+NPRIV。那么他做任何访问都只能是 NS+NPRIV 属性。这解释了为什么 DMA 从 SRAM1 中加载链表数据结构时出错。

【解决方法】要解决问题这个问题,只要保证 DMA 的访问权限等于或者高于被访问目标允许的访问权限就可以。那么修改方法有两个:

  • 在 S 工程中将 SRAM1 配置为 NS+NPRIV 属性,NS App 代码保持不变。

  • 在 NS App 中添加代码,设置 DMA Channel 为 PRIV 属性。

这两种方法都可以让 NS App 中的 DMA 成功完成链表模式的数据搬移操作。

在这个小节的内容中我们可以看到 DMA 在 TrustZone 架构下有额外的安全访问配置,当然这些配置可以通过直接手写代码完成,其实也可以通过 STM32CubeMX 工具在图形界面中完成所有的配置。这样产生的初始化代码更加容易保持配置的一致性。在第 5 章节中也会对这部分做出简要介绍。

来源:STM32

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

围观 31

在工业4.0与智能制造的大背景下,工业物联网发展迅猛,越来越多的设备具备了连接能力,大量数据在物联网与互联网之间传递,这使得信息安全成为嵌入式联网设备越来越需要关注的话题。信息安全涉及的知识和技术可能非常广泛而复杂,在嵌入式系统中实现安全性往往成为开发者的一个负担。有没有方法帮助开发者减轻这样的负担?这是ST试图通过STM32Trust来回答的问题,STM32Trust是一项专注于提高设备安全性以及为非专家开发者提供安全专业知识而带来的所有软件和硬件解决方案的计划。

开发人员可能需要让产品的安全设计能够满足安全认证的要求,与此同时也希望更快地实现设备的信息保护,帮助工程师意味着我们要让ST的工具以及解决方案更易于使用。为此ST采取的举措之一就是在2023年初宣布的Secure Manager安全管理器解决方案,九月份Secure Manager安全管理器已经正式发布了第一个版本,STM32H5便是Secure Manager所支持的第一款STM32 MCU。让我们来快速回顾一下什么是安全管理器,它能如何帮助到开发者在他的产品中快速实施安全保护。

STM32 TEE可信执行环境解决方案Secure Manager安全管理器

Secure Manager是ST率先推出的以二进制形式提供的TEE可信执行环境(Trusted Execution Environment)解决方案,也是能够在系统级别达到SESIP和PSA 3级安全认证目标的(先进)解决方案。由于该方案提供的是二进制文件而非源代码,可以省去大量的开发和集成时间,大大加快产品的认证过程。Secure Manager采用可下载软件包的形式提供,其中包含二进制文件、库、代码实现和文档等。

目前Secure Manager已经发布了支持STM32H5的第一个正式版本,欢迎访问网址https://www.st.com/en/embedded-software/stm32trustee-sm.html 了解更多有关STM32 TRUSTEE Secure Manager的详细信息,也可以从该网页下载X-CUBE-SEC-M-H5软件包。

最易获取的STM32安全解决方案

以前,对于安全保护方案,ST提供的是STM32的硬件特性以及以源代码形式交付的软件(例如获得了PSA和SESIP Level3认证的STM32U5 TF-M方案),这意味着开发人员必须自己完成一些客制化和适配集成的工作,如果产品有认证需求,可能还需要再次对代码进行验证,因为很多时候,原有的认证只有在代码保持不变的情况下才继续有效。而以二进制文件形式提供的Secure Manager安全管理器恰恰解决了这个问题。此外,Secure Manager安全管理器提供了一个交钥匙解决方案,可以自动启用并设置安全启动功能ST-iRoT和ST-uROT,并且直接从TrustZone的安全侧提供安全存储、加解密和Attestation等安全功能,实施安全解决方案的过程变得格外简单。开发者只需要关注如何调用相关API使用安全管理器已经提供的功能,而无需开发安全侧的服务,他们可以将更多的精力用于客户应用程序的开发。

此外,客户不必担心这个安全解决方案的维护问题,Secure Manager完全由ST拥有并进行维护,我们将会在需要的时候编写和发布新版本或者补丁。由于工作流程大大简化,即使是对于在安全方面拥有丰富专业知识的团队,这样的方案也会收到欢迎。事实上,除非产品有着非常特殊的需求,否则使用ST的二进制文件可以节省大量的时间和资源。Secure Manager还提供了安全管理器访问工具包(或SMAK--Secure Manager Access Kit),以帮助开发人员创建运行在TrustZone环境非安全侧的应用程序,并使用安全管理器的服务。

面向高级用户的全面的解决方案

ST在设计新的Secure Manager方案时也考虑到了灵活性,因此,允许经验丰富的开发人员自定义他们的解决方案。除了SMAK,Secure Manager还提供开发工具包(SMDK--Secure Manager Development Kit),可以帮助开发者创建复杂的可信应用程序(TA – Trusted Application)。例如,一个开发指纹算法的团队可以使用SMDK将算法变成一个TA 可信应用模块,这个可信应用可以装载到Secure Manager安全管理器中,成为运行在TrustZone安全侧的一个特权级可信应用,非安全侧的应用程序能够调用这个可信应用提供的服务。

此外,得益于ST-iRoT和Secure Manager提供的服务,程序员可以在STM32H5中存储密钥和证书,让嵌入式系统轻松注册并连接到云服务器,免去使用外部硬件安全模块等繁琐问题。Secure Manager的加解密API还允许程序员使用密钥对敏感数据进行加密和解密,而无需访问密钥本身,从而保护它们免受攻击。

1.jpg

上图是STM32 Trusted Execution Environment 可信执行环境Secure Manager安全管理器的框架示意框图。图的右半边属于TrustZone的安全侧,其中蓝色的部分是安全管理器默认提供支持的部分,包括安全启动ST-iROT/ST-uROT和基础安全服务,无需开发;粉红色的部分则是基于SMDK开发的可以安装在安全管理器中运行的扩展安全应用,这部分客户可以自己开发,也可以使用来自第三方的开发好的安全应用。使用STM32H5 的安全管理器,意味着从安全启动、安全升级到默认的安全应用都已经准备好,无需开发与适配。图的左半边属于TrustZone的非安全侧,其中黄色的部分才是客户需要自己开发的应用业务逻辑。

近期STM32MCU生态系统中的STM32CubeProgramer和STM32CubeMX等工具也进行了更新,发布了新版本,其中增加了支持STM32H5的新安全特性和Secure Manager的一系列功能,配合安全管理器SMAK的首个正式版本发布。例如STM32的初始化软件STM32CubeMX中增加了启动路径配置选项,可以指导开发人员激活某些安全功能,如STM32H5的iRoT,生成可以直接配合Secure Manager的应用工程框架等。最新的STM32Cube工具也可以很方便地从STM32 Developer Zone入口快速下载。(附下载链接)

最后再给大家推荐几个STM32MCU的wiki链接,方便读者详细了解STM32H5的安全特性、Secure Manager解决方案、以及如何在STM32CubeProgrammer、STM32CubeMX等工具中配置和使用STM32H5的安全特性、功能与解决方案。

来源:STM32

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

围观 34

01、前言

STM32 MCU 新产品的早期用户有时候会遇见工具链还在完善中的情形,例如,一部分STM32 工具已经支持该产品,而另外一部分 STM32 工具还在更新中。具体到 Keil 用户,用户有可能可以使用 STM32CubeProgrammer 进行下载,但是 Keil 编译器中支持该产品系列的软件 Pack 还需要一些时间才会被更新。从而,用户能够使用 Keil 编译器进行编译甚至调试,但没法直接在 Keil 环境中对新产品进行下载。对此,用户可以选择等待,也可以自行扩展 Keil 的 FLM 来支持该产品。但考虑到用户产品开发的时间限制以及新的STM32 正式 Pack 很快就会发布,更简单快速的一种解决方案是在 Keil 中直接使用STM32CubeProgammer 在进行调试前下载。

02、步骤

这里以一个 NUCLEO-H723ZG 的 CRC_Example 为例。它是 STM32Cube 包中的一个完善的工程,可以正常使用配套的 Pack 进行编译下载调试。我们只是使用这个工程说明如何直接使用 STM32CubeProgrammer 进行 Flash 下载,没有其他特别的含义。首先,在 Keil 工程界面里,选择[Flash]->[Configure Flash Tools]菜单。

1.png

图1.配置菜单

或者在工程浏览器的工程名字上点击右键,选择[Options]然后选择[Utilities]

2.png

图2.工程选项

你可以看到如下菜单,说明该工程默认使用 Pack 中的 FLM 进行下载。

3.png

图3.配置工具选项

我们将其切换成[Use External Tool for Flash Programming]。

在[Command]中选择 STM32_Programmer_CLI.exe,它会自动填上所在的全路径,例如:

C:\ProgramFiles\STMicroelectronics\STM32Cube\STM32CubeProgrammer\bin\STM32_Programmer_CLI.exe 
在[Agruments]中输入使用 ST-Link 以及文件名参数,如下: 

-c port=swd -w #L 

STM32_Programmer_CLI 的更多用法,例如,在调试前修改某个特定选项字节,可以参考STM32CubeProgrammer 用户手册 UM2237。 

这里值得一提的是 Keil #L 参数的使用。为了该命令行的通用性,我们应该使用编译器工具提供的一些参数间接指向所需要烧录的路径及文件,而不是硬编码。这样,工程选项的改动,不影响该命令行;而且该命令行也可以在多个工程中复制使用。#L 以及其他类似参数的含义可以在 Keil 联机帮助中搜索 “ Key Sequence for Tool Parameters ”。设置界面如下:

4.png

图4.配置烧写指令

其中[Run Independent]的含义是,是否让 Keil 不需要等待该命令行执行完毕。我们希望按顺序执行,所以该选项没有勾上。用户可以切换此选项观察效果。

03、效果

这时候如果直接选择[Debug]

5.png

图5. 调试

则会发现 Flash 下载并没有发生。确实,这是其中不够完美的地方。但是如果选择[Download]

6.png

图6.下载

则会发现 Keil 调用 STM32CubeProgrammer 命令行进行当前工程的下载,如下所示:

7.png

图7.命令日志

然后,用户可以使用[Debug]启动调试,一切正常。所以,简单的方法就是,用户在调试前,按下 F8。这样比使用 Pack 的 FLM 并没有麻烦多少。

04、小结

本文提供了在 Keil 中使用STM32CubeProgrammer 来进行调试前下载固件的方法,适合 STM32 MCU 新产品的早期用户在使用 Keil 时进行参考。

来源:STM32单片机

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

围观 34

01、前言

客户在使用 STM32H7 的时候,想要使用 DWT 计数来测量代码执行时间,评估执行效率。客户发现在重新上电或 reset 后,无法启用 DWT 进行计数。

02、调研

在 ARMv7-M 架构中有个 DEMCR 寄存器,这个寄存器可以控制 DWT 的使能。在power-on reset 后这个寄存器所有位的值都为 0。而当 bit[24]为 0 时,DWT 和 ITM 模块都是 disabled 的。所以为了启用 DWT 模块,必须将 DEMCR 的 bit[24]置为 1。如图 1 所示:

1.png

图1.DEMCR 寄存器

03、启用 DWT 进行计数

STM32H7 基于 Arm Cortex-M7 内核,而 Cortex-M7 是 ARMv7-M 架构,所以 H7 在配置 DWT 模块之前需要将 DEMCR 的 bit[24]置位。在基于 Cortex-M7 的芯片中,需要使用DWT-LAR 来解锁 DWT(其他核可能不需要,应具体分析),然后对 DWT_CTRL 进行相应使能即可。 

在 CMSIS 文件中已经提供了相关寄存器的宏定义(例如在“core_cm7.h”文件中包提供了 DWT 和 DEMCR 的宏定义),我们可以使用这些宏定义方便的进行配置,如图 2所示:

2.png

图2.core_cm7.h 文件

示例(如下):使用 DWT 测量代码执行所用的时钟 cycle 数。

3.png

4.png

04、小结

在使用 ARMv7-M 架构的 STM32 时,对 DWT 配置之前应确保 DEMCR 中的 bit[24]已经被配置(使能 DWT),然后才能使用 DWT。

来源:STM32单片机

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

围观 15

一、引言
STM32 MCU 中较新的产品系列例如 STM32L5、STM32U5 采用了 ARM Cortex V8M 的 CM33 内核,并引入了 TrustZone 概念。在此基础上,从内核到存储器再到外设等设计了完整的支持 TrustZone 架构的系统隔离机制。

在新的 TrustZone 架构下,软件的开发由原来的单一工程,变成了 Secure 安全和 NonSecure 非安全两个工程的联合开发,系统上电首先从 Secure 工程开始运行,完成必要初始化之后跳转至 NonSecure 工程运行,之后 NonSecure 工程还可以通过调用 Secure 工程经由 NSC(Secure NonSecure Callable)区提供的 API 调用 Secure 工程的函数。

由于此时系统的所有资源,包括 Memory、外设等等都区分了安全和非安全属性,而CPU 也区分安全和非安全运行状态,其对应的安全或非安全代码及其使用的数据都需要有相应的存储空间存放,且该存储空间需要具有相同的安全或者非安全属性,否则代码无法正常运行。因此,在 TrustZone 架构下首先需要针对不同物理区间做地址安排及相应安全属性的正确配置。对于 V8M 内核来说,这涉及到 SAU/IDAU 的配置,且取指令与取数据可能有不同的访问规则,同时指令以及数据是否能够从 memory 中正确取得,除了和 SAU/IDAU 的配置有关以外,还与 Memory 自身的安全属性配置有关。

本文将对 SAU/IDAU 配置,Memory 的自身安全属性配置,以及内核访问指令与数据时的安全访问规则加以阐述,希望可以帮助相关开发者更好地理解 V8M TrustZone 的架构以及在 STM32 中的实现,同时,还会列举一些与 memory 的 TrustZone 安全配置相关的常见问题及分析方法,给开发者做参考。

详阅请点击下载:《STM32 TrustZone 开发调试技巧 | 地址安全区及资源安全属性配置》

来源: STM32

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

围观 41

新开发者软件为STM32H5设计,利用ST的Secure Manager安全软件,简化物联网设备与AWS平台的安全连接

2023年10月10日,中国--服务多重电子应用领域、全球排名前列的半导体公司意法半导体(STMicroelectronics,简称ST;纽约证券交易所代码:STM)日前在STM32Cube开发工具包内新增一款软件,以简化高性能物联网(IoT)设备与AWS云的连接。 

1.jpg

意法半导体发布了X-CUBE-AWS-H5扩展包,让物联网设备能够无缝、安全地接入AWS云。在这个软件扩展包中有一套为专门终端设备STM32H5系列高性能微控制器设计的软件库和应用代码示例。

 该解决方案基于FreeRTOS开源实时操作系统和意法半导体的Secure Manager嵌入式安全软件,可以与最近发布的STM32H5探索套件配套使用,让开发人员能够将基于STM32H5的物联网设备原型轻松安全地连接到AWS IoT Core物联网平台。 

STM32市场总监Daniel Colona表示:“STM32H5是为下一代物联网边缘设备准备的,为市场带来以有限的能耗预算处理复杂应用的性能。STM32Cube生态系统帮助开发人员释放STM32H5的强大功能,加快应用开发速度,并用我们最新的软件安全连接到AWS云中强大的存储和数据分析服务。”

 STM32H5 是性能最强的Arm®Cortex®-M33 MCU系列之一。无法改变的设备身份是在意法半导体工厂内写进设备之中。配合意法半导体的安全管理器,这个方法可以简化智能设备在AWS云端的注册过程,而且无需购置昂贵的安全基础设施,在生产过程中保护物联网设备身份。 

在生产期间和安装现场,设备还可以享受第三方服务提供商的远程网络开通和证书管理服务。 

Secure Manager的隔离功能可以保护多方共同持有的知识产权,又称多方持有IP保护。这个软件属于一个保障全面的安全服务,在开发制造过程中和安装现场,保护STM32应用开发者和合作伙伴资产的秘密和完整性。 

这个软件非常适合边缘AI的使用场景,神经网络模型在边缘设备上运行,Secure Manager提供安全保护,并通过云完成进一步的人工智能训练和安全更新。The STM32Trust TEE Secure Manager让系统安全变得更强、更简单。 

总体而言,STM32Cube生态系统配合STM32H5微控制器为开发人员开发符合未来法规和标准的物联网应用提供了一个强大而安全的平台。STM32H5于2023年3月推出,是第一个支持Secure Manager的微控制器,目标应用是PSA Certified level 3 和 SESIP3认证。

来源:STM32单片机

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

围观 12

问:玩转STM32 - 使用 STM32 来控制 NeoPixels

目前,诸如 Arduino  Feather 等高级开发平台已经提供了出色的支持,可以通过易于使用的库和普遍使用的示例代码与NeoPixel LED 灯带矩阵 等相连接。然而,更高级的平台(例如 STM32 开发板 )通常缺乏相同水平的支持。因此,希望将NeoPixels整合到项目中的 开发人员需要全面了解NeoPixel通信协议以及如何克服它所带来的挑战。




1.gif

NeoPixels

Adafruit 推出的极受欢迎的可寻址全彩LED灯“NeoPixels”系列分为RGB和RGBW两个种类。尽管二者都将红、绿和蓝色LED与驱动器芯片相集成,但RGBW组件还集成了第四个纯白色的LED。可以使用类似的单线串行接口来控制这两种类型的NeoPixel,其时间值和数据结构仅存在微小的差异。

WS2812

RGB NeoPixels实际上是WS2812智能控制LED,包括数据信号输入引脚(DIN)和数据信号输出引脚(DOUT)。这允许多个LED级联并且只用一个数据线进行控制。链中的第一个LED负责处理从MCU接收到的前三个字节数据,然后将后续的数据简单地转发给DOUT引脚,该引脚可以连接到另一个LED的DIN引脚。LED将以此方式继续向下传递数据,直到它们接收到复位信号为止(即,DIN线在一段时间内持续保持低电平状态)。传输的字节按照图1所示的协议进行组织。第一个字节(G7-G0)表示绿色LED的8位PWM强度,其中0x00是完全关闭,0xFF是完全打开。类似地,第二个字节(R7-R0)用于控制红色LED的强度,第三个字节(B7-B0)用于控制蓝色LED的强度。

2.jpg

图 1 : WS2812 LED的3字节数据协议的结构

这些24位数据都是通过改变方波的脉冲宽度来进行编码的,如图2所示。请注意,无论发送代码0还是代码1,方波的周期仍保持在1.25μs。对于WS2812,使数据线保持低电平至少50μs即可生成复位信号。另请注意,图2中显示的计时值具有±0.15μs的公差。

3.jpg
图2:WS2812 LED的0和1位的计时图

一种截然不同的组件,NeoPixels的RGBW种类实际上是SK6812智能控制LED,采用与WS2812 LED相同的运作原理。然而,由于它们包含第四个LED,因此实施了图3所示的4字节数据协议。与图1相比,唯一的区别在于数据的串联字节(W7-W0),该字节指定了白色LED的8位PWM强度。

4.jpg

图 3 : SK6812 LED的4字节数据协议的结构。

图4展示了SK6812控制信号的时间值,同样与WS2812略有差别(不过仍在±0.15μs的公差范围内)。请注意,这两种代码的方波周期均保持不变,都为1.2μs。此外,SK6812的复位信号长度为80μs ,而非50μs。

5.jpg
图4:SK6812 LED的0位和1位的计时图。

步骤

由于NeoPixel的控制信号对计时要求非常严格,因此除非使用汇编语言,否则无法通过简单的比特带宽方法产生此信号。虽然还有许多其他方法可以利用各种MCU外设、外部硬件或其组合来生成该信号,但其中最直接的方法是配置MCU定时器来生成PWM输出信号。这是因为,如上一部分中所述,NeoPixel控制信号只是一种固定频率的PWM信号,采用不同的占空比表示0位和1位。为了以与传输协议相同的速率高效地在这两个占空比之间进行切换,还必须配置DMA流来管理更新。尽管这种方法可能是内存效率最低的方式,但它易于理解、CPU高效并且易于实施(得益于STM32Cube环境)。

以下应用程式利用STM32CubeIDE(版本1.8.0)、NUCLEO-F401RE开发板和RGBW 5x8 NeoPixel Shield实现上述的方法。不过,这些步骤可以轻松地推广到任何STM32 MCU/板和NeoPixel产品上。假定我们已经创建了一个STM32CubeIDE项目。如需使用其他IDE,你可以改为使用独立的STM32CubeMX代码配置器工具,将项目导出到所需的开发平台上。

1.配置PWM

a. 先打开STM32CubeMX配置.ioc 文件(如果还未打开的话)。随后,STM32CubeIDE将切换到*器件配置工具(*Device Configuration Tool ) 视图,供你配置MCU。

b. 将定时器通道备用功能分配给选定的GPIO引脚,以与NeoPixel进行连接。所选定时器通道应该能够生成PWM输出。图5显示了我的项目中的相关部分,我选择了引脚PB10,并将它分配给定时器2、通道3(TIM2_CH3)功能。

6.jpg

图5:将连接到DIN的GPIO引脚配置为定时器通道

c. 从左侧的组件列表中选择上一步中确定的定时器外设,以打开模式和配置(*Mode and Configuration ) 面板。在模式(*Mode ) 面板中,选择“内部时钟”作为时钟源,并从适当的定时器通道的下拉列表中选择“PWM生成CHx”。在图6中,定时器2、通道3已设为“PWM生成CH3”模式,因为我在上一步中选择了TIM2_CH3备用功能。请注意,在完成此步骤后,关联的GPIO引脚应在引脚排列视图中从黄色变为绿色。

d. 在定时器的*配置(*Configuration ) 面板中,验证“预分频器”和“脉冲”值是否都设置为0。计数器周期,即自动重载寄存器(ARR),需要进行设置以得到所需的PWM周期(如果使用RGB WS2812 LED,则为1.25μs;如果使用RGBW SK6812 LED,则为1.2μs)。这将取决于定时器外设输入的速率。只需将所需的PWM周期除以时钟周期,并减去1即可得到此值(减去1是因为定数器从0开始)。就我的器件而言,该公式得出的ARR值为99.8,我将其四舍五入为100(图6)。请参见下文,了解有关计算理想ARR值的详细说明。

7.jpg
图6:将所选定时器通道配置为PWM输出

计算ARR值

假设定时器“预分频器”值设为0,可以很容易的计算出ARR值

8.jpg

具体来说,ARR值等于PWM信号周期除以定时器外设的时钟信号周期。我们知道,根据使用的NeoPixel类型不同,TPWM可以是1.25μs或1.2μs(例如本例中,TPWM=1.2μs)。要确定Ttimer,你需要查阅器件的规格书,确定定时器外设连接到哪个总线。规格书可以在ST的网站上找到或STM32CubeIDE会随附提供:选择帮助>目标器件文档和资源( Help > Target Device Docs and Resources ) 。然后,在MCU 选项卡下选择规格书,如图7所示。

9.jpg

图 7 : 查找器件规格书

在我使用的MCU(STM32F401RE)规格书中,器件框图中显示我的定时器(TIM2)已连接到APB1(见图8)。

10.jpg

图 8 : STM32F401xD/xE的部分框图(源自DS10086

图9介绍了:通过切换到STM32CubeIDE中的*时钟配置(*Clock Configuration)选项卡,我们可以发现TIM2的时钟频率为84MHz11.jpg

12.jpg

图 9 : 确定定时器时钟频率
因此,
13.jpg

为了使PWM周期尽可能接近NeoPixel控制信号的周期,我们四舍五入至最接近的整数并得到 ARR=100 。

2.配置DMA

a. 从组件列表中选择DMA外设。

b. 在配置(Configuration) 面板的DMA1 选项卡下,点击添加 ( Add ) 按钮。在下拉菜单中,选择你的定时器/通道组合。在我的项目中,我选择了“TIM2_CH3/UP”。

c. 针对该新的DMA请求,将方向改为“内存到外设”。

d. 同时,将优先级改为“非常高”。

e. 验证默认的DMA请求设置是否与图10中显示的相匹配。

f. 保存.ioc 文件,以生成项目代码。

14.jpg

图 10 : 配置DMA流,以便有效更新PWM信号的占空比

3.编写代码

在main.c 文件中,按从上到下的顺序编写,本部分展示了一个简单的示例应用,用于测试NeoPixel LED的全彩能力。此处提供了两个版本的main() 函数,一个用于RGB WS2818 LED,另一个用于RGBW SK6812 LED。

a. 在main.c 文件的私有typedef部分,你可以创建一个新的数据类型,以便轻松访问单个LED颜色值以及整个NeoPixel数据结构(如图1和图3所示)。列表1提供了RGB和RGBW NeoPixel组件的typedef。此代码应粘贴在/* USER CODE BEGIN PTD */ 和/* USER CODE END PTD */ 注释之间。

列表 1 : 为RGB WS2812和RGBW SK6812 LED自定义数据类型

typedef union

{

struct

{

uint8_t b;

  uint8_t r;

uint8_t g;

} color;

uint32_t data;

} PixelRGB_t;

typedef union

{

struct

{

uint8_t w;

uint8_t b;

uint8_t r;

uint8_t g;

} color;

uint32_t data;

} PixelRGBW_t;

b. 更改“脉冲”寄存器(也称为CCRx)的值,这样可以改变PWM波形的占空比。因此,我们必须计算适当的CCRx值,以实现使用的NeoPixels所需的代码0和代码1方波(无论是在图2还是图4中所示的那些)。对于RGB WS2812 LED,这些值计算如下:

ZERO=(ARR+1)(0.32)

ONE=(ARR+1)(0.64)

对于RGBW SK6812 LED,其计算过程稍有不同。

ZERO=(ARR+1)(0.25)

ONE=(ARR+1)(0.5)

当然,这些计算出的值应该四舍五入到最接近的整数。在 main.c 文件的私有定义部分,为每个值创建一个#define指令(请参见以下图11中的示例)。

c. 除了CCRx值之外,还应在私有定义部分中定义控制的NeoPixel LED数量和DMA缓冲区大小。如图11所示,只需将LED的数量乘以相应的NeoPixel数据结构中的位数即可(回想图1和图3)。还必须分配一个额外的缓冲区元素,因为最后一个CCRx值应为零(复位信号)。

15.jpg

图 11 : WS2812和SK6812 LED的私有定义

d. 将列表2中提供的DMA完成回调函数添加到/* USER CODE BEGIN 0 /和/ USER CODE END 0*/之间的私有用户代码部分。务必将 TIM_CHANNEL_x 更改为步骤1c中配置的通道。

列表 2 : HAL_TIM_PWM_PulseFinishedCallback() 函数的实施

void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)

{

HAL_TIM_PWM_Stop_DMA(htim, TIM_CHANNEL_x);

}

e. 最后,必须将应用代码添加到main() 函数中。列表3提供了一个使用WS2812 LED的示例main() 函数,而列表4提供了使用SK6812 LED的类似示例main() 函数。请注意,HAL_TIM_PWM_Start_DMA() 函数的TIM_CHANNEL_x 参数必须再次进行修改,以匹配步骤1c中配置的通道。

列表 3 : RGB WS2812 LED的示例main() 函数

int main(void)

{

/* USER CODE BEGIN 1 */

PixelRGB_t pixel[NUM_PIXELS] = {0};

uint32_t dmaBuffer[DMA_BUFF_SIZE] = {0};

uint32_t *pBuff;

int i, j, k;

uint16_t stepSize;

/* USER CODE END 1 */

/* MCU Configuration--------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */

HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */

SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */

MX_GPIO_Init();

MX_USART2_UART_Init();

MX_DMA_Init();

MX_TIM2_Init();

/* USER CODE BEGIN 2 */

/* USER CODE END 2 */

/* Infinite loop */

/* USER CODE BEGIN WHILE */

k = 0;

stepSize = 4;

while (1)

{

/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

for (i = (NUM_PIXELS - 1); i > 0; i--)

{

pixel[i].data = pixel[i-1].data;

}

if (k < 255)

{

pixel[0].color.g = 254 - k; //[254, 0]

pixel[0].color.r =  k + 1;  //[1, 255]

pixel[0].color.b = 0;

}

else if (k < 510)

{

pixel[0].color.g = 0;

pixel[0].color.r = 509 - k; //[254, 0]

pixel[0].color.b = k - 254; //[1, 255]

j++;

}

else if (k < 765)
{

pixel[0].color.g = k - 509; //[1, 255];

pixel[0].color.r = 0;

pixel[0].color.b = 764 - k; //[254, 0]

}

k = (k + stepSize) % 765;

// not so bright

pixel[0].color.g >>= 2;

pixel[0].color.r >>= 2;

pixel[0].color.b >>= 2;

pBuff = dmaBuffer;

for (i = 0; i < NUM_PIXELS; i++)

{

for (j = 23; j >= 0; j--)

{

if ((pixel[i].data >> j) & 0x01)

{

*pBuff = NEOPIXEL_ONE;

}

else

{
*pBuff = NEOPIXEL_ZERO;

}

pBuff++;

}

}

dmaBuffer[DMA_BUFF_SIZE - 1] = 0; // last element must be 0!

HAL_TIM_PWM_Start_DMA(&htim2, TIM_CHANNEL_x, dmaBuffer, DMA_BUFF_SIZE);

HAL_Delay(10);

}

/* USER CODE END 3 */

}

列表 4 : RGBW SK6812 LED的示例main() 函数

int main(void)

{

/* USER CODE BEGIN 1 */

PixelRGBW_t pixel[NUM_PIXELS] = {0};

uint32_t dmaBuffer[DMA_BUFF_SIZE] = {0};

uint32_t *pBuff;

int i, j, k;

uint16_t stepSize;

/* USER CODE END 1 */

/* MCU Configuration--------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */

HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */

SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */

MX_GPIO_Init();

MX_USART2_UART_Init();

MX_DMA_Init();

MX_TIM2_Init();

/* USER CODE BEGIN 2 */

/* USER CODE END 2 */

/* Infinite loop */

/* USER CODE BEGIN WHILE */

k = 0;

stepSize = 4;

while (1)
{

/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

for (i = (NUM_PIXELS - 1); i > 0; i--)

{
pixel[i].data = pixel[i-1].data;

}

if (k < 255)

{

pixel[0].color.g = 254 - k; //[254, 0]

pixel[0].color.r =  k + 1; //[1, 255]

pixel[0].color.b = 0;

pixel[0].color.w = 0;

}

else if (k < 510)

{

pixel[0].color.g = 0;

pixel[0].color.r = 509 - k; //[254, 0]

pixel[0].color.b = k - 254; //[1, 255]

pixel[0].color.w = 0;

j++;

}
else if (k < 765)

{

pixel[0].color.g = 0;

pixel[0].color.r = 0;

pixel[0].color.b = 764 - k; //[254, 0]

pixel[0].color.w = k - 509; //[1, 255]

}

else if (k < 1020)

{

pixel[0].color.g = k - 764; //[1, 255]

pixel[0].color.r = 0;

pixel[0].color.b = 0;

pixel[0].color.w = 1019 - k; //[254, 0]

}

k = (k + stepSize) % 1020;

// 50% brightness

pixel[0].color.g >>= 2;

pixel[0].color.r >>= 2;

pixel[0].color.b >>= 2;

pixel[0].color.w >>= 2;

pBuff = dmaBuffer;

for (i = 0; i < NUM_PIXELS; i++)

{

for (j = 31; j >= 0; j--)

{

if ((pixel[i].data >> j) & 0x01)

{

*pBuff = NEOPIXEL_ONE;

}

else

{

*pBuff = NEOPIXEL_ZERO;

}

pBuff++;

}

}

dmaBuffer[DMA_BUFF_SIZE - 1] = 0; // last element must be 0!

HAL_TIM_PWM_Start_DMA(&htim2, TIM_CHANNEL_x, dmaBuffer, DMA_BUFF_SIZE);

HAL_Delay(10);

}

/* USER CODE END 3 */

}

该项目现在应该能够成功构建,并支持你在器件上运行代码了。

结论

使用逻辑分析仪捕获了上面提供的RGB和RGBW配置生成的控制信号。分别如图12和图13中所示。请注意,它们与图2和图4中指定的预期输出相匹配。

16.jpg

图 12 : 生成的WS2812控制信号(正在发送0b0011……)

17.jpg

图 13 : 生成的SK6812控制信号(正在发送0b0010……)

来源:得捷电子DigiKey

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

围观 31

01、前言

有客户反馈,使用STM32F4的TIM2结合DMA,产生的PWM波形不符合预期,但是相同的配置使用在TIM3上,得到的PWM波形就是符合预期的。其代码和配置都是从F1移植过来的,在F1上使用TIM2是没有问题的,对于F4的TIM2发生的问题,客户一直没有找到根本原因。

02、实验

根据客户的反馈,我们进行了实验。

硬件:STM32F401RE-NUCLEO

在STM32CubeMX中,将TIM2和TIM3所有参数均做相同的配置,其中配置DMA两端均为halfword长度。

1.png

2.png

生成代码,并定义两个数组如下图所示:

3.png

在主函数中开启Timer。

4.png

我们可以发现,实验结果如客户反馈的,TIM2输出的PWM是不正确的,TIM3输出的PWM是正确的。

5.png

03、分析

我们的实验中,TIM2和TIM3的配置是完全一样的,即使传输相同的数据,得到的PWM波形也是不同的。为此我们比较了TIM2和TIM3的硬件属性,可以很容易查看出,TIM2的计数器是32bit的,而TIM3的计数器是16bit的。

我想我们已经知道答案了,TIM2的计数器是32bit的,但是我们配置的DMA是halfword长度,这在AHB总线上解析数据时产生了非预期的结果。在调试界面我们也能看到,当问题发生时,TIM2的CCR1竟然比ARR的值要大,或者出现异常值,所以出现异常波形。

6.png

根本原因在于,对于大部分STM32系列,主设备基于AHB外设进行寻址是不支持byte/half-word传输的,总线会强制将数据转化为32bit传送到总线上,这就是为什么我们看到CCR1的高半字和低半字的值是相同的原因。

当我们将TIM2的DMA外设端修改为word长度,并将内存数组定义为32bit,再次实验,可以发现PWM的波形就是正常的了:

7.png

8.png

9.png

04、小结

因为F103上没有32bit计数器的Timer,所以客户在F103上并没有出现类似的问题。在使用DMA访问经过AHB转APB的桥接外设时,我们要注意DMA对外设的访问宽度配置问题。

来源:STM32单片机

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

围观 68

基于STM32分析栈、堆、全局区、常量区、代码区、RAM、ROM

cathy的头像

在一个STM32程序代码中,从内存高地址到内存低地址,依次分布着栈区、堆区、全局区(静态区)、常量去、代码区,其中全局区中高地址分布着.bss段,低地址分布着.data段。

页面

订阅 RSS - STM32