blog
blog copied to clipboard
My blog
# 1. Overview Cortex-M3(2006年)和Cortex-M4(2010)都是32位架构,寄存器和数据通路、总线接口都是32位。M系列使用指令集架构(ISA,Instruction Set Architecture)叫做Thumb ISA,它是基于Thumb-2 Technology(支持16位/32位指令)。  M系列的处理器从**架构层面**有以下特点: * 三级流水线设计; * **哈佛总线架构**,且具有统一的存储器空间:指令和地址总线使用相同的地址空间; * 32位寻址,支持4GB存储空间; * 基于ARM **AMBA**(Advanced Microcontroller Bus Architecture)支持高吞吐的流水线操作。 关于流水线操作,可以参考:https://github.com/carloscn/blog/issues/62 * 名为**NVIC**(Nested Vectored Interrupt Controller,嵌套向量中断控制器)的中断控制器,支持最多240 个中断请求和8 ~256...
# 10_ELF文件_ARM的镜像文件(.bin-.hex-.s19) ARM的编译器直接编译出文件应该是elf格式的,类似于Linux,它是有elf解析器可以对elf进行解析和提取的,而baremental环境是鲜有elf解析器,因为它对于baremental的环境实在是太大了。因此这里就需要我们自己去handle二进制文件,把他们放在一个正确的内存里面。 每个厂家的bootROM不一样,所以**对于二进制文件的存储要求也不一样**。这个规则也是看二级厂家是怎么定义,但是这里还是能抽象出一些比较通用的规则。image文件主要是用来做大规模量产的。既要做大规模量产,由于各芯片厂家制定的标准不一,所以实际上image文件有很多种格式。本文包含其中最具有代表性也应用最广泛的3种image文件格式: * 通用的bin * intel的hex * S-Record 本文以NXP rt1176 Cortex-M7的处理器为demo,来研究一下 * image文件的种类 * image文件与代码段的管理 生成的二进制文件列表如图所示:  本文的顺序及内容参考[^5],并对[^5]进行扩展和扩充。软件参考[^4] 。 # 1. image文件种类 ## 1.1 Binary 第一种格式叫binary,以.bin为文件后缀,这种格式是一种通用image格式,其完全是机器码裸数据的集合,没有其他任何多余信息,这个数据可以直接被编程器/下载器下载到芯片内部非易失性存储器里,不需要任何额外的数据转换。由于是纯二进制编码的文件,所以普通text编辑器无法正确查看这个文件,需要用专用的十六进制编辑器(比如Hex Editor)才能正常打开。 ...
# 0x01_Linux内核的启动(一)之启动前准备 在广州市图书馆偶然间看到尹锡训 -《ARM Linux内核源码剖析》(코드로 알아보는 ARM 리눅스 커널)[^1],这个书我觉得非常适合我现在看。本书涉及Linux内核启动和处理,紧密和ARM架构机制相结合,一方面可以加深对ARM硬件机制的理解,另一方面能够科普Linux内核内设机制,作为Linux内核机制的入门,相当于从ARM迈入Linux的桥梁。本书需要结合ARM手册和Linux内核两本书同时参考。  # 1. 内核构建系统 操作系统必然是一个非常庞大和复杂的系统[^2]。由调度程序、文件系统、内存管理、网络系统等诸多子系统组成。这种内核十分庞大,**但是其生成只需要一个二进制启动文件**(zImage/bzImage)。可以将**zImage文件就视为内核elf文件**。 ## 1.1 内核初始化和配置 内核初始化状态是从kernel.org下载的tar.gz内核源程序压缩包,解压之后为内核源码的代码树,这种状态叫做**内核的初始状态**。 使用`make mrproper`和 `make distclean`等指令可以内核源码恢复到内核初始状态。注意: * 执行mrproper编译指令,只清除.config文件在内的为内核编译级链接而生成的诸多设置文件。 * 执行distclean编译指令,清除内核编译后生成的所有对象文件、备份文件。 内核在初始状态不可以直接编译,虽然可以生成vmlinux(没有压缩的内核文件[^3]),但大部分情况会引起**内核严重错误(kernel panic)**。因此,需要执行最重要、最需要谨慎处理的**内核配置(kernel configuration)**的过程,也是生成编译必要.config文件的过程。注意: *...
# 1. Overview Cortex-M是32位的处理器,因此处理器能够寻址到4GB的地址空间。M-CPU采用的是哈佛结构,因此数据空间和指令空间在同一个空间维度。这些空间被分为多个区域,后面会介绍memory map。关于M核的存储系统,有以下比较重点features: * 多总线接口允许指令和数据并发访问地址空间。 * AMBA总线协议 * 大小端存储都支持 * 支持非对齐的数据传输 * 支持排他访问(操作系统的信号量) * 比特级的内存访问宽度 * 内存属性和访问权限的配置(指定区域) * MPU # 2. Memory Map 4GB的寻址空间,一部分被内部的外设预留,作为外设访问的地址空间,例如NVIC和一些调试的组件。这些外设的预留的空间都是固定的。还有一部分的空间被分配如图: 这样的分配: * 处理器这样设计是为了支持多种内存,并且对于二级厂家开箱即用。 *...
# 0. 导语 今年的study-2023计划中,包含了rust和Cortex-M处理器架构的学习。截止到目前为止RUST已经学的七七八八,偶然间找到了RUST编写简易操作系统的博客[https://os.phil-opp.com/](https://os.phil-opp.com/) 大为震撼。该博主基于x86架构的芯片使用rust编写了操作系统,里面包含了,中断异常处理、内存分配、还有任务管理的一些机制。受到该博主的启发,或许我们可以基于Cortex-M的同步进行开发。这样做的好处,我们既可以熟悉rust,又可以熟悉Cortex-M,又结合了操作系统的知识,可以说一举三得。我相信理论基础的学习也仅仅是第一步,自己动手编写和调试才能有很深刻的掌握。 我不打算把rbp-os作为一个要交付的“产品”,它不会是一个从顶层到底层的的设计方式。它更像是一种“乐高积木”,一个系统要素一个要素的去实现。在自定义的操作系统中,我们可以随意的增加自己的系统模块。我们按照博主的思路,先去做一个最小的内核,然后慢慢开发中断异常的处理,后续增加内存MMU管理,heap分配器,而这些机制可能一开始我们做一个能够“work”的最简单的实现方式,后续我们慢慢的增强,借鉴Linux内核的处理机制不断的去完善更复杂的场景。 本文会大量的引用: * Linux操作系统或者FreeRTOS中的操作系统机制来解决baremental的问题 * https://github.com/carloscn/blog#rtos * https://github.com/carloscn/blog#linux-kernel * 基于Cortex-M的架构级的机制 * https://github.com/carloscn/blog#armv7-m-cortex-m 本节中会涉及大量关于嵌入式应用方面的知识,硬件架构知识和系统模型分别在上述连接中进行引用。 # 1. 嵌入式平台 ## 1.1 硬件基本介绍 参考 https://stevenbai.top/rustbook/book/intro/hardware.html 的博客,这里提供了很基础的硬件思路,我们将借助该文档对Cortex-M的rust开发环境进行入门级的整理。在博客中使用了[STM32F303VCT6](https://www.st.com/en/microcontrollers/stm32f303vc.html) 微控制器。我自己也买了一个这个平台的微控制器: 该控制器基本的feature为: *...
Github地址:[carloscn/uncle-ben-os at car_lab_06 (github.com)](https://github.com/carloscn/uncle-ben-os/tree/car_lab_06) ### ARMv8指令集介绍 * A64指令集只能运行在aarch64 * 所有A64汇编都是32 bits宽的 * 关注指令的使用、有什么limitation * A64能访问的地址数据是64位宽的 * A64支持全部的大写或者小写方式 * ARM官方大写 * 应用使用小写 * 寄存器命名 * Wn表示32bits宽的寄存器 * Xn表示64bits宽的寄存器 * WZR表示32位内容全为0的寄存器 *...
# 20_ARMv8_barrier(一)流水线和一致性模型 我在工作的时候,又看见osal_wmb()还有osal_rmb()的接口,而那时候有个任务就是要设计osal的套件,针对于内存屏障的接口,有一点不知所措。内存屏障是ARM编程很重要的一部分,尤其是在多核并行的程序中。我们这一节主要就是来描述内存屏障的产生的原因和解决方法。这一节主要的思路来自于《ARM64体系结果编程》,另外从ARMv8的programmer guide中:整理第十三章memory odering、第十四章Multi-core processors中的知识。 内存屏障可以从两个维度发生: * 编译器级。编译器会把C语言转为汇编文件的时候进行优化,如内存访问指令的重排可以提高指令的效率。然而对于一些你对ordering十分care的环境下,这就发生了歧义。通常在`#define barrier() __asm__ __volatile__ ("":::"memory")`告诉编译器不要对此处进行优化。 * CPU级。在指令执行的时候,由于现代的处理器都是采用的超标量的架构、乱序发射(issue)、乱序执行等等,这些技术都是提高执行效率的方法,因此在指令执行的阶段,指令在流水线中可能被打乱,直观的感受就是运行的时候发现和编写的代码不一致。 内存屏障只用于多核系统中,相对于cache而言,**也可以属于多核的一致性问题**。我们理解ARMv8的ordering的问题,就要首先理解流水线的乱序执行和一致性模型的理论基础。 # 1. 流水线技术 我们来先科普一波什么是ARM的流水技术,还有超标量、多发射、乱序执行。 ## 1.1 CPU的流水线指令设计[^3] ### 1.1.1 单指令周期处理器(历史) `程序的性能 = 指令数×CPI×时钟周期`,一个CPU的时钟周期认为是可以完成一条最简单的计算机指令所需要的时间。在**单指令周期处理器(Single Cycle...
# 1. Overview PKCS#11标准定义了与密码令牌(如硬件安全模块(HSM)和智能卡)的独立于平台的API,并将API本身命名为`Cryptoki`(来自“加密令牌接口”,发音为“crypto-key” - 但是“PKCS#11”通常用于指代API以及定义它的标准)。 API定义了最常用的加密对像类型(RSA密钥,X.509证书,DES / 三重DES密钥等)以及使用,创建/生成,修改和删除这些对象所需的所有功能。参考:http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/os/pkcs11-base-v2.40-os.html 本文使用NXP LS1046A来对pkcs11进行验证。pkcs11对硬件有所要求,需要智能卡或者HSM。因此,本文会着重整理关于pkcs11如何和HSM进行配置的部分。NXP提供了Virual HSM,其底层使用OPTEE-OS进行实现;中间层使用`Secure Object Library`,在用户侧使用`Cryptoki`对其进行封装,用户只需要按照要求调用API即可。总结顺序为:OPTEE-OS-> Secure Object Library(SOL) -> Cryptoki APIs。另外,Secure Object Libray还可以被OpenSSL API作为engine使用。 SOL对HSM要求是: * 产生密钥对在HSM内部 * 导入私钥进入HSM内部 私钥对于用户侧永远不可见。 OPTEE内部实现框图如图所示:...