依照前面分析的u-boot的启动流程,自己写一个简单的Bootloader。这是參考韦东山老师的视频写的。

1、初始化硬件:关看门狗、设置时钟、设置SDRAM、初始化NAND Flash

2、假设Bootloader比較大,要重定位到SDRAM

3、把内核从NAND FLASH读入SDRAM

4、设置“要传给内核的參数”

5、跳转运行内核

start.S代码例如以下:

  1. #define S3C2440_MPLL_200MHZ ((0x5c<<12)|(0x01<<4)|(0x02))
  2. #define MEM_CTL_BASE 0x48000000
  3.  
  4. .text
  5. .global _start
  6. _start:
  7.  
  8. /* 1. 关看门狗 */
  9. ldr r0, =0x53000000
  10. mov r1, #0
  11. str r1, [r0]
  12.  
  13. /* 2. 设置时钟 */
  14. ldr r0, =0x4c000014
  15. mov r1, #0x03; // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1
  16. str r1, [r0]
  17.  
  18. /* 假设HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */
  19. mrc p15, 0, r1, c1, c0, 0 /* 读出控制寄存器 */
  20. orr r1, r1, #0xc0000000 /* 设置为“asynchronous bus mode” */
  21. mcr p15, 0, r1, c1, c0, 0 /* 写入控制寄存器 */
  22.  
  23. /* MPLLCON = S3C2440_MPLL_200MHZ */
  24. ldr r0, =0x4c000004
  25. ldr r1, =S3C2440_MPLL_200MHZ
  26. str r1, [r0]
  27.  
  28. /* 3. 初始化SDRAM */
  29. ldr r0, =MEM_CTL_BASE
  30. adr r1, sdram_config /* sdram_config的当前地址 */
  31. add r3, r0, #(13*4)
  32. 1:
  33. ldr r2, [r1], #4
  34. str r2, [r0], #4
  35. cmp r0, r3
  36. bne 1b
  37.  
  38. /* 4. 重定位 : 把bootloader本身的代码从flash拷贝到它的链接地址去 */
  39. ldr sp, =0x34000000
  40.  
  41. bl nand_init
  42.  
  43. mov r0, #0
  44. ldr r1, =_start
  45. ldr r2, =__bss_start
  46. sub r2, r2, r1
  47.  
  48. bl copy_code_to_sdram
  49. bl clear_bss
  50.  
  51. /* 5. 运行main */
  52. ldr lr, =halt
  53. ldr pc, =main
  54. halt:
  55. b halt
  56.  
  57. sdram_config:
  58. .long 0x22011110 //BWSCON
  59. .long 0x00000700 //BANKCON0
  60. .long 0x00000700 //BANKCON1
  61. .long 0x00000700 //BANKCON2
  62. .long 0x00000700 //BANKCON3
  63. .long 0x00000700 //BANKCON4
  64. .long 0x00000700 //BANKCON5
  65. .long 0x00018005 //BANKCON6
  66. .long 0x00018005 //BANKCON7
  67. .long 0x008C04F4 // REFRESH
  68. .long 0x000000B1 //BANKSIZE
  69. .long 0x00000030 //MRSRB6
  70. .long 0x00000030 //MRSRB7

init.c

  1. /* NAND FLASH控制器 */
  2. #define NFCONF (*((volatile unsigned long *)0x4E000000))
  3. #define NFCONT (*((volatile unsigned long *)0x4E000004))
  4. #define NFCMMD (*((volatile unsigned char *)0x4E000008))
  5. #define NFADDR (*((volatile unsigned char *)0x4E00000C))
  6. #define NFDATA (*((volatile unsigned char *)0x4E000010))
  7. #define NFSTAT (*((volatile unsigned char *)0x4E000020))
  8.  
  9. /* GPIO */
  10. #define GPHCON (*(volatile unsigned long *)0x56000070)
  11. #define GPHUP (*(volatile unsigned long *)0x56000078)
  12.  
  13. /* UART registers*/
  14. #define ULCON0 (*(volatile unsigned long *)0x50000000)
  15. #define UCON0 (*(volatile unsigned long *)0x50000004)
  16. #define UFCON0 (*(volatile unsigned long *)0x50000008)
  17. #define UMCON0 (*(volatile unsigned long *)0x5000000c)
  18. #define UTRSTAT0 (*(volatile unsigned long *)0x50000010)
  19. #define UTXH0 (*(volatile unsigned char *)0x50000020)
  20. #define URXH0 (*(volatile unsigned char *)0x50000024)
  21. #define UBRDIV0 (*(volatile unsigned long *)0x50000028)
  22.  
  23. #define TXD0READY (1<<2)
  24.  
  25. void nand_read(unsigned int addr, unsigned char *buf, unsigned int len);
  26.  
  27. int isBootFromNorFlash(void)
  28. {
  29. volatile int *p = (volatile int *)0;
  30. int val;
  31.  
  32. val = *p;
  33. *p = 0x12345678;
  34. if (*p == 0x12345678)
  35. {
  36. /* 写成功, 是nand启动 */
  37. *p = val;
  38. return 0;
  39. }
  40. else
  41. {
  42. /* NOR不能像内存一样写 */
  43. return 1;
  44. }
  45. }
  46.  
  47. void copy_code_to_sdram(unsigned char *src, unsigned char *dest, unsigned int len)
  48. {
  49. int i = 0;
  50.  
  51. /* 假设是NOR启动 */
  52. if (isBootFromNorFlash())
  53. {
  54. while (i < len)
  55. {
  56. dest[i] = src[i];
  57. i++;
  58. }
  59. }
  60. else
  61. {
  62. //nand_init();
  63. nand_read((unsigned int)src, dest, len);
  64. }
  65. }
  66.  
  67. void clear_bss(void)
  68. {
  69. extern int __bss_start, __bss_end;
  70. int *p = &__bss_start;
  71.  
  72. for (; p < &__bss_end; p++)
  73. *p = 0;
  74. }
  75.  
  76. void nand_init(void)
  77. {
  78. #define TACLS 0
  79. #define TWRPH0 1
  80. #define TWRPH1 0
  81. /* 设置时序 */
  82. NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
  83. /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */
  84. NFCONT = (1<<4)|(1<<1)|(1<<0);
  85. }
  86.  
  87. void nand_select(void)
  88. {
  89. NFCONT &= ~(1<<1);
  90. }
  91.  
  92. void nand_deselect(void)
  93. {
  94. NFCONT |= (1<<1);
  95. }
  96.  
  97. void nand_cmd(unsigned char cmd)
  98. {
  99. volatile int i;
  100. NFCMMD = cmd;
  101. for (i = 0; i < 10; i++);
  102. }
  103.  
  104. void nand_addr(unsigned int addr)
  105. {
  106. unsigned int col = addr % 2048;
  107. unsigned int page = addr / 2048;
  108. volatile int i;
  109.  
  110. NFADDR = col & 0xff;
  111. for (i = 0; i < 10; i++);
  112. NFADDR = (col >> 8) & 0xff;
  113. for (i = 0; i < 10; i++);
  114.  
  115. NFADDR = page & 0xff;
  116. for (i = 0; i < 10; i++);
  117. NFADDR = (page >> 8) & 0xff;
  118. for (i = 0; i < 10; i++);
  119. NFADDR = (page >> 16) & 0xff;
  120. for (i = 0; i < 10; i++);
  121. }
  122.  
  123. void nand_wait_ready(void)
  124. {
  125. while (!(NFSTAT & 1));
  126. }
  127.  
  128. unsigned char nand_data(void)
  129. {
  130. return NFDATA;
  131. }
  132.  
  133. void nand_read(unsigned int addr, unsigned char *buf, unsigned int len)
  134. {
  135. int col = addr % 2048;
  136. int i = 0;
  137.  
  138. /* 1. 选中 */
  139. nand_select();
  140.  
  141. while (i < len)
  142. {
  143. /* 2. 发出读命令00h */
  144. nand_cmd(0x00);
  145.  
  146. /* 3. 发出地址(分5步发出) */
  147. nand_addr(addr);
  148.  
  149. /* 4. 发出读命令30h */
  150. nand_cmd(0x30);
  151.  
  152. /* 5. 推断状态 */
  153. nand_wait_ready();
  154.  
  155. /* 6. 读数据 */
  156. for (; (col < 2048) && (i < len); col++)
  157. {
  158. buf[i] = nand_data();
  159. i++;
  160. addr++;
  161. }
  162.  
  163. col = 0;
  164. }
  165.  
  166. /* 7. 取消选中 */
  167. nand_deselect();
  168. }
  169.  
  170. #define PCLK 50000000 // init.c中的clock_init函数设置PCLK为50MHz
  171. #define UART_CLK PCLK // UART0的时钟源设为PCLK
  172. #define UART_BAUD_RATE 115200 // 波特率
  173. #define UART_BRD ((UART_CLK / (UART_BAUD_RATE * 16)) - 1)
  174.  
  175. /*
  176. * 初始化UART0
  177. * 115200,8N1,无流控
  178. */
  179. void uart0_init(void)
  180. {
  181. GPHCON |= 0xa0; // GPH2,GPH3用作TXD0,RXD0
  182. GPHUP = 0x0c; // GPH2,GPH3内部上拉
  183.  
  184. ULCON0 = 0x03; // 8N1(8个数据位。无较验。1个停止位)
  185. UCON0 = 0x05; // 查询方式,UART时钟源为PCLK
  186. UFCON0 = 0x00; // 不使用FIFO
  187. UMCON0 = 0x00; // 不使用流控
  188. UBRDIV0 = UART_BRD; // 波特率为115200
  189. }
  190.  
  191. /*
  192. * 发送一个字符
  193. */
  194. void putc(unsigned char c)
  195. {
  196. /* 等待,直到发送缓冲区中的数据已经所有发送出去 */
  197. while (!(UTRSTAT0 & TXD0READY));
  198.  
  199. /* 向UTXH0寄存器中写入数据,UART即自己主动将它发送出去 */
  200. UTXH0 = c;
  201. }
  202.  
  203. void puts(char *str)
  204. {
  205. int i = 0;
  206. while (str[i])
  207. {
  208. putc(str[i]);
  209. i++;
  210. }
  211. }
  212.  
  213. void puthex(unsigned int val)
  214. {
  215. /* 0x1234abcd */
  216. int i;
  217. int j;
  218.  
  219. puts("0x");
  220.  
  221. for (i = 0; i < 8; i++)
  222. {
  223. j = (val >> ((7-i)*4)) & 0xf;
  224. if ((j >= 0) && (j <= 9))
  225. putc('0' + j);
  226. else
  227. putc('A' + j - 0xa);
  228.  
  229. }
  230.  
  231. }

boot.c

  1. #include "setup.h"
  2.  
  3. extern void uart0_init(void);
  4. extern void nand_read(unsigned int addr, unsigned char *buf, unsigned int len);
  5. extern void puts(char *str);
  6. extern void puthex(unsigned int val);
  7.  
  8. static struct tag *params;
  9.  
  10. void setup_start_tag(void)
  11. {
  12. params = (struct tag *)0x30000100;
  13.  
  14. params->hdr.tag = ATAG_CORE;
  15. params->hdr.size = tag_size (tag_core);
  16.  
  17. params->u.core.flags = 0;
  18. params->u.core.pagesize = 0;
  19. params->u.core.rootdev = 0;
  20.  
  21. params = tag_next (params);
  22. }
  23.  
  24. void setup_memory_tags(void)
  25. {
  26. params->hdr.tag = ATAG_MEM;
  27. params->hdr.size = tag_size (tag_mem32);
  28.  
  29. params->u.mem.start = 0x30000000;
  30. params->u.mem.size = 64*1024*1024;
  31.  
  32. params = tag_next (params);
  33. }
  34.  
  35. int strlen(char *str)
  36. {
  37. int i = 0;
  38. while (str[i])
  39. {
  40. i++;
  41. }
  42. return i;
  43. }
  44.  
  45. void strcpy(char *dest, char *src)
  46. {
  47. while ((*dest++ = *src++) != '\0');
  48. }
  49.  
  50. void setup_commandline_tag(char *cmdline)
  51. {
  52. int len = strlen(cmdline) + 1;
  53.  
  54. params->hdr.tag = ATAG_CMDLINE;
  55. params->hdr.size = (sizeof (struct tag_header) + len + 3) >> 2;
  56.  
  57. strcpy (params->u.cmdline.cmdline, cmdline);
  58.  
  59. params = tag_next (params);
  60. }
  61.  
  62. void setup_end_tag(void)
  63. {
  64. params->hdr.tag = ATAG_NONE;
  65. params->hdr.size = 0;
  66. }
  67.  
  68. int main(void)
  69. {
  70. void (*theKernel)(int zero, int arch, unsigned int params);
  71. volatile unsigned int *p = (volatile unsigned int *)0x30008000;
  72.  
  73. /* 0. 帮内核设置串口: 内核启动的開始部分会从串口打印一些信息,可是内核一開始没有初始化串口 */
  74. uart0_init();
  75.  
  76. /* 1. 从NAND FLASH里把内核读入内存 */
  77. puts("Copy kernel from nand\n\r");
  78. nand_read(0x60000+64, (unsigned char *)0x30008000, 0x200000);
  79. puthex(0x1234ABCD);
  80. puts("\n\r");
  81. puthex(*p);
  82. puts("\n\r");
  83.  
  84. /* 2. 设置參数 */
  85. puts("Set boot params\n\r");
  86. setup_start_tag();
  87. setup_memory_tags();
  88. setup_commandline_tag("noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0");
  89. setup_end_tag();
  90.  
  91. /* 3. 跳转运行 */
  92. puts("Boot kernel\n\r");
  93. theKernel = (void (*)(int, int, unsigned int))0x30008000;
  94. theKernel(0, 362, 0x30000100);
  95. /*
  96. * mov r0, #0
  97. * ldr r1, =362
  98. * ldr r2, =0x30000100
  99. * mov pc, #0x30008000
  100. */
  101.  
  102. puts("Error!\n\r");
  103. /* 假设一切正常, 不会运行到这里 */
  104.  
  105. return -1;
  106. }

boot.lds

  1. SECTIONS {
  2. . = 0x33f80000;
  3. .text : { *(.text) }
  4.  
  5. . = ALIGN(4);
  6. .rodata : {*(.rodata*)}
  7.  
  8. . = ALIGN(4);
  9. .data : { *(.data) }
  10.  
  11. . = ALIGN(4);
  12. __bss_start = .;
  13. .bss : { *(.bss) *(COMMON) }
  14. __bss_end = .;
  15. }

setup.h

  1. /*
  2. * linux/include/asm/setup.h
  3. *
  4. * Copyright (C) 1997-1999 Russell King
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. *
  10. * Structure passed to kernel to tell it about the
  11. * hardware it's running on. See linux/Documentation/arm/Setup
  12. * for more info.
  13. *
  14. * NOTE:
  15. * This file contains two ways to pass information from the boot
  16. * loader to the kernel. The old struct param_struct is deprecated,
  17. * but it will be kept in the kernel for 5 years from now
  18. * (2001). This will allow boot loaders to convert to the new struct
  19. * tag way.
  20. */
  21. #ifndef __ASMARM_SETUP_H
  22. #define __ASMARM_SETUP_H
  23.  
  24. #define u8 unsigned char
  25. #define u16 unsigned short
  26. #define u32 unsigned long
  27.  
  28. /*
  29. * Usage:
  30. * - do not go blindly adding fields, add them at the end
  31. * - when adding fields, don't rely on the address until
  32. * a patch from me has been released
  33. * - unused fields should be zero (for future expansion)
  34. * - this structure is relatively short-lived - only
  35. * guaranteed to contain useful data in setup_arch()
  36. */
  37. #define COMMAND_LINE_SIZE 1024
  38.  
  39. /* This is the old deprecated way to pass parameters to the kernel */
  40. struct param_struct {
  41. union {
  42. struct {
  43. unsigned long page_size; /* 0 */
  44. unsigned long nr_pages; /* 4 */
  45. unsigned long ramdisk_size; /* 8 */
  46. unsigned long flags; /* 12 */
  47. #define FLAG_READONLY 1
  48. #define FLAG_RDLOAD 4
  49. #define FLAG_RDPROMPT 8
  50. unsigned long rootdev; /* 16 */
  51. unsigned long video_num_cols; /* 20 */
  52. unsigned long video_num_rows; /* 24 */
  53. unsigned long video_x; /* 28 */
  54. unsigned long video_y; /* 32 */
  55. unsigned long memc_control_reg; /* 36 */
  56. unsigned char sounddefault; /* 40 */
  57. unsigned char adfsdrives; /* 41 */
  58. unsigned char bytes_per_char_h; /* 42 */
  59. unsigned char bytes_per_char_v; /* 43 */
  60. unsigned long pages_in_bank[4]; /* 44 */
  61. unsigned long pages_in_vram; /* 60 */
  62. unsigned long initrd_start; /* 64 */
  63. unsigned long initrd_size; /* 68 */
  64. unsigned long rd_start; /* 72 */
  65. unsigned long system_rev; /* 76 */
  66. unsigned long system_serial_low; /* 80 */
  67. unsigned long system_serial_high; /* 84 */
  68. unsigned long mem_fclk_21285; /* 88 */
  69. } s;
  70. char unused[256];
  71. } u1;
  72. union {
  73. char paths[8][128];
  74. struct {
  75. unsigned long magic;
  76. char n[1024 - sizeof(unsigned long)];
  77. } s;
  78. } u2;
  79. char commandline[COMMAND_LINE_SIZE];
  80. };
  81.  
  82. /*
  83. * The new way of passing information: a list of tagged entries
  84. */
  85.  
  86. /* The list ends with an ATAG_NONE node. */
  87. #define ATAG_NONE 0x00000000
  88.  
  89. struct tag_header {
  90. u32 size;
  91. u32 tag;
  92. };
  93.  
  94. /* The list must start with an ATAG_CORE node */
  95. #define ATAG_CORE 0x54410001
  96.  
  97. struct tag_core {
  98. u32 flags; /* bit 0 = read-only */
  99. u32 pagesize;
  100. u32 rootdev;
  101. };
  102.  
  103. /* it is allowed to have multiple ATAG_MEM nodes */
  104. #define ATAG_MEM 0x54410002
  105.  
  106. struct tag_mem32 {
  107. u32 size;
  108. u32 start; /* physical start address */
  109. };
  110.  
  111. /* VGA text type displays */
  112. #define ATAG_VIDEOTEXT 0x54410003
  113.  
  114. struct tag_videotext {
  115. u8 x;
  116. u8 y;
  117. u16 video_page;
  118. u8 video_mode;
  119. u8 video_cols;
  120. u16 video_ega_bx;
  121. u8 video_lines;
  122. u8 video_isvga;
  123. u16 video_points;
  124. };
  125.  
  126. /* describes how the ramdisk will be used in kernel */
  127. #define ATAG_RAMDISK 0x54410004
  128.  
  129. struct tag_ramdisk {
  130. u32 flags; /* bit 0 = load, bit 1 = prompt */
  131. u32 size; /* decompressed ramdisk size in _kilo_ bytes */
  132. u32 start; /* starting block of floppy-based RAM disk image */
  133. };
  134.  
  135. /* describes where the compressed ramdisk image lives (virtual address) */
  136. /*
  137. * this one accidentally used virtual addresses - as such,
  138. * its depreciated.
  139. */
  140. #define ATAG_INITRD 0x54410005
  141.  
  142. /* describes where the compressed ramdisk image lives (physical address) */
  143. #define ATAG_INITRD2 0x54420005
  144.  
  145. struct tag_initrd {
  146. u32 start; /* physical start address */
  147. u32 size; /* size of compressed ramdisk image in bytes */
  148. };
  149.  
  150. /* board serial number. "64 bits should be enough for everybody" */
  151. #define ATAG_SERIAL 0x54410006
  152.  
  153. struct tag_serialnr {
  154. u32 low;
  155. u32 high;
  156. };
  157.  
  158. /* board revision */
  159. #define ATAG_REVISION 0x54410007
  160.  
  161. struct tag_revision {
  162. u32 rev;
  163. };
  164.  
  165. /* initial values for vesafb-type framebuffers. see struct screen_info
  166. * in include/linux/tty.h
  167. */
  168. #define ATAG_VIDEOLFB 0x54410008
  169.  
  170. struct tag_videolfb {
  171. u16 lfb_width;
  172. u16 lfb_height;
  173. u16 lfb_depth;
  174. u16 lfb_linelength;
  175. u32 lfb_base;
  176. u32 lfb_size;
  177. u8 red_size;
  178. u8 red_pos;
  179. u8 green_size;
  180. u8 green_pos;
  181. u8 blue_size;
  182. u8 blue_pos;
  183. u8 rsvd_size;
  184. u8 rsvd_pos;
  185. };
  186.  
  187. /* command line: \0 terminated string */
  188. #define ATAG_CMDLINE 0x54410009
  189.  
  190. struct tag_cmdline {
  191. char cmdline[1]; /* this is the minimum size */
  192. };
  193.  
  194. /* acorn RiscPC specific information */
  195. #define ATAG_ACORN 0x41000101
  196.  
  197. struct tag_acorn {
  198. u32 memc_control_reg;
  199. u32 vram_pages;
  200. u8 sounddefault;
  201. u8 adfsdrives;
  202. };
  203.  
  204. /* footbridge memory clock, see arch/arm/mach-footbridge/arch.c */
  205. #define ATAG_MEMCLK 0x41000402
  206.  
  207. struct tag_memclk {
  208. u32 fmemclk;
  209. };
  210.  
  211. struct tag {
  212. struct tag_header hdr;
  213. union {
  214. struct tag_core core;
  215. struct tag_mem32 mem;
  216. struct tag_videotext videotext;
  217. struct tag_ramdisk ramdisk;
  218. struct tag_initrd initrd;
  219. struct tag_serialnr serialnr;
  220. struct tag_revision revision;
  221. struct tag_videolfb videolfb;
  222. struct tag_cmdline cmdline;
  223.  
  224. /*
  225. * Acorn specific
  226. */
  227. struct tag_acorn acorn;
  228.  
  229. /*
  230. * DC21285 specific
  231. */
  232. struct tag_memclk memclk;
  233. } u;
  234. };
  235.  
  236. struct tagtable {
  237. u32 tag;
  238. int (*parse)(const struct tag *);
  239. };
  240.  
  241. #define tag_member_present(tag,member) \
  242. ((unsigned long)(&((struct tag *)0L)->member + 1) \
  243. <= (tag)->hdr.size * 4)
  244.  
  245. #define tag_next(t) ((struct tag *)((u32 *)(t) + (t)->hdr.size))
  246. #define tag_size(type) ((sizeof(struct tag_header) + sizeof(struct type)) >> 2)
  247.  
  248. #define for_each_tag(t,base) \
  249. for (t = base; t->hdr.size; t = tag_next(t))
  250.  
  251. /*
  252. * Memory map description
  253. */
  254. #define NR_BANKS 8
  255.  
  256. struct meminfo {
  257. int nr_banks;
  258. unsigned long end;
  259. struct {
  260. unsigned long start;
  261. unsigned long size;
  262. int node;
  263. } bank[NR_BANKS];
  264. };
  265.  
  266. extern struct meminfo meminfo;
  267.  
  268. #endif

Makefile

  1. CC = arm-linux-gcc
  2. LD = arm-linux-ld
  3. AR = arm-linux-ar
  4. OBJCOPY = arm-linux-objcopy
  5. OBJDUMP = arm-linux-objdump
  6.  
  7. CFLAGS := -Wall -O2
  8. CPPFLAGS := -nostdinc -nostdlib -fno-builtin
  9.  
  10. objs := start.o init.o boot.o
  11.  
  12. boot.bin: $(objs)
  13. ${LD} -Tboot.lds -o boot.elf $^
  14. ${OBJCOPY} -O binary -S boot.elf $@
  15. ${OBJDUMP} -D -m arm boot.elf > boot.dis
  16.  
  17. %.o:%.c
  18. ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
  19.  
  20. %.o:%.S
  21. ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
  22.  
  23. clean:
  24. rm -f *.o *.bin *.elf *.dis

u-boot学习(六):自己写bootloader的更多相关文章

  1. Linux学习 : 自己写bootloader

    一.bootloader 目标:启动内核 基本功能: ①初始化硬件:关看门狗.设置时钟.设置SDRAM.初始化NAND FLASH ②image比较大需要重定位到SDRAM ②将内核从NAND FLA ...

  2. spring boot 学习(六)spring boot 各版本中使用 log4j2 记录日志

    spring boot 各版本中使用 log4j2 记录日志 前言 Spring Boot中默认日志工具是 logback,只不过我不太喜欢 logback.为了更好支持 spring boot 框架 ...

  3. Spring boot 学习六 spring 继承 mybatis (基于注解)

    MyBatis提供了多个注解如:@InsertProvider,@UpdateProvider,@DeleteProvider和@SelectProvider,这些都是建立动态语言和让MyBatis执 ...

  4. Spring Boot 学习笔记(六) 整合 RESTful 参数传递

    Spring Boot 学习笔记 源码地址 Spring Boot 学习笔记(一) hello world Spring Boot 学习笔记(二) 整合 log4j2 Spring Boot 学习笔记 ...

  5. Spring Boot学习路线

    Spring Boot 学习路线,本文计划根据作者近几年的工作.学习经验,来分析和制定一个学习使用 Spring Boot技术的步骤路线图. SpringBoot是伴随着Spring4.0诞生的: S ...

  6. spring boot / cloud (六) 开启CORS跨域访问

    spring boot / cloud (六) 开启CORS跨域访问 前言 什么是CORS? Cross-origin resource sharing(跨域资源共享),是一个W3C标准,它允许你向一 ...

  7. Spring Boot入门(六):使用MyBatis访问MySql数据库(注解方式)

    本系列博客记录自己学习Spring Boot的历程,如帮助到你,不胜荣幸,如有错误,欢迎指正! 本篇博客我们讲解下在Spring Boot中使用MyBatis访问MySql数据库的简单用法. 1.前期 ...

  8. Spring Boot学习大全(入门)

    Spring Boot学习(入门) 1.了解Spring boot Spring boot的官网(https://spring.io),我们需要的一些jar包,配置文件都可以在下载.添置书签后,我自己 ...

  9. Spring Boot学习记录(二)--thymeleaf模板 - CSDN博客

    ==他的博客应该不错,没有细看 Spring Boot学习记录(二)--thymeleaf模板 - CSDN博客 http://blog.csdn.net/u012706811/article/det ...

  10. Spring boot学习1 构建微服务:Spring boot 入门篇

    Spring boot学习1 构建微服务:Spring boot 入门篇 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框 ...

随机推荐

  1. D - Constructing Roads

    D - Constructing Roads 思路:并查集板子 #include<cstdio> #include<cstring> #include<iostream& ...

  2. SQL-Oracle存储过程-循环A表,向B表插入数据

    --存储过程,查询A表,向B表插入数据 create or replace procedure prc_sg_sjtj_config(p_flag out varchar2) IS BEGIN FOR ...

  3. 3D数学读书笔记——矩阵进阶

    本系列文章由birdlove1987编写,转载请注明出处. 文章链接:http://blog.csdn.net/zhurui_idea/article/details/25242725 最终要学习矩阵 ...

  4. 通过meta标签改变浏览器内核做兼容

    <meta name="renderer" content="webkit|ie-stand|ie-comp" /> <meta http-e ...

  5. HTML5 格式化方式以及应用

    <b>加粗字体 <big>定义大号字体 <em>定义着重文字 <i>定义斜体字 <small>定义小号字体 <strong>定义 ...

  6. Inside ARC — to see the code inserted by the compiler

    前言 这是我在我们技术团队所做的一次分享,稍作改动放到博客上来. 我们技术团队会不定期(一般一个月1~2次)做技术分享,对我们团队有兴趣的能够私信我. 下面是正文. 这里的主题是"Insid ...

  7. PHP生成二维码的2种方式

    二维码的用处俺也就不说了,看一下用PHP生成的二维码吧. 利用谷歌提供的API 生成二维码,如今非常多国外站点都提供了这类API 看下代码吧<=======================> ...

  8. 高斯混合模型Gaussian Mixture Model (GMM)——通过增加 Model 的个数,我们可以任意地逼近任何连续的概率密分布

    从几何上讲,单高斯分布模型在二维空间应该近似于椭圆,在三维空间上近似于椭球.遗憾的是在很多分类问题中,属于同一类别的样本点并不满足“椭圆”分布的特性.这就引入了高斯混合模型.——可以认为是基本假设! ...

  9. 杂项:CMM

    ylbtech-杂项:CMM CMM是指“能力成熟度模型”,其英文全称为Capability Maturity Model for Software,英文缩写为SW-CMM,简称CMM.它是对于软件组 ...

  10. BZOJ 1369 树形DP

    思路: f[i][j] 表示节点i 染成j时 子树的最小权值 (我会猜这个j很小 你打我吖~) 随便DP一发就好了 (证明我也不会) //By SiriusRen #include <cstdi ...