본문 바로가기
Robot/MCU

Cortex-M3 System Timer를 이용한 Delay함수 구현

by lifeseed 2013. 8. 30.
1. Cortex-M3 Private Peripheral
CortexM3는 기본적으로 내부 Peripheral 을 가지고 있습니다.
Memory Map을 살펴보면 0xE000 0000 ~ 0xE00F FFFF  의 1M영역이 Private Peripheral을 위해 할당되어 있습니다.
ARM에서 제공하는 Cortex-M3 Devices Generic User Guide 4장에 Detail 한 설명이 나와 있습니다.
 
다음은 Cortex-M3가 제공하는 Peripheral Bus Map 입니다.
 Address  Core Peripheral   Description 
 0xE000E008 - 0xE000E00F  System Control block  Table 4-12 on page 4-11
 0xE000E010 - 0xE000E01F  System Timer  Table 4-12 on page 4-11 
 0xE000E100 - 0xE000E4EF   Nested Vectored Interrupt Controller  Table 4-12 on page 4-11
 0xE000ED00 - 0xE000ED3F  System control block  Table 4-12 on page 4-11 
 0xE000ED90 - 0xE000ED93  MPU Type Register  Reads as zero, indication MPU is not implemented
 0xE000ED90 - 0xE000EDB8  Memory Protection Unit  Table 4-38 on page 4-38
 0xE000EF00 - 0xE000EF03  Nested Vectored Interrupt Controller  Table 4-2 on page 4-3
 
우리는 여기서 Sytem Timer에 대해 살펴 보려고 합니다.


2. Cortex-M3 System Timer
System Timer Registers Summary  (Table 4-32)
Address Name Type Required
privilege
Description
0xE000E010 SYST_CSR RW privileged SysTick Control and Status Register
0xE000E014 SYST_RVR RW privileged SystTick Reload Value Register on page 4-34
0xE000E018 SYST_CVR RW privileged SystTick Current Value Register on page 4-35
0xE000E01C SYST_CALIB RO privileged SystTick Calibration Value Register on page 4-35
 
각 Register에 대해 살펴보면 다음과 같습니다.
1) SYST_CSR : Control & Status Register 
17~31 Bit  : Reserved
16 Bit : COUNTFLAG  - Timer의 Count가 0이되면 1로 설정 됩니다.
15~3 Bit : Reserved
2 Bit : CLKSOURCE  - 0 이면 외부 Clock을 1 이면 내부 Clock을 사용하게 됩니다.
1 Bit : TICKINT
    - 1 로 설정될 경우 Timer 만료시 인터럽트가 발생되어, Vector Table의 16번째 정의된 SystickHandler 가 호출됩니다.
0 Bit : ENABLE - 1 일경우 Timer가 Enable됩니다.
 
2) SYST_RVR : Reload Value Register
23~0 Bit 의 24bit Count Value입니다. Timer가 시작될때의 초기 Count 값입니다.
 
3) SYST_CVR : Current Value Register
23~0 Bit 의 24bit Count Value입니다. Timer가 동작 중일 때의 현재  Count 값입니다.
이 값이 0이 될경우 Timer가 SYST_CSR의 COUNTFLAG가 1이 되며, Interrupt가 Enable되어 있을 경우 Interrupt가 발생됩니다.
 
4) SYST_CALIB : Calibration Value Register
읽기 전용 Register이며, Timer의 세부적인 성격을 확인할 수 있습니다.
자세한 내용을 알고 싶으면 Cortex-M3 Devices Generic User Guide 참조하시기 바랍니다.

3. Delay 함수 구현
이제 delay 함수를 구현해보고자 합니다.
다음의 조건으로 함수가 구현되었습니다.
1) 8M 외부 클럭을 이용함
2) msec 단위로 delay를 수행함
3) Interrupt를 사용하지 않고 polling 모드로 wating함
 
typedef struct
{
  __IO uint32_t CTRL;        /*!< Offset: 0x000 (R/W)  SysTick Control and Status Register */
  __IO uint32_t LOAD;       /*!< Offset: 0x004 (R/W)  SysTick Reload Value Register       */
  __IO uint32_t VAL;         /*!< Offset: 0x008 (R/W)  SysTick Current Value Register      */
  __I  uint32_t CALIB;       /*!< Offset: 0x00C (R/ )  SysTick Calibration Register        */
} SysTick_Type;
#define SysTick             ((SysTick_Type   *)   0xE000E010)   /*!< SysTick configuration struct       */
#define HSE_VALUE       8000000
void mdelay (unsigned int msec)
{
    unsigned int temp;
    SysTick->LOAD=(uint32_t)msec*(HSE_VALUE/1000);
    SysTick->VAL =0x00;  // clear Count flag
    SysTick->CTRL=0x01;
    do
    {
        temp=SysTick->CTRL;
    }
    while((temp&0x01)&&!(temp&(1<<16))); // wait Count flag set
    SysTick->CTRL=0x00;
    SysTick->VAL =0X00;
}

typedef struct 는 CMSIS Library에 구현된 구조체를 이용하였습니다.

usec단위로 delay함수를 구현하고자 할 경우 LOAD 값을 usec*(HSE_VALUE/1000000 ) 로 수정하면 됩니다.

 

이상 간단하게나마 CM3의 Polling Mode Timer동작을 살펴 보았습니다.

각자 필요하신 분은 코딩에 참조하시면 될 듯합니다.
 
[참고자료]
[1]  Cortex-M3 Devices Generic User Guide
[2]  CMSIS Library