본문 바로가기

임베디드/ARM

Core Register & CMSIS

Core Register & CMSIS

Cortex-Mx Core Register

Contents

1. Non-memory mapped register, Memory-mapped register

2. 모드 변경 - Privileged, Unprivileged


1. Non-memory mapped register , Memory mapped register

- Core 레지스터는 memory map에서 주소를 가지고 있지 않다. 따라서, 접근해서 값을 읽을 수 있는 개념이 아니다.

- 해당 레지스터의 값을 읽고, 쓰려면 메모리 맵에 접근하는 것이 아닌 assembly instruction을 이용해야 한다.

- CMSIS는 assembly instruction를 포함한다.

CMSIS Register 예시

- Memory mapped register는 두 종류로 나뉜다. (Processor Register / Vender Specific Register)

 : Processor Register는 칩 벤더사에서 임의로 바꿀 수 없으며, Vender Specific Register는 칩 벤더 마다 설계 방향에 따라 다를 수 있다.

 

2. 모드 변경 - Privileged, Unprivileged

Privileged IPSR > 0 OR CONTROL.nPRIV = 0 Core 레지스터의 IPSR이 
Thread 모드 아니거나,
CONTROL.nPRIV가 Privileged
Unprivileged IPSR = 0 AND CONTROL.nPRIV = 1 Core 레지스터의 IPSR이
Thread 모드 이면서,
CONTROL.nPRIV가 Unprivileged

- Core레지스터의 IPSR이 0 일때는 Thread 모드이고, 그외에는 Handler 모드이다.

- CONTROL레지스터의 nPRIV 영역이 1 이면 Unprivileged 이고, 0이면 Privileged 이다.

- Unprivileged 일때는 Thread 모드 이면서, CONTROL.nPRIV = 1 이어야 한다.

- Privileged 일때는 Handler 모드이거나, CONTROL.nPRIV = 0 이어야 한다.

 

모드 변경시 레지스터 접근을 위해 CMSIS를 이용할 수 있다.

- 레벨 변경시에는 Privileged --> Unprivileged로 가능하다.

- 그 반대는 불가능 하다. 그도 그럴것이 Unprivileged 레벨에서는 레벨 변경이 불가능 하기 때문이다.

/**************************************************************************//**
Purpose:        Sets the CPU to the given privilege level.
Description:    Is used to set the CPU back to unprivileged level.
@param          newPrivLevel  New privileged level
@note           Cannot be used to switch from unprivileged to privileged level.
******************************************************************************/
void Kernel_SetPrivilegedLevel(ARM_CPU_MODE newPrivLevel)
{
    CONTROL_Type regCONTROL;
    IPSR_Type    regIPSR;

    regCONTROL.w = __get_CONTROL();  // CONTROL 레지스터 값 읽어온다.
    regIPSR.w = __get_IPSR();        // IPSR 레지스터 값 읽어온다.

    if ( regIPSR.w != 0                       // handler mode 이거나
        || regCONTROL.b.nPRIV == Privileged ) // privileged 레벨 이라면
    {
        // set Unprivileged level only if called in privileged or handler mode
        regCONTROL.b.nPRIV = newPrivLevel;
        __set_CONTROL(regCONTROL.w);  //CONTROL 레지스터에 값을 쓴다.
    }
}

Privileged 레벨로 변경하기 위한 방법으로 미리 정의된 서비스 함수(svc)를 이용하는 방법이 있으며,

아래와 같이 구현할 수 있다.

/**************************************************************************//**
Purpose:        Raises the CPU to privileged mode.
Description:    Triggers an SVC call to raise the CPU to privileged mode.
@return         @ref ARM_CPU_MODE  Returns the previously
******************************************************************************/
ARM_CPU_MODE Kernel_RaisePrivilegedLevel(void)
{
    CONTROL_Type regCONTROL;
    IPSR_Type    regIPSR;
    ARM_CPU_MODE oldPrivLevel;

    regCONTROL.w = __get_CONTROL();  // CONTROL 레지스터 값 읽어온다.
    regIPSR.w = __get_IPSR();        // IPSR 레지스터 값 읽어온다.
    oldPrivLevel = (ARM_CPU_MODE)regCONTROL.b.nPRIV;  // 현재  ARM CPU mode

    if ( regIPSR.w != 0 )  // Handler 모드라면, 이미 Privileged 레벨이다.
    {
        // bug check here, function is not intended to be called in handler mode
        PANIC();
    }

    if ( regCONTROL.b.nPRIV == Unprivileged ) //Unprivileged 레벨이라면
    {
        // 서비스 함수를 이용해 레벨 변경이 가능하다.
        Kernel_SetPrivilegedLevelSvc((int)&Kernel_SetPrivilegedLevel, Privileged );
    }

    return oldPrivLevel;
}

 

2. 모드 변경 - MRS, MSR Instruction

Previledge 모드로 변경하는 다른 방법이다.

void change_access_level_unpriv(void)
{
    //read
    __asm volatile("MRS R0, CONTROL");
    //modify
    __asm volatile("ORR R0, R0, #0x01");
    //write
    __asm volatile("MSR CONTROL, R0");
}

[Reference]

www.udemy.com/course/embedded-system-programming-on-arm-cortex-m3m4/


(참고용)

core_cm3.h

/**
  \brief  Union type to access the Control Registers (CONTROL).
 */
typedef union
{
  struct
  {
    uint32_t nPRIV:1;         /*!< bit:      0  Execution privilege in Thread mode */
    uint32_t SPSEL:1;         /*!< bit:      1  Stack to be used */
    uint32_t _reserved1:30;   /*!< bit:  2..31  Reserved */
  } b;                        /*!< Structure used for bit  access */
  uint32_t w;                 /*!< Type      used for word access */
} CONTROL_Type;


/**
  \brief  Union type to access the Interrupt Program Status Register (IPSR).
 */
typedef union
{
  struct
  {
    uint32_t ISR:9;           /*!< bit:  0.. 8  Exception number */
    uint32_t _reserved0:23;   /*!< bit:  9..31  Reserved */
  } b;                        /*!< Structure used for bit  access */
  uint32_t w;                 /*!< Type      used for word access */
} IPSR_Type;

 

Framework.h

/** @brief enumeration reflecting the ARM CPU modes
 **
 ** The CONTROL register controls the stack used and the privilege level for
 ** software execution when the processor is in Thread mode. See also the register
 ** summary the ARM user guide.
 **/
typedef enum _arm_cpu_mode_
{
    Privileged   = 0,
    Unprivileged = 1
} ARM_CPU_MODE;

 

반응형

'임베디드 > ARM' 카테고리의 다른 글

000_ARM Contents  (0) 2021.03.20
Cortex-M3/M4 Utils  (0) 2021.03.20
ARM 교육 받을 수 있는 곳  (0) 2021.02.13
ARM Product 관련 문서 번역(Cortext-M3)  (0) 2020.12.20
ARM ToolChain 관련 문서  (0) 2020.10.06