【RISC-V设计-14】- RISC-V处理器设计K0A之打印输出
【RISC-V设计-14】- RISC-V处理器设计K0A之打印输出
文章目录
- 【RISC-V设计-14】- RISC-V处理器设计K0A之打印输出
- 1.简介
- 2.验证用例
- 3.软件代码
- 4.链接脚本
- 5.编译脚本
- 6.仿真结果
- 6.1 复位结束
- 6.2 运行成功
- 6.3 终端打印
- 7.总结
1.简介
本文将详细阐述如何利用 printf
来打印字符串,在此过程中使用了一个开源的库 xprintf
。xprintf
是一个紧凑的字符串 I/O 库,它非常适用于程序存储器不足以用于常规 printf 函数的微型微控制器。通过调用 xprintf
函数成功输出了“Hello RISC-V World!”,同时还对该库的使用方法以及如何进行编译等内容加以介绍。xprintf
库的地址为:http://elm-chan.org/fsw/strf/xprintf.html,下载后使将使用xprintf.c
和xprintf.h
两个文件。
2.验证用例
// -------------------------------------------------------------------------------------------------
// Copyright 2024 Kearn Chen, kearn.chen@aliyun.com
//
// 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.
// -------------------------------------------------------------------------------------------------
// Description :
// 1. Run Hello World!
// -------------------------------------------------------------------------------------------------task initcase;load_instr("hello_world_test/hello_world_test.bin");endtasktask testcase;#2_000_000;endtask
在验证用例中,任务initcase
加载Bin文件到仿真模型中,任务testcase
延迟2毫秒,等待CPU执行完软件指令。
3.软件代码
// -------------------------------------------------------------------------------------------------
// Copyright 2024 Kearn Chen, kearn.chen@aliyun.com
//
// 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 "xprintf.h"void xfunc_output_callback(int c)
{*((volatile unsigned int *)0xc0000) = c;
}void simulation_finish(void)
{*((volatile unsigned int *)0xc0004) = 0x12345678;
}int main(void)
{xfunc_output = xfunc_output_callback;xprintf("Hello RISC-V World!\n");simulation_finish();while(1);
}
上述代码中,首先是初始化打印输出的回调函数,在回调函数中,将要输出的字符写入地址0xc0000寄存器中,这个寄存器在之前的文章【RISC-V设计-12】- RISC-V处理器设计K0A之验证环境中第4部分有描述,写入此寄存器的数据会存入到一个队列里面,在遇到输出字符为\n
时,将整个队列内的输出到终端。在输出完字符后,调用simulation_finish
函数,仿真运行结束。在xprintf
库中,有一些宏定义,如下所示,根据需要可以打开和关闭。
#define XF_USE_OUTPUT 1 /* 1: Enable output functions */
#define XF_CRLF 0 /* 1: Convert \n ==> \r\n in the output char */
#define XF_USE_DUMP 0 /* 1: Enable put_dump function */
#define XF_USE_LLI 0 /* 1: Enable long long integer in size prefix ll */
#define XF_USE_FP 0 /* 1: Enable support for floating point in type e and f */
#define XF_DPC '.' /* Decimal separator for floating point */
#define XF_USE_INPUT 0 /* 1: Enable input functions */
#define XF_INPUT_ECHO 0 /* 1: Echo back input chars in xgets function */
4.链接脚本
ENTRY( _start )__stack_size = 2048;PROVIDE( _stack_size = __stack_size );MEMORY
{ROM (rx) : ORIGIN = 0x00000, LENGTH = 512KRAM (xrw) : ORIGIN = 0x80000, LENGTH = 256K
}SECTIONS
{.init :{_sinit = .;. = ALIGN(4);KEEP(*(SORT_NONE(.init))). = ALIGN(4);_einit = .;} >ROM.text :{. = ALIGN(4);*(.text)*(.text.*)*(.rodata)*(.rodata*)*(.gnu.linkonce.t.*). = ALIGN(4);} >ROM.fini :{KEEP(*(SORT_NONE(.fini))). = ALIGN(4);} >ROMPROVIDE( _etext = . );PROVIDE( _eitcm = . ); .preinit_array :{PROVIDE_HIDDEN (__preinit_array_start = .);KEEP (*(.preinit_array))PROVIDE_HIDDEN (__preinit_array_end = .);} >ROM.init_array :{PROVIDE_HIDDEN (__init_array_start = .);KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))PROVIDE_HIDDEN (__init_array_end = .);} >ROM.fini_array :{PROVIDE_HIDDEN (__fini_array_start = .);KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))PROVIDE_HIDDEN (__fini_array_end = .);} >ROM.ctors :{KEEP (*crtbegin.o(.ctors))KEEP (*crtbegin?.o(.ctors))KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))KEEP (*(SORT(.ctors.*)))KEEP (*(.ctors))} >ROM.dtors :{KEEP (*crtbegin.o(.dtors))KEEP (*crtbegin?.o(.dtors))KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))KEEP (*(SORT(.dtors.*)))KEEP (*(.dtors))} >ROM.dalign :{. = ALIGN(4);PROVIDE(_data_vma = .);} >RAM AT>ROM .dlalign :{. = ALIGN(4); PROVIDE(_data_lma = .);} >ROM.data :{. = ALIGN(4);*(.gnu.linkonce.r.*)*(.data .data.*)*(.gnu.linkonce.d.*). = ALIGN(8);PROVIDE( __global_pointer$ = . + 0x800 );*(.sdata .sdata.*)*(.sdata2*)*(.gnu.linkonce.s.*). = ALIGN(8);*(.srodata.cst16)*(.srodata.cst8)*(.srodata.cst4)*(.srodata.cst2)*(.srodata .srodata.*). = ALIGN(4);PROVIDE( _edata = .);} >RAM AT>ROM.bss :{. = ALIGN(4);PROVIDE( _sbss = .);*(.sbss*)*(.gnu.linkonce.sb.*)*(.bss*)*(.gnu.linkonce.b.*) *(COMMON*). = ALIGN(4);PROVIDE( _ebss = .);} >RAM AT>ROMPROVIDE( _end = _ebss);PROVIDE( end = . );.stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size :{PROVIDE( _heap_end = . );. = ALIGN(4);PROVIDE(_susrstack = . );. = . + __stack_size;PROVIDE( _eusrstack = .);} >RAM
}
5.编译脚本
# -------------------------------------------------------------------------------------------------
# Copyright 2024 Kearn Chen, kearn.chen@aliyun.com
#
# 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.
# -------------------------------------------------------------------------------------------------PREFIX := riscv-none-embed-LINKER := ../common/link.ldOBJECT += ../common/startup.o
OBJECT += ../common/xprintf.o
OBJECT += main.oCFLAGS := -march=rv32e -mabi=ilp32e -I../commonLFLAGS := -march=rv32e -mabi=ilp32e -T$(LINKER) -nostartfilesTARGET := $(notdir $(shell pwd))all : $(TARGET).asm $(TARGET).bin%.bin : %.elf$(PREFIX)objcopy -Obinary $< $@%.asm : %.elf$(PREFIX)objdump -D $< > $@%.elf : $(OBJECT)$(PREFIX)gcc $(LFLAGS) -o $@ $^$(PREFIX)size $@%.o : %.S$(PREFIX)gcc $(CFLAGS) -c -o $@ $<%.o : %.c$(PREFIX)gcc $(CFLAGS) -c -o $@ $<clean :@rm -rf *.o *.elf *.asm *.bin ../common/*.o.PHONY: clean all.SECONDARY:
上述脚本中所使用的startup.o文件为startup.S文件所编译产生,这个文件在之前的文章【RISC-V设计-09】- RISC-V处理器设计K0A之CIC中第5部分已有介绍,这个文件为RISCV-K0A
的启动文件,同时还具有中断处理的功能。编译结果如下
riscv-none-embed-gcc -march=rv32e -mabi=ilp32e -I../common -c -o ../common/startup.o ../common/startup.S
riscv-none-embed-gcc -march=rv32e -mabi=ilp32e -I../common -c -o ../common/xprintf.o ../common/xprintf.c
riscv-none-embed-gcc -march=rv32e -mabi=ilp32e -I../common -c -o main.o main.c
riscv-none-embed-gcc -march=rv32e -mabi=ilp32e -T../common/link.ld -nostartfiles -o hello_world_test.elf ../common/startup.o ../common/xprintf.o main.o
riscv-none-embed-size hello_world_test.elftext data bss dec hex filename3164 0 2056 5220 1464 hello_world_test.elf
riscv-none-embed-objdump -D hello_world_test.elf > hello_world_test.asm
riscv-none-embed-objcopy -Obinary hello_world_test.elf hello_world_test.bin
6.仿真结果
6.1 复位结束
6.2 运行成功
6.3 终端打印
*Verdi* FSDB WARNING: The FSDB file already exists. Overwriting the FSDB file may crash the programs that are using this file.
*Verdi* : Create FSDB file 'novas.fsdb'
*Verdi* : Begin traversing the scopes, layer (0).
*Verdi* : End of traversing.
[MCU_INFO] : Hello RISC-V World!
$finish called from file "../env/slave_model.v", line 136.
$finish at simulation time 43210
7.总结
本文介绍了如何在RISCV-K0A
上使用xprintf
库文件,并通过xprintf
输出了"Hello RISC-V World!"到终端显示。
相关文章:

【RISC-V设计-14】- RISC-V处理器设计K0A之打印输出
【RISC-V设计-14】- RISC-V处理器设计K0A之打印输出 文章目录 【RISC-V设计-14】- RISC-V处理器设计K0A之打印输出1.简介2.验证用例3.软件代码4.链接脚本5.编译脚本6.仿真结果6.1 复位结束6.2 运行成功6.3 终端打印 7.总结 1.简介 本文将详细阐述如何利用 printf 来打印字符串…...

时序预测|基于变分模态分解-时域卷积-双向长短期记忆-注意力机制多变量时间序列预测VMD-TCN-BiLSTM-Attention
时序预测|基于变分模态分解-时域卷积-双向长短期记忆-注意力机制多变量时间序列预测VMD-TCN-BiLSTM-Attention 文章目录 前言时序预测|基于变分模态分解-时域卷积-双向长短期记忆-注意力机制多变量时间序列预测VMD-TCN-BiLSTM-Attention 一、VMD-TCN-BiLSTM-Attention模型1. **…...
Python知识点:如何使用Godot与Python进行游戏脚本编写
在Godot中使用Python进行游戏脚本编写,你需要通过一个插件来实现,因为Godot原生支持的脚本语言是GDScript、VisualScript和C#。这个插件被称为Godot-Python,它允许你在Godot引擎中使用Python编写脚本。以下是详细的步骤指导你如何配置和使用G…...

Spring MVC数据绑定和响应学习笔记
学习视频:12001 数据绑定_哔哩哔哩_bilibili 目录 1.数据绑定 简单数据绑定 默认类型数据绑定 简单数据类型绑定的概念 参数别名的设置 PathVariable注解的两个常用属性 POJO绑定 自定义类型转换器 xml方式 注解方式 数组绑定 集合绑定 复杂POJO绑定 属性为对象类…...

Vulnhub JIS-CTF靶机详解
项目地址 https://www.vulnhub.com/entry/jis-ctf-vulnupload,228/https://www.vulnhub.com/entry/jis-ctf-vulnupload,228/ 修改靶机的网卡 开机时长按shift,进入此页面 选择root模式进入 将只读模式改为读写模式 mount -o remount,rw / 查看本机的网卡名称 …...

FPGA资源评估
FPGA资源评估 文章目录 FPGA资源评估前言一、资源评估1.1 资源有哪些1.2 资源统计 二、 FPGA 的基本结构三、 更为复杂的 FPGA 架构 前言 一、资源评估 大家在项目中一般会要遇到需要资源评估的情况,例如立了新项目,前期需要确定使用什么FPGA片子&…...
REST framework中Views API学习
REST framework提供了一个APIView类,它是Django的View类的子类。 APIView类和一般的View类有以下不同: 被传入到处理方法的请求不会是Django的HttpRequest类的实例,而是REST framework的Request类的实例。处理方法可以返回REST framework的…...
Vue(四)——总结
渐进式JavaScript框架 Vue.js是一套构建用户界面(UI)的渐进式JavaScript框架。 1、库和框架的区别? 库:库是提供给开发者的一个封装好的特定于某一方面的集合(方法和函数),库没有控制权&…...

计算机毕业设计 招生宣传管理系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试
🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点…...

练习题PHP5.6+变长参数 ⇒ usort回调后门 ⇒ 任意代码执行
突破长度限制 使用usort上传后门 usort — 使用用户自定义的比较函数对数组中的值进行排序 paramusort(...$GET); ...为php设置可变长参数 在url地址栏中输入[]test&1[]phpinfo();&2assert 包含了phpiinfo()命令执行 结合usort使用 assert…...

EPLAN关于PLC的输入输出模块绘制
EPLAN关于PLC的输入输出模块绘制 总览图上的PLC绘制原理图上的PLC绘制编辑IO注释显示总览界面IO注释自动关联总览IO地址 总览图上的PLC绘制 右键项目【新建】 页类型选择【总览】,描述可以自由编辑,之后确认即可。 由于我们需要绘制PLC的输入输出&#x…...

【Linux】sersync 实时同步
原理 rsync 是不支持实时同步的,通常我们借助于 inotify 这个软件来实时监控文件变化,一旦inotify 监控到文件变化,则立即调用 rsync 进行同步,推送到 rsync 服务端。 环境准备 步骤1:获取数据包 获取 sersync 的包…...

Unity 资源分享 之 恐龙Ceratosaurus资源模型携 82 个动画来袭
Unity 资源分享 之 恐龙Ceratosaurus资源模型携 82 个动画来袭 一、前言二,资源包内容三、免费获取资源包 一、前言 亲爱的 Unity 开发者和爱好者们,大家好!今天要为大家分享一份超级酷炫的 Unity 资源——恐龙资源模型,而且它还…...

【AI绘画】 学习内容简介
AI绘画-学习内容简介 1. 效果展示 本次测试主要结果展示如下: 卡通手办定制1 卡通手办定制2 艺术写真定制 2. 主要目录 AI 绘画- 文生图,图生图及lora使用(基于diffusers) AI 绘画- 模型转换与快速生图(基于diffus…...

树形结构查找(B树、B+树)
平衡树结构的树高为 O(logn) ,平衡树结构包括两种平衡二叉树结构(分别为 AVL 树和 RBT)以及一种树结构(B-Tree,又称 B 树,它的度大于 2 )。AVL 树和 RBT 适合内部存储的应用,而 B 树…...

网络通信(TCP/UDP协议 三次握手四次挥手 )
三、TCP协议与UDP协议 1、TCP/IP、TCP、 UDP是什么 TCP/IP协议是一个协议簇,里面包括很多协议的, UDP只是其中的一个, 之所以命名为TCP/IP协议, 因为TCP、 IP协议是两个很重要的协议,就用他两命名了,而TCP…...
C# ADO.Net 通用按月建表插入数据
原理是获取原表表结构以及索引动态拼接建表SQL,如果月表存在则不创建,不存在则创建表结构 代码如下 /// <summary>/// 根据指定的表名和时间按月进行建表插入(如果不存在对应的月表)/// </summary>/// <param nam…...

19-ESP32-C3加大固件储存区
1默认编译情况。 2、改flash4M。ESP-IDF Partition Table Editor修改。 3、设置输入Partition Table 改自定义.CSV。保存。 4、查看命令输入Partition Table Editor打开-分区表编辑器UI。按图片增加。 nvs,data,nvs,0x9000,0x6000,, phy_init,data,phy,0xF000,0x1000,, factory…...

【STL】stack/queue 容器适配器 deque
1.stack的介绍和使用 1.1.stack的介绍 1. stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。 2. stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容…...

(回溯) LeetCode 17. 电话号码的组合
原题链接 一. 题目描述 17. 电话号码的字母组合 已解答 中等 相关标签 相关企业 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...

从零开始了解数据采集(二十八)——制造业数字孪生
近年来,我国的工业领域正经历一场前所未有的数字化变革,从“双碳目标”到工业互联网平台的推广,国家政策和市场需求共同推动了制造业的升级。在这场变革中,数字孪生技术成为备受关注的关键工具,它不仅让企业“看见”设…...

归并排序:分治思想的高效排序
目录 基本原理 流程图解 实现方法 递归实现 非递归实现 演示过程 时间复杂度 基本原理 归并排序(Merge Sort)是一种基于分治思想的排序算法,由约翰冯诺伊曼在1945年提出。其核心思想包括: 分割(Divide):将待排序数组递归地分成两个子…...

高效的后台管理系统——可进行二次开发
随着互联网技术的迅猛发展,企业的数字化管理变得愈加重要。后台管理系统作为数据存储与业务管理的核心,成为了现代企业不可或缺的一部分。今天我们要介绍的是一款名为 若依后台管理框架 的系统,它不仅支持跨平台应用,还能提供丰富…...

如何做好一份技术文档?从规划到实践的完整指南
如何做好一份技术文档?从规划到实践的完整指南 🌟 嗨,我是IRpickstars! 🌌 总有一行代码,能点亮万千星辰。 🔍 在技术的宇宙中,我愿做永不停歇的探索者。 ✨ 用代码丈量世界&…...

Qt的学习(二)
1. 创建Hello Word 两种方式,实现helloworld: 1.通过图形化的方式,在界面上创建出一个控件,显示helloworld 2.通过纯代码的方式,通过编写代码,在界面上创建控件, 显示hello world; …...
算法刷题-回溯
今天给大家分享的还是一道关于dfs回溯的问题,对于这类问题大家还是要多刷和总结,总体难度还是偏大。 对于回溯问题有几个关键点: 1.首先对于这类回溯可以节点可以随机选择的问题,要做mian函数中循环调用dfs(i&#x…...
Electron简介(附电子书学习资料)
一、什么是Electron? Electron 是一个由 GitHub 开发的 开源框架,允许开发者使用 Web技术(HTML、CSS、JavaScript) 构建跨平台的桌面应用程序(Windows、macOS、Linux)。它将 Chromium浏览器内核 和 Node.j…...