1. 摘要

Cortex-M内核实现了一个高效异常处理模块,可以捕获非法内存访问和数个程序错误条件。本应用笔记从程序员角度描述Cortex-M Fault异常,并且讲述在软件开发周期中的Fault用法。

2. 简介

Cortex-M3(以下简称CM3)和Cortex-M4(以下简称CM4)内核的Fault异常可以捕获非法内存方法和非法编程行为。Fault异常能够检测到以下情况:

  • 总线Fault:在取址、数据读/写、取中断向量、进入/退出中断时寄存器堆栈操作(入栈/出栈)时检测到内存访问错误。

  • 存储器管理Fault:检测到内存访问违反了MPU定义的区域。

  • 用法Fault:检测到未定义的指令异常,未对齐的多重加载/存储内存访问。如果使能相应控制位,还可以检测出除数为零以及其他未对齐的内存访问。

  • 硬Fault:如果上面的总线Fault、存储器管理Fault、用法Fault的处理程序不能被执行(例如禁能了总线Fault、存储器管理Fault、用法Fault异常或者在这些异常处理程序执行过程中又出现了Fault)则触发硬Fault。

本应用笔记描述CM3和CM4的Fault异常用法。系统控制寄存器组中的寄存器可以控制Fault异常或者提供引发异常的原因信息。

更深入的文档

完整的异常描述见《Cortex - M3 Technical Reference Manual》或者《Cortex -M4 Technical Reference Manual》,这两本参考手册都可以在www.arm.com中找到。

另一个很好的参考书是由Joseph Yiu编写的《The Definitive Guide to the ARM Cortex-M3》 (这本书有中文版:宋岩译的《ARM Cortex-M3权威指南》)。

3. Cortex-M Fault异常和寄存器

每个符合CMSIS规范的编译器所提供的启动文件(Startup_device)都会定义好设备所有的异常和中断向量。这些向量表定义了异常或中断处理程序的入口地址。下表给出了一个典型的向量表,Fault异常向量用蓝色标注。

    :
    :
__Vectors DCD __initial_sp ; 栈顶
DCD Reset_Handler          ; 复位处理程序入口
DCD NMI_Handler            ; NMI 处理程序入口
DCD HardFaul t_Handler     ; 硬Fault处理程序入口
DCD MemManage_Handler      ; 存储器管理处理程序入口
DCD BusFault_Handler       ; 总线Fault 处理程序入口
DCD UsageFault_Handler     ; 用法 Fault 处理程序入口
DCD                       ; 保留
    :
    :

通常总是使能硬Fault异常的,硬Fault异常具有固定的优先级,并且优先级高于其它Fault异常以及中断,但低于NMI。硬Fault异常处理程序在以下情况下会被执行:其它非硬Fault异常(非硬Fault异常是指总线、存储器管理和用法Fault 异常,下同。)被禁能,并且这些Fault异常被触发;在执行一个非硬Fault异常处理程序中又产生非硬Fault异常。

所有非硬Fault具有可编程的优先级。当Cortex-M内核复位后,这些非硬Fault被禁能,你可以在应用软件中通过设置“系统Handler控制及状态寄存器(SHCSR)”来使能非硬Fault异常。这个寄存器属于系统控制模寄存器组(SCB)

3.1 Fault异常的控制寄存器

在这里有必要介绍一下系统控制模块寄存器组(SCB)的成员,这个寄存器组的定义可以在core_cm3.h文件中,该文件属于CMSIS Cortex-M3 内核外设接口抽象层的一部分(关于不清楚CMSIS的,可以自行查找资料)。定义如下:

1.定义系统控制寄存器组结构体

 /** @brief System Control Block (SCB) register structure definition */
 typedef struct
 {
     __I uint32_t CPUID;   /*!< Offset: 0x00 CPU ID Base Register*/
     __IO uint32_t ICSR;   /*!< Offset: 0x04 Interrupt Control State Register*/
    __IO uint32_t VTOR;   /*!< Offset: 0x08 Vector Table Offset Register*/
    __IO uint32_t AIRCR;  /*!< Offset: 0x0C Application Interrupt / Reset Control Register*/
    __IO uint32_t SCR;    /*!< Offset: 0x10 System Control Register*/
    __IO uint32_t CCR;    /*!< Offset: 0x14 Configuration Control Register*/
    __IO uint8_t SHP[]; /*!< Offset: 0x18 System Handlers Priority Registers (4-7, 8-11, 12-15) */
    __IO uint32_t SHCSR;  /*!< Offset: 0x24 System Handler Control and State Register */
    __IO uint32_t CFSR;   /*!< Offset: 0x28 Configurable Fault Status Register*/
    __IO uint32_t HFSR;   /*!< Offset: 0x2C Hard Fault Status Register*/
    __IO uint32_t DFSR;   /*!< Offset: 0x30 Debug Fault Status Register */
    __IO uint32_t MMFAR;  /*!< Offset: 0x34 Mem Manage Address Register*/
    __IO uint32_t BFAR;   /*!< Offset: 0x38 Bus Fault Address Register*/
    __IO uint32_t AFSR;   /*!< Offset: 0x3C Auxiliary Fault Status Register*/
    __I uint32_t PFR[];  /*!< Offset: 0x40 Processor Feature Register*/
    __I uint32_t DFR;     /*!< Offset: 0x48 Debug Feature Register*/
    __I uint32_t ADR;     /*!< Offset: 0x4C Auxiliary Feature Register*/
    __I uint32_t MMFR[]; /*!< Offset: 0x50 Memory Model Feature Register*/
    __I uint32_t ISAR[]; /*!< Offset: 0x60 ISA Feature Register*/
} SCB_Type;   

2. 定义系统控制寄存器组物理空间基地址

3. 定义指向系统控制寄存器组的指针

#define SCB ((SCB_Type *)SCB_BASE) /*!< SCB configuration struct * / 

通过以上三步,我们就可以使用结构体指针SCB来访问系统控制寄存器组的寄存器了,比如给系统控制寄存器SCR赋值:SCB->SCR=0xFF;

SCB->CCR寄存器控制除数为零和未对齐内存访问是否触发用法Fault。

SCB->SHCSR寄存器可用来使能非硬Fault异常。如果一个非硬Fault异常被禁能并且相关Fault发生,这时异常会升级为硬Fault。SCB->SHP寄存器组控制异常的优先级。

Fault异常控制寄存器列表:

地址/访问

寄存器

复位值

描述

0xE000ED14

RW 特权级

SCB->CCR

0x00000000

配置和控制寄存器:包含控制除数为零和未对齐内存访问是否触发用法Fault的使能位。

0xE000ED18

RW 特权级

SCB->SHP[12]

0x00

系统处理程序优先级寄存器:控制异常处理程序的优先级

0xE000ED24

RW特权级

SCB->SHCSR

0x00000000

系统处理程序控制和状态寄存器

3.1.1 SCB->CCR 寄存器

蓝色部分控制是否使能相应的用法Fault

名称

描述

[31:10]

-

保留

[9]

STKALIGN

表示进入异常时的堆栈对齐。

0:4字节对齐

1:8字节对齐

进入异常时,处理器使用压入堆栈的PSR位[9]来指示堆栈对齐。从异常返回时,这个堆栈位被用来恢复正确的堆栈对齐。

[8]

BFHFNMIGN

使能时,使得以优先级位-1或-2运行的处理程序忽略加载和存储指令引起的数据总线故障。它用于硬故障、NMI和FAULTMASK升级处理程序中:

0:加载和存储指令引起的数据总线故障会引起锁定。

1:以优先级-1或-2运行的处理程序忽略加载和存储指令引起的数据总线故障。

仅在处理程序和其数据处于绝对安全的存储器时将该位设为1。一般将该位用于探测系统设备和桥接器以检测并纠正控制路径问题。

[7:5]

-

保留

[4]

DIV_0_TRP

当处理器进行除0操作(SDIV或UDIV指令)时,会导致故障或停止。

0:不捕获除以零故障

1:捕获除以零故障。

当该位设为0时,除以零返回的商数为0。

[3]

UNALIGN_TRP

使能非对齐访问捕获:

0:不捕获非对齐半字和字访问

1:捕获非对齐半字和字访问。

如果该位设为1,非对齐访问产生一个使用故障。无论UNALIGN_TRP是否设为1,非对齐的LDM、STM、LDRD和STRD指令总是出错。

[2]

-

保留

[1]

USERSETM

PEND

使能对STIR的无特权软件访问。

0:禁能

1:使能

[0]

NONEBASE

THRDENA

指示处理器如何进入线程模式:

0:处理器仅在没有有效异常时才能够进入线程模式。

1:处理器可以从EXC_RETURN值控制下的任何级别进入线程模式

3.1.2 SCB->SHP 寄存器组

以下SCB->SHP 寄存器组的寄存器用来设置异常处理程序的优先级:

SCB->SHP[0]:存储器管理Fault的优先级

SCB->SHP[1]:总线Fault的优先级

SCB->SHP[2]:用法Fault的优先级

为了编程中断和异常的优先级,CMSIS提供了函数NVIC_SetPrioriity和NVIC_GetPriority。这两个函数也位于core_cm3.h中,源码为:

可以通过下面的示例代码更改异常优先级:

    :
    :
NVIC_SetPriority (MemoryManagement_IRQn, 0xF0);
NVIC_SetPri ority (BusFault_IRQn, 0x80);
NVIC_SetPriority ( UsageFault_IRQn, 0x10);
    :
UsageFault_prio = NVIC_GetPriority ( UsageFault_IRQn);
    :
    :   

3.1.3 SCB->SHCSR寄存器

与Fault异常相关位见下表的蓝色部分

名称

描述

[31:19]

-

保留

[18]

USGFAULTENA

用法Fault使能位,设为1时使能

[17]

BUSFAULTENA

总线Fault使能位,设为1时使能

[16]

MEMFAULTENA

存储器管理Fault使能位,设为1使能

[15]

SVCALLPENDED

SVC调用挂起位,如果异常挂起,该位读为1

[14]

BUSFAULTPENDED

总线Fault异常挂起位,如果异常挂起,该位读为1

[13]

MEMFAULTPENDED

存储器Fault故障异常挂起位,如果异常挂起,该位读为1

[12]

USGFAULTPENDED

用法Fault异常挂起位,如果异常挂起,该位读为1

[11]

SYSTICKACT

SysTick 异常有效位,如果异常有效,该位读为1

[10]

PENDSVACT

PendSV异常有效位,如果异常有效,该位读为1

[9]

-

保留

[8]

MONITORACT

调试监控有效位,如果调试监控有效,该位读为1

[7]

SVCALLACT

SVC调用有效位,如果SVC调用有效,该位读为1

[6:4]

-

保留

[3]

USGFAULTACT

用法Fault异常有效位,如果异常有效,该位读为1

[2]

-

保留

[1]

BUSFAULTACT

总线Fault异常有效位,如果异常有效,该位读为1

[0]

MEMFAULTACT

存储器管理Fault异常有效位,如果异常有效,该位读为1

尽管可以写SCB->SHCSR寄存器的所有位,但建议软件只写异常使能位。下面的例子用于使能所有非硬Fault(存储器管理Fault、总线Fault、用法Fault异常):

SCB - >SHCSR |= 0x00007000; /*enable Usage Fault, Bus Fault, and MMU Fault*/   

注:要包含core_cm3.h头文件。

3.2 Fault异常的状态和地址寄存器

Fault状态寄存器组(SCB->CFSR和SCB->HFSR)和Fault地址寄存器组(SCB->MMAR和SCB->BFAR)包含Fault的详细信息以及异常发生时访问的内存地址。

地址/访问

寄存器

复位值

描述

0xE000ED28

RW 特权级

SCB->CFSR

0x00000000

可配置Fault状态寄存器:包含指示存储器管理Fault、总线Fault或用法Fault的原因位

0xE000ED2C

RW 特权级

SCB->HFSR

0x00000000

硬Fault状态寄存器:包含用于指示硬Fault原因位。

0xE000ED34

RW特权级

SCB->MMFAR

不可知

存储器管理Fault地址寄存器:包括产生存储器管理Fault的位置的地址

0xE000ED38

RW特权级

SCB->BFAR

不可知

总线Fault地址寄存器:包括产生总线Fault的位置的地址

3.2.1 SCB->CFSR寄存器

SCB->CFSR寄存器的位分配表:

bit31                                                                           bit16

bit15                   bit8

bit7                    bit0

用法Fault状态寄存器(UFSR)

总线Fault状态寄存器(BFSR)

存储器管理Fault状态寄存器(MMFSR)

SCB->CFSR寄存器可以被分成三个组:

存储器管理Fault 状态寄存器:地址0x0xE000ED28,可以按字节访问

总线Fault状态寄存器:地址0xE000ED29,可以按字节访问

用法Fault状态寄存器:地址0xE000ED2A,可以按半字访问

3.2.1.1 存储器管理Fault状态寄存器MMFSR:指示存储器访问Fault的原因

名称

描述

[7]

MMARVALID

存储器管理Fault地址寄存器(MMAR)有效标志:

0:MMAR中的值不是一个有效Fault地址

1:MMAR中保留一个有效Fault地址。

如果发生了一个存储器管理Fault,并由于优先级的原因升级成一个硬Fault,那么硬Fault处理程序必须将该位设为0。

[6:5]

-

保留

[4]

MSTKERR

进入异常时的入栈操作引起的存储器管理Fault:

0:无入栈Fault

1:进入异常时的入栈操作引起了一个或一个以上的访问违犯。

当该位设为1时,依然要对SP进行调节,并且堆栈的上下文区域的值可能不正确。处理器没有向MMAR中写入Fault地址。

[3]

MUNSTKERR

异常返回时的出栈操作引起的存储器管理Fault:

0:无出栈Fault

1:异常返回时的出栈操作已引起一个或一个以上的访问违犯.

该Fault与处理程序相连,这意味着当该位为1时,原始的返回堆栈仍然存在。

处理器不能对返回失败的SP进行调节,并且不会执行新的存储操作。处理器没有向MMAR中写入Fault地址。

[2]

-

保留

[1]

DACCVIOL

数据访问违犯标志:

0:无数据访问违犯Fault

1:处理器试图在不允许执行操作的位置上进行加载和存储。

当该位为1时,异常返回的压入堆栈的PC值指向出错指令。处理器已在MMAR中加载了目标访问的地址。

[0]

IACCVIOL

指令访问违犯标志:

0:无指令访问违犯错误

1:处理器试图从不允许执行操作的位置上进行指令获取。

即使MPU被禁能,这一故障也会在XN(CM3内核的0xE0000000~0xFFFFFFFF区域)区寻址时发生。

当该位为1时,异常返回的压入堆栈的PC值指向出错指令。处理器没有向MMAR中写入故障地址。

3.2.1.2 总线Fault状态寄存器BFSR:指示总线访问Fault原因

名称

描述

[7]

BFARVALID

总线Fault地址寄存器(BFAR)有效标志:

0:BFAR中的值不是有效故障地址

1:BFAR中保留一个有效故障地址。

在地址已知的总线故障发生后处理器将该位设为1。该位可以被其他Fault清零,例如之后发生的存储器管理Fault。

如果发生总线Fault,并由于优先级原因升级为一个硬Fault,那么硬Fault处理程序必须将该位设为0。

[6:5]

-

保留

[4]

STKERR

进入异常时的入栈操作引起的总线Fault:

0:无入栈故障

1:进入异常时的入栈操作已引起一个或一个以上的总线故障。

当处理器将该位设为1时,依然要对SP进行调节,并且堆栈的上下文区域的值可能不正确。处理器没有向BFAR中写入Fault地址。

[3]

UNSTKERR

异常返回时的出栈操作引起的总线Fault:

0:无出栈Fault

1:异常返回时的出栈操作已引起一个或一个以上的总线Fault。

该Fault与处理程序相连, 这意味着当处理器将该位设为1时,原始的返回堆栈仍然存在。处理器不能对返回失败的SP进行调节,并且不会执行新的存储操作,也未向BFAR中写入Fault地址。

[2]

IMPRECISERR

非精确数据总线错误:

0:无非精确数据总线错误

1:已发生一个数据总线错误,但是堆栈帧中的返回地址与引起错误的指令无关。

当处理器将该位设为1时,不向BFAR中写入Fault地址。

这是一个异步Fault。因此,如果在当前进程的优先级高于总线Fault优先级时检测到该Fault,总线Fault被挂起并仅在处理器从所有更高优先级进程中返回时开始变为有效。如果在处理器进入非精确总线Fault的处理程序前发生一个精确Fault,那么处理程序同时对IMPRECISERR 和其中一个精确Fault状态位进行检测,判断它们是否置位为1。

[1]

PRECISERR

精确数据总线错误:

0:非精确数据总线错误

1:已发生一个数据总线错误,且异常返回的压入堆栈的PC值指向引起Fault的指令。

当处理器将该位设为1时,向BFAR中写入Fault地址。

[0]

IBUSERR

指令总线错误:

0:无指令总线错误

1:指令总线错误。

处理器检测到预取指令时的指令总线错误,但仅在其试图签发Fault指令时才将IBUSERR 标志设为1。

当处理器将该位设为1时,不向BFAR中写入Fault地址。

3.2.1.3 用法Fault状态寄存器UFSR:指示产生用法Fault的原因

名称

描述

[15:10]

-

保留

[9]

DIVBYZERO

0:无除以零Fault或除以零捕获未使能

1:处理器已执行SDIV或UDIV指令(除以零)。

当处理器将该位设为1时,异常返回的压入堆栈的PC值指向执行除以零的指令。

注:通过将CCR中的DIV_0_TRP位设为1使能除以零捕获,默认是不使能的。

[8]

UNALIGNED

0:无非对齐访问Fault,或非对齐访问捕获未使能

1:处理器已进行了一次非对齐的存储器访问。

注:通过将CCR中的UNALIGN_TRP位设为1来使能非对齐访问捕获,默认是不使能的。非对齐的LDM、STM、LDRD和STRD指令总是出错,与UNALIGN_TRP的设置无关。

[7:4]

-

保留

[3]

NOCP

无协处理器用法Fault。处理器不支持协处理器指令:

0:试图访问一个协处理器未引起用法Fault

1:处理器已试图访问一个协处理器。

[2]

INVPC

EXC_RETURN的无效PC加载引起的无效PC加载用法Fault:

0:没有发生无效PC加载用法Fault

1:处理器已试图将EXC_RETURN非法载入PC,作为一个无效的上下文或一个无效的EXC_RETURN值。

当该位被设为1时,异常返回的压入堆栈的PC值指向尝试执行非法PC加载的指令。

[1]

INVSTATE

无效状态用法Fault:

0:未发生无效状态用法Fault

1:处理器已试图执行一个非法使用EPSR的指令。

当该位设为1时,异常返回的压入堆栈的PC值指向一个尝试非法使用EPSR的指令。

如果一个未定义的指令使用了EPSR,则该位不被置位为1。

[0]

UNDEFINSTR

未定义的指令用法Fault:

0:无未定义的指令用法Fault

1:处理器已试图执行一个未定义的指令。当该位设为1时,异常返回的压入堆栈的PC值指向未定义的指令。

未定义的指令是一条不能被处理器译码的指令。

3.2.2 SCB->HSFR寄存器

SCB->HSFR寄存器提供关于激活硬Fault处理程序的事件的信息,写入1清零相应位。

名称

描述

[31]

DEBUGEVT

硬Fault因调试事件产生,保留供调试使用。对寄存器执行写操作时,必须向该位写入0;否则,该行为不可预知。

[30]

FORCED

指示硬Fault是否由上访产生,非硬Fault的处理程序无法执行时,会上访成硬Fault。

0:硬Fault不是因为非硬Fault上访产生的

1:硬Fault是通过非硬Fault上访产生的。

当该位设为1时,硬Fault处理程序必须读其他Fault状态寄存器以找出Fault原因。

[29:2]

-

保留

[1]

VECTTBL

指示一个在异常处理过程中读向量表而引起的总线Fault:

0:读向量表未引起总线Fault

1:读向量表引起了总线Fault。

这一错误通常情况下都由硬Fault处理程序来处理。

[0]

-

保留

3.2.3 SCB->MMFAR和SCB->BFAR寄存器

为了确定产生了哪个Fault异常以及什么原因引起的Fault异常,你需要检测Fault状态寄存器。

如果SCB->CFSR寄存器的BFARVALID位有效(为1),则SCB->BFAR寄存器的值表示引起总线Fault的内存地址。

如果SCB->CFSR寄存器的MMFARVALID位有效(为1),则SCB->MMFAR寄存器的值表示引起存储器管理Fault的内存地址。

参考资料:

1. ARM Cortex-M3权威指南                Joseph Yiu著   宋岩译

2. Application Note 209   Using Cortex-M3 and Cortex -M4 Fault exceptions         Copyright 2010 ARM

3. LPC178x/7x用户手册                       NXP

Cortex-M3和Cortex-M4 Fault异常应用之一 ----- 基础知识的更多相关文章

  1. Cortex-M3和Cortex-M4 Fault异常应用之二 ----- Fault处理函数的实现

    在项目处于调试期间,Fault处理程序可能只是一个断点指令,调试器遇到这个指令后停止程序的运行.默认情况下,由于非硬Fault被禁能,所有发生的非Fault都会上访成硬Fault,因此只要在硬Faul ...

  2. ARM 架构、ARM7、ARM9、STM32、Cortex M3 M4 、51、AVR 之间有什么区别和联系?(转载自知乎)

    ARM架构:  由英国ARM公司设计的一系列32位的RISC微处理器架构总称,现有ARMv1~ARMv8种类. ARM7:       一类采用ARMv3或ARMv4架构的,使用冯诺依曼结构的内核. ...

  3. 【ARM-Linux开发】ARM7 ARM9 ARM Cortex M3 M4 有什么区别

    ARM7 ARM9 ARM Cortex M3 M4 区别 arm7 arm9 可以类比386和奔腾, 不同代,arm9相比arm7指令集和性能都有所增强,arm7和arm9都有带mmu和无mmu的版 ...

  4. 【freertos】002-posix模拟器设计与cortex m3异常处理

    目录 前言 posix 标准接口层设计 模拟器的系统心跳 模拟器的task底层实质 模拟器的任务切换原理 cortex M3/M4异常处理 双堆栈指针 双操作模式 栈帧 EXC_RETURN 前言 如 ...

  5. ARM Cortex M3(V7-M架构)硬件启动程序 一

    Cortex-m3启动代码分析笔记 启动代码文件名是STM32F10X.S,它的作用先总结下,然后再分析. 启动代码作用一般是: 1)堆和栈的初始化: 2)中断向量表定义: 3)地址重映射及中断向量表 ...

  6. Implementation of Serial Wire JTAG flash programming in ARM Cortex M3 Processors

    Implementation of Serial Wire JTAG flash programming in ARM Cortex M3 Processors The goal of the pro ...

  7. ARM Cortex M3系列GPIO口介绍(工作方式探讨)

    一.Cortex M3的GPIO口特性    在介绍GPIO口功能前,有必要先说明一下M3的结构框图,这样能够更好理解总线结构和GPIO所处的位置. Cortex M3结构框图     从图中可以看出 ...

  8. STM32学习之路入门篇之指令集及cortex——m3的存储系统

    STM32学习之路入门篇之指令集及cortex——m3的存储系统 一.汇编语言基础 一).汇编语言:基本语法 1.汇编指令最典型的书写模式: 标号 操作码        操作数1, 操作数2,... ...

  9. STM32 F4xx Fault 异常错误定位指南

    STM32 F407 采用 Cortex-M4 的内核,该内核的 Fault 异常可以捕获非法的内存访问和非法的编程行为.Fault异常能够检测到以下几类非法行为: 总线 Fault: 在取址.数据读 ...

随机推荐

  1. JQ----树杈型导航

    简单的做了一个树杈型的导航结构如下所示: 废话不多说,上代码: HTML: <div class="wrapper"> <div class="tabt ...

  2. Vue.js 学习示例

    本篇和大家分享的是学习Vuejs的总结和调用webapi的一个小示例:快到年底了争取和大家多分享点东西,希望能对各位有所帮助:本章内容希望大家喜欢,也希望各位多多扫码支持和推荐谢谢: » Vuejs ...

  3. 从setTimeout到浏览器线程机制

    看高性能javascipt 这本书时,看到这么一句话: Putting scripts at the top of the page in this way typically leads to a ...

  4. 在WPF中自定义你的绘制(四)

    原文:在WPF中自定义你的绘制(四)                                   在WPF中自定义你的绘制(四)                                 ...

  5. INNO SETUP 获得命令行参数

    原文 http://www.cnblogs.com/ahuo/archive/2009/07/30/1534998.html );           Result := CmdLine;       ...

  6. 一张图片入门Python

    一张图片入门Python 之前已有别人整理了,一张图入门Python,快速了解各种基本的语法. 英文版: 图 5.1. Quick Python Script Explanation 中文版: 图 5 ...

  7. Java的Git管理工具Gitblit

    From:http://www.oschina.net/p/gitblit Gitblit 是一个纯 Java 库用来管理.查看和处理 Git 资料库.相当于 Git 的 Java 管理工具. 下载地 ...

  8. Linux 零碎知识点

    ln -s ../libs/ libs 在当前目录下建立一个符号链接文件libs,使它指向上一层目录的libs文件夹 关于su和su -的区别切换用户是可以使用su tom或者su - tom来实现, ...

  9. 使用StoryBoard设置Scrollview的横向滚动不用一行代码

    1).创建一个空工程Single类型的工程,然后打开故事版(StoryBoard)在ViewController上添加scrollview 2).然后对scrollview添加约束,上下左右全部都是0 ...

  10. Android解决异常apk on device '0292bea1': Unable to open sync connection!

    方式一:使用手机管家(如腾讯手机管家,只要拖动发射火箭就行了)清理一下正在运行的后台程序. 方式二:把USB数据线拔了重新链接. 方法三:找到USB调试,关掉USB调试,然后重新开启.在设置 --&g ...