车载雷达实战之Firmware内存优化

news2024/11/19 21:31:39
内存(Memory)是计算机中最重要的部件之一,计算机运时的程序以及数据都依赖它进行存储。内存主要分为随机存储器(RAM),只读存储器(ROM)以及高速缓存(Cache)。
仅仅雷达的原始回波数据(Radar data cube)就可能达MByte级别的数据体量,这对MCU的内存来说尺寸很大。本篇文章主要介绍了在雷达嵌入式编程中会遇到的MPU(Memory Protect Unit)、Cache以及不同数据格式在内存中的存储格式和雷达基带涉及的加速核与内存区的映射。总而言之,与内存相关的嵌入式编程以及优化方式会在本文中对其进行说明,并从内存优化的角度对可以应用的诸如 同址复用等思路进行说明。 👻

MPU+Cache

Cache一致性问题一般发生在多核处理器上,单核处理器基本不用考虑这个问题。

现在的处理器一般都有两级(L1cache,L2cache)甚至三级缓存,当核0读写外部存储器如DDR内的数据时,会将数据保存在L2cache和L1Dcache中。后续如果该数据一直在cache中,那么对该数据的读写都会直接操作cache内的数据,而不会去修改DDR中的数据。以此提高CPU的读写速度。但是这可能导致其他主机(如其他核)读取DDR的数据与核0中cache中的数据不一致。例如核0已经将位于DDR中的变量num从11修改为56了,但是其他核读取num时,依然有可能读取到的是11。最新的num数据56可能依旧在核0的cache中,没有写回到DDR中。一般来说,多级缓存之间的一致性不需要我们来维护,我们主要维护不同核之间的数据一致。

    // ...
    // recieve data from DMA or HW peripheral
    // addr = cache line aligned buffer address
    // size = multiple of cache line aligned size in bytes
    // invalidate contents of cache so that a CPU can see the data written by DMA or HW peripheral
 
    CacheP_inv(addr, size, CacheP_TYPE_ALL);

上面的代码为将对应地址空间执行了Writeback-Invalidate操作,其的作用是将Cache写回到DDR中,之后Cache中的数据将会无效。这种操作多用于读取核间共享的存储区域之前。除了Writeback-Invalidate操作,还有Invalidate(将CACHE中的数据视为无效数据)以及Writeback(将CACHE中的数据写回存储器中如DDR)等操作。


MPU定义了存储器不同地址空间的属性和存储器的访问权限。MPU不会提升嵌入式应用的性能,而是用于系统中问题的检测(比如试图访问非法或者不允许的存储器位置所导致的应用错误)。如果检测到有错误,则会触发HardFault异常。实际上,许多微控制器用不到MPU,但MPU可以提高嵌入式系统的健壮性,使得系统更加安全

/** MPU Region Base Address Register Value
*
* \param Region The region to be configured, number 0 to 15.
* \param BaseAddress The base address for the region.
*/
#define ARM_MPU_RBAR(Region, BaseAddress) \
  (((BaseAddress) & MPU_RBAR_ADDR_Msk) |  \
   ((Region) & MPU_RBAR_REGION_Msk)    |  \
   (MPU_RBAR_VALID_Msk))

#define ARM_MPU_RASR_EX(DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size)    \
  ((((DisableExec)      << MPU_RASR_XN_Pos)   & MPU_RASR_XN_Msk)                                  | \
   (((AccessPermission) << MPU_RASR_AP_Pos)   & MPU_RASR_AP_Msk)                                  | \
   (((AccessAttributes) & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk))) | \
   (((SubRegionDisable) << MPU_RASR_SRD_Pos)  & MPU_RASR_SRD_Msk)                                 | \
   (((Size)             << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk)                                | \
   (((MPU_RASR_ENABLE_Msk))))

/**
* MPU Region Attribute and Size Register Value
*
* \param DisableExec       Instruction access disable bit, 1= disable instruction fetches.
* \param AccessPermission  Data access permissions, allows you to configure read/write access for User and Privileged mode.
* \param TypeExtField      Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral.
* \param IsShareable       Region is shareable between multiple bus masters.
* \param IsCacheable       Region is cacheable, i.e. its value may be kept in cache.
* \param IsBufferable      Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy.
* \param SubRegionDisable  Sub-region disable field.
* \param Size              Region size of the region to be configured, for example 4K, 8K.
*/
#define ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size) \
  ARM_MPU_RASR_EX(DisableExec, AccessPermission, ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable), SubRegionDisable, Size)

/* Region 3 setting: Memory with Device type, not shareable, non-cacheable */
MPU->RBAR = ARM_MPU_RBAR(3, 0x31C00000U); //0x30000000U
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_32MB);

上述代码将0x31C00000为起点的32MB数据区域设置为了non-cacheable(意味着所有observers都可以观察该内存的实际值),not shareable(如果被多个observer使用Non-shareable内存,无序的读写的操作顺序会导致异常)。当然,在设置MPU regions时,建议将cache与MPU失能,配置完成之后再使能。

Data representation

在基带模块中主要涉及的数据类型如下:

  • 定点实数/复数

  • 浮点复数

  • 伪浮点复数

定点实数/复数

下图是一个8位定点实数的Bit图,高四位是整数,第四位是小数。实数1.5对应表示为00011000。

定点的复数如下图为高32位为实部,低32位为虚部。0-12bit位为虚部的小数部分,13-31bit为虚部的整数部分。32-44bit为实部小数部分,45-63bit为实部的整数部分。

浮点复数

如下图所示,浮点复数的实部和虚部是由两个符合IEEE754标准的单精度短浮点数的标准的32位数表示。

单精度短浮点数的由1位符号位,8位指数位和23位有效数字位构成。实际上有效数字位是24位,因为第一位有效数字总是“1”,不必存储。有效数字位是一个二进制纯小数。8位指数位中第一位是符号位,这符号位和一般的符号位不同,它用“1”代表正,用”0“代表负。整个单精度短浮点数的符号位用“1”代表负,“0”代表正。指数位为正代表有效数字位需要右移指数+1,为负则代表需要左翼左移指数按位取反。距离举个转换的例子:

==

伪浮点复数

伪浮点复数这种数据存储格式能够有效的减少内存压力,它将需要64位存储的浮点复数用32位来存储。结构如下:

实部和虚部都以14位数表示,他们的浮点位置由高4位计算得出。复数的实数部分数值=,复数的虚数部分数值=。下面举个例子,复数-7+4i在内存中以伪浮点复数存储为0x34002400。

Memory Map

雷达的MCU一般都是多核的,成本高一点的会是多个ARM核与DSP核,成本低一点的也会有ARM核与各种加速核。这些核心都有对RAM进行读写的需要。我们针对低成本芯片集成电路蓝本,大约简化以下几个主体。

  • Bus Master:ARM核,我们编写的代码就是跑在这个核心。

  • PREP:主要用于原始的AD回波数据的存储组织。

  • BB_DMA:Direct Memory Access.它可以解放核心,提供内存间拷贝的功能。也可以为诸如FFT这种核心提供内存块数据的逐条/个数据的读取等操作。

  • P1:提供在距离维之前的数据处理功能,包括幅相等校准与Zeros的工作。

  • P2:提供在速度维之前的数据处理工作,包括复数的累加求信号均值等操作。

  • FFT:提供快速傅里叶变化算法实现。

  • CFAR:提供各种恒虚警算法实现。

我们把RAM分为两部分,BUF1和BUF2,BUF1存储包括FFT的原始与结果数据,BUF2存储一些窗口数据。MCU中的每个核心都对RAM有不同位宽的读写需求,核心直接也有相互写入的需求。我们把数据想象成水流,而各个加速核想象成水处理池,而我们嵌入式工程师就像是水管工,将核心根据需要用RAM中的数据连接起来,来搭建一个信号处理流程。下表是这些核心与RAM不同位宽的读写关系图(纵向表头为请求方,表格中的读写是请求方的读写,横向为响应方)。

P1_ZO

P1_MUL

FFT

P2

CFAR

BUF1

BUF2

BUS Master

32/64读/写

32/64读/写

BB_DMA

16写

32写

32写

8/16/32/64读

8/16/32写

8/16/32/64读

8/16/32写

PREP

64写

P1

32写

32写

FFT

32写

16/32读

32写

P2

32写

32读

32写

32读

32写

CFAR

32读

64写

BUF1可以根据存储的数据种类进一步划分,比如可以划分为存储AD回波数据的区域,存储距离维FFT结果数据区,速度维FFT结果数据,这么存储可以进行更好的调试信号处理调试以及更灵活的信号处理流程搭建,但是一旦流程固定之后,我们完全可以将一些数据区域复用,比如ADC_SAMPLE_ADDR与FFT1D_CACHE_ADDR可以指向一个地址,这样处理可以大大减少对内存空间的压力。


除了上述的可供ARM核心读写的BUF1+BUF2内存区域(我们称之为原始数据区),具有加速核的雷达SOC还有一些"影子RAM",这么称呼是因为他们仿佛是原始数据区域的影子一样,这些区域ARM核心并不能直接写,但是可以读,每当我们向原始数据区写入的后,不同的影子RAM会自动写入对应原始数据经过一种固定运算或者更改存储格式后的数据.

正如上图,第一个影子RAM是对应原始复数数据经过i.e.abs,log2,log运算之后的幅度实数数据,CFAR加速核进行相应算法的原始数据就来自这里。第二个影子RAM是对应以伪浮点数存储的原始数据以符合IEEE754标准的浮点数进行存储,P1/2的涉及的一些复数运算来源于这里。


十六宿舍 原创作品,转载必须标注原文链接。
©2023 Yang Li. All rights reserved.
欢迎关注 『十六宿舍』 ,大家喜欢的话,给个 👍 ,更多关于嵌入式相关技术的内容持续更新中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/388326.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

树莓派Pico W无线WiFi开发板使用方法及MicroPython编程实践

树莓派Pico W开发板是树莓派基金会于2022年6月底推出的一款无线WiFi开发板&#xff0c;它支持C/C和MicroPython编程。本文介绍树莓派Pico W无线WiFi开发板的使用方法及MicroPython编程示例&#xff0c;包括树莓派Pico W开发板板载LED使用及控制编程示例&#xff0c;Pico W开发板…

Spring——什么是IOC?

一、原则高内聚、低耦合二、什么是IOC&#xff1f;控制反转&#xff0c;把对象创建和对象之间的调用过程&#xff0c;交给spring进行管理三、使用IOC的目的是什么&#xff1f;降低耦合&#xff08;谁和谁的耦合&#xff1f;&#xff1f;如何降低的&#xff1f;&#xff09;原来…

openai-chatGPT的API调用异常处理

因为目前openai对地区限制的原因&#xff0c;即使设置了全局代理使用API调用时&#xff0c;还是会出现科学上网代理的错误问题。openai库 0.26.5【错误提示】&#xff1a;raise error.APIConnectionError(openai.error.APIConnectionError: Error communicating with OpenAI: …

泛型详解.

1 泛型的引入 问题&#xff1a;我们之前实现过的顺序表&#xff0c;只能保存 int 类型的元素&#xff0c;如果现在需要保存 指向 Person 类型对象的引用的顺序表&#xff0c;请问应该如何解决&#xff1f;如果又需要保存指向 Book 对象类型的引用呢&#xff1f; 之前写的顺序表…

红黑树-随记

文章目录1.为什么hashmap用红黑树不用二叉树和平衡二叉树1.1 二叉树&#xff08;Binary Search Tree&#xff09;1.2 红黑树&#xff08;Red Black Tree&#xff09;1.3 平衡二叉树&#xff08;Balence Binary Tree&#xff09;也称AVT2.为什么mysql用b数&#xff0c;不用B数或…

Windows程序员学习Linux环境下VI(VIM)编辑器的使用方法

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;今天我们来重新审视一下Windows程序员如何学习Linux环境知识。由于很多程序在Windows环境下开发好后&#xff0c;还要部署到Linux服务器上去&#xff0c;所以作为Windows程序员有必要学习Linux环境的知识。VI…

为什么KT6368A双模蓝牙芯片焊到板子上,没反应没收到芯片TX上电返回信息呢

目录 一、问题简介 为什么我把KT6368A芯片焊到板子上面&#xff0c;没有收到芯片TX的脚上电返回信息呢&#xff0c;而KT6368A芯片的2脚一直是2点多v的电压&#xff0c;换了好几个芯片都是这样 二、详细说明 一、问题简介 为什么我把KT6368A芯片焊到板子上面&#xff0c;没有…

QWidgetTable获取选中多行数据

QWidgetTable获取选中的多行数据获取选中行的行编号和打印指定第几列功能快捷键插入链接与图片创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能&#xff0c;丰富你的文章UML 图表FLowchart流…

buu [NPUCTF2020]这是什么觅 1

题目描述&#xff1a; 就一个这种文件&#xff0c;用记事本打开后&#xff1a; 题目分析&#xff1a; 打开后就一串看不懂的东西&#xff0c;想想这个东西曾经在 010editor 或 winhex中出现过&#xff08;右端&#xff09;既然如此那么我们就用它打开&#xff0c;得到&#…

使用 JaCoCo 生成测试覆盖率报告

0、为什么要生成测试覆盖率报告 在我们实际的工作中&#xff0c;当完成程序的开发后&#xff0c;需要提交给测试人员进行测试&#xff0c;经过测试人员测试后&#xff0c;代码才能上线到生产环境。 有个问题是&#xff1a;怎么能证明程序得到了充分的测试&#xff0c;程序中所…

线程池和ThreadLocal详解

线程池和ThreadLocal详解线程池池化模式&#xff1a;线程池里的线程数量设定为多少比较合适?添加线程规则&#xff1a;实现原理&#xff1a;线程池实现任务复用的原理线程池状态&#xff1a;Executors 创线程池工具类手动创建&#xff08;更推荐&#xff09;&#xff1a;自动创…

高码率QPSK调制解调方案(FPGA实现篇)

在前面的章节中,已经讲过QPSK调制的方案和Matlab算法仿真,在本篇中,主要讲解基于FPGA的高速QPSK调制的实现。根据前面提到的技术指标,本系统传输的数据速率为500Mbps,中频为720MHz,因此,传统的串行QPSK调制已经不合适在FPGA中实现,需采用全数字的并行方式进行调制,具体…

电商API是什么?为什么要用?主要应用场景有哪些?

电商API是什么&#xff1f;API是application programming interface&#xff08;应用程序接口&#xff09;的简称&#xff0c;实际上是一些预先定义的函数&#xff0c;目的是提供应用程序与开发人员基于某软件或硬件的以访问一组例程的能力&#xff0c;而又无需访问源码&#x…

强强联合,再强的英伟达NVIDIA也不落俗套

强强联合&#xff0c;全球科技领域永恒的话题【科技明说 &#xff5c; 每日看点】前些天&#xff0c;我看到GPU领域的英伟达(Nvidia)与微软(Microsoft)做了一项十年期的云计算协议&#xff0c;起初我以为微软Microsoft Azure与英伟达GPU方面有所合作&#xff0c;其实不然&#…

微小目标识别研究(1)——白酒杂质识别

文章目录研究项目简介基于机器视觉技术的白酒杂质检测系统研究&#xff08;大概浏览&#xff09;研究背景国内外研究现状和发展趋势国内国外总结白酒杂质检测算法YOLO V3算法K近邻算法滤波处理动态范围增强形态学图像处理运动目标提取数据集制作数据增强基于机器视觉的液体药品…

学习笔记 —— 基于C加速的Python高效计算 (Cython pybind11)

目录引言Cython示例介绍第一阶段优化第二阶段优化Cython Annotation tool优化方法第三阶段优化比对下 JIT的Numba总结pybind11LinksIntroductionImplementationImplementation CmakecytpesCython & pybind11 性能比较TODO Implementation Cmake --pybind11 Cython & py…

Linux SPI 驱动实验

目录 一、Linux 下 SPI 驱动框架简介 1、SPI 主机驱动 2、SPI 设备驱动 SPI 设备数据收发处理流程 3、SPI 设备和驱动匹配过程 二、添加SPI 设备信息 1、添加 ICM20608 所使用的 IO 2、 在 ecspi3 节点追加 icm20608 子节点 三、编写 ICM20608 驱动 1、修改makefile​…

深度学习目标检测ui界面-交通标志检测识别

深度学习目标检测ui界面-交通标志检测识别 为了将算法封装起来&#xff0c;博主尝试了实验pyqt5的上位机界面进行封装&#xff0c;其中遇到了一些坑举给大家避开。这里加载的训练模型参考之前写的博客&#xff1a; 自动驾驶目标检测项目实战(一)—基于深度学习框架yolov的交通…

C++ 二级指针的理解

指针一直很抽象&#xff0c;不是很容易理解&#xff0c;尤其是二级指针。有天路上&#xff0c;脑子里突然想起二级指针&#xff0c;并开始思考什么是二级指针&#xff0c;经过分析和调试验证&#xff0c;对二级指针有了进一步的认识。故写下此篇。 一级指针 假设变量 a、p 的…

消息队列 rabbitmq 学习

RabbitMQ是一个在AMQP基础上完整的&#xff0c;可复用的企业消息系统。他遵循Mozilla Public License开源协议。 MQ全称为Message Queue, 消息队列&#xff08;MQ&#xff09;是一种应用程序对应用程序的通信方法。应用程序通过读写出入队列的消息&#xff08;针对应用程序的数…