• 分得清自动驾驶中的DCU、MCU、MPU、SOC吗?

    本文探讨自动驾驶中的DCU、MCU和MPU在电子电气架构中的作用,比较了分布式与集中式架构的优势,以及ADAS系统从L0-L2+的发展历程。

    09-04 307浏览
  • 简述STM32Cortex-M3

    总结了STM32的一些基本知识,希望能为STM32的学习​打好基础。

    08-20 155浏览
  • 嵌入式开发中的C语言特性

    本文面向的,正是使用单片机、ARM7、Cortex-M3这类微控制器的编程人员。从C语言特性入手,讨论如何编写优质的嵌入式C程序。

    08-20 136浏览
  • 如何优化STM32项目的内存使用?

    本文对STM32启动文件startup_stm32f10x_hd.s的代码进行讲解,此文件的代码在任何一个STM32F10x工程中都可以找到。

    08-07 141浏览
  • 如何破解STM32F103芯片?

    本文介绍ARM系列STM32F103芯片的解密方法,其内核是Cortex-M3,内存从16K-512K都有。 该芯片主要应用非常广泛,日常消费类电子产品,工控设备,电机驱动,变频器,打印机等等。 一般来说,攻克芯片解密的方法,都是采用物理破解的方法,即重新改变芯片内部线路的方法,这种方法所读取出来的程序正确率为100%。针对此款STM32F103我们也是采用此方法。另外推荐下关于单片机程序破解的另一篇内容:单片机程序被破解了? 在芯片解密行业中,最正确的解密方法就是采取硬件解密的方法,即用特定的溶脂溶解开芯片,让其晶片裸露出来,在操作这一步的时候,也是需要有一定的技巧,当然,在操作这一步的时候,有时候,也可能会把芯片溶解坏,就是把线溶解断了,这样芯片就完全用不了了,这就是为什么在解密的时候,最好可以提供2颗母片,就是防止一颗失败无法进行。 当然,如果只有一个母片的时候,就可以拿去绑定厂重新绑定,但这样的话,就会产生一定的费用,时间上也大大加长了,一般绑定一次的话需要一周的时间,如果绑定测试不通过的话,那么就要再次拿去绑定,如果是这么一种情况的话,技术人员就会重新再开一个芯片,争取在最短的时间内将程序提取出来。以下就是开完片后的芯片: 当晶片裸露出来后,我们就要用到高倍显微镜和FIB(聚焦离子束设备),用这两种设备,查找芯片的加密位置,通过改变其线路的方法,将加密芯片变为不加密的一个状态,然后再用编程器,将芯片内部的程序读取出来。 像这种读取芯片程序的方法,其正确性是100%。为什么呢?因为我们知道,芯片的程序一般是首先写了C语言,在写入芯片之前,要将C语言反汇编成汇编语言,当汇编语言通过编程器写入芯片内部后,就成了机器码,而我们解密的方法,就是把最终的程序读取出来,所以,一般解密出来的程序的格式都是机器码。 读取出来的二进制代码,如果没有软加密(UID绑定加密),那烧录到新的芯片中是完全可以正常工作的,如果存在软加密,那就需要去除软加密。

    07-19 164浏览
  • 嵌入式系统软件开发内存对齐的理由

    做嵌入式系统软件开发,经常在代码中看到各种各样的对齐,很多时候我们都是知其然不知其所以然,知道要做好各种对齐,但是不明白为什么要对齐,不对齐会有哪些后果,这篇文章大概总结了内存对齐的理由。 CPU体系结构和MMU的要求 目前有一些RISC指令集的CPU不支持非对齐的内存变量访问操作,比如 MIPS/PowerPC/某些DSP等等,如果发生非对齐的内存访问,会产生unaligned exception 异常。 ARM指令集是从ARMv6(ARM11)开始支持非对齐内存访问的,以前老一点的ARM9的CPU也是不支持非对齐访问的。ARM指令集支持的部分特性迭代如下: 尽管现代的ARMv7 ARMv8 指令集的Cortex-AXX系列CPU都支持非对齐内存访问,但是考虑到如下图所示现代SOC芯片里面多种异构CPU协调工作的情况,主CPU用于跑Linux/Android操作系统的ARM64可以支持非对齐内存访问,但是SOC里面还有其它不知道体系结构和版本的协CPU(可能是MIPS, ARM7,Cortex-R/M系列, 甚至51单片机核).这些协CPU都和主ARM64主CPU共享物理内存的不同地址段,并且有自己的固件程序在内存上运行,所以在划分地址空间的时候还是要注意内存对齐的问题,尤其是考虑到这些协CPU可能不支持非对齐访问,同样在编写协CPU固件程序的时候,也要清晰认识到该CPU是否支持非对齐内存访问。 同样在ARM的MMU虚拟地址管理中,也有内存地址对齐的要求,下图是ARM的MMU的工作原理和多级页表(Translation Tables)的索引关系图 ARM体系架构的MMU要求 arm 32位体系结构要求L1第一级页表基地址(The L1 Translation Table Base Addr)对齐到16KB的地址边界,L2第二级页表地址(The L2 Translation Table Add)对齐到1KB的地址边界。 ARM 64位体系结构要求虚拟地址的第21-28位VA[28:21]对齐到64 KB granule, 第16到20位VA[20:16]对齐到4 KB granule。 ARM 的Memory ordering特性中的不同Memory types对非对齐内存访问的支持的要求是不同的。下图是ARM Memory ordering特性中三种不同的Memory types访问规则 只有Normal Memory是支持非对齐内存访问的 Strongly-ordered 和 Device Memory不支持非对齐内存访问 对原子操作的影响 尽管现代的ARMv7 ARMv8 指令集的ARM CPU支持非对齐内存访问,但是非对齐内存访问是无法保证操作的原子性。下图分别是一个变量在内存对齐和非对齐的时候的内存布局: 内存对齐的变量访问,使用单个通用的CPU寄存器暂存,一个内存对齐的变量的读写操作能保证是单次原子操作. 非对齐的变量的内存访问是非原子操作,他们通常情况下访问一个非对齐的内存中的变量需要2次分别的对内存进行访问,因而不能保证原子性,一旦发生2次分别内存访问,2次分别的访问中间就有可能被异步事件打断,造成变量改变,因而不能保证原子性。 ARM NEON的要求 现代ARM CPU一般都有一个NEON的协处理器,一般用在浮点计算中用来做SIMD并行矢量加速计算。下图是NEON SIMD并行矢量计算的基本原理图: NEON本身是支持非对齐内存访问的 但是NEON访问非对齐的内存一般会有2个指令周期的时间penalty 通常情况下,为了灵活应用NEON的并行计算特性,在做SIMD并行矢量加速运算时,我们要根据NEON寄存器的Lane的bits数对齐相应的变量。如果是配置成8-bits的计算,就做8-bits对齐,如果是16-bits计算,就做16-bits对齐,以此类推,NEON的并行矢量计算的lane根据spec手册,有各种灵活配置的方法。 对性能perf的影响 通常而言,尽管现代的ARM CPU已经支持非对齐内存的访问,但是ARM访问非对齐的内存地址还是会造成明显的性能下降。因为访问一个非对齐的内存,需要增加多次load/store内存变量次数,进而增加了程序运行的指令周期 才有perf工具进行性能分析,能看到非对齐内存访问的性能下降,在perf工具中有一个alignment-faults的事件,可以观察程序访问非对齐内存的事件统计 cache line 对齐 除了通常所讲的根据CPU访问内存的地址位数的内存对齐之外,在程序优化的时候,还要考虑到cache存在的情况,根据cache line的长度来对齐你的访问变量。 cache和cache line的结构原理图如下(其中图2从该文章引用自: cenalulu),cache line是cache和内存进行数据传输的最小单位,一般cache都是以cache line的长度一次读写内存中的映射地址。 在ARM 系列的CPU中,不同型号的ARM CPU的cache line长度是不一样的,因此同样是基于ARM平台的CPU,从A平台移植优化过的程序到B平台时,一定要注意不同CPU的cache line大小是否一致,是否要重新调整cache line对齐优化。下图是ARMv7几款公版CPU的cache line的资料手册,ARMv8 64位的公版CPU(A53, A57, A72, A73)目前的cache line大小都是64 bytes, 但是各家公司基于公版ARM的定制版CPU的cache line大小可能有差异,一定要参考相关TRM手册进行调整、对齐、优化. 下图是一个例子关于未做cache line对齐的情况下,进行内存读写性能抖动的例子,引用自cenalulu.测试代码如下 程序的大意,对不同大小的数组进行1亿次读写操作,统计不同数组size时的读写时间。从测试的结果可以看出,当数组大小小于cache line size时,读写时间基本变化不大,当数组大小刚刚超过cache line size的时候,读写时间发生了剧烈的抖动。这是因为超过cache line 大小的数组元素可能没有提前预读到cache line中,在访问完cache line中的数组元素之后,要重新从内存读取数据,刷新cache line,因而产生了性能抖动。通过这个例子告诉我们,充分利用系统cache特性,根据cache line对齐你的数据,保证程序访问的局部数据都在一个cache line中可以提升系统性能。 #include 'stdio.h' #include  #include  long timediff(clock_t t1, clock_t t2) {     long elapsed;     elapsed = ((double)t2 - t1) / CLOCKS_PER_SEC * 1000; return elapsed; } int main(int argc, char *argv[]) #******* {     int array_size=atoi(argv[1]);     int repeat_times = 1000000000;     long array[array_size]; for(int i=0; i

    07-18 208浏览
  • STM32芯片内部架构的理解

    STM32芯片主要由内核和片上外设组成,STM32F103采用的是Cortex-M3内核。芯片生产厂商ST,负责在内核之外设计部件并生产芯片。这些内核之外的部件被称为核外外设或片上外设,如 GPIO、...

    07-12 210浏览
  • 详解如何基于标准库构建STM32工程

    从STM32新建工程、编译下载程序出发,让新手由浅入深,尽享STM32标准库开发的乐趣

    07-12 148浏览
  • STM32单片机系统结构的知识点总结

    从STM32新建工程、编译下载程序出发,让新手由浅入深,尽享STM32标准库开发的乐趣

    07-11 182浏览
  • STM32是怎么启动的?

    本文对STM32启动文件startup_stm32f10x_hd.s的代码进行讲解,此文件的代码在任何一个STM32F10x工程中都可以找到。

    07-05 127浏览
正在努力加载更多...
广告