u-boot移植第一弹——制作可用的BL1
我的BL1源代码来源于网路,博客地址是http://blog.csdn.net/xiaojiaohuazi/article/details/8265757。在这里记录下自己的移植心得。
为什么要制作这个BL1呢,对于官方以及很多人说的它是u-boot启动的第二阶段,这里我不做过多说明,我想说的是,这个BL1可以让你对内存操作的理解更加深入,对于后面移植u-boot的理解有帮助。
实际上在BL1阶段只需要做串口和内存的初始化就可以了,初始化串口的目的是调试使用,这个是必须要的;初始化内存那不用说了,你想拷贝代码,不初始化内存怎么能行的。
但是在这里我还加入了一个LED的操作代码,为什么要加入呢,对于学习一个东西,不能说会移植了就算学会了,我想有问题的时候会调试才是更重要的,在开发时也是如此,有了调试手段就有了查错的手段,那么找问题就可以很方便的定位了。所以加入这个LED的控制目的也就是为了调试使用,这也是看到网上有人说过,仔细想想,非常好用,O(∩_∩)O。
首先看看我的BL1的所有文件:
这里只说明移植的时候涉及到的文件,build、main.c、mem_setup.S、s5pv210.h、start.S这几个文件。其中build是我加入的一个文件,目的在操作编译烧写的时候减少输入命令,build文件的内容如下:
#!/bin/sh
make
./mkv210_image bl.bin blSD2.bin
dd iflag=dsync oflag=dsync if=blSD2.bin of=/dev/sdc seek=1
做的工作就是编译,制作BL1,烧写到SD卡。
这个BL1启动的入口也是在start.S文件,看看做的是什么:
.text.global _start_start:bl mem_ctrl_asm_initldr sp, =0xD0035400bl mainloop:b loop
第一步就是初始化内存也就是进入mem_ctrl_asm_init这个函数进行执行,这个函数的代码如下:
mem_ctrl_asm_init:/* DMC0 Drive Strength (Setting 2X) */ldr r0, =ELFIN_GPIO_BASEldr r1, =0x0000AAAAstr r1, [r0, #MP1_0DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP1_1DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP1_2DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP1_3DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP1_4DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP1_5DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP1_6DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP1_7DRV_SR_OFFSET]ldr r1, =0x00002AAAstr r1, [r0, #MP1_8DRV_SR_OFFSET]/* DMC1 Drive Strength (Setting 2X) */ldr r0, =ELFIN_GPIO_BASEldr r1, =0x0000AAAAstr r1, [r0, #MP2_0DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP2_1DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP2_2DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP2_3DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP2_4DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP2_5DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP2_6DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP2_7DRV_SR_OFFSET]ldr r1, =0x00002AAAstr r1, [r0, #MP2_8DRV_SR_OFFSET]/* DMC0 initialization at single Type*/ldr r0, =APB_DMC_0_BASEldr r1, =0x00101000 @PhyControl0 DLL parameter setting, manual 0x00101000str r1, [r0, #DMC_PHYCONTROL0]ldr r1, =0x00000086 @PhyControl1 DLL parameter setting, LPDDR/LPDDR2 Casestr r1, [r0, #DMC_PHYCONTROL1]ldr r1, =0x00101002 @PhyControl0 DLL onstr r1, [r0, #DMC_PHYCONTROL0]ldr r1, =0x00101003 @PhyControl0 DLL startstr r1, [r0, #DMC_PHYCONTROL0]find_lock_val:ldr r1, [r0, #DMC_PHYSTATUS] @Load Phystatus register valueand r2, r1, #0x7cmp r2, #0x7 @Loop until DLL is lockedbne find_lock_valand r1, #0x3fc0 mov r2, r1, LSL #18orr r2, r2, #0x100000orr r2 ,r2, #0x1000 orr r1, r2, #0x3 @Force Value lockingstr r1, [r0, #DMC_PHYCONTROL0]#if 0 /* Memory margin test 10.01.05 */orr r1, r2, #0x1 @DLL offstr r1, [r0, #DMC_PHYCONTROL0]
#endif/* setting DDR2 */ldr r1, =0x0FFF2010 @ConControl auto refresh offstr r1, [r0, #DMC_CONCONTROL]ldr r1, =DMC0_MEMCONTROL @MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down offstr r1, [r0, #DMC_MEMCONTROL]ldr r1, =DMC0_MEMCONFIG_0 @MemConfig0 256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixedstr r1, [r0, #DMC_MEMCONFIG0]ldr r1, =DMC0_MEMCONFIG_1 @MemConfig1str r1, [r0, #DMC_MEMCONFIG1]ldr r1, =0xFF000000 @PrechConfigstr r1, [r0, #DMC_PRECHCONFIG]ldr r1, =DMC0_TIMINGA_REF @TimingAref 7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E)str r1, [r0, #DMC_TIMINGAREF]ldr r1, =DMC0_TIMING_ROW @TimingRow for @200MHzstr r1, [r0, #DMC_TIMINGROW]ldr r1, =DMC0_TIMING_DATA @TimingData CL=3str r1, [r0, #DMC_TIMINGDATA]ldr r1, =DMC0_TIMING_PWR @TimingPowerstr r1, [r0, #DMC_TIMINGPOWER]ldr r1, =0x07000000 @DirectCmd chip0 Deselectstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x01000000 @DirectCmd chip0 PALLstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00020000 @DirectCmd chip0 EMRS2str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00030000 @DirectCmd chip0 EMRS3str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00010400 @DirectCmd chip0 EMRS1 (MEM DLL on, DQS# disable)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00000542 @DirectCmd chip0 MRS (MEM DLL reset) CL=4, BL=4str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x01000000 @DirectCmd chip0 PALLstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x05000000 @DirectCmd chip0 REFAstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x05000000 @DirectCmd chip0 REFAstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00000442 @DirectCmd chip0 MRS (MEM DLL unreset)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00010780 @DirectCmd chip0 EMRS1 (OCD default)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00010400 @DirectCmd chip0 EMRS1 (OCD exit)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x07100000 @DirectCmd chip1 Deselectstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x01100000 @DirectCmd chip1 PALLstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00120000 @DirectCmd chip1 EMRS2str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00130000 @DirectCmd chip1 EMRS3str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00110400 @DirectCmd chip1 EMRS1 (MEM DLL on, DQS# disable)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00100542 @DirectCmd chip1 MRS (MEM DLL reset) CL=4, BL=4str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x01100000 @DirectCmd chip1 PALLstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x05100000 @DirectCmd chip1 REFAstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x05100000 @DirectCmd chip1 REFAstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00100442 @DirectCmd chip1 MRS (MEM DLL unreset)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00110780 @DirectCmd chip1 EMRS1 (OCD default)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00110400 @DirectCmd chip1 EMRS1 (OCD exit)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x0FF02030 @ConControl auto refresh onstr r1, [r0, #DMC_CONCONTROL]ldr r1, =0xFFFF00FF @PwrdnConfigstr r1, [r0, #DMC_PWRDNCONFIG]ldr r1, =DMC0_MEMCONTROL @MemControl 0x00202400 BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down offstr r1, [r0, #DMC_MEMCONTROL]/* DMC1 initialization */ldr r0, =APB_DMC_1_BASEldr r1, =0x00101000 @Phycontrol0 DLL parameter settingstr r1, [r0, #DMC_PHYCONTROL0]ldr r1, =0x00000086 @Phycontrol1 DLL parameter settingstr r1, [r0, #DMC_PHYCONTROL1]ldr r1, =0x00101002 @PhyControl0 DLL onstr r1, [r0, #DMC_PHYCONTROL0]ldr r1, =0x00101003 @PhyControl0 DLL startstr r1, [r0, #DMC_PHYCONTROL0]
find_lock_val1:ldr r1, [r0, #DMC_PHYSTATUS] @Load Phystatus register valueand r2, r1, #0x7cmp r2, #0x7 @Loop until DLL is lockedbne find_lock_val1and r1, #0x3fc0 mov r2, r1, LSL #18orr r2, r2, #0x100000orr r2, r2, #0x1000orr r1, r2, #0x3 @Force Value lockingstr r1, [r0, #DMC_PHYCONTROL0]#if 0 /* Memory margin test 10.01.05 */orr r1, r2, #0x1 @DLL offstr r1, [r0, #DMC_PHYCONTROL0]
#endif/* settinf fot DDR2 */ldr r0, =APB_DMC_1_BASEldr r1, =0x0FFF2010 @auto refresh offstr r1, [r0, #DMC_CONCONTROL]ldr r1, =DMC1_MEMCONTROL @MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down offstr r1, [r0, #DMC_MEMCONTROL]ldr r1, =DMC1_MEMCONFIG_0 @MemConfig0 512MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixedstr r1, [r0, #DMC_MEMCONFIG0]ldr r1, =DMC1_MEMCONFIG_1 @MemConfig1str r1, [r0, #DMC_MEMCONFIG1]ldr r1, =0xFF000000str r1, [r0, #DMC_PRECHCONFIG]ldr r1, =DMC1_TIMINGA_REF @TimingAref 7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4str r1, [r0, #DMC_TIMINGAREF]ldr r1, =DMC1_TIMING_ROW @TimingRow for @200MHzstr r1, [r0, #DMC_TIMINGROW]ldr r1, =DMC1_TIMING_DATA @TimingData CL=3str r1, [r0, #DMC_TIMINGDATA]ldr r1, =DMC1_TIMING_PWR @TimingPowerstr r1, [r0, #DMC_TIMINGPOWER]ldr r1, =0x07000000 @DirectCmd chip0 Deselectstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x01000000 @DirectCmd chip0 PALLstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00020000 @DirectCmd chip0 EMRS2str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00030000 @DirectCmd chip0 EMRS3str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00010400 @DirectCmd chip0 EMRS1 (MEM DLL on, DQS# disable)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00000542 @DirectCmd chip0 MRS (MEM DLL reset) CL=4, BL=4str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x01000000 @DirectCmd chip0 PALLstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x05000000 @DirectCmd chip0 REFAstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x05000000 @DirectCmd chip0 REFAstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00000442 @DirectCmd chip0 MRS (MEM DLL unreset)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00010780 @DirectCmd chip0 EMRS1 (OCD default)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00010400 @DirectCmd chip0 EMRS1 (OCD exit)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x07100000 @DirectCmd chip1 Deselectstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x01100000 @DirectCmd chip1 PALLstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00120000 @DirectCmd chip1 EMRS2str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00130000 @DirectCmd chip1 EMRS3str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00110440 @DirectCmd chip1 EMRS1 (MEM DLL on, DQS# disable)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00100542 @DirectCmd chip1 MRS (MEM DLL reset) CL=4, BL=4str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x01100000 @DirectCmd chip1 PALLstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x05100000 @DirectCmd chip1 REFAstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x05100000 @DirectCmd chip1 REFAstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00100442 @DirectCmd chip1 MRS (MEM DLL unreset)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00110780 @DirectCmd chip1 EMRS1 (OCD default)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00110400 @DirectCmd chip1 EMRS1 (OCD exit)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x0FF02030 @ConControl auto refresh onstr r1, [r0, #DMC_CONCONTROL]ldr r1, =0xFFFF00FF @PwrdnConfig str r1, [r0, #DMC_PWRDNCONFIG]ldr r1, =DMC1_MEMCONTROL @MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down offstr r1, [r0, #DMC_MEMCONTROL]//下面为点灯代码,用于调试ldr r0, =0xE0200C00 ldr r1, =0x11000000 str r1, [r0] ldr r1, =0xc0 str r1, [r0, #4]//上面为点灯代码,用于调试 mov pc, lr
可以看到我在该函数的最后增加了LED灯的代码,具体的含义请参考帖子 http://blog.csdn.net/kevinshq/article/details/7968409不同的板子LED接口可能不同,这样的话就需要修改寄存器的地址了,也可能没有LED,如果是这种情况就需要使用其他的提醒功能来代替LED了(最好是能够看到现象的)。LED代码放在这里在启动板子的时候就可以观察LED的状态来判断内存初始化这部分代码是否启动了。
好,现在回到该函数的起始部分,对于该函数已经有人做过了分析,这里我就引用之博文地址为http://blog.csdn.net/mutemob/article/details/12974483。在这之外我们需要注意一个问题,那就是下面代码的位置处
有可能你的代码红色部分为0x00202400这种格式的16进制,最好是改成上图所示的请款个,目的是为了方便修改。
从start.S文件中可以知道,第二个执行的函数为main函数,函数位置在main.c。
main.c文件源代码请下载下来观看,这里我就不一次全部贴上来了。我们从main主函数出发,看看都做了些什么:
int main (void)
{__attribute__((noreturn)) void (*uboot)(void); uart_init(); //串口初始化mem_test(); //内存测试printf ("copy uboot from sd to sdram ddr2\r\n"); copy_uboot_to_ram(); printf ("jump to u-boot image\r\n"); //下面代码是控制班子上的LED,可用于调试 //*(volatile unsigned int *)0xE0200C00 = 0x11000000; //*(volatile unsigned int *)0xE0200C04 = 0x000000c0; //上面代码是控制班子上的LED,可用于调试 /* Jump to U-Boot imaguboot = (void *)0x33e00000; (*uboot)(); return 1;
}
开始进行了串口的初始化,然后是内存的测试,接着是u-boot的拷贝阶段,最后跳转到u-boot的位置开始执行。我的u-boot的起始地址是0x33e00000,不同的板子地址可能有所不同,请调整为自己的u-boot起始地址即可,也就是把0x33e00000换成自己的板子的地址。
串口的初始化我的板子是Real210板子,调试口使用的是串口2,所以在网络上原来的代码基础上把他的串口初始化从串口0修改到了串口2,在源码的s5pv210.h中可以看到各寄存器的定义。串口的初始化是在文件uart.c中进行,这里我不再说明,具体的请参阅s5pv210 pdf进行对比学习。
内存的测试函数mem_test()代码如下:
void mem_test()
{#define test_mem1 0x30000000#define test_mem2 0x33e00004#define test_mem3 0x3f000f08#define test_mem4 0x3ffff0fc#define test_mem5 0x3ffffffc //内存地址是每隔4个字节存放的,所以访问时是4个字节访问#define test_mem6 0x40000000#define test_mem7 0x43e00004#define test_mem8 0x4f00f008#define test_mem9 0x4ffffff8 #define test_mem10 0x4ffffffcunsigned int *p1 = (volatile unsigned int *)test_mem1;unsigned int *p2 = (volatile unsigned int *)test_mem2;unsigned int *p3 = (volatile unsigned int *)test_mem3;unsigned int *p4 = (volatile unsigned int *)test_mem4;unsigned int *p5 = (volatile unsigned int *)test_mem5;unsigned int *p6 = (volatile unsigned int *)test_mem6;unsigned int *p7 = (volatile unsigned int *)test_mem7;unsigned int *p8 = (volatile unsigned int *)test_mem8;unsigned int *p9 = (volatile unsigned int *)test_mem9;unsigned int *p10 = (volatile unsigned int *)test_mem10;printf ("******s5pv210 Test********\r\n");printf ("********By ZheGao********\r\n");*p1 = 0x12345678;if (*p1 == 0x12345678) {printf ("1: equ\r\n");} else {printf ("1: not equ\r\n");}*p2 = 0x12345678;if (*p2 == 0x12345678) {printf ("2: equ\r\n");} else {printf ("2: not equ\r\n");}*p3= 0xfffffff0;if (*p3 == 0xfffffff0) {printf ("3: equ\r\n");} else {printf ("3: not equ\r\n");}*p4 = 0x12345678;if (*p4 == 0x12345678) {printf ("4: equ\r\n");} else {printf ("4: not equ\r\n");}*p5 = 0x12345678;if (*p5 == 0x12345678) {printf ("5: equ\r\n");} else {printf ("5: not equ\r\n");}*p6= 0xfffffff0;if (*p6 == 0xfffffff0) {printf ("6: equ\r\n");} else {printf ("6: not equ\r\n");}*p7 = 0x12345678;if (*p7 == 0x12345678) {printf ("7: equ\r\n");} else {printf ("7: not equ\r\n");}*p8 = 0x12345678;if (*p8 == 0x12345678) {printf ("8: equ\r\n");} else {printf ("8: not equ\r\n");}*p9= 0x12345678;if (*p9 == 0x12345678) {printf ("9: equ\r\n");} else {printf ("9: not equ\r\n");}*p10= 0x12345678;if (*p10 == 0x12345678) {printf ("10: equ\r\n");} else {printf ("10: not equ\r\n");}}
从最开始宏定义可以知道测试的内存地址,这里把我板子的全部内存做了隔段测试,我的内存地址是从0x30000000到0x4fffffff总共512MB,注意在测试的时候内存地址需要隔4个字节进行测试,也就是最后一位只能取值0、4、8、c这四个值,原因是,我们的内存是32位的也就是4个字节,所以在测试访问的时候需要隔4个字节,注意不能取最后一位除0、4、8、c以外的值,否者就会死掉。
copy_uboot_to_ram()这个拷贝函数的说也参考一个博文http://blog.csdn.net/shangguobuliuhen/article/details/9844371。
同样在main函数中也有LED灯的代码,不过这次换成了C语言的写法,放在这里也是为了判断代码执行的位置,进而判断代码会死在哪里,这个LED定位的思想要灵活运用,可以为你学习和调试带来极大的帮助。就在u-boot中一样我们使用串口打印信息来进行调试一个道理。
第一阶段告一段落,后面继续更新,下一个就是让u-boot能够启动并能进入控制台,过些天在写上来吧。有问题得朋友可以留言,大家共同探讨。
u-boot移植第一弹——制作可用的BL1相关推荐
- 【registry】registry合并带spring boot项目第一弹
1.概述 我现在有一个jetty项目是registry项目是开源的,貌似使用的dropwizard-core框架,现在我有个spring boot项目,想把registry囊括进来,我是直接把regi ...
- 【第一弹】经典移植至IOS端、经典合集
前段时间比较空间,无奈手机又没有一些游戏可玩,之后就在捣鼓一些移植的游戏系列 以免以后在出现手机只能看网页的尴尬局面,也是从网上搜索,整合而至! 一部分是移植到IOS端的,一部分是经典游戏,我也顺道整 ...
- 搜狐快站制作html,搜狐快站H5页面设计制作大赛,获奖作品第一弹!
原标题:搜狐快站H5页面设计制作大赛,获奖作品第一弹! 快海报设计大赛开赛两周以来,已经收到了众多朋友的踊跃投稿.我们从4月15日之前的投稿作品中精选出六部,作为首批获奖者! 我们的比赛并没有结束,下 ...
- 与阿里云容器服务 ACK 发行版的深度对话第一弹:如何借助 sealer 实现快速构建 部署
作者:淮右.王飞.瑜佳 记者: 阿里云原生的读者朋友们大家好,今天应广大感兴趣朋友们的强烈要求,我们邀请来了「阿里云容器服务 ACK 发行版」做客我们的栏目,为大家讲述它的身世之谜,以及它是如何和伙伴 ...
- JVM面试八股文第一弹
大家好,我是路人张,今天更新JVM面试八股文第一弹,JVM这个系列大概会有三到四篇,公众号后台回复"面试手册"可以获取面试后侧PDF版. 推荐阅读: 面试手册第三版,更新! 面试八 ...
- 2023春节祝福系列第一弹(下)(放飞祈福孔明灯,祝福大家身体健康)(附完整源代码及资源免费下载)
2023春节祝福系列第一弹(下) (放飞祈福孔明灯,祝福大家身体健康) (附完整源代码及资源免费下载) 目录 四.画一朵真实的祥云 (1).画一个渐变的白色径向渐变背景 (2).应用一个SVG feT ...
- 萝卜魂军曹机器人_《萝卜魂》参战作品详介第一弹:《交响诗篇》
NBGI近日公布了一款以"Robot魂"可动模型为素材的动作游戏<战斗机器人之魂>,预定于明年春天发售.参战作品有<交响诗篇><剧场版:交响诗篇彩虹满 ...
- 2023春节祝福系列第一弹(上)(放飞祈福孔明灯,祝福大家身体健康)(附完整源代码及资源免费下载)
2023春节祝福系列第一弹(上) (放飞祈福孔明灯,祝福大家身体健康) (附完整源代码及资源免费下载) 目录 一.前言 二.一片星光闪烁的旋转星空 (1).效果展示: (2).相关源代码 (3).语法 ...
- 2019奥迪创新实验室大赛招募第一弹|趁现在,定一份未来出行计划
2019奥迪创新实验室大赛招募第一弹|趁现在,定一份未来出行计划 人们对于出行的想象,从未停止. 1899年,欧洲的一本杂志曾组织一群美术家.插画家,做了关于100年后世界的想象,并把他们想到的样子画 ...
最新文章
- 深度学习调参体验(一)
- linux进程间通信:popen函数通过管道与shell通信
- HTML5 定位 geolocation
- 查询一个字符串的子串出现的次数在sql中
- 操作系统的安装与启动基本原理
- Git学习总结(18)——让你成为Git和GitHub大神的20个技巧
- 开箱即用的 Prometheus 告警规则集
- Python3的迭代器
- 学习java需要用到哪些软件?
- 电信版的华为EC6108V9C刷机
- rabbitmq消息队列原理
- 【Markdown语法】5分钟快速入门保姆级教程(建议收藏...)
- php正则替空行,正则匹配空行实例
- elementUI动态菜单
- 项目实战:51单片机无线音乐门铃设计资料 五首歌曲自由切换 (含实物 图纸 程序 仿真)
- java降低if的圈复杂度_几种减少圈复杂度的实践
- 微波炉的维修(2)(转自谢工摆渡的博客)
- 【使用 arm-poky-linux-gnueabi-gcc -v 指令可以查看 gcc 版本时报错】
- 刘汝佳算法竞赛入门例题-循环部分
- 基于HTML5的在线地图 - 加载TopoJSON数据
热门文章
- latex 波浪线_湖熟镇月牙刀波浪刀带哪家好厂家
- oracle产品追溯,如何追溯AR到Receipt再到GL
- java学绘图吗_Java绘图
- linux哪个命令可以切换工作目录?如何显示当前所在的目录,Linux cd命令:切换目录...
- tensorflow gpu python3.5_Win10+Anaconda3下tensorflow-gpu环境配置
- 网站使用CloudFlare
- 字节月薪6万招 kubernetes 开发,看到要求我傻眼了……
- 装X神器!NuShell
- 豆瓣读书评分 8.7 以上! 这 40 本 Python 畅销书包邮送
- 喜马拉雅 xm文件转m4a_4K YouTube to MP3 Mac(YouTube转mp3软件)