EDA365电子工程师网

标题: 【转载】 JLINKv9在迅为iTOP-4412精英板上的应用 [打印本页]

作者: 独孤九剑17    时间: 2017-9-12 10:43
标题: 【转载】 JLINKv9在迅为iTOP-4412精英板上的应用
& u1 j" m5 _" ~) T, E" ]
本文转自:https://www.amobbs.com/thread-5680586-1-1.html
很多人买迅为iTop4412精英板,在Android或Linux+Qt跑起来后学习开发调试应用程序或驱动,但在linux内核运行前发生了什么?能进行什么开发工作?并没有完整资料。其实,只要一根百元价位的JLINKv9,就可以搭建一个实用的boot阶段程序开发环境,使我们可以深入到貌似神秘的史前时代一探究竟。
我的精英板和JLINKv9刚到手一周左右,花了两三天功夫在环境搭建上,也遇到了一些坑,幸运的是都解决了。下面我就总结介绍一下这几天的工作,希望能对感兴趣的人有所帮助,能抛砖引玉就更好了。当然,在解决问题过程中,除了靠自己积累的知识外,也参考学习了网上的一些资料,在此向作者表示谢意,并尽量列出所参考的文章。
还要声明一点,就是boot阶段的开发当然需要一定的底层硬件知识。虽然本文所涉较少,但还是提醒初学者谨慎操作,以免损坏硬件。
正文:
系统环境:win8.1+VMWare+ubuntu14.04LTS
硬件:iTop4412精英板+JLINKv9调试电缆+SD卡及读卡器。JLINKv9电缆常用JTAG接头是2.54mm间距的大头,精英板上的JTAG接口是2mm间距的小头,所以还需要购买或自制转接板和小头电缆(淘宝售价10元以内)。硬件上一个小坑是我买的JLINKv9的JTAG接口的2脚有3.3V输出(SEGGER手册上写明NC,但有3.3V输出不知为什么),而精英板的JTAG口的1脚和2脚是短路的,这就使得如果不做改动直接连接,就使得JTAG1脚的检测电压是自身2脚输出的3.3V,而不是精英版输出的1.8V,使JLINK识别目标失败。改起来很简单,吧转接板大头和小头2脚间的连线划断就可以了。
关于JLINK软件的安装,只要去SEGGER官网下载最新版的Linux版的DEB安装包,用dpkg命令安装就可以了。还应该在Windows宿主机上安装win版的JLINK软件,这样宿主机也可以识别JLINK,出问题时也可和Linux虚拟机作对照。
首先确认JLINK可以识别4412。把JLINK电缆和串口电缆接好,开启Ubuntu虚拟机,在虚拟机Wokstation->虚拟机->可移动设备 菜单下把串口和SEGGER J-link与虚拟机连接好。开启虚拟机串口终端(我用的C-kermit),精英板上电进入u-boot状态。进入JLINK安装目录(缺省/opt/SEGGER/JLink/),运行 JLinkExe,如果没问题应该有VTref = 1.8xxV的目标检测电压输出(如果检测电压为3.3V,说明JTAG转接板未改,参考前面)。由于JLINKv9不直接支持4412,所以不能自动识别目标,需手动连接。按提示输入connect命令,依次输入“CORTEX-A9”,回车,“J”,回车,“-1,-1”,回车,4000,回车。界面如下图。
此时若JLINK和目标板软硬件没问题,则4412的cortex-a9 CPU#0能被识别,这正是我们期待的。截图如下。
在此基础上可以做些实验,发现如下问题:cp15协处理器读写命令无效;只能调试单核;0x02000000物理地址开始的内存无法读取,而这是关键的iROM和iRAM映射区域,史前文明的秘密宝藏就在这里。第一个问题可以在编程时用汇编指令读cp15到通用寄存器然后设置相应断点来一定程度规避。第二个问题对于调试boot阶段程序来说不是问题,因为这时本来只有CPU#0运行。第三个问题就得认真对待了。从上图可以看到此时MMU使能,物理地址已不能直接应用。我还没有深究此版本u-boot源码,不知道该段物理地址是否映射到某个虚拟地址。换个思路,可以重写一个BL2阶段的程序,该程序为目的只是一个无限循环,用JLinkExe的halt命令终止其运行,就可保留BL1刚结束而BL2刚开始时的现场。让我们实现这个思路看看会得到什么。
我利用较新版(建议2017以后)的u-boot源码改造生成SPL的方式产生所需要的BL2程序。ARM交叉工具链用Linaro的arm-eabi-系列。按照上述思路,只要在u-boot源码的arch/arm/cpu/armv7/start.S的第一条指令改为跳转自身地址的指令即可。但经过实验,以此生成的BL2程序在精英板运行后,JLinkExe检测到的VTref为0V,JLINK无法连接目标。由此猜想是BL2程序缺少必要的电源管理设置。参考网上文章http://blog.csdn.net/techping/article/details/69911634,找到该文中arch/arm/mach-exynos/board.c的电源管理部分代码,根据相关4412的寄存器地址,查4412手册知道要设置PSHOLD引脚输出,又对照精英板的原理图,发现PSHOLD信号确实是控制电源管理芯片的,就用汇编实现此功能。修改后的start.S入口处代码如下:
reset:. r, L0 i! j: b5 b; t, I( K1 `: L# ]$ `
/* Allow the board to save important registers */6 [4 z: ]+ ~9 ?/ d' a
/*b save_boot_params*/
& u# S9 [" N- a8 pldr r1, =0x1002330c# E4 r1 n, n4 e4 l
ldr r0, [r1]
1 t7 h1 _& M  ~, R& g9 q6 wdmb
. d& S& r5 W$ F  L0 `ldr r2, =0x300
+ q+ }, ?& T! N# L* horr r0, r0, r26 C* \$ ^" n& L+ `5 S% R
dmb% D0 B6 x& E% ~4 p% M, B' {5 |& B
str r0, [r1]
, [  n. p, b# e( e5 J# e) M- d9 W5 D/ f' j1 u
ldr r1, =0x11000c081 h5 H8 }& d2 I% N
mov r0, #08 x+ N3 x8 ^6 W
dmb
8 ~  h. ^! i+ k1 z( g0 @str r0, [r1]
# e- n4 h  f8 a6 j( P7 _" creset11:+ i. Q, M! q* ^8 y
breset11
u-boot的配置用什么?也是这篇网文建议用三星origen板子的配置改。只要把include/configs/origen.h中#define CONFIG_SPL_TEXT_BASE 的值改为0x02023400即可。这个地址是三星提供的BL1程序对它引导的BL2程序的要求。此配置项的作用就是生成SPL程序的lds链接文件的.ram区域的起始地址和设置.TEXT段的起始地址(二者相同),这可在SPL的Makefile文件中看到。然后在新版u-boot目录下运行make origen_defconfig,配置完后交叉编译新版u-boot即可。此时在新版u-boot源码目录下生成spl目录,其中的u-boot-spl.bin就是我们要得到的BL2程序镜像。
下面的工作需要借用精英板光盘提供的CodeSign4SecureBoot_SCP目录文件和旧版u-boot源码。在旧版u-boot源码下有个mkbl2程序是用来生成最终14K大小的bl2.bin文件的,但此程序有问题,用它生成会产生Unsupported szie错误。网上有改过的该程序源码,为方便我直接粘贴如下
/*
* m! J& M. W6 O1 |( v * Copyright (c) 2010 Samsung Electronics Co., Ltd. / w! v, ^5 ^4 x3 N& d2 H" m+ N: r
*              http://www.samsung.com/
* b% s0 }% C3 r9 }1 l, j( k *
& ^) m6 E1 f9 u4 l( X0 q" w. @ * This program is free software; you can redistribute it and/or modify
2 Z5 _$ g0 |& L. i4 ^* Q * it under the terms of the GNU General Public License version 2 as
2 w& K7 \9 K. V1 w/ O * published by the Free Software Foundation. / E6 [& c5 R! W- r% Q! i5 Y
*/  
" [: S: Y- O6 h  9 |3 N1 a2 X) ]  f, D4 o
#include <stdio.h>  
, A) ^  q- Q6 z( b3 y#include <string.h>  5 U9 \. ]$ K: F& H  p
#include <stdlib.h>  
: e0 g5 l' x/ D, ^" W2 C! Q! s  
2 Y7 i2 L9 ]! H! T  h) Nint main (int argc, char *argv[])  ) ^! s9 }# D8 g& v5 p2 X! {
{  9 L9 j- L9 }) j1 P2 N
    FILE        *fp;  # E4 h- `5 {. i+ ~2 E
    unsigned char   src;  
2 a% L4 N6 R+ z6 m7 _4 L6 K    char        *Buf, *a;  
2 d5 ]! P' O7 N, d0 ~+ m% w    int     BufLen;  
1 [- I4 u7 Y2 P( B    int     nbytes, fileLen;  
! O$ }9 l( H! Z3 B    unsigned int    checksum = 0;  + ^9 ~$ @1 W% H6 }* V* C
    int     i;  
$ J7 ?) q9 a  J* D' J  
1 c' R7 z7 L# o2 |. [- Q( g# @8 y    if (argc != 4)  7 L7 t! j! B- `6 T
    {  ( Q& a! s3 v% Q' F6 f' C: ]
        printf("Usage: mkbl1 <source file> <destination file> <size> \n");  
( l, o7 ~6 C- F3 P        return -1;  & o- E. B! X5 F; b. ^' z
    }  6 v, Q) _* e3 a5 @$ v
  
5 ^# h: S. D% f1 c7 `    BufLen = atoi(argv[3]);  ' G: r4 x' n4 }5 E$ `0 \
    Buf = (char *)malloc(BufLen);  
, [4 b3 }% R& \' Z) z; _! O- X- @    memset(Buf, 0x00, BufLen);  % o0 L  W) s+ P4 A; O8 t+ T
    Z$ J* s: d7 H8 w- A9 \
    fp = fopen(argv[1], "rb");  ! |" \$ ]2 Y  }5 F9 s% E  k, W
    if( fp == NULL)  
/ W+ d6 b! q+ x$ [! M5 I4 d* l    {  : f! I' j; j) G* m$ V
        printf("source file open error\n");  
) X( ]. A* r; X. v6 B        free(Buf);  
: F! v7 h& M9 Z        return -1;  7 O# f& m$ t; f  C, t5 S
    }  ) _8 z  A; j+ g: a% H& ~# q$ R, Z9 C
  # d/ ]  X- f- _9 [/ j9 I- [6 }% R( G$ U
    fseek(fp, 0L, SEEK_END);  ( Q  D, h: B4 j" x& Q1 u, y, I
    fileLen = ftell(fp);  
  U! k* V) v! T' v8 [- z+ _    fseek(fp, 0L, SEEK_SET);  7 i- z0 b' L( F+ C
/*
8 l3 q% o  E" P    if ( BufLen > fileLen )
9 G3 a) [; S* ?) Z1 l" R( E    {
9 u! A4 g6 y" u* u# ^+ [8 F/ b" H$ r5 d        printf("Usage: unsupported size\n"); ! A) q' A1 a  L3 k$ f: Z; x
        free(Buf); ! \; o2 t4 c# H4 Z  D3 S8 k& l" h
        fclose(fp);
( G  n/ g- y- M# ~        return -1; 1 V8 p# T8 t+ B( m- B: t* X* b& }
    }
2 X6 D8 V) h  _" |* a2 N+ \& r  n. o*/  ' g: e) V5 S- n' L
    //nbytes = fread(Buf, 1, BufLen, fp);  
+ C9 A9 i. G( _& J, r: a    if(BufLen > fileLen)  ) I$ h4 w2 `1 x
        nbytes = fread(Buf, 1, fileLen, fp);  
4 J/ Q. D: w/ X, }    else  
' |6 }$ M" O2 [# G* j        nbytes = fread(Buf, 1, BufLen, fp);  
8 K7 d! e* \& U# g, y/*
% P2 f  C: T8 a0 V) Q    if ( nbytes != BufLen ) ! Y- {) N1 z! j# m( d
    { * _0 J2 s8 O. p3 y0 \
        printf("source file read error\n");
+ [1 q- t4 Y8 D, A        free(Buf);
9 s- I( \7 @& d( c: T( [% |7 }        fclose(fp);
) X9 c: g- c1 U2 g$ ~        return -1; ; A  l% u- J. K" Y6 }; t
    }
: _3 D* _! G, z0 g4 j6 }5 a*/  # A$ A& k# d4 I$ L  X9 ]! O
    fclose(fp);  
$ W) h5 b. a8 h, S9 Q  
! S  j7 q5 q, f4 L% `" n    for(i = 0;i < (14 * 1024) - 4;i++)  " C- d/ j/ W( a5 |- F5 X" C+ X
    {  % ~, {! N1 H3 S" x+ Y! @
        checksum += (unsigned char)(Buf);  1 A) B6 f- K" \, a
    }  
" Z  }; C+ e) }: P: M/ C' p) I    *(unsigned int*)(Buf+i) = checksum;  
# S- }8 M; f' z, ?8 s' h  
  S5 r! r2 i, ]- G9 }* ]3 k4 S    fp = fopen(argv[2], "wb");  9 J- l3 T7 g9 j) _3 t8 m' u/ X
    if (fp == NULL)  
. b  Y" x" L+ f5 a) b( {' i( v    {  6 U9 |+ Y7 I0 ?5 m* k
        printf("destination file open error\n");  6 z* I0 ~5 g  Y# X" ~7 G
        free(Buf);  
9 U$ b1 L2 h1 J- j! H        return -1;  - n, s# k3 U/ L7 ]
    }  1 A% U" G  D! f4 m" A
  
7 k- V: u/ W+ s% {+ O, [3 V! M* O0 P    a   = Buf;  
5 m* V( X, o; j    nbytes  = fwrite( a, 1, BufLen, fp);  
5 G8 B/ W, h; j9 E; \* c# d  . q3 J9 `8 `# u. i, l4 ~  P
    if ( nbytes != BufLen )  3 P! D6 w: O0 w! L/ p+ q5 a. ^
    {  
) ^4 G' a- M4 j+ M, U        printf("destination file write error\n");  + ~0 Q) t; Y1 |0 m) o
        free(Buf);  
6 D0 I8 k8 L  \0 |        fclose(fp);  $ _2 r3 M5 |% H6 A6 |% Y
        return -1;  : E' u8 u; s  _2 J
    }  + J' [! g; C0 F, x" N( d) p6 ]( c
  " C4 D' k; {5 Z$ Q9 S
    free(Buf);  ! ^- i7 k% a3 d' n
    fclose(fp);  * m1 v  e! S( p$ A
  
  Y4 X- z. s8 r# I! M! _- G    return 0;  7 R& @0 I5 a8 S! x! ^
}  
读者可用此源码本地编译生成可用的mkbl2程序来代替旧版的。然后把编译新版u-boot生成的u-boot-spl.bin拷贝在旧版u-boot源码下。在旧版u-boot源码目录下运行如下命令
./mkbl2 u-boot-spl.bin bl2.bin 14336 生成可用的bl2.bin镜像。把bl2.bin拷贝到CodeSign4SecureBoot_SCP目录下,并把旧版u-boot目录下的E4412_N.bl1.bin拷贝到CodeSign4SecureBoot_SCP目录下。在CodeSign4SecureBoot_SCP目录下新建一shell脚本文件my_build_bin.sh,内容如下
#!/bin/sh
3 r" x9 x2 |% D# O$ a8 D' lcat E4412_N.bl1.bin bl2.bin all00_padding.bin > u-boot-iTOP-4412.bin9 R% o" w: C: R: t
mv u-boot-iTOP-4412.bin ~/iTop/iTop4412_uboot/
其中mv命令的目标目录是我的旧版u-boot源码目录,读者应改为自己的相应路径。
CodeSign4SecureBoot_SCP目录下运行./my_build_bin命令,在旧版u-boot目录下就有u-boot-iTop-4412.bin文件生成,该文件大小正好为24k,就是我们要烧到SD卡的启动镜像,包括BL1和BL2阶段的程序。然后参考ITop4412 精英板手册出厂前首次烧录TF卡方法用旧版u-boot目录下的mkuboot命令制作SD卡。把SD卡插入精英板,拨码开关设置为TF卡启动模式,启动精英板,用JLinkExe连接目标板,此时输出部分截图如下
可以看到此时MMU是关闭的。现在用mem再查看0x02000000物理地址区域,可以访问了!貌似JLINK不支持一次读取大量内存内容,我用savebin命令分次读取了iROM在0x02000000的64k映像,合并成一个文件,并用arm-eabi-objdump反汇编之,就可以弄清完整史前时代的来龙去脉了。下面是iROM程序的反汇编成果的开始部分,有兴趣的读者可以留邮箱,我会把完整的64k iROM程序镜像发给你。
irom:     fileformat binary
$ h/ h, J9 c" V, O- D, A
8 ?4 @" _+ ~$ j1 A% J8 n+ x' e3 ]" A( q8 Y+ x( S7 I
Disassembly of section .data:% b+ z  m- a2 k9 [

2 b4 G7 `- J; E5 ~7 K00000000 <.data>:
5 j; R1 v% E) U% m       0:   ea000006   b   0x20
; q, L0 `7 u; J; N- Z3 a       4:   eafffffe   b   0x4
, }8 j2 F; b; i1 k* l8 `       8:   eafffffe   b   0x85 @) x; n9 B; E$ n
       c:   eafffffe   b   0xc$ o9 |' f+ f7 f8 p) p0 E  v. G; P) L
      10:   eafffffe   b   0x10
! y. s; w/ i# T  N      14:   eafffffe   b   0x14
' S) v2 y" Q6 z8 S" [" z      18:   ea00301a   b   0xc088$ ?% S& A( Q" c. O2 U
      1c:   ea00301b   b   0xc090. c$ U; f7 t& r- |) D$ [
      20:   e59f01a4   ldr r0,[pc, #420]  ; 0x1cc
1 n9 g& d! M5 j. ^      24:   e3a01000   mov r1,#0
6 N  j0 B( ?; B9 |! x7 f0 n      28:   e5801000   str r1,[r0]
' F# T, G) h* d, P* G      2c:   e59f019c   ldr r0,[pc, #412]  ; 0x1d03 e  ]" t8 l3 U7 o4 q. s
      30:   e5900000   ldr r0,[r0]
8 r& P$ y5 S+ {# ?8 I2 |9 @      34:   e200003e   and r0,r0, #62 ; 0x3e7 A) ?, L7 I" d  }7 j" P4 i4 t
      38:   e330003e   teq r0,#62 ; 0x3e
$ h4 J$ U7 R7 g# [2 J      3c:   1a00000d   bne 0x78
  j3 X8 \( Y+ d0 i      40:   e59f018c   ldr r0,[pc, #396]  ; 0x1d4
5 _8 Z$ \1 Y( ]7 v      44:   e5900000   ldr r0,[r0]
% T  o8 x5 h8 `6 T+ M  S/ f8 p# L2 M      48:   e3100001   tst r0,#1
1 o- |! N  x& }8 |; s: z      4c:   1a000009   bne 0x78
8 |8 Y5 i: A! M3 `0 A2 H      50:   e59f2180   ldr r2,[pc, #384]  ; 0x1d8
* |0 ~& G' A! r3 ~0 K      54:   e5922000   ldr r2,[r2]
6 d" B: M& G# I- z8 X      58:   e3e03000   mvn r3,#0
) j9 J4 P9 M3 K- z6 M1 u4 Y: G8 B      5c:   e1120003   tst r2,r30 n: P5 B3 t( R( Q4 X6 V6 [! s% x
      60:   1a000003   bne 0x748 d# ~0 l. n+ j' P8 I* h& I
      64:   e59f0170   ldr r0,[pc, #368]  ; 0x1dc
7 C' N: \8 F3 p) @- X# p  ?" z      68:   e59f1170   ldr r1,[pc, #368]  ; 0x1e0* R/ ?9 J! `( [5 y
      6c:   e5801000   str r1,[r0]
- ?: d( e9 W# D      70:   e59f2164   ldr r2,[pc, #356]  ; 0x1dc
2 o/ L! p+ S# f5 n  l      74:   e1a0f002   mov pc,r2
. [! f3 a: _' Q! e/ t0 R; P      78:   e321f0d3   msr CPSR_c,#211    ; 0xd3
+ K2 n. A- L+ h; K+ j      7c:   ee110f10   mrc 15,0, r0, cr1, cr0, {0}
+ F9 D0 D2 C1 L* t      80:   e3c00001   bic r0,r0, #12 M# e( k: D# q# B
      84:   e3c00004   bic r0,r0, #4
# J! _% ]0 a3 x5 b# P! T     88:   e3a02281    mov r2,#268435464  ; 0x10000008/ D) Z% {4 `+ D- e+ O* ?3 ]
      8c:   e5923000   ldr r3,[r2]0 g4 ]$ C- g0 l& z7 B
      90:   e3130501   tst r3,#4194304    ; 0x400000
  U( H+ Y3 M1 Z7 P* ^8 d      94:   0a000002   beq 0xa4- x' r  E6 _5 C( p" Q/ Q2 m
      98:   e3c00a01   bic r0,r0, #4096   ; 0x1000$ s: H9 f7 ?% W& A' ?1 `7 a
      9c:   ee010f10   mcr 15,0, r0, cr1, cr0, {0}
8 N/ s. h, d6 |* l      a0:   ea000006   b   0xc0+ ~1 B3 T" U1 B
      a4:   e3a00000   mov r0,#06 W4 M1 g7 B5 z* A% L& l) E
      a8:   ee080f17   mcr 15,0, r0, cr8, cr7, {0}0 x- \2 s1 T% \# P
      ac:   ee070f15   mcr 15,0, r0, cr7, cr5, {0}; C/ K3 e& r7 G  b
      b0:   eb0022ea   bl  0x8c60
( m) h) f# R) a      b4:   ee110f10   mrc 15,0, r0, cr1, cr0, {0}
; L- w- v, a0 z8 a* `. _7 j      b8:   e3800a01   orr r0,r0, #4096   ; 0x1000" G6 t7 Z, U% S! Z; u! r3 l/ D: g
      bc:   ee010f10   mcr 15,0, r0, cr1, cr0, {0}5 O% X+ u9 ~7 d2 p
      c0:   ee10cfb0   mrc 15,0, ip, cr0, cr0, {5}; L# p! u" w6 v3 d/ z. S
      c4:   e20cc003   and ip,ip, #3
; d2 ~/ z5 V: S4 o# U      c8:   e59f2114   ldr r2,[pc, #276]  ; 0x1e4
* |1 o1 l$ V% O5 g' m      cc:   e082010c   add r0,r2, ip, lsl #2$ t# G$ u$ W: H
      d0:   e35c0000   cmp ip,#0
; x% A% L$ U; q1 o$ T      d4:   1a0022da   bne 0x8c44
% j( k5 g, E1 x      d8:   e59f0108   ldr r0,[pc, #264]  ; 0x1e8
* B; @( I  n1 w2 s      dc:   e5900000   ldr r0,[r0]: y4 P' v- k# M& N. f' O
      e0:   e3a01102   mov r1,#-2147483648    ; 0x800000001 v- H* a( E3 ?7 e# ~; k
      e4:   e1100001   tst r0,r1* s% T& x2 K, t2 F/ O: s; j% Y
      e8:   0a000024   beq 0x180* r, s. X/ D" n
      ec:   e59f00f8   ldr r0,[pc, #248]  ; 0x1ec
' T) `+ h& a8 f5 M. [2 D, f      f0:   e5900000   ldr r0,[r0]
5 N9 {3 z& h* d4 c5 y9 J      f4:   e3100001   tst r0,#1( `! q' C/ A; Q# p
      f8:   0a000020   beq 0x180
! v& H! C+ V. J! t7 T      fc:   e59f00ec   ldr r0,[pc, #236]  ; 0x1f0
' R' d+ q7 V% u( X- Z     100:   e5900000   ldr r0,[r0]
至此,我们的史前时代探险完成了。作为一个有价值的副产品,我们也建立了用JLINK搭建的boot阶段程序调试环境。下面我简要介绍下gdb调试环境的搭建。
退出JLinkExe,运行JLinkGDBServer -device CORTEX-A9 -speed 4000命令,则JLinkGDBServer就与目标建立了连接,并等待gdb连入。在另一个虚拟终端下运行arm-eabi-gdb命令,在(gdb)提示符下输入target remote localhost:2331命令与JLinkGDBServer建立连接,用file命令关联新版u-boot源码spl目录下的u-boot-spl文件,就可以进行源码级调试了。这样,我们就搭建了一个实用的boot阶段程序调试环境,并可以借用新版u-boot源码平台开发属于自己的boot程序了。
附主要参考的文章链接:
http://blog.csdn.net/techping/article/details/69911634
http://www.cnblogs.com/humaoxiao/p/4166230.html
http://blog.csdn.net/lizuobin2/article/details/52832857
0 w: |. c( \1 @% O7 V; B6 d

作者: 紫菁    时间: 2017-9-12 13:41

作者: 孟亚凡    时间: 2017-9-22 10:30
多谢分享教程,学习了,好贴
作者: 孤久厌闹    时间: 2017-10-9 15:03
1111111111111111,好贴
作者: soku338    时间: 2017-10-27 11:17
好贴,受益了
作者: chfanjiang    时间: 2017-10-28 19:16
好贴,受益了
作者: whawbb    时间: 2017-11-25 20:25
晕 在我帖里面找偶像啊??
作者: 罗云安安    时间: 2018-2-9 10:32
赞,,好文章




欢迎光临 EDA365电子工程师网 (https://bbs.elecnest.cn/) Powered by Discuz! X3.2