본문 바로가기

Architecture/LM3S8962

[LM3S8962] Bit band, 레지스터 접근법

Cortex-M3에서 제공되는 Bit Banding 기능을 알아보고 기존의 방식과 속도면에서 어떤 차이점이 있는지 어셈크드를 통해 알아보았다.

1. Bit Banding이란?
  Bit banding은 간단하게 말하면 bit operation을 빠르게 해줄 수 있는 방법을 제공,
 즉 어떤 레지스터의 특정 비트를 1이나 0으로 변경하는 것을 매우 빠르고 쉽게 해줄 수 있는 것.
 이것이 가능한 것은 하드웨어적으로 어떤 특정 비트를 각각 어떤 특정 어드레스에 할당을 해놓고 있는 것이다.







 SRAM부분과 Peripheral 부분에 이상한 형태의 내용이 있는 것이 보인다. bit band region  이라는 것이 있고, bit band alias라는 내용이 있다. 각각 공간은 1MB와 32MB가 잡혀 있다. alias영역에 쓰이는 행위는 그에 상응하는 bit-band영역의 특정 비트에 영향을 주는 것이다.
 0x20000000 번지의 1번 비트가 어떻게 되는지 생각해보면 이것은 0x22000004 번지에 할당되어있다. 무조건 32비트(4바이트)로 증가되기 때문에 하나의 증가가 0x22000004 번지로 4만큼 증가된 것이다. 0x22000004 번지는 0x20000000 번지의 1번 비트와 연결되어 있다.
 그럼 0x20000004 번지가 0x20000004 번지의 0번 비트를 변화시킬 수 있는 것이다. 0x20000004 번지의 1번 비트는 0x22000084 번지이다.

bit_word_addr = bit_band_base + (byte_offset * 32) + (bit_number * 4)

 이것은 alias영역의 주소값을 찾아주는 식이다. bit_band_base는 위 예제에서는 0x22000000이 될 것이고, peripheral register의 경우는 0x42000000이 될 것이다. 위의 예를 보면 4가 된다. 마지막으로 bit_number는 우리가 원하는 그 비트 번호가 된다. 비트 1이라면 1이 될 것이다.

다시 예를 들어 설명해 보면, 만약 0x20000300의 비트 2번을 처리할 수 있는 alias 주소값을 알고 싶을 경우
0x22996008 = 0x22000000 + (0x300*32) + (2*4) 이다.

Cortex-M3는 이런 bit-band 영역이 두 개 존재한다. peripheral register들과 SRAM 영역이다.





코드화 하면 다음과 같다.

#define HWREG(x)          (*((volatile unsigned long *)(x)))
#define HWREGH(x)        (*((volatile unsigned short *)(x)))
#define HWREGB(x)         (*((volatile unsigned char *)(x)))
#define HWREGBITW(x, b)                                                       
        HWREG(((unsigned long)(x) & 0xF0000000) | 0x02000000 |                
              (((unsigned long)(x) & 0x000FFFFF) << 5) | ((b) << 2))
#define HWREGBITH(x, b)                                                       
        HWREGH(((unsigned long)(x) & 0xF0000000) | 0x02000000 |               
               (((unsigned long)(x) & 0x000FFFFF) << 5) | ((b) << 2))
#define HWREGBITB(x, b)                                                       
        HWREGB(((unsigned long)(x) & 0xF0000000) | 0x02000000 |               
               (((unsigned long)(x) & 0x000FFFFF) << 5) | ((b) << 2))


HWREG( )
기능 x 주소의 레지스터의 32비트 접근
원형 #define HWREG(x) (*((volatile unsigned long *)(x)))
변수 x : 하드웨어의 레지스터 주소

HWREGH( )
기능 x 주소의 레지스터의 16비트 접근
원형 #define HWREG(x) (*((volatile unsigned long *)(x)))
변수 x : 하드웨어의 레지스터 주소
HWREGB( )
기능 x 주소의 레지스터의 8비트 접근
원형 #define HWREG(x) (*((volatile unsigned long *)(x)))
변수 x : 하드웨어의 레지스터 주소
HWREGBITW( )
기능 x 주소의 레지스터의 bit-band alias 접근으로 b 비트를 접근한다.
원형 #define HWREGBITW(x , b) \
HWREG(((unsigned long)(x) & 0xF0000000) | 0x02000000 | \
(((unsigned long)(x) & 0x000FFFFF) << 5) | ((b) << 2))
변수 x :SRAM 0x20000000~0x200FFFFC와 Peripheral 0x40000000~0x400FFFFC  bit-band region
b : 비트 범위 0~31
HWREGBITH( )
기능 x 주소의 레지스터의 bit-band alias 접근으로 b 비트를 접근한다.
원형 #define HWREGBITH(x , b) \
HWREGH(((unsigned long)(x) & 0xF0000000) | 0x02000000 | \
(((unsigned long)(x) & 0x000FFFFF) << 5) | ((b) << 2))
변수 x :SRAM 0x20000000~0x200FFFFC와 Peripheral 0x40000000~0x400FFFFC  bit-band region
b : 비트 범위 0~15
HWREGBITB( )
기능 x 주소의 레지스터의 bit-band alias 접근으로 b 비트를 접근한다.
원형 #define HWREGBITB(x , b) \
HWREGB(((unsigned long)(x) & 0xF0000000) | 0x02000000 | \
(((unsigned long)(x) & 0x000FFFFF) << 5) | ((b) << 2))
변수 x :SRAM 0x20000000~0x200FFFFC와 Peripheral 0x40000000~0x400FFFFC  bit-band region
b : 비트 범위 0~7




실제 소스코드로 확인 해보자.

1. Bit Banding을 이용한 레지스터의 bit 변경


2. 레지스터 직접 접근하여 레지스터의 bit 변경

=> 결론 : Bit Banding을 이용시 어셈 명령어 3줄, 직접 접근시 5줄로 Bit Banding이용시 확실히 빠름을 볼수 있다.




아래는 Intro To Cortex-M3(http://www.arm.com/pdfs/IntroToCortex-M3.pdf)에 나오는 bit-banding 성능 설명 그림이다.