S32DS中链接文件及启动代码学习

一、链接文件

<Linker Files>文件夹中有linker_flash.ld文件和linker_ram.ld文件。

Linker File称为链接文件,它是作用在链接过程。程序代码(.s 和 .c)源文件会经过预编译、编译、汇编、链接最后生成目标可执行文件;

linker_flash.ld文件功能:Flash和SRAM内存分配,为Flash构建目标分配代码段和数据段;

linker_ram.ld文件功能:SRAM内存分配,为RAM构建目标分配代码段和数据段。

linker_flash.ld文件分析:

二、启动代码

<Startup_Code>文件夹中有以下几个文件:

1.<startup_cm7.s>内主要分为定义部分和程序执行部分;

定义部分:

1)定义部分常量

 1 #define MAIN_CORE 0
2 #define MCME_CTL_KEY 0x402DC000
3 #define MCME_PRTN1_PUPD 0x402DC304
4 #define MCME_PRTN1_STAT 0x402DC308
5 #define MCME_PRTN1_COFB0_CLKEN 0x402DC330
6 #define MCME_MSCM_REQ (1 << 24)
7 #define MCME_KEY 0x5AF0
8 #define MCME_INV_KEY 0xA50F
9 #define CM7_ITCMCR 0xE000EF90
10 #define CM7_DTCMCR 0xE000EF94
11 ​
12 #define SBAF_BOOT_MARKER (0x5AA55AA5)
13 #define CM7_0_ENABLE_SHIFT (0)
14 #define CM7_1_ENABLE_SHIFT (1)
15 ​
16 #define CM7_0_ENABLE (1)
17 #define CM7_1_ENABLE (0)
18 #define CM7_0_VTOR_ADDR (__ROM_INTERRUPT_START)
19 #define CM7_1_VTOR_ADDR (0)
20 #define XRDC_CONFIG_ADDR (0)
21 #define LF_CONFIG_ADDR (0)
22 ​
23 .syntax unified
24 .arch armv7-m

2)定义".init_table"段内容为可分配

 1 /* Table for copying and zeroing */
2 /* Copy table:
3 - Table entries count
4 - entry one ram start
5 - entry one rom start
6 - entry one rom end
7 ...
8 - entry n ram start
9 - entry n rom start
10 - entry n rom end
11 Zero Table:
12 - Table entries count
13 - entry one ram start
14 - entry one ram end
15 */
16 /** 1.定义部分 **/
17 .section ".init_table", "a" //段内容可分配
18 .long 4
19 .long __RAM_CACHEABLE_START
20 .long __ROM_CACHEABLE_START
21 .long __ROM_CACHEABLE_END
22 .long __RAM_NO_CACHEABLE_START
23 .long __ROM_NO_CACHEABLE_START
24 .long __ROM_NO_CACHEABLE_END
25 .long __RAM_SHAREABLE_START
26 .long __ROM_SHAREABLE_START
27 .long __ROM_SHAREABLE_END
28 .long __RAM_INTERRUPT_START
29 .long __ROM_INTERRUPT_START
30 .long __ROM_INTERRUPT_END

3)定义".zero_table"段内容为可分配

1 .section ".zero_table", "a" //段内容可分配
2 .long 3
3 .long __BSS_SRAM_SH_START
4 .long __BSS_SRAM_SH_END
5 .long __BSS_SRAM_NC_START
6 .long __BSS_SRAM_NC_END
7 .long __BSS_SRAM_START
8 .long __BSS_SRAM_END

4)定义".core_loop"段内容为可分配,可执行

 1 .globl RESET_CATCH_CORE
2 .globl _core_loop
3 .section ".core_loop","ax" //段内容可分配,可执行
4 .thumb
5 ​
6 _core_loop:
7 nop
8 nop
9 nop
10 nop
11 b _core_loop

5)定义".boot_header"段内容为可分配,可执行(详细见startup_cm7.s文件)

 1 .section ".boot_header","ax"    //段内容可分配,可执行
2 .long SBAF_BOOT_MARKER /* IVT marker */
3 .long (CM7_0_ENABLE << CM7_0_ENABLE_SHIFT) | (CM7_1_ENABLE << CM7_1_ENABLE_SHIFT) /* Boot configuration word */
4 .long 0 /* Reserved */
5 .long CM7_0_VTOR_ADDR /* CM7_0 Start address */
6 .long 0 /* Reserved */
7 .long CM7_1_VTOR_ADDR /* CM7_1 Start address */
8 .long 0 /* Reserved */
9 .long XRDC_CONFIG_ADDR /* XRDC configuration pointer */
10 .long LF_CONFIG_ADDR /* Lifecycle configuration pointer */
11 .long 0 /* Reserved */

执行部分:

其中代码执行的顺序是按S32K3xx RTD启动步骤执行的,如下图:

1) Reset_Handler:

 1 .set VTOR_REG, 0xE000ED08
2 .thumb
3 .thumb_func
4 .globl Reset_Handler
5 .globl _start
6 _start: /** 2.程序执行部分 **/
7 Reset_Handler:
8 /*****************************************************/
9 /* Skip normal entry point as nothing is initialized */
10 /*****************************************************/
11 cpsid i //关闭中断
12 mov r0, #0
13 mov r1, #0
14 mov r2, #0
15 mov r3, #0
16 mov r4, #0
17 mov r5, #0
18 mov r6, #0
19 mov r7, #0

2) InitMSCMClock:

a) 通过判断 MC_ME 模块 PRTN1_COFB0_STAT 寄存器第 24bit,检查 MSCM 时钟使能情况。

b) 若时钟已使能,跳转到 SetVTOR 执行

c) 若时钟未使能,继续往下执行

d) 通过置位 MC_ME 模块 PRTN1_COFB0_CLKEN 寄存器第 24bit,打开 MSCM 时钟

e) 通过往 MC_ME 模块 PRTN1_PUPD 寄存器写 1,更新时钟操作

f) 通过往 MC_ME 模块 CTL_KEY 写入 KEY 值,使能硬件操作

 1 InitMSCMClock:  //
2 /* Enable clock in PRTN1 */
3 ldr r0, =MCME_PRTN1_COFB0_CLKEN
4 ldr r1, [r0]
5 ldr r2, =MCME_MSCM_REQ
6 orr r1, r2
7 str r1, [r0]
8 ​
9 /* Set PUPD field */
10 ldr r0, =MCME_PRTN1_PUPD
11 ldr r1, [r0]
12 ldr r2, =1
13 orr r1, r2
14 str r1, [r0]
15 ​
16 /* Trigger update */
17 ldr r0, =MCME_CTL_KEY
18 ldr r1, =MCME_KEY
19 str r1, [r0]
20 ldr r1, =MCME_INV_KEY
21 str r1, [r0]
22 ​
23 ldr r0, =MCME_PRTN1_PUPD

3) WaitForClock:

a) 循环等到时钟初始化完成

WaitForClock:
ldr r1, [r0]
ldr r2, =1
and r1, r2
cmp r1, #1
bge WaitForClock

4) SetVTOR:(向 CM7 内核设置向量表地址偏移,相对 0x00000000)

a) 将.non_cacheable_data 段的__interrupts_ram_start 地址写入了中断偏移地址

p.s. :_interrupts_ram_start地址的内容从__interrupts_rom_start 地址获得,其内容为”.intc_vector”段,”.intc_vector”内容的定义在 Vector_Table.s 中

b) 获取当前内核 ID, 若 为 main core, 跳转到 SetCore0Stack ,否则跳转到SetCore1Stack。

 1 /* relocate vector table to RAM */
2 ldr r0, =VTOR_REG
3 ldr r1, =__RAM_INTERRUPT_START
4 str r1,[r0]
5 ​
6 /*GetCoreID*/
7 ldr r0, =0x40260004
8 ldr r1,[r0]
9 ​
10 ldr r0, =MAIN_CORE
11 cmp r1,r0
12 beq SetCore0Stack

5) SetCore0Stack:

a) 设置 MSP(main stack pointer)为__Stack_start_c0

b) 跳转到 DisableSWT0

1 SetCore0Stack:
2 /* set up stack; r13 SP*/
3 ldr r0, =__Stack_start_c0
4 msr MSP, r0
5 b DisableSWT0

6) SetCore1Stack:

a) S32K344 为单主核(另一核不做分析)

7) DisableSWT0:

a) 失能内核 0 看门狗后,跳转到 RamInit

/* Note from manual: For any operation to be performed on an SWT  */
/* instance, its respective core must be enabled. */
DisableSWT0:
ldr r0, =0x40270010
ldr r1, =0xC520
str r1, [r0]
ldr r1, =0xD928
str r1, [r0]
ldr r0, =0x40270000
ldr r1, =0xFF000040
str r1, [r0]
b RamInit

8). DisableSWT1:

a) S32K344 为单主核(另一核不做分析)

9). RamInit:(没有清零 SRAM,用户需自己认定 SRAM 数据上电后不可靠)

a) 比较__RAM_INIT 和 0,若相等,跳转到 SRAM_LOOP_END(不成立)

b) _INT_SRAM_EDN-__INT_SRAM_START = 1 则跳转到 SRAM_LOOP_END(不成立)

c) 清空 r0,r3 通用寄存器

 1 /******************************************************************/
2 /* Autosar Guidance 13 - The start-up code shall initialize a */
3 /* minimum amount of RAM in order to allow proper execution of */
4 /* the MCU driver services and the caller of these services. */
5 /******************************************************************/
6 RamInit:
7 /* Initialize SRAM ECC */
8 ldr r0, =__RAM_INIT
9 cmp r0, 0
10 /* Skip if __SRAM_INIT is not set */
11 beq SRAM_LOOP_END
12 ldr r1, =__INT_SRAM_START
13 ldr r2, =__INT_SRAM_END
14
15 subs r2, r1
16 subs r2, #1
17 ble SRAM_LOOP_END
18 ​
19 movs r0, 0
20 movs r3, 0

10). SRAM_LOOP:

a) r1 的地址值(__INT_SRAM_START)+8 ,将值写给 r0,r3

b) r2 的地址值(__INT_SRAM_END-1)-8,若大于 0,跳转到SRAM_LOOP

1 SRAM_LOOP:
2 stm r1!, {r0,r3}
3 subs r2, 8
4 bge SRAM_LOOP

11). SRAM_LOOP_END:

无操作

1 SRAM_LOOP_END:

12). DTCM_Init/ ITCM_Init:

a) 比较__DTCM_INIT 和 0,若相等,跳转到 DTCM_LOOP_END(不成立)

b) 往内核寄存器 DTCMCR 写 1,使能 DTCM

c) _INT_DTCM_END-__INT_DTCM_START = 1 则跳转到DTCM_LOOP_END(不成立)

 1 DTCM_Init:
2 /* Initialize DTCM ECC */
3 ldr r0, =__DTCM_INIT
4 cmp r0, 0
5 /* Skip if __DTCM_INIT is not set */
6 beq DTCM_LOOP_END
7 /* Enable TCM */
8 LDR r1, =CM7_DTCMCR
9 LDR r0, [r1]
10 LDR r2, =0x1
11 ORR r0, r2
12 STR r0, [r1]
13 ​
14 ldr r1, =__INT_DTCM_START
15 ldr r2, =__INT_DTCM_END
16
17 subs r2, r1
18 subs r2, #1
19 ble DTCM_LOOP_END
20 ​
21 movs r0, 0
22 movs r3, 0

13). DTCM_LOOP/ ITCM_LOOP:

参照 SRAM_LOOP

1 DTCM_LOOP:
2 stm r1!, {r0,r3}
3 subs r2, #8
4 bge DTCM_LOOP

14). DTCM_LOOP_END/ ITCM_LOOP_END:

无操作

1 DTCM_LOOP_END:

15). DebuggerHeldCoreLoop:

1 DebuggerHeldCoreLoop:
2 ldr r0, =RESET_CATCH_CORE
3 ldr r0, [r0]
4 ldr r1, =0x5A5A5A5A
5 cmp r0, r1
6 beq DebuggerHeldCoreLoop

16). _DATA_INIT:(数据初始化)

a) 判断当前核是否为主核,是则跳转到 _INIT_DATA_BSS ,否则跳转到__SYSTEM_INIT

 1 /************************/
2 /* Erase ".bss Section" */
3 /************************/
4 _DATA_INIT:
5 /* If this is the primary core, initialize data and bss */
6 ldr r0, =0x40260004
7 ldr r1,[r0]
8 ​
9 ldr r0, =MAIN_CORE
10 cmp r1,r0
11 beq _INIT_DATA_BSS
12 b _MAIN

17). _INIT_DATA_BSS:

跳转到 startup.c 的 init_data_bss()函数

a) 把".init_table"段(非 0 的全局静态等变量的 sram 起始地址,flash 起始/终止地址)地址对应的信息,从只能读不能写的片内 flash 拷贝到 SRAM.

b) 清零".zero_table"段(BSS 段)

1 _INIT_DATA_BSS:
2 bl init_data_bss

18). __SYSTEM_INIT:

跳转到 system.c 的 SystemInit()函数

a) 获取内核 ID,使能对应 CM7 内核的所有(240 个)中断请求

b) 使能 FPU

c) 清空 cache,关闭 cache

d) 将内存的地址起始位置,大小,属性(读/写,共享等)写入 CM7 内核 MPU 对应寄存器

e) 使能 MPU,打开 cache

1 __SYSTEM_INIT:
2 bl SystemInit

19). _MAIN:

跳转到 main.c 的 main()函数(详细见startup_cm7.s文件)

1 _MAIN:
2 cpsie i
3 bl startup_go_to_user_mode
4 bl main

2.< startup.c>作用:

1.把".init_table"段(非 0 的全局静态等变量的 sram 起始地址,flash 起始/终止地址)地址对应的信息,从只能读不能写的片内 flash 拷贝到 SRAM.

2.清零".zero_table"段(BSS 段)

 1 /*FUNCTION**********************************************************************
2 *
3 * Function Name : init_data_bss
4 * Description : Make necessary initializations for RAM.
5 * - Copy the vector table from ROM to RAM.
6 * - Copy initialized data from ROM to RAM.
7 * - Copy code that should reside in RAM from ROM
8 * - Clear the zero-initialized data section.
9 *
10 * Tool Chains:
11 * __GNUC__ : GNU Compiler Collection
12 * __ghs__ : Green Hills ARM Compiler
13 * __ICCARM__ : IAR ARM Compiler
14 * __DCC__ : Wind River Diab Compiler
15 * __ARMCC_VERSION : ARMC Compiler
16 *
17 * Implements : init_data_bss_Activity
18 *END**************************************************************************/
19 void init_data_bss(void);
20 ​
21 void init_data_bss(void)
22 {
23 const Sys_CopyLayoutType * copy_layout;
24 const Sys_ZeroLayoutType * zero_layout;
25 const uint8 * rom;
26 uint8 * ram;
27 uint32 len = 0U;
28 uint32 size = 0U;
29 uint32 i = 0U;
30 uint32 j = 0U;
31 ​
32 const uint32 * initTable = (uint32 *)__INIT_TABLE;
33 const uint32 * zeroTable = (uint32*)__ZERO_TABLE;
34 ​
35 /* Copy initialized table */
36 len = *initTable;
37 copy_layout = (Sys_CopyLayoutType *)(initTable + 1U);
38 for(i = 0; i < len; i++)
39 {
40 rom = copy_layout[i].rom_start;
41 ram = copy_layout[i].ram_start;
42 size = (uint32)copy_layout[i].rom_end - (uint32)copy_layout[i].rom_start;
43 ​
44 for(j = 0UL; j < size; j++)
45 {
46 ram[j] = rom[j];
47 }
48 }
49
50 /* Clear zero table */
51 len = *zeroTable;
52 zero_layout = (Sys_ZeroLayoutType *)(zeroTable + 1U);
53 for(i = 0; i < len; i++)
54 {
55 ram = zero_layout[i].ram_start;
56 size = (uint32)zero_layout[i].ram_end - (uint32)zero_layout[i].ram_start;
57 ​
58 for(j = 0UL; j < size; j++)
59 {
60 ram[j] = 0U;
61 }
62 }
63 }

3.< system.c>作用:

system.c中SystemInit()主要完成按如下顺序完成系统初始化

1.获取内核 ID,使能对应 CM7 内核的所有(240 个)中断请求

2.使能 FPU

3.清空 cache,关闭 cache

4.将内存的地址起始位置,大小,属性(读/写,共享等)写入 CM7 内核 MPU 对应寄存器

5.使能 MPU,打开 cache

主要功能是完成对 CM7 内核 MPU 寄存器的设置。

 1 void SystemInit(void)
2 {
3 uint32 i;
4 uint32 coreMask;
5 uint8 regionNum = 0U;
6 ​
7 uint8 coreId = OsIf_GetCoreID();
8 ​
9 switch(coreId)
10 {
11 case CM7_0:
12 coreMask = (1UL << MSCM_IRSPRC_M7_0_SHIFT);
13 break;
14 case CM7_1:
15 coreMask = (1UL << MSCM_IRSPRC_M7_1_SHIFT);
16 break;
17 default:
18 coreMask = 0UL;
19 break;
20 }
21 ​
22 /* Configure MSCM to enable/disable interrupts routing to Core processor */
23 for (i = 0; i < MSCM_IRSPRC_COUNT; i++)
24 {
25 MSCM->IRSPRC[i] |= coreMask;
26 }
27 /**************************************************************************/
28 /* FPU ENABLE*/
29 /**************************************************************************/
30 #ifdef ENABLE_FPU
31 /* Enable CP10 and CP11 coprocessors */
32 S32_SCB->CPACR |= (S32_SCB_CPACR_CPx(10U, 3U) | S32_SCB_CPACR_CPx(11U, 3U));
33 ​
34 ASM_KEYWORD("dsb");
35 ASM_KEYWORD("isb");
36 #endif /* ENABLE_FPU */
37 ​
38 /**************************************************************************/
39 /* DEFAULT MEMORY ENABLE*/
40 /**************************************************************************/
41 ASM_KEYWORD("dsb");
42 ASM_KEYWORD("isb");
43 ​
44 /* Set default memory regions */
45 for (regionNum = 0U; regionNum < CPU_DEFAULT_MEMORY_CNT; regionNum++)
46 {
47 S32_MPU->RNR = regionNum;
48 S32_MPU->RBAR = rbar[regionNum];
49 S32_MPU->RASR = rasr[regionNum];
50 }
51 ​
52 /* Enable MPU */
53 S32_MPU->CTRL |= S32_MPU_CTRL_ENABLE_MASK;
54 ​
55 ASM_KEYWORD("dsb");
56 ASM_KEYWORD("isb");
57
58 /**************************************************************************/
59 /* ENABLE CACHE */
60 /**************************************************************************/
61 sys_m7_cache_init();
62 }

三、程序编译链接过程

程序编译链接过程分为四个阶段:预编译->编译->汇编->链接;

1.预编译:

1)删除所有的“#define”,并且展开所有的宏定义;

2)处理所有的条件预编译指令,“#if”、“#ifdef”、“#endif”等;

3)处理“#include”预编译指令,将被包含的文件插入到该预编译指令的位置;

4)删除所有的注释;

5)添加行号和文件名标识,以便于编译器产生调试用的符号信息及编译时产生编译错误和警告时显示行号;

6)保留所有的#pragma 编译器指令,因为编译器需要使用它们。

2.编译:

词法分析、语法分析、语义分析,代码优化,汇总符号。

(编译过程往往是整个程序构建的核心部分,也是最复杂的部分之一,编译阶段结束后会生成 .s 文件)

3.汇编:

将汇编指令翻译成二进制格式,生成各个 section,生成符号表。(汇编阶段结束后会生成 .o 文件)

4.链接:

1)合并各个 section,调整 section 的起始位移和段大小,合并符号表,进行符号解析,给符号分配虚拟地址

2)符号重定位

四、名词介绍

1.RAM(Random Access Memory)随机存储器:可读可写,特点是掉电会丢失数据。

RAM又分为SRAM(Static RAM)和DRAM(Dynamic RAM),SRAM是读写速度非常快的存储设备,但价格昂贵。DRAM比ROM速度快,但是比SRAM速度慢,价格低于SRAM,计算机内存使用的就是DRAM。

静态RAM(Static RAM/SRAM),SRAM速度非常快,是目前读写最快的存储设备了;但它也非常昂贵,所以只在要求很苛刻的地方使用,譬如CPU的一级缓冲,二级缓冲;掉电数据消失,持续供电时数据一直存在,不需要动态刷新。

动态RAM(Dynamic RAM/DRAM),DRAM保留数据的时间很短,速度也比SRAM慢,不过它还是比任何的ROM都要快,但从价格上来说DRAM相比SRAM要便宜很多,计算机内存就是DRAM的;掉电数据丢失,供电时需要刷新电路(因为栅极会漏电)

2.ROM(Read Only Memory) 只读存储器:ROM是只读存储器,掉电时可以保存数据:

只读存储器,在单片机运行时,只能从中读取数据,不能向里面写数据。特点是掉电不丢失数据,在单片机中主要用来存储代码和常量等内容。

ROM种类:

ROM也有很多种,PROM是可编程的ROM,PROM和EPROM(可擦除可编程ROM)两者区别是,PROM是一次性的,也就是软件灌入后无法修改,这种是早期的产品,现在已经不可能使用了;而EPROM是通过紫外光的照射擦除原先的程序,是一种通用的存储器。另外一种EEPROM是通过电子擦出,价格很高,写入时间很长,写入很慢。

3.FLASH存储器:FLASH存储器又称闪存,它结合了ROM和RAM的长处,不仅具备电子可擦除可编程(EEPROM)的性能,还不会断电丢失数据,同时可以快速读取数据(NVRAM的优势),U盘和MP3里用的就是这种存储器。在过去的20年里,嵌入式系统一直使用ROM(EPROM)作为它们的存储设备,然而近年来Flash全面代替了ROM(EPROM)在嵌入式系统中的地位,它用作存储Bootloader以及操作系统或者程序代码,或者直接当硬盘使用(U盘)。

4.RTD:NXP最新一代GPIS芯片:S32K3系列,K3系列的配套驱动软件叫做RTD。

5.BAF(Boot Assist Firmware):BAF是在重启后运行在HSE-B安全核心上的第一个代码,它执行必要的系统初始化,搜索和解析IVT(Image Vector Table),最后停止HSE-B,启用SWT并启动应用程序核心。

6.IVT(Image Vector Table):图像矢量表。

五、关键词功能及使用

1.ENTRY(func):定义应用程序代码的程序入口,它是应用程序/引导加载程序重置处理程序。

2.MEMORY{}:包括几个区域的内存映射分配。

−<region> (attribute): ORIGIN = start_address, LENGTH = size of the region。

3.ORIGIN:用于分配内存区域的起始地址,可以缩写为org或o。

4.LEGHTH:用于分配内存区域的长度,它可以缩写为len或l。

5.SECTIONS{}:包含所有的section放置,可以包含几个section组:

−AT用于分配ROM/Flash上的段存储地址(可选);

−KEEP用于保留未使用的section,如向量表、IVT;

−ALIGN用于内存地址对齐,并添加必要的填充数据字节的连接器;

−NOLOAD用于告诉链接器一个段是不可加载的,当程序运行时,它将不会被加载到内存中(可选)。

6.A <section group>:具有任何合法名称的<section组>可以包含多个section放置。

7..:一个点“.”可以用来获取当前内存地址。

8.ORIGIN():在MEMORY{}和SECTIONS{}之外,ORIGIN()可以用来分配一个内存区域的起始地址,并且LEGHTH()获取内存区域的长度。

9..text: 以下是代码段。

10..data:以下是初始化数据段。

11..bss:以下是未初始化数据段。

12..long:定义一个长整型,并为它分配空间,占四字节,0x12345678。

13.align:例:.align absexpr1,absexpr2;以某种对齐方式,在未使用的存储区域填充值。 第一个值表示对齐方式,4, 8,16或32. 第二个表达式值表示填充的值。


——2022.6.23继续学习继续补充、完善、纠正此内容

 

S32DS中链接文件及启动代码学习的更多相关文章

  1. 1.JAVA中使用JNI调用C++代码学习笔记

    Java 之JNI编程1.什么是JNI? JNI:(Java Natibe Inetrface)缩写. 2.为什么要学习JNI?  Java 是跨平台的语言,但是在有些时候仍然是有需要调用本地代码 ( ...

  2. C#中获取文件信息的代码

    如下的内容内容是关于C#中获取文件信息的内容,应该对大伙有一些好处. FileInfo fi = new FileInfo(@"C:file.txt"); if(fi.Exists ...

  3. kernel中对文件的读写【学习笔记】【原创】

    /*1. 头文件 */ #include <linux/init.h> #include <linux/module.h> #include <linux/modulep ...

  4. C51单片机头文件和启动文件

    STARTUP.A51//启动文件. 清理RAM.设置堆栈等.即执行完start.a51后跳转到.c文件的main函数 <reg51.h>  //特殊寄存器的字节地址和位地址,sfr定义字 ...

  5. 浏览器中用JavaScript获取剪切板中的文件

    本文转自我的个人网站  , 原文地址:http://www.zoucz.com/blog/2016/01/29/get-file-from-clipboard/  ,欢迎前往交流讨论 在网页上编辑内容 ...

  6. bootloader启动代码init.s解析----IRQ中断处理函数

    bootloader启动代码init.s解析----IRQ中断处理函数 init.s源代码如下: ;///////////////////////////////////////////// ;opt ...

  7. 【转】Android 学习笔记——利用JNI技术在Android中调用、调试C++代码

    原文网址:http://cherishlc.iteye.com/blog/1756762 在Android中调用C++其实就是在Java中调用C++代码,只是在windows下编译生成DLL,在And ...

  8. ARM启动代码中_main 与用户主程序main()的区别

    1.1  问题描述     __main函数的作用是什么呀?1.2  问题剖析     __main函数是C/C++运行时库的一个函数,嵌入式系统在进入应用主程序之前必须有一个初始化的过程,使用__m ...

  9. 预处理、编译、汇编、链接、启动代码、相关command

    被忽略的过程 对于C这种编译性语言,我们平时编译时,不管是通过IDE图形界面,还是通过命令行,总感觉编译一下就完成了,然后就得到了针对某OS和某CPU的二进制可执行文件(机器指令的文件).但是实际上在 ...

  10. STM32启动代码分析及其汇编学习-ARM

    STM32 启动代码 Author By YuCloud 边看启动文件边学汇编 汇编 see ARM: Assembler User Guide see: https://blog.csdn.net/ ...

随机推荐

  1. pkill 直接对进程对名字进行操作,可以同时杀死多个进程。

    Linux pkill 命令  Linux 命令大全 Linux pkill 用于杀死一个进程,与 kill 不同的是它会杀死指定名字的所有进程,类似于 killall 命令. kill 命令杀死指定 ...

  2. PHP-循环文件夹-yield-生成器

    <?php define(DS, DIRECTORY_SEPARATOR); function gen_dir($path='.'){ $c_dir = opendir($path); whil ...

  3. dcloud打包安卓隐私政策上架问题!

    友情链接: https://ask.dcloud.net.cn/article/36937 两种方式: 方式1. 使用dcloud的方式,在打包文件中配置 隐私json文件,使用dclould封装的隐 ...

  4. scrum和SAFe

    昨天公司培训了scrum开发流程和SAFe,留点资料记录一下 网站:www.scrum.cn 资料:<scrum敏捷软件开发>

  5. uniapp改变icon

    <!DOCTYPE html><html lang="zh-CN"> <head> <meta charset="utf-8&q ...

  6. js 动态给table添加、删除行。

    1.添加table 行 function addtablTr() { var $table = $("#abc"); var vTr = '<tr><td> ...

  7. R语言主成分PCA、因子分析、聚类对地区经济研究分析重庆市经济指标|附代码数据

    全文下载链接:http://tecdat.cn/?p=27515 最*我们被客户要求撰写关于主成分PCA.因子分析.聚类的研究报告,包括一些图形和统计输出. 建立重庆市经济指标发展体系,以重庆市一小时 ...

  8. Ubuntu22 vim配置

    插件管理器 vim-plug # 下载插件管理器 sh -c 'curl -fLo ~/.vim/autoload/plug.vim --create-dirs \ https://raw.githu ...

  9. Rocky8.6软raid

    .tdi_3.td-a-rec { text-align: center } .tdi_3 .td-element-style { z-index: -1 } .tdi_3.td-a-rec-img ...

  10. Docker内容总结

    Docker内容总结目录什么是Docker?Docker的应用场景有哪些?Docker的优点有哪些?Docker与虚拟机的区别是什么?Docker的三大核心是什么?如何快速安装Docker?如何修改D ...