일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- ros
- ICER
- 마법의숲탐색
- 코드트리
- 시뮬레이션
- 토끼와 경주
- ISER
- DP
- ARM
- 이진탐색
- 나무박멸
- 코드트리빵
- 왕실의기사대결
- 순서대로방문하기
- 수영대회결승전
- Calibration
- DenseDepth
- 구현
- 조합
- BFS
- 백준
- dfs
- 삼성기출
- 싸움땅
- 3Dreconstruction
- 루돌프의반란
- 소프티어
- 슈퍼컴퓨터클러스터
- 마이크로프로세서
- 포탑부수기
Archives
- Today
- Total
from palette import colorful_colors
[마이크로프로세서] C언어와 ARM 명령어 비교 예시2 (feat. GPIO) 본문
1. GPIO의 ODR 비트 조절하기
예시: GPIOA의 ODR의 8번 비트를 1로 켜기
C 언어:
GPIOA->ODR |= 1UL << 8; // GPIOA -> ODR의 bit8을 1로 만든다
ARM 어셈블리어:
GPIOA_BASE EQU 0x48000000 ; GPIOA의 BASE 주소는 0x48000000이다.
GPIO_ODR EQU 0x14 ; ODR은 GPIO BASE에서 0x14만큼 떨어져 있으므로
LDR r7, = GPIOA_BASE
LDR r1, [r7, #GPIO_ODR] ; r1에 GPIOA의 ODR에 있는 값을 불러온다
ORR r1, r1, #2_100000000 ; 8번 비트를 1로 만든다
STR r1, [r7, #GPIO_ODR] ; GPIOA의 ODR에 다시 변경한 값을 저장한다.
2. GPIO OUTPUT
예시: GPIOB의 pin2번을 push-pull 방식으로 설정하여 LED를 켜고 싶을때:
C 언어:
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOBEN; // portB의 RCC clock을 enable 시켜준다
GPIOB->MODER &= ~(3UL<<4); // bit4, 5번을 clear시킨다(pin2가 4,5번 비트고, "01"이 output mode니깐 우선 4번,5번 비트를 "00"으로 만들어준다.)
GPIOB->MODER |= 1UL<<4; // bit4번을 1로 set시켜 "01"을 만든다.
GPIO->OTYPE &= ~(1UL<<2) // pin2의 output type을 open-drain(1)이 아닌 push-pull(0)로 만든다
GPIO->ODR |= 1UL << 2; // pin2의 비트(3번째 비트)를 1(HIGH)로 설정한다.
ARM 어셈블리어:
AREA main, CODE, READONLY
EXPORT _main ; main을 외부 파일에서도 쓸 수 있게 한다(linker에게 보일 수 있게 한다)
_main PROC
;/////GPIOB RCC 설정하기/////
LDR r2, =RCC_BASE
LDR r1, [r2, #RCC_AHB2ENR]
ORR r1, r1, #2; ; RCC에서 GPIOB는 2번째 bit이므로, 해당 비트를 1 시켜준다.
STR r1, [r2, #RCC_AHB2ENR] ; RCC의 GPIOB(2번째 비트)를 1로 켜는 작업 마무리
LDR r3, = GPIOB_BASE
;/////GPIO_BASE의 pin2의 MODER 설정하기/////
LDR r1, [r3, #GPIO_MODER]
BIC r1, r1, #(3 << 4)
ORR r1, r1, #(1 << 4) ; 최종적으로 pin2(4,5번 비트)를 01로 설정하게 된다.
STR r1, [r3, #GPIO_MODER] ; GPIOB의 MODER의 pin2를 01로 설정하는 작업 마무리
;/////Push-pull(0) or Open drain(1) 설정하기/////
LDR r1, [r3, #GPIO_OTYPER]
BIC r1, r1, #(1<<2) ; pin2번의(3번째 비트)를 0으로 설정해서 push-pull 방식으로 설정했다.
STR r1, [r3, #GPIO_OTYPER]
;/////ODR 설정해서 LED 켜기/////
LDR r1, [r3, #GPIO_ODR]
ORR r1, r1, #(1<<2) ; pin2번을 1로 설정한다. #(1<<2) 말고 #2_00000100으로 설정해도 된다.
STR r1, [r3, #GPIO_ODR]
stop
B_stop
ENDP
END
3. GPIO INPUT
예시: GPIOA의 pin0번에서 pull-up, pull-down 사용하지 않고 입력값 받기
C 언어:
uint32_t input;
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN; // RCC에서 GPIOA의 clock 을 open시킨다.
GPIOA->MODER &= ~3UL; // GPIOA의 MODE를 input(00)으로 변경시킨다.
GPIO->PUPDR &= ~3UL; // GPIOA의 pull-up, pull-down을 설정하지 않는다(00)
// pin0 읽기
input = (GPIOA->IDR & 1UL) // GPIOA->IDR를 input변수에 넣는다
if (input == 0){
// 입력이 안 들어왔을때 실행할 것들
}
else {
// 입력이 들어왔을때 실행할 것들
}
ARM 어셈블리어:
AREA main, CODE, READONLY
EXPORT _main
ENTRY
_main PROC
;////GPIOA RCC 설정하기////
LDR r2, =RCC_BASE
LDR r1, [r2, #RCC_AHB2ENER]
ORR r1, r1, #1 ; GPIOA는 첫번째 비트이므로, RCC를 1로 설정
STR r1, [r2, #RCC_AHB2ENER]
LDR r3, =GPIOA_BASE
;////GPIOA MODE - Input으로 변경시키기////
LDR r1, [r3, GPIO_MODER]
BIC r1, r1, #3 ; pin0을 00으로 바꾸고 싶으므로, MODER의 제일 처음 두 비트를 0으로 만든다
STR r1, [r3, GPIO_MODER]
;////Pull up, Pull down 설정하기////
LDR r1, [r3, #GPIO_PUPDR]
BIC r1, r1, #3 ; pin0을 00으로 만들어 pull up, pull down 둘 다 설정 안 함
STR r1, [r3, #GPIO_PUPDR]
;////input 변수에 핀 상태 읽어오기////
LDR r1, [r3, #GPIO_IDR]
AND r1, r1, #1 ; 나는 pin0만 관심있으므로, 첫번째 비트만 가져온다.
CMP r1, #1 ; r1과 1 비교,
BLEQ center_pressed ; r1 == 1일때 center_pressed 함수 호출
BLNE center_not_pressed ; r1 != 1일때 center_not_pressed 함수 호출
stop
B stop
ENDP
4. Interrupt Control Bits
예시: interrrupt number가 IRQn = j + 32xi 일때, 해당 interrupt의 ISER 혹은 ICER 접근하기
C 언어:
WordOffset = IRQn >> 5; // WordOffset은 i, 몫이 된다.
BitOffset = IRQn & 0x1F; // BitOffset은 j, 나머지가 된다.
NVIC->ISER[WordOffset] = 1<<BitOffset; // 해당 인터럽트 enable한다고 가정할 시, 이렇게 표현 가능하다. (dissable이라면 ICER로 대신)
ARM 어셈블리어:
; input arguments:
; r0: interrupt number of a peripheral interrupt
; r1: 1 = Enable, 0 = Disable
Peripheral_Interrupt_Enable PROC
PUSH {r4, lr} ; 이전 환경 저장
AND r2, r0, #0x1F ; r2에는 32로 나눈 나머지인 j가 담긴다.
MOV r3, #1
LSL r3, r3, r2 ; r3에는 1을 j만큼 left shift시킨 값이 담긴다.
LDR r4, =NVIC_BASE
CMP r1, #0
LDRNE r1, = NVIC_ISER0 ; r1이 1이라면 enable, ISER이다.
LDREQ r1, = NVIC_ICER0 ; r1이 0라면 Disable, ICER이다.
ADD r1, r4, r1 ; r1에는 해당 NVIC의 ISER 혹은 ICER 주소가 담긴다.
LSR r2, r0, #5 ; r0를 32로 나눠 r2에는 몫 i가 담긴다.
LSL r2, r2, #2 ; 번지는 4씩 증가하므로 몫(i)에 4를 곱해준다.
STR r3, [r1, r2] ; left shift한 비트를 [r1, r2]에 담는다.
POP {r4, pc} ; 이전 환경 복귀
ENDP
'EE 학부과목 > 마이크로프로세서' 카테고리의 다른 글
[마이크로프로세서] C언어와 ARM 명령어 비교 예시 (0) | 2023.04.19 |
---|---|
[마이크로프로세서] ARM 명령어 모음 + 지시어, flag register (0) | 2023.04.19 |
[마이크로프로세서] Floating point(부동소수점) (0) | 2023.03.20 |
[컴퓨터구조] 22-2학기 수업 필기자료 (0) | 2023.03.16 |
[마이크로프로세서] 명령어와 CISC vs RISC (0) | 2023.03.07 |