开发一个RISC-V上的操作系统(七)—— 硬件定时器(Hardware Timer)

目录

往期文章传送门

一、硬件定时器

硬件实现

软件实现

二、上板测试


往期文章传送门

开发一个RISC-V上的操作系统(一)—— 环境搭建_riscv开发环境_Patarw_Li的博客-CSDN博客

开发一个RISC-V上的操作系统(二)—— 系统引导程序(Bootloader)_Patarw_Li的博客-CSDN博客

开发一个RISC-V上的操作系统(三)—— 串口驱动程序(UART)_Patarw_Li的博客-CSDN博客

开发一个RISC-V上的操作系统(四)—— 内存管理_Patarw_Li的博客-CSDN博客

开发一个RISC-V上的操作系统(五)—— 协作式多任务_Patarw_Li的博客-CSDN博客

开发一个RISC-V上的操作系统(六)—— 中断(interrupt)和异常(exception)_Patarw_Li的博客-CSDN博客

本节的代码在仓库的 05_HW_TIMER 目录下,仓库链接:riscv_os: 一个RISC-V上的简易操作系统

本文代码的运行调试会在前面开发的RISC-V处理器上进行,仓库链接:cpu_prj: 一个基于RISC-V指令集的CPU实现

一、硬件定时器

生活离不开对时间的管理,操作系统也是一样。

时钟节拍(Tick)

  • 操作系统中最小的时间单位。
  • Tick的单位(周期)由硬件定时器的周期决定(通常为1~100ms)。
  • Tick周期越小,系统精度越高,但开销越大。

系统时钟 

  • 操作系统维护一个整形计数值,记录着系统启动直到当前发生的Tick总数。

硬件实现

在本项目中,timer作为一个外设挂载在总线rib上,rtl文件为 cpu_prj\FPGA\rtl\perips\timer.v : 

五个读写信号用于读写timer模块中的寄存器,信号 timer_int_flag_o 用于给 clint 中断模块发出中断信号,verilog 代码如下:

// 32bit 定时器
module timer(input   wire                        clk                 ,input   wire                        rst_n               ,// 读写信号    input   wire                        wr_en_i             , // write enableinput   wire[`INST_ADDR_BUS]        wr_addr_i           , // write addressinput   wire[`INST_REG_DATA]        wr_data_i           , // write datainput   wire[`INST_ADDR_BUS]        rd_addr_i           , // read addressoutput  reg [`INST_REG_DATA]        rd_data_o           , // read data// 中断信号output  wire                        timer_int_flag_o    );localparam TIMER_CTRL = 4'h0;localparam TIMER_COUNT = 4'h4;localparam TIMER_EVALUE = 4'h8;// [0]: timer enable// [1]: timer int enable// [2]: timer int pending, software write 0 to clear it// addr offset: 0x00reg[31:0] timer_ctrl;// timer current count, read only// addr offset: 0x04reg[31:0] timer_count;// timer expired value// addr offset: 0x08reg[31:0] timer_evalue;assign timer_int_flag_o = ((timer_ctrl[2] == 1'b1) && (timer_ctrl[1] == 1'b1))? 1'b1 : 1'b0;// 读写寄存器,write before readalways @ (posedge clk or negedge rst_n) beginif (!rst_n) begintimer_ctrl <= `ZERO_WORD;timer_evalue <= `ZERO_WORD;endelse beginif (wr_en_i == 1'b1) begincase (wr_addr_i[3:0])TIMER_CTRL: begin// 这里代表软件只能把 timer_ctrl[2]置0,无法将其置1timer_ctrl = {wr_data_i[31:3], (timer_ctrl[2] & wr_data_i[2]), wr_data_i[1:0]};endTIMER_EVALUE: begintimer_evalue = wr_data_i;endendcaseendif(timer_ctrl[0] == 1'b1 && timer_count >= timer_evalue) begintimer_ctrl[0] = 1'b0;timer_ctrl[2] = 1'b1;endcase (rd_addr_i[3:0])TIMER_CTRL: beginrd_data_o = timer_ctrl;endTIMER_COUNT: beginrd_data_o = timer_count;endTIMER_EVALUE: beginrd_data_o = timer_evalue;enddefault: beginrd_data_o = `ZERO_WORD;endendcaseendend// 计数器 timer_countalways @ (posedge clk or negedge rst_n) beginif (!rst_n) begintimer_count <= `ZERO_WORD;endelse beginif (timer_ctrl[0] != 1'b1 || timer_count >= timer_evalue) begintimer_count <= `ZERO_WORD;endelse begintimer_count <= timer_count + 1'b1;endendendendmodule

其中:

timer_ctrl 为控制寄存器,低三位有效,分别是第0位 timer enable ,置1则 timer_count 开始计时;第1位 timer int enable,置1则允许发出中断信号,反之则不允许;第2位 timer int pending,当 timer_count >= timer_evalue 时,就把该位置1,表示有中断信号要发出,需要软件置0。

timer_count 为计数寄存器(只读)。

timer_evalue 存放过期值,用来与 timer_count 寄存器比较,当 timer_count >= timer_evalue 时则发出中断信号。

软件实现

代码实现为 riscv_os/05_HW_TIMER/timer.c :

// 1s
#define TIMER_INTERVAL 50000000/** The TIMER control registers are memory-mapped at address TIMER (defined in inc/platform.h). * This macro returns the address of one of the registers.*/
#define TIMER_REG_ADDRESS(reg) ((volatile uint32_t *) (TIMER + reg))/** TIMER registers map* timer_count is a read-only reg*/
#define TIMER_CTRL      0
#define TIMER_COUNT     4
#define TIMER_EVALUE    8#define timer_read_reg(reg) (*(TIMER_REG_ADDRESS(reg)))
#define timer_write_reg(reg, data) (*(TIMER_REG_ADDRESS(reg)) = (data))#define TIMER_EN          1 << 0
#define TIMER_INT_EN      1 << 1
#define TIMER_INT_PENDING 1 << 2static uint32_t _tick = 0;void timer_load(uint32_t interval)
{timer_write_reg(TIMER_EVALUE, interval);timer_write_reg(TIMER_CTRL, (timer_read_reg(TIMER_CTRL) | (TIMER_EN)));
}/** enable timer interrupt*/
void timer_init()
{timer_write_reg(TIMER_CTRL, (timer_read_reg(TIMER_CTRL) | (TIMER_INT_EN)));timer_load(TIMER_INTERVAL);
}void timer_handler()
{timer_write_reg(TIMER_CTRL, (timer_read_reg(TIMER_CTRL) & ~(TIMER_INT_PENDING)));_tick++;printf("tick: %d\n", _tick);timer_load(TIMER_INTERVAL);
}

其中:

_tick 为该模块维护的全局时间节拍。

timer_load(uint32_t interval) 函数用于给定时器模块寄存器赋值,interval 个硬件时钟周期后发出定时器中断(如果 interval = 板子系统时钟频率,相当于1s)。

timer_init() 函数用于给定时器模块寄存器初始化。

timer_handler() 函数用于执行定时器中断处理,当定时器中断发生的时候,执行这个函数的内容。该函数会将 _tick 值加一后,执行 timer_load(uint32_t interval) 函数,从而达到持续计数的功能。

二、上板测试

烧录到板子上后,打开串口调试程序,可以看到tick值一直在计数,从而实现系统时钟的功能:

遇到问题欢迎加群 892873718 交流~ 

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

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

相关文章

AD域机器KMS自动激活

1、打开AD域控&#xff0c;点击DNS管理 2、创建其它记录 3、选择服务位置 SRV 4、输入相关信息 服务&#xff1a;_VLMCS协议&#xff1a;_TCP权重&#xff1a;100端口号&#xff1a;1688KMS服务器地址&#xff1a;10.3.0.211 5、成功&#xff0c;这时域内主机重启后&#xff0…

腾讯云CVM服务器2核2g1m带宽支持多少人访问?

腾讯云2核2g1m的服务器支持多少人同时访问&#xff1f;2核2g1m云服务器短板是在1M公网带宽上&#xff0c;腾讯云服务器网以网站应用为例&#xff0c;当大规模用户同时访问网站时&#xff0c;很大概率会卡在公网带宽上&#xff0c;所以压根就谈不上2核2G的CPU内存计算性能是否够…

烧写PYNQ镜像到SD卡

一&#xff0c;安装 Win32diskimager 首先将Micro SD卡插入读卡器的卡槽中&#xff0c;然后再将读卡器插入计算机USB接口&#xff0c;此时计算机将会识别到插入的可移动磁盘。双击打开Win32DiskImager-1.0.0.zip 压缩文件&#xff0c;里面win32diskimager-1.0.0-install.exe文…

Postman

Postman 简介下载安装 简介 Postman 是一款用于测试和开发 API&#xff08;应用程序编程接口&#xff09;的工具&#xff0c;它提供了用户友好的界面和丰富的功能&#xff0c;帮助开发者轻松地创建、测试、调试和文档化各种类型的 API。无论是在构建 Web 应用、移动应用还是其…

“深入解析Maven:安装、创建项目和依赖管理的完全指南“

目录 引言Maven的安装创建Maven项目之前的装备工作Eclipse创建新的Maven项目项目依赖管理 总结 引言 Maven是一个流行的项目管理工具&#xff0c;被广泛用于Java项目的构建、依赖管理和部署。它提供了一种简单而强大的方式来管理项目的各个方面&#xff0c;使开发人员能够更专…

LeetCode 1631. Path With Minimum Effort【最小瓶颈路;二分+BFS或DFS;计数排序+并查集;最小生成树】1947

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…

阿里云PolarDB数据库倚天ARM架构详细介绍

阿里云云原生数据库PolarDB MySQL版推出倚天ARM架构&#xff0c;倚天ARM架构规格相比X86架构规格最高降价45%&#xff0c;PolarDB针对自研倚天芯片&#xff0c;从芯片到数据库内核全链路优化&#xff0c;助力企业降本增效。基于阿里云自研的倚天服务器&#xff0c;同时在数据库…

pytest fixture 用于teardown工作

fixture通过scope参数控制setup级别&#xff0c;setup作为用例之前前的操作&#xff0c;用例执行完之后那肯定也有teardown操作。这里用到fixture的teardown操作并不是独立的函数&#xff0c;用yield关键字呼唤teardown操作。 举个例子&#xff1a; 输出&#xff1a; 说明&…

二十二、策略模式

目录 1、项目需求2、传统方案解决鸭子问题的分析和代码实现3、传统方式实现存在的问题分析和解决方案4、策略模式基本介绍5、使用策略模式解决鸭子问题6、策略模式的注意事项和细节7、策略模式的使用场景 以具体项目来演示为什么需要策略模式&#xff0c;策略模式的优点&#x…

贝锐蒲公英:快速搭建连锁门店监控体系,赋能企业高效管理

随着国民生活水平的提高和零售场景的变革&#xff0c;消费者对于餐饮类目的消费支出不断增加&#xff0c;线下社区生鲜商超作为下沉市场最主要的消费场景之一&#xff0c;蕴藏着巨大价值机会。 对于线下连锁生鲜超市而言&#xff0c;连锁门店多、员工多&#xff0c;门店管理时会…

ubuntu磁盘管理

show partition information 挂载设备在这 显示文件系统信息 build file system mkfs -t ext4 /dev/nvme0n1p4命令作用&#xff1a;将/dev/nvme0n1p4 格式化为 ext4 建立交换分区 mkswap -c -v1 /dev/nvme0n1p4 102400-c&#xff1a;check -v1&#xff1a;新版交换分区 -v0&…

gitblit windows部署

1.官网下载 往死慢&#xff0c;我是从百度找的1.9.1&#xff0c;几乎就是最新版 http://www.gitblit.com/ 2.解压 下载下来是一个zip压缩包&#xff0c;直接解压即可 3.配置 3.1.配置资源库路径 找到data文件下的gitblit.properties文件&#xff0c;用Notepad打开 **注意路…

小程序具体开发

window 导航栏 属性名类型默认值作用navigationBarTitleText string字字符串导航栏标题内容navigationBarBackgroundColorHexcolor#000000设置导航栏背景颜色&#xff08;比如荧黄色 #ffa&#xff09;navigationBarTextStylestringwhite设置导航栏标题的颜色&#xff08;仅含有…

通过将信号频谱与噪声频谱进行比较,自动检测适当的带通滤波器转折频率研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

【数据结构与算法】十大经典排序算法-堆排序

&#x1f31f;个人博客&#xff1a;www.hellocode.top &#x1f3f0;Java知识导航&#xff1a;Java-Navigate &#x1f525;CSDN&#xff1a;HelloCode. &#x1f31e;知乎&#xff1a;HelloCode &#x1f334;掘金&#xff1a;HelloCode ⚡如有问题&#xff0c;欢迎指正&#…

用库造一个list的轮子 【C++】

文章目录 list的模拟实现默认成员函数构造函数拷贝构造函数赋值运算符重载析构函数 迭代器迭代器为什么要存在&#xff1f;const_iteratorbegin和end inserterasepush_back && pop_backpush_front &&pop_frontswap 完整代码 list的模拟实现 默认成员函数 构造…

HCIP BGP小综合

BGP小综合 AS配置AS1AS2 中的小自治系统64512AS2 中的小自治系统64513AS3 测试 首先该实验分成三个AS&#xff0c;AS2里面有联邦&#xff0c;所以配置顺序 要先将IBGP通&#xff0c;然后配置AS1,AS3和联邦 AS配置 AS1 R1 # bgp 1router-id 1.1.1.1peer 12.1.1.2 as-number …

二十二、责任链模式

目录 1、使用demo演示责任链模式2、传统方案解决oa系统审批3、传统方案解决oa系统审批存在的问题4、职责链模式基本介绍5、职责链模式原理类图6、职责链模式解决oa系统采购审批7、职责链模式的注意事项和细节8、职责链模式的实际使用场景举例 1、使用demo演示责任链模式 学校o…

数据库相关面试题

巩固基础&#xff0c;砥砺前行 。 只有不断重复&#xff0c;才能做到超越自己。 能坚持把简单的事情做到极致&#xff0c;也是不容易的。 mysql怎么优化 : MySQL的优化可以从以下几个方面入手&#xff1a; 数据库设计优化&#xff1a;合理设计表结构&#xff0c;选择合适的数…

GitHub 如何部署写好的H5静态页面

感谢粉皮zu的私信&#xff0c;又有素材写笔记了。(●’◡’●) 刚好记录一下我示例代码的GitHub部署配置&#xff0c;以便于后期追加仓库。 效果 环境 gitwin 步骤 第一步 新建仓库 第二步 拉取代码 将仓库clone到本地 git clone 地址第三步 部署文件 新建.github\workflo…