背景
基于microblaze的裸机程序设计中,通常会遇到需要执行多个任务,并且每个任务的执行时间间隔有所不同的情况,通常使用RTOS是一个好的选择,但是对于简单任务,RTOS是一个沉重的负担。另一个可行的选项就是基于Timer中断的任务调度。
下面使用ChatGPT来回答使用基于中断的任务调度和基于RTOS的任务调度的异同:
-
任务调度方式
基于 Timer 的多任务多优先级设计任务通常由 定时器(Timer)中断 触发,基于 时间片轮转 或 优先级决策 进行任务切换。
一般采用 轮询(Polling) 或 中断驱动(Interrupt-driven) 机制进行任务管理。需要手动管理任务执行顺序,任务之间通常通过 全局变量、标志位或软中断 进行通信。基于 RTOS 的多任务调度由 RTOS 内核 负责任务调度,提供 抢占式(Preemptive) 或 协作式(Cooperative) 任务调度机制。采用 优先级调度(Priority Scheduling)、时间片轮转(Time-Slicing)、抢占式调度(Preemptive Scheduling)等策略进行任务管理。任务间可以通过 信号量(Semaphore)、消息队列(Message Queue)、事件标志(Event Flags)等 方式进行同步和通信。 -
系统复杂度
基于 Timer代码逻辑简单,适用于 简单的嵌入式系统,不需要复杂的任务管理。任务切换依赖于定时器 周期性触发,可能需要手动控制任务优先级。维护困难,当任务增多时,管理复杂度急剧上升。基于 RTOS具有 任务管理、同步机制、内存管理 等完整的功能,适用于 复杂的实时系统。更易扩展,支持多个任务动态管理,任务优先级可以灵活调整。需要学习 RTOS 的 API 和概念,系统资源占用较大。 -
实时性保障
基于 Timer实时性取决于定时器和中断处理的效率,如果某个任务执行时间过长,可能会影响其他任务。任务调度通常是 固定的,无法动态调整任务优先级。适用于 低实时性 需求的场景,如简单传感器数据采集、LED 控制等。基于 RTOS采用 优先级调度 和 任务抢占,可以保证高优先级任务及时执行。具有实时性保障,适用于 对时序要求严格 的应用,如工业控制、汽车电子、医疗设备等。 -
可扩展性
基于 Timer扩展性差,随着任务增多,定时器管理和任务调度的复杂度会大幅提升。需要手动管理任务的触发和执行,难以适应动态变化的需求。基于 RTOS可扩展性强,支持动态创建和销毁任务,适用于 多任务、复杂逻辑 的嵌入式系统。任务间可以通过 队列、信号量 进行高效通信,适应更复杂的应用场景。
适用场景 | 设计方式 |
---|---|
基于 Timer | 简单的嵌入式系统,任务少,逻辑固定,如 LED 控制、定时传感器采样等。 |
基于 RTOS | 复杂的嵌入式系统,需要多任务调度、实时性保障,如机器人控制、工业自动化等。 |
总结
基于 Timer 适用于任务较少、实时性要求不高 的系统,逻辑简单但不易扩展。
基于 RTOS 适用于任务较多、实时性要求高 的系统,调度更灵活但系统资源消耗较大。
如果你的系统简单、资源受限,可以使用基于 Timer 的调度方式;如果需要更好的实时性和可扩展性,使用 RTOS 更合适。
硬件设计
此处需要添加必须要添加的有Timer,GPIO,其他的IIC,UART可以忽略
对应的block design tcl代码如下
################################################################
# This is a generated script based on design: design_1
#
# Though there are limitations about the generated script,
# the main purpose of this utility is to make learning
# IP Integrator Tcl commands easier.
################################################################
namespace eval _tcl {
proc get_script_folder {} {
set script_path [file normalize [info script]]
set script_folder [file dirname $script_path]
return $script_folder
}
}
variable script_folder
set script_folder [_tcl::get_script_folder]
################################################################
# Check if script is running in correct Vivado version.
################################################################
set scripts_vivado_version 2023.2
set current_vivado_version [version -short]
if { [string first $scripts_vivado_version $current_vivado_version] == -1 } {
puts ""
if { [string compare $scripts_vivado_version $current_vivado_version] > 0 } {
catch {common::send_gid_msg -ssname BD::TCL -id 2042 -severity "ERROR" " This script was generated using Vivado <$scripts_vivado_version> and is being run in <$current_vivado_version> of Vivado. Sourcing the script failed since it was created with a future version of Vivado."}
} else {
catch {common::send_gid_msg -ssname BD::TCL -id 2041 -severity "ERROR" "This script was generated using Vivado <$scripts_vivado_version> and is being run in <$current_vivado_version> of Vivado. Please run the script in Vivado <$scripts_vivado_version> then open the design in Vivado <$current_vivado_version>. Upgrade the design by running \"Tools => Report => Report IP Status...\", then run write_bd_tcl to create an updated script."}
}
return 1
}
################################################################
# START
################################################################
# To test this script, run the following commands from Vivado Tcl console:
# source design_1_script.tcl
# If there is no project opened, this script will create a
# project, but make sure you do not have an existing project
# <./myproj/project_1.xpr> in the current working folder.
set list_projs [get_projects -quiet]
if { $list_projs eq "" } {
create_project project_1 myproj -part xc7a12ticsg325-1L
}
# CHANGE DESIGN NAME HERE
variable design_name
set design_name design_1
# If you do not already have an existing IP Integrator design open,
# you can create a design using the following command:
# create_bd_design $design_name
# Creating design if needed
set errMsg ""
set nRet 0
set cur_design [current_bd_design -quiet]
set list_cells [get_bd_cells -quiet]
if { ${design_name} eq "" } {
# USE CASES:
# 1) Design_name not set
set errMsg "Please set the variable <design_name> to a non-empty value."
set nRet 1
} elseif { ${cur_design} ne "" && ${list_cells} eq "" } {
# USE CASES:
# 2): Current design opened AND is empty AND names same.
# 3): Current design opened AND is empty AND names diff; design_name NOT in project.
# 4): Current design opened AND is empty AND names diff; design_name exists in project.
if { $cur_design ne $design_name } {
common::send_gid_msg -ssname BD::TCL -id 2001 -severity "INFO" "Changing value of <design_name> from <$design_name> to <$cur_design> since current design is empty."
set design_name [get_property NAME $cur_design]
}
common::send_gid_msg -ssname BD::TCL -id 2002 -severity "INFO" "Constructing design in IPI design <$cur_design>..."
} elseif { ${cur_design} ne "" && $list_cells ne "" && $cur_design eq $design_name } {
# USE CASES:
# 5) Current design opened AND has components AND same names.
set errMsg "Design <$design_name> already exists in your project, please set the variable <design_name> to another value."
set nRet 1
} elseif { [get_files -quiet ${design_name}.bd] ne "" } {
# USE CASES:
# 6) Current opened design, has components, but diff names, design_name exists in project.
# 7) No opened design, design_name exists in project.
set errMsg "Design <$design_name> already exists in your project, please set the variable <design_name> to another value."
set nRet 2
} else {
# USE CASES:
# 8) No opened design, design_name not in project.
# 9) Current opened design, has components, but diff names, design_name not in project.
common::send_gid_msg -ssname BD::TCL -id 2003 -severity "INFO" "Currently there is no design <$design_name> in project, so creating one..."
create_bd_design $design_name
common::send_gid_msg -ssname BD::TCL -id 2004 -severity "INFO" "Making design <$design_name> as current_bd_design."
current_bd_design $design_name
}
common::send_gid_msg -ssname BD::TCL -id 2005 -severity "INFO" "Currently the variable <design_name> is equal to \"$design_name\"."
if { $nRet != 0 } {
catch {common::send_gid_msg -ssname BD::TCL -id 2006 -severity "ERROR" $errMsg}
return $nRet
}
set bCheckIPsPassed 1
##################################################################
# CHECK IPs
##################################################################
set bCheckIPs 1
if { $bCheckIPs == 1 } {
set list_check_ips "\
xilinx.com:ip:microblaze:11.0\
xilinx.com:ip:axi_uartlite:2.0\
xilinx.com:ip:axi_gpio:2.0\
xilinx.com:ip:axi_timer:2.0\
xilinx.com:ip:axi_iic:2.1\
xilinx.com:ip:axi_intc:4.1\
xilinx.com:ip:mdm:3.2\
xilinx.com:ip:clk_wiz:6.0\
xilinx.com:ip:proc_sys_reset:5.0\
xilinx.com:ip:lmb_v10:3.0\
xilinx.com:ip:lmb_bram_if_cntlr:4.0\
xilinx.com:ip:blk_mem_gen:8.4\
"
set list_ips_missing ""
common::send_gid_msg -ssname BD::TCL -id 2011 -severity "INFO" "Checking if the following IPs exist in the project's IP catalog: $list_check_ips ."
foreach ip_vlnv $list_check_ips {
set ip_obj [get_ipdefs -all $ip_vlnv]
if { $ip_obj eq "" } {
lappend list_ips_missing $ip_vlnv
}
}
if { $list_ips_missing ne "" } {
catch {common::send_gid_msg -ssname BD::TCL -id 2012 -severity "ERROR" "The following IPs are not found in the IP Catalog:\n $list_ips_missing\n\nResolution: Please add the repository containing the IP(s) to the project." }
set bCheckIPsPassed 0
}
}
if { $bCheckIPsPassed != 1 } {
common::send_gid_msg -ssname BD::TCL -id 2023 -severity "WARNING" "Will not continue with creation of design due to the error(s) above."
return 3
}
##################################################################
# DESIGN PROCs
##################################################################
# Hierarchical cell: microblaze_0_local_memory
proc create_hier_cell_microblaze_0_local_memory { parentCell nameHier } {
variable script_folder
if { $parentCel