Core Register & CMSIS
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를 포함한다.
- 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 |