mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 07:06:47 +00:00
🆕 uart驱动
This commit is contained in:
parent
be8ac71aa9
commit
22359344e4
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,3 +6,4 @@ kernel/kernel
|
|||||||
|
|
||||||
*.o
|
*.o
|
||||||
*.s
|
*.s
|
||||||
|
serial_opt.txt
|
@ -125,6 +125,11 @@ HPET.o: driver/timers/HPET/HPET.c
|
|||||||
timer.o: driver/timers/timer.c
|
timer.o: driver/timers/timer.c
|
||||||
gcc $(CFLAGS) -c driver/timers/timer.c -o driver/timers/timer.o
|
gcc $(CFLAGS) -c driver/timers/timer.c -o driver/timers/timer.o
|
||||||
|
|
||||||
|
OBJ_LIST += uart.o
|
||||||
|
LD_LIST += driver/uart/uart.o
|
||||||
|
uart.o: driver/uart/uart.c
|
||||||
|
gcc $(CFLAGS) -c driver/uart/uart.c -o driver/uart/uart.o
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
all: kernel
|
all: kernel
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
: "memory") //关闭外部中断
|
: "memory") //关闭外部中断
|
||||||
#define nop() __asm__ __volatile__("nop\n\t")
|
#define nop() __asm__ __volatile__("nop\n\t")
|
||||||
#define hlt() __asm__ __volatile__("hlt\n\t")
|
#define hlt() __asm__ __volatile__("hlt\n\t")
|
||||||
|
#define pause() asm volatile ("pause\n\t"); // 处理器等待一段时间
|
||||||
|
|
||||||
//内存屏障
|
//内存屏障
|
||||||
#define io_mfence() __asm__ __volatile__("mfence\n\t" :: \
|
#define io_mfence() __asm__ __volatile__("mfence\n\t" :: \
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
#include "../mm/mm.h"
|
#include "../mm/mm.h"
|
||||||
#include "../process/spinlock.h"
|
#include "../process/spinlock.h"
|
||||||
|
|
||||||
|
#include <driver/uart/uart.h>
|
||||||
|
|
||||||
//#include "linkage.h"
|
//#include "linkage.h"
|
||||||
|
|
||||||
struct screen_info pos;
|
struct screen_info pos;
|
||||||
@ -110,13 +112,16 @@ void auto_newline()
|
|||||||
* @brief 超过每行最大字符数,自动换行
|
* @brief 超过每行最大字符数,自动换行
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (pos.x > pos.max_x)
|
if (pos.x > pos.max_x)
|
||||||
{
|
{
|
||||||
|
uart_send(COM1, '\n');
|
||||||
pos.x = 0;
|
pos.x = 0;
|
||||||
++pos.y;
|
++pos.y;
|
||||||
}
|
}
|
||||||
if (pos.y > pos.max_y)
|
if (pos.y > pos.max_y)
|
||||||
{
|
{
|
||||||
|
uart_send(COM1, '\n');
|
||||||
pos.y = pos.max_y;
|
pos.y = pos.max_y;
|
||||||
int lines_to_scroll = 1;
|
int lines_to_scroll = 1;
|
||||||
scroll(true, lines_to_scroll * pos.char_size_y, false);
|
scroll(true, lines_to_scroll * pos.char_size_y, false);
|
||||||
@ -625,6 +630,8 @@ static void putchar(uint *fb, int Xsize, int x, int y, unsigned int FRcolor, uns
|
|||||||
* @param BKcolor 背景颜色
|
* @param BKcolor 背景颜色
|
||||||
* @param font 字符的bitmap
|
* @param font 字符的bitmap
|
||||||
*/
|
*/
|
||||||
|
// 输出到串口
|
||||||
|
uart_send(COM1, font);
|
||||||
|
|
||||||
unsigned char *font_ptr = font_ascii[font];
|
unsigned char *font_ptr = font_ascii[font];
|
||||||
unsigned int *addr;
|
unsigned int *addr;
|
||||||
|
88
kernel/driver/uart/uart.c
Normal file
88
kernel/driver/uart/uart.c
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
#include "uart.h"
|
||||||
|
#include <common/kprint.h>
|
||||||
|
|
||||||
|
#define UART_MAX_BITS_RATE 115200
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 当前是否有数据到达
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define serial_received(p) ((io_in8(p + 5) & 1))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 当前是否有数据正等待发送
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define is_transmit_empty(p) ((io_in8(p + 5) & 0x20))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 初始化com口
|
||||||
|
*
|
||||||
|
* @param port com口的端口号
|
||||||
|
* @param bits_rate 通信的比特率
|
||||||
|
*/
|
||||||
|
int uart_init(uint32_t port, uint32_t bits_rate)
|
||||||
|
{
|
||||||
|
// 错误的比特率
|
||||||
|
if (bits_rate > UART_MAX_BITS_RATE || UART_MAX_BITS_RATE % bits_rate != 0)
|
||||||
|
return E_UART_BITS_RATE_ERROR;
|
||||||
|
|
||||||
|
io_out8(port + 1, 0x00); // Disable all interrupts
|
||||||
|
io_out8(port + 3, 0x80); // Enable DLAB (set baud rate divisor)
|
||||||
|
|
||||||
|
uint16_t divisor = E_UART_BITS_RATE_ERROR / bits_rate;
|
||||||
|
io_out8(port + 0, divisor & 0xff); // Set divisor (lo byte)
|
||||||
|
io_out8(port + 1, (divisor >> 8) & 0xff); // (hi byte)
|
||||||
|
io_out8(port + 3, 0x03); // 8 bits, no parity, one stop bit
|
||||||
|
io_out8(port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
|
||||||
|
io_out8(port + 4, 0x0B); // IRQs enabled, RTS/DSR set
|
||||||
|
io_out8(port + 4, 0x1E); // Set in loopback mode, test the serial chip
|
||||||
|
io_out8(port + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
|
||||||
|
|
||||||
|
// Check if serial is faulty (i.e: not same byte as sent)
|
||||||
|
if (io_in8(port + 0) != 0xAE)
|
||||||
|
{
|
||||||
|
return E_UART_SERIAL_FAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If serial is not faulty set it in normal operation mode
|
||||||
|
// (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
|
||||||
|
io_out8(port + 4, 0x0F);
|
||||||
|
return UART_SUCCESS;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Notice that the initialization code above writes to [PORT + 1]
|
||||||
|
twice with different values. This is once to write to the Divisor
|
||||||
|
register along with [PORT + 0] and once to write to the Interrupt
|
||||||
|
register as detailed in the previous section.
|
||||||
|
The second write to the Line Control register [PORT + 3]
|
||||||
|
clears the DLAB again as well as setting various other bits.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 发送数据
|
||||||
|
*
|
||||||
|
* @param port 端口号
|
||||||
|
* @param c 要发送的数据
|
||||||
|
*/
|
||||||
|
void uart_send(uint32_t port, char c)
|
||||||
|
{
|
||||||
|
while (is_transmit_empty(port) == 0)
|
||||||
|
pause();
|
||||||
|
io_out8(port, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 从uart接收数据
|
||||||
|
*
|
||||||
|
* @param port 端口号
|
||||||
|
* @return uchar 接收到的数据
|
||||||
|
*/
|
||||||
|
uchar uart_read(uint32_t port)
|
||||||
|
{
|
||||||
|
while (serial_received(port) == 0)
|
||||||
|
pause();
|
||||||
|
|
||||||
|
return io_in8(port);
|
||||||
|
}
|
64
kernel/driver/uart/uart.h
Normal file
64
kernel/driver/uart/uart.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/**
|
||||||
|
* @file uart.h
|
||||||
|
* @author longjin (longjin@RinGoTek.cn)
|
||||||
|
* @brief uart驱动程序 RS-232驱动
|
||||||
|
* @version 0.1
|
||||||
|
* @date 2022-04-15
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2022
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <common/glib.h>
|
||||||
|
|
||||||
|
#define UART_SUCCESS 0
|
||||||
|
#define E_UART_BITS_RATE_ERROR 1
|
||||||
|
#define E_UART_SERIAL_FAULT 2
|
||||||
|
enum uart_port_io_addr
|
||||||
|
{
|
||||||
|
COM1 = 0x3f8,
|
||||||
|
COM2 = 0x2f8,
|
||||||
|
COM3 = 0x3e8,
|
||||||
|
COM4 = 0x2e8,
|
||||||
|
COM5 = 0x5f8,
|
||||||
|
COM6 = 0x4f8,
|
||||||
|
COM7 = 0x5e8,
|
||||||
|
COM8 = 0x4E8,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum uart_register_offset
|
||||||
|
{
|
||||||
|
REG_DATA = 0,
|
||||||
|
REG_INTERRUPT_ENABLE = 1,
|
||||||
|
REG_II_FIFO = 2, // Interrupt Identification and FIFO control registers
|
||||||
|
REG_LINE_CONTROL = 3,
|
||||||
|
REG_MODEM_CONTROL = 4,
|
||||||
|
REG_LINE_STATUS = 5,
|
||||||
|
REG_MODEM_STATUE = 6,
|
||||||
|
REG_SCRATCH = 7
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 初始化com口
|
||||||
|
*
|
||||||
|
* @param port com口的端口号
|
||||||
|
* @param bits_rate 通信的比特率
|
||||||
|
*/
|
||||||
|
int uart_init(uint32_t port, uint32_t bits_rate);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 发送数据
|
||||||
|
*
|
||||||
|
* @param port 端口号
|
||||||
|
* @param c 要发送的数据
|
||||||
|
*/
|
||||||
|
void uart_send(uint32_t port, char c);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 从uart接收数据
|
||||||
|
*
|
||||||
|
* @param port 端口号
|
||||||
|
* @return uchar 接收到的数据
|
||||||
|
*/
|
||||||
|
uchar uart_read(uint32_t port);
|
@ -27,6 +27,7 @@
|
|||||||
#include <driver/timers/rtc/rtc.h>
|
#include <driver/timers/rtc/rtc.h>
|
||||||
#include <driver/timers/HPET/HPET.h>
|
#include <driver/timers/HPET/HPET.h>
|
||||||
#include <driver/timers/timer.h>
|
#include <driver/timers/timer.h>
|
||||||
|
#include <driver/uart/uart.h>
|
||||||
|
|
||||||
unsigned int *FR_address = (unsigned int *)0xb8000; //帧缓存区的地址
|
unsigned int *FR_address = (unsigned int *)0xb8000; //帧缓存区的地址
|
||||||
ul bsp_idt_size, bsp_gdt_size;
|
ul bsp_idt_size, bsp_gdt_size;
|
||||||
@ -83,6 +84,7 @@ void system_initialize()
|
|||||||
|
|
||||||
// 初始化printk
|
// 初始化printk
|
||||||
printk_init(8, 16);
|
printk_init(8, 16);
|
||||||
|
uart_init(COM1, 115200);
|
||||||
kinfo("Kernel Starting...");
|
kinfo("Kernel Starting...");
|
||||||
// 重新加载gdt和idt
|
// 重新加载gdt和idt
|
||||||
|
|
||||||
@ -100,7 +102,6 @@ void system_initialize()
|
|||||||
kdebug("cpu_core_info[0].tss_vaddr=%#018lx", cpu_core_info[0].tss_vaddr);
|
kdebug("cpu_core_info[0].tss_vaddr=%#018lx", cpu_core_info[0].tss_vaddr);
|
||||||
kdebug("cpu_core_info[0].stack_start%#018lx", cpu_core_info[0].stack_start);
|
kdebug("cpu_core_info[0].stack_start%#018lx", cpu_core_info[0].stack_start);
|
||||||
|
|
||||||
|
|
||||||
// 初始化中断描述符表
|
// 初始化中断描述符表
|
||||||
sys_vector_init();
|
sys_vector_init();
|
||||||
|
|
||||||
@ -145,14 +146,10 @@ void system_initialize()
|
|||||||
// test_slab();
|
// test_slab();
|
||||||
// test_mm();
|
// test_mm();
|
||||||
|
|
||||||
|
|
||||||
// process_init();
|
// process_init();
|
||||||
current_pcb->cpu_id = 0;
|
current_pcb->cpu_id = 0;
|
||||||
current_pcb->preempt_count = 0;
|
current_pcb->preempt_count = 0;
|
||||||
HPET_init();
|
HPET_init();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//操作系统内核从这里开始执行
|
//操作系统内核从这里开始执行
|
||||||
@ -177,7 +174,6 @@ void Start_Kernel(void)
|
|||||||
multiboot2_magic = (uint)mb2_magic;
|
multiboot2_magic = (uint)mb2_magic;
|
||||||
multiboot2_boot_info_addr = mb2_info + PAGE_OFFSET;
|
multiboot2_boot_info_addr = mb2_info + PAGE_OFFSET;
|
||||||
|
|
||||||
|
|
||||||
system_initialize();
|
system_initialize();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
2
run.sh
2
run.sh
@ -93,7 +93,7 @@ if [ $flag_can_run -eq 1 ]; then
|
|||||||
bochs -q -f ${bochsrc} -rc ./tools/bochsinit
|
bochs -q -f ${bochsrc} -rc ./tools/bochsinit
|
||||||
else
|
else
|
||||||
qemu-system-x86_64 -cdrom ${iso} -m 512M -smp 2,cores=2,threads=1,sockets=1 \
|
qemu-system-x86_64 -cdrom ${iso} -m 512M -smp 2,cores=2,threads=1,sockets=1 \
|
||||||
-monitor stdio -d cpu_reset,guest_errors,trace:check_exception,exec,cpu,out_asm,in_asm -s -S -cpu IvyBridge --enable-kvm -rtc clock=host,base=localtime \
|
-monitor stdio -d cpu_reset,guest_errors,trace:check_exception,exec,cpu,out_asm,in_asm -s -S -cpu IvyBridge --enable-kvm -rtc clock=host,base=localtime -serial file:serial_opt.txt \
|
||||||
-drive id=disk,file=bin/disk.img,if=none \
|
-drive id=disk,file=bin/disk.img,if=none \
|
||||||
-device ahci,id=ahci \
|
-device ahci,id=ahci \
|
||||||
-device ide-hd,drive=disk,bus=ahci.0 \
|
-device ide-hd,drive=disk,bus=ahci.0 \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user