Files
2025-yatcpu/lab1/csrc/hello.c
TOKISAKIX\21168 910ee11168 init repo
2023-12-11 21:50:22 +08:00

176 lines
3.4 KiB
C

// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "mmio.h"
#define MUL80(x) (((x) << 6) + ((x) << 4))
struct screen {
unsigned char row, col;
} scr;
void copy_line(int prev, int cur) {
int *prev_vram_start = ((int *) (MUL80(prev) + VRAM_BASE));
int *cur_vram_start = ((int *) (MUL80(cur) + VRAM_BASE));
for (int i = 0; i < 20; ++i) {
prev_vram_start[i] = cur_vram_start[i];
}
}
void write_char(int row, int col, unsigned char ch) {
VRAM[MUL80(row) + col] = ch;
}
void move_to(int row, int col) {
scr.row = row;
scr.col = col;
}
void new_line() {
scr.col = 0;
if (scr.row == 29) {
for (int i = 0; i < 29; ++i) {
copy_line(i, i + 1);
}
int *vram = (int *) (MUL80(29) + VRAM_BASE);
for (int i = 0; i < 20; ++i) {
vram[i] = 0x20202020;
}
} else {
++scr.row;
}
}
void putch(unsigned char ch) {
if (ch == '\n') {
new_line();
} else if (ch == '\r') {
scr.col = 0;
} else {
if (scr.col == 79) {
new_line();
}
write_char(scr.row, scr.col, ch);
++scr.col;
}
}
void clear_screen() {
scr.row = 0;
scr.col = 0;
int *vram = ((int *) VRAM_BASE);
for (int i = 0; i < 600; ++i) vram[i] = 0x20202020;
}
void print_hex(unsigned int counter) {
putch('0'); putch('x');
for (int i = 7; i >= 0; --i) {
unsigned int num = (counter >> (i << 2)) & 0xF;
if (num < 10) {
putch('0' + num);
} else {
putch('A' + num - 10);
}
}
}
void putstr(const char *s) {
while (*s) {
putch(*(s++));
}
}
int hc = 1;
int fast = 0;
void print_timer() {
putstr("Hardware timer count limit = ");
print_hex(*TIMER_LIMIT);
putstr(", enabled = ");
print_hex(*TIMER_ENABLED);
putch('\n');
}
void print_uart() {
putstr("UART Baud rate = ");
print_hex(*UART_BAUDRATE);
putch('\n');
}
void handle_timer() {
putstr("Timer trigger times = ");
print_hex(hc++);
putch('\n');
int mode = ((hc & 0x10) >> 4);
if (hc == 0x40) {
putstr("Disable timer!\n");
*TIMER_ENABLED = 0;
print_timer();
return;
}
if (fast ^ mode) {
putstr("Switch timer frequency\n");
if (fast == 0) {
*TIMER_LIMIT = 25000000;
} else {
*TIMER_LIMIT = 100000000;
}
fast = mode;
print_timer();
}
}
void handle_uart() {
unsigned int ch = *UART_RECV;
*UART_SEND = ch;
putstr("UART Recv hex = "); print_hex(ch); putstr(", ch = "); putch(ch); putch('\n');
}
void trap_handler(void *epc, unsigned int cause) {
putstr("Interrupt! EPC = ");
print_hex((unsigned int) epc);
putstr(", CAUSE = ");
print_hex(cause);
putch('\n');
switch (cause) {
case 0x8000000B:
handle_uart();
break;
default:
handle_timer();
break;
}
}
extern void enable_interrupt();
extern unsigned int get_epc();
int main() {
clear_screen();
hc = 0;
*TIMER_ENABLED = 1;
putstr("YatCPU Demo Program ");
putch(137);
putstr("2021 Howard Lau\n");
putstr("Hello, world!\n");
putstr("Last EPC = ");
print_hex(get_epc());
putch('\n');
print_timer();
print_uart();
*((int *) 0x4) = 0xDEADBEEF;
unsigned int i = 0;
enable_interrupt();
for (;;) ;
}