RVOS-2.基于NS16550a ,为os添加终端交互功能。

2.1 实验目的

为os添加uart功能,通过串口实现开发板与PC交互。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.1 硬件信息

QEMU虚拟SoC含有 虚拟NS16550A设备 。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

不同的地址线组合(A2、A1、A0)对应的读写模式和寄存器如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.2 NS16550a 的初始化

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

线路控制寄存器(LCR)中的bit7位来实现复用DLL、DLM两个寄存器拼起来作为16位波特率寄存器。当bit7位被设置为1时,地址0和1用于访问除数锁存寄存器(DLL和DLM),用于设置波特率。

  • 关闭中断
  • 设置波特率
  • 设置异步数据通信格式
void uart_init()
{/* disable interrupts. */uart_write_reg(IER, 0x00);/** Setting baud rate. Just a demo here if we care about the divisor,* but for our purpose [QEMU-virt], this doesn't really do anything.** Notice that the divisor register DLL (divisor latch least) and DLM (divisor* latch most) have the same base address as the receiver/transmitter and the* interrupt enable register. To change what the base address points to, we* open the "divisor latch" by writing 1 into the Divisor Latch Access Bit* (DLAB), which is bit index 7 of the Line Control Register (LCR).** Regarding the baud rate value, see [1] "BAUD RATE GENERATOR PROGRAMMING TABLE".* We use 38.4K when 1.8432 MHZ crystal, so the corresponding value is 3.* And due to the divisor register is two bytes (16 bits), so we need to* split the value of 3(0x0003) into two bytes, DLL stores the low byte,* DLM stores the high byte.*/uint8_t lcr = uart_read_reg(LCR);uart_write_reg(LCR, lcr | (1 << 7));uart_write_reg(DLL, 0x03);uart_write_reg(DLM, 0x00);/** Continue setting the asynchronous data communication format.* - number of the word length: 8 bits* - number of stop bits:1 bit when word length is 8 bits* - no parity* - no break control* - disabled baud latch*/lcr = 0;uart_write_reg(LCR, lcr | (3 << 1));
}

原代码这里是这样,感觉不太对,应该是左移一位的。

lcr = 0;
uart_write_reg(LCR, lcr | (3 << 0));

2.3 NS16550a 的数据读写

在NS16550A UART中,区分读写模式是通过控制信号(如读/写控制线)来实现的,而不是通过寄存器地址。这些控制信号通常由CPU或其他主控设备提供。以下是区分读写模式的一般步骤:

  1. 当CPU或其他主控设备想要从UART读取数据时,它会将读控制线置为有效状态(低电平)。同时将芯片选择信号置为有效状态,以选中UART设备。
  2. 当CPU或其他主控设备想要向UART写入数据时,它会将写控制线置为有效状态(低电平)。同样将芯片选择信号置为有效状态,以选中UART设备。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

读:

/** LINE STATUS REGISTER (LSR)* LSR BIT 0:* 0 = no data in receive holding register or FIFO.* 1 = data has been receive and saved in the receive holding register or FIFO.* ......* LSR BIT 5:* 0 = transmit holding register is full. 16550 will not accept any data for transmission.* 1 = transmitter hold register (or FIFO) is empty. CPU can load the next character.* ......*/
#define LSR_RX_READY (1 << 0)
#define LSR_TX_IDLE  (1 << 5)int uart_putc(char ch)
{while ((uart_read_reg(LSR) & LSR_TX_IDLE) == 0);return uart_write_reg(THR, ch);
}void uart_puts(char *s)
{while (*s) {uart_putc(*s++);}
}

写:

练习 7-2

要求:参考code/os/01-helloRVOS,在此基础上增加采⽤轮询⽅式读取控制台上输入的字符并 回显 在控制台上。另外⽤户按下回⻋后能够另起⼀⾏从头开始。

int uart_getc()
{char ch;while ((uart_read_reg(LSR) & LSR_RX_READY) == 0);ch = uart_read_reg(RHR);return ch;
}void uart_gets(char *s, int len)
{int i = 0;char ch;while (i < len - 1) {ch = uart_getc(); if (ch == '\r') { break;}s[i++] = ch;}s[i] = '\0'; 
}/*** 回显功能:读取用户输入并回显到控制台*/
void uart_echo()
{char buffer[100]; 	uart_puts("UART Echo Ready:\r\n");while (1) {uart_gets(buffer, sizeof(buffer)); uart_putc('\r'); uart_putc('\n'); uart_puts("--kernel收到数据--\n");uart_puts(buffer);uart_putc('\r'); uart_putc('\n'); }
}

最后一定记得在kernel.c添加extern声明:

extern void uart_echo(void);void start_kernel(void)
{uart_init();uart_puts("Hello, RVOS!\n");uart_echo();  // 开始回显while (1) {}; // stop here!
}

运行结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

存在一个问题就是在终端输入的内容无法显示,且无法删除。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


问题解决:在当前实现中,输入的字符虽然被回显,但无法正确处理删除键(Backspace)的功能。这是因为 uart_gets 函数没有对删除键 (‘\b’ 或 ASCII 8) 进行处理。以下是改进方案:

我们需要在 uart_gets 中添加对删除键的处理逻辑。当用户按下删除键时,应该从缓冲区中移除最后一个字符,并在终端上删除回显的字符。

void uart_gets(char *s, int len)
{int i = 0;char ch;while (i < len - 1) {ch = uart_getc(); // 读取一个字符if (ch == '\r') { // 如果是回车符,结束读取break;} else if (ch == '\b' || ch == 127) { // 处理删除键('\b' 或 ASCII 127)if (i > 0) {i--; // 从缓冲区中移除最后一个字符uart_putc('\b'); // 回显删除键uart_putc(' ');  // 用空格覆盖已删除的字符uart_putc('\b'); // 将光标移回一格}} else {s[i++] = ch; 	// 存储字符uart_putc(ch); 	// 回显输入的字符}}s[i] = '\0'; // 添加字符串结束符
}

问题完美解决!!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

【[完结] 循序渐进,学习开发一个RISC-V上的操作系统 - 汪辰 - 2021春】 https://www.bilibili.com/video/BV1Q5411w7z5/?p=19&share_source=copy_web&vd_source=d63943fdb26087d14a536adf35c52d6b

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/76098.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java导入excel更新设备经纬度度数或者度分秒

文章目录 一、背景介绍二、页面效果三、代码0.pom.xml1.ImportDevice.vue2.ImportDeviceError.vue3.system.js4.DeviceManageControl5.DeviceManageUserControl6.Repeater7.FileUtils8.ResponseModel9.EnumLongitudeLatitude10.词条 四、注意点本人其他相关文章链接 一、背景介…

【力扣hot100题】(080)爬楼梯

让我们掌声恭迎动态规划的始祖—— 最基础的动态规划&#xff0c;原始方法是维护一个数组&#xff0c;每次记录到该阶梯的方案数量&#xff0c;每次的数量是到上一个阶梯的方案数量加上到上上一阶梯的方案数量&#xff0c;因为只有两种走法。 进阶可以优化空间复杂度&#xf…

CVE-2025-24813 漏洞全解析|Apache Tomcat 关键路径绕过与RCE

CVE-2025-24813 漏洞全解析&#xff5c;Apache Tomcat 关键路径绕过与RCE 作者:Factor .Poc作者:iSee857 CVE-2025-24813 漏洞全解析&#xff5c;Apache Tomcat 关键路径绕过与RCE一、漏洞概述二、影响版本三、漏洞原理&#x1f3af; 利用流程&#xff08;两步&#xff09;&am…

初识Linux:常见指令与权限的理解,以及相关衍生知识

目录 前言 关于linux的简介 代码开源 网络功能强大 系统工具链完整 一、Linux下的基本指令 1.ls指令 2.pwd指令 3.cd指令 4.whoami指令 5.touch指令 6.mkdir指令 7.rm指令 8.man指令 9.cp指令 10.mv指令 11.nano指令 12.cat指令 13.tac指令 14.more指令 15.less指令 16.head指令…

JVM虚拟机篇(七):JVM垃圾回收器全面解析与G1深度探秘及四种引用详解

JVM垃圾回收器全面解析与G1深度探秘及四种引用详解 JVM虚拟机&#xff08;七&#xff09;&#xff1a;JVM垃圾回收器全面解析与G1深度探秘及四种引用详解一、JVM有哪些垃圾回收器1. Serial回收器2. ParNew回收器3. Parallel Scavenge回收器4. Serial Old回收器5. Parallel Old回…

革新电销流程,数企云外呼开启便捷 “直通车”

在当今竞争激烈的商业环境中&#xff0c;电销作为一种重要的营销手段&#xff0c;依旧在企业的客户拓展与业务增长中扮演着关键角色。然而&#xff0c;传统电销流程常常面临诸多困扰&#xff0c;像是封卡封号风险、接通率不理想、客户开发与管理艰难以及销售考核复杂等问题&…

适合工程建筑行业的OA系统有什么推荐?

工程行业具有项目周期长、协作链条复杂等特性&#xff0c;传统管理模式下的 “人治”“纸质化” 弊端日益凸显。OA 系统作为数字化管理的核心载体&#xff0c;通过流程标准化、数据可视化&#xff0c;精准解决工程行业项目管理核心痛点。 泛微 e-office 深度聚焦工程场景&#…

车载刷写架构 --- ECU收到相同的blockSequenceCounter数据包的思考

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 周末洗了一个澡,换了一身衣服,出了门却不知道去哪儿,不知道去找谁,漫无目的走着,大概这就是成年人最深的孤独吧! 旧人不知我近况,新人不知我过…

C++ RAII 的用途及业务代码实现案例

C RAII 的用途及业务代码实现案例 RAII 的核心概念 RAII (Resource Acquisition Is Initialization&#xff0c;资源获取即初始化) 是 C 的核心编程范式&#xff0c;其核心思想是&#xff1a; 资源获取与对象构造绑定资源释放与对象析构绑定利用 C 对象生命周期自动管理资源…

黑马 SpringAI+DeepSeek 实战:从对话机器人到企业级知识库的大模型开发全攻略

附完整代码 项目案例&#xff0c;3 天吃透大模型应用开发核心技术 需要完整项目学习视频以及源码的私信博主&#xff0c;谢谢~大家一起加油呐&#xff01;&#xff01; 01.认识AI和大模型 小结 AI的发展过程 符号主义 机器学习 深度学习——自然语言处理&#xff08;NLP…

共工新闻社与韩国新华报社达成合作

在当下媒体融合浪潮奔涌的时代背景下&#xff0c;大湾区经济网战略媒体香港共工新闻社与韩国新华报社顺利签署合作协议&#xff0c;携手为传播全球化进程以及海外华文媒体从单一媒体向多媒体的内涵拓展&#xff0c;乃至区域经济协同与文化融合发展贡献力量。 缔结友好华文媒体协…

嵌入式Linux驱动——3 总线设备驱动模型

目录 1.总线设备驱动模型 1.1 总线设备驱动模型 1.2 设备树 1.3 platform_device 和 platform_driver 的匹配规则 1.3.1 最先比较 1.3.2 然后比较 1.3.3 最后比较 2.LED 模板驱动程序的改造&#xff1a;总线设备驱动模型 1.总线设备驱动模型 在前面的 led 驱动程序中…

操作系统常用命令

逻辑卷创建及挂载步骤&#xff1a; vgcreate vg_app /dev/sda //在sda盘上创建vg_app卷组 lvcreate -L 50G -n lv_mysql vg_app //在vg_app卷组上创建逻辑卷lv_mysql mkfs.xfs /dev/vg_app/lv_mysql //对lv_mysql 逻辑卷创建文件系统 mkdir mysql //创建mysql目录 ech…

Git 的进阶功能和技巧

1、分支的概念和使用 1.1、什么是分支&#xff1f; 分支&#xff08;Branch&#xff09;是在版本控制中非常重要的概念。几乎所有版本控制系统都支持某种形式的分支。在 Git 中&#xff0c;分支是 Git 强大功能之一&#xff0c;它允许我们从主开发线分离出来&#xff0c;在不…

mapbox基础,加载F4Map二维地图

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀前言1.1 ☘️mapboxgl.Map 地图对象1.2 ☘️mapboxgl.Map style属性二、🍀F4Map 简介2.1 ☘️技术特点2.2 ☘️核…

Conda使用方法详解

Conda是一个开源的包管理和环境管理系统&#xff0c;主要用于Python/R等科学计算领域&#xff0c;可以轻松管理不同项目的依赖关系。以下是Conda的详细使用方法&#xff1a; 一、安装与配置 1.安装Miniconda/Anaconda Miniconda是精简版&#xff0c;只包含conda和Python Ana…

Unity ViewportConstraint

一、组件功能概述 ViewportConstraint是一个基于世界坐标的UI边界约束组件&#xff0c;主要功能包括&#xff1a; 将UI元素限制在父容器范围内支持自定义内边距&#xff08;padding&#xff09;可独立控制水平和垂直方向的约束 二、实现原理 1. 边界计算&#xff08;世界坐…

代码随想录-动态规划24

leetcode-300-最长递增子序列 dp[i]表示i之前包括i的以nums[i]结尾的最长递增子序列的长度 dp[j]是(0,i-1)不包括i的以nums[i-1]结尾的最长递增子序列长度 int lengthOfLIS(int* nums, int numsSize) {if(numsSize < 1)return numsSize;int dp[numsSize];for(int i 0 ; i &…

银河麒麟V10 Ollama+ShellGPT打造Shell AI助手——筑梦之路

环境说明 1. 操作系统版本: 银河麒麟V10 2. CPU架构&#xff1a;X86 3. Python版本&#xff1a;3.12.9 4. 大模型&#xff1a;mistral:7b-instruct 准备工作 1. 编译安装python 3.12 # 下载python 源码wget https://www.python.org/ftp/python/3.12.9/Python-3.12.9.tg…

2025 跨平台技术如何选:KMP 与 Flutter 的核心差异

前言 在移动开发的演进历程中&#xff0c;跨平台技术始终是一个充满争议却无法回避的话题。从早期的 React Native 到如今的 Kotlin Multiplatform&#xff08;KMP&#xff09;和 Flutter&#xff0c;开发者们始终在代码复用与原生体验之间寻找平衡。本文我们从技术实现、性能…