Uboot启动分析笔记-----Stage1(start.S与lowlevel_init.S详解)

2024-01-25 17:08

本文主要是介绍Uboot启动分析笔记-----Stage1(start.S与lowlevel_init.S详解),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Uboot启动分析笔记-----Stage1(start.S与lowlevel_init.S详解)

 

1  u-boot.lds

    首先了解uboot的链接脚本board/my2410/u-boot.lds,它定义了目标程序各部分的链接顺序。

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")  /*指定输出可执行文件为ELF格式,32为,ARM小端*/

OUTPUT_ARCH(arm)/*指定输出可执行文件为ARM平台*/

ENTRY(_start)/*起始代码段为 _start*/

SECTIONS

{

         /* 指定可执行image文件的全局入口点,通常这个地址都放在ROM(flash)0x0位置*、

         . = 0x00000000;从 0x0位置开始

         . = ALIGN(4); 4字节对齐

         .text :

         {

                   cpu/arm920t/start.o    (.text)

                   board/my2440/lowlevel_init.o      (.text)

                   *(.text)

         }

         . = ALIGN(4);

         .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }

         . = ALIGN(4);

         .data : { *(.data) }  /*  只读数据段 ,所有的只读数据段都放在这个位置*/

         . = ALIGN(4);

         .got : { *(.got) }  /*指定got段, got段式是uboot自定义的一个段, 非标准段*/

         . = .;

         __u_boot_cmd_start = .; /*把__u_boot_cmd_start赋值为当前位置, 即起始位置*/

         .u_boot_cmd : { *(.u_boot_cmd) }  /*  u_boot_cmd段,所有的u-boot命令相关的定义都放在这个位置,因为每个命令定义等长,

                       所以只要以__u_boot_cmd_start为起始地址 进行查找就可以很快查找到某一个命令的定义,并依据定义的命令指针调用相应的函数进行处理用户的任务*/

         __u_boot_cmd_end = .;   /* u_boot_cmd段结束位置,由此可以看出,这段空间的长度并没有严格限制,

                                                 用户可以添加一些u-boot的命令,最终都会在连接是存放在这个位置。*/

         . = ALIGN(4);

         __bss_start = .; /*把__bss_start赋值为当前位置,即bss段的开始位置*/

         .bss (NOLOAD) : { *(.bss) . = ALIGN(4); } /*指定bss段,这里NOLOAD的意思是这段不需装载,仅在执行域中才会有这段*/

         _end = .; /*把_end赋值为当前位置,即bss段的结束位置*/

}

第一个链接的是cpu/board/start.o,也即Uboot的入口指令在start中,下面详细分析程序的跳转和函数调用关系。

 

2 Stage1 : cpu/arm920t/start.S

    这个汇编程序时UBoot的入口程序,以复位向量开头。

                    reset

                        ↓

                cpu_init_crit

                        ↓

                   relocate

                        ↓

                stack_setup

                        ↓

               start_armboot()

                        ↓

             init_sequence[]

                        ↓

                  getenv()

                        ↓

                 main_loop()

 其中前面4步为Stage1下面来详细分析一下  cpu/arm920t/start.S

这里以ARM9 2410为例,2440移植时需要修改一些配置,具体的再后面的移植中介绍.

/* 这段代码的主要作用:

进入SVC模式

关闭看门狗

屏蔽所有IRG掩码

设置时钟频率 FCLK HCLK PCLK

清楚I/D Cache

禁止MMU和CACHE

配置memory control

重定位:如果代码不在指定的地址上需要把uboot从当前位置copy到RAM指定位置上

建立堆栈,为进入C函数做准备

清0 .bss段

跳入start_armboot函数进入stage2(lib_arm/board.c)*/

/****************************************************/

.globl _start
_start: /* 系统复位位置, 各个异常向量对应的跳转代码 */
b reset /* 复位向量 */
ldr pc, _undefined_instruction /* 未定义的指令异常向量 */
ldr pc, _software_interrupt /* 软件中断异常向量 */
ldr pc, _prefetch_abort /* 预取指令操作异常向量 */
ldr pc, _data_abort /* 数据操作异常向量 */
ldr pc, _not_used /* 未使用 */
ldr pc, _irq /* 慢速中断异常向量 */
ldr pc, _fiq /* 快速中断异常向量 */
_undefined_instruction:
.word undefined_instruction
_software_interrupt:
.word software_interrupt
_prefetch_abort:
.word prefetch_abort
_data_abort:
.word data_abort
_not_used:
.word not_used
_irq:
.word irq
_fiq:
.word fiq
.balignl 16,0xdeadbeef


/**ARM9支持7种异常。下面是异常的响应过程

*第一个复位异常,它放在0x0的位置,一上电就执行它,而且我们的程序总是从复位异常处理程序

*    开始执行的,因此复位异常处理程序不需要返回。

*其他异常处理的如下:

*当一个异常出现以后,ARM会自动执行以下几个步骤:

*(1) 把下一条指令的地址放到连接寄存器LR(通常是R14),这样就能够在处理异常返回时从正确的位置继续执行。

*(2) 将相应的CPSR(当前程序状态寄存器)复制到SPSR(备份的程序状态寄存器)中。从异常退出的时候,就可以由SPSR来恢复CPSR。

*(3) 根据异常类型,强制设置CPSR的运行模式位。

*(4) PC(程序计数器)被强制成相关异常向量处理函数地址,从而跳转到相应的异常处理程序中。

* 当异常处理完毕后,ARM会执行以下几步操作从异常返回:

*(1)将连接寄存器LR的值减去相应的偏移量后送到PC中

*(2) 将SPSR复制回CPSR中

*(3) 若在进入异常处理时设置了中断禁止位,要在此清除

*

* ARM规定了异常向量的地址:
* b reset ; 复位 0x0

* ldr pc, _undefined_instruction ; 未定义的指令异常 0x4

* ldr pc, _software_interrupt ; 软件中断异常 0x8

* ldr pc, _prefetch_abort ; 预取指令 0xc

* ldr pc, _data_abort ; 数据 0x10

* ldr pc, _not_used ; 未使用 0x14

* ldr pc, _irq ; 慢速中断异常 0x18

* ldr pc, _fiq ; 快速中断异常 0x1c
* 当处理器碰到异常时,PC会被强制设置为对应的异常向量,从而跳转到

* 相应的处理程序,然后再返回到主程序继续执行。

* .balignl 16,0xdeadbeef, 将地址对齐到16的倍数,如果地址寄存器的值(PC)跳过4个字节才是16的倍数,

* 则使用0xdeadbeef填充这4个字节,如果它跳过1、2、3个字节,则填充值不确定。如果地址寄存器的值(PC)是16的倍数,则无需移动。********************/

 

/*************************************************************************
* Startup Code (reset vector) ………………….

*************************************************************************/
/* 保存变量的数据区 */
_TEXT_BASE:
.word TEXT_BASE   ;定义一个字并分配空间 4bytes

.globl _armboot_start
_armboot_start:
.word _start  ;声明一个全局的,并用 _start 初始化它, 在u-boot.lds中定义

/* These are defined in the board-specific linker script.*/
.globl _bss_start
_bss_start:
.word __bss_start
.globl _bss_end
_bss_end:
.word _end
#ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START
IRQ_STACK_START:
.word 0x0badc0de
/* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START
FIQ_STACK_START:
.word 0x0badc0de
#endif
/* the actual reset code*/
/* 系统的复位代码。系统一上电,就跳到这里运行 */

 

reset:
    mrs r0,cpsr          /* 取得当前程序状态寄存器cpsr到r0 */
    bic r0,r0,#0x1f    /* 这里使用位清除指令,把中断全部清除,只置位模式控制位为中断提供服务通常是 OS设备驱动程序的责任,

                                 因此在 Boot Loader 的执行全过程中可以不必响应任何中断*/
    orr r0,r0,#0xd3   /* 计算为超级保护模式,并disable IRQ和FIQ */
    msr cpsr,r0 /* 设置cpsr为超级保护模式 */
/*****************

*CPSR 的底8位为I     F        T        M4       M3       M2       M1       M0

          IRQdisable FIQdisable StateBit

SVC[M4~M0] = 10011

StateBit = set:THUMB state, others:ARM state

* 设置cpu运行在SVC32模式。ARM9共有7种模式:
* 用户模式(usr): arm处理器正常的程序执行状态
* 快速中断模式(fiq): 用于高速数据传输或通道处理
* 外部中断模式(irq): 用于通用的中断处理
* 超级保护模式(svc): 操作系统使用的保护模式
* 数据访问终止模式(abt): 当数据或指令预取终止时进入该模式,可用于虚拟存储及存储保护
* 系统模式(sys): 运行具有特权的操作系统任务
* 未定义指令中止模式(und): 当未定义的指令执行时进入该模式,可用于支持硬件协处理器的软件仿真
* 通过设置ARM的CPSR寄存器,让CPU运行在操作系统保护模式,为后面进行其它操作作好准备了。

*********************************************************/

#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)

     /* turn off the watchdog */

//这段是关watchdog

#if defined(CONFIG_S3C2400)

#  define pWTCON   0x15300000

#  define INTMSK   0x14400008    /* Interupt-Controller base addresses */

#  define CLKDIVN  0x14800014    /* clock divisor register */

#else

#  define pWTCON   0x53000000

#  define INTMSK   0x4A000008    /* Interupt-Controller base addresses */

#  define INTSUBMSK    0x4A00001C

#  define CLKDIVN  0x4C000014    /* clock divisor register */

# endif

     ldr  r0, =pWTCON   //具体可以查看手册

     mov  r1, #0x0

     str  r1, [r0]

     /*

      * mask all IRQs by setting all bits in the INTMR - default

      */

     mov  r1, #0xffffffff //禁止所有中断

     ldr  r0, =INTMSK

     str  r1, [r0]

# if defined(CONFIG_S3C2410)

     ldr  r1, =0x3ff

     ldr  r0, =INTSUBMSK

     str  r1, [r0]

# endif

     /* FCLK:HCLK:PCLK = 1:2:4 */

     /* default FCLK is 120 MHz ! */

     ldr  r0, =CLKDIVN

     mov  r1, #3

     str  r1, [r0]

#endif  /* defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)*/

/*
* we do sys-critical inits only at reboot,
* not when booting from ram!
*/
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
       bl cpu_init_crit  ;cpu初始化,其中会调用lowlevel_init.S


/******************************************************************************
* BL为相对寻址,以程序计数器PC 的当前值为基地址,指令中的地址标号作为偏移量,将两者相加之后得到操作数的有效地址
* ARM 指令集中的4条跳转指令可以完成从当前指令向前或向后的32MB 的地址空间的跳转,
* 用的是相对寻址,它们是:B、BL、BLX、BX
*******************************************************************************/

#endif


#ifndef CONFIG_SKIP_RELOCATE_UBOOT
/* 重定位Boot代码到RAM内存,将Boot代码从FLASH移到RAM中 。因为flash中执行速度很慢,而且系统每次复位了都会在0x00000000处执行*/


relocate: /* relocate U-Boot to RAM */
adr r0, _start /* r0 <- current position of code */

/**************************************************************************
* 把_start的相对地址移到r0, 相对寻址以程序计数器PC 的当前值为基地址,
* 指令中的地址标号作为偏移量,将两者相加之后得到操作数的有效地址。
* 它是与位置无关的,主要看Boot在哪里运行,也就是PC指针在哪里 (假设_start偏移量为0),
* 例如这段代码在 0x05000000 (FLASH起始地址)运行,即此时PC=0x05000000,

那么 adr r0, _start 得到 r0 = 0x05000000;
* 如果在地址 0x33008000(Boot在RAM中加载地址)运行,即此时PC=0x33008000,那么r0就是 0x33008000 了。

*通过adr指令得到当前代码的地址信息:如果U-boot是从RAM开始运行,则从adr,r0,_start得到的地址信息为*r0=_start=_TEXT_BASE=TEXT_BASE=0x3ff80000;如果U-boot从Flash开始运行,即从处理器对应的地址运 行,则*r0=0x0000,这时将会执行copy_loop标识的那段代码了
**************************************************************************/
     ldr r1, _TEXT_BASE/* test if we run from flash or RAM */

/* 把_TEXT_BASE地址处的值TEXT_BASE,也就是BOOT在RAM中运行地址移到r1 */
   cmp r0, r1 /* don't reloc during debug */

/* 比较两个地址是否相同,如果相同,就已经在RAM运行,否则就是FLASH中运行 */

beq stack_setup
/* 如果是在FLASH中运行, 则把FLASH中的Boot代码移到RAM中,然后再运行 */
ldr r2, _armboot_start /* 把_armboot_start地址处的值也就是_start绝对地址(也即在内存中的地址,这个绝对
* 地址是在 link 的时候确定的,如0x81008000)移到r2 */
        ldr r3, _bss_start /* 把_bss_start地址处的值也就是__bss_start绝对地址(也即在内存中的地址,这个绝对
* 地址是在 link 的时候确定的)移到r3 */
        sub r2, r3, r2 /* r2 <- size of armboot */ /* 计算引导代码大小并存到r2 */
        add r2, r0, r2 /* r2 <- source end address */ /* 计算引导代码最后相对地址并存入r2 */
copy_loop:
        ldmia r0!, {r3-r10} /* copy from source address [r0] */ /* 从源地址[r0]读取32个字节到寄存器,并更新r0 */
        stmia r1!, {r3-r10} /* copy to target address [r1] */ /* 拷贝寄存器r3-r10的32个字节值保存到 [r1]指明的地址,并更新r1的值 */
        cmp r0, r2 /* until source end addreee [r2] */ /* 循环拷贝,直到把所有引导代码都移到内存 */
        ble copy_loop
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */

 

/* Set up the stack */
/* 在内存中建立起堆栈 */

 

stack_setup:
        ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
        sub r0, r0, #CFG_MALLOC_LEN /* malloc area */
        sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
#ifdef CONFIG_USE_IRQ
        sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
        sub sp, r0, #12 /* leave 3 words for abort-stack */


/* 初始化内存中bss段中数据为0 */
clear_bss:
        ldr r0, _bss_start /* find start of bss segment*/

 /* 把_bss_start地址处存储的绝对地址移到r0 */
ldr r1, _bss_end /* stop here */ /* 把_bss_end地址处存储的绝对地址移到r1 */
mov r2, #0x00000000 /* clear */
clbss_l:
str r2, [r0] /* clear loop... STR 指令用于从源寄存器中r2将一个32 位的字数据传送到存储器中[r0]*/
add r0, r0, #4
cmp r0, r1
ble clbss_l /* 小于或等于跳转 */
ldr pc, _start_armboot


/***********************************************************
* 已经准备好了堆栈,就可跳到C写的代码里了,也就是
* 跳到内存中的/u-boot-1.1.6/board.c --> start_armboot中运行了
* 把_start_armboot地址处的值也就是start_armboot绝对地址值移到pc
* 神啊!终于跳到C代码了。
***********************************************************/
_start_armboot:
.word start_armboot
/*************************************************************************
*
* CPU_init_critical registers
*
* setup important registers
* setup memory timing
*
*************************************************************************/
/**************************************************************************
* 1、关闭 MMU和CPU 内部指令/数据 (I/D)cache。
* 2、设置 CPU 的速度和时钟频率。
* 3 、RAM 初始化。
****************************************************************************/
cpu_init_crit:
/* flush v4 I/D caches*/
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
/******************************************************************************************************
* MCR 指令用于将ARM 处理器寄存器中的数据传送到协处理器寄存器中,格式为:
* MCR 协处理器编码,协处理器操作码1,源寄存器,目的寄存器1,目的寄存器2,协处理器操作码2。
* 其中协处理器操作码1 和协处理器操作码2 为协处理器将要执行的操作,
* 源寄存器为ARM 处理器的寄存器,目的寄存器1 和目的寄存器2 均为协处理器的寄存器。
******************************************************************************************************/
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
/ * disable MMU stuff and caches*/
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */
bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */
orr r0, r0, #0x00000002 /* set bit 2 (A) Align */
orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */
mcr p15, 0, r0, c1, c0, 0
/ * Go setup Memory and board specific bits prior to relocation.*/
mov ip, lr /* perserve link reg across call */
bl lowlevel_init /* go setup pll,mux,memory */ /* 位于u-boot-1.1.6/board/xxx(开发板目录名称)/lowlevel_init.S */
mov lr, ip /* restore link */
mov pc, lr /* back to my caller */ /* 从cpu_init_crit子函数返回 */
/*************************************************************************
*
* Interrupt handling
*
*************************************************************************/

/*下面是中断相关的东西,这里略去*/

 

 


3 ./board/my2410/lowlevel_init.S

 

.globl lowlevel_init //读取下面标号为SMRDATA处的地址到R0中
    ldr r0, =SMRDATA
     /*读取上面标号为_TEXT_BASE处的地址内容到R1中
     *也就是取得TEXT_BASE的值到R1中*/
    ldr    r1, _TEXT_BASE
     /*计算SMRDATA的相对地址保存到R0中
     *SMRDATA为虚拟地址,而TEXT_BASE为虚拟地址的起始地址
     *而现在Uboot的起始地址并不为虚拟地址
     *TEXT_BASE为0x33F8 0000,SMRDATA为0x33F8 06C8
     *而现在程序运行在起始地址为0x0000 0000的地方
     *所以需要计算以0x0000 0000为标准的相对地址*/
    sub    r0, r0, r1
     //取得带宽与等待状态控制寄存器地址到R1中
    ldr    r1, =BWSCON    /* Bus Width Status Controller */
     //一共需要设置13个寄存器,每个寄存器4字节,详见芯片手册
    add r2, r0, #13*4
0:
     //读取R0所指的项的值到R3中后R0自加4字节
    ldr r3, [r0], #4
     //将R3中的值保存到R1所指的地址中后R1自加4字节
    str r3, [r1], #4
     //比较R0和R2是否相等,相等则说明13个寄存器全部设置完毕
    cmp r2, r0
     //不等则跳转到上面标号为0处的地址继续执行
    bne 0b
     //跳回到返回地址中继续执行
    mov    pc, lr
    .ltorg
/* the literal pools origin */
SMRDATA:
    .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))

//设置每个BWSCON,注意BANK0由硬件连线决定了
    .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
    .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
    .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
    .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
    .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
    .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
   //设置BANKCON0~BANKCON5    

    .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
    .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))

//设置BANKCON6~BANKCON7
    .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)

//设置REFRESH,在S3C2440中11~17位是保留的,也即(Tchr<<16)无意义
    .word 0x32

//设置BANKSIZE,对于容量可以设置大写,多出来的空内存会被自动检测出来
    .word 0x30

//设置MRSRB6
    .word 0x30

//设置MRSRB7

这篇关于Uboot启动分析笔记-----Stage1(start.S与lowlevel_init.S详解)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/643980

相关文章

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

springboot3打包成war包,用tomcat8启动

1、在pom中,将打包类型改为war <packaging>war</packaging> 2、pom中排除SpringBoot内置的Tomcat容器并添加Tomcat依赖,用于编译和测试,         *依赖时一定设置 scope 为 provided (相当于 tomcat 依赖只在本地运行和测试的时候有效,         打包的时候会排除这个依赖)<scope>provided

内核启动时减少log的方式

内核引导选项 内核引导选项大体上可以分为两类:一类与设备无关、另一类与设备有关。与设备有关的引导选项多如牛毛,需要你自己阅读内核中的相应驱动程序源码以获取其能够接受的引导选项。比如,如果你想知道可以向 AHA1542 SCSI 驱动程序传递哪些引导选项,那么就查看 drivers/scsi/aha1542.c 文件,一般在前面 100 行注释里就可以找到所接受的引导选项说明。大多数选项是通过"_

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

用命令行的方式启动.netcore webapi

用命令行的方式启动.netcore web项目 进入指定的项目文件夹,比如我发布后的代码放在下面文件夹中 在此地址栏中输入“cmd”,打开命令提示符,进入到发布代码目录 命令行启动.netcore项目的命令为:  dotnet 项目启动文件.dll --urls="http://*:对外端口" --ip="本机ip" --port=项目内部端口 例: dotnet Imagine.M