嵌入式软件工程师&&太极拳
全部博文(548)
分类: LINUX
2011-02-20 19:47:54
Processor
=========
MCU强调把CPU、储存器和外围电路集成在一个芯片中。
主流的CPU核如下:
1. ARM(Advanced RISC Machines)
2. MIPS(Silicon Graphics公司)
3. PowerPC(IBM, Motorola)
CPU的分类:
. 按照应用领域:
1. GPP(通用处理器)
1) MCU(微控制器)
2) MPU(微处理器)
2. DSP(数字信号处理器)
1) 定点DSP
2) 浮点DSP
3. ASP(专用处理器)及ASIC
1) 网络处理器
2) 音视频编解码器
3) ...
. 按体系结构:
1. 冯.诺伊曼结构
将程序指令存储器和数据存储器合并在一起,通过同一条总线访问程序指令和数据,指令和数据宽度相同;
2. 哈佛结构
程序指令和数据分开存储,采用了独立的程序总线和数据总线,指令和数据可以有不同的数据宽度。
. 按照指令集:
1. RISC(精简指令集计算机)
2. CISC(复杂指令集计算机)
存储器:
======
. ROM:只读存储器
1 .不可编程ROM
2. 可编程ROM(PROM)
3. EPROM(可擦除可编程ROM)
4. EEPROM(电可擦除可编程ROM)
. RAM:随机存取存储器
1. SRAM:由6个晶体管组成
2. DRAM:由1个晶体管和1个电容器组成。数据存放在电容器中,需要定期刷新。
SDRAM
DDR SDRAM: 同时利用时钟脉冲的上升沿和下降沿传输数据,数据传输频率加倍。
3. 特定用途的RAM:
NVRAM: 非易失性RAM
DPRAM: 双端口RAM
CAM: 内容寻址RAM
FIFO: 先进现出队列
...
. Flash:闪存
1. Nor Flash(与非):类似SRAM的访问接口,XIP(eXecute In Place)
2. Nand Flash(或非):必须控制电路进行转换
NAND Flash的接口:
I/O总线: 传输地址、指令和数据
nCE: 芯片使能
nWE: 写使能
nRE: 读使能
CLE(Command Latch Enable): 命令锁存使能
ALE(Address Latch Enable): 地址锁存使能
nR/B(Ready/Busy): 就绪/忙
3. 名词解释:
CFI(Common Flash Interface):一个公开的、标准的从NOR Flash器件读取数据的接口
. 光介质存储器
. 磁介质存储器
接口和总线:
==========
串口:
RS-232:
RS-232C:为连接DTE(数据终端设备)和DCE(数据通信设备)而制定。1969年发布。
标准接口有:
1. 25条线(4条数据线、11条控制线、3条定时线、7条备用和未定义线)
2. 9条线:
RTS/CTS:请求发送/清除发送流控制
RxD/TxD:数据收发
DSR/DTR:数据终端就绪/数据设置就绪流控制
DCD:数据载波检测,也称RLSD
Ringing-RI:振铃指示
SG:信号地
组成RS-232C串口的硬件原理:
CPU <----> UART <----> CMOS/TTL电平与RS-232C电平转换器 <----> DB9/DB25的连接器
RS-422:单机发送、多机接收的单向、平衡传输规范。改进了RS-232通信距离短、速率低的缺点。
RS-485:增加了多点、双向通信能力
IIC总线(内置集成电路总线)
由两个信号组成:SDA(数据线)和SCL(时钟线)
支持多主控模式(multi-mastering),主控能控制数据的传输和时钟频率,在任意时刻只能有一个主控
IIC的信号格式:
1个开始位: SCL稳定在高电平时,SDA由高到低的变化就产生一个开始位
传输1字节从设备地址位(前7位为设备地址,最后1位为读写标志)
再传输1字节数据,每个字节传完后,在SCL的第9个上升沿到来之前,接收方应该发出1个ACK位。
1个停止位; SCL为高电平时,SDA由高到低的变化就产生一个停止位
USB(通用串行总线)
USB提供4种传输方式:
1. control(控制传输方式)
双向传输,数据量通常较小。主要用于进行查询、配置和给USB设备发送通用的命令。
2. Synchronization(同步传输方式)
提供确定的带宽和间隔时间,用于时间严格并具有较强容错性的流数据传输。如:语音业务传输。
3. Interrupt(中断传输方式)
主要用于定时查询设备是否有中断数据要传送。如:键盘、鼠标等
4. Bulk(批量传输方式)
主要应用在没有带宽和间隔时间要求的大量数据的传送和接收。如:打印机和扫描仪等。
以太网接口:
由MAC + PHY组成(以太网媒体接入控制器和物理接口收发器)
MAC:实现数据链路层
PHY:实现物理层功能
MII(媒体独立接口):用于连接MAC和PHY。包括:1个数据接口和1个MAC和PHY之间的管理接口。
以太网接口电路原理:
CPU <----> MAC <----> PHY <----> 隔离变压器 <----> RJ45插座
ISA总线(工业标准结构总线):
ISA的接口信号有3组:
总线基本信号:如复位、时钟、电源、地等;
总线访问信号:访问ISA总线设备的地址线、数据线以及相应的应答信号;
总线控制信号:中断和DMA请求。
PCI(外围部件互连)和cPCI(Compact PCI)
特点:
. 数据总线为32位,可扩充到64位;
. 总线时钟频率为33MHz或66MHz,最高传输率可达528MB/s;
连接方式:
各部分通过PCI总线和PCI-PCI桥连接在一起。
PCI卡刚加点时,卡上只有配置空间是可被访问的。配置空间共为256字节。
cPCI:是以PCI电气规范为标准的高性能工业用总线。
CPLD和FPGA
==========
CPLD(复杂可编程逻辑器件)
. CPLD的基本逻辑单元是宏单元,宏单元由一些"与或"阵列加上触发器构成。
. "与或"阵列完成逻辑功能,"触发器"完成时序逻辑
. 组成部分:
LAB(逻辑阵列模块,由多个宏单元组成)
PIA(可编程互连阵列)
I/O控制模块
FPGA(现场可编程门阵列)
. 基于LUT(查找表)工艺。
. 组成部分:
IOC(输入/输出控制模块):每个IOC包含一个双向I/O缓冲器和一个既可做输入寄存器,也可做输出寄存器的触发器。
EAB(嵌入式阵列块):一种输入输出端带有寄存器的非常灵活的RAM。
可以作为RAM,也可以事先被写入查表值构成如:乘法器、纠错逻辑等电路。
LAB:一个LAB包括多个LE(逻辑单元),每个LE包括组合逻辑及一个可编程触发器。
FAST TRACK(快速通道互连)
字符设备、块设备、网络设备的差异:
1. 字符设备:以串行顺序依次进行访问,不经过系统的快速缓冲;
2. 块设备:以块为单位进行操作,可以用任意顺序进行访问(如:硬盘,软驱,flash);
3. 网络设备:不对应文件系统的节点,以socket方式访问(struct net_device, sk_buf);
platform_driver, usb_driver,pci_driver都是总线和接口类设备驱动。
用来给具体的char, net, block,tty设备驱动提供接口。
主要包括:
probe
remove/disconnect
shutdown
resume
struct platform_device:常用于SoC中的外设控制器。
i2c设备驱动:
1. 主要数据结构(p355-356):
2. 工程师要实现的主要工作(p357)
1)
第16章 linux网络设备驱动
========================
linux系统对网络设备驱动定义了4个层次:
1. 网络协议接口层;
. 主要功能:
给上层协议提供透明的数据包发送和接受接口;
dev_queue_xmit() --发送包函数
netif_rx() --接受包函数
2. 网络设备接口层;
3. 提供实际功能的设备驱动功能层;
4. 网络设备与媒介层。
设计网络设备驱动要完成的主要工作:
1. 编写设备驱动功能层的相关函数以填充net_device数据结构的内容;
1) struct net_device中的相关函数:
open <--> xxx_open()
stop <--> xxx_stop()
set_config <--> xxx_config()
hard_start_xmit <--> xxx_tx()
do_ioctl <--> xxx_ioctl()
hard_header <--> xxx_hard_header()
get_stats <--> xxx_get_stats()
tx_timeout <--> xxx_tx_timeout()
change_mtu <--> xxx_change_mtu()
xxx_poll()
2) 接收网络数据包引发的中断处理函数
主要功能:读取硬件上接收到的数据包并传送给上层协议。
xxx_interrupt():完成中断类型判断等基本功能。
xxx_rx():完成数据包的生成和递交上层等复杂工作。
2. 将struct net_device注册到内核。
网络设备的注册/注销:
int register_netdev(struct net_device *dev);
void unregister_netdev(struct net_device *dev);
net_device的分配赋值/释放:
struct net_device *alloc_netdev(int sizeof_priv,
const char *name,
void(*setup)(struct net_device *));
struct net_device *alloc_etherdev(int sizeof_priv);
void free_netdev(struct net_device *dev);
第18章 LCD设备驱动
==================
-----------------------
帧缓冲设备驱动的模块加载/卸载函数模板:
static int __devinit xxxfb_init(void)
{
return platform_driver_register(&xxxfb_driver);
}
static void __exit xxxbf_cleanup(void)
{
platform_driver_unregister(&xxxfb_driver);
}
module_init(xxxfb_init);
module_exit(xxxfb_cleanup);
----------------------
----------------------
帧缓冲设备驱动平台类驱动的探测/移除函数模板:
/* 平台驱动结构体 */
static struct platform_driver xxxfb_driver = {
.probe = xxxfb_probe,
.remove = xxxfb_remove,
.suspend = xxxfb_suspend,
.resume = xxxfb_resume,
.driver = {
.name = "xxx-lcd",
.owner = THIS_MODULE,
},
};
static int __init xxxfb_probe(...)
{
struct fb_info *info;
/* 分配fb_info结构体 */
info = framebuffer_alloc(...);
info->screen_base = framebuffer_virtual_memory;
info->var = xxxfb_var;
info->fix = xxxfb_fix;
/* 分配显示缓冲区 */
alloc_dis_buffer(...);
/* 初始化lcd控制器 */
lcd_init(...);
/* 检查可变参数 */
xxxfb_check_var(&info->var, info);
/* 注册fb_info */
if(register_framebuffer(info) < 0)
return -EINVAL;
return 0;
}
static void __exit xxxfb_remove(...)
{
struct fb_info *info = dev_get_drv_data(dev);
if(info)
{
unregister_framebuffer(info); /* 注销fb_info */
}
dealloc_dis_buffer(...); /* 释放显示缓冲区 */
framebuffer_release(info); /* 注销fb_info */
return 0;
}
------------------------
------------------------
帧缓冲设备显示缓冲区的分配/释放:
static int __init xxxfb_map_video_memory(struct xxxfb_info *fbi)
{
fbi->map_size = PAGE_ALIGN(fbi->fb->fix.smem_len + PAGE_SIZE);
fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size,
&fbi->map_dma, GFP_KERNEL); /* 分配内存 */
fbi->map_size = fbi->fb->fix.smem_len;
if(fbi->map_cpu)
{
memset(fbi->map_cpu, 0xf0, fbi->map_size);
fbi->screen_dma = fbi->map_dma; /* 物理地址 */
fbi->fb->screen_base = fbi->map_cpu; /* 虚拟地址 */
fbi->fb->fix.smem_start = fbi->screen_dma;
}
return fbi->map_cpu ? 0 : -ENOMEM;
}
static inline void xxxfb_unmap_video_memory(struct s3c2410fb_info *fbi)
{
dma_free_writecombine(fbi->dev, fbi->map_size, fbi->map_cpu,
fbi->map_dma);
}
-----------------------
-----------------------
填充struct fb_ops中的主要函数指针:
fb_check_var()
fb_set_var()
fb_fillrect() -- cfb_fillrect()
fb_copyarea() -- cfb_copyarea()
fb_imageblit() -- cfb_imageblit()
fb_setcolreg() /* 实现伪颜色表和颜色表的填充 */
fb_setcolreg()函数模板:
static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp, struct fb_info *info)
{
struct xxxfb_info *fbi = info->par; /*xxxfb_info指针存放在fb_info中*/
unsigned int val;
switch(fbi->fb->fix.visual)
{
case FB_VISUAL_TRUECOLOR:
if(regno < 16)
{
u32 *pal = fbi->fb->pseudo_palette;
val = chan_to_field(red, &fbi->fb->var.red);
val |= chan_to_field(green, &fbi->fb->var.green);
val |= chan_to_field(blue, &fbi->fb->var.blue);
pal[regno] = val;
}
break;
case FB_VISUAL_PSEUDOCOLOR:
if(regno < 256)
{
val = ((red >> 0) & 0xf800);
val |= ((green >> 5) & 0x07e0);
val |= ((blue >> 11) & 0x001f);
writel(val, XXX_TFTPAL(regno));
schedule_palette_update(fbi, regno, val);
}
break;
...
}
return 0;
}
----------------------
用户空间访问帧缓冲设备显示缓冲区的范例:参考fb_ops_user.c文件
操作/dev/fbn的一般步骤:
1. 打开/dev/fbn设备文件;
2. 用ioctl()操作取得当前显示屏幕的参数,如:屏幕分辨率、每个
像素点的比特数和偏移。根据屏幕参数可计算屏幕缓冲区的大小;
3. 将屏幕缓冲区映射到用户空间;
4. 映射后可以直接读/写屏幕缓冲区,进行绘图和图片显示了。
----------------------