查看: 1094|回复: 0
打印 上一主题 下一主题

STM32中的那些易混淆的点

[复制链接]
跳转到指定楼层
沙发
发表于 2015-9-28 00:09:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
STM32中的那些易混淆的点
外部晶振(external crystal)和外部时钟(external clock)有什么区别?
外部晶振(external crystal),就是晶体。
外部时钟(external clock)  ,就是一个时钟信号。
外部晶振,就是时钟产生电路在内部,只是使用了一个外部的晶振。
外部时钟,则时钟产生电路在外部,至于是否使用晶振,要看它的具体实现。
外部时钟源,即从属模式,在外部接一个可以产生时钟信号的器件,比如时钟发生器;
外部晶体,即震荡模式,是使用片内震荡电路和外部接的晶体来产生时钟信号。

ioremap 和 mmap有什么区别?
ioremap得到的内存,在读写数据时不会存在CACHE里,直达硬件,对于ARM来说,IO和MEM是统一编址的,唯一差别就是CACHE
mmap是给应用程序提供映射地址的
ioremap是为一段高端的物理内存建立映射,即增加相关的页表内容
驱动常用mmap是为可能不连续的一系列逻辑上相关的(如整体是一个文件)物理内存段建立映射,并呈现一个连续的虚拟地址空间,应用程序常用
mmap是系统调用,只能应用程序用
ioremap是kernel提供的函数,只能在kernel里用

ONFI规范
  ONFI(Open NAND Flash Interface,开放式NAND快闪存储器接口)规范是一种Flash闪存接口的标准,它是Intel为统一当初混乱的闪存接口所倡导的标准。要了解ONFI规范,大家要先了解一下Intel推出ONFI规范的初衷。
  此前Intel是主攻NOR闪存的,与NAND阵营打了多年的仗。在当时业界对容量需求还不高的时候,NOR凭借着出众的访问速度与传输带宽,一直打压着NAND的发展,可后来随着整合封装技术的广泛采用,以及对大容量数据存储的需求不断增长,NAND逐渐成为了市场的主流。因此,Intel也深有切入NAND市场之意。不过,在当时的NAND市场已经被三星和东芝占据了近70%,因此在内存领域玩标准出身的Intel只能另辟蹊径推出自家的标准。因为当时市场上销售的NAND闪存芯片在引脚定义方面,各家都不完全相同,这就造成了同一个闪存控制器,如果是为东芝芯片设计的,就很可能出现无法使用三星或海力士芯片的情况,这就给上游的主控设计商以及最终的产品的设计人员出了一个很大的难题。
  为此,Intel提出了ONFI的设想,就是统一NAND闪存芯片的引脚定义,并在此基础上进一步采用新的技术以实现新的功能,并在2006年12月推出了ONFI 1.0标准。而且在ONFI联盟的基础上,Intel、微软与戴尔专门合作成立了NVMHCI(Non-Volatile Memory Host Controller Interface,非易失性存储器主控制器接口)组织,在ONFI标准上,提出针对PC的NAND闪存接口标准,为硬件、主板、固态存储设备、外接式快闪存储装置提供标准硬件操作系统的驱动。
  当然,Intel推出ONFI规范的目的并不单单是为了统一闪存的接口,另一个目的是为了让闪存芯片厂商们配合推广当时的Turbo Memory技术。这就是今天我们最终在P55主板上看到Braidwood技术的前身。目前硬盘是电脑,尤其是笔记本的最大性能瓶颈,而闪存存储技术可以很好的解决这一问题。因此Intel为了提升电脑的启动性能,推出了Turbo Memory闪存加速技术,它曾是当年高端迅驰移动平台的一大卖点。不过,当时由于闪存接口并不统一、将闪存应用到电脑上就会有巨大的障碍。由于Turbo Memory是以Mini Card扩充模块的方式通过PCI-E接口插在主板扩充插槽上,这要求厂商必须重新设计主板。为了让闪存能在PC平台发挥所长,制定统一化的接口标准是推进Turbo Memory技术的一个重要步骤。

NAND Flash与文件系统、oob数据扫盲
NAND每一页大小为(512+16)字节(还有其他格式的NAND,比如每页大小为(256+8)、(2048+64)等),其中的512字节就是一般存储数据的区域,16字节称为OOB(Out Of Band)区。通常在OOB区存放坏块标记、前面512字节的ECC较验码等。
cramfs、jffs2文件系统映像文件中并没有OOB区的内容,如果将它们烧入NOR Flash中,则是简单的“平铺”关系;如果将它们烧入NAND中,则NAND的驱动程序首先根据OOB的标记略过坏块,然后将一页数据(512字节)写入后,还会计算这512字节的ECC较验码,最后将它写入OOB区,如此循环。cramfs、jffs2文件系统映像文件的大小通常是512的整数倍。
而yaffs文件系统映像文件的格式则跟它们不同,文件本身就包含了OOB区的数据(里面有坏块标记、ECC较验码、其他yaffs相关的信息)。所以烧写时,不需要再计算ECC值,首先检查是否坏块(是则跳过),然后写入512字节的数据,最后写入16字节的OOB数据,如此循环。yaffs文件系统映像文件的大小是(512+16)的整数倍。
注意:烧写yaffs文件系统映像时,分区上第一个可用的(不是坏块)块也要跳过。
怎样设置大端模式、小端模式?
1、大端模式还是小端模式,首先受制于硬件,比如STM8就是大段模式;
2、有些时候,有些MCU是可以在硬件上选择大端模式还是小端模式的;
3、如果硬件上没差别,可能取决于编译器,比如Keil C51就是大端模式,而IAR for 51就是小端模式;
4、楼主希望的是大端模式,可以解决这个问题,但是用 union 是不能本质上解决的。

例如S3C6410采用的是小端模式
i2c中,master mode、slave mode 求解释:
master mode 主机模式 (下面例子中老大的模式)
slave mode 从机模式 (下面例子中小混混的模式)
master or slave transmit mode 主机或者从机 发送模式
master or slave receive mode 主机或者从机 接受模式
i2c是一个传输的协议,可以通过协议来传递数据,需要有SCL时钟线和SDA数据线
主机就像老大,控制时钟线,从机就像小混混,小混混可以有1个或者多个 每个有固定的编号
也就是地址,老大如果要叫小混混打一个人,先发送小混混的编号(地址),小混混确认后,老大再发打人的资料(数据),然后小混混得到数据 ,去执行,这就是主机模式!
小混混如果要叫老大救命(数据),就要先申请,掌控时钟线,然后按上述类似步骤,这就是从机模式

href和hsync到底有什么关系?
回答:HREF与HSYNC都是行同步信号,但不同的是HREF是行有效同步信号,即其高电平下都是有效数据;HSYNC的高电平一般其下降沿与HREF一致,但上升沿早于HREF,在某些特殊平台应用时,一般是先采到HSYNC的上升沿,然后开始以PCLK为单位计数,计到一定的数目之后就开始显示数据;
Href,Hsync都是行开始指示信号,一般是sensor output,用来表示新的一行开始输出了。
区别只是电平表现不同,一个是脉冲的形式,一个是整个区间都维持高电平。
不同厂家叫法做法稍有区别,一般不用理会这个,只要关注H信号开始的timing是否满足就好了

高光溢出现象(Blooming):
特指当画面内射入高亮度点光源时,在整个画面从上端至底端形成一条白色条纹(带状)的现象。
高光溢出现象
高光溢出现象.jpg (10.71 KB, 下载次数: 0)
下载附件 保存到相册
高光溢出现象
2015-4-13 10:23 上传





无高光溢出现象
无高光溢出现象.jpg (10.64 KB, 下载次数: 0)
下载附件 保存到相册
无高光溢出现象
2015-4-13 10:23 上传





GPIO与普通IO区别?
GPIO的意思是通用输入输出端口,可由编程决定其状态,MCU的IO就是GPIO,也称双向输入输出端口,
而IO则泛指所有类型的输入输出端口,包括单向的端口如逻辑门电路的输入输出管脚和双向的GPIO端口,而GPIO则必然是双向的,这是为了避免不同语境下易造成混淆而采取的特称。
当然,沟通时的语境是明确的前提下,二者往往混用。

为什么要提出中断线程化?
在Linux中,中断具有最高的优先级。不论在任何时刻,只要产生中断事件,内核将立即执行相应的中断处理程序,等到所有挂起的中断和软中断处理完毕后才能执行正常的任务,因此有可能造成实时任务得不到及时的处理。中断线程化之后,中断将作为内核线程运行而且被赋予不同的实时优先级,实时任务可以有比中断线程更高的优先级。这样,具有最高优先级的实时任务就能得到优先处理,即使在严重负载下仍有实时性保证。but,并不是所有的中断都可以被线程化,比如时钟中断,主要用来维护系统时间以及定时器等,其中定时器是操作系统的脉搏,一旦被线程化,就有可能被挂起,这样后果将不堪设想,所以不应当被线程化。

什么是内存节点node
内存节点node是计算机系统中对物理内存的一种描述方法,一个总线主设备访问位于同一个节点中的任意内存单元所花的代价相同,而访问任意两个不同节点中的内存单元所花的代价不同。在一致存储结构(Uniform Memory Architecture,简称UMA)计算机系统中只有一个节点,而在非一致性存储结构(NUMA)计算机系统中有多个节点。Linux内核中使用数据结构pg_data_t来表示内存节点node。如常用的ARM架构为UMA架构。

Linux 挂起和休眠的区别:
  1、挂起
    挂起是standby,这时只有内存等一些部件通电,不可断电,否则运行的程序都完了;
    挂起是挂起硬盘,把当前工作状态保存在内存中,即硬盘停止供电,但内存还要供电。
    优点:是恢复快;
    缺点:是要持续供电。

    2、休眠
    休眠是把内存中的内容保存到硬盘上,可断掉电源,重启后可以从硬盘上保存的内容恢复到内存中,即恢复到之前的工作状态。
    优点:不需要供电,可休眠很长时间;
    缺点:是恢复速度慢(相对于挂起)。

Linux串口编程VTIME和VMIN的设置
VTIME 定义要求等待的时间,单位:100ms
VMIN 定义要求等待的最小字节数
VTIME=0,VMIN=y:read函数只有在读取了y个字节或收到一个信号的时候才返回
VTIME=x,VMIN=0:即使没有数据可以读取,read函数等待x时间量后返回,这时,read函数不需要像其通常情况那样要遇到一个文件结束标志才返回0
VTIME=x,VMIN=y:此时VTIME定义的是当接收到第一个字节的数据后开始等待的时间量。如果当调用read函数时可以得到数据,计时器马上开始计时。如果当调用read函数时还没有任何数据可读,则等接收到第一个字节的数据后,计时器开始计时。函数read可能会在读取到VMIN个字节的数据后返回,也可能在计时完毕后返回,这主要取决于哪个条件首先实现。不过函数至少会读取到一个字节的数据,因为计时器是在读取到第一个数据时开始计时的。
VTIME=0,VMIN=0:即使读不到任何数据,read函数也会立即返回,同时,返回值0表示read函数不需要等待文件结束标志就返回了
另外特别注意的是当设置VTIME后,如果read第三个参数小于VMIN,将会将VMIN修改为read的第三个参数
GPIO加上拉电阻、下拉电阻的作用:
当GPIO引脚处于第三态(非高低电平,而是高阻态,即相当于没接芯片)时,它的电平状态由上拉电阻和下拉电阻确定

Linux内核中分配4M以上大内存方法:
在Linux内核中,kmalloc能够分配的最大连续内存为2的(MAX_ORDER-1)次方个page
参见alloc_pages函数:
if (unlikely(order >= MAX_ORDER))
return NULL;
page的大小一般是4K bytes,MAX_ORDER缺省定义为11,所以如果不修改内核,kmalloc能够分配的最大连续内存一般是4M bytes

内核中获取4M以上大内存的方法有三种:
1.修改MAX_ORDER,重新编译内核
2.内核启动选型传递"mem="参数, 如"mem=80M", 预留部分内存; 然后通过request_mem_region和ioremap_nocache将预留的内存映射到模块中,需要修改内核启动参数, 无需重新编译内核。 但这种方法不支持x86架构,只支持ARM,PowerPC等非x86架构
3.在start_kernel中mem_init函数之前调用alloc_boot_mem函数预分配大块内存,需要重新编译内核

在不重新编译内核的前提下, x86架构下内核中只能获取到最大4M的连续内存, 或者使用vmalloc获取4M以上的非连续内存. 而且, 无论是kmalloc还是vmalloc, 分配的内存越大, 失败的可能性越大; 系统启动后分配内存的时间越早(此时空闲内存越多, 分部也越规律), 成功的可能性越大。

为什么说Linux的每个进程都享有4GB的内存空间?
首先得分清“可以寻址”和“实际使用”的区别:其实我们讲的每个进程都有4G虚拟地址空间,讲的都是“可以寻址”4G,意思是虚拟地址的0-3G对于一个进程的用户态和内核态来说是可以访问的,而3-4G是只有进程的内核态可以访问的。并不是说这个进程会用满这些空间。其次,所谓“独立拥有的虚拟地址”是指对于每一个进程,你可以访问自己的0-4G的虚拟地址。虚拟地址是“虚拟”的,需要转化为“真实”的物理地址。好比你有你的地址簿,我有我的地址簿。你和我的地址簿都有1、2、3、4页,但是每页里面的实际内容是不一样的,我的地址簿第1页写着3,你的地址簿第1页写着4,对你我自己来说都是用第1页(虚拟),实际上用的分别是第3、4页(物理),不冲突。内核用的896M虚拟地址是直接映射的,意思是只要把虚拟地址减去一个偏移量(3G)就等于物理地址。同样,这里指的还是寻址,实际使用前还是要分配内存。而且896M只是个最大值。如果物理内存小,内核能使用(分配)的可用内存也小。
Linux不大清楚,不过看你描述和Windows类似。32位的Windows,每个进程也有4G地址空间的,仅仅是地址空间,不是实际的内存,需要使用时,向系统申请,系统会分配实际的内存给你,并将你进程中的地址和实际地址进行映射,当然这个映射对你来说是透明的,进程A的地址0x00001000可能映射到实际地址0x10002000,进程B的地址0x00001000可能映射到实际地址0x30003F00,各个进程的地址空间是独立的。地址空间也有个例外,其中高位的1G,就是3G~4G这个地址段是系统内核使用的,应用程序不可直接访问,这段内存地址对于所有进程是相同的,如果0xF0000000在进程A中表示显存开始地址,那么0xF0000000在进程B中也是表示显存开始地址。虚拟内存是很重要的机制,WindowsNT之前win98什么的就是所有进程共用地址空间,虽然少了一道转换,但一个进程可以对所有进程包括系统内存进行修改,所以哪个程序有bug就会造成系统崩溃,就经常蓝屏。
32位意味着4G的寻址空间,linux把它分为两部分:最高的1G(虚拟地址从0xC0000000到0xffffffff)用做内核本身,成为“系统空间”,而较低的3G字节(从0x00000000到0xbffffff)用作各进程的“用户空间”。这样,理论上每个进程可以使用的用户空间都是3G。当然,实际的空间大小收到物理存储器大小的限制。虽然各个进程拥有其自己的3G用户空间,系统空间却由所有的进程共享。从具体进程的角度看,则每个进程都拥有4G的虚拟空间,较低的3G为自己的用户空间,最高的1G为所有进程以及内核共享的系统空间。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入因仑

本版积分规则

快速回复 返回顶部 返回列表