嵌入式软件工程师&&太极拳
全部博文(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. 映射后可以直接读/写屏幕缓冲区,进行绘图和图片显示了。 ----------------------