ORPSoC boot过程分析

转自http://blog.csdn.net/rill_zhen/article/details/8855743

引言

之前做了很多工作,能起orpmon,能起linux,能run helloworld。但是这些都可以说是空中楼阁,如果不把CPU的启动过程搞明白,总感觉心里没底似的。所以本小节就看一下ORPSoC在最初上电之后做的一些工作,与大部分介绍启动代码的流程的角度有所不同。

Note:并不讨论上电timing等内容,直接从fetch开始。

 

1,从哪里取第一条指令

从or1200_defines.v里面可以看到PC的初值,这个是由硬件决定的。这个文件的目录和内容如下图:

分析:

第一条取值的地址:0xf0000100

这个地址有两个含义:

1>第一条指令存放的wishbone slave设备的地址是0xf

2>第一条指令存放的wishbone slave设备的内部地址是0x100

此外,这个地址对应的模块,必须在掉电时数据不能丢失。比如flash,rom等。

 

 

2,第一条指令 保存在哪呢

既然已经知道wishbone的slave地址,那么只要找到这个地址对应的模块即可:

在orpsoc-params.v里面:

分析:

1>这个模块应该挂在arbiter_ibus(指令总线)上,找找看,可以看到指令总线上一共只有两个slave:slave0是rom,slave1是ddr1(sdram):

sdram掉电丢失,那第一条指令一定放在rom0里面:

指令总线上的sdram:

 

指令总线上的rom0:

 

2>为了进一步确定,我们查看rom0的wishbone地址,可以看到rom0,这个wishbone slave模块的地址是0xf,如下图:

 

 

3,第一条指令是什么呢

既然已经知道第一条指令的存放模块和模块内部的地址,找到rom0的rtl模块,看看吧:

分析:

里面有一个包含文件bootrom.v:就是指令:

 

bootrom.v内容:

 

4,启动代码的反汇编

上面我们找到了启动代码的存放地方,但是都是十六进制的,共40条指令,一般人看不懂,所以我就手动反汇编了一下:

之前没有手动反汇编过,这次体验了一下,40条指令,竟然用了2个多小时。

详细反汇编过程和结果,以及分析结果,我已上传:

http://download.csdn.net/detail/rill_zhen/5349541

步骤:

第一步:先将十六进制代码转成二进制。

第二步:将二进制与Architecture Manual中的指令集对照,找到对应的指令类型。

第三步:逐个分析每个指令的含义,得到其汇编指令。

如下:

 

最终结果如下:

 

[html]  view plain copy print ?
  1. /*  
  2. * file:rom.S  
  3. * rill create 2013-04-26  
  4. * rillzhen@gmail.com  
  5. *  
  6. */  
  7.   
  8. l.movhi r0,0x0  //boot init,rill add 130509  
  9. l.movhi r1, 0x0    
  10. l.movhi r4, 0xb000  
  11.   
  12.   
  13. l.ori r2, r0, 0x51  //spi init,rill add 130509  
  14. l.sb 0x0(r4),r2    
  15. l.sb 0x4(r4),r0    
  16. l.ori r6, r0, 0x1    
  17. l.sb 0x4(r4),r6    
  18. l.jal 0x18    
  19. l.ori r3, r0, 0x3    
  20. l.jal 0x16    
  21. l.ori r3, r0, 0xc    
  22. l.jal 0x14    
  23. l.ori r3, r0, 0x0    
  24. l.jal 0x12    
  25. l.ori r3, r0, 0x0    
  26. l.movhi r6, 0x0    
  27. l.movhi r7, 0xffff  
  28.   
  29.   
  30. l.jal 0xe  //copy,rill add 130509  
  31. l.add r8,r6,r0    
  32. l.sb 0x0(r8),r3    
  33. l.addi r6,r6,0x1    
  34. l.sfeqi r6,0x4    
  35. l.bf 0x7    
  36. l.sfeq r6,r7    
  37. l.bnf 0x3fffff9    
  38. l.nop    
  39.   
  40.   
  41. l.ori r1, r1, 0x100 //reset ,rill add 130509   
  42. l.jr r1    
  43. l.sb 0x4(r4),r0   
  44.    
  45. l.j 0x3fffff4  //stor word,rill add 130509  
  46. l.lwz r7,0x0(r1)    
  47.   
  48.   
  49. l.sb 0x2(r4),r3  //spi_xfer,rill add 130509  
  50. l.ori r3, r0, 0x1  
  51.     
  52. l.andi r3,r3,0x1  //spi_xfer_poll,rill add 130509  
  53. l.sfeqi r3,0x1    
  54. l.bf 0x3fffffe    
  55. l.lbz r3,0x1(r4)    
  56. l.jr r9    
  57. l.lbz r3,r4,0x2  


 

 

 

5,疑问

经过上面的折腾,之前的空中楼阁总算离地面近了不少。

上面的过程看似很好,但是有一点疑问:

既然第一条指令的地址是0xf0000100,0xf这个地址对应rom0,这没错,

但是rom0的内容在0x100这个地方没有东西啊,它只有40条指令啊,也就是说rom.v里面的那个“case (wb_adr_i)”语句是走default的,也就是说第一条指令是取不到!

我查了一下flashrom,例化的orpsoc_flashROM模块,里面有devboard_flashROM.mem文件,但是ORPSoC这个project并没有用它,如下图:

另外:case (wb_adr_i)后面的地址应该是0xf开头的啊。怎么是从0开始的呢,即使是从0开始,也应该是0,4,8,c。。。。间隔为4啊。

还有,两个boot地址:OR1200_BOOT_PCREG_DEFAULT 和 OR1200_BOOT_ADR既然可以根据一个相互计算出另外一个(OR1200_BOOT_PCREG_DEFAULT should be ((OR1200_BOOT_ADR-4)>>2))。为什么还要两个地址呢。

 

怎么回事?我错在哪里了呢?

 

 6,疑问的解决

1>rom的wishbone地址的问题:

经过查看genpc模块,if模块,immu模块,ic模块,biu模块,都没有发现问题,最后不经意间发现如下问题,疑惑荡然无存。

经过查找发现case中的wb_adr_i,只用了[7:2] 6个bit,如下图,需要注意的是本地的参数经过了重定义:

本地参数:

重定义参数:

rom0的指令总线上对应的地址:

从上面可以才看出:0xf0000100(32‘b1111_0000_0000_0000_0000_0001_0000_0000)这个boot地址只用了[7:2] 共6位。

地址的间隔也是0,1,2,3,4,。。。。间隔为1。当然也决定的启动代码的大小不能超过2的6次方(64条),这个rom只用了40条,是符合要求的。

 

2>两个启动地址的转换问题

看完下面的代码,clear了:

 

 

7,总结

通过上面的努力,我们对ORPSoC的最初的启动过程有了一个直观的清晰的了解了。


附录:

1, for more information:

http://opencores.org/or1k/ORPSoC_RTL_simulation_debugging#bootrom

2,其实可以直接查看bootrom的源码:发现和我手动反汇编的结果一致!

soc-design/orpsocv2/sw/bootrom

通过这个目录下的makefile文件可以看出,将bootrom.S转换成bootrom.v的过程。其中有代码的拷贝,但是被拷贝的代码从何而来呢,请参考:

http://blog.csdn.net/rill_zhen/article/details/9045837

3,文件详细内容如下:

board.h:


[html]  view plain copy print ?
  1. #ifndef _BOARD_H_  
  2. #define _BOARD_H_  
  3.   
  4. #define IN_CLK            50000000 // Hz  
  5. //#define IN_CLK          32000000 // Hz  
  6. //#define IN_CLK          30000000 // HZ  
  7. //#define IN_CLK          24000000 // HZ  
  8. //#define IN_CLK          20000000 // HZ  
  9. //#define IN_CLK          18000000 // HZ  
  10. //#define IN_CLK          16000000 // HZ  
  11.   
  12. //  
  13. // ROM bootloader  
  14. //  
  15. // Uncomment the appropriate bootloader define. This will effect the bootrom.S  
  16. // file, which is compiled and converted into Verilog for inclusion at   
  17. // synthesis time. See bootloader/bootloader.S for details on each option.  
  18. #ifndef PRELOAD_RAM  
  19. #define BOOTROM_SPI_FLASH  
  20. //#define BOOTROM_GOTO_RESET  
  21. //#define BOOTROM_LOOP_AT_ZERO  
  22. //#define BOOTROM_LOOP_IN_ROM  
  23. #define BOOTROM_ADDR_BYTE2 0x0c  
  24. #define BOOTROM_ADDR_BYTE1 0x00  
  25. #define BOOTROM_ADDR_BYTE0 0x00  
  26. #else  
  27. #define BOOTROM_GOTO_RESET  
  28. #endif  
  29.   
  30. //  
  31. // Defines for each core (memory map base, OR1200 interrupt line number, etc.)  
  32. //  
  33. #define SDRAM_BASE                 0x0  
  34. //#define MT48LC32M16A2 // 64MB SDRAM part  
  35. #define MT48LC16M16A2 // 32MB SDRAM part  
  36. //#define MT48LC4M16A2 // 8MB SDRAM part  
  37.   
  38. #define FLASHROM_BASE       0xcf000000  
  39. #define FLASHROM_SIZE            0x100  
  40.   
  41. #define GPIO_0_BASE         0x91000000  
  42.   
  43. #define UART0_BASE          0x90000000  
  44. #define UART0_IRQ                    2  
  45. #define UART0_BAUD_RATE     115200  
  46.   
  47. #define UART1_BASE          0x93000000  
  48. #define UART1_IRQ                    3  
  49. #define UART1_BAUD_RATE     115200  
  50.   
  51. #define UART2_BASE          0x94000000  
  52. #define UART2_IRQ                    5  
  53. #define UART2_BAUD_RATE     115200  
  54.   
  55. #define SPI0_BASE           0xb0000000  
  56. #define SPI0_IRQ                     6  
  57.   
  58. #define SPI1_BASE           0xb1000000  
  59. #define SPI1_IRQ                     7  
  60.   
  61. #define SPI2_BASE           0xb2000000  
  62. #define SPI2_IRQ                     8  
  63.   
  64. #define I2C_0_BASE          0xa0000000  
  65. #define I2C_0_IRQ                   10  
  66.   
  67. #define I2C_1_BASE          0xa1000000  
  68. #define I2C_1_IRQ                   11  
  69.   
  70. #define I2C_2_BASE          0xa2000000  
  71. #define I2C_2_IRQ                   12  
  72.   
  73. #define I2C_3_BASE          0xa3000000  
  74. #define I2C_3_IRQ                   13  
  75.   
  76. #define USB0_BASE            0x9c000000  
  77. #define USB0_HOST_IRQ                20  
  78. #define USB0_SLAVE_IRQ               21  
  79.   
  80. #define USB1_BASE            0x9d000000  
  81. #define USB1_HOST_IRQ                22  
  82. #define USB1_SLAVE_IRQ               23  
  83.   
  84. #define ETH0_BASE            0x92000000  
  85. #define ETH0_IRQ                      4  
  86.   
  87. #define ETH_MACADDR0               0x00  
  88. #define ETH_MACADDR1               0x12  
  89. #define ETH_MACADDR2               0x34  
  90. #define ETH_MACADDR3               0x56  
  91. #define ETH_MACADDR4               0x78  
  92. #define ETH_MACADDR5               0x9a  
  93.   
  94.   
  95. //  
  96. // OR1200 tick timer period define  
  97. //  
  98. #define TICKS_PER_SEC   100  
  99.   
  100. //  
  101. // UART driver initialisation  
  102. //   
  103. #define UART_NUM_CORES 3  
  104.   
  105. #define UART_BASE_ADDRESSES_CSV                     \  
  106.     UART0_BASE, UART2_BASE, UART2_BASE  
  107.   
  108. #define UART_BAUD_RATES_CSV                     \  
  109.     UART0_BAUD_RATE, UART1_BAUD_RATE, UART1_BAUD_RATE  
  110.   
  111. //   
  112. // i2c_master_slave core driver configuration  
  113. //  
  114.   
  115. #define I2C_MASTER_SLAVE_NUM_CORES 4  
  116.   
  117. #define I2C_MASTER_SLAVE_BASE_ADDRESSES_CSV     \  
  118.     I2C_0_BASE, I2C_1_BASE, I2C_2_BASE,I2C_3_BASE  
  119.   
  120.   
  121.   
  122. #endif  



bootrom.S:


[html]  view plain copy print ?
  1. //  
  2. ///                                                                  
  3. /// bootrom                                                         
  4. ///                                                                 
  5. /// Assembly programs to be embedded inside system to aid boot      
  6. ///                                                                 
  7. /// Julius Baxter, julius@opencores.org                             
  8. ///                                                                 
  9. //  
  10.                                                                 
  11.  Copyright (C) 2009, 2010 Authors and OPENCORES.ORG             
  12.                                                                 
  13.  This source file may be used and distributed without           
  14.  restriction provided that this copyright statement is not      
  15.  removed from the file and that any derivative work contains    
  16.  the original copyright notice and the associated disclaimer.   
  17.                                                                 
  18.  This source file is free software; you can redistribute it     
  19.  and/or modify it under the terms of the GNU Lesser General     
  20.  Public License as published by the Free Software Foundation;   
  21.  either version 2.1 of the License, or (at your option) any     
  22.  later version.                                                 
  23.                                                                 
  24.  This source is distributed in the hope that it will be         
  25.  useful, but WITHOUT ANY WARRANTY; without even the implied     
  26.  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR        
  27.  PURPOSE.  See the GNU Lesser General Public License for more   
  28.  details.                                                       
  29.                                                                 
  30.  You should have received a copy of the GNU Lesser General      
  31.  Public License along with this source; if not, download it     
  32.  from http://www.opencores.org/lgpl.shtml                       
  33.                                                                 
  34. //  
  35.   
  36. // Defines for which bootrom app to use are in board.h - TODO: use the  
  37. // processed orspoc-defines.v file for this define. It makes more sense  
  38. // as this software ends up as gates.  
  39.       
  40. #include "board.h"  
  41.   
  42. #ifdef BOOTROM_SPI_FLASH  
  43.       
  44.     /* Assembly program to go into the boot ROM */  
  45.     /* For use with simple_spi SPI master core and standard SPI flash  
  46.        interface-compatible parts (ST M25P16 for example.)*/  
  47.     /* Currently just loads a program from SPI flash into RAM */  
  48.     /* Assuming address at RAM_LOAD_BASE gets clobbered, we need  
  49.        a byte writable address somewhere!*/  
  50.   
  51. #define SPI_BASE SPI0_BASE  
  52. /* simple_spi driver */   
  53. #define SPI_SPCR 0x0  
  54. #define SPI_SPSR 0x1  
  55. #define SPI_SPDR 0x2  
  56. #define SPI_SPER 0x3  
  57. #define SPI_SPSS 0x4  
  58.   
  59. #define SPI_SPCR_XFER_GO 0x51  
  60. #define SPI_SPSS_INIT 0x1  
  61. #define SPI_SPSR_RX_CHECK 0x01 /* Check bit 0 is cleared, fifo !empty*/  
  62.       
  63. #define RAM_LOAD_BASE SDRAM_BASE  
  64. #define RESET_ADDR 0x100  
  65.   
  66. boot_init:    
  67.     l.movhi r0, 0  
  68.     l.movhi r1, RAM_LOAD_BASE  
  69.     l.movhi r4, hi(SPI_BASE)  
  70.       
  71. spi_init:  
  72.     l.ori   r2, r0, SPI_SPCR_XFER_GO /* Setup SPCR with enable bit set */  
  73.     l.sb    SPI_SPCR(r4), r2  
  74.     l.sb    SPI_SPSS(r4), r0         /* Clear SPI slave selects */  
  75.     l.ori   r6, r0, SPI_SPSS_INIT  
  76.     l.sb    SPI_SPSS(r4), r6         /* Set appropriate slave select */  
  77.     l.jal   spi_xfer  
  78.     l.ori   r3, r0, 0x3              /* READ command opcode for SPI device*/  
  79.     l.jal   spi_xfer  
  80. #ifdef BOOTROM_ADDR_BYTE2  
  81.     l.ori   r3, r0, BOOTROM_ADDR_BYTE2 /* Use addr if defined. MSB first */  
  82. #else     
  83.     l.or    r3, r0, r0  
  84. #endif    
  85.     l.jal   spi_xfer  
  86. #ifdef BOOTROM_ADDR_BYTE1  
  87.     l.ori   r3, r0, BOOTROM_ADDR_BYTE1  
  88. #else     
  89.     l.or    r3, r0, r0  
  90. #endif    
  91.     l.jal   spi_xfer  
  92. #ifdef BOOTROM_ADDR_BYTE0  
  93.     l.ori   r3, r0, BOOTROM_ADDR_BYTE0  
  94. #else     
  95.     l.or    r3, r0, r0  
  96. #endif    
  97.     l.movhi r6, 0  
  98.     l.movhi r7, 0xffff    
  99.   
  100. copy:     
  101.     l.jal   spi_xfer         /* Read a byte into r3 */  
  102.     l.add   r8, r1, r6       /* Calculate store address */  
  103.     l.sb    0(r8), r3        /* Write byte to memory */  
  104.     l.addi  r6, r6, 1        /* Increment counter */  
  105.     l.sfeqi r6, 0x4          /* Is this the first word ?*/  
  106.     l.bf    store_sizeword   /* put sizeword in the register */  
  107.     l.sfeq  r6, r7           /* Check if we've finished loading the words */  
  108.     l.bnf   copy             /* Continue copying if not last word */  
  109.     l.nop  
  110.   
  111. goto_reset:  
  112.     l.ori   r1, r1, RESET_ADDR  
  113.     l.jr    r1  
  114.     l.sb    SPI_SPSS(r4), r0 /* Clear SPI slave selects */  
  115.       
  116. store_sizeword:  
  117. #ifdef SPI_RETRY_IF_INSANE_SIZEWORD  
  118.     l.lwz   r7, 0(r1)        /* Size word is in first word of SDRAM */  
  119.     l.srli  r10, r7, 16  /* Chop the sizeword we read in half */  
  120.     l.sfgtui r10, 0x0200     /* It's unlikely we'll ever load > 32MB */  
  121.     l.bf    boot_init  
  122.     l.nop  
  123.     l.j     copy  
  124.     l.nop  
  125.   
  126. #else     
  127.     l.j     copy  
  128.     l.lwz   r7, 0(r1)         /* Size word is in first word of SDRAM */  
  129. #endif  
  130.       
  131. spi_xfer:  
  132.     l.sb    SPI_SPDR(r4), r3  /* Dummy write what's in r3 */  
  133.     l.ori   r3, r0, SPI_SPSR_RX_CHECK /* r3 = , ensure loop just once */  
  134. spi_xfer_poll:    
  135.     l.andi  r3, r3, SPI_SPSR_RX_CHECK /* AND read fifo bit empty */  
  136.     l.sfeqi r3, SPI_SPSR_RX_CHECK    /* is bit set? ... */  
  137.     l.bf    spi_xfer_poll     /* ... if so, rxfifo empty, keep polling */  
  138.     l.lbz   r3, SPI_SPSR(r4) /* Read SPSR */  
  139.     l.jr    r9  
  140.     l.lbz   r3, SPI_SPDR(r4) /* Get data byte */  
  141.   
  142.   
  143. #endif  
  144.   
  145. #ifdef BOOTROM_GOTO_RESET  
  146.     /* Jump to reset vector in the SDRAM */  
  147.     l.movhi r0, 0  
  148.     l.movhi r4, SDRAM_BASE  
  149.     l.ori   r4, r4, 0x100  
  150.     l.jr    r4  
  151.     l.nop  
  152.       
  153. #endif    
  154.   
  155. #ifdef BOOTROM_LOOP_AT_ZERO  
  156.   
  157.     /* Don't load app via SPI, instead just put an infinite loop into bottom  
  158.     of memory and jump there.  
  159.     */  
  160.     l.movhi r0, 0  
  161.     l.movhi r4, SDRAM_BASE  
  162.     l.sw    0x0(r4), r0  
  163.     l.movhi r5, hi(0x15000001) /* A l.nop 1 so sim exits if this enabled */  
  164.     l.ori   r5, r5, lo(0x15000001)  
  165.     l.sw    0x4(r4), r5  
  166.     l.sw    0x8(r4), r5  
  167.     l.sw    0xc(r4), r5  
  168.     l.jr    r4  
  169.     l.nop  
  170.   
  171.       
  172.   
  173. #endif  
  174.   
  175. #ifdef BOOTROM_LOOP_IN_ROM  
  176.   
  177.     /* Don't load app via SPI, instead just put an infinite loop into bottom  
  178.     of memory and jump there.  
  179.     */  
  180.     l.movhi r0, 0  
  181.     l.nop   0x1  
  182.     l.j     0  
  183.     l.nop  
  184.     l.nop   
  185. #endif  



bootrom.v:可以比较这个目录下的文件和soc-design\orpsocv2\boards\altera\ordb2a-ep4ce22\rtl\verilog\include目录下的文件创建时间,相同。

[html]  view plain copy print ?
  1. 0 : wb_dat_o <=  32'h18000000;  
  2. 1 : wb_dat_o <=  32'h18200000;  
  3. 2 : wb_dat_o <=  32'h1880b000;  
  4. 3 : wb_dat_o <=  32'ha8400051;  
  5. 4 : wb_dat_o <=  32'hd8041000;  
  6. 5 : wb_dat_o <=  32'hd8040004;  
  7. 6 : wb_dat_o <=  32'ha8c00001;  
  8. 7 : wb_dat_o <=  32'hd8043004;  
  9. 8 : wb_dat_o <=  32'h04000018;  
  10. 9 : wb_dat_o <=  32'ha8600003;  
  11. 10 : wb_dat_o <=  32'h04000016;  
  12. 11 : wb_dat_o <=  32'ha860000c;  
  13. 12 : wb_dat_o <=  32'h04000014;  
  14. 13 : wb_dat_o <=  32'ha8600000;  
  15. 14 : wb_dat_o <=  32'h04000012;  
  16. 15 : wb_dat_o <=  32'ha8600000;  
  17. 16 : wb_dat_o <=  32'h18c00000;  
  18. 17 : wb_dat_o <=  32'h18e0ffff;  
  19. 18 : wb_dat_o <=  32'h0400000e;  
  20. 19 : wb_dat_o <=  32'he1013000;  
  21. 20 : wb_dat_o <=  32'hd8081800;  
  22. 21 : wb_dat_o <=  32'h9cc60001;  
  23. 22 : wb_dat_o <=  32'hbc060004;  
  24. 23 : wb_dat_o <=  32'h10000007;  
  25. 24 : wb_dat_o <=  32'he4063800;  
  26. 25 : wb_dat_o <=  32'h0ffffff9;  
  27. 26 : wb_dat_o <=  32'h15000000;  
  28. 27 : wb_dat_o <=  32'ha8210100;  
  29. 28 : wb_dat_o <=  32'h44000800;  
  30. 29 : wb_dat_o <=  32'hd8040004;  
  31. 30 : wb_dat_o <=  32'h03fffff4;  
  32. 31 : wb_dat_o <=  32'h84e10000;  
  33. 32 : wb_dat_o <=  32'hd8041802;  
  34. 33 : wb_dat_o <=  32'ha8600001;  
  35. 34 : wb_dat_o <=  32'ha4630001;  
  36. 35 : wb_dat_o <=  32'hbc030001;  
  37. 36 : wb_dat_o <=  32'h13fffffe;  
  38. 37 : wb_dat_o <=  32'h8c640001;  
  39. 38 : wb_dat_o <=  32'h44004800;  
  40. 39 : wb_dat_o <=  32'h8c640002;  

makefile:从中可以看到bootrom.S的编译,转换过程,及用到的工具。

[html]  view plain copy print ?
  1. # Makefile for bootROM Verilog  
  2. SW_ROOT=..  
  3. include $(SW_ROOT)/Makefile.inc  
  4.   
  5. # Whenever PRELOAD_RAM is defined on command line, we probably want the bootrom  
  6. # to be jumping to reset instead of doing a full boot preload.  
  7. ifeq ($(PRELOAD_RAM),1)  
  8. OR32_CFLAGS += -DPRELOAD_RAM  
  9. endif  
  10.   
  11. all: bootrom.v  
  12.   
  13. %.v: %.bin $(SW_ROOT)/utils/bin2vlogarray  
  14.     $(Q)$(SW_ROOT)/utils/bin2vlogarray < $< > $@  
  15.   
  16. %.dis: %.o  
  17.     $(Q)$(OR32_OBJDUMP) -d $< > $@  
  18.   
  19. %.bin: %.o  
  20.     $(Q)$(OR32_OBJCOPY) -O binary $< $@  
  21.   
  22. $(SW_ROOT)/utils/bin2vlogarray:  
  23.     $(Q)$(MAKE) -C $(SW_ROOT)/utils bin2vlogarray  
  24.   
  25. clean:  
  26.     $(Q)rm -f *.o *.bin *.hex *.in *.dis *.v  


后记

合抱之木,生于毫末;九层之台,起于垒土;千里之行,始于足下。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值