u-boot-2013.04-rc1 在ok6410的移植

#1.解压
tar -jxvf u-boot-2013.04-rc1.tar.bz2

#2.删除不必要的文件

/arch/下除arm
/arch/arm/cpu/下除arm1176和uboot.lds
/arch/arm/include/asm/arch-* 除 arch-64xx
/board/下除samsung
/board/samsung/下smdk*除smdk6400
/nand_spl/board/下除samsung/include/configs/下除smdk6400.h

#3.准备ok6410的单板信息

mv board/samsung/smdk6400 board/samsung/ok6410
mv board/samsung/ok6410/smdk6400_nand_spl.c board/samsung/ok6410/ok6410_nand_spl.c
mv board/samsung/ok6410/smdk6400.c board/samsung/ok6410/ok6410.c
board/samsung/ok6410/ok6410.c  中 smdk6400 改为 ok6410  s3c6400 -> s3c6410
board/samsung/ok6410/makefile  中 smdk6400 改为 ok6410

#4.建立nand_spl

mv nand_spl/board/samsung/smdk6400 nand_spl/board/samsung/ok6410
nand_spl/board/samsung/ok6400/makefile 中 smdk6400 改为 ok6410

#5.建立头文件

mv arch/arm/include/asm/arch-s3c64xx/s3c6400.h arch/arm/include/asm/arch-s3c64xx/s3c6410.h
arch/arm/include/asm/arch-s3c64xx/s3c6410.h 中
#define DMC1_MEM_CFG    0X0001001A  /* burst 4, 14-bit row, 10-bit col */
#define DMC1_MEM_CFG2   0XB45
#define DMC1_CHIP0_CFG  0X150F0     /* 0X5000_0000~0X5FFF_FFFF(256MB) */mv include/configs/smdk6400.h   include/configs/ok6410.h
include/configs/ok6410.h 中 S3C6400 改为 S3C6410
#define CONFIG_SYS_PROMPT   "ok6410#"
#define CONFIG_IDENT_STRING "for ok6410"
#define PHYS_SDRAM_1_SIZE   0x10000000  /* 256MB */

#6.处理器makefile
arch/arm/cpu/arm1176/s3c64xx/makefile 中 S3C6400 改为 S3C6410

#7.其他

ok6410.c 和 lowlevel_init.S 中 smdk6400 -> ok6410 s3c6400 -> s3c6410arch/arm/cpu/arm1176/s3c64xx中
cpu_init.S reset.S speed.c timer.cdrivers/usb/host/s3c64xx-hcd.c
drivers/mtd/nand/s3c64xx.c
drivers/serial/s3c64xx.cinclude/common.h        CONFIG_S3C6400 -> CONFIG_S3C6410
drivers/usb/host/ohci-hcd.c CONFIG_S3C6400 -> CONFIG_S3C6410

#8.顶层makefile
SMDK6400 -> OK6410

#9.编译

export BUILD_DIR=./build
make ok6410_config
make all

DEBUG:

#arm-linux-ld:/home/forlinx/u-boot/u-boot-2013.04-rc1/build/u-boot.lds:19: syntax error
/home/forlinx/u-boot/u-boot-2013.04-rc1/board/samsung/ok6410/u-boot-nand.lds 中
align -> ALIGN#/home/forlinx/u-boot/u-boot-2013.04-rc1/build/nand_spl/board/samsung/ok6410/start.S:227: undefined reference to `_main'
nand_spl/board/samsung/ok6410/Makefile 中
SOBJS   = start.o cpu_init.o lowlevel_init.o crt0.o$(obj)crt0.S:@rm -f $@@ln -s $(TOPDIR)/arch/arm/lib/crt0.S $@/arch/arm/lib/crt0.S 中注释@bl coloured_LED_init@bl red_led_on

#10.MMC启动

编写 arch/arm/cpu/arm1176/s3c64xx/s3c6410_sdboot.c
arch/arm/cpu/arm1176/s3c64xx/Makefile中
COBJS-$(CONFIG_S3C6410) += cpu_init.o speed.o
COBJS-$(CONFIG_BOOT_SD) += s3c6410_sdboot.o
COBJS-y += timer.o init.o
arch/arm/cpu/arm1176/start.S中
#if defined(CONFIG_BOOT_SD) && !defined(CONFIG_NAND_SPL)ldr     sp,=CONFIG_SYS_INIT_SP_ADDRbl  BootCopyMMCtoMemcmp r0,#0
copyerror:beq   copyerrorldr    pc,=_main  @to BL2 in SDRAM
#elsebl _main
#endif
include/configs/ok6410.h中
#define CONFIG_BOOT_SD
board/samsung/ok6410/lowlevel_init.S中
LED初始化修改
时钟初始化修改:/* FOUT of EPLL is 96MHz */@ldr    r1, =0x200203ldr   r1, =0x80200103 @ldr  r1, =0x80200203
MMU表修改:/* 256MB for SDRAM 0xC0000000 -> 0x50000000 */.set __base, 0x500/*.rept 0xC80 - 0xC00 by Ronny*/.rept 0xD00 - 0xC00FL_SECTION_ENTRY __base, 3, 0, 1, 1.set __base, __base + 1.endr/* access is not allowed. *//*.rept 0x1000 - 0xC80 by Ronny*/.rept 0x1000 - 0xD00.word 0x00000000.endr
include/configs/ok6410.h中
#define CONFIG_MACH_TYPE 1626
#define CONFIG_SYS_HZ   1562500
#define CONFIG_ENV_SIZE 0X80000
#define CONFIG_ENV_OFFSET   0X0080000
#define CONFIG_SYS_NAND_U_BOOT_OFFS (16*1024)
#define CONFIG_SYS_NAND_U_BOOT_SIZE (496*1024)
#define CONFIG_SYS_NAND_PAGE_SIZE 4096
#define CONFIG_SYS_NAND_PAGE_COUNT 128
#define CONFIG_SYS_NAND_BLOCK_SIZE (128*4096)
#define CONFIG_SYS_NO_FLASH
arch/arm/lib/borad.c//hang();
include/flash.h中
#ifdef CONFIG_SYS_NO_FLASH
链接文件修改
board/samsung/ok6410/u-boot-nand.lds:
.text      :{arch/arm/cpu/arm1176/start.o   (.text)board/samsung/ok6410/libok6410.o (.text)*(.text)}
raise : signal #8 caught异常
arch/arm/cpu/arm1176/s3c64xx/timer.c中DECLARE_GLOBAL_DATA_PTR;
//static ulong timer_load_val;
//static unsigned long lastdec;
//static unsigned long long timestamp;#define timer_load_val    (gd->arch.timer_rate_hz)
#define lastdec     (gd->arch.lastinc)
#define timestamp   (gd->arch.timer_reset_value)
ulong get_timer_masked(void)
{unsigned long long res = get_ticks();//do_div (res, (timer_load_val / (100 * CONFIG_SYS_HZ)));return res;
}

#11.添加MMC驱动
编写 drivers/mmc/s3c6410_sdhci.c

include/configs/ok6410.h :
#define CONFIG_MMC      //select mmc device as block device
#define CONFIG_GENERIC_MMC  //added mmc.c
#define CONFIG_CMD_MMC      //added cmd_mmc.c
#define CONFIG_SDHCI        //added sdhci.c
#define CONFIG_MMC_SDMA
#define CONFIG_S3C6410_SDHCI    //added s3c6410_sdhci.c
dirvers/mmc/sdhci.c :
#define SDHCI_DEFAULT_BOUNDARY_SIZE (1024*512)add_sdhci()
{
..mmc->b_max = 1024;    //blocks sdhci_reset(host, SDHCI_RESET_ALL);mmc_register(mmc);return 0;
}注释
//mask |= SDHCI_INT_DATA_END;
drivers/mmc/Makefile
COBJS-$(CONFIG_S3C6410_SDHCI) += s3c6410_sdhci.o

对应uboot的命令

mmc read addr blk# cnt
mmc write addr blk# cnt
mmc erase blk# cnt
mmc rescan
mmc part - lists available partition on current mmc device
mmc dev [dev] [part] - show or set current mmc device [partition]
mmc list - lists available devices
fatinfo mmc 0
fatls mmc 0
fatload mmc 0 50000000 u-boot-nand.bin

#12.添加hello命令

编写 common/cmd_hello.c

common/Makefile
COBJS-$(CONFIG_CMD_HELLO) += cmd_hello.o
ok6410.h
#define CONFIG_CMD_HELLO#MMC环境变量
ok6410.h
#define CONFIG_ENV_IS_IN_NAND
#define CONFIG_SYS_MMC_ENV_DEV  0#ifndef CONFIG_ENV_IS_IN_MMC
#define CONFIG_ENV_IS_IN_NAND
#endif

对应命令

env default [-f] -a - [forcibly] reset default environment
env default [-f] var [...] - [forcibly] reset variable(s) to their default values
env delete [-f] var [...] - [forcibly] delete variable(s)
env edit name - edit environment variable
env export [-t | -b | -c] [-s size] addr [var ...] - export environment
env import [-d] [-t | -b | -c] addr [size] - import environment
env print [-a | name ...] - print environment
env run var [...] - run commands in an environment variable
env save - save environment
env set [-f] name [arg ...]
setenv
saveenv
printenv

#13.cache

arch/arm/lib/cache.c中
void __enable_caches(void)
{icache_enable();if(!icache_status()){puts("WARING: iCache not enabled\n");}dcache_enable();if(!dcache_status()){puts("WARING: dCache not enabled\n");}//puts("WARNING: Caches not enabled\n");
}

需要注意的是,打开data cache会导致mmc无法使用

#14.添加NAND驱动

/ nand //
#define CONFIG_S3C6410_CUSTOM_NAND_TIMING
#define CONFIG_S3C6410_TACLS        7   //hclk*tacls        0~7
#define CONFIG_S3C6410_TWRPH0       7   //hclk*(twrph0+1)  0~7
#define CONFIG_S3C6410_TWRPH1       7   //hclk*(twrph1+1)  0~7#define CONFIG_SYS_NAND_U_BOOT_OFFS  (16*1024)
#define CONFIG_SYS_NAND_U_BOOT_SIZE     (496*1024)
#define CONFIG_SYS_NAND_PAGE_SIZE   4096
#define CONFIG_SYS_NAND_PAGE_COUNT  128
#define CONFIG_SYS_NAND_BLOCK_SIZE  (128*4096)//#define CONFIG_SYS_NAND_SELECT_DEVICE#define CONFIG_SYS_S3C_NAND_HWECC
#define CONFIG_NAND_BL1_8BIT_ECC
#define CONFIG_SYS_NAND_ECCSIZE     512
#define CONFIG_SYS_NAND_ECCBYTES    13
#define CONFIG_SYS_NAND_OOBSIZE     218
#define CONFIG_SYS_NAND_ECCPOS      {114,115,116,117,118,119,120,121,122,123,\124,125,126,127,128,129,130,131,132,133,\134,135,136,137,138,139,140,141,142,143,\144,145,146,147,148,149,150,151,152,153,\154,155,156,157,158,159,160,161,162,163,\164,165,166,167,168,169,170,171,172,173,\174,175,176,177,178,179,180,181,182,183,\184,185,186,187,188,189,190,191,192,193,\194,195,196,197,198,199,200,201,202,203,\204,205,206,207,208,209,210,211,212,213,\214,215,216,217}

nand_base.c 中的nand_get_flash_type()函数的读id有bug,读id前没有片选中nand,记得修改,这里不贴出

drivers/mtd/nand/s3c64xx.c :
#if defined(CONFIG_S3C6410_CUSTOM_NAND_TIMING)tacls  = CONFIG_S3C6410_TACLS;twrph0 = CONFIG_S3C6410_TWRPH0;twrph1 =  CONFIG_S3C6410_TWRPH1;cfg = readl(NFCONF); cfg &= ~(tacls << 12);cfg &= ~(twrph0 << 8);cfg &= ~(twrph1 << 4);cfg |= (tacls << 12);cfg |= (twrph0 << 8);cfg |= (twrph1 << 4);writel(cfg,NFCONF);cfg = readl(NFCONT); cfg |= 0x7;writel(cfg,NFCONT);
#endif
arch/arm/include/arch-s3c64xx/s3c6410.h :
#define NF8ECCERR0      __REG(ELFIN_NAND_BASE + 0x44)
#define NF8ECCERR1      __REG(ELFIN_NAND_BASE + 0x48)
#define NF8ECCERR2      __REG(ELFIN_NAND_BASE + 0x4c)
#define NFM8ECC0        __REG(ELFIN_NAND_BASE + 0x50)
#define NFM8ECC1        __REG(ELFIN_NAND_BASE + 0x54)
#define NFM8ECC2        __REG(ELFIN_NAND_BASE + 0x58)
#define NFM8ECC3        __REG(ELFIN_NAND_BASE + 0x5c)
#define NFMLC8BITPT0        __REG(ELFIN_NAND_BASE + 0x60)
#define NFMLC8BITPT1        __REG(ELFIN_NAND_BASE + 0x64)
board/samsung/ok6410/lowlevel_init.S :
nand_asm_init:ldr   r0, =ELFIN_NAND_BASEldr    r1, [r0, #NFCONF_OFFSET]orr r1, r1, #0x10orr    r1, r1, #0x300str   r1, [r0, #NFCONF_OFFSET]ldr r1, [r0, #NFCONT_OFFSET]orr r1, r1, #0x07str    r1, [r0, #NFCONT_OFFSET]mov pc, lr
nand_base.c:
static struct nand_ecclayout nand_oob_218 = {.eccbytes = 104,.eccpos = { //eccpos要与预定义中的一致,预定义中的eccpos是nand启动必须的24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104, 105, 106, 107, 108, 109, 110, 111,112, 113, 114, 115, 116, 117, 118, 119,120, 121, 122, 123, 124, 125, 126, 127},.oobfree = {{.offset = 2,.length = 22} }
};nand_scan_tail()
{
...case 218:chip->ecc.layout = &nand_oob_218;break;
}
nand_get_flash_type()
{
.....
}

uboot中的命令

nand info - show available NAND devices
nand device [dev] - show or set current device
nand read - addr off|partition sizenand write - addr off|partition sizeread/write 'size' bytes starting at offset 'off'to/from memory address 'addr', skipping bad blocks.nand read.raw - addr off|partition [count]nand write.raw - addr off|partition [count]Use read.raw/write.raw to avoid ECC and access the flash as-is.nand erase[.spread] [clean] off size - erase 'size' bytes from offset 'off'With '.spread', erase enough for given file size, otherwise,'size' includes skipped bad blocks.nand erase.part [clean] partition - erase entire mtd partition'
nand erase.chip [clean] - erase entire chip'
nand bad - show bad blocks
nand dump[.oob] off - dump page
nand scrub [-y] off size | scrub.part partition | scrub.chip really clean NAND erasing bad blocks (UNSAFE)
nand markbad off [...] - mark bad block(s) at offset (UNSAFE)
nand biterr off - make a bit error at offset (UNSAFE)nand read/write 的 size必须为页对齐

#15.nand_spl

cmd_nand.c:
do_nand()
{
...
#endif}else if(!read && s !=NULL && (!strcmp(s,".uboot")) && nand->writesize == 4096){rwsize = 4096;nand_write(nand,off,&rwsize,(u_char*)addr);off += 4096;addr += 2048;nand_write(nand,off,&rwsize,(u_char*)addr);off += 4096;addr += 2048;nand_write(nand,off,&rwsize,(u_char*)addr);off += 4096;addr += 2048;nand_write(nand,off,&rwsize,(u_char*)addr);off += 4096;addr += 2048;rwsize = CONFIG_SYS_NAND_U_BOOT_SIZE - 8*1024;ret = nand_write(nand,off,&rwsize,(u_char*)addr);
#ifdef CONFIG_CMD_NAND_YAFFS
...
}nand_spl/board/samsung/ok6410/config.mk
PAD_TO  := $(shell expr $$[$(CONFIG_SYS_TEXT_BASE) + 8192])   #有bug
PAD_TO  := $(shell expr $(CONFIG_SYS_TEXT_BASE) + 8192)
make 后 build/下u-boot.bin大小减u-boot-nand.bin为8192nand_spl工程中的所有中间文件
SOBJS   = start.o cpu_init.o lowlevel_init.o crt0.o
COBJS   = nand_boot.o nand_ecc.o s3c64xx.o ok6410_nand_spl.o nand_base.ocrt0.S中的_main中的board_init_f()在生成u-boot.bin和u-boot-nand.bin时有所不同
u-boot.bin in arch/arm/lib/crt0.S
u-boot-nand.bin in board/samsung/ok6410/ok6410_nand_spl.ccrt0.S:
#if defined(CONFIG_NAND_SPL)/* deprecated, use instead CONFIG_SPL_BUILD */ldr   sp, =(CONFIG_SYS_INIT_SP_ADDR)
/*bss_clean:*/          /* bug*/ldr r0, =__bss_start   /* this is auto-relocated! */ldr    r1, =__bss_end__   /* this is auto-relocated! */mov    r2, #0x00000000     /* prepare zero to clear BSS */
bss_clean:cmp   r0,r1strlo  r2,[r0]addlo    r0,r0,#4blo bss_cleanldr    pc,=nand_boot
#elif defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)ok6410.h:
#ifdef CONFIG_ENABLE_MMU
#define CONFIG_SYS_MAPPED_RAM_BASE  0xc0000000
//#define CONFIG_BOOTCOMMAND    "nand read 0xc0018000 0x100000 0x500000;" \"bootm 0xc0018000"
#else
#define CONFIG_SYS_MAPPED_RAM_BASE  CONFIG_SYS_SDRAM_BASE
//#define CONFIG_BOOTCOMMAND    "nand read 0x50018000 0x100000 0x500000;" \"bootm 0x50018000"
#endif#ifdef CONFIG_BOOT_SD
#define CONFIG_BOOTCOMMAND  "fatload mmc 0 50008000 u-boot-nand.bin;" \"nand erase.chip;"               \"nand write.uboot 50008000 0 0"
#else
#define CONFIG_BOOTCOMMAND  "fatload mmc 0 50008000 uImage;"      \"bootm    50008000"
#endif

#16.DM9000网卡驱动移植

#if 0
#define CONFIG_CS8900           /* we have a CS8900 on-board    */
#define CONFIG_CS8900_BASE      0x18800300
#define CONFIG_CS8900_BUS16     /* follow the Linux driver  */
#endif
//dm9000 macros
#define CONFIG_DM9000
#define CONFIG_DM9000_NO_SROM 1
#define CONFIG_DRIVER_DM9000 1
//dm9000
#define CONFIG_DM9000_BASE 0x18800300
#define DM9000_IO CONFIG_DM9000_BASE
#define DM9000_DATA (CONFIG_DM9000_BASE + 0X04)
#define CONFIG_DM9000_USE_16BIT
#define CONFIG_ETHADDR  00:40:5c:26:0a:5b
#define CONFIG_NETMASK  255.255.255.0
#define CONFIG_IPADDR       192.168.244.244
#define CONFIG_SERVERIP     192.168.244.132
#define CONFIG_GETEWAYIP    192.168.244.1board/samsung/ok6410/ok6410.c:
int board_eth_init(bd_t *bis)
{int rc = 0;
#ifdef CONFIG_CS8900rc = cs8900_initialize(0, CONFIG_CS8900_BASE);
#endif
#ifdef CONFIG_DM9000rc = dm9000_initialize(bis);
#endifreturn rc;
}

OK6410移植UBOOT相关推荐

  1. 移植u-boot到stm32f407

    上年刚从硬件跳槽为嵌软,没有任何一丝丝的防备,一入职.领导就交代了一特难任务-在stm32上移植linux,瞬间我就懵逼了~没办法硬着头发上,先搜集资料,一看还真是个艰难的任务,我之前跑的是ok641 ...

  2. uboot和linux内核移植,Uboot与kernel移植总结

    设置uimage入口:由于一个可执行的Image必须有一个入口点,并且只能有一个全局入口,通常这个入口放在ROM(Flash)的0x0地址,因此,必须通知编译器以使其知道这个入口,该工作可通过修改连接 ...

  3. S5PV210之Sate210-F DIY硬件,移植uboot,kernel,android 活动现在已经进入实施阶段吗,欢迎广大网友参与 !...

    大家一起来diy 超低价四核的exynos4412或者Cortex A8S5pv210开源开发板 商业版Sate210已经完成了好久了. Sate4412 也已经出来. 但是这两个接口非常全,主要是针 ...

  4. 移植U-BOOT之支持烧写YAFFS文件系统以及制作U-BOOT补丁

    今天,我们来移植U-BOOT让其支持YAFFS文件系统映像的烧写,以及最后的终极目标,制作Uboot补丁,因为我们信心苦苦移植好了Uboot,如果换一个地方的或者换一台电脑之类的,我们也不想再浪费时间 ...

  5. jz2440开发板移植U-boot之修改代码支持DM9000网卡

    今天我们来移植U-boot到jz2440开发板,修改代码支持DM9000网卡.查看之前写的移植记录请点击链接:点击查看之前的移植记录 现在大多数开发板都支持DM9000网卡.我们的U-boot源码里面 ...

  6. 移植uboot之修改代码支持NorFlash记录续集二

    先说一个事:我会在最后把移植好的uboot,内核,分别做一个补丁文件,以后如果用到相同的uboot以及内核都可以直接下载我这个补丁进行打补丁操作就可以直接用~ 上一个移植uboot续集,我们解决了无法 ...

  7. 移植uboot之修改代码支持NorFlash记录续集

    接着上一篇文章写的内容(上一篇文章链接:移植uboot之修改代码支持NORFLASH),上一篇结尾测试flash的擦除读写功能,结果无法写flash,卡在了这里: 前面已经擦除成功,这里写内容写不进去 ...

  8. 移植uboot之修改代码支持NorFlash记录

    学习交流加 个人qq: 1126137994 个人微信: liu1126137994 学习交流资源分享qq群: 962535112 今天我们的任务是修改uboot源码支持NorFlash. 上两篇关于 ...

  9. 移植U-Boot思路和实践 | 基于RK3399

    0. 背景介绍 我们手里这块RK3399开发板出厂时带的是2017.09版本的U-Boot. U-Boot 2017.09 (Sep 26 2021 - 08:53:15 +0000)Model: F ...

  10. fpga烧写bin文件_S3C2440移植uboot之编译烧写uboot

    @[TOC] 移植环境 主 机:VMWare--ubuntu16.04 开发板:S3C2440 编译器:arm-linux-gcc-4.3.2.tgz u-boot:u-boot-2012.04.01 ...

最新文章

  1. Scrapy基础(一) ------学习Scrapy之前所要了解的
  2. CS中using的使用-以FileStream写入文件为例
  3. f12 卡 谷歌浏览器_干货分享。关于谷歌浏览器的使用技巧,不需要插件
  4. 出现画面抖动_解析液晶拼接大屏在使用中出现的常见问题及解决方案
  5. python数据结构_(列表)大O性能_学习笔记(2)
  6. 支持M1芯片mac 达芬奇17中文版(详细安装教程) DaVinci Resolve Studio 17.3.1b5
  7. 常量池在堆还是方法区_详解Java 虚拟机(第③篇)——String 类和常量池
  8. jquery 表单验证
  9. Oracle非常规恢复(使用BBED跳过归档)
  10. VS2010 在Win 7 附加w3wp.exe进程进行调试
  11. Java EE7和Maven工程入门(1)
  12. webservice框架 java_java开发webservice的几种方式详解
  13. android listener使用实例,如何使用lambda表达式/缩短onclicklisteners android studio(示例代码)...
  14. 【喜报】利用COOC又发表了多篇一区SCI、SSCI、CSSCI
  15. Mybatis的学习
  16. 在studio one中使用iZotope Ozone 9?臭氧9怎么导入到Logic Pro X和AU中?速看教程
  17. MTK modem log中判断SIM卡类型__2020.07.16
  18. 磊科nw336 linux驱动程序,Ubuntu 10.04 安装磊科nw336驱动 rtl8188su rtl8192su
  19. 第六十五集 Squid缓存代理服务(p≧w≦q)
  20. 常见恶意软件类型及危害

热门文章

  1. FPGA基本设计流程
  2. 怎么根据分隔符号将Excel数据换行复制
  3. 【LaTeX入门】15、在文章中添加脚注
  4. 基于MATLAB小波变换的的图像压缩
  5. VB操作excel 格式设置及打印页面设置(精简)
  6. 吾欲使汝为恶,则恶不可为;使汝为善,则我不为恶。
  7. Android Studio 开关控件Switch使用
  8. 三角函数科学计算机在线应用,Scientific Calculator插件,在线科学计算器
  9. 通过wait,notify等实现线程通讯
  10. 【办公类-09】20220511word邮件合并功能插入照片(上下环绕照片)