SoC入门-3自动驾驶AI芯片框架

文摘   2024-10-19 11:58   上海  

提到自动驾驶AI芯片,其实大家都在抄,那抄的来源是哪里?没错就是--漂亮国。上面图里面是特斯拉的一个自动驾驶AI芯片的架构图,下面的图是英伟达的。

英伟达Orin芯片参考之前的文章:

NVIDIA ADAS-英伟达Orin芯片介绍

本文从全局的角度来进行说明,首先要介绍点重要的英文缩写,当字典用:

老外就喜欢一天没事搞缩写造词行业黑话装逼大王,例如问你一个问题:为什么有了USA,还造出来USB,那USC又是什么?

不过好处就是同级别的都懂这些黑话交流更顺畅。估计是英文的先天缺陷,汉语象形文字就没这个问题,看到文字就能知道意思。预计英文的这种乱玩迟早会把自己搞死,一个缩写无数种解释,感觉未来还是应该是象形文字的天下。好像一个科幻片里面的外星人就是一个圆圈的象形文字。

SoC组成:

  1. CPU(Central Processing Uni)子系统
  2. FSI(Function Safety Island)子系统
  3. VPU(Video Processing Unit)子系统
  4. PMU(Power Management Unit)子系统
  5. ISP(Image Signal Processing)子系统
  6. MIPI(Mobile Industry Processor Interface)移动工业处理接口子系统
  7. NPU(Neural Processing Unit)子系统,很多系统里面也叫TPU、BPU、GPU、DPU等各种PU(就像PUA一样了),就是用于AI算法加速的。
  8. PMU(Power Management Unit)电源管理子系统
  9. NoC(Network on chip)片上网络
  10. HSSYS(High Speed Subsystem)高速外设子系统
  11. LSSYS(Low Speed Subsystem)低速外设子系统
  12. UFS(Universal Flash Storage)通用闪存存储子系统
  13. DTM(Debug trace monitor)调试,追踪和监测
  14. CM(Crypto Master)硬件加密主控引擎
  15. LPDDR(Low Power Double Data Rate)低功耗双倍数据率子系统
  16. HSM(Hardware secure module)硬件安全模块子系统
  17. OPTEE(Open Portable Trusted Execution Environment)开源的可信执行环境子系统
  18. AUTOSRA CP(Automotive Open System Architecture Classic Platform)子系统

1. Memory Mapping

作为软件工程师,看到的硬件最直观的就是寄存器地址,那这些地址是怎么统一规划的,每个子系统基于基地址的偏移都是什么含义,这就需要看芯片手册了。

一般芯片会提供3个手册

  1. 用户手册(User Manual):使用环境搭建,烧写软件等,介绍怎么使用这个系统,不涉及编码和编译。
  2. 开发手册(Develop Manual):sdk代码框架介绍,编译,各种模块的配置修改方法
  3. 技术参考手册(Reference Manual):整体芯片参数,寄存器描述

Memory Mapping地址映射就是来规划整个系统地址的使用的,就像整个系统的门牌号:

  1. 规定了那段地址归哪个子系统使用的,子系统内部也有内存布局
  2. 不同的子系统看到的地址可能不一样
  3. 出于系统安全的需求,地址分为安全世界和非安全世界
  4. 地址开头都是一些cfg配置相关,然后是SRAM等存储相关,最后是DDR内存相关的地址
  5. 一般的地址分为devices属性和memory属性,由一定的硬件例如MPU、TCM去控制访问

    关于存储的一些设置如下:
  • SRAM要比DDR更加的高效,一般的子系统核周围根据需求都配置的有,用于固件存储运行,共享内存、核间通信,信息调度中转,休眠存储信息等功能使用。
  • efuse是一次性编程存储,用于存放密钥
  • LPDDR低功耗双倍速率动态随机存取存储器
  • Flash存储器
  • UFS,存放系统程序,及应用数据
  • TCM:在ARMCortex处理器中,TCM是一种位于处理器核心旁边的高速存储器,设计目的是提供低延迟和高带宽的内存访问性能。它与处理器内核紧密耦合,因此访问TCM中的存储器通常比访问普通RAM或缓存中的存储器要快。
  • MMU用于地址映射
  • DDR交织:把连续的地址分配到不同的DDR颗粒上,这样提高DDR的带宽和利用率

对于32bit和64bit异构处理器看到的地址范围是不一样的,所以需要进行不同的映射。

2. SoC片内通信

2.1 总线发展介绍

数据的流动主要借助了片上系统中的I/O总线,例如上图中Arm提供的AMBA标准。采用DMA控制器则可以让外部数据直接被传送到存储器,无需经过中央处理器,这可以大大改善数据吞吐的效率。

最近10年来,SoC设计的一个趋势是采用基于网络的拓扑结构,来提高片上通信的效率。这种基于路由的数据包互连网络称为“片上网络“(NoC),可以克服基于传统总线网络的带宽瓶颈。

片上网络(NoC)相比传统的总线接口通信有什么优点和缺点?

SoC所包含的IP模块数量不断增加,同时片上服务质量(QoS)、仲裁和数据流优化的复杂性越来越高, NoC逐渐取代总线和交叉开关(crossbar),而成为片上互连的行业标准。总线是共享的通信资源,除了最简单的系统之外,总线无法提供系统所需的带宽。交叉开关虽然可以提供足够带宽,但是其大小随着所连接的IP模块数量成倍增长,并且大型的交叉开关根本无法构建。它们都不能很好地利用布线,而布线可是当今芯片技术中最为昂贵的东西。NoC可以极大地减少裸片面积(尤其是更少的布线),功耗更低,而且可以对片上数据流和服务质量进行微调优化,甚至可以提供数据保护功能以提高整个系统的功能安全性。

总线是系统级芯片发展的早期阶段所采用的标准,那时连接的IP模块(CPU、存储器和外围控制器等)可能不超过20个。然而,随着更多IP模块连接到总线,它们开始争夺优先级和可用的带宽。总线需要集中的仲裁器和地址解码逻辑,而随着主机和从机数量的增加,大家竞争同一条总线资源,这反而成了SoC性能的瓶颈。

  • NOC总线可以通过AXI、APB等跟子系统相连。通过总线访问数据对于多核就有数据一致性问题,后面搞个专题讲下。这里最典型的就是A核的多核通过NOC访问其他硬件例如LPDDR、SRAM等,就需要在A核和NOC中间加一个硬件模块,例如CMN600AE。
  • 对于对带宽要求高的子系统,例如AI子系统需要处理大量的摄像头等多媒体数据,需要独立的专用通道连接到NoC上面,避免跟其他子系统进行争抢NoC资源。
  • 通过NoC可以访问配置寄存器和数据寄存器。例如在A核中去访问ISP的寄存器就需要通过NoC了

2.2 ARM自家的CI-700和Arteris的NoC

NoC从结构上分为Request Path和Response Path,每个Patch内部分为NIU、switch、link、reorder buffer等,这里举例两种常用的方案ARM自家的CI-700和Arteris的NoC

参考:https://blog.csdn.net/ygyglg/article/details/137525338

ARM的CI-700:

  • AMBA 5 CHI互连:CI-700是一种基于AMBA 5 CHI(Coherent Hub Interface)的互连技术,专为移动和客户端SoC设计,提供高性能和低功耗的解决方案。
  • 可定制的网状拓扑结构:CI-700支持可定制的网状拓扑结构,允许设计者根据SoC的具体需求来优化网络结构,以实现最佳的性能和功耗平衡。
  • 支持Armv9处理器设计:CI-700与Armv9处理器架构兼容,能够支持新一代的高性能计算需求。
  • 系统级缓存:CI-700引入了系统级缓存的概念,可以提高数据传输效率,减少对外部存储器的访问,从而降低系统功耗。Arteris的NoC:
  • FlexNoC 5:Arteris的NoC技术以FlexNoC 5为代表,是一种不可或缺的IP生成器,用于高效、高性能的NoC设计。
  • 物理感知:FlexNoC 5具有先进的物理感知能力,可以在设计周期早期提供直观的设计反馈,加速时序收敛,减少面积,并为物理布局团队提供良好的起点。
  • 支持多种协议:Arteris的NoC支持多种协议,包括AMBA 5 ACE-Lite、AHB、AXI等,使得IP块之间的互操作性更加灵活。
  • 功能安全:FlexNoC 5提供了FuSa选项,支持高达ASIL D级别的功能安全,适用于需要高安全性的汽车和工业应用。

对比总结

  • 设计理念:CI-700注重于为移动和客户端SoC提供定制化的互连解决方案,而Arteris的NoC更侧重于提供灵活、可配置的网络互连技术,适用于多种应用场景。
  • 性能与功耗:CI-700通过系统级缓存和网状拓扑结构优化性能和功耗,而Arteris的NoC通过物理感知和多协议支持来提升性能和降低功耗。
  • 功能安全:Arteris的NoC提供了功能安全支持,这对于汽车和工业应用尤为重要,而CI-700虽然也关注安全性,但未明确提及功能安全支持。
  • 互操作性:Arteris的NoC支持更广泛的协议,这使得它能够更容易地与不同的IP块进行互操作,而CI-700则专注于与Arm处理器架构的兼容性。
  • 在选择适合的片上网络互连技术时,设计者需要根据SoC的具体需求、预期的应用场景以及对性能、功耗和安全性的要求来做出决策。

ARM的CI-700和Arteris的NoC都是为SoC设计提供的片上网络互连解决方案,但它们在设计理念和目标应用方面存在一些差异。

CI-700是基于ARM的AMBA 5 CHI互连标准设计的,专为移动和客户端SoC应用场景优化。它具有可定制的网状拓扑结构,能够根据SoC的需求调整网络结构,以达到高性能和低功耗的目标。CI-700与ARMv9处理器架构兼容,支持新一代的计算需求,并引入了系统级缓存来提高数据传输效率和降低系统功耗。

另一方面,Arteris的NoC,特别是FlexNoC 5,是一种高效、高性能的NoC设计,具有物理感知能力,可以在设计早期提供直观的反馈,帮助优化互连结构,减少开发时间和芯片面积,同时降低功耗。Arteris的NoC支持多种协议,包括AMBA 5,并且提供了功能安全支持,适用于需要高安全性的汽车和工业应用。

总的来说,CI-700更侧重于与ARM处理器架构的紧密集成和为移动SoC提供优化的解决方案,而Arteris的NoC提供了更广泛的协议支持和功能安全特性,适用于多种不同的应用场景。设计者在选择片上网络互连技术时,应根据项目的具体需求和目标应用来决定使用哪种技术。

ARM的手册是公开的:

https://developer.arm.com/search#numberOfResults=48&q=ci-700就可以下载

Arteris的需要注册账号下载。

3. 时钟和复位

时钟是由PLL产生的,

  • 不同的子系统需要的时钟频率不同,就需要多个PLL。
  • 对于FSI等有功能安全需求的模块需要单独的PLL
  • 对于AON域的模块也需要单独的PLL,因为系统休眠的时候还需要单独运行
  • DDR作为高速接口对稳定性要求高且内部结构复杂需要走线比较多而产生信号干扰,从而影响稳定性,需要多个PLL分开提供时钟,防止时钟偏斜和有更强的时钟供应灵活性
  • PLL存在于CRU中,是CRU的一部分

对于电源域和电压源

  • 根据不同的电压设计电压域
  • 根据不同的子系统功能设计电源域
  • AON(Always on)是不断电的区域
  • PIMC控制电源的开关

复位

  • CRU控制,一个子系统例如FSI、SCP对内部的硬件模块有独立的CRU去控制,对其寄存器操作就可以
  • 整个芯片系统有一个TOP CRU对各个子系统进行复位控制
  • DDR有多个PLL控制,也有多个CRU控制复位状态,更加的灵活
  • CRU中有PoR(Power-On Reset,上电复位)监控电源
  • 整机复位由外部按钮或者特殊的GPIO信号等触发,也可以由寄存器的软复位触发,除非的子系统需要高级的权限,例如只能FSI或者SCP触发,A核和其他子系统不能触发。
  • 看门狗WDT也可以触发复位

对于不同的电源模式,例如休眠模式、节能模式、关机模式等都需要关闭一些硬件功能,这时就需要使用CRU去控制这些硬件的时钟和复位信号了。对于安全复位需要先清空应用数据,特别是NoC总线上传输的数据后再进行复位操作。

对于SoC的休眠:

  • A核需要把自己的数据和程序保存到DDR中
  • DDR training数据保存到AON的SRAM里面
  • 系统重要的数据也保存到AON的SRAM里面
  • 主控核(一般是A核)通知其他子系统进入休眠
  • SCP控制PPU进入低功耗状态
  • SCP控制PMIC对一些硬件断电
  • SCP控制PLL关闭部分时钟
  • SCP自己进入WFE低功耗模式等待唤醒

唤醒:

  • 唤醒源唤醒SCP退出WFE
  • SCP控制PPL提供时钟
  • SCP控制PMIC上电
  • SCP控制PPU退出低功耗模式
  • SCP通知主控核退出休眠
  • 主控核通知其他子系统退出休眠
  • DDR恢复现场继续运行

上下电时序:

  • 根据电压域进行上电的顺序
  • 必须严格按照顺序上电启动,时间间隔需要满足需求

安全复位:对子系统的安全复位需求清空其总线上通信的数据和子系统内部的安全关闭

 1. NoC总线清空 

在 NoC 中使用 IdleReq,IdleAck 和 Idle 来实现 disconnect 的操作。

当 NoC 需要进行 reset 或者 clock gating 之前,PMU 会发起 IdleReq = 1,当 NoC 回复 IdleAck = 1 和

Idle = 1 即完成握手操作,此时就可以安全的 reset 和 gating 了;

在完成 reset 和 gating 之后,PMU 可以再次发起 IdleReq = 0,当 Idle 和 IdleAck=0 时,则代表完成

Re-connect,之后就可以正常传输了。

2. ADB/APB LPI Q-channel清空

在子系统和 CRU 之间,芯片使用 ADB 和 APB 异步桥来连接跨时钟域。因此使用 LPI Q-channel 同

样可以实现 disconnect 的操作。

当子系统需要进行 reset 或者 power gating 之前,PMU 需要发起 pwrqreqn = 0,等待 pwrqacceptn = 0

即完成握手操作,进入 Q_STOPPED 状态,此时可以安全的复位和 power gating;

当子系统完成 reset 或者 power gating 之后,PMU 再次发起 pwrqreqn = 1,等待 pwrqacceptn = 1 即进

入 Q_RUN 状态,恢复正常运行。

LPI Q-channel同理,LPI(Low-Power Interface,低功耗接口)中的Q-channel和P-channel是AMBA(Advanced Microcontroller Bus Architecture)规范中定义的两种重要接口。其区别:

  • Q-channel主要是为简单的运行-停止(operational-quiescent)状态转换而设计的。它适用于那些只有两种主要电源状态(上电和断电)的场景。
  • P-channel则设计用于更复杂的电源状态转换场景。它允许设备在不同的低功耗状态之间转换,而无需每次都回到一个公共的运行状态。

3. 子系统内部安全复位

  • 需要核进入WFI后再复位,这样WFI情况下,大部分时钟已关闭,可以进行安全复位
  • 或者核通过LPI总线控制自己进入低功耗模式再关闭,这样避免系统错误

4. MailBox通信

NoC解决了硬件模块的通信访问机制,就是某个子系统核去访问某个位置。但是多个子系统协同工作就需要告诉对方去访问那个位置。这就是核间通信MailBox,准确来说是告知,因为数据并不是直接发过去,而是放某个地方,告知对方来取。

  1. 数据放某个地方,一般是共享内存,或者MailBox硬件内部
  2. 通过硬件的中断连线触发对方中断告知

一个MailBox有很多个Channel通路,可以支持很多条通信的路同时工作。通路也分安全通路和非安全通路,接收者需要对这两种消息进行分类处理,例如非安全通路发来了安全的请求就可以丢弃。参考之前的文章:XXX中断

5. 子系统主要硬件模块

5.1 中断控制

对于异构核,例如A核(GIC)、M核(NVIC)、R核(GIC)、RISC-V核(PLIC)等,都有自己的中断控制器硬件

芯片手册需要提供各个核的中断向量表,方便软件进行功能开发。软件debug的时候经常需要利用中断号来定位是那个模块出问题了。

5.2 DMA硬件

DMA可以通过AXI、APB等接口连接到总线上。一般需要大量数据搬运的需要加上DMA硬件,例如A核和NPU等。

5.3 看门狗WDT

各个子系统内部都需要内置WDT,防止子系统死机的时候进行复位,或者上报事件给安全中心去处理。

一般WDT支持两级事件。第一级是子系统自己去处理,第二级是子系统已经死了,没有处理能力的时候,上报给外部系统处理。

5.4 Timer

为了实现定时中断和延时等时间有关的功能,需要子系统内置Timer硬件

5.4 RTC

实时时钟(Real-Time Clock)提供时钟日历功能

5.5 调试与跟踪

一般需要上位机通过JTAG或者USB对芯片进行调试与跟踪

  1. 调试架构
  • ARM CoreSight:ARM CoreSight是ARM提供的一套高级的调试和跟踪技术,专为复杂SoC设计而打造。其中,SoC-400是这一技术系列中的一个解决方案,提供系统级的调试和跟踪能力,支持多核和跨SoC调试,具有断点、观察点等高级调试功能,并能跟踪处理器的指令流、数据流和系统事件。
  1. 调试工具
  • JTAG/SWD接口:JTAG(Joint Test Action Group)和SWD(Single Wire Debug)是两种常用的调试接口,允许开发人员通过边界扫描或单线调试连接来访问SoC的内部寄存器、内存和执行调试操作。
  • 调试器:专业的调试器软件,如ARM的Keil MDK、IAR Embedded Workbench等,提供了图形化的调试界面,支持断点设置、单步执行、变量查看等调试功能。
  1. 跟踪技术
  • 指令跟踪:跟踪SoC中处理器的指令执行序列,有助于理解程序的执行流程和性能瓶颈。
  • 数据流跟踪:跟踪处理器间或处理器与外部设备间的数据传输,帮助识别数据路径中的错误或性能问题。
  • 系统事件跟踪:记录SoC中的系统事件,如中断、异常、DMA传输等,以便在调试时分析系统的行为。

5.6 PVT

PVT用于感知芯片的工艺变化和操作环境,包含以下几种传感器

  • Thermal Sensing(TS):热传感,精度高,集成方便。支持功率优化和可靠性
  • Distributed Thermal Sensing(DTS):分布式热传感。支持thermal mapping,高度精细的布放,低延时
  • Supply Monitoring(VM):供电监控,测量多个域的电源电压、验证配电网络、实施静态和动态IR压降分析
  • Process Monitoring(PD):工艺监控,在大规模量产或者单个芯片生命周期,了解硅片速度变化(slow,fast,typical)。提供功率优化和老化监控

PVT-Controller对PVT温度数据进行采集后,会产生中断来获取温度数据,如果温度数据超标会继续上报给更高级的子系统例如FSI去决策,这时FSI可能令系统关机。

5.7 pinctrl引脚复用

芯片需要提供pin引脚复用规则

大多数 SOC的 pin都是支持复用的,比如 I.MX6ULL的 GPIO1_IO03既可以作为普通的GPIO使用,也可以作为 I2C1的 SDA等等。此外我们还需要配置 pin的电气特性,比如上 /下拉、速度、驱动能力等等。传统的配置 pin的方式就是直接操作相应的寄存器,但是这种配置方式比较繁琐、而且容易出问题 (比如 pin功能冲突 )。pinctrl子系统就是为了解决这个问题而引入的, pinctrl子系统主要工作 内容如下:

  1. 获取设备树中 pin信息。

  2. 根据获取到的 pin信息来设置 pin的复用功能

  3. 根据获取到的 pin信息来设置 pin的电气特性,比如上 /下拉、速度、驱动能力等。

对于我们使用者来讲,只需要在设备树里面设置好某个 pin的相关属性即可,其他的初始化工作均由 pinctrl子系统来完成, pinctrl子系统源码目录为 drivers/pinctrl。

6. 安全设计

TrustZone将系统的资源(通过寄存器地址)划分为安全世界和非安全世界

一些硬件和数据只能安全世界去访问,Linux应用里面不能直接访问,必须通过系统调用到内核然后再到BL31或者SCP等安全子系统去执行安全寄存器的操作。这样linux应用只能访问到固定的接口,而不是暴露所有的寄存器,从而安全。

  • BL31和OPTEE是安全世界
  • SCP和FSI是安全世界
  • DDR和SRAM可以部分是安全世界地址,部分是非安全的,需要硬件例如TZC或者APB Filter进行配置保护。
  • NoC中区分了Secure slave和non-Secure slave
  • DMA可以配置是否访问安全空间

7. SoC启动设计

7.1 安全启动介绍

可以参考之前的文章:

  1. 安全启动 secureboot入门-8硬件杂谈和汇总 

  2. ATF:ATF入门-4BL31启动流程分析 等

这部分就是安全启动了,

  • 需要支持ATF密码验签流程和BL1从芯片中的ROM启动。
  • 对于验签需要CM硬件模块的支持。
  • BootROM的启动有启动模式,可以通过efuse和pin进行配置。
  • 密钥存储需要eFUSE支持
  • fip包存储需要UFS的QSPI FLASH支持
  • 支持XIP、安全恢复、安全配置、安全调试、诊断等模式
  • 支持AB分区、生命周期管理、启动日志等功能

常见的拨码开关,pin配置:

  1. 强制恢复模式:从UFS中启动
  2. USB启动模式:从USB下载启动
  3. XIP启动:eXecute In Place(芯片内执行)启动方式,是指芯片能够直接在非易失性存储器(如Flash)中执行程序代码,而无需将代码先复制到RAM(随机存取存储器)中。

7.2 启动示例

image.png

上图是基于SCP启动SoC的一个流程图:

  1. SCP_BL1 boot 流程:

系统启动,首先运行scp_romfw firmware代码。执行scp应用初始化流程的初始流程fwk_arch_init(),按照Firmware.cmake中定义的module顺序进行初始化,中断初始化,module启动,这些完成后会循环调用处理运行时event消息。

  1. ATF 中BL2加载SCP_BL2:

TF(Trusted Firmware)是ARM在Armv8引入的安全解决方案,为安全提供了整体解决方案。它包括启动和运行过程中的特权级划分。ATF BL2的主要职责就是将后续固件如u-boot。kernel,SCP或者其他异构核的固件,加载到ram中。SCP firmware的加载及boot 由arm Arm Trusted Firmware-A (TF-A)来完成。

SCP用于电源,时钟,复位和系统控制。BL2将可选的SCP_BL2镜像从平台存储设备加载到特定的安全内存区域。SCP_BL2的后续处理是特定于具体平台的,需要自行实现。例如,Arm juno :

  • BL2先把SCP_BL2加载到trust sram,
  • 再使用Boot Over MHU (BOM) 协议,把SCP_BL2加载到 SCP的内部RAM之后,
  • SCP运行SCP_BL2,
  • SCP给AP发出signals,通知BL2继续执行。

ATF中,BL2的编译选项在如下位置定义plat/arm/board/juno/platform.mk中的BL2_SOURCES,morello ATF plat/arm/board/morello/platform.mk中未定义BL2_SOURCES,不包含BL2.是否包含BL2相关通用代码及配置由CSS_LOAD_SCP_IMAGES决定

  1. scp romfw 跳转执行ramfw:

在juno中,ATF的BL2中通过SDS(Shared-Data-Structure,在juno平台中替代之前Boot-Over_MHU (BOM)协议)和SCP的romfw通信(mod_bootloader调用sds API),发送ramfw到安全内存,然后再由romfw从安全内存加载到其他位置并执行。

SCP_BL2的运行跟SCP_BL1一样,两者都是使用SCP的框架代码,属于两个系统。执行scp应用初始化流程的初始流程fwk_arch_init(),按照Firmware.cmake中定义的module顺序进行初始化,中断初始化,module启动,这些完成后会循环调用处理运行时event消息。

参考:

https://blog.csdn.net/ty1121466568/article/details/123735268?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2~default~CTRLIST~Rate-1-123735268-blog-107282533.pc_relevant_3mothn_strategy_and_data_recovery&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2~default~CTRLIST~Rate-1-123735268-blog-107282533.pc_relevant_3mothn_strategy_and_data_recovery&utm_relevant_index=1

后记:

本文使用了大量的SoC硬件缩写名词,一般看一遍也记不住,有空多看几遍,琢磨研究,用ChatGPT给解释下,慢慢一回生二回熟就也能脱口而出这些名词了,不然听别人讲跟听天书一样。

本文只是大致介绍了下SoC用到的一些主要技术,要想详细研究最好找一个芯片手册,多看几遍,一通百通,还是需要下一点功夫还需要一点兴趣和悟性的。

“啥都懂一点,啥都不精通,

干啥都能干,干啥啥不是,

专业入门劝退,堪称程序员杂家”。

欢迎各位有自己公众号的留言:申请转载

纯干货持续更新,欢迎分享给朋友点赞、收藏、在看、划线和评论交流

彩蛋:

  1. 本公众号提供微信技术交流群,一起探讨汽车软件技术(先加微信:thatway1989,备注感兴趣的技术方向)。

  2. 有需要投放广告、商业合作的也可以联系博主。

  3. 赞赏1元钱交个朋友

《8天学RAM》福利

芯片设计软硬件相关的都是高薪,10年经验,上百个W在北上广都很随意。

首先说下本篇文章开头是一个福利,同志们先领一个券到手99元

通过博主的二维码链接,打折到了99元,原价是128元,妥妥的福利。每人只能领取一次。领取后,3天失效。

课程内容:

课表:

IC技术圈
致力于建立IC技术知识、IC技术圈内人的联系
 最新文章