精华内容
下载资源
问答
  • 问题:服务器端启动后cpu占用率很高,经常是99%,100%。原因分析:RecvThread的终止判断条件最初是if (num == -1)//这里的num是指通道读取到buffer中的字节数,当没有数据时,客户端的IntputStream始终没有终止或...

     问题:服务器端启动后,cpu占用率很高,经常是99%,100%。
    原因分析:
    RecvThread的终止判断条件最初是if (num == -1)//这里的num是指通道读取到buffer中的字节数,当没有数据时,客户端的IntputStream始终没有终止或关闭,
     也就是说SocketChannel始终无法读到流的末尾。但是服务器的channel始终在尝试读取客户端的数据,但读取的数据都为空,
     这样就使得cpu一直在做“无用功”——空转。

    --------------------------------------------------
     或许你会问,只不过才一个线程在接收数据而已,不至于使得cpu慢的如老牛耕地吧?你这样说是没错的。但是接下来,我在无意中做了个
     小小的实验:我在RecvThread类中加入了运行时的debug信息。
     另外,请观众注意,当我们在ListenThread中启动RecvThread并运行的同时,原先的线程ListenThread也没闲着,而是在继续往下执行。
     
    服务器端启动后,我使用客户端发送了一个字符(仅仅是一个字符)给服务器端,意外出现了:服务器的console中打印了不止一个RecvThread线程的debug信息。
    为什么会有这么多线程?按照我们的思路,当判断SelectionKey是readable厚,我们只new了一个线程来接收数据啊。而且NIO api中对

    Selector的select()方法解释如下:
     

    是啊,没错啊,只有select至少一个有效的通道时,select()才会返回,否则就一直阻塞。
    但是,从我刚才的实验中,大家也许很清楚的看到了,其实当RecvThread处理数据的同时,select()方法并没有阻塞,继而它后面的程序仍然会继续执行。
    以至于new 了第二个、第三个....第n个RecvThread的实例。
    后来我专门又输出了select()的返回值,结果也进一步验证了我刚才所言——RecvThread线程处理数据的同时,select()并没有老老实实的阻塞在那里,而是返回了一个0。

    最后,唯一令我感到欣慰的是,这n个线程并不是每一个都接收了客户端发来的数据,而是仅仅其中一个线程接收到了数据。

     

    解决方法:把RecvThread的终止判断条件改成if (num <= 0),并且强烈建议您:不要在selectionKey.isReadable()判断之后,去新建一个线程来接收到来的数据。原因1是因为刚才我所讲的一个消息对应n个线程,将耗费掉大量的cpu资源,
    而且这n个线程中为我们做事的却只有其中一个(这也许刚好就是当今经济危机下大部分企业都在裁员的原因)。原因之二,千万不要单纯以为这不过是n个线程而已,
    服务器接收客户端消息是很频繁的,一个消息对应n个线程,那么100条消息就对应了.....我想你不会希望看到自己的cpu被这n*100个线程累垮。^_^

    展开全文
  • 测试环境, 操作系统:Windows XP sp3 开发环境:Visual Studio2010 开发语言及支持库:WPF,...1、启动程序,点击打开按钮。打开文件对话框中选中需要处理的图片,点击“打开”。软件随即开始处理。 2、...

    测试环境,

    操作系统:Windows XP sp3

    开发环境:Visual Studio2010

    开发语言及支持库:WPF,.NET 4,EmguCV

    硬件:lenovo Y430,CPU:T4200 奔腾双核 2.0GHz ,内存2G,集成显卡

    软件截图:

    使用说明:

    1、启动程序后,点击打开按钮。在打开文件对话框中选中需要处理的图片,点击“打开”。软件随即开始处理。 

    2、处理完成后,软件会在下方的信息框内打印相关的处理信息,此处的处理时间指计算暗通道的时间,图像去雾的时间不算在内。

    3、点击保存按钮会连续两次弹出保存对话框,依次保存去雾后的图像和图像的暗通道灰度图。

    4、用户可以右侧单选框选择两种算法,然后把两次处理的暗通道结果保存为外部文件。然后点击图像之差,选择两次计算的暗通道,这样两幅图像之差就显示在“图片之差”图片栏。信息框会打印出非0值的个数。

    一下附两种去雾处理效果图:窗口大小为15,窗口较小时,任务后背的汗渍会成血红色,失真较大,一般取15为宜。

    为了是代码便于阅读,程序未加入soft mating,去雾后景物边缘出现白边请自行调整A,omaga,t0三个参数,不便之处敬请谅解~

    原图

    原图

    去雾后的图像

     安装文件及测试素材下载地址 

    下载HazeRemover.rar解压安装,

    然后下载EmguCVx86解压,将其中的所有文件复制到安装目录下即可.

    程序需要.NET4 支持,vista,win7用户无需安装,xp用户需升级到sp3后安装.NET4

    审稿老师需源代码,请联系liuxia19872003@qq.com

    转载于:https://www.cnblogs.com/liuxia19872003/archive/2012/08/02/2620739.html

    展开全文
  • TI Cortex M3串口转以太网例程分析2-----bootloader

    千次阅读 热门讨论 2011-08-10 15:07:14
    bootloader是TI串口转以太网代码的一小部分,位于Flash开始的4KB空间内。它的一个重要作用是应用远程升级,可以通过串口、USB...bootloader是CPU启动后最先执行的程序,它会把自己拷贝到SRAM,并判断是否有固件升级,

            bootloader是TI串口转以太网代码的一小部分,位于Flash开始的4KB空间内。它的一个重要作用是在应用远程升级,可以通过串口、USB、IIC、以太网等通道进行远程固件升级。bootloader是CPU启动后最先执行的程序,它会把自己拷贝到SRAM,并判断是否有固件升级,如果有升级请求,则执行升级程序;反之,执行用户程序。

      一.流程图       

               由于这里只考虑基于以太网的bootloader,其流程图如图2-1所示:


    图2-1

     二.配置文件     

            由于bootlaoder可以使用串口、USB、IIC、以太网等通道进行远程固件升级,那么怎么样配置才可以使用以太网呢?这就牵扯到bl_config文件。此文件是专门配置bootloader的。代码就不贴了,看一下这里面几个必须配置的选项:

    1. 以下至少且只能定义一个,用于指明使用何种方式升级。

            CAN_ENABLE_UPDATE,       

            ENET_ENABLE_UPDATE,

            I2C_ENABLE_UPDATE,

            SSI_ENABLE_UPDATE,

            UART_ENABLE_UPDATE,

            USB_ENABLE_UPDATE

    2. 以下必须定义

            APP_START_ADDRESS                        用户程序启动地址

            VTABLE_START_ADDRESS                 用户程序向量表起始地址

            FLASH_PAGE_SIZE                               Flash页大小,TI的目前为止都为1K

            STACK_SIZE                                           堆栈大小

    3. 当选择了以太网升级后,以下必须定义

            CRYSTAL_FREQ                                     目标板晶振频率

    三.bootloader启动代码分析

              不少人不喜欢分析汇编文件,甚至总想绕过汇编。网络上也出现一些人教导初学者学习单片机的时候直接用C语言编程,避开汇编。我个人是极其不同意这种“速成”方法的。作为一名合格的嵌入式工程师或者说爱好者,汇编绝不可回避。汇编能帮助理解硬件,特别是CPU结构、存储和寻址等等;现在的嵌入式程序虽然绝大多数是用C编写的,但要想精通C语言,必须具有汇编基础,任何技术都是入门容易,精通难,因此要想深入理解C的指针、数组甚至是变量存储,还非少不了汇编不可;再者,有些地方必须使用汇编,比如一些实时性要求高的模块(不常见),还有就是接下来要说的启动代码。先附源代码。

    ;******************************************************************************
    ;
    ; bl_startup_rvmdk.S - Startup code for RV-MDK.
    ;
    ; Copyright (c) 2007-2010 Texas Instruments Incorporated.  All rights reserved.
    ; Software License Agreement
    ; 
    ; Texas Instruments (TI) is supplying this software for use solely and
    ; exclusively on TI's microcontroller products. The software is owned by
    ; TI and/or its suppliers, and is protected under applicable copyright
    ; laws. You may not combine this software with "viral" open-source
    ; software in order to form a larger program.
    ; 
    ; THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    ; NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    ; NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    ; A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    ; CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    ; DAMAGES, FOR ANY REASON WHATSOEVER.
    ; 
    ; This is part of revision 6288 of the Stellaris Firmware Development Package.
    ;
    ;******************************************************************************
    
        include bl_config.inc
    
    ;******************************************************************************
    ;
    ; A couple of defines that would normally be obtained from the appropriate C
    ; header file, but must be manually provided here since the Keil compiler does
    ; not have a mechanism for passing assembly source through the C preprocessor.
    ; 以下定义通常在C头文件中定义过,但仍要在这里定义,因为keil编译器没有从汇编器直接
    ; 调用C预编译器的机制.
    ;
    ;******************************************************************************
    SYSCTL_RESC                     equ     0x400fe05c	  ;复位原因
    SYSCTL_RESC_MOSCFAIL            equ     0x00010000
    NVIC_VTABLE                     equ     0xe000ed08	  ;向量表偏移量寄存器
    
    ;******************************************************************************
    ;
    ; Put the assembler into the correct configuration.
    ;
    ;******************************************************************************
        thumb			   ;thumb指令
        require8
        preserve8
    
    ;******************************************************************************
    ;
    ; The stack gets placed into the zero-init section.
    ; 将堆放到零初始化区
    ;
    ;******************************************************************************
        area    ||.bss||, noinit, align=2	 ;4字节对齐,2的2次幂
    
    ;******************************************************************************
    ;
    ; Allocate storage for the stack.
    ; 为堆分配空间,STACK_SIZE在bl_config.h中定义的宏,通过bl_config.inc加载armcc
    ;
    ;******************************************************************************
    g_pulStack
        space   _STACK_SIZE * 4
    
    ;******************************************************************************
    ;
    ; This portion of the file goes into the reset section.
    ;
    ;******************************************************************************
        area    RESET, code, readonly, align=3	  ;8字节对齐?
    
    ;******************************************************************************
    ;
    ; The minimal vector table for a Cortex-M3 processor.
    ;
    ;******************************************************************************
        export  __Vectors
    __Vectors
        dcd     g_pulStack + (_STACK_SIZE * 4)  ; Offset 00: Initial stack pointer 初始化堆栈指针
        if      :def:_FLASH_PATCH_COMPATIBLE
        dcd     Reset_Handler + 0x1000          ; Offset 04: Reset handler	 为某些Flash打了补丁的器件
        dcd     NmiSR + 0x1000                  ; Offset 08: NMI handler
        dcd     FaultISR + 0x1000               ; Offset 0C: Hard fault handler
        else
        dcd     Reset_Handler                   ; Offset 04: Reset handler
        dcd     NmiSR                           ; Offset 08: NMI handler
        dcd     FaultISR                        ; Offset 0C: Hard fault handler
        endif
        dcd     IntDefaultHandler               ; Offset 10: MPU fault handler
        dcd     IntDefaultHandler               ; Offset 14: Bus fault handler
        dcd     IntDefaultHandler               ; Offset 18: Usage fault handler
        dcd     0                               ; Offset 1C: Reserved
        dcd     0                               ; Offset 20: Reserved
        dcd     0                               ; Offset 24: Reserved
        dcd     0                               ; Offset 28: Reserved
        if      :def:_FLASH_PATCH_COMPATIBLE
        dcd     UpdateHandler + 0x1000          ; Offset 2C: SVCall handler	  SVC异常
        else
        dcd     UpdateHandler                   ; Offset 2C: SVCall handler
        endif
        dcd     IntDefaultHandler               ; Offset 30: Debug monitor handler
        dcd     0                               ; Offset 34: Reserved
        dcd     IntDefaultHandler               ; Offset 38: PendSV handler
        if      :def:_ENET_ENABLE_UPDATE
        import  SysTickIntHandler
        dcd     SysTickIntHandler               ; Offset 3C: SysTick handler
        else
        dcd     IntDefaultHandler               ; Offset 3C: SysTick handler
        endif
        if      :def:_UART_ENABLE_UPDATE :land: :def:_UART_AUTOBAUD
        import  GPIOIntHandler
        dcd     GPIOIntHandler                  ; Offset 40: GPIO port A handler
        else
        dcd     IntDefaultHandler               ; Offset 40: GPIO port A handler
        endif
        if      :def:_USB_ENABLE_UPDATE :lor:                                     \
                (_APP_START_ADDRESS != _VTABLE_START_ADDRESS) :lor:               \
                :def:_FLASH_PATCH_COMPATIBLE
        dcd     IntDefaultHandler               ; Offset 44: GPIO Port B
        dcd     IntDefaultHandler               ; Offset 48: GPIO Port C
        dcd     IntDefaultHandler               ; Offset 4C: GPIO Port D
        dcd     IntDefaultHandler               ; Offset 50: GPIO Port E
        dcd     IntDefaultHandler               ; Offset 54: UART0 Rx and Tx
        dcd     IntDefaultHandler               ; Offset 58: UART1 Rx and Tx
        dcd     IntDefaultHandler               ; Offset 5C: SSI0 Rx and Tx
        dcd     IntDefaultHandler               ; Offset 60: I2C0 Master and Slave
        dcd     IntDefaultHandler               ; Offset 64: PWM Fault
        dcd     IntDefaultHandler               ; Offset 68: PWM Generator 0
        dcd     IntDefaultHandler               ; Offset 6C: PWM Generator 1
        dcd     IntDefaultHandler               ; Offset 70: PWM Generator 2
        dcd     IntDefaultHandler               ; Offset 74: Quadrature Encoder 0
        dcd     IntDefaultHandler               ; Offset 78: ADC Sequence 0
        dcd     IntDefaultHandler               ; Offset 7C: ADC Sequence 1
        dcd     IntDefaultHandler               ; Offset 80: ADC Sequence 2
        dcd     IntDefaultHandler               ; Offset 84: ADC Sequence 3
        dcd     IntDefaultHandler               ; Offset 88: Watchdog timer
        dcd     IntDefaultHandler               ; Offset 8C: Timer 0 subtimer A
        dcd     IntDefaultHandler               ; Offset 90: Timer 0 subtimer B
        dcd     IntDefaultHandler               ; Offset 94: Timer 1 subtimer A
        dcd     IntDefaultHandler               ; Offset 98: Timer 1 subtimer B
        dcd     IntDefaultHandler               ; Offset 9C: Timer 2 subtimer A
        dcd     IntDefaultHandler               ; Offset A0: Timer 2 subtimer B
        dcd     IntDefaultHandler               ; Offset A4: Analog Comparator 0
        dcd     IntDefaultHandler               ; Offset A8: Analog Comparator 1
        dcd     IntDefaultHandler               ; Offset AC: Analog Comparator 2
        dcd     IntDefaultHandler               ; Offset B0: System Control
        if      :def:_FLASH_PATCH_COMPATIBLE
        dcd     0x00000881                      ; Offset B4: FLASH Control
        else
        dcd     IntDefaultHandler               ; Offset B4: FLASH Control
        endif
        endif
        if      :def:_USB_ENABLE_UPDATE :lor:                                     \
                (_APP_START_ADDRESS != _VTABLE_START_ADDRESS)
        dcd     IntDefaultHandler               ; Offset B8: GPIO Port F
        dcd     IntDefaultHandler               ; Offset BC: GPIO Port G
        dcd     IntDefaultHandler               ; Offset C0: GPIO Port H
        dcd     IntDefaultHandler               ; Offset C4: UART2 Rx and Tx
        dcd     IntDefaultHandler               ; Offset C8: SSI1 Rx and Tx
        dcd     IntDefaultHandler               ; Offset CC: Timer 3 subtimer A
        dcd     IntDefaultHandler               ; Offset D0: Timer 3 subtimer B
        dcd     IntDefaultHandler               ; Offset D4: I2C1 Master and Slave
        dcd     IntDefaultHandler               ; Offset D8: Quadrature Encoder 1
        dcd     IntDefaultHandler               ; Offset DC: CAN0
        dcd     IntDefaultHandler               ; Offset E0: CAN1
        dcd     IntDefaultHandler               ; Offset E4: CAN2
        dcd     IntDefaultHandler               ; Offset E8: Ethernet
        dcd     IntDefaultHandler               ; Offset EC: Hibernation module
        if      :def: _USB_ENABLE_UPDATE
        import  USB0DeviceIntHandler
        dcd     USB0DeviceIntHandler            ; Offset F0: USB 0 Controller
        else
        dcd     IntDefaultHandler               ; Offset F0: USB 0 Controller
        endif
        endif
    
    ;******************************************************************************
    ;
    ; Initialize the processor by copying the boot loader from flash to SRAM, zero
    ; filling the .bss section, and moving the vector table to the beginning of
    ; SRAM.  The return address is modified to point to the SRAM copy of the boot
    ; loader instead of the flash copy, resulting in a branch to the copy now in
    ; SRAM.
    ; 初始化处理器,将boot loader从flash拷贝到SRAM,将.bss区用零填充并将向量表重映射到
    ; SRAM的开始处.
    ;
    ;******************************************************************************
        export  ProcessorInit
    ProcessorInit
        ;
        ; Copy the code image from flash to SRAM.
        ;
        if      :def:_FLASH_PATCH_COMPATIBLE
        movs    r0, #0x1000
        else
        movs    r0, #0x0000		 
        endif
        movs    r1, #0x0000
        movt    r1, #0x2000		 ;将16位的立即数放到寄存器的高16位,低位不受影响
        import  ||Image$SRAM$ZI$Base||  ;为汇编器提供一个在当前汇编程序中未定义的符号
        ldr     r2, =||Image$SRAM$ZI$Base||	;SRAM区中的ZI输出节执行地址
    copy_loop
            ldr     r3, [r0], #4
            str     r3, [r1], #4
            cmp     r1, r2
            blt     copy_loop
    
        ;
        ; Zero fill the .bss section.将.bss区用零填充
        ;
        movs    r0, #0x0000
        import  ||Image$SRAM$ZI$Limit||	   ;SRAM区中ZI 输出节末尾地址后面的字节地址
        ldr     r2, =||Image$SRAM$ZI$Limit||
    zero_loop
            str     r0, [r1], #4
            cmp     r1, r2
            blt     zero_loop
    
        ;
        ; Set the vector table pointer to the beginning of SRAM.
    	; 将向量表指针指向SRAM开始处
        ;
        movw    r0, #(NVIC_VTABLE & 0xffff)		;放入r0低16位,高位清零
        movt    r0, #(NVIC_VTABLE >> 16)		;NVIC_VTABLE=0xe000ed08(向量表偏移量寄存器)
        movs    r1, #0x0000
        movt    r1, #0x2000
        str     r1, [r0]						;向量表重定位到0x2000 0000处
    
        ;
        ; Return to the caller.返回
        ;
        bx      lr
    
    ;******************************************************************************
    ;
    ; The reset handler, which gets called when the processor starts.
    ;
    ;******************************************************************************
        export  Reset_Handler
    Reset_Handler
        ;
        ; Initialize the processor.
        ;
        bl      ProcessorInit
    
        ;
        ; Branch to the SRAM copy of the reset handler.
        ;
        ldr     pc, =Reset_Handler_In_SRAM       ;进入SRAM执行程序
    
    ;******************************************************************************
    ;
    ; The NMI handler.
    ;
    ;******************************************************************************
    NmiSR
        if      :def:_ENABLE_MOSCFAIL_HANDLER
        ;
        ; Grab the fault frame from the stack (the stack will be cleared by the
        ; processor initialization that follows).
        ;
        ldm     sp, {r4-r11}
        mov     r12, lr
    
        ;
        ; Initialize the processor.
        ;
        bl      ProcessorInit
    
        ;
        ; Branch to the SRAM copy of the NMI handler.
        ;
        ldr     pc, =NmiSR_In_SRAM
        else
        ;
        ; Loop forever since there is nothing that we can do about a NMI.
        ;
        b       .
        endif
    
    ;******************************************************************************
    ;
    ; The hard fault handler.
    ;
    ;******************************************************************************
    FaultISR
        ;
        ; Loop forever since there is nothing that we can do about a hard fault.
        ;
        b       .
    
    ;******************************************************************************
    ;
    ; The update handler, which gets called when the application would like to
    ; start an update.
    ; 升级服务函数,当应用程序想要开始升级时,调用这个函数.
    ;
    ;******************************************************************************
    UpdateHandler
        ;
        ; Initialize the processor.	初始化处理器
        ;
        bl      ProcessorInit		  ;调用子程序
    
        ;
        ; Branch to the SRAM copy of the update handler.
        ;
        ldr     pc, =UpdateHandler_In_SRAM
    
    ;******************************************************************************
    ;
    ; This portion of the file goes into the text section.
    ;
    ;******************************************************************************
        align   4
        area    ||.text||, code, readonly, align=2
    
    Reset_Handler_In_SRAM
        ;
        ; Call the user-supplied low level hardware initialization function
        ; if provided.
    	; 如果用户提供了底层硬件初始化函数,则调用这个函数
        ;
        if      :def:_BL_HW_INIT_FN_HOOK
        import  $_BL_HW_INIT_FN_HOOK
        bl      $_BL_HW_INIT_FN_HOOK
        endif
    
        ;
        ; See if an update should be performed.
    	; 检查是否有升级请求
        ;
        import  CheckForceUpdate
        bl      CheckForceUpdate
        cbz     r0, CallApplication	   ;结果为零则转移(只能跳到下一行)
    
        ;
        ; Configure the microcontroller.
        ;
    EnterBootLoader
        if      :def:_ENET_ENABLE_UPDATE
        import  ConfigureEnet
        bl      ConfigureEnet
        elif    :def:_CAN_ENABLE_UPDATE
        import  ConfigureCAN
        bl      ConfigureCAN
        elif    :def:_USB_ENABLE_UPDATE
        import  ConfigureUSB
        bl      ConfigureUSB
        else
        import  ConfigureDevice
        bl      ConfigureDevice
        endif
    
        ;
        ; Call the user-supplied initialization function if provided.
    	; 如果用户提供了初始化函数,则调用.
        ;
        if      :def:_BL_INIT_FN_HOOK
        import  $_BL_INIT_FN_HOOK
        bl      $_BL_INIT_FN_HOOK
        endif
    
        ;
        ; Branch to the update handler.
        ; 进入升级处理程序
    	;
        if      :def:_ENET_ENABLE_UPDATE
        import  UpdateBOOTP
        b       UpdateBOOTP
        elif    :def:_CAN_ENABLE_UPDATE
        import  UpdaterCAN
        b       UpdaterCAN
        elif    :def:_USB_ENABLE_UPDATE
        import  UpdaterUSB
        b       UpdaterUSB
        else
        import  Updater
        b       Updater
        endif
    
        ;
        ; This is a second symbol to allow starting the application from the boot
        ; loader the linker may not like the perceived jump.
        ;
        export StartApplication
    StartApplication
        ;
        ; Call the application via the reset handler in its vector table.  Load the
        ; address of the application vector table.
        ;
    CallApplication
        ;
        ; Copy the application's vector table to the target address if necessary.
        ; Note that incorrect boot loader configuration could cause this to
        ; corrupt the code!  Setting VTABLE_START_ADDRESS to 0x20000000 (the start
        ; of SRAM) is safe since this will use the same memory that the boot loader
        ; already uses for its vector table.  Great care will have to be taken if
        ; other addresses are to be used.
    	; 如果必要的话,复制应用程序的向量表到目标地址.
    	; 请注意,不正确的boot loader配置会破坏整个程序!设置VTABLE_START_ADDRESS为
    	; 0x2000 0000(从SRAM启动)也是可以的,因为这将和boot loader使用同样的内存
        ;
        if (_APP_START_ADDRESS != _VTABLE_START_ADDRESS) ;看应用程序的起始地址是否和应用程序的向量表存储地址相同
        movw    r0, #(_VTABLE_START_ADDRESS & 0xffff)
        if (_VTABLE_START_ADDRESS > 0xffff)
        movt    r0, #(_VTABLE_START_ADDRESS >> 16)
        endif
        movw    r1, #(_APP_START_ADDRESS & 0xffff)
        if (_APP_START_ADDRESS > 0xffff)
        movt    r1, #(_APP_START_ADDRESS >> 16)
        endif
    
        ;
        ; Calculate the end address of the vector table assuming that it has the
        ; maximum possible number of vectors.  We don't know how many the app has
        ; populated so this is the safest approach though it may copy some non
        ; vector data if the app table is smaller than the maximum.
    	; 计算向量表的结束地址,假设向量表有最大数目. 我们不知道应用程序使用了多少
    	; 向量表,但这样是最安全的
        ;
        movw    r2, #(70 * 4)
        adds    r2, r2, r0
    VectorCopyLoop
            ldr     r3, [r1], #4
            str     r3, [r0], #4
            cmp     r0, r2
            blt     VectorCopyLoop
        endif
    
        ;
        ; Set the vector table address to the beginning of the application.
    	; 将向量表重定位到应用程序开始处
        ;
        movw    r0, #(_VTABLE_START_ADDRESS & 0xffff)
        if (_VTABLE_START_ADDRESS > 0xffff)
        movt    r0, #(_VTABLE_START_ADDRESS >> 16)
        endif
        movw    r1, #(NVIC_VTABLE & 0xffff)	 			;向量表偏移寄存器
        movt    r1, #(NVIC_VTABLE >> 16)
        str     r0, [r1]
    
        ;
        ; Load the stack pointer from the application's vector table.
    	; 从应用程序向量表装载用户堆栈.
        ;
        if (_APP_START_ADDRESS != _VTABLE_START_ADDRESS)
        movw    r0, #(_APP_START_ADDRESS & 0xffff)
        if (_APP_START_ADDRESS > 0xffff)
        movt    r0, #(_APP_START_ADDRESS >> 16)
        endif
        endif
        ldr     sp, [r0]
    
        ;
        ; Load the initial PC from the application's vector table and branch to
        ; the application's entry point.
        ;
        ldr     r0, [r0, #4]
        bx      r0
    
    ;******************************************************************************
    ;
    ; The update handler, which gets called when the application would like to
    ; start an update.
    ; 升级处理函数,当用户程序想要开始升级时,调用此函数
    ;
    ;******************************************************************************
    UpdateHandler_In_SRAM
        ;
        ; Load the stack pointer from the vector table.
    	; 从boot loader向量表中装载堆栈指针
        ;
        if      :def:_FLASH_PATCH_COMPATIBLE
        movs    r0, #0x1000
        else
        movs    r0, #0x0000
        endif
        ldr     sp, [r0]
    
        ;
        ; Call the user-supplied low level hardware initialization function
        ; if provided.
    	; 调用用户提供的底层硬件初始化函数
        ;
        if      :def:_BL_HW_INIT_FN_HOOK
        bl      $_BL_HW_INIT_FN_HOOK
        endif
    
        ;
        ; Call the user-supplied re-initialization function if provided.
    	; 调用用户提供的初始化函数
        ;
        if      :def:_BL_REINIT_FN_HOOK
        import  $_BL_REINIT_FN_HOOK
        bl      $_BL_REINIT_FN_HOOK
        endif
    
        ;
        ; Branch to the update handler.
    	; 进入升级例程
        ;
        if      :def:_ENET_ENABLE_UPDATE
        b       UpdateBOOTP		   ;在bl_enet.c中
        elif    :def:_CAN_ENABLE_UPDATE
        import  AppUpdaterCAN
        b       AppUpdaterCAN
        elif    :def:_USB_ENABLE_UPDATE
        import  AppUpdaterUSB
        b       AppUpdaterUSB
        else
        b       Updater
        endif
    
    ;******************************************************************************
    ;
    ; The NMI handler.
    ; NMI异常服务例程,处理主振荡器失败
    ;
    ;******************************************************************************
        if      :def:_ENABLE_MOSCFAIL_HANDLER
    NmiSR_In_SRAM
        ;
        ; Restore the stack frame.
        ;
        mov     lr, r12
        stm     sp, {r4-r11}
    
        ;
        ; Save the link register.
        ;
        mov     r9, lr
    
        ;
        ; Call the user-supplied low level hardware initialization function
        ; if provided.
        ;
        if      :def:_BL_HW_INIT_FN_HOOK
        bl      _BL_HW_INIT_FN_HOOK
        endif
    
        ;
        ; See if an update should be performed.
        ;
        bl      CheckForceUpdate
        cbz     r0, EnterApplication
    
            ;
            ; Clear the MOSCFAIL bit in RESC.
            ;
            movw    r0, #(SYSCTL_RESC & 0xffff)
            movt    r0, #(SYSCTL_RESC >> 16)
            ldr     r1, [r0]
            bic     r1, r1, #SYSCTL_RESC_MOSCFAIL
            str     r1, [r0]
    
            ;
            ; Fix up the PC on the stack so that the boot pin check is bypassed
            ; (since it has already been performed).
            ;
            ldr     r0, =EnterBootLoader
            bic     r0, #0x00000001
            str     r0, [sp, #0x18]
            
            ;
            ; Return from the NMI handler.  This will then start execution of the
            ; boot loader.
            ;
            bx      r9
    
        ;
        ; Restore the link register.
        ;
    EnterApplication
        mov     lr, r9
    
        ;
        ; Copy the application's vector table to the target address if necessary.
        ; Note that incorrect boot loader configuration could cause this to
        ; corrupt the code!  Setting VTABLE_START_ADDRESS to 0x20000000 (the start
        ; of SRAM) is safe since this will use the same memory that the boot loader
        ; already uses for its vector table.  Great care will have to be taken if
        ; other addresses are to be used.
        ;
        if (_APP_START_ADDRESS != _VTABLE_START_ADDRESS)
        movw    r0, #(_VTABLE_START_ADDRESS & 0xffff)
        if (_VTABLE_START_ADDRESS > 0xffff)
        movt    r0, #(_VTABLE_START_ADDRESS >> 16)
        endif
        movw    r1, #(_APP_START_ADDRESS & 0xffff)
        if (_APP_START_ADDRESS > 0xffff)
        movt    r1, #(_APP_START_ADDRESS >> 16)
        endif
    
        ;
        ; Calculate the end address of the vector table assuming that it has the
        ; maximum possible number of vectors.  We don't know how many the app has
        ; populated so this is the safest approach though it may copy some non
        ; vector data if the app table is smaller than the maximum.
        ;
        movw    r2, #(70 * 4)
        adds    r2, r2, r0
    VectorCopyLoop2
            ldr     r3, [r1], #4
            str     r3, [r0], #4
            cmp     r0, r2
            blt     VectorCopyLoop2
        endif
    
        ;
        ; Set the application's vector table start address.  Typically this is the
        ; application start address but in some cases an application may relocate
        ; this so we can't assume that these two addresses are equal.
        ;
        movw    r0, #(_VTABLE_START_ADDRESS & 0xffff)
        if (_VTABLE_START_ADDRESS > 0xffff)
        movt    r0, #(_VTABLE_START_ADDRESS >> 16)
        endif
        movw    r1, #(NVIC_VTABLE & 0xffff)
        movt    r1, #(NVIC_VTABLE >> 16)
        str     r0, [r1]
    
        ;
        ; Remove the NMI stack frame from the boot loader's stack.
        ;
        ldmia   sp, {r4-r11}
    
        ;
        ; Get the application's stack pointer.
        ;
        if (_APP_START_ADDRESS != _VTABLE_START_ADDRESS)
        movw    r0, #(_APP_START_ADDRESS & 0xffff)
        if (_APP_START_ADDRESS > 0xffff)
        movt    r0, #(_APP_START_ADDRESS >> 16)
        endif
        endif
        ldr     sp, [r0, #0x00]
    
        ;
        ; Fix up the NMI stack frame's return address to be the reset handler of
        ; the application.
        ;
        ldr     r10, [r0, #0x04]
        bic     r10, #0x00000001
    
        ;
        ; Store the NMI stack frame onto the application's stack.
        ;
        stmdb   sp!, {r4-r11}
    
        ;
        ; Branch to the application's NMI handler.
        ;
        ldr     r0, [r0, #0x08]
        bx      r0
        endif
    
    ;******************************************************************************
    ;
    ; The default interrupt handler.
    ;
    ;******************************************************************************
    IntDefaultHandler
        ;
        ; Loop forever since there is nothing that we can do about an unexpected
        ; interrupt.
        ;
        b       .
    
    ;******************************************************************************
    ;
    ; Provides a small delay.  The loop below takes 3 cycles/loop.
    ; 提供一个小的延时函数. 循环一次需要3个时钟周期.
    ;
    ;******************************************************************************
        export  Delay
    Delay
        subs    r0, #1
        bne     Delay
        bx      lr
    
    ;******************************************************************************
    ;
    ; This is the end of the file.
    ;
    ;******************************************************************************
        align   4
        end

    1. 汇编文件正文的第一句

          include bl_config.inc

    包含bl_config.inc,这个文件是什么,从哪里来,有什么作用?再看bootloader工程Options---User---Run User Programs Before Build/Rebuild内的用户命令(见图2-2)又是什么?


    图2-2

             所有的一切,要从keil MDK的汇编器说起,在启动代码中要用到配置文件bl_config.h中定义的一些配置选项,但因为MDK汇编器不能通过C预处理器运行汇编代码,所以bl_config.h中的相关内容需要 转化为汇编格式并包含到MDK的启动代码中。这需要手动运行C预编译器进行格式转化。图2-2中红色部分圈出的内容正是为了完成这个转换。在点击Build/Rebuild编译按钮之后,会先运行图2-2指定的命令,再进行编译。先来分析一下这条命令:

                                    armcc --device DLM -o bl_config.inc -E bl_config.c

              这条命令的作用是将bl_config.c(包含bl_config.h文件)进行而且仅进行预编译处理,并生成bl_config.inc文件。

              armcc是Keil MDK提供的C编译工具,语法为:

                                     armcc [Options]  file1  file2  ...  file n

               介绍一下这里用到的Options选项:

                                       --device<dev>:设置目标的设备类型,DLM为Luminary的设备标识。

                                       -I<directory>   :目录列表

                                       -E                      :仅执行预处理

                                       -o<file>            :指定输出文件的名字

    2. 看一下目标板上电后启动代码的运行流程

              上电后程序先到Flash地址0x00处装载堆栈地址,这跟以前接触过的处理器不同,以前0x00处都是放置的复位处理代码,但Cortex M3内核却不是,0x00处是放置的堆栈地址,而不是跳转指令。

               堆栈设置完成后,跳转到Reset处理程序处,调用处理器初始化函数ProcessorInit,该函数将bootloader从Flash拷贝到SRAM,将.bss区用零填充并将向量表重映射到SRAM开始处。

               之后跳转到Reset_Handler_In_SRAM函数,在该函数中,如果用户提供了底层硬件初始化函数(在bl_config.h中使能),则调用这个函数。然后调用CheckForceUpdate函数,检查是否有升级请求。如果没有升级请求,跳转到CallApplication函数,在该函数中,将向量表重映射到应用程序开始处(这里为地址0x1000),装载用户程序堆栈地址,跳转到用户程序的Reset服务函数。

               如果调用CheckForceUpdate函数检测到有升级请求,则配置以太网,跳转到升级程序UpdateBOOTP处执行。

    3. 如何在用户程序中调用升级程序

              用户程序存在于Flash地址0x1000处,bootloader存放于Flash地址0x00处,并且用户程序在执行的时候已经将向量表重映射到了Flash地址0x1000处了,那么应用程序是如何调用位于bootloader中的升级程序呢?

            再看bootloader启动代码的中断向量表,在Flash地址的0x2C中存放的是CPU SVC异常服务跳转地址:

                        dcd     UpdateHandler                   ; Offset 2C: SVCall handler

            而bootloader正是用这个异常来处理升级请求的。那么,应用程序只要执行该地址处的跳转指令,就能进行一次程序升级,在应用程序中的swupdate.c中,使用了如下C代码来执行位于Flash地址0x2C内的跳转程序:

                        (*((void (*)(void))(*(unsigned long *)0x2c)))();  

             对C语言还没有入门的同学可能会比较的头痛,这像谜一样的语句是如何执行位于bootloader的SVC异常服务例程呢?还是分解一下吧:

                          (*(unsigned long *)0x2c):将0x2C强制转化为unsigned long类型指针,并指向该地址所在的数据;

                          void (*)(void)                      :函数指针,指针名为空,该函数参数为空,返回值为空

                         (void (*)(void))(*(unsigned long *)0x2c):将Flash地址0x2C中的内容强制转化为函数指针,该函数参数为空,返回值为空

                         (*((void (*)(void))(*(unsigned long *)0x2c)))();:调用函数,即开始从启动代码中的UpdateHandler标号处开始执行。











    展开全文
  • I/O设备与主机交换信息...CPU在启动I/O设备,不查询设备是否已准备就绪,继续执行原 来的程序,只是当I/O设备准备就绪并向CPU发出中断请求才给 予响应。 3、DMA: 主存与I/O设备之间有一条数据通道,主存与I/O设备

    I/O设备与主机交换信息共有5种方式(我简单记录前三种)

    1、程序查新方式
    2、程序中断方式
    3、直接存储器存取方式(DMA)
    4、I/O通道方式
    5、I/O处理机方式

    1、程序查询方式:

    程序查询方式是由CPU不断查询I/O设备是否已做好准备,从而控制I/O设备与主机交换信息。

    2、程序中断方式:

    CPU在启动I/O设备后,不查询设备是否已准备就绪,继续执行原来的程序,只是当I/O设备准备就绪并向CPU发出中断请求后才给予响应。

    3、DMA:

    主存与I/O设备之间有一条数据通道,主存与I/O设备交换信息的时,无需调用中断程序服务程序。若是出现DMA与CPU同时访问主存,CPU总是将总线的占有权让给DMA(因为DMA优先级更高),通常将 DMA的这种占有成为周期窃取/周期挪用(窃取时间一般为一个存储周期,会考的哟,嘿嘿嘿)

    其中程序查询、程序中断、DMA三者信息交换特点

    查询:CPU与设备串行工作,传送与主程序串行工作
    中断:CPU与设备并行工作,传送与主程序串行工作
    DMA: CPU与设备并行工作,传送与主程序并行工作

    其中主机与I/O设备传递数据时,采用DMA方式,CPU利用率最高,程序查询方式,CPU利用率最低。

    I/O采用统一编址,进行输入输出操作的指令是:访存指令
    I/O采用不统一编制,进行输入输出操作指令是:输入输出指令

    简单总结了,便于后期复习呢,寒假快来了,加油(>ω<)喵

    展开全文
  • 摘要:TMS320C62x和TMS320C67xDSPs提供了几种不同的启动模式,不同的启动模式决定了DSP复位的初始化以及代码装载方式。本文就TMS320C62xDSP的HPI启动模式进行详细的说明。 1绪言 TMS320C62x系列DSP中,主机口...
  • 记录一下,方便以后翻阅~ 主要内容: 1) STM32内部温度传感器概述;2 ) 相关实验代码解读。 实验功能:系统启动后...2.2 该温度传感器内部和ADCx_IN16输入通道相连接,此通道把传感器输出的电压转换成数字值; 2.3
  • gpio上拉失效问题

    千次阅读 2017-03-21 17:53:00
    通过当时记录的串口信息,最开始的异常出现sdk加载上,sdk加载失败内核打印localbus的错误,设备重启ubi挂载失败 /home下程序丢失 问题分析: P1020 cpu中的localbus是e500核与外围控制器的通道,与r
  • 我们对rabbimq进行性能测试时发现单个队列的情况下,无论怎么压qps都上不去,而此时服务器的cpu、网络、磁盘都没什么压力,但通过web管理界面看到发送通道不断的处于流控状态,显然流控机制被启动是性能不佳的最...
  • 63.计算机启动后找不到PCI声卡 64.主板PS/2口供电不足 65.主板与鼠标不兼容导致启动异常 66.病毒防护导致不能安装操作系统 67.硬件中断冲突 68.手动调节中断 69.启动时系统提示“UpdatingESCD” 1.3 内存故障 70....
  • • 通常按时间片分配:各个程序在CPU上执行的轮换时间。 • 操作系统:CTSS(M.I.T.)、Multics(computer community) • 特征: o 同时性 ♣ 也称多路性。若干用户同时与一台计算机相连,宏观上看各个用户在同时...
  • bios的设置,,,,,

    2010-04-23 19:39:52
    CPU Speed CPU速率:该选项显示启动后中央处理器的运行速率 Bus Speed 总线速率:显示处理器总线速率 Processor 0 ID 处理器ID:显示处理器所属种类及模型号 Clock Speed 时钟频率 Cache Size 缓存值:显示...
  • 图3中所示为电机控制的一个单周期时序,GPTA生成一相带死区的互补式PWM波形,PWM中点同时触发ADC0和ADC1的转换,ADC模块完成对应通道转换后启动CPU中断服务程序。 提供本开发板以为了让大家可以迅速提高学习本...
  • iSee视频监控 v5.2

    热门讨论 2013-02-20 14:34:39
    本系统可切换D1与CIF分辨率,切换分辨率设置主界面必须关 闭通道视频,重新打开通道视频,设置才能生效。 本系统主机工作于常温(-10_3℃~55_2℃)、清洁的环境,并且保持 良好的通风状态。 本系统软件属于我...
  • F-System 用于关闭可立即达到安全状态的控制过程。 换言之,F-System 用于控制一些过程,这些过程中立即停机不会对人身或环境造成危害。  ET 200pro 分布式 I/O 设备是 PROFIBUS DP/PROFINET IO 上的 DP 从...
  • Xen虚拟化技术

    2016-02-16 00:35:11
    , (1)基本机制和策略,即Xen半虚拟化技术的3大核心机制:与虚拟机启动和管理相关的信息页机制,与虚拟机特权级控制和通信相关的超级调用和事件通道机制,以及与虚拟机数据共享和传输相关的授权表机制。, (2)虚拟...
  • 系统 BIOS 已禁用内存单位错误 (SBE) 记录,重新引导系统之前,不会再记录更多的 SBE。“##”表示 BIOS 指示的 DIMM。 E2112 Mem Spare DIMM ## 系统 BIOS 确定内存中有太多错误,因此已将内存释放。“## & ##...
  • 例如想要查看硬盘的工作模式,只要双击相应的IDE通道即可弹出属性窗口,属性窗口中可轻检看到硬盘的设备类型及传送模式。这些都是开机画面所不能提供的。   需要注意的是Windows Xp之前的操作系统中所提供的...
  • linux 原生迅雷

    2015-10-21 10:47:43
    执行这条命令你当前目录下生成数个包,其中包括xware-desktop_??????.deb安装包。 安装 回到图形化界面,XwareDesktop的源代码目录的上级目录,你应该能找到名为xware-desktop_??????.deb的安装包文件, ...
  • 开启计算机或重新启动计算机,听见自检通过的声音,按 “Del”键就可以进入CMOS的设置界面;要注意的是,如果按得太晚,计算机将会启动系统,这时只有重新启动计算机了。大家可开机立刻按DEL键直到进入CMOS...
  • •设备管理:实质是对硬件设备的管理,其中包括对输入输出设备的分配、启动、完成和回收; •进程管理:又称处理机管理,实质上是对处理机执行“时间”的管理,即如何将CPU真正合理地分配给每个任务。 4...
  • 启动Tornado组件FTP Server,WFTPD窗口中选择菜单Security中的User/right..., 其 弹出窗口中选择New User...,根据提示信息输入登录用户名和口令,并且要指定下载文 件 VxWorks所在根目录。可能还需要选取主...
  • 一、申请短信通道,国内的短信通道很多,不同的通道速度不一样,我们申请时要一个基本原则就是速度要快,基本上要发送即接收了,客户不可能等的。国内调查发现,客户等网页打开的时间是最长不超过5秒,短信接收的...
  • 目前,比较流行的压缩软件共有40多种,每一种都有其各自的优点和不足,一般来说,TMPEGenc可以说是其中的佼佼者,压缩的画质所有的压缩软件中可以说是名列前茅,众多网友中的口碑相当的不错,缺点就是压缩的...
  • 目前,比较流行的压缩软件共有40多种,每一种都有其各自的优点和不足,一般来说,TMPEGenc可以说是其中的佼佼者,压缩的画质所有的压缩软件中可以说是名列前茅,众多网友中的口碑相当的不错,缺点就是压缩的...
  • 将消息转发给通道后,当接收到submitResponse后,通过response.getRequest()获取对应的request 。注意此时有两个msgID,一个是通道给你的msgID,一个是你给来源客户的。数据库里记录相关信息(至少包括消息来源...
  • 有的用户登录就长时间空闲,有可能导致安全上的问题,通过打开 /etc/profile 中 TMOUT 注释,将设置的时间到达自动logout用户 例如: export TMOUT=120 那么, 用户两分钟没有击键,将自动logout //AIX系统中如何...
  • 同时需要提醒,如果你的 redis 持久化手段中有 aof,那么 server 故障失效再次启动前,需要检测 aof 文件的完整性。 如果想启动AOF格式的数据持久化机制,那么就要关闭RDB机制, ##此选项为aof功能的开关,...
  • A: cFosSpeed 安装, 必须设定目前连线帐号启动 Traffic Shaping (红色勾预设启动), 至于 LAN 部分选择自动即可. 然后重新开机 (不确定, 我用的是 cFos)cFos 安装, 笔者将过去由 Windows XP 内建的 PPPoE ...

空空如也

空空如也

1 2 3
收藏数 45
精华内容 18
关键字:

在cpu启动通道后