2771

帖子

0

TA的资源

裸片初长成(中级)

41
 

TO SOSO

我来回答这个问题,
  
   所谓低层驱动,就是和下面的硬件打交道,主要靠配置相关寄存器来完成的,大家都知道,做硬件靠的都是平时的功底的积累,什么A/D,D/A,GPIO,UART,做这方面和单片机开发比较类似了.
    嵌入式门槛比较高,高在"硬软兼施".不仅仅需要掌握软件编程和操作系统,还要具备良好的硬件功底.在开发LINUX系统的原作者已经是顶尖级高手,而且开发过程中不能使自己收益.他们做出来的东西缺少注释,即"官方"文档.也是LINUX中比较难学的一点.在图形界面的支持上,LINUX不及WINDOWDS.
   其实,我们做的工作很简单,就是把PC上的LINUX拿到MCU上去做,不需要你去写操作系统这些高深的技巧.只需要做些设备驱动和应用软件就可以了!

赞赏

1

查看全部赞赏


回复

196

帖子

0

TA的资源

五彩晶圆(中级)

42
 
呵呵,从零学起,好~
 
 

回复

196

帖子

0

TA的资源

五彩晶圆(中级)

43
 
底层驱动还有另一层含义(个人认为):那就是如何实现上层软件和底层硬件的相互通信问题。
 
 
 

回复

68

帖子

0

TA的资源

纯净的硅(中级)

44
 

bootloader部分初稿已经完成,正在审稿,不久便可发布出来。敬请期待...

bootloader部分初稿已经完成,正在审稿,不久便可发布出来。敬请期待...
 
 
 

回复

68

帖子

0

TA的资源

纯净的硅(中级)

45
 

下面进行第二阶段:bootloader (1)

一. BootLoader简介

应用程序

文件系统

操作系统内核

BootLoader

简单的说bootloader是一段程序,它的作用就是加载操作系统,BootLoader(引导加载程序是系统加电后运行的
第一段软件代码。通过这段代码实现硬件的初始化,建立内存空间的映射图,为操作系统内核准备好硬件环境并引导内核的启动。如右图所示的那样在设备的启动过程中bootloader位于最底层,首先被运行来引导操作系统运行,很容易可以看出 bootloader是底层程序所以它的实现严重地依赖于硬件,特别是在嵌入式世界。因此,在嵌入式世界里建立一个通用的BootLoader几乎是不可的。尽管如此,一些功能强大、支持硬件环境较多的BootLoader也被广大的使用者和爱好者所支持,从而形成了一些被广泛认可的、较为通用的的bootloader实现。简单的介绍几种:

1.U-BOOT(下载地址http://sourceforge.net/projects/u-boot

uboot是一个庞大的公开源码的软件。他支持一些系列的arm体系,包含常见的外设的驱动,是一个功能强大的板极支持包。其代码可以从下载 U-BOOT是由PPCBOOT发展起来的,是PowerPC、ARM9、Xscale、X86等系统通用的Boot方案,从官方版本 0.3.2开始全面支持SC系列单板机。u-boot是一个开源的bootloader

2vivi(下载地址http://www.mizi.com/developer

vivi是韩国mizi 公司开发的bootloader, 适用于ARM9处理器。 Vivi有两种工作模式:启动加载模式和下载模式。启动加载模式可以在一段时间后(这个时间可更改)自行启动linux内核,这vivi的默认模式。如果修改或更新需要进入下载模式,在下载模式下,vivi为用户提供一个命令行接口通过接口可以使用vivi提供的一些命令,来实现flash的烧写、管理、操作mtd分区信息、启动系统等功能。


其它还有一些bootloader实现如下表所示:
名称
说明
支持的架构
LILO
Linux的磁盘引导加载程序
x86
GRUB
LILOGNU版本
x86
Loadlin
DOS引导Linux
x86
RedBoot
eCos为基础的引导程序
x86 ARMPowerPCMIPS
ROLO
ROM引导Linux,且不需要BIOS
x86
Etherboot
从以太网卡启动Linux系统的固件
x86
LinuxBIOS
Linux为基础的BIOS的替代品
x86
blob
来自LART计划的引导程序
ARM

由于u-boot的通用性好,功能全面,适合初学者学习和使用,我们选用u-boot作为基准代码,在此基础上进行修改,完成移植工作。

二.移植准备
1.目标板:

这是进行U-Boot移植首先要明确的。可以根据目标板上CPUFLASHSDRAM的情况,以尽可能相一致为原则,先找出
一个与所移植目标板为同一个或同一系列处理器的U-Boot支持板为移植参考板。


以上图片是本次移植所用到的开发板实物图
一些重要参数如下:
CPU处理器
Samsung S3C2440AL,主频400MHz,最高533MHz
SDRAM内存
板载64MB SDRAM
32bit数据总线
SDRAM时钟频率高达100MHz
Hynix809E
Flash存储器
板载64MB Nand Flash,掉电非易失
板载2MB Nor Flash
K9F1208u00

[ 本帖最后由 topembedded 于 2009-8-20 14:39 编辑 ]
 
 
 

回复

1668

帖子

0

TA的资源

裸片初长成(初级)

46
 
原帖由 jxb01033016 于 2009-8-19 17:38 发表
我来回答这个问题,
  
   所谓低层驱动,就是和下面的硬件打交道,主要靠配置相关寄存器来完成的,大家都知道,做硬件靠的都是平时的功底的积累,什么A/D,D/A,GPIO,UART,做这方面和单片机 ...

hehe. 这个同意。
做一段时间驱动以后,对于常见外设的工作模式有了一定的理解,如网卡的收发、BD队列等概念,成型以后就明白一个设备如何work的。这样遇到问题也能够迎刃而解了。
其实在不同操作系统下,外设的驱动大同小异,只是各个操作系统的驱动模型不同,从语言的角度来说就是挂接各个函数钩子手段的区别。实际的设备工作模型是不变的。
 
 
 

回复

1668

帖子

0

TA的资源

裸片初长成(初级)

47
 
原帖由 jxb01033016 于 2009-8-19 14:41 发表
补充几个

    1,chmod 755 xxx
              修改文件权限

这个,不完整,chmod 755只是让所有用户可读可执行,文件拥有者可写。
最后三位是8进制数。用ls -al可以看到这个八进制数的意义。

root@rattata% ls -al
total 808
drwxr-xr-x   3 root  wheel    512 Aug 17 01:04 .
drwxr-xr-x  11 root  wheel    512 Aug 17 01:05 ..
-rw-r--r--   1 root  wheel    361 Aug 16 22:24 .cshrc
-rw-------   1 root  wheel   2609 Aug 20 18:23 .history
-rw-r--r--   1 root  wheel   1090 Aug 16 22:24 .login
-rw-r--r--   1 root  wheel    215 Aug 16 22:24 .profile
drwx------   2 root  wheel    512 May 25 23:01 .ssh
-rw-r--r--   1 root  wheel  48932 Jul 16 01:00 RP.config
-rw-r--r--   1 root  wheel  49060 Jul 28 22:35 ReceiverDR.config
-rw-r--r--   1 root  wheel  49204 Aug 11 22:28 ReceiverDR_diffzone.config
-rw-r--r--   1 root  wheel  49217 Jul 28 22:48 ReceiverDR_norpf.config
-rw-r--r--   1 root  wheel  49165 Aug 11 22:26 ReceiverDR_samezone.config
-rw-r--r--   1 root  wheel  48711 Jul 13 20:33 SourceDR.config
-rw-r--r--   1 root  wheel  48928 Jun 17 01:45 cluster.config
-rw-r--r--   1 root  wheel  46560 Jun  4 01:53 rattata.config
root@rattata%

如上, 第一个d表示是否为目录。后面的9个bit对应的就是三位八进制数,分别代表文件拥有者的读/写/执行权限,文件拥有者所在组的读/写/执行权限和其他用户的读/写/执行权限。
 
 
 

回复

68

帖子

0

TA的资源

纯净的硅(中级)

48
 
–         
网卡

DM9000EP

DM9

2.源文件:

选择一标准的u-boot代码:u-boot-1.1.6

3.烧写工具:
u-boot的烧写使用JTAG线进行下载,用SJF2440.exe软件进行烧写,使用DNW终端进行串口调试。用串口线相连。

4.知识储备:
u-boot的目录结构:
目录
说明
board
和一些已有开发板有关的文件,比如makefileU-Boot.ldS等都和具体开发板的硬件和地址分配有关。
common
与体系结构无关的文件,实现各种命令的C文件
cpu

CPU相关文件,其中的子目录都是以U-Boot所支持的CPU为名,比如子目录arm926ejSmips等,每个特定的子目录都包括cpu.cinterrupt.cstart.s。其中cpu.c初始化CPU、设置指令cache和数据cache等。Interruput.c设置系统的各种中断和异常;start.sU-Boot自动执行时的第一个文件,它主要是设置系统堆栈和工作方式,为进入C程序奠定基础。

disk
Disk驱动的分区处理代码
doc
文档
drivers
通用设备驱动程序,例如各种网卡、支持CFIFlash、串口、USB
fs
支持文件系统的文件,目前支持cramfsfatfdosjffs2registerfs
include
头文件,还有对各种硬件平台支持的汇编文件,系统配置文件等
net
与网络有关的代码,BOOTP协议、TFTP协议、RARPNFS
lib_arm
ARM体系结构相关的代码
tools
创建S-Record格式文件和U-Boot images的工具

u-boot代码:
由于代码比较庞大,只简单分析启动部分。网络和书很多书中有详细的分析,如果想详细了解查阅相关资料,或着提出讨论,还可以登陆顶嵌公司网站技术文档里查看。网址:http://www.top-e.org/jiaoshi/html/?320.html
 
 
 

回复

1668

帖子

0

TA的资源

裸片初长成(初级)

49
 

回复 49楼 topembedded 的帖子

hehe, 很不错,连tool-chain的代码都和盘托出了。
tool-chain虽然一般都open source,不过不同的厂商还是会有所修改的。总的来说,level比较高的同学,学习这些code能很有收获。
 
 
 

回复

2771

帖子

0

TA的资源

裸片初长成(中级)

50
 
原帖由 richiefang 于 2009-8-21 10:44 发表

这个,不完整,chmod 755只是让所有用户可读可执行,文件拥有者可写。
最后三位是8进制数。用ls -al可以看到这个八进制数的意义。

root@rattata% ls -al
total 808
drwxr-xr-x   3 root  wheel    512 Aug 1 ...



我再来补充下:  第一个字母为d表示这是文件目录
    ...   c表示为字符设备文件
    ...   - 为普通文件
    ...   b      块设备文件
          p     管道文件

赞赏

1

查看全部赞赏

 
 
 

回复

68

帖子

0

TA的资源

纯净的硅(中级)

51
 

下面进行第二阶段:bootloader (2)

U-Boot启动过程可以分成两个阶段(stage)

下面是u-boot启动过程的流程图其中左右两部分分别是启动过程的两个阶段

第一阶段(stage 1)是依赖于CPU体系结构的代码(如设备初始化代码等),一般用汇编语言来实现。主要进行以下方面的设置:设置ARM进入SVC模式、禁止IRQFIQ、关闭看门狗、屏蔽所有中断。设置时钟(FCLK,HCLK,PCLK)、清空I/D cache、清空TLB、禁止MMUcache、配置内存控制器、为搬运代码做准备、搬移uboot映像到RAM中(使用copy_loop实现)、分配堆栈、清空bss段(使用clbss_l实现)。

第二阶段(stage 2)通常用C语言来实现。
start_armboot():

一系列初始化(cpu, 板卡,中断,串口,控制台等),开启I/D cache。初始化FLASH,根据系统配置执行其他初始化操作。打印LOG,使能中断,获取环境变量,初始化网卡。最后进入main_loop()函数。在main_loop函数中会检查bootdelaybootcmd环境变量,如果bootcmd已经设置过,则在等待bootdelay个毫秒后会自动执行bootcmd。如果等待过程中被用户中断(ctl+c)或者bootcmd没有设置,则会等待用户输入命令。


关键点一:
U-Boot移植参考板

这是进行U-Boot移植首先要明确的。可以根据目标板上CPUFLASHSDRAM的情况,以尽可能相一致为原则,先找出
一个与所移植目标板为同一个或同一系列处理器的U-Boot支持板为移植参考板。对U-Boot移植新手,建议依照循序渐进的原则,目标板文件名暂时先用移
植参考板的名称,在逐步熟悉U-Boot移植基础上,再考虑给目标板重新命名。在实际移植过程中,可用Linux命令查找移植参考板的特定代码,如 grep –r 2410 ./ 可确定出在U-Boot中与smdk2410板有关的代码,依此对照目标板实际进行屏蔽或修改。同时应不局限于移植参考板中的代码,要广泛借鉴U-Boot 中已有的代码更好地实现一些具体的功能。

关键点二:
U-Boot烧写地址和CPU寄存器参数设置


不同目标板,对U-BootFLASH中存放地址要求不尽相同。事实上,这是由处理器中断复位向量来决定的,与主板硬件相关
。也就是说,U-Boot烧写具体位置是由硬件决定的,而不是程序设计来选择的。


根据CPU处理器系列、类型不同,寄存器名称与作用有一定差别。必须根据目标板的实际,进行合
理配置。一个较为可行和有效的方法,就是借鉴参考移植板的配置,再根据目标板实际,进行合理修改。这是一个较费时间和考验耐力的过程,需要仔细对照处理器
各寄存器定义、参考设置、目标板实际作出选择并不断测试。


关键点三:串口调试。

能从串口输出信息,即使是乱码,也可以说U-Boot移植取得了实质性突破。
依据笔者调试经历,串口是否有输出,除了与串口驱动相关外,还与FLASH相关的寄存器设置有关。因为U-Boot是从FLASH中被引导启动的,如果 FLASH设置不正确,U-Boot代码读取和执行就会出现一些问题。因此,还需要就FLASH的相关寄存器设置进行一些参数调试。同时,要注意串口收发
芯片相关引脚工作波形。依据笔者调试情况,如果串口无输出,有一种可能就是该芯片损坏或工作不正常。
如果出现乱码,有一种可能就是波特率等参数设置有问题。

三.修改源代码:
1.
添加新开发板信息
1)顶层Makefile:为了能让u-boot在编译之前根据此规则来获得具体的配置文件和编译规则。

smdk2410_config :   unconfig
    @$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0
之后,添加以下内容:
tq2440_config :   unconfig
    @$(MKCONFIG) $(@:_config=) arm arm920t tq2440 NULL s3c24x0
添加交叉编译器路径(根据个人情况):
ifeq ($(ARCH),arm)
CROSS_COMPILE= /opt/crosstool/gcc-3.4.5-glibc-2.3.6/arm-softfloat-linux/bin/arm-softfloat-linux-
endif

2)建立新开发板目录:可以把类似的开发板进行修改
cd board
mkdir tq2440
cd tq2440
cp -arf ../smdk2410/* .
mv smdk2410.c tq2440.c

3)修改 board/tq2440/u-boot.lds


cpu/arm920t/start.o
(.text)后添加:
board/tq2440/boot_init.o (.text)

并在tq2440目录下新建boot_init.c文件,内容参考源文件,该代码主要实现了CopyCode2Ram函数,该函数功能是拷贝flash代码到sdram中,实现原理如下图。

CopyCode2Ram函数实现原理

4)修改tq2440目录下的Makefile
COBJS
:= tq2440.o flash.o boot_init.o

5)修改tq2440.c
增加宏定义:
#define S3C2440_MPLL_400MHZ     ((0x7f<<12)|(0x02<<4)|(0x01))
#define S3C2440_UPLL_48MHZ      ((0x38<<12)|(0x02<<4)|(0x02))
 
 
 

回复

68

帖子

0

TA的资源

纯净的硅(中级)

52
 
S3C2440的主时钟源来自外部晶振(XTIPLL)或外部时钟(EXTCLK)。S3C2440有两个PLLphase locked loop)一个是MPLL,一个是UPLLMPLL用于CPU及其他外围器件,UPLL用于USB      

     1MPLL, 用于产生FCLK HCLK PCLK三种频率, 这三种频率分别有不同的用途:
     FCLKCPU提供的时钟信号。
     HCLK是为AHB总线提供的时钟信号, Advanced High-performance Bus,主要用于高速外设,比如内存控制器,中断控制器,LCD控制器, DMA 等。
S3C2440DataSheet里可以看到,S3C2440最大支持400MHz的主频,但是这并不意味着一定工作在400MHz下面,可以通过设定MPLL, UPLL寄存器来设定CPU的工作频率。
     PCLK是为APB总线提供的时钟信号,Advanced Peripherals Bus,主要用于低速外设,比如看门狗,UART控制器, IIS, I2C SDI/MMC, GPIORTC and SPI等。


     2UPLL,专门用于驱动USB host/Device。并且驱动USB host/Device的频率必须为48MHz
   如果要设置MPLLUPLL,要注意它们的先后顺序,MPLLUPLL的设定是有前后顺序的,必须先设定UPLL,然后才能设定MPLL,而且中间需要大约7个空指令(NOP)的间隔。
定义MPLL/UPLL/CLKDIV,参考S3C2440芯片用户手册,参考255页内容如下:





#define S3C2440_CLKDIV
0x05
/* FCLK:HCLK:PCLK = 1:4:8 */

该寄存器参考内如下:






  1. int board_init (void)
  2. {
  3.         S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
  4.         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();

  5.         /* FCLK:HCLKCLK = 1:4:8 */
  6.         clk_power->CLKDIVN = S3C2440_CLKDIV;
  7.         /* change to asynchronous bus mod */
  8.         __asm__(    "mrc    p15, 0, r1, c1, c0, 0\n"    /* read ctrl register   */  
  9.                         "orr    r1, r1, #0xc0000000\n"      /* Asynchronous         */  
  10.                         "mcr    p15, 0, r1, c1, c0, 0\n"    /* write ctrl register  */  
  11.                         :::"r1"
  12.                    );

  13.         /* to reduce PLL lock time, adjust the LOCKTIME register */
  14.         clk_power->LOCKTIME = 0xFFFFFF;

  15.         /* configure MPLL */
  16.         clk_power->MPLLCON = S3C2440_MPLL_400MHZ;

  17.         /* some delay between MPLL and UPLL */
  18.         delay (4000);

  19.         /* configure UPLL */
  20.         clk_power->UPLLCON = S3C2440_UPLL_48MHZ;

  21.         /* some delay between MPLL and UPLL */
  22.         delay (8000);

  23.         /* set up the I/O ports */
  24.         gpio->GPACON = 0x007FFFFF;
  25.         gpio->GPBCON = 0x00044555;
  26.         gpio->GPBUP = 0x000007FF;
  27.         gpio->GPCCON = 0xAAAAAAAA;
  28.         gpio->GPCUP = 0x0000FFFF;
  29.         gpio->GPDCON = 0xAAAAAAAA;
  30.         gpio->GPDUP = 0x0000FFFF;
  31.         gpio->GPECON = 0xAAAAAAAA;
  32.         gpio->GPEUP = 0x0000FFFF;
  33.         gpio->GPFCON = 0x000055AA;
  34.         gpio->GPFUP = 0x000000FF;
  35.         gpio->GPGCON = 0xFF95FFBA;
  36.         gpio->GPGUP = 0x0000FFFF;
  37.         gpio->GPHCON = 0x002AFAAA;
  38.         gpio->GPHUP = 0x000007FF;

  39.         /* arch number of SMDK2410-Board */
  40.         gd->bd->bi_arch_number = MACH_TYPE_S3C2440;

  41.         /* adress of boot parameters */
  42.         gd->bd->bi_boot_params = 0x30000100;

  43.         icache_enable();
  44.         dcache_enable();

  45.         return 0;
  46. }
复制代码




 
 
 

回复

68

帖子

0

TA的资源

纯净的硅(中级)

53
 


  1. (6)lowlevel_init.S
  2. #define B1_BWSCON          (DW32)  修改为  #define B1_BWSCON         (DW16)
  3. #define B5_BWSCON          (DW16)  修改为  #define B5_BWSCON         (DW8)
  4. #define REFCNT                1113 /* period=15.6us, HCLK=60Mhz, (2048+1-15.6*60) */
  5. 修改为
  6. #define REFCNT                0x4f4/*period=7.8125us,HCLK=100Mhz, (2048+1-7.8125*100) */

  7. 二. 头文件修改 include/configs/tq2440.h
  8. (1) cp include/configs/smdk2410.h include/configs/tq2440.h
  9. (2) 增加宏定义:
  10. #define CONFIG_DRIVER_DM9000          1
  11. #define CONFIG_DM9000_BASE        0x20000300
  12. #define DM9000_IO                    CONFIG_DM9000_BASE
  13. #define DM9000_DATA               (CONFIG_DM9000_BASE + 4)
  14. #define CONFIG_DM9000_USE_16BIT
  15. #define CONFIG_SETUP_MEMORY_TAGS    1
  16. #define CONFIG_CMDLINE_TAG          1
  17. (3)#define CONFIG_COMMANDS \中增加如下三项:
  18.                      CFG_CMD_PING     | \
  19.                      CFG_CMD_JFFS2    | \
  20.                      CFG_CMD_NAND       | \
  21. (4)修改网络相关参数:
  22. #define CONFIG_BOOTDELAY          1
  23. #define CONFIG_BOOTARGS            "noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0"
  24. #define CONFIG_ETHADDR                     0a:1b:2c:3d:4e:5f
  25. #define CONFIG_NETMASK                     255.255.255.0
  26. #define CONFIG_IPADDR                  192.168.1.6
  27. #define CONFIG_SERVERIP                     192.168.1.8

  28. (5)#define CONFIG_AMD_LV400   1     /* uncomment this if you have a LV400 flash */
  29. #if 0
  30. #define CONFIG_AMD_LV800    1     /* uncomment this if you have a LV800 flash */
  31. #endif
  32. 修改为:
  33. #if 0
  34. #define CONFIG_AMD_LV400    1     /* uncomment this if you have a LV400 flash */
  35. #endif
  36. #define CONFIG_AMD_LV800    1     /* uncomment this if you have a LV800 flash */

  37. (6) 在最后#endif   /* __CONFIG_H */前增加NAND相关宏定义:
  38. #define CFG_NAND_BASE           0
  39. #define CFG_MAX_NAND_DEVICE     1
  40. #define NAND_MAX_CHIPS          1


  41. 三. 修改cpu/arm920t/start.S
  42. (1) #elif defined(CONFIG_S3C2410)后添加:
  43. # define INTMOD     0X4A000004
  44. (2)将
  45. /* FCLK:HCLK:PCLK = 1:2:4 */
  46.        /* default FCLK is 120 MHz ! */
  47.        ldr   r0, =CLKDIVN
  48.        mov r1, #3
  49.        str   r1, [r0]
  50. 修改为:
  51. #if 0
  52.        /* FCLK:HCLK:PCLK = 1:2:4 */
  53.        /* default FCLK is 120 MHz ! */
  54.        ldr   r0, =CLKDIVN
  55.        mov r1, #3
  56.        str   r1, [r0]
  57. #endif

  58. (3) 在
  59. bl      cpu_init_crit
  60. #endif后面加上
  61.        /* Set up the stack                                         */
  62. stack_setup:
  63.        ldr   r0, _TEXT_BASE         /* upper 128 KiB: relocated uboot   */
  64.        sub  r0, r0, #CFG_MALLOC_LEN       /* malloc area                      */
  65.        sub  r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */

  66.        sub  sp, r0, #12             /* leave 3 words for abort-stack    */

  67.     bl clock_init

  68. (4)  将下列代码替换
  69. #ifndef CONFIG_SKIP_RELOCATE_UBOOT
  70. relocate:                       /* relocate U-Boot to RAM        */
  71.        adr   r0, _start        /* r0 <- current position of code   */
  72.        ldr   r1, _TEXT_BASE         /* test if we run from flash or RAM */
  73.        cmp     r0, r1                  /* don't reloc during debug         */
  74.        beq     stack_setup

  75.        ldr   r2, _armboot_start
  76.        ldr   r3, _bss_start
  77.        sub  r2, r3, r2        /* r2 <- size of armboot            */
  78.        add  r2, r0, r2        /* r2 <- source end address         */

  79. copy_loop:
  80.        ldmia       r0!, {r3-r10}         /* copy from source address [r0]    */
  81.        stmia       r1!, {r3-r10}         /* copy to   target address [r1]    */
  82.        cmp r0, r2                    /* until source end addreee [r2]    */
  83.        ble   copy_loop
  84. #endif     /* CONFIG_SKIP_RELOCATE_UBOOT */

  85.        /* Set up the stack                                         */
  86. stack_setup:
  87.        ldr   r0, _TEXT_BASE         /* upper 128 KiB: relocated uboot   */
  88.        sub  r0, r0, #CFG_MALLOC_LEN       /* malloc area                      */
  89.        sub  r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */
  90. #ifdef CONFIG_USE_IRQ
  91.        sub  r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
  92. #endif
  93.        sub  sp, r0, #12             /* leave 3 words for abort-stack    */
  94. 替换为:
  95. #ifndef CONFIG_SKIP_RELOCATE_UBOOT
  96. relocate:                       /* relocate U-Boot to RAM        */
  97.        adr   r0, _start        /* r0 <- current position of code   */
  98.        ldr   r1, _TEXT_BASE         /* test if we run from flash or RAM */
  99.        cmp     r0, r1                  /* don't reloc during debug         */
  100.        beq     clear_bss

  101.        ldr   r2, _armboot_start
  102.        ldr   r3, _bss_start
  103.        sub  r2, r3, r2        /* r2 <- size of armboot            */
  104. #if 1
  105.        bl  CopyCode2Ram      /* r0: source, r1: dest, r2: size */
  106. #else
  107.        add  r2, r0, r2        /* r2 <- source end address         */

  108. copy_loop:
  109.        ldmia       r0!, {r3-r10}         /* copy from source address [r0]    */
  110.        stmia       r1!, {r3-r10}         /* copy to   target address [r1]    */
  111.        cmp r0, r2                    /* until source end addreee [r2]    */
  112.        ble   copy_loop
  113. #endif
  114. #endif     /* CONFIG_SKIP_RELOCATE_UBOOT */


复制代码


[ 本帖最后由 topembedded 于 2009-8-28 13:14 编辑 ]
 
 
 

回复

68

帖子

0

TA的资源

纯净的硅(中级)

54
 
  1. 4.相关头文件
  2. (1) include/s3c24x0.h
  3. 在下面结构体中添加S3C24X0_REG32 CAMDIVN;
  4. typedef struct {
  5. S3C24X0_REG32 LOCKTIME;
  6. S3C24X0_REG32 MPLLCON;
  7. S3C24X0_REG32 UPLLCON;
  8. S3C24X0_REG32 CLKCON;
  9. S3C24X0_REG32 CLKSLOW;
  10. S3C24X0_REG32 CLKDIVN;
  11. }

  12. 添加NAND寄存器结构体
  13. /* NAND FLASH (see S3C2440 manual chapter 6, www.top-e.org) */
  14. typedef struct {
  15. S3C24X0_REG32 NFCONF;
  16. S3C24X0_REG32 NFCONT;
  17. S3C24X0_REG32 NFCMD;
  18. S3C24X0_REG32 NFADDR;
  19. S3C24X0_REG32 NFDATA;
  20. S3C24X0_REG32 NFMECCD0;
  21. S3C24X0_REG32 NFMECCD1;
  22. S3C24X0_REG32 NFSECCD;
  23. S3C24X0_REG32 NFSTAT;
  24. S3C24X0_REG32 NFESTAT0;
  25. S3C24X0_REG32 NFESTAT1;
  26. S3C24X0_REG32 NFMECC0;
  27. S3C24X0_REG32 NFMECC1;
  28. S3C24X0_REG32 NFSECC;
  29. S3C24X0_REG32 NFSBLK;
  30. S3C24X0_REG32 NFEBLK;
  31. } /*__attribute__((__packed__))*/ S3C2440_NAND;


  32. (2) cpu/arm920t/s3c24x0/speed.c
  33. 【1】在#define MPLL 0
  34. #define UPLL 1上面增加
  35. DECLARE_GLOBAL_DATA_PTR;
  36. 【2】在 m = ((r & 0xFF000) >> 12) + 8;
  37. p = ((r & 0x003F0) >> 4) + 2;
  38. s = r & 0x3;后面 增加
  39. /* support both of S3C2410 and S3C2440 */
  40. if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)
  41. return((CONFIG_SYS_CLK_FREQ * m) / (p << s));
  42. else
  43. return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s)); /* S3C2440 */
  44. 【3】增加宏定义
  45. /* for s3c2440 */
  46. #define S3C2440_CLKDIVN_PDIVN (1<<0)
  47. #define S3C2440_CLKDIVN_HDIVN_MASK (3<<1)
  48. #define S3C2440_CLKDIVN_HDIVN_1 (0<<1)
  49. #define S3C2440_CLKDIVN_HDIVN_2 (1<<1)
  50. #define S3C2440_CLKDIVN_HDIVN_4_8 (2<<1)
  51. #define S3C2440_CLKDIVN_HDIVN_3_6 (3<<1)
  52. #define S3C2440_CLKDIVN_UCLK (1<<3)

  53. #define S3C2440_CAMDIVN_CAMCLK_MASK (0xf<<0)
  54. #define S3C2440_CAMDIVN_CAMCLK_SEL (1<<4)
  55. #define S3C2440_CAMDIVN_HCLK3_HALF (1<<8)
  56. #define S3C2440_CAMDIVN_HCLK4_HALF (1<<9)
  57. #define S3C2440_CAMDIVN_DVSEN (1<<12)
  58. 【4】get_HCLK get_PCLK函数修改
  59. ulong get_HCLK(void)
  60. {
  61. S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
  62. unsigned long clkdiv;
  63. unsigned long camdiv;
  64. int hdiv = 1;

  65. /* support both of S3C2410 and S3C2440 */
  66. if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)
  67. return((clk_power->CLKDIVN & 0x2) ? get_FCLK()/2 : get_FCLK());
  68. else
  69. {
  70. clkdiv = clk_power->CLKDIVN;
  71. camdiv = clk_power->CAMDIVN;

  72. /* work out clock scalings */

  73. switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
  74. case S3C2440_CLKDIVN_HDIVN_1:
  75. hdiv = 1;
  76. break;

  77. case S3C2440_CLKDIVN_HDIVN_2:
  78. hdiv = 2;
  79. break;

  80. case S3C2440_CLKDIVN_HDIVN_4_8:
  81. hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
  82. break;

  83. case S3C2440_CLKDIVN_HDIVN_3_6:
  84. hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
  85. break;
  86. }

  87. return get_FCLK() / hdiv;
  88. }
  89. }

  90. /* return PCLK frequency */
  91. ulong get_PCLK(void)
  92. {
  93. S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
  94. unsigned long clkdiv;
  95. unsigned long camdiv;
  96. int hdiv = 1;

  97. /* support both of S3C2410 and S3C2440 */
  98. if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)
  99. return((clk_power->CLKDIVN & 0x1) ? get_HCLK()/2 : get_HCLK());
  100. else
  101. {
  102. clkdiv = clk_power->CLKDIVN;
  103. camdiv = clk_power->CAMDIVN;

  104. /* work out clock scalings */

  105. switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
  106. case S3C2440_CLKDIVN_HDIVN_1:
  107. hdiv = 1;
  108. break;

  109. case S3C2440_CLKDIVN_HDIVN_2:
  110. hdiv = 2;
  111. break;

  112. case S3C2440_CLKDIVN_HDIVN_4_8:
  113. hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
  114. break;

  115. case S3C2440_CLKDIVN_HDIVN_3_6:
  116. hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
  117. break;
  118. }

  119. return get_FCLK() / hdiv / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1);
  120. }
  121. }


  122. (3) common/env_nand.c

  123. // puts ("*** Warning - bad CRC or NAND, using default environment\n\n"); //HJ_del
  124. 注释此句

  125. (4) include/nand.h
  126. struct nand_write_options {结构体中添加
  127. int skipfirstblk; /* if true, skip the first good block*/

  128. (5) include/s3c2410.h
  129. 添加:
  130. /* for s3c2440, www.top-e.org */
  131. static inline S3C2440_NAND * const S3C2440_GetBase_NAND(void)
  132. {
  133. return (S3C2440_NAND * const)S3C2410_NAND_BASE;
  134. }
复制代码
 
 
 

回复

68

帖子

0

TA的资源

纯净的硅(中级)

55
 
  1. 5.增加函数实现
  2. (1)common/cmd_load.c
  3. 【1】增加函数声明
  4. /* support xmodem*/
  5. static ulong load_serial_xmodem (ulong offset);
  6. 并后面添加其函数实现:
  7. /* support xmodem */
  8. static ulong load_serial_xmodem (ulong offset)
  9. {
  10. int size;
  11. char buf[32];
  12. int err;
  13. int res;
  14. connection_info_t info;
  15. char xmodemBuf[1024];
  16. ulong store_addr = ~0;
  17. ulong addr = 0;

  18. size = 0;
  19. info.mode = xyzModem_xmodem;
  20. res = xyzModem_stream_open (&info, &err);
  21. if (!res) {

  22. while ((res =
  23. xyzModem_stream_read (xmodemBuf, 1024, &err)) > 0) {
  24. store_addr = addr + offset;
  25. size += res;
  26. addr += res;
  27. #ifndef CFG_NO_FLASH
  28. if (addr2info (store_addr)) {
  29. int rc;

  30. rc = flash_write ((char *) xmodemBuf,
  31. store_addr, res);
  32. if (rc != 0) {
  33. flash_perror (rc);
  34. return (~0);
  35. }
  36. } else
  37. #endif
  38. {
  39. memcpy ((char *) (store_addr), xmodemBuf,
  40. res);
  41. }

  42. }
  43. } else {
  44. printf ("%s\n", xyzModem_error (err));
  45. }

  46. xyzModem_stream_close (&err);
  47. xyzModem_stream_terminate (false, &getcxmodem);


  48. flush_cache (offset, size);

  49. printf ("## Total Size = 0x%08x = %d Bytes\n", size, size);
  50. sprintf (buf, "%X", size);
  51. setenv ("filesize", buf);

  52. return offset;
  53. }

  54. 【2】增加UBOOT命令
  55. /* support xmodem */
  56. U_BOOT_CMD(
  57. loadx, 3, 0, do_load_serial_bin,
  58. "loadx - load binary file over serial line (xmodem mode)\n",
  59. "[ off ] [ baud ]\n"
  60. " - load binary file over serial line"
  61. " with offset 'off' and baudrate 'baud'\n"
  62. );

  63. 【3】在
  64. printf ("## Ready for binary (ymodem) download "
  65. "to 0x%08lX at %d bps...\n",
  66. offset,
  67. load_baudrate);前添加
  68. /* support xmodem */
  69. if (strcmp(argv[0],"loadx")==0) {
  70. printf ("## Ready for binary (xmodem) download "
  71. "to 0x%08lX at %d bps...\n",
  72. offset,
  73. load_baudrate);

  74. addr = load_serial_xmodem (offset);

  75. } else if (strcmp(argv[0],"loady")==0) {

  76. (2)common/cmd_nand.c
  77. 【1】U_BOOT_CMD(nand, 5, 1, do_nand,中, 增加
  78. "nand read.yaffs addr off size - read the `size' byte yaffs image starting\n"
  79. " at offset `off' to memory address `addr'\n"
  80. "nand write.yaffs addr off size - write the `size' byte yaffs image starting\n"
  81. " at offset `off' from memory address `addr'\n"
  82. 【2】在
  83. } else {
  84. /* write */
  85. nand_write_options_t opts;
  86. memset(&opts, 0, sizeof(opts));
  87. opts.buffer = (u_char*) addr;
  88. opts.length = size;
  89. opts.offset = off;
  90. /* opts.forcejffs2 = 1; */
  91. opts.pad = 1;
  92. opts.blockalign = 1;
  93. opts.quiet = quiet;
  94. ret = nand_write_opts(nand, &opts);
  95. }后面添加
  96. }else if ( s != NULL && !strcmp(s, ".yaffs")){
  97. if (read) {
  98. /* read */
  99. nand_read_options_t opts;
  100. memset(&opts, 0, sizeof(opts));
  101. opts.buffer = (u_char*) addr;
  102. opts.length = size;
  103. opts.offset = off;
  104. opts.readoob = 1;
  105. opts.quiet = quiet;
  106. ret = nand_read_opts(nand, &opts);
  107. } else {
  108. /* write */
  109. nand_write_options_t opts;
  110. memset(&opts, 0, sizeof(opts));
  111. opts.buffer = (u_char*) addr;
  112. opts.length = size;
  113. opts.offset = off;
  114. /* opts.forceyaffs = 1; */
  115. opts.noecc = 1;
  116. opts.writeoob = 1;
  117. opts.blockalign = 1;
  118. opts.quiet = quiet;
  119. opts.skipfirstblk = 1;
  120. ret = nand_write_opts(nand, &opts);
  121. }

  122. (3)common/main.c
  123. // run_command (s, 0);此句注释,并添加
  124. boot_zImage(0x4c000,0x200000);

  125. (4)drivers/dm9000x.c
  126. 【1】修改
  127. for (i = 0; i < 6; i++)
  128. ((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i); char *tmp = getenv("ethaddr");
  129. 为:
  130. char *end;

  131. for (i = 0; i < 6; i++)
  132. // ((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i);
  133. {
  134. bd->bi_enetaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0;
  135. if(tmp)
  136. tmp = (*end) ? end+1 : end;
  137. }
  138. 【2】 DM9000_iow(DM9000_IMR, IMR_PAR); /* Enable TX/RX interrupt mask */前添加#if 0
  139. return 0;前添加#endif

  140. (5) drivers/nand/nand_base.c
  141. 最后return this->scan_bbt (mtd);
  142. 修改为 return 0;

  143. (6) drivers/nand/nand_util.c
  144. 【1】 u_char *buffer = opts->buffer;
  145. size_t written;
  146. int result;后面添加
  147. int skipfirstblk = opts->skipfirstblk;
  148. 【2】在
  149. readlen = meminfo->oobblock;
  150. if (opts->pad && (imglen < readlen)) {前面添加
  151. /* skip the first good block when wirte yaffs image */
  152. if (skipfirstblk) {
  153. mtdoffset += erasesize_blockalign;
  154. skipfirstblk = 0;
  155. continue;
  156. }

  157. (7)增加新文件 lib_arm/boot_zImage.c
  158. #include
  159. #include
  160. #include
  161. #include
  162. #include
  163. #include
  164. #include
  165. #include "asm-arm/mach-types.h"



  166. #define LINUX_KERNEL_OFFSET 0x8000
  167. #define LINUX_PARAM_OFFSET 0x100
  168. #define LINUX_PAGE_SIZE 0x00001000
  169. #define LINUX_PAGE_SHIFT 12
  170. #define LINUX_ZIMAGE_MAGIC 0x016f2818
  171. #define DRAM_SIZE 0x04000000

  172. extern int nand_read_ll_lcd(unsigned char*, unsigned long, int);

  173. /*
  174. * Disable IRQs
  175. */
  176. #define local_irq_disable() \
  177. ({ \
  178. unsigned long temp; \
  179. __asm__ __volatile__( \
  180. "mrs %0, cpsr @ local_irq_disable\n" \
  181. " orr %0, %0, #128\n" \
  182. " msr cpsr_c, %0" \
  183. : "=r" (temp) \
  184. : \
  185. : "memory", "cc"); \
  186. })

  187. static inline void cpu_arm920_cache_clean_invalidate_all(void)
  188. {
  189. __asm__(
  190. " mov r1, #0\n"
  191. " mov r1, #7 << 5\n" /* 8 segments */
  192. "1: orr r3, r1, #63 << 26\n" /* 64 entries */
  193. "2: mcr p15, 0, r3, c7, c14, 2\n" /* clean & invalidate D index */
  194. " subs r3, r3, #1 << 26\n"
  195. " bcs 2b\n" /* entries 64 to 0 */
  196. " subs r1, r1, #1 << 5\n"
  197. " bcs 1b\n" /* segments 7 to 0 */
  198. " mcr p15, 0, r1, c7, c5, 0\n" /* invalidate I cache */
  199. " mcr p15, 0, r1, c7, c10, 4\n" /* drain WB */
  200. );
  201. }

  202. void cache_clean_invalidate(void)
  203. {
  204. cpu_arm920_cache_clean_invalidate_all();
  205. }

  206. static inline void cpu_arm920_tlb_invalidate_all(void)
  207. {
  208. __asm__(
  209. "mov r0, #0\n"
  210. "mcr p15, 0, r0, c7, c10, 4\n" /* drain WB */
  211. "mcr p15, 0, r0, c8, c7, 0\n" /* invalidate I & D TLBs */
  212. );
  213. }

  214. void tlb_invalidate(void)
  215. {
  216. cpu_arm920_tlb_invalidate_all();
  217. }


  218. void call_linux(long a0, long a1, long a2)
  219. {
  220. local_irq_disable();
  221. cache_clean_invalidate();
  222. tlb_invalidate();

  223. __asm__(
  224. "mov r0, %0\n"
  225. "mov r1, %1\n"
  226. "mov r2, %2\n"
  227. "mov ip, #0\n"
  228. "mcr p15, 0, ip, c13, c0, 0\n" /* zero PID */
  229. "mcr p15, 0, ip, c7, c7, 0\n" /* invalidate I,D caches */
  230. "mcr p15, 0, ip, c7, c10, 4\n" /* drain write buffer */
  231. "mcr p15, 0, ip, c8, c7, 0\n" /* invalidate I,D TLBs */
  232. "mrc p15, 0, ip, c1, c0, 0\n" /* get control register */
  233. "bic ip, ip, #0x0001\n" /* disable MMU */
  234. "mcr p15, 0, ip, c1, c0, 0\n" /* write control register */
  235. "mov pc, r2\n"
  236. "nop\n"
  237. "nop\n"
  238. : /* no outpus */
  239. : "r" (a0), "r" (a1), "r" (a2)
  240. : "r0","r1","r2","ip"
  241. );
  242. }


  243. /*
  244. * pram_base: base address of linux paramter
  245. */
  246. static void setup_linux_param(ulong param_base)
  247. {
  248. struct param_struct *params = (struct param_struct *)param_base;
  249. char *linux_cmd;

  250. // printk("Setup linux parameters at 0x%08lx\n", param_base);
  251. memset(params, 0, sizeof(struct param_struct));

  252. params->u1.s.page_size = LINUX_PAGE_SIZE;
  253. params->u1.s.nr_pages = (DRAM_SIZE >> LINUX_PAGE_SHIFT);

  254. /* set linux command line */
  255. linux_cmd = getenv ("bootargs");
  256. if (linux_cmd == NULL) {
  257. printk("Wrong magic: could not found linux command line\n");
  258. } else {
  259. memcpy(params->commandline, linux_cmd, strlen(linux_cmd) + 1);
  260. // printk("linux command line is: "%s"\n", linux_cmd);
  261. }
  262. }


  263. /*
  264. * dst: destination address
  265. * src: source
  266. * size: size to copy
  267. * mt: type of storage device
  268. */
  269. static inline int copy_kernel_img(ulong dst, const char *src, size_t size)
  270. {
  271. int ret = 0;
  272. ret = nand_read_ll((unsigned char *)dst,
  273. (unsigned long)src, (int)size);
  274. return ret;
  275. }


  276. int boot_zImage(ulong from, size_t size)
  277. {
  278. int ret;
  279. ulong boot_mem_base; /* base address of bootable memory 鍢庡敱? */
  280. ulong to;
  281. ulong mach_type;

  282. boot_mem_base = 0x30000000;

  283. /* copy kerne image */
  284. to = boot_mem_base + LINUX_KERNEL_OFFSET;
  285. printk("Copy linux kernel from 0x%08lx to 0x%08lx, size = 0x%08lx ... ",
  286. from, to, size);
  287. ret = copy_kernel_img(to, (char *)from, size);
  288. if (ret) {
  289. printk("failed\n");
  290. return -1;
  291. } else {
  292. printk("Copy Kernel to SDRAM done,");
  293. }

  294. if (*(ulong *)(to + 9*4) != LINUX_ZIMAGE_MAGIC) {
  295. printk("Warning: this binary is not compressed linux kernel image\n");
  296. printk("zImage magic = 0x%08lx\n", *(ulong *)(to + 9*4));
  297. } else {
  298. // printk("zImage magic = 0x%08lx\n", *(ulong *)(to + 9*4));
  299. ;
  300. }

  301. /* Setup linux parameters and linux command line */
  302. setup_linux_param(boot_mem_base + LINUX_PARAM_OFFSET);

  303. /* Get machine type */
  304. mach_type = MACH_TYPE_S3C2440;
  305. // printk("MACH_TYPE = %d\n", mach_type);

  306. /* Go Go Go */
  307. printk("NOW, Booting Linux......\n");
  308. call_linux(0, mach_type, to);

  309. return 0;
  310. }

  311. int do_boot_zImage (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  312. {
  313. boot_zImage(0x4c000,0x200000);
  314. return 0;
  315. }

  316. U_BOOT_CMD(
  317. boot_zImage, 3, 0, do_boot_zImage,
  318. "boot_zImage - boot Linux 's zImage\n",
  319. " - boot Linux 's zImage"
  320. );

  321. int boot_noos(ulong from, size_t size)
  322. {
  323. int ret;
  324. ulong boot_mem_base; /* base address of bootable memory 鍢庡敱? */
  325. ulong to;

  326. boot_mem_base = 0x30000000;

  327. /* copy kerne image */
  328. to = boot_mem_base;
  329. printk("Copy code from 0x%08lx to 0x%08lx, size = 0x%08lx ... ",
  330. from, to, size);
  331. ret = copy_kernel_img(to, (char *)from, size);
  332. if (ret) {
  333. printk("failed\n");
  334. return -1;
  335. } else {
  336. printk("Copy code to SDRAM done,");
  337. }

  338. /* Go Go Go */
  339. printk("NOW, Booting code......\n");
  340. run_command("go 0x30000000", 0);

  341. return 0;
  342. }
  343. int do_boot_noos (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  344. {
  345. boot_noos(0x4c000,0x200000);
  346. return 0;
  347. }

  348. U_BOOT_CMD(
  349. boot_noos, 3, 0, do_boot_noos,
  350. "boot_noos - boot SKY2440_test\n",
  351. " - boot SKY2440_test"
  352. );
复制代码
 
 
 

回复

68

帖子

0

TA的资源

纯净的硅(中级)

56
 

四.u-boot烧写:

1.硬件连接
把JTAG下载板接到并口,把JTAG下载板上和开发板上的JTAG口用JTAG线相连。
2.烧写过程
首先运行SJF2440.exe。点击“开始”中的“运行”,如下图所示:



在弹出的菜单中输入“cmd”点击确定,如下图所示:



在弹出的界面中用DOS命令进入SJF2440所在文件夹打开开发板电源运行SJF2440,过程如下图所示:


选择“0”回车,“0”回车,“0”回车。如下图所示:



烧写成功后按“2”退出,可以连接串口线用DNW查看串口信息设置使用的串口COM和波特率115200
后可以看到u-boot界面如图:



看到界面已经很接近成功了,要检验u-boot是否彻底成功可以将内核烧写到开发板上看看是否可以运行,这将是第三阶段中的内容——内核移植过程。
 
 
 

回复

2771

帖子

0

TA的资源

裸片初长成(中级)

57
 

不错

顶LZ
 
 
 

回复

29

帖子

0

TA的资源

纯净的硅(初级)

58
 
实在不错的教程,如果有点视频的话效果会更好。
 
 
 

回复

14

帖子

0

TA的资源

一粒金砂(高级)

59
 

顶顶

!!!!
 
 
 

回复

169

帖子

0

TA的资源

五彩晶圆(高级)

60
 
突然觉得。。。。我很白痴,不懂啊!相大家学习!相见恨晚!谢各位啦!
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表