240604_ GPIO, Assembly
ROM과 RISC-V CPU : I BUS
RAM과 RISC-V CPU : D BUS
ROM에서 RISC-V 로는 I BUS를 통해 Instruction만 받고
RISC-V에서 RAM peripheral, sp2 등등에는 WDataBus, Control Signal Bus, Addr Bus 세가지와 Decoder이 Adder Bus를 받아 RAM, peripheral, sp2중 어느것을 실행시킬지 정하고 그 출력값이 MUX를 통해 RDataBus가 되어 RISC CPU로 되돌아온다.
4GB, 2**32bit --> 32bitAddress.
초기화되면 0번지로 ROM먼저 읽어들어야 하기 때문에 ROM의 Instruction Memory가 0번지이다.
그 이후는 할당하기 나름이다.
32bit중 뒷 8bit는 주소 한세트라서 빼고 처리했다.
0x0000_1000 : RAM
0x0000_2000 : P1
등등 decoder로 선택한다.
decoder로 선택된 장치만 동작하기 때문에 주소를 받아서 CASE문을 통해 선택.
AMBA -AHB, APB 의 동작이 이렇게 된다. 기본적인 BUS 구조.
추가적인건 burst , control signal에서 추가되는 정보 등등..
단 AXI는 많이 다른 구조를 가지고 있다.
교수님코드
Decoder를 통해 Memory Mapping을 볼 수 있다.
Decoder와 MUX가 지정하는 Memory Mapping의 address는 같아야한다.
<< 어셈블리코드 >>
SW : RAM에 저장. STORE S-TYPE의 SW이다.
pointer.
8912 : 0x2000
256 : 0x100
lw, li, Sll 한 값을 SW로 저장.
==> 이것을 보고 Simulation의 Timing Diagram을 파악할줄 알아야 한다.
delay를 부르고 있다. 100을 넣어서 불렀다.
li a0, 100
call delay --> 어셈블러가 delay : 되어있는 곳에 가서 알아서 계산.
addi : sp, sp- 48 ~~~ stack에 저장하는 작업. + 뺴는 작업을 진행하고 있다.
왜 Stack에 넣을까???? stack memory 영역에 넣고 빼고 한다.
sw zero, -20(s0) temp = 0
j .L4 --> L4 : 로 가서 lw a5, -36(s0) 0보다 크면. bgtz a5.L7 L7로 가라. J를 통해 연결.
ra : return .
assembly를 짜라고는 하지는 않지만 이해를 할 필요는 있다. + 내부적으로 어떻게 동작하는지는 알아야 한다.
X0는 Zero 라는 예명.
s0, a5 둘다 register File 이다.
mv li jr --> 우리가 만든 명령어랑 이름이 다르다.
base : 우리가 만든 명령어.
pseudoinstruction : 여기서 쓰는 명령
명령어를 대체할 수 있다.
전통적으로 사용하던 명령어를 --> 이런식으로 대체할 수 있다. --> 명령어가 확 줄었다.
CISC : 다 하드웨어적으로 구현.
RISC : 줄였다.
<<GPO>>
GPOA bink.
GPOB ledshift
GPOC
중간과제
/* Type your code here, or load an example. */
#define PORTA *(int*)(0x00002100)
#define PORTB *(int*)(0x00002200)
void delay(int t);
int prevTime1 = 0;
int prevTime2 = 0;
int millis = 0;
int a = 0;
int main() {
while(1)
{
if (millis - prevTime1 >= 200)
{
prevTime1 = millis;
PORTA ^= 0x0f;
}
if (millis - prevTime2 >= 100)
{
prevTime2 = millis;
PORTB = 1<<a;
a++;
if( a== 4 ) a = 0;
}
delay(1);
millis++;
}
return 0;
}
void delay(int t)
{
int temp = 0;
while (t>0){
for (int i = 0; i <100000; i++) temp++;
t--;
}
}
prevTime1:
.zero 4
prevTime2:
.zero 4
millis:
.zero 4
a:
.zero 4
main:
addi sp,sp,-16
sw ra,12(sp)
sw s0,8(sp)
addi s0,sp,16
.L4:
lui a5,%hi(millis)
lw a4,%lo(millis)(a5)
lui a5,%hi(prevTime1)
lw a5,%lo(prevTime1)(a5)
sub a4,a4,a5
li a5,199
ble a4,a5,.L2
lui a5,%hi(millis)
lw a4,%lo(millis)(a5)
lui a5,%hi(prevTime1)
sw a4,%lo(prevTime1)(a5)
li a5,8192
addi a5,a5,256
lw a4,0(a5)
li a5,8192
addi a5,a5,256
xori a4,a4,15
sw a4,0(a5)
.L2:
lui a5,%hi(millis)
lw a4,%lo(millis)(a5)
lui a5,%hi(prevTime2)
lw a5,%lo(prevTime2)(a5)
sub a4,a4,a5
li a5,99
ble a4,a5,.L3
lui a5,%hi(millis)
lw a4,%lo(millis)(a5)
lui a5,%hi(prevTime2)
sw a4,%lo(prevTime2)(a5)
lui a5,%hi(a)
lw a4,%lo(a)(a5)
li a5,8192
addi a5,a5,512
li a3,1
sll a4,a3,a4
sw a4,0(a5)
lui a5,%hi(a)
lw a5,%lo(a)(a5)
addi a4,a5,1
lui a5,%hi(a)
sw a4,%lo(a)(a5)
lui a5,%hi(a)
lw a4,%lo(a)(a5)
li a5,4
bne a4,a5,.L3
lui a5,%hi(a)
sw zero,%lo(a)(a5)
.L3:
li a0,1
call delay
lui a5,%hi(millis)
lw a5,%lo(millis)(a5)
addi a4,a5,1
lui a5,%hi(millis)
sw a4,%lo(millis)(a5)
j .L4
delay:
addi sp,sp,-48
sw s0,44(sp)
addi s0,sp,48
sw a0,-36(s0)
sw zero,-20(s0)
j .L6
.L9:
sw zero,-24(s0)
j .L7
.L8:
lw a5,-20(s0)
addi a5,a5,1
sw a5,-20(s0)
lw a5,-24(s0)
addi a5,a5,1
sw a5,-24(s0)
.L7:
lw a4,-24(s0)
li a5,98304
addi a5,a5,1695
ble a4,a5,.L8
lw a5,-36(s0)
addi a5,a5,-1
sw a5,-36(s0)
.L6:
lw a5,-36(s0)
bgtz a5,.L9
nop
lw s0,44(sp)
addi sp,sp,48
jr ra
<<GPI>>
IDR은 READ만 가능하다.
PORT INPUT DATA : IDR
reserved : 사용 X
GPOC, GPOD --> GPIC, GPID
GPIC, GPID 의 주소로 받아줘야 한다.
<<GPIO>>
Memory Mapping .
32bit Register 3개 만들기.
gpioReg 가 addr 4씩 증가를 받기위해 3:2로 잘라서 사용.
1bit씩 자릿수로 보기.