首页 嵌入式学习笔记3
文章
取消

嵌入式学习笔记3

2022.9.6

串口通信的基本概念

串口通信的特点

  1. 异步:发送方与接收方之间无统一时钟信号。
  2. 电平信号:串口通信出现的时间较早、速率较低、传输距离近,所以采用了电平信号传输。
  3. 串行:每次只能传送1个二进制位。

RS232电平和TTL电平

在电平信号是,多少V代表1,多少V代表0不是固定的,而是取决于电平标准。

  1. RS232电平标准:-3V~-15V表示1,+3V~+15V表示0;
  2. TTL电平标准:+5V表示1,0V表示0.
  3. 区别在于适用的环境和条件不同,RS232适用于距离远、干扰大的情况,TTL电平适合距离近、干扰小的情况。

波特率

波特率指的是串口通信的速率,即通信时每秒钟可以传输多少个二进制位,比如波特率为9600(每秒传输9600个二进制位)。

串口的波特率为选择特定值,不可随意选择,常用的为9600或115200.

  1. 通信双方需事先设定好相同的波特率才可以成功通信;
  2. 使用的过程中形成的共识,常用这两个值。

串口通信的流程

  1. 串口通信以周期为单位进行,这个周期就是一个通信单元,由起始位+数据位+奇偶校验位+停止位组成。
  2. 起始位:代表一个通信单元的开始,由串口通信标准事先指定,由通信线上的电平变化来反映;
  3. 数据位:是一个通信单元中发送的有效信息位,一次发送多少数据可以指定,通常选择8位数据位,便于发送ASCII编码数据发送;
  4. 奇偶校验位:用来校验数据,需校验的数据总和为奇/偶,从而决定为0/1,一定程度上防止位翻转;
  5. 停止位:代表一个通信单元的结束,基本上使用1位停止位,由通信线上的电平变化来反映。

通信双方需要事先约定好通信参数,包括波特率、数据位、奇偶校验位、停止位。(起始位唯一,不用手动选择)

串口通信的基本原理

串口通信最少需要2根(GND和信号线),可以实现单工通信;3根通信线(Tx,Rx,GND),可以实现全双工。

  1. 单工:单方向,A发B收;
  2. 半双工:同时只能单方向,单方向可以改变,同一时间内A发B收B发A收;
  3. 全双工:双方同时收发,A发B收同时B发A收。

串口通信的关键参数设置错误,将会导致串口通信出错。

信息在

2022.9.4

通信的基础概念

通信中最重要的两个方面:信息表示、解析方法 + 信息的传输方法,通信双方要实现约定好表示及解析方法。

同步通信和异步通信

  1. 同步:发送方和接收方以同一时钟节拍下工作;
  2. 异步:发送方和接收方没有统一的时钟节拍,各自按照自己的节拍工作。
  3. 同步通信:发送信息的同时发送时钟信号,接收方根据发送方的时钟来安排自己的节奏,用于经常通信时、交换频率固定时。
  4. 异步通知:接收方不用一直等待发送方,发送方发送信息前会先发送一个起始信号,接收方开始接收信息,直到再次收到结束信号,用于双方通信频率不固定时。

电平信号和差分信号

  1. 用来描述通信线路传输方式,即如何在线路上表达1和0;
  2. 电平信号:传输线中有一个参考电平(GND),信号上的信号值由信号线电平和参考电平线的电压差决定;
  3. 差分信号:传输中没有参考电平,1和0的表达靠信号线之间的电压插;
  4. 总结:电平信号中的2个通信线之间的电平差异容易收到干扰,传输容易失败;差分信号不容易收到干扰,传输质量比较稳定,现在基本上使用差分信号
  5. 因为差分信号抗干扰能力强,一个发送周期更短。

并行接口和串行接口

  1. 串行、并行主要是考虑信号线的根数,即同时可以传递信息量的多少;
  2. 电平信号下,1根参考电平线+1根信号线可以传输1位二进制,1根参考电平线+2根信号线可以同时传输2位二进制,以此类推;
  3. 差分信号下,2根线(彼此差分)可以发送1位二进制,发送2位二进制需要4根线(两套彼此差分);
  4. 串行一次只能发送1次二进制,并行接口一次可以发送多位二进制,但串行使用更广,因为更省信号线,对线材要求低,可以通过提高通信速度来提升整体通信性能。

最终得到了异步、串行、差分,譬如USB和网络通信。

2022.8.29

SoC时钟系统

基础概念

时钟是同步工作系统的同步节拍

SoC内部中的多个器件需要协同工作,需要同步的时钟系统来指挥。

时钟的获得方式

  1. 使用引脚从外部直接输入时钟信号(多个设备同步时钟)
  2. 外部晶体振荡器+内部时钟发生器产生时钟(低频单片机)
  3. 外部晶体振荡器+内部时钟发生器+内部PLL产生高频时钟+内部分频器分频得到各个频率的时钟(S5PV210)

时钟频率的高低与系统性能有很大影响,官方建议800MHz~1.2GHz,一般为1GHz主频(主要频率)

每个外设的工作都需要一定频率的时钟,并由时钟系统编制控制工作模式,确定每个外设的时钟来源时钟分频系统

频率高 –> 功耗大 –> 不稳定 –> 散热条件苛刻

外设未使用的时候最好关掉,否则会导致功耗提升、发热增大,开关外设通过时钟系统来控制。

时钟域

  1. MSYS(Master):包含CPU、DRAM控制器、IRAM&IROM等
  2. DSYS(Digital):视频显示、编解码相关模块
  3. PSYS:和内部的各种外设有关,串口、SD接口、I2C、AC97、USB等
  4. 因为内部模块彼此工作时钟速率差异太大,按照速度分类放到一起(高/低速)

时钟来源

  1. APLL:用于MSYS域
  2. MPLL&EPLL:用于DSYS&PSYS域
  3. VPLL:用于Video相关模块

时钟域详解

  1. MSYS:
    1. ARMCLK:给CPU内核使用的时钟,即主频(1000MHz)
    2. HCLK_MSYS:MSYS域的高频时钟,DMC0和DMC1使用(200MHz)
    3. PCLK_MSYS:MSYS域的低频时钟(100MHz)
    4. HCLK_ITEM:给iROM和IRAM(iMEM)使用(100MHz)
  2. DSYS:
    1. HCLK_DSYS:DSYS域的高频时钟(166MHz)
    2. PCLK_DSYS:DSYS域的低频时钟(83MHz)
  3. PSYS:
    1. HCLK_PSYS:PSYS域的高频时钟(133MHz)
    2. PCLK_PSYS:PSYS域的低频时钟(66MHz)
    3. SCLK_ONENAND:(133MHz 166MHz)

各个时钟的典型值:刚上电时(24MHz),iROM初始化后(系统默认推荐运行频率)

2022.8.25

初始化DDR2

初始化的一些注意事项

  1. 初始化与SoC有关,也和使用的芯片有关,初始化步骤有数据手册可得知共有27步;     
  2. 初始化DRAM时分为两步,第一部分初始化DRAM0(256MB),第二部分初始化DRAM1(256MB)。
  3. 代码取自于开发版uboot及厂商教程,外加自己修改理解。

设置IO端口驱动强度

DDR芯片和SoC芯片通过引脚连接,通信时要一定的驱动信号,并且需要一定的电平水平来抗干扰,所以需要设置这些引脚的驱动能力。

DRAM控制器对应的引脚设置为驱动强度2x,该数据是参考自原厂的代码。

2022.8.24

SDRAM

定义

SDRAM:同步动态随机存储器;

DDR即为DDR SDRAM

特性

SDRAM属于动态内存,需要先运行一段初始化代码来初始化才可以使用。

市场高度标准化,基本上由主流厂商主导。

原理图分析

210开发版共有两个内存端口(类似于台式机两个内存插槽),两个内存端口分别为DRAM0(Port1)、DRAM1(Port2)。

DRAM0:0x2000000~0x3FFFFFFF(512M),对应引脚XM1.

DRAM1:0x40000000~0x7FFFFFFF(1024M),对应引脚XM2.

即最多支持1.5G内存,更多的内存无法识别。

本开发版只有512MB内存,合法地址为0x20000000~0x2FFFFFFF(256MB),0x40000000~0x4FFFFFFF(256MB).

每个DDR端口都由3类总线构成:

  1. 地址总线:Xmn_ADDR0~Xmn_ADDR13共14颗
  2. 数据总线:Xmn1_DATA0~Xmn_ADDR31共32颗
  3. 控制总线:原理图中间部分

采用两颗16位的内存并联得到了32位内存,地址总线接法一样,数据总线相加起来,就可以将2个芯片看成1个。

SDRAM部分原理图

框图位128Mb*8,8指8Bank,每个Bank为128Mbit。

210的DDR端口信号中有BA0~BA2,用来寻找Bank的

通过row address(14位)+column address(10位)综合寻址,类似于平面直角坐标系。

能寻址的范围为2的24次方,即16MB/128Mbit。

adr与ldr的区别

ldr:长加载,加载符号地址时,加载的是链接地址 adr:短加载,加载符号地址时,加载的是运行地址

重定位只重定位代码段+数据段的长度,bss段不需要重定位

2022.8.20

设置栈和调用C语言

volatile的作用

让程序在编译时,编译器不对程序做优化,避免在测试时达不到自己想要的效果。是否有效取决于编译器,如果本身不会做优化,则是否添加不会有差别。

启动iCache

定义

cache是一种内存,为高速缓存。

210中有32KB iCache(用来缓存指令)和32KB dcache(用来缓存数据)。

启动方法

1
2
3
4
	mrc p15,0,r0,c1,c0,0;	//读取cp15的c1到r0中
	bic r0, r0, #(1<<12)	  //bit12 置0 关icache
	orr r0, r0, #(1<<12)	  //bit12 置1 开icache
	mcr p15,0,r0,c1,c0,0;	//存入

可以明显看到关闭iCache时,程序运行速度变慢。

重定位引入和链接脚本(重点内容)

一些基本概念

  1. 位置无关编码PIC:汇编源文件被编码成二进制可执行文件时,编码方式与位置(内存地址)无关。
  2. 位置有关编码:…,编码方式与位置(内存地址)有关。
  3. 在设计程序时,会给这个程序指定运行地址(编译地址),得到的二进制可执行程序理论上与运行地址有关,且必须在这个地址上运行;但有些特别指令会和指定的地址无关,即位置无关代码。
  4. 链接地址:编译的时候指定的地址,Makefile中用 -Text或链接脚本。
  5. 运行地址:运行的时候真正使用的地址,由实际运行时被加载到内存的那个位置说了算。

对于位置有关代码来说,若运行地址与链接地址不同时,运行会出错。对于位置无关代码来说,使用有限制,不能完成所有功能。

linux中应用程序:默认链接地址为0x0; 210中的裸机程序:由CPU设计决定,0xd0020010;

210的启动过程

三星推荐的启动方式

假定bootloader必须介于16KB~96KB,开机上电后BL0运行,加载前16KB(BL1)到SRAM中运行,BL1运行时会加载BL2(剩余)到SRAM中运行,BL2运行时会初始化DDR并将OS放到DDR中执行。

UBoot执行方式

uboot大小随意,开机上电后BL0运行,BL0会加载uboot的前16KB(BL1)到SRAM中运行,BL1运行时会初始化DDR,将整个uboot搬运到DDR中,然后用长跳转(SRAM~DDR)指令直接到DDR中执行uboot,执行完成后从uboot中启动OS。

uboot方式更加灵活,bootloader启动更加有针对性,更稳定。

重定位的重要性

链接地址和运行地址有的时候必须不相同,且不能全部用位置无关码,这时候只能使用重定位

源代码到可执行程序的步骤

  1. 预编译:由预编译器执行,比如C中的宏定义、注释由预编译器处理。
  2. 编译:由编译器来执行,将 .c .s 等源码编译成机器码 .o
  3. 链接:由链接器来执行,将 .o 文件中各函数按照规则(链接脚本来制定)链接在一起,最终形成可执行文件。
  4. strip :将生成的可执行文件中的符号信息去除,节省内存。(可选)
  5. objcopy:由可执行程序生成可烧录的镜像bin文件。(可选)

程序段

代码段、数据段、bss段、自定义段等。

段名的分类

  1. 先天性段名
    1. 代码段.text,函数编译后生成的东西
    2. 数据段.data,C语言中有显式初始化为非0的全局变量
    3. bss段.bss,零初始化(ZI)段,C语言中初始化为0的全局变量
  2. 后天性段名
    1. 段名、属性及特征由自己定义

现象的解释

  1. C语言中全局变量未显示初始化,值为0.–>C语言在定义此变量时将其放入了bss段
  2. C运行时显式初始化为非0的全局变量值在main函数前就被赋值了。–>变量放在了.data段中,.data段在main函数前就被处理

链接脚本的作用

本质上是个规则文件,用来指挥链接器工作的。链接器会参考链接脚本,并且使用其中规定的规则来处理.o中的段,生成可执行程序。

重点是:段名+地址

1
2
3
SECTIONS{} 整个链接脚本 
. 当前地址
= 赋值

2022.8.18

看门狗

看门狗的定义

看门狗定时器:SoC内部的一个定时器,定好时间之后回计时,时间到之前必须重新置位,若未执行将会被强制执行。

因为一些外部因素,电子设备经常会跑飞或者死机。在这种情况下我们希望设备自动复位而非人工干预。

系统正常工作时,系统会自动置位定时,所以不会复位。但如果系统故障,会在下一个周期自动复位,达到我们期望的效果。

物理特性

物理特性上就是个定时器,一个SoC的内部外设。

看门狗属于内部外设,没有外部的原件与他有关,所以原理图上无法找到看门狗。

数据手册7.3 WatchDog Timer

关键操作寄存器

WTCON(0xE2700000)的bit5,0代表关,1代表开

设置栈及调用C

C语言运行环境

C语言运行时runtime需要一定的条件,这些条件由汇编来提供,主要是需要。C语言的局部变量都是用栈来实现的,如果未预先设置合理合法的栈地址,那么局部变量会落空。

CPU模式和各种模式下的栈

ARM中37个寄存器,每种模式下都有自己独立的SP寄存器(r13),如果每个模式都用一个sp,如果应用程序出错,会导致操作系统也会崩溃。

系统在复位后默认进入SVC,所以直接设置SP即可。

栈必须是一段可用的内存(可用:必须有被初始化且可以访问,只会用作栈),CPU刚启动,外部DRAM为初始化,可用内存仅有内部的SRAM。

寻找可用内存段的规则:SVC Stack(0xD0037780~0xD037D80)

  1. 满栈:进栈(先移动指针再存数据),出栈(先出数据再移动指针)
  2. 空栈:进栈(先存数据再移动指针),出栈(先移动指针再出数据)
  3. 减栈:进栈(指针向下移动),出栈(指针向上移动)
  4. 增栈:进栈(指针向上移动),出栈(指针向下移动)

在ARM中,ATPCS(最新为AAPCS)要求使用满减栈

所以

汇编与C语言的互相调用

bl cfunction

C语言访问寄存器的语法

寄存器的地址类似于内存地址,所以就是用C语言来读写内存地址,使用指针来操作。

unsigned int *p = (unsigned int *)0xE0200240
*p = 0x11111111; 
本文由作者按照 CC BY 4.0 进行授权

嵌入式学习笔记2

-