当前位置:首页 > 嵌入式 > 嵌入式硬件
[导读](1) 事情来由几个月前从朋友那里拿到了一块参考Micetek EV44b0-II开发板设计的板子,对其bootloader MBL感觉很不错. 朋友说可能是移植 u-boot的.但Micetek并没有提供MBL的源

(1) 事情来由

几个月前从朋友那里拿到了一块参考Micetek EV44b0-II开发板设计的板子,对其bootloader MBL感觉很不错. 朋友说可能是移植 u-boot的.但Micetek并没有提供MBL的源代码, 因此当时没有仔细去研究. 最近公司准备想做基于S3C44B0X CPU的产品,因此购买了杭州立宇泰公司()的armsys-c及armsys-b开发板和.armsys提供的 bootloader 是其公司自己开发的bootloader,觉得其USB这一块做的还可以,但利用USB下载调试uclinux是非常麻烦的,操作很不爽,其 bootloader也不提供网络下载调试.因此自己计划移植u-boot.

(2) 开始

由于没有接触过u-boot,因此第一步要做的就是google一些资料.

u-boot官方网站:http://sourceforge.net/projects/u-boot(比较慢)

http://u-boot.sourceforge.net/这个快一些.

DENX U-Boot及Linux使用手册: http://coosign.blogchina.com/coosign/1318487.html, 这是一遍翻译的文档.主要介绍了u-boot编译及使用的命令.但没有涉及新板子的移植流程.

到board目录查了一下:

#cd u-boot

#cd board

#find . -exec grep -l 44B0 {} \;

结果是:

./dave/B2/B2.c

B2网站是: ,初初看了B2开发板的介绍,但不详细.包括使用的网络芯片等都没有介绍.

google "u-boot 移植"后查到一篇文章:

"收集了一些关于U-BOOT的文章"

http://www.bloghome.cn/index.php?op=ViewArticle&articleId=2111&blogId=390

里面搜集了不少关于u-boot移植的问题.

里面介绍了"U-Boot 在44B0X 开发板上的移植以及代码分析"的内容,仔细看了看.发现其移植的版本比较低,但对了解u-boot结构是满不错的,因为这个版本不支持44B0X,因此完全是支持新CPU的移植.了解到 make XX_config是在Makefile中定义的.

另外"MPC8xx的U-Boot移植体会(ZT) "这一篇对u-boot介绍满详细的.但对移植工作只做了理论性和经验性介绍,没有具体的操作步骤.

"基于Atmel at91rm9200的armlinux的bootloader启动代码分析 "

http://www.linuxfans.org/nuke/modules.php?name=News&file=print&sid=2765

里面介绍了u-boot移植到at91rm9200上的情况,可以参考一下.

另外就是仔细阅读u-boot下的README文件.

(3) 编译一把

看了相关的资料,心动不如行动.先编译一把看看情况.既然只有B2开发板是S3C44B0X CPU的,因此先编译一下B2开发板看看. 具体:

#cd u-boot

#make B2_config

#make

结果顺利,成功编译.

(4) 开始动手移植

我以B2板子的程序做为模板来做.

#cd board

#cp -r dave wx (自己取个公司名wx)

#cd wx

#mv B2 wx20 (自己取个板子名wx20)

#cd wx20

# mv B2.c wx20.c

修改Makefile及wx20.c, 主要是B2改成wx20.

增加配置文件:

#cd include/configs

#cp B2.h wx20.h

修改Makefile配置文件,增加wx20_config.

1432 wx20_config : unconfig

1433 @./mkconfig $(@:_config=) arm s3c44b0 wx20 wx

[注:前面的数字是文件行号,以下一样].

将board/wx目录下和wx20.h文件中的B2改成wx20或WX20.

这里其实是最重要的步骤,就是根据硬件的情况来修改相关的参数.由于对硬件板子的情况不是太了解,因此此时最需要的就是耐心地看看硬件资料.主要修改的地方有:

include/configs/wx20.h ---- 配置文件,大部分参数是这里配置的.

board/wx/wx20/lowlevel_init.S -- 内存参数配置

cpu/s3c44b0/serial.c -- 串口配置

cpu/s3c44b0/start.S -- 程序入口

如果此时配置全部正确了,那么我们就简单的很了.(如果你用我的patch的话,就是如此了!)那么我也就不会仔细再去研究u-boot其他部分了. 困难就是你学习的最好机会!

(5) 开始编译

经过简单的参数修改,编译成功.然后下载u-boot.bin(二进制格式). 此时你可以用nm看一下u-boot(elf格式)的内容,会有所收获的.

然后用armsys的bootloader将u-boot.bin调入到内存0xc100000运行.结果可想而知,串口没有任何显示,而且死机.bootloader也必须断电重起.

(6) u-boot流程

原因是比较明显的,就是参数和硬件没有符合.因此接下来做的事情就是仔细阅读S3C44B0 CPU的硬件资料,包括内存配置,串口配置这些.我觉得要让串口出信息,最主要的就是CPU的初始化,内存配置和串口配置.另外就是了解u-boot程序运行流程,这个对了解需要设置的参数是非常有帮助的.我这里大致说一下u-boot运行流程.

入口: cpu/s3c44b0/start.S

主要是CPU初始化( cpu_init_crit 200), 调内存配置函数( lowlevel_init 200), 然后判断u-boot是否从flash运行,如果是就把u-boot代码拷贝到TEXT_BASE定义的地方.然后转到 start_armboot.

start_armboot: lib_arm/board.c

进行各种初始化设置,主要有:

cpu_init CPU相关的设置, 具体在./cpu/s3c44b0/cpu.c中.

board_init 板子相关的设置, 具体在board/wx/wx20/wx20.c 中

interrupt_init中断设置,我们没有用,具体在./cpu/s3c44b0/interrupts.c中

env_init 初始化环境变量, 具体要看用什么介质来存储环境变量,如果用flash来存贮, 程序在common/env_flash.c中.

init_baudrate 设置baud参数

serial_init 串口初始化, 具体在cpu/s3c44b0/serial.c.

console_init_f 控制台设置, 具体在./common/console.c

display_banner 显示标题.

dram_init 可用内存配置, 具体在./board/wx/wx20/wx20.c.

flash_init flash初始化,具体./drivers/cfi_flash.c.

接下来就是环境变量初始化, 网络初始化,最后到main_loop,可以运行各种命令.

(7) 主要参数修改

经过一段时间调试,终于串口出东西了,这段时间犯了一个小错误,走了一段冤枉路.其实配置参数可能早已正确,但串口老是乱码,原因是自己的u-boot.bin传下来时目录搞错了,结果老是运行错误的u-boot.bin.这段时间里主要改的参数有:[!--empirenews.page--]

include/configs/wx20.h:

#define CONFIG_S3C44B0_CLOCK_SPEED 64

CPU主频,armsys板的是64M

#define PHYS_SDRAM_1 0x0c000000 /* SDRAM Bank #1 */

B2板子里的定义是错误的.还有RAM大小,flash大小需要修改,跟B2板不同.

#define CONFIG_DRIVER_RTL8019

#define RTL8019_BASE 0x08000000

配置rtl8019AS网络芯片.

#define CFG_LOAD_ADDR 0x0c008000 /* default load address */

uclinux运行入口地址

lowlevel_init.S:

MEMORY_CONFIG:

.long 0x11010102

.long 0x600

.long 0x7ffc

.long 0x7ffc

.long 0x7ffc

.long 0x7ffc

.long 0x2610

.long 0x18000

.long 0x18000

.long 0x960459

.long 0x10

.long 0x20

.long 0x20

由于对armsys硬件不是太了解,没有办法,只得看armsys bootloader程序,但每个版本又有差别.因此是用AXD调试看bootlaoder启动后0x1c80000中的值定的.

cpu/s3c44b0/serial.c:

#elif CONFIG_S3C44B0_CLOCK_SPEED==64

divisor = 34;

串口设置,这个也是根据bootloader里的公式计算出来的.这里只定义了115200得值,其他没有去设置.

cpu/s3c44b0/start.S:

ldr r1, =PLLCON

#if CONFIG_S3C44B0_CLOCK_SPEED==66

ldr r0, =0x34031 /* 66MHz (Quartz=11MHz) */

#elif CONFIG_S3C44B0_CLOCK_SPEED==75

ldr r0, =0x610c1 /*B2: Xtal=20mhz Fclk=75MHz */

#elif CONFIG_S3C44B0_CLOCK_SPEED==64

ldr r0, =((M_DIV<<12)+(P_DIV<<4)+S_DIV) //Fin=8MHz,Fout=64MHz

#else

# error CONFIG_S3C44B0_CLOCK_SPEED undefined

#endif

PLLCON的值,也是根据bootlaoder的公式.

board/wx/wx20/wx20.c

主要是PORT配置,具体我不知道有没有影响.

(8) 关于u-boot入口的疑问

由于开始串口没有出内容,因此对u-boot入口产生怀疑.在网上也找到一个帖子,碰到同样疑问的人:

http://www.linuxforum.net/forum/showflat.php?Cat=&Board=embedded&Number=563322&page=0&view=collapsed&sb=5&o=0&fpart=

"链接得到的起始地址为什么是TEXT_BASE,而不是0呢,所以现在只能够下载到ram中运行,但是无法烧写道flash中跑,这是怎么回事呢?u-boot中应该是start.S中的这段代码在flash中运行吧,后面就把自身拷贝到ram中TEXT_BASE地址处,为什么在链接文件中指定的_start的起始地址为0x00000000呢? "

后来我理解了:

“链接得到的起始地址为什么是TEXT_BASE,而不是0呢,”

因为u_boot如果从flash运行的话,那么它会将自己的代码拷贝到RAM中,然后运行。u-boot开始部分代码与编译的入口没有关系,而主要的代码是在RAM中运行,因此编译的入口地址是TEXT_BASE.因此u-boot既可以flash运行,也可以ram运行。

“为什么在链接文件中指定的_start的起始地址为0x00000000呢?”

lds文件中的起始地址为0x00000000是不起作用的,由-TTEXT_BASE参数替代的。

刚开始比较疑惑的原因是对:

126 relocate: /* relocate U-Boot to RAM */

127 adr r0, _start /* r0 <- current position of code */

adr这条指令没有理解正确,因为把它想成mv r0,_start了,实际上adr这里的_start是相对的,如果从flash运行的话,r0就是0, 如果从ram运行的话,r0就是C100000。

(9) u-boot显示信息

经过上面的努力,我们终于可以看到u-boot的庐山真面目了.当然这还不是最终的结果.但至少离胜利不远了.现在我们可以用printf来调试了.此时全部是通过armsys bootloader下载u-boot.bin到0xc100000运行.

现在显示信息是:

Plese wait a moment to start running...i am samfei!

iamsam!

U-Boot 1.1.3 (Jul 1 2005 - 13:46:03)

U-Boot code: 0C100000 -> 0C11A73C BSS: -> 0C11ECF4

RAM Configuration:

Bank #0: 0c000000 8 MB

[flash_get_size, 224] Entering ...

[flash_get_size, 232] value=bf

[flash_get_size, 255] value=234b

Flash: 2 MB

*** Warning - bad CRC, using default environment

In: serial

Out: serial

Err: serial

MAC: 26:26:26:26:26:26

Hit any key to stop autoboot: 0

=>

(10) 希望环境变量存贮到flash

B2板缺省的定义是把环境变量存贮到EEPROM上,虽然armsys上也有,但我也搞不清楚它的硬件配置,因此希望把环境变量存贮到flash上.

增加配置: include/configs/wx20.h (从evb4510.h中学来!)

79 #define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \

80 CFG_CMD_DATE | \

81 CFG_CMD_ELF | \

82 CFG_CMD_NET | \

83 CFG_CMD_ENV|CFG_CMD_FLASH 200)this.width=200'>screen.width/2)this.style.width=screen.width/2;" border=0>

173 #define CFG_ENV_IS_IN_FLASH

174 #undef CFG_ENV_IS_NOWHERE

175

176 #define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x20000) /* environment start address */

177 #define CFG_ENV_SECT_SIZE 0x10000 /* Total Size of Environment Sector */

编译运行, 并操作setenv, saveenv, printenv. 看起来正常.

=> setenv ipaddr 192.168.1.100

=> saveenv

Saving Environment to Flash...

Un-Protected 1 sectors

Erasing Flash...

done

Erased 1 sectors

Writing to Flash... done

Protected 1 sectors

ð printenv

但重新启动机器后,参数没有起作用,还是缺省的.仔细看了环境变量的程序,发现是由于ENV_IS_EMBEDDED定义造成的,而此变量定义是在./tools/envcrc.c中:[!--empirenews.page--]

# if (CFG_ENV_ADDR >= CFG_MONITOR_BASE) && \

((CFG_ENV_ADDR + CFG_ENV_SIZE) <= (CFG_MONITOR_BASE + CFG_MONITOR_LEN))

# define ENV_IS_EMBEDDED 1

# endif

因此在wx20.h中增加了:

#define CFG_MONITOR_BASE PHYS_SDRAM_1 (我还没搞清楚这个变量干啥的.)

主要是去除ENV_IS_EMBEDDED的定义。

结果确实准备使用flash的环境变量,但每次总是说标志头错误,经过仔细调试,最终发现flash写出现错误,原因是我忘了修改wx/common/flash.c中的CONFIG_B2为CONFIG_WX20. 修改后就正常了.

(11) arm-linux和arm-elf

上面调试一直是arm-elf,原因是以前有问题时怀疑编译器问题而修改了,因此没有改变。改用arm-linux编译后:

U-Boot 1.1.3 (Jul 3 2005 - 07:01:36)

U-Boot code: 0C100000 -> 0C117DA0 BSS: -> 0C11C0F0

RAM Configuration:

Bank #0: 0c000000 8 MB

env_init flash_addr=20000

flash_addr=20000 env_ptr=20000 env_ptr->data=bootargs=setenv bootargs root=/dev/ram ip=192.168.1.100:::::eth0:off ether=25,0,0,0,eth0 ethaddr=00:50:c2:1e:af:fb

envptr->crc=1470de2 1470de2

buffer->crc=1470de2

[flash_get_size, 224] Entering ...

[flash_get_size, 232] value=bf

[flash_get_size, 255] value=234b

Flash: 2 MB

env_ptr=20000

gd->env_addr=20004 gd->env_valid=1

env_relocate[211] offset = 0x0

env_relocate[229] malloced ENV at 00000000

In:

Out:

Err:

死机!!!

然后改回arm-elf编译:

U-Boot 1.1.3 (Jul 3 2005 - 07:04:48)

U-Boot code: 0C100000 -> 0C119B98 BSS: -> 0C11DCD8

RAM Configuration:

Bank #0: 0c000000 8 MB

env_init flash_addr=20000

flash_addr=20000 env_ptr=20000 env_ptr->data=bootargs=setenv bootargs root=/dev/ram ip=192.168.1.100:::::eth0:off ether=25,0,0,0,eth0 ethaddr=00:50:c2:1e:af:fb

envptr->crc=1470de2 1470de2

buffer->crc=1470de2

[flash_get_size, 224] Entering ...

[flash_get_size, 232] value=bf

[flash_get_size, 255] value=234b

Flash: 2 MB

env_ptr=20000

gd->env_addr=20004 gd->env_valid=1

env_relocate[211] offset = 0x0

env_relocate[229] malloced ENV at 0c0dfc08

In: serial

Out: serial

Err: serial

rtl8019 MAC: 2a:2a:2a:2a:2a:2a

Hit any key to stop autoboot: 0

=>

正常!因此最好是用arm-elf编译. 我在看网上查资料时记得有人说过"用arm-linux编译时,malloc返回0,而改成arm-elf编译时就好了".有个印象,具体帖子不记得在哪里了.所以后来我就一直使用arm-elf编译,没有再去试arm-linux编译.

(12) 网卡调试

剩下来的事情就是调网络了.根据上面配置rtl8019as后,网络仍然不同,然后参考uclinux驱动中的寄存器定义修改,网络就可以了.具体修改是:

drivers/rtl8019.h

36 #define ETH_ADDR_SFT (8)

37 #define EI_SHIFT(x) ((x)<

38

39 #define RTL8019_REG_00 (RTL8019_BASE + EI_SHIFT(0x00))

40 #define RTL8019_REG_01 (RTL8019_BASE + EI_SHIFT(0x01))

......

(13) 开始load uclinux

设置好本机ip地址,服务器ip地址, 下载文件名这些参数后,就可以load uclinux了.

=> tftpboot

eth_init...00:50:c2:1e:af:fb

TFTP from server 192.168.1.25; our IP address is 192.168.1.100

Filename 'image.bin'.

Load address: 0xc008000

Loading: #################################################################

#################################################################

#################################################################

#################################################################

#################################################################

#################################################################

###############################

死机!

原因是我们现在的u-boot入口地址是C100000,而uclinux内核大约2M,因此load过来就冲突了.因此我们把u-boot的入口地址改成C300000,具体修改在board/wx/wx20/config.mk:

TEXT_BASE = 0x0C300000

重新编译运行就可以了.

(14) 设置自动运行uclinux

刚才我们是用命令load uclinux并执行的.自动运行需要设置bootcmd环境变量:

=> setenv bootcmd "tftpboot; go 0xc008000" ==》设置错误

## Starting application at 0x0C008000 ...

=> setenv bootcmd "tftpboot\; go 0xc008000" ==》需要有个\

=> saveenv

重新开机运行u-boot:

Hit any key to stop autoboot: 0

Unknown command '"tftpboot' - try 'help'

## Starting application at 0x0C008000 ...

结果还是不能自动下载uclinux和运行.经过调试才发现在设置bootcmd时多加了引号造成的!正确的设法是:

=> setenv bootcmd tftpboot \; go 0xc008000 ==》正确的设置

此时可以成功自动下载uclinux和运行了.

(15) flash运行

刻录到flash后,运行uclinux出现问题,运行到:uclinux 开中断后就死机,提示:

Linux version 2.4.24-uc0 (root@samfei) (gcc version 2.95.3 20010315 (release)(ColdFire patches - 20010318 from :http://fiddes.net/coldfire/)(uClinux XIP and shared lib patches from :http://www.snapgear.com/)) #46 Áù 7ÔÂ 2 15:52:55 CST 2005[!--empirenews.page--]

Processor: Samsung S3C44B0X revision 0

Architecture: S3C44B0X

On node 0 totalpages: 2048

zone(0): 0 pages.

zone(1): 2048 pages.

zone(2): 0 pages.

Kernel command line: root=/dev/rom0 init=/linuxrc

前面一直用armsys的bootloader,将u-boot下载到0xc300000运行,然后再load linux到0xc0080000运行,正常.而将u-boot刻录到flash后运行不正常,经过调试uclinux,到init/main.c中 sti()函数后出现死机.因此怀疑中断向量设置问题.

将cpu/s3c44b0/start.S中代码修改成;

40 .globl _start

41 _start: b reset

42 /*

43 add pc, pc, #0x0c000000

44 add pc, pc, #0x0c000000

45 add pc, pc, #0x0c000000

46 add pc, pc, #0x0c000000

47 add pc, pc, #0x0c000000

48 add pc, pc, #0x0c000000

49 add pc, pc, #0x0c000000

50 */

51 LDR PC, Undefined_Addr

52 LDR PC, SWI_Addr

53 LDR PC, Prefetch_Addr

54 LDR PC, Abort_Addr

55 LDR PC,RESERVE_Addr

56 LDR PC, IRQ_Addr

57 /* subs pc,lr,#4*/

58 LDR PC, IRQ_Addr

59 /* subs pc,lr,#4*/

114 Undefined_Addr:

115 .word 0x0c000004

116 SWI_Addr:

117 .word 0x0c000008

118 Prefetch_Addr:

119 .word 0x0c00000C

120 Abort_Addr:

121 .word 0x0c000010

122 RESERVE_Addr:

123 .word 0x0c000014

124 IRQ_Addr:

125 .word 0x0c000018

126 FIQ_Addr:

127 .word 0x0c00001C

128

129 /*

130 * the actual reset code

131 */

132

133 reset:

后编译,刻录,然后运行.正常了!!!

(16) 补丁制作和测试

[root@samfei u-boot]# make distclean

[root@samfei 44b0]# mv u-boot u-boot.wx

[root@samfei 44b0]# cvs -d200) server:anonymous@cvs.sourceforge.net:/cvsroot/u-boot login

Logging in to server:anonymous@cvs.sourceforge.net:2401/cvsroot/u-boot

CVS password:

[root@samfei 44b0]# cvs -z3 -d200) server:anonymous@cvs.sourceforge.net:/cvsroot/u-boot co -P u-boot

cvs checkout: Updating u-boot

U u-boot/CHANGELOG

U u-boot/COPYING

U u-boot/CREDITS

U u-boot/MAINTAINERS

。。。。。。

[root@samfei 44b0]# diff -Naur u-boot u-boot.wx > uboot-wx-20050703.patch

[root@samfei 44b0]# vi uboot-wx-20050703.patch

去掉没有用的文件.做补丁的好处就是自己可以很清楚的知道哪些文件修改了!做完了,别忘了测试一下.

[root@samfei 44b0]# cd u-boot

[root@samfei u-boot]# patch -p1 < ../uboot-wx-20050703.patch

[root@samfei u-boot]# make wx20_config

[root@samfei u-boot]# make

(17) 后记

写这份材料化了不少时间.由于在调试的时候记录了大部分的调试信息,因此不用费脑筋去回忆.写完了这个经历,非常开心..一则自己可以温故而知新,二则就是与人共享啊.在开源的世界里,与人共享应该是件很快乐的一件事情.

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

在嵌入式系统开发、调试和测试过程中,J-Link作为一种高效的调试工具,为开发者提供了极大的便利。然而,要想充分发挥J-Link的功能,首先需要正确安装其驱动程序。本文将详细介绍J-Link驱动的安装过程,并深入解析其中...

关键字: jlink 嵌入式系统 嵌入式开发

与谷歌的合作使 Nordic 能够在 nRF Connect SDK 中嵌入开发人员软件,以构建与安卓移动设备兼容的谷歌Find My Device和未知跟踪器警报服务

关键字: 谷歌 SoC 嵌入式开发

嵌入式开发作为当今电子工程和信息技术领域的核心分支,涵盖了广泛的软硬件技术和系统集成方法,用于构建高性能、低成本、低功耗、体积小巧且功能专一的嵌入式系统。这些系统无处不在,从微型传感器节点到复杂的工业控制设备,从日常使用...

关键字: 嵌入式开发 Python

嵌入式开发是当今信息技术领域不可或缺的一部分,它融合了硬件设计、软件开发和系统集成等多个学科,专门用于创建那些被嵌入到特定设备或系统中的专用计算机系统。嵌入式开发的主要过程包括利用分立元件或集成器件进行电路设计、结构设计...

关键字: 嵌入式开发 硬件设计 软件开发

嵌入式开发作为一种专业且技术密集型的领域,涵盖了从硬件底层驱动、中间件到应用层软件开发等多个层面的工作,其所需的工具种类繁多,各有针对性,旨在提升开发效率、保证代码质量以及简化调试过程。

关键字: 嵌入式开发 keil

嵌入式开发作为信息技术领域的重要分支,其涉及的语言种类繁多,各具特色。这些语言的选择取决于目标平台的特性、性能需求、开发者的熟练程度以及项目的具体要求。本文将详细介绍几种常见的嵌入式开发语言,包括C语言、C++、汇编语言...

关键字: 嵌入式开发 C语言

嵌入式开发是一项综合了硬件设计、软件编程以及系统整合的技术活动,其目的是为了创造出能够在特定环境中高效、稳定运行的嵌入式系统。这一流程涵盖了多个紧密关联且不可或缺的阶段,从最初的客户需求分析到最终的产品测试和交付,每个环...

关键字: 嵌入式开发 硬件设计

嵌入式开发作为一个融合了计算机软硬件和系统工程的综合性领域,其成功与否往往取决于三个核心要素的有效整合与协调。这三个要素分别是:硬件平台的选择与设计、软件开发及其优化、以及系统级的设计与集成。深入理解并熟练掌握这三个方面...

关键字: 嵌入式开发 ARM

嵌入式开发作为信息技术的关键支柱,在全球数字化转型浪潮中扮演着无可替代的角色。从传统的嵌入式微控制器到如今先进的片上系统(SoC),再到与云计算、人工智能深度融合的智能终端,嵌入式系统的演进与发展始终紧跟时代脉搏。本文将...

关键字: 嵌入式开发 智能应用

嵌入式开发是一种专门针对特定硬件平台设计和实现软件系统的工程实践,它涵盖了从需求分析、系统设计、编程实现、调试测试直到产品部署及维护的全过程。本文将深入探讨嵌入式开发的主要阶段,分解其流程并阐述每个步骤的关键要点,以便于...

关键字: 嵌入式开发 嵌入式软件
关闭
关闭