@ -1,8 +1,8 @@
 
			
		
	
		
		
			
				
					
					# 第八章. : ( ) 
# 第八章. : ( ) 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					### 目录
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					### 目录  
- [8.1 实验5的基础知识 ](#fundamental )  
 
			
				
				
			
		
	
		
		
			
				
					
					- [8.1 实验4的基础知识 ](#fundamental )  
 
			
		
	
		
		
	
		
		
			
				
					
					  - [8.1.1  pynq开发板介绍 ](#subsec_pynq )
  - [8.1.1  pynq开发板介绍 ](#subsec_pynq )
 
			
		
	
		
		
			
				
					
					  - [8.1.2  内存映射I/O(MMIO) ](#subsec_MMIO ) 
  - [8.1.2  内存映射I/O(MMIO) ](#subsec_MMIO ) 
 
			
		
	
		
		
			
				
					
					  - [8.1.3  riscv-fesvr原理 ](#subsec_fesvr )
  - [8.1.3  riscv-fesvr原理 ](#subsec_fesvr )
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -10,116 +10,128 @@
 
			
		
	
		
		
			
				
					
					  - [8.1.5 中断驱动I/O控制方式 ](#subsec_plic )  
  - [8.1.5 中断驱动I/O控制方式 ](#subsec_plic )  
 
			
		
	
		
		
			
				
					
					  - [8.1.6 设备文件 ](#subsec_file )
  - [8.1.6 设备文件 ](#subsec_file )
 
			
		
	
		
		
			
				
					
					- [8.2 lab5_1 POLL ](#polling ) 
- [8.2 lab5_1 POLL ](#polling ) 
 
			
		
	
		
		
			
				
					
					  - [给定应用 ](#lab4_1_app )
  - [给定应用 ](#lab5_1_app )
 
			
				
				
			
		
	
		
		
			
				
					
					  - [实验内容 ](#lab4_1_content )
  - [实验内容 ](#lab5_1_content )
 
			
				
				
			
		
	
		
		
			
				
					
					  - [实验指导 ](#lab4_1_guide )
  - [实验指导 ](#lab5_1_guide )
 
			
				
				
			
		
	
		
		
			
				
					
					- [8.3 lab5_2_PLIC ](#PLIC ) 
  - [答案解析 ](#lab5_1_ans )
 
			
				
				
			
		
	
		
		
			
				
					
					  - [给定应用 ](#lab4_2_app )
- [8.3 lab5_2 PLIC ](#PLIC ) 
 
			
				
				
			
		
	
		
		
			
				
					
					  - [实验内容 ](#lab4_2_content )
  - [给定应用 ](#lab5_2_app )
 
			
				
				
			
		
	
		
		
			
				
					
					  - [实验指导 ](#lab4_2_guide )
  - [实验内容 ](#lab5_2_content )
 
			
				
				
			
		
	
		
		
			
				
					
					- [8.4 lab5_3_hostdevice ](#hostdevice ) 
  - [实验指导 ](#lab5_2_guide )
 
			
				
				
			
		
	
		
		
			
				
					
					  - [给定应用 ](#lab4_3_app )
  - [答案解析 ](#lab5_2_ans )
 
			
				
				
			
		
	
		
		
			
				
					
					  - [实验内容 ](#lab4_3_content )
- [8.4 lab5_3 hostdevice ](#hostdevice ) 
 
			
				
				
			
		
	
		
		
			
				
					
					  - [实验指导 ](#lab4_3_guide )
  - [给定应用 ](#lab5_3_app )
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					  - [实验内容 ](#lab5_3_content )
 
			
		
	
		
		
			
				
					
					  - [实验指导 ](#lab5_3_guide )
 
			
		
	
		
		
			
				
					
					  - [答案解析 ](#lab5_3_ans )
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					< a  name = "fundamental" > < / a > < a  name = "fundamental" > < / a >  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					## 7 .1 实验5的基础知识
## 8 .1 实验5的基础知识
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					完成前面所有实验后, 四的设备实验中, ,  ocket chip上增加uart模块和蓝牙模块, , , 
完成前面所有实验后, 五的设备实验中, ,  ocket chip上增加uart模块和蓝牙模块, , , 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					< a  name = "subsec_pynq" > < / a > < a  name = "subsec_pynq" > < / a >  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					### 7 .1.1 pynq开发板介绍
### 8 .1.1 pynq开发板介绍
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					本实验中, 2开发板上搭载两块芯片,  架构32位芯片, , ; , , , , 
本实验中, 1开发板上搭载两块芯片,  架构32位芯片, , 操作系统 ; , , , , 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					 < img  title = ""  src = "pictures/fig6_4.png"  alt = ""  data-align = "center" >  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					如上图, , , ( ) , ; , , ( ) , , , , 
如上图, , , ( ) , 控制器 等; , , ( ) , , , , 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					实验四和前三个实验的关系 如下:
实验五和前四个实验的区别 如下:
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					 < img  title = ""  src = "pictures/fig6_5.png"  alt = ""  data-align = "center"  width = "600" >  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					可见除了部分硬件相关的操作外, , , , 
可见除了部分硬件相关的操作外, , PL端与PS端 两端的设备,另一方面在不同地方运行基本不用修 改太多代码,非常优越。
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					< a  name = "subsec_MMIO" > < / a > < a  name = "subsec_MMIO" > < / a >  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					### 7 .1.2 内存映射I/O(MMIO)
### 8 .1.2 内存映射I/O(MMIO)
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					内存映射(Memory-Mapping I/O)是一种用于设备驱动程序和设备通信的方式, , , , , , 
内存映射(Memory-Mapping I/O)是一种用于设备驱动程序和设备通信的方式, , , , , , 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					在MMIO中, , , , , , , , , , 
在MMIO中, , , , , , , , , , 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					在本章节中,  固定的内存地址,因此可以通过对这些地址进行读写控制蓝牙和小车电机。
在本上一章节中,  固定的内存地址,因此可以通过对这些地址进行读写控制蓝牙和小车电机。
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					< a  name = "subsec_fesvr" > < / a > < a  name = "subsec_fesvr" > < / a >  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					### 7 .1.3 riscv-fesvr原理
### 8 .1.3 riscv-fesvr原理
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					riscv-fesvr是PKE在PYNQ开发板上使用的重要工具, , , ,  块负责接受PKE对ARM端的系统调用请求, ; , 
riscv-fesvr是PKE在PYNQ开发板上运行的重要工具, , , :  块负责接受PKE对ARM端的系统调用请求, ,并返回相应的操作结果 ;内存模块负责ARM端 读写RISCV端的内存, 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					PKE调用宿主机/开发板ARM端的系统调用函数使用的是HTIF协议。协议要求内核保留两个地址, , , , , ,  。
PKE调用宿主机/开发板ARM端的系统调用函数使用的是HTIF协议。协议要求内核保留两个64位变量: , , ,  。
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					 tohost与fromhost变量的格式如下:   
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					打个比方, , , , , , , , , , , ,  < img  src = "pictures/to_from_host.png"  title = ""  alt = ""  data-align = "center"  width = "500" >  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					riscv-fesvr的内存模块用来读写RISCV端的内存, , , 
当通过HTIF进行系统调用时, , : 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					< img  src = "pictures/fig6_7.png"  title = ""  alt = ""  data-align = "center" >  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					例如, , , , , , , , , , 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					PKE在写入tohost变量发起ARM端系统调用后, , , 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					riscv-fesvr的内存模块用来读写RISCV端的内存, , , 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					另外, , : 
另外, , : 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					* ioctl函数比较简单, 
* ioctl系统调用的实现比较简单,  
 
			
				
				
			
		
	
		
		
			
				
					
					* mmap函数比较麻烦, , , , ; , , 
* mmap系统调用的实现比较麻烦, , ,  内存用数组存储映射地址, ; 读取时, PKE向readmmap传入数组 索引, ARM端被映射 地址, 
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					< a  name = "subsec_polling" > < / a > < a  name = "subsec_polling" > < / a >  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					### 7 .1.4  轮询I/O控制方式
### 8 .1.4  轮询I/O控制方式
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					在实验四中,我们设备管理的主要任务是控制设备与内存的数据传递,具体为从蓝牙设备读取到用户输入的指令字符(或传递数据给蓝牙在手机端进行打印),解析为小车前、后、左、右、停止等动作来传输数据给电机实现对小车的控制。在前两个实验中,我们分别需要对轮询控制方式和中断控制 方式进行实现。
在实验五中,我们设备管理的主要任务是控制设备与内存间的数据传递。具体来讲,需要将从蓝牙设备读取到的用户输入指令字符,解析为小车前进、后退、左转、右转和停止动作,并传输对应的小车控制指令给电机控制器实现对小车的控制。在前两个实验中,我们分别需要对蓝牙设备的轮询和中断访问 方式进行实现。
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					首先, ( ) , , , ,  。对于轮询方式( ) , , , , ,  。 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					轮询I/O控制方式流程如图: 
轮询I/O控制方式流程如图: 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					< img  = "pictures/fig6_1_polling.png"  alt = "fig6_1"  style = "zoom:100%;"  / > < img  title= ""   src= "pictures/fig6_1_polling.png"  alt = "fig6_1"  style = "zoom:100%;"  data-align = "center"  width = "301" >  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					< a  name = "subsec_plic" > < / a > < a  name = "subsec_plic" > < / a >  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					### 7 .1.5  中断驱动I/O控制方式
### 8 .1.5  中断驱动I/O控制方式
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					在前一种轮询的控制方式中, , 处于 等待I/O设备完成数据传输的循环测试中, , , , , , , , , , 
在前一种轮询的控制方式中, , 在 等待I/O设备完成数据传输的循环测试中, , , , , , 当 采用中断驱动的控制方式时 , , , 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					Riscv 包含三类中断:软中断、时钟中断和外部中断。软中断和时钟中断我们在实验一已经接触过,而设备触发的中断属于外部中断。在实验一中,我们在机器态捕获了时钟中断,然后将其转发成内核态的软中断交由中断处理程序处理; , , , ( ) , , , 
RISCV 包含三类中断:软中断、时钟中断和外部中断。软中断和时钟中断我们在实验一已经接触过,而设备触发的中断属于外部中断。在实验一中,我们在机器态捕获了时钟中断,然后将其转发成内核态的软中断交由中断处理程序处理。本章则直接通过设置MIDELEG寄存器,  内核态的中断处理程序处理, , ( ) , , , 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					中断驱动I/O方式流程如图: 
中断驱动I/O方式流程如图: 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					< img  = "pictures/fig6_2_plic.png"  alt = "fig6_2"  style = "zoom:100%;"  / > < img  title= ""   src= "pictures/fig6_2_plic.png"  alt = "fig6_2"  style = "zoom:100%;"  data-align = "center"  width = "319" >  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					< a  name = "subsec_file" > < / a > < a  name = "subsec_file" > < / a >  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					### 7 .1.6 设备文件
### 8 .1.6 设备文件
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					用户程序访问外部设备通常有两种方式:通过特定系统调用访问和通过设备文件访问。前者即操作系统提供专门的函数控制设备,后者是操作系统把设备指定成一个文件,通过通用的文件的读写 函数控制设备。设备文件常用的函数除了open、read、write、close, : 
用户程序访问外部设备通常有两种方式:通过特定系统调用访问和通过设备文件访问。前者即操作系统提供专门的函数控制设备,后者是操作系统把设备抽象成一个设备文件,通过通用的文件访问 函数控制设备。设备文件常用的函数除了open、read、write、close, : 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					* ioctl: ; , , ; , , ; , ; 我们 可以设置采样率、数据格式等。
* ioctl: ; , , ; , , ; , ; 
 
			
				
				
			
		
	
		
		
			
				
					
					* mmap: , , ; , , , 填NULL表示由操作系统自己 指定; , ; ; , 
* mmap: , , ; , , , 传递NULL表示由操作系统 指定; , 访问 权限和其他参数; ; , 
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					在本章节中, 将使用PKE通过HTIF协议和PS端的riscv-fesvr进行通信, , 
在本章的第三个实验中,我们 将使用PKE通过HTIF协议和PS端的riscv-fesvr进行通信, , 另外, , , , ,  
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					< a  name = "polling" > < / a > < a  name = "polling" > < / a >  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					## 7.2 lab4 _1 poll
## 8.2 lab5 _1 poll
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					< a  name = "lab 4 _1_app"> < / a > < a  name = "lab 5 _1_app"> < / a >  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					#### ** 给定应用**
#### ** 给定应用**
 
			
		
	
		
		
			
				
					
					- user/app_poll.c
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					- user/app_polling.c
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```c
```c
 
			
		
	
		
		
			
				
					
					  1 /*
  1 /*
 
			
		
	
		
		
			
				
					
					  2  * Below is the given application for lab4 _1.
  2  * Below is the given application for lab5 _1.
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					  3  * The goal of this app is to control the car via Bluetooth. 
  3  * The goal of this app is to control the car via Bluetooth. 
 
			
		
	
		
		
			
				
					
					  4  */
  4  */
 
			
		
	
		
		
			
				
					
					  5 
  5 
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -142,50 +154,54 @@ Riscv包含三类中断: 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					应用通过轮询的方式从蓝牙端获取指令,实现对小车的控制功能。
应用通过轮询的方式从蓝牙端获取指令,实现对小车的控制功能。
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					* ( 3_3的答案, ) ,  _3中所做的修改, : 
* ( 4_3的答案, ) ,  _3中所做的修改, : 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```bash
```bash
 
			
		
	
		
		
			
				
					
					//切换到lab4 _1
//切换到lab5 _1
 
			
				
				
			
		
	
		
		
			
				
					
					$ git checkout lab4 _1_poll
$ git checkout lab5 _1_poll
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					//继承lab3 _3以及之前的答案
//继承lab4 _3以及之前的答案
 
			
				
				
			
		
	
		
		
			
				
					
					$ git merge lab3_3_rrsched -m "continue to work on lab4 _1"
$ git merge lab4_3_hardlink -m "continue to work on lab5 _1"
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					//重新构造
//重新构造
 
			
		
	
		
		
			
				
					
					$ make clean; make
$ make clean; make
 
			
		
	
		
		
			
				
					
					```
```
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					由于本实验给出的基础代码修改了硬件相关的部分代码, , , 六 章中的说明完成了fpga实验1, 
由于本实验给出的基础代码修改了硬件相关的部分代码, , , 七 章中的说明完成了fpga实验1, 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					make完成后, , : 
make完成后, , : 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					1. 首先, : , , 
1. 首先, : , , 
 
			
				
				
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					2. 通过ssh协议连接到开发板( ) , : 
 
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					2. 通过ssh协议连接到开发板( ) , : 
 
			
		
	
		
		
			
				
					
					   
 
			
		
	
		
		
			
				
					
					   ```bash
   ```bash
 
			
		
	
		
		
			
				
					
					   $ sudo ./program.sh # 若重启过开发板,则在执行程序前要先执行此脚本进行烧录
   $ sudo ./program.sh # 若重启过开发板,则在执行程序前要先执行此脚本进行烧录
 
			
		
	
		
		
			
				
					
					   $ sudo ./riscv-fesvr riscv-pke app_poll
   $ sudo ./riscv-fesvr riscv-pke app_polling 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					   In m_start, hartid:0
   In m_start, hartid:0
 
			
		
	
		
		
			
				
					
					   (Emulated) memory size: 256 MB
   (Emulated) memory size: 256 MB
 
			
		
	
		
		
			
				
					
					   Enter supervisor mode...
   Enter supervisor mode...
 
			
		
	
		
		
			
				
					
					   PKE kernel start 0x0000000080000000, PKE kernel end: 0x0000000080009000, PKE kernel size: 0x0000000000009 000 .
   PKE kernel start 0x0000000080000000, PKE kernel end: 0x0000000080011000, PKE kernel size: 0x0000000000011 000 .
 
			
				
				
			
		
	
		
		
			
				
					
					   free physical memory address: [0x0000000080009 000, 0x00000000800fffff] 
   free physical memory address: [0x0000000080011 000, 0x00000000800fffff] 
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					   kernel memory manager is initializing ...
   kernel memory manager is initializing ...
 
			
		
	
		
		
			
				
					
					   KERN_BASE 0x0000000080000000
   KERN_BASE 0x0000000080000000
 
			
		
	
		
		
			
				
					
					   physical address of _etext is: 0x0000000080005 000
   physical address of _etext is: 0x0000000080009 000
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					   kernel page table is on 
   kernel page table is on 
 
			
		
	
		
		
			
				
					
					   RAMDISK0: base address of RAMDISK0 is: 0x0000000080072000
 
			
		
	
		
		
			
				
					
					   RFS: format RAMDISK0 done!
 
			
		
	
		
		
			
				
					
					   Switch to user mode...
   Switch to user mode...
 
			
		
	
		
		
			
				
					
					   in alloc_proc. user frame 0x00000000800f9000, user stack 0x000000007ffff000, user kstack 0x00000000800f8000 
   in alloc_proc. user frame 0x0000000080066000, user stack 0x000000007ffff000, user kstack 0x0000000080065000 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					   FS: created a file management struct for a process.
 
			
		
	
		
		
			
				
					
					   in alloc_proc. build proc_file_management successfully.
 
			
		
	
		
		
			
				
					
					   User application is loading.
   User application is loading.
 
			
		
	
		
		
			
				
					
					   Application: app_polling
   Application: app_polling
 
			
		
	
		
		
			
				
					
					   CODE_SEGMENT added at mapped info offset:3
   CODE_SEGMENT added at mapped info offset:4
 
			
				
				
			
		
	
		
		
			
				
					
					   Application program entry point (virtual address): 0x0000000000010078
   DATA_SEGMENT added at mapped info offset:5
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					   Application program entry point (virtual address): 0x00000000000100b0
 
			
		
	
		
		
			
				
					
					   going to insert process 0 to ready queue.
   going to insert process 0 to ready queue.
 
			
		
	
		
		
			
				
					
					   going to schedule process 0 to run.
   going to schedule process 0 to run.
 
			
		
	
		
		
			
				
					
					   Ticks 0
 
			
		
	
		
		
			
				
					
					   please input the instruction through bluetooth!
   please input the instruction through bluetooth!
 
			
		
	
		
		
			
				
					
					   You have to implement sys_user_uart_getchar to get data from UART using uartgetchar in lab4_1 and modify it in lab4 _2.
   You have to implement sys_user_uart_getchar to get data from UART using uartgetchar in lab5_1 and modify it in lab5 _2.
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					   
   
 
			
		
	
		
		
			
				
					
					   System is shutting down with exit code -1.
   System is shutting down with exit code -1.
 
			
		
	
		
		
			
				
					
					   ```
   ```
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -198,24 +214,29 @@ make完成后, 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					如输出提示所表示的那样, , , , , : 
如输出提示所表示的那样, , , , , : 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```  bash
```bash
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					$ sudo ./program.sh # 若重启过开发板,则在执行程序前要先执行此脚本进行烧录
$ sudo ./program.sh # 若重启过开发板,则在执行程序前要先执行此脚本进行烧录
 
			
		
	
		
		
			
				
					
					$ sudo ./riscv-fesvr riscv-pke app_poll
$ sudo ./riscv-fesvr riscv-pke app_polling 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					In m_start, hartid:0
In m_start, hartid:0
 
			
		
	
		
		
			
				
					
					(Emulated) memory size: 256 MB
(Emulated) memory size: 256 MB
 
			
		
	
		
		
			
				
					
					Enter supervisor mode...
Enter supervisor mode...
 
			
		
	
		
		
			
				
					
					PKE kernel start 0x0000000080000000, PKE kernel end: 0x0000000080009000, PKE kernel size: 0x0000000000009 000 .
PKE kernel start 0x0000000080000000, PKE kernel end: 0x0000000080011000, PKE kernel size: 0x0000000000011 000 .
 
			
				
				
			
		
	
		
		
			
				
					
					free physical memory address: [0x0000000080009 000, 0x00000000800fffff] 
free physical memory address: [0x0000000080011 000, 0x00000000800fffff] 
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					kernel memory manager is initializing ...
kernel memory manager is initializing ...
 
			
		
	
		
		
			
				
					
					KERN_BASE 0x0000000080000000
KERN_BASE 0x0000000080000000
 
			
		
	
		
		
			
				
					
					physical address of _etext is: 0x0000000080005 000
physical address of _etext is: 0x0000000080009 000
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					kernel page table is on 
kernel page table is on 
 
			
		
	
		
		
			
				
					
					RAMDISK0: base address of RAMDISK0 is: 0x0000000080072000
 
			
		
	
		
		
			
				
					
					RFS: format RAMDISK0 done!
 
			
		
	
		
		
			
				
					
					Switch to user mode...
Switch to user mode...
 
			
		
	
		
		
			
				
					
					in alloc_proc. user frame 0x00000000800f9000, user stack 0x000000007ffff000, user kstack 0x00000000800f8000 
in alloc_proc. user frame 0x0000000080066000, user stack 0x000000007ffff000, user kstack 0x0000000080065000 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					FS: created a file management struct for a process.
 
			
		
	
		
		
			
				
					
					in alloc_proc. build proc_file_management successfully.
 
			
		
	
		
		
			
				
					
					User application is loading.
User application is loading.
 
			
		
	
		
		
			
				
					
					Application: app_polling
Application: app_polling
 
			
		
	
		
		
			
				
					
					CODE_SEGMENT added at mapped info offset:3
CODE_SEGMENT added at mapped info offset:4
 
			
				
				
			
		
	
		
		
			
				
					
					Application program entry point (virtual address): 0x0000000000010078
DATA_SEGMENT added at mapped info offset:5
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					Application program entry point (virtual address): 0x00000000000100b0
 
			
		
	
		
		
			
				
					
					going to insert process 0 to ready queue.
going to insert process 0 to ready queue.
 
			
		
	
		
		
			
				
					
					going to schedule process 0 to run.
going to schedule process 0 to run.
 
			
		
	
		
		
			
				
					
					please input the instruction through bluetooth!
please input the instruction through bluetooth!
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -226,42 +247,43 @@ please input the instruction through bluetooth!
 
			
		
	
		
		
			
				
					
					1. 在手机端下载任意一种蓝牙串口通信APP( : , , ) 
1. 在手机端下载任意一种蓝牙串口通信APP( : , , ) 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					2. 打开手机蓝牙开关。
2. 打开手机蓝牙开关。
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					3. 点击蓝牙串口通信APP下方的蓝牙设备按钮, , , , 
3. 点击蓝牙串口通信APP下方的蓝牙设备按钮, , , , 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					4. 点击蓝牙串口通信APP下方的收发数据按钮, , : 
4. 点击蓝牙串口通信APP下方的收发数据按钮, , : 
 
			
		
	
		
		
			
				
					
					
      
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					   ** 注意,若软硬件都正确无误,在发送下方指令后小车会立即开始运动。请务必确保小车的运动在实验人员的控制之内!若小车上有连接用于调试的网线等设备,建议暂时使小车的四个车轮处于悬空状态。当功能全部测试无误后,可以在保持程序运行的情况下直接拔掉网线,并将小车放置在地面上移动**。
   ** 注意,若软硬件都正确无误,在发送下方指令后小车会立即开始运动。请务必确保小车的运动在实验人员的控制之内!若小车上有连接用于调试的网线等设备,建议暂时使小车的四个车轮处于悬空状态。当功能全部测试无误后,可以在保持程序运行的情况下直接拔掉网线,并将小车放置在地面上移动**。
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					| 命令 |                      效果                        |
| 命令  | 效果                            |
 
			
				
				
			
		
	
		
		
			
				
					
					|  :--:  |  :----------------- ----------------------------:  |
|:--- :|:----------------------------:|
 
			
				
				
			
		
	
		
		
			
				
					
					|   1   |                     小车前进                     |
| 1   | 小车前进                          |
 
			
				
				
			
		
	
		
		
			
				
					
					|   2   |                     小车后退                     |
| 2   | 小车后退                          |
 
			
				
				
			
		
	
		
		
			
				
					
					|   3   |                     小车左转                     |
| 3   | 小车左转                          |
 
			
				
				
			
		
	
		
		
			
				
					
					|   4   |                     小车右转                     |
| 4   | 小车右转                          |
 
			
				
				
			
		
	
		
		
			
				
					
					|   0   |                     小车停止                     |
| 0   | 小车停止                          |
 
			
				
				
			
		
	
		
		
			
				
					
					|   q   | 程序停止( ) 
| q   | 程序停止( ) 
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					< a  name = "lab 4 _1_guide"> < / a > < a  name = "lab 5 _1_guide"> < / a >  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					#### ** 实验指导**
#### ** 实验指导**
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					基于实验lab1_1, , : , , , , , : 
基于实验lab1_1, , : , , , , , : 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```c
```c
 
			
		
	
		
		
			
				
					
					16	#define  SYS_user_uart_putchar (SYS_user_base + 6 )34 #define  SYS_user_uart_putchar (SYS_user_base + 30 ) 
			
				
				
			
		
	
		
		
			
				
					
					17	#define  SYS_user_uart_getchar (SYS_user_base + 7 )35 #define  SYS_user_uart_getchar (SYS_user_base + 31 ) 
			
				
				
			
		
	
		
		
			
				
					
					18	#define  SYS_user_uart2_putchar (SYS_user_base + 8 )36 #define  SYS_user_uart2_putchar (SYS_user_base + 32 ) 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					```
```
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					继续追踪, , , : 
继续追踪, , , : 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```c
```c
 
			
		
	
		
		
			
				
					
					133	     case SYS_user_uart_putchar:297      case SYS_user_uart_putchar: 
			
				
				
			
		
	
		
		
			
				
					
					134	       sys_user_uart_putchar(a1);return 1;298        sys_user_uart_putchar(a1);return 1; 
			
				
				
			
		
	
		
		
			
				
					
					135	     case SYS_user_uart_getchar:299      case SYS_user_uart_getchar: 
			
				
				
			
		
	
		
		
			
				
					
					136	       return sys_user_uart_getchar();300        return sys_user_uart_getchar(); 
			
				
				
			
		
	
		
		
			
				
					
					137	     case SYS_user_uart2_putchar:301      case SYS_user_uart2_putchar: 
			
				
				
			
		
	
		
		
			
				
					
					138	       sys_user_uart2_putchar(a1);return 1;302          sys_user_uart2_putchar(a1);return 1; 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					```
```
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					读者的任务即为在kernel/syscall.c中追踪并完善sys_user_uart_getchar。对于uart相关的函数, : 
读者的任务即为在kernel/syscall.c中追踪并完善sys_user_uart_getchar。对于uart相关的函数, : 
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -270,37 +292,59 @@ please input the instruction through bluetooth!
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					图中的axi_uartlite_0对应于蓝牙设备的uart端口, , , , , 
图中的axi_uartlite_0对应于蓝牙设备的uart端口, , , , , 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					在kernel/syscall.c中找到函数实现空缺, ( 4_2需要对lab4_1完成的代码进行修改,  _2的提示) : 
在kernel/syscall.c中找到函数实现空缺, ( 5_2需要对lab5_1完成的代码进行修改,  _2的提示) : 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```c
```c
 
			
		
	
		
		
			
				
					
					 95 ssize_t sys_user_uart_getchar() {
227 ssize_t sys_user_uart_getchar() {
 
			
				
				
			
		
	
		
		
			
				
					
					 96   // TODO (lab4_1 and lab4_2): implment the syscall of sys_user_uart_getchar and modify it in lab4_2.
228   // TODO (lab5_1 and lab5_2): implment the syscall of sys_user_uart_getchar and modify it in lab5_2.
 
			
				
				
			
		
	
		
		
			
				
					
					 97   // hint (lab4_1): The functionality of sys_user_uart_getchar is to get data from UART address.
229   // hint (lab5_1): the functionality of sys_user_uart_getchar is to get data from UART address.
 
			
				
				
			
		
	
		
		
			
				
					
					 98   // Therefore we should check the data from the address of bluetooth status repeatedly, until the data is ready. 
230   // therefore, we should let a pointer point, insert it in 
 
			
				
				
			
		
	
		
		
			
				
					
					 99   // Then read the data from the address of bluetooth reading and return.
231   // the rear of ready queue, and finally, schedule a READY process to run.
 
			
				
				
			
		
	
		
		
			
				
					
					100   // hint (lab4_2): the functionality of sys_user_uart_getchar is let process sleep and wait for value. therefore,
232   // hint (lab5_2): the functionality of sys_user_uart_getchar is let process sleep
 
			
				
				
			
		
	
		
		
			
				
					
					101   // we should call do_sleep to let process 0 sleep. 
233   // and register a callback function to handle system call return value.
 
			
				
				
			
		
	
		
		
			
				
					
					102   // then we should get uartvalue and return.
234   // therefore, we should call do_sleep to let process 0 sleep. 
 
			
				
				
			
		
	
		
		
			
				
					
					103     panic( "You have to implement sys_user_uart_getchar to get data from UART using uartgetchar in lab4_1 and modify it in lab4_2.\n" );
235   // Note that the do_sleep function will never return, and the function passed to do_sleep
 
			
				
				
			
		
	
		
		
			
				
					
					104 
236   // will be called in do_wake.
 
			
				
				
			
		
	
		
		
			
				
					
					105 }
237   panic( "You have to implement sys_user_uart_getchar to get data from UART using uartgetchar in lab5_1 and modify it in lab5_2.\n" );
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					238 }
 
			
		
	
		
		
			
				
					
					```
```
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					**注意: 4_2的提示(  行),防止后面实验的合并错误!**
**注意: 5_2的提示(  行),防止后面实验的合并错误!**
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					**实验完毕后,记得提交修改(命令行中-m后的字符串可自行确定) , 4 _1中所做的工作**: 
**实验完毕后,记得提交修改(命令行中-m后的字符串可自行确定) , 5 _1中所做的工作**: 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```
```
 
			
		
	
		
		
			
				
					
					$ git commit -a -m "my work on lab4 _1 is done."
$ git commit -a -m "my work on lab5 _1 is done."
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					```
```
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					< a  name = "lab4_1_ans" > < / a >  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					#### 答案解析
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					将kernel/syscall.c文件中的
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```c
 
			
		
	
		
		
			
				
					
					panic( "You have to implement sys_user_uart_getchar to get data from UART using uartgetchar in lab5_1 and modify it in lab5_2.\n" );
 
			
		
	
		
		
			
				
					
					```
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					替换成:
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```c
 
			
		
	
		
		
			
				
					
					volatile uint32 *status = (void* )(uintptr_t)0x60000008;
 
			
		
	
		
		
			
				
					
					volatile uint32 *rx = (void* )(uintptr_t)0x60000000;
 
			
		
	
		
		
			
				
					
					while (!(*status &  0x00000001));
 
			
		
	
		
		
			
				
					
					return *rx;
 
			
		
	
		
		
			
				
					
					```
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					替换原因:
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					地址0x60000008被映射到axi uartlite IP核的状态寄存器, , , , , ( ) , ( ) 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					< a  name = "PLIC" > < / a > < a  name = "PLIC" > < / a >  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					## 7.3 lab4_2_PLIC 
## 7.3 lab5_2 PLIC 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					< a  name = "lab4_2_app" > < / a > < a  name = "lab 5 _2_app"> < / a >  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					#### ** 给定应用**
#### ** 给定应用**
 
			
		
	
		
		
			
				
					
					
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -308,7 +352,7 @@ $ git commit -a -m "my work on lab4_1 is done."
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```c
```c
 
			
		
	
		
		
			
				
					
					  1  /*
  1  /*
 
			
		
	
		
		
			
				
					
					  2  * Below is the given application for lab4 _2.
  2  * Below is the given application for lab5 _2.
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					  3  * The goal of this app is to control the car via Bluetooth. 
  3  * The goal of this app is to control the car via Bluetooth. 
 
			
		
	
		
		
			
				
					
					  4  */
  4  */
 
			
		
	
		
		
			
				
					
					  5 
  5 
 
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -352,19 +396,18 @@ $ git commit -a -m "my work on lab4_1 is done."
 
			
		
	
		
		
			
				
					
					 43 
 43 
 
			
		
	
		
		
			
				
					
					 44   return 0;
 44   return 0;
 
			
		
	
		
		
			
				
					
					 45 }
 45 }
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```
```
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					应用通过中断的方式从蓝牙端获取指令, , , 
应用通过中断的方式从蓝牙端获取指令, , , 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					* ( 4_1的答案, ) ,  _1中所做的修改, : 
* ( 5_1的答案, ) ,  _1中所做的修改, : 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```bash
```bash
 
			
		
	
		
		
			
				
					
					//切换到lab4 _2
//切换到lab5 _2
 
			
				
				
			
		
	
		
		
			
				
					
					$ git checkout lab4 _2_PLIC
$ git checkout lab5 _2_PLIC
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					//继承lab4 _1以及之前的答案
//继承lab5 _1以及之前的答案
 
			
				
				
			
		
	
		
		
			
				
					
					$ git merge lab4_1_poll -m "continue to work on lab4 _2"
$ git merge lab5_1_poll -m "continue to work on lab5 _2"
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					//重新构造
//重新构造
 
			
		
	
		
		
			
				
					
					$ make clean; make
$ make clean; make
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -377,70 +420,156 @@ $ sudo ./program.sh # 若重启过开发板,则在执行程序前要先执行
 
			
		
	
		
		
			
				
					
					$ sudo ./riscv-fesvr riscv-pke app_PLIC
$ sudo ./riscv-fesvr riscv-pke app_PLIC
 
			
		
	
		
		
			
				
					
					```
```
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					直接编译执行结果和完成后的lab4_1一致,  _1所写的代码并添加中断处理, , , 
直接编译执行结果和完成后的lab5_1一致,  _1所写的代码并添加中断处理, , , 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					< a  name = "lab 4 _2_content"> < / a > < a  name = "lab 5 _2_content"> < / a >  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					#### ** 实验内容**
#### ** 实验内容**
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					如输出提示所表示的那样, 4_1所写的代码并添加中断处理。完成后按lab4 _1的方法执行, , , 
如输出提示所表示的那样, 5_1所写的代码并添加中断处理。完成后按lab5 _1的方法执行, , , 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					< a  name = "lab 4 _2_guide"> < / a > < a  name = "lab 5 _2_guide"> < / a >  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					#### ** 实验指导**
#### ** 实验指导**
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					在kernel/syscall.c中找到lab4_1写的代码, : 
在kernel/syscall.c中找到lab5_1写的代码, : 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```c
 
			
		
	
		
		
			
				
					
					227 ssize_t sys_user_uart_getchar() {
 
			
		
	
		
		
			
				
					
					228   // TODO (lab5_1 and lab5_2): implment the syscall of sys_user_uart_getchar and modify it in lab5_2.
 
			
		
	
		
		
			
				
					
					229   // hint (lab5_1): the functionality of sys_user_uart_getchar is to get data from UART address.
 
			
		
	
		
		
			
				
					
					230   // therefore, we should let a pointer point, insert it in 
 
			
		
	
		
		
			
				
					
					231   // the rear of ready queue, and finally, schedule a READY process to run.
 
			
		
	
		
		
			
				
					
					232   // hint (lab5_2): the functionality of sys_user_uart_getchar is let process sleep
 
			
		
	
		
		
			
				
					
					233   // and register a callback function to handle system call return value.
 
			
		
	
		
		
			
				
					
					234   // therefore, we should call do_sleep to let process 0 sleep. 
 
			
		
	
		
		
			
				
					
					235   // Note that the do_sleep function will never return, and the function passed to do_sleep
 
			
		
	
		
		
			
				
					
					236   // will be called in do_wake.
 
			
		
	
		
		
			
				
					
					237   panic( "You have to implement sys_user_uart_getchar to get data from UART using uartgetchar in lab5_1 and modify it in lab5_2.\n" );
 
			
		
	
		
		
			
				
					
					238 }
 
			
		
	
		
		
			
				
					
					```
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					当应用程序调用uartgetchar获取蓝牙输入指令时, , , ) : 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```c
 
			
		
	
		
		
			
				
					
					312 void do_sleep(void wake_cb(void*), void* wake_cb_arg){
 
			
		
	
		
		
			
				
					
					313   current->status = BLOCKED;
 
			
		
	
		
		
			
				
					
					314   set_wake_callback(current->pid, wake_cb, wake_cb_arg);
 
			
		
	
		
		
			
				
					
					315   schedule();
 
			
		
	
		
		
			
				
					
					316 }
 
			
		
	
		
		
			
				
					
					```
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					`do_sleep` 除了将当前进程阻塞外,还将一个调用者提供的回调函数`wake_cb`以及它对应的参数`wake_cb_arg`注册到了当前进程中。 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					相应的,本实验中还提供了一个`do_wake`( 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```c
```c
 
			
		
	
		
		
			
				
					
					 95 ssize_t sys_user_uart_getchar() {
320 void do_wake(uint64 pid) { 
			
				
				
			
		
	
		
		
			
				
					
					 96   // TODO (lab4_1 and lab4_2): implment the syscall of sys_user_uart_getchar and modify it in lab4_2.
321   procs[pid].status = READY;  
			
				
				
			
		
	
		
		
			
				
					
					 97   // hint (lab4_1): The functionality of sys_user_uart_getchar is to get data from UART address.
322   current->status = READY;  
			
				
				
			
		
	
		
		
			
				
					
					 98   // Therefore we should check the data from the address of bluetooth status repeatedly, until the data is ready. 
323   insert_to_ready_queue(&procs[pid]);   
			
				
				
			
		
	
		
		
			
				
					
					 99   // Then read the data from the address of bluetooth reading and return.
324   insert_to_ready_queue( current );  
			
				
				
			
		
	
		
		
			
				
					
					100   // hint (lab4_2): the functionality of sys_user_uart_getchar is let process sleep and wait for value. therefore,
325   
			
				
				
			
		
	
		
		
			
				
					
					101   // we should call do_sleep to let process 0 sleep. 
326   if (procs[pid].wake_callback)  
			
				
				
			
		
	
		
		
			
				
					
					102   // then we should get uartvalue and return.
327     procs[pid].wake_callback(procs[pid].wake_callback_arg);  
			
				
				
			
		
	
		
		
			
				
					
					103     panic( "You have to implement sys_user_uart_getchar to get data from UART using uartgetchar in lab4_1 and modify it in lab4_2.\n" ); // 该行已被你之前写的代码替换
328   
			
				
				
			
		
	
		
		
			
				
					
					104 
329   schedule();  
			
				
				
			
		
	
		
		
			
				
					
					105 }
330  } 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					```
```
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					当蓝牙有数据发送时, , 
`do_wake` 除了会唤醒指定进程,  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					当蓝牙有数据发送时, , 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					在kernel/strap.c中找到函数空缺, : 
在kernel/strap.c中找到函数空缺, : 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```c
```c
 
			
		
	
		
		
			
				
					
					103     case CAUSE_MEXTERNEL_S_TRAP:
110     case CAUSE_MEXTERNEL_S_TRAP:
 
			
				
				
			
		
	
		
		
			
				
					
					104       {
111       {
 
			
				
				
			
		
	
		
		
			
				
					
					105         //reset the PLIC so that we can get the next external interrupt.
112         //reset the PLIC so that we can get the next external interrupt.
 
			
				
				
			
		
	
		
		
			
				
					
					106         volatile int irq = *(uint32 * )0xc201004L;
113         volatile int irq = *(uint32 * )0xc201004L;
 
			
				
				
			
		
	
		
		
			
				
					
					107         *(uint32 * )0xc201004L = irq;
114         *(uint32 * )0xc201004L = irq;
 
			
				
				
			
		
	
		
		
			
				
					
					108         volatile int *ctrl_reg = (void * )(uintptr_t)0x6000000c;
115         volatile int *ctrl_reg = (void * )(uintptr_t)0x6000000c;
 
			
				
				
			
		
	
		
		
			
				
					
					109         *ctrl_reg = *ctrl_reg | (1 < <  4 ) ; 
116         *ctrl_reg = *ctrl_reg | (1 < <  4 ) ; 
 
			
				
				
			
		
	
		
		
			
				
					
					110         // TODO (lab4_2): implment the case of CAUSE_MEXTERNEL_S_TRAP.
117         // TODO (lab5_2): implment the case of CAUSE_MEXTERNEL_S_TRAP.
 
			
				
				
			
		
	
		
		
			
				
					
					111         // hint: the case of CAUSE_MEXTERNEL_S_TRAP is to get data from UART address and wake the process. therefore,
118         // hint: the case of CAUSE_MEXTERNEL_S_TRAP is to get data from UART address and wake 
 
			
				
				
			
		
	
		
		
			
				
					
					112         // and you need to store the data in struct process.value. 
119         // the process. therefore, you need to construct an update_uartvalue_ctx structure
 
			
				
				
			
		
	
		
		
			
				
					
					113         panic( "You have to implement CAUSE_MEXTERNEL_S_TRAP to get data from UART and wake the process 0 in lab4_2.\n" );
120         // then store the interrupt processing process pid and the uart value in it
 
			
				
				
			
		
	
		
		
			
				
					
					114         
121         // and use this structure to update the wake callback context of the process
 
			
				
				
			
		
	
		
		
			
				
					
					115         break;
122         // finally call do_wake to wake up the process.
 
			
				
				
			
		
	
		
		
			
				
					
					116       }
123         panic( "You have to implement CAUSE_MEXTERNEL_S_TRAP to get data from UART and wake the process 0 in lab5_2.\n" );
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					124 
 
			
		
	
		
		
			
				
					
					125         break;
 
			
		
	
		
		
			
				
					
					126       }
 
			
		
	
		
		
			
				
					
					```
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					注意, , , , , ( ) : ( : ) , , , , 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					**实验完毕后,记得提交修改(命令行中-m后的字符串可自行确定) , : 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```
 
			
		
	
		
		
			
				
					
					$ git commit -a -m "my work on lab5_2 is done."
 
			
		
	
		
		
			
				
					
					```
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					< a  name = "lab5_2_ans" > < / a >  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					#### 答案解析
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					将kernel/strap.c文件中的: 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```c
 
			
		
	
		
		
			
				
					
					panic( "You have to implement CAUSE_MEXTERNEL_S_TRAP to get data from UART and wake the process 0 in lab5_2.\n" );
 
			
		
	
		
		
			
				
					
					```
```
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					**实验完毕后,记得提交修改(命令行中-m后的字符串可自行确定) , : 
替换为:
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```c
 
			
		
	
		
		
			
				
					
					volatile uint32 *rx = (void* )(uintptr_t)0x60000000;
 
			
		
	
		
		
			
				
					
					uint32 data = *rx;
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					uint64 handle_intr_pid = 0;  // the pid of the process that will handle this interrupt
 
			
		
	
		
		
			
				
					
					struct update_uartvalue_ctx *ctx = (struct update_uartvalue_ctx * )alloc_page();
 
			
		
	
		
		
			
				
					
					ctx->uartvalue = (char)data;
 
			
		
	
		
		
			
				
					
					ctx->pid = handle_intr_pid;
 
			
		
	
		
		
			
				
					
					set_wake_callback(handle_intr_pid, NULL, ctx);  // add wake callback context
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					do_wake(handle_intr_pid);
 
			
		
	
		
		
			
				
					
					```
```
 
			
		
	
		
		
			
				
					
					$ git commit -a -m "my work on lab4_2 is done."
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					替换原因:
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					此处的代码会在产生外部中断时被调用, ( ) , ( ) , , ( ) , , : 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```c
 
			
		
	
		
		
			
				
					
					229 void update_uartvalue(void *ctx) {
 
			
		
	
		
		
			
				
					
					230   struct update_uartvalue_ctx *uart_ctx = (struct update_uartvalue_ctx * )ctx;
 
			
		
	
		
		
			
				
					
					231   char value = uart_ctx->uartvalue;
 
			
		
	
		
		
			
				
					
					232   process *proc = &procs[uart_ctx->pid]; 
 
			
		
	
		
		
			
				
					
					233 
 
			
		
	
		
		
			
				
					
					234   // set system call return value
 
			
		
	
		
		
			
				
					
					235   proc->trapframe->regs.a0 = (uint64)value;
 
			
		
	
		
		
			
				
					
					236 }
 
			
		
	
		
		
			
				
					
					```
```
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					再将kernel/syscall.c文件中的sys_user_uart_getchar函数内容替换为: 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```c
 
			
		
	
		
		
			
				
					
					do_sleep(update_uartvalue, NULL);
 
			
		
	
		
		
			
				
					
					return 0;
 
			
		
	
		
		
			
				
					
					```
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					替换原因:
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					当小车控制进程间接调用该函数获取蓝牙设备输入时, , , , , , , ( ) , 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					< a  name = "hostdevice" > < / a > < a  name = "hostdevice" > < / a >  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					## 7.4 lab4_3_hostdevice
## 7.4 lab5_3  hostdevice
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					< a  name = "lab4_3_app" > < / a > < a  name = "lab 5 _3_app"> < / a >  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					#### ** 给定应用**
#### ** 给定应用**
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					- user/app_host_device.c
- user/app_host_device.c
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```c
```c
 
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -531,16 +660,16 @@ $ git commit -a -m "my work on lab4_2 is done."
 
			
		
	
		
		
			
				
					
					 85 }
 85 }
 
			
		
	
		
		
			
				
					
					```
```
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					该用户程序包含两个进程,其中主进程和实验4 _2类似, , ( ) ; , , : , , , ( ) , , , , , open和 ioctl两个 系统调用,对其进行完善从而实现小车的障碍识别和停止功能。
该用户程序包含两个进程,其中主进程和实验5 _2类似, , ( ) ; , , : , , , ( ) , , , , , ,   
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					* ( 4_2的答案, ) ,  _2中所做的修改, : 
* ( 5_2的答案, ) ,  _2中所做的修改, : 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```bash
```bash
 
			
		
	
		
		
			
				
					
					//切换到lab4 _3
//切换到lab5 _3
 
			
				
				
			
		
	
		
		
			
				
					
					$ git checkout lab4 _3_hostdevice
$ git checkout lab5 _3_hostdevice
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					//继承lab4 _2以及之前的答案
//继承lab5 _2以及之前的答案
 
			
				
				
			
		
	
		
		
			
				
					
					$ git merge lab4_2_PLIC -m "continue to work on lab4 _3"
$ git merge lab5_2_PLIC -m "continue to work on lab5 _3"
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					//重新构造
//重新构造
 
			
		
	
		
		
			
				
					
					$ make clean; make
$ make clean; make
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -555,41 +684,54 @@ $ sudo ./riscv-fesvr riscv-pke app_host_device
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					< a  name = "lab4_3_content" > < / a > < a  name = "lab4_3_content" > < / a >  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					####  实验内容
#### 实验内容
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					如应用提示所表示的那样, , , ; , , 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					如应用提示所表示的那样, , , ; , , 
在之前的文件系统实验中, , , , , ,  。 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					跟踪相关系统调用,  : 为了在PKE中操作摄像头设备, : , ; , , ; ,  :  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```c
```c
 
			
		
	
		
		
			
				
					
					 25 int do_open(char *pathname, int flags) {
21 void fs_init(void) {
 
			
				
				
			
		
	
		
		
			
				
					
					 26     // TODO (lab4_3): call host open through spike_file_open and then bind fd to spike_file
22   // initialize the vfs
 
			
				
				
			
		
	
		
		
			
				
					
					 27     // hint: spike_file_dup function can bind spike_file_t to an int fd.
23   vfs_init();
 
			
				
				
			
		
	
		
		
			
				
					
					 28     panic( "You need to finish open function in lab4_3.\n" );
24 
 
			
				
				
			
		
	
		
		
			
				
					
					 29 }
25   // register hostfs-file and mount it as the root
 
			
				
				
			
		
	
		
		
			
				
					
					 30 int do_write(int fd, char *buf, uint64 count) {
26   if( register_hostfs() <  0  )  panic (  " fs_init:  cannot  register  hostfs . \n"  ); 
 
			
				
				
			
		
	
		
		
			
				
					
					 31     spike_file_t *f = spike_file_get(fd);
27   struct device *hostdev = init_host_device("HOSTDEV", "./hostfs_root");
 
			
				
				
			
		
	
		
		
			
				
					
					 32     return spike_file_write(f, buf, count);
28   vfs_mount("HOSTDEV", MOUNT_AS_ROOT);
 
			
				
				
			
		
	
		
		
			
				
					
					 33 }
29 
 
			
				
				
			
		
	
		
		
			
				
					
					 34 int do_close(int fd) {
30   // register hostfs-dev and mount it as /dev
 
			
				
				
			
		
	
		
		
			
				
					
					 35     spike_file_t *f = spike_file_get(fd);
31   struct device *hostdev_dev = init_host_device("dev", "/dev");
 
			
				
				
			
		
	
		
		
			
				
					
					 36     return spike_file_close(f);
32   vfs_mount("dev", MOUNT_DEFAULT);
 
			
				
				
			
		
	
		
		
			
				
					
					 37 }
33 
 
			
				
				
			
		
	
		
		
			
				
					
					 38 
34   // register and mount rfs
 
			
				
				
			
		
	
		
		
			
				
					
					 39 int do_ioctl(int fd, uint64 request, char *data) {
35   if( register_rfs() <  0  )  panic (  " fs_init:  cannot  register  rfs . \n"  ); 
 
			
				
				
			
		
	
		
		
			
				
					
					 40     // TODO (lab4_3): call host ioctl through frontend_sycall
36   struct device *ramdisk0 = init_rfs_device("RAMDISK0");
 
			
				
				
			
		
	
		
		
			
				
					
					 41     // hint: fronted_syscall ioctl argument:
37   rfs_format_dev(ramdisk0);
 
			
				
				
			
		
	
		
		
			
				
					
					 42     // 1.call number
38   vfs_mount("RAMDISK0", MOUNT_DEFAULT);
 
			
				
				
			
		
	
		
		
			
				
					
					 43     // 2.fd
39 }
 
			
				
				
			
		
	
		
		
			
				
					
					 44     // 3.the order to device
```
 
			
				
				
			
		
	
		
		
			
				
					
					 45     // 4.data address
 
			
				
				
			
		
	
		
		
			
				
					
					 46     panic( "You need to call host's ioctl by frontend_syscall in lab4_3.\n" );
另外, ( ) , ( ) , 
 
			
				
				
			
		
	
		
		
			
				
					
					 47 }
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					为了通过ioctl操作设备文件, , , , , , 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```c
 
			
		
	
		
		
			
				
					
					215 int hostfs_ioctl(struct vinode *f_inode, uint64 request, char *data) {
 
			
		
	
		
		
			
				
					
					216   spike_file_t *pf = (spike_file_t * )f_inode->i_fs_info;
 
			
		
	
		
		
			
				
					
					217   if (pf <  0 )  { 
 
			
		
	
		
		
			
				
					
					218     sprint("hostfs_write: invalid file handle!\n");
 
			
		
	
		
		
			
				
					
					219     return -1;
 
			
		
	
		
		
			
				
					
					220   }
 
			
		
	
		
		
			
				
					
					221   panic( "You need to call host's ioctl by frontend_syscall in lab5_3.\n" );
 
			
		
	
		
		
			
				
					
					222 }
 
			
		
	
		
		
			
				
					
					```
```
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					实验预期结果: , 
实验预期结果: , 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					< a  name = "lab4_3_guide" > < / a > < a  name = "lab 5 _3_guide"> < / a >  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					#### 实验指导
#### 实验指导
 
			
		
	
		
		
			
				
					
					
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -610,10 +752,31 @@ USB摄像头最基础的控制方法是使用读写设备文件的方式。拍
 
			
		
	
		
		
			
				
					
					应用第21行可以看到, , , , , , 
应用第21行可以看到, , , , , , 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					注意:对于灰度阈值的设定可根据环境亮度进行一定的调整,可以先根据摄像头返回的图像进行分析,计算出对应障碍物的灰度值;灰度阈值越精确,小车对于障碍物的识别将越灵敏,并能在合理的距离内识别到障碍物并停车。
注意:对于灰度阈值的设定可根据环境亮度进行一定的调整,可以先根据摄像头返回的图像进行分析,计算出对应障碍物的灰度值;灰度阈值越精确,小车对于障碍物的识别将越灵敏,并能在合理的距离内识别到障碍物并停车。
 
			
		
	
		
		
			
				
					
					**虽然如此,该算法仍不是非常精确。所以,这里给出的障碍物判断算法仅供参考,我们鼓励大家编写更高级的算法,实现更强大的功能。**
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					**虽然如此,但该算法仍不是非常精确。所以,这里给出的障碍物判断算法仅供参考,我们鼓励大家编写更高级的算法,实现更强大的功能。**
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					**实验完毕后,记得提交修改(命令行中-m后的字符串可自行确定) , : 
**实验完毕后,记得提交修改(命令行中-m后的字符串可自行确定) , : 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```
```
 
			
		
	
		
		
			
				
					
					$ git commit -a -m "my work on lab4_3 is done."
$ git commit -a -m "my work on lab5_3 is done."
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					```
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					< a  name = "lab5_3_ans" > < / a >  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					#### 答案解析
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					将`kernel/hostfs.c`文件中的:
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```c
 
			
		
	
		
		
			
				
					
					panic( "You need to call host's ioctl by frontend_syscall in lab5_3.\n" );
 
			
		
	
		
		
			
				
					
					```
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					替换成:
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					```c
 
			
		
	
		
		
			
				
					
					return frontend_syscall(HTIFSYS_ioctl, pf->kfd, request, (uint64)data, 0, 0, 0, 0);
 
			
		
	
		
		
			
				
					
					```
```
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					替换原因:
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					frontend_syscall函数在spike_interface/spike_utils.c中定义, , , , ,