0%

基本原理

GPIOF->BSRR = 0x00000001;

通用输入输出端口,就相当于一大堆导线,只不过可以通过代码对这些导线做到开关控制。每根导线相当于一条导线。对于输入也是看每条导线上的电压,电压高就是1,电压低就是0,这样就可以表示任何可以数字化的信息。

Read more »

STM32芯片介绍

STM32是ST公司以ARM cortex-M为内核的单片机,有很多外设(peripheral)。这里的外设就是定时器,串口,GPIO,SPI等等。ST公司是意大利和法国的两个公司合并而来的。

STM32是个一些列MCU的总称,有多种选项可选,根据命名规则标识芯片规格。

相关学习资料的主要来源包括:ARM公司,ST公司,开发板公司

MCU工作原理

从图中我们可以看出一个MCU一般由CPU(中央处理单元)、地址空间、片上外设三个部分组成。CPU是处理器的核心,它控制着整个系统的运作。片上外设以及芯片内部的各种存储设备都会被映射到地址空间中,使得我们在编写程序的时候只需要对地址空间中的某一段进行读写就可以操控外设了。 片上外设实际上是一个集合,指的是MCU芯片内部为实现某一特殊功能而专门设计的模块,比如说串口、GPIO等等,它们都会映射到地址空间中。

一个芯片上有很多引脚,它们有片上外设控制,是连接芯片内部与用户设备之间的桥梁。 每个引脚的功能基本都是确定的,不过为了节省资源同一个引脚往往对应几个不同的功能。所以具体一个引脚是用作串口还是输出PWM信号,除了由其物理属性决定之外, 还需要在程序中通过软件进行配置。通过正确的连接和配置引脚的功能,合理的操控片上外设,我们就可以控制LED,驱动SD卡,进而实现期望的功能。

MCU工作原理

注:以上部分转自网上一篇文章STM32的启动过程

最小系统

用STM32组成的最小系统需要:供电、复位、时钟、Boot模式、下载、后备电池几个部分。

如果自行设计一个PCB,至少需要考虑这几个部分,然后才是其他功能。

  • 供电
    • 要考虑模拟电源、数字电源分开。AMS1117是种输出电压为3.3V的正向低压降稳压器
  • 复位:就是一个按钮开关,接一下地就ok了
  • 时钟:高速,低速精准
  • Boot:两个引脚决定启动模式。就是从SRAM启动,还是从Flash启动
  • 下载:SWD、JTAG、串口
  • 后备电池:1n4148是小型的高速开关二极管

MAC上STM32开发环境搭建

  1. gcc-arm-embedded:arm cortex平台的编译器,开源,免费

brew cask install gcc-arm-embedded

  1. st-link : st公司开发的upload工具

brew install stlink

  1. PlatformIO IDE(VSCode 插件)

在vscode中安装PlatformIO,这个会自动下载MCU所需要的HAL库,能够自动编译,上传,还是比较方便。

这样就有IDE + Toolchain + Loader,而且都是开源免费的

对嵌入式开发的肤浅理解

MCU内核就是一个CPU,现在普遍用ARM,我想主要是因为生态好。STM32能够广泛被应用,也是因为生态好。其实如果认真看看MIT6.004,都能设计一个CPU出来,但是非主流的指令集没人用。而且小众CPU的成本肯定高。

MCU的外设就是一个电路,他通过寄存器的电压信号,再加上各种电路,比如晶体管,电阻,或者与非门,选择器,移位器等等,来实现数据传递。如果传数据,那就是按照时序,一位位的把信息传递出去。每一位在物理层面传递的只是高电压和低电压,通过人为约定变成0或1。如果传控制信号,可能就是用PWM信号传递。

我原来理解的外设就是鼠标,键盘,显示器这些叫外设。但是在MCU的世界里面,一小块接口电路就叫外设,其实他就是一个外设接口,仅仅是信息通路。

学习MCU就是学习他的各种机制,或者简单说就是规则。然后从外部接数据,和给外部发数据,来实现某种应用。这些应用更多的就是为了让人们省时省力省钱。MCU的软件开发其实就是调用厂家提供的API实现功能,难度和JS开发差不多,不会有什么核心技术。当然一整套完整的嵌入式开发还是牵扯的面比较广,器件选型,接口电路设计,PCB制版,焊装,代码开发,调试运行。内容也不少。但这些毕竟是应用技术,就当是开开眼界吧。

很想做一个全栈开发,但是不太可能。这些知识太多,而且如果只是流于表面,那也只是停留在科普水平。完全深入不太可能,记住所有细节也不可能,了解所有细节也不可能。

只能靠随机碰运气,似乎也是很郁闷。

那该怎么办?

随缘。如果自己感兴趣,就去记录,何必在意结果呢。我想用比较简单的文字,记录在当下这一刻,我所知道和理解的一点点知识。也许写的是错的,也许很多遗漏,而且肯定过两天就忘了。但是那又能怎样呢?无所谓!心态!

软件

  • Program Language
  • Network
  • DB
  • DS / Algorithm
  • Compiler
  • OS
    • 驱动开发

电子

  • 单片机
    • STM32
    • STM32开发准备
  • 数电
  • 模电
  • 电路

机械

基础

  • 物理
    • 理论力学
  • 数学
    • 线性代数
    • 微积分

机器人

  • 入门
    • 斯坦福大学公开课——机器人学,Oussama Khatib
    • 教程:John Craig,Introduction to Robotics: Mechanics and Control
  • 实践
    • 比赛:RoboMaster、飞思卡尔智能车大赛、电子设计大赛
    • Penn’s Robotics Specialization(Coursera)
      • Aerial Robotics
      • Computational Motion Planning
      • Mobility
      • Perception
      • Estimation and Learning
    • ROS
      • 官网的教程ROS Tutorials(Robot Operating System, ROS)
      • 硬件平台:TurtleBot、Baxter、Universal Robot
  • 进阶
    • 补数学
      • 数值计算方法:《Numerical Methods for Engineers》
      • 凸优化:Stanford 的公开课《Convex Optimization》
    • Modern Robotics (Coursera)
    • 李群李代数《Notes on Differential Geometry and Lie Groups, I & II》
    • 控制:
      • youtube Brian Douglas
      • Khalil 的教材《Modeling, identification and control of robots》
    • 运动规划
      • 教材《Planning Algorithms》
      • 教材《Principles of Robot Motion Theory, Algorithms, and Implementations》
    • 机器学习
    • 强化学习
      • Sutton 的《Introduction to reinforcement learning》
  • 论文:RSS、ICRA、IROS 等相关会议,了解机器人领域的最新进展

虚拟这两个字太讨厌了。虚拟文件系统一点都不虚拟,做了很多实在的工作。

文件系统
  • 对于要长期保存的数据,独立保存起来,这块数据叫做一个文件。文件和目录形成文件系统。

  • 裸机情况下,硬盘只能根据地址定位一段数据的读写,没法用。需要os进行统一分配和管理

  • 文件描述符,“描述符”,类似还有全局描述符,页目录描述符,其实就是一个struct,里面有各种属性信息。文件被打开后,os会在内核记录被打开文件的属性,还包括状态和信息

    • 文件指针,最近一次读写位置,每个进程维护自己
    • 打开次数
    • 文件磁盘位置,缓存
  • os:文件就是数据块;用户:文件是数据结构

  • 文件读写必须以块为单位,内存是以字节为单位:

    • 读:读出一块,返回对应部分;写:读出一块,修改,写回一块
  • 目录实现

    • 列表、hash表
    • 根目录在磁盘中位置固定
    • PWD,当前工作路径
文件系统分层

类unix文件系统,把标准输入,输出,磁盘文件,网络socket都看成文件。这样就会给程序员,有统一的读写接口。最基础的接口无非就是open, read, write, close。整体分层如下:

  • libc的接口(如:open,read)
  • syscall接口(sys_read, sys_write)
  • vfs接口 (vfs_open, vfs_read)
    • 为什么有这层?主要是为了同一个不同io的接口。统一都使用inode表示一个文件。inode是个索引节点,通过inode,可以找到文件具体在磁盘上的位置。
  • 具体文件系统接口
    • 每个文件系统都有自己的数据结构,主要是如何把数据放到磁盘上
    • 一般来说,都是前面有个superblock,记录整体信息
    • 然后是根目录的inode。对于目录的inode就是记录了每一项的inode位置。
    • 通过目录inode,就可以找到文件的inode。
    • 文件的inode记录每块数据的存储位置。
  • 设备接口(driver)
    • 具体向io发起指令的部分,跟外设相关
文件系统功能

分配磁盘空间

管理文件块

空闲空间管理

分配算法

文件操作
  • 打开:

    • 内核会记录所有打开的文件
  • 读文件

    • 获取字节所在数据块
  • 写文件

    • 先读一块,修改,然后写会
基本数据结构

文件系统基本数据结构,这些全部是在硬盘上的

  • 文件卷控制块(superblock)

    • 对应文件系统,空余块
    • 在磁盘上位置是固定的,他指向目录项
    • 文件系统mount的时候,就是读取这部分数据
  • 文件控制块

    • 每个文件一个
    • 数据块位置
  • 目录项

    • 指向文件数据块,父目录,子目录

文件描述符

  • 对应打开的文件
  • 文件状态信息
  • 系统有系统级全局的打开文件表,每个进程有自己的打开文件表
  • 打开文件,目录项和文件都需要被打开
加载内存时间
  • 卷控制块:文件系统挂载时,载入内存
  • 文件控制块:当文件被访问的时候
  • 目录节点:在遍历文件路径
文件分配
  • 三种分配方式:连续、链式、索引
  • 索引分配:在文件头里指向索引块,索引块保存指向每个数据块指针
  • 对于大文件,用链式索引块,或多级索引块
  • UFS多级索引分配,文件头包含13个指针
文件打开操作
  • 先找到对应设备
  • 从对应设备的mount的fs,进行lookup
  • 找到文件inode,读磁盘加载
  • 保存对应文件inode,到file列表
  • 返回fd给应用进程

内核线程

当bios把os的内核代码从磁盘上加载到内存, os完成内存初始化后,就可以开始执行各种函数进行工作了,单片机就是到这一步,后续执行自身的代码逻辑。而os是给通用计算用的,他需要加载用户程序,所以还不能这么简单的处理。单片机的模式是传感器->cpu/软件逻辑->执行机构,计算机的模式是输入->cpu/软件->人。计算机的输出,驱动的是人,而不是步进马达。

os在加载用户进程前,还要先创建一些必要的内核线程。这些线程也会和用户进程一起参与调度。为了能让多个线程,并发执行,os需要设计一套机制,能够让多个线程、进程共存和切换。这套机制中会有很多复杂的数据结构,会利用栈,会利用很多寄存器。

内核之所以能够切换这些线程或进程,是通过切换相关寄存器来实现的,比如切换eip,代码执行位置就变了,切换esp,ebp,进程的栈就变了。所以,切换前要保护现场,就是要找块内存记录下这些值。这些值是PCB进程控制块的一个成员叫context,context保存了8个寄存器。

内核把当前执行线,封装为主线程,叫idle_proc,实际上他只是做调度。

idle_proc创建了init_main这个内核线程,init_main创建了user_main,启动用户shell。然后init_main就进入wait状态,然后也是反复执行schedule()。

内核线程会通过调用schedule(),主动放弃cpu,换句话说,就是用户进程没法通过时钟中断抢到cpu。而用户进程时间片一到就会被os强制放弃cpu。

用户进程

加载用户进程

os内存管理的目标是做到高效分配回收内存,支持多进程并发使用,又要做到进程之间的隔离。内存是一堆三极管,电容等器件组成的电路模块。每个内存单元有两个属性,对程序开发特别重要,一个是地址,一个是单元内保存的数据。

物理内存管理

分页机制

分页是CPU和操作系统共同实现的内存管理方式。目的是为了尽可能的减少内存碎片,同时可以让多个进程共享内存。把一个逻辑地址,通过页表转换为一个物理内存地址。转换过程是依靠CPU中的MMU单元。页表的数据是由操作系统来生成。x86架构是在80386推出时(1985年),实现的页机制。

物理内存管理上,只要启动分页机制,就是“虚拟”内存,这一层是CPU的机制(MMU单元的功能)。

OS在此基础上,对每个用户进程进行了隔离,在x86_32上,每个进程都可以访问4G的空间,但其实物理机器上有可能只有1G的内存,这个是通过swap机制实现的。

分页机制可以减少内存碎片。可以把不连续的逻辑地址,可以分配成连续物理内存空间。也可以把连续的逻辑地址,分配成不连续的物理空间。

分页机制可以把不同逻辑地址,映射到相同的物理地址上。

Read more »

系统启动

  1. CPU上电,加载BIOS
  2. BIOS从MBR上加载BootLoader
  3. BootLoader设置保护模式,加载内核
  4. 内核进行初始化,进入用户shell

中断机制

  1. 中断初始化 填中断门描述符
  2. 时钟中断
  3. int 0x80 系统调用 系统调用是操作系统给应用程序提供的接口API。通过中断,应用程序可以对外设、网络进行读写。
  4. trapframe
Read more »

最近在学习清华操作系统原理课程,他们的课程有实验环节,虽然参考了很多xv6,但是他们的有课程视频,还有实验指导书,学起来比mit6.828还是轻松不少。课程基本都已经听完了,实验也都跑通了,后面打算花一周时间把各章收获总结一下。

Read more »