树莓派开发Linux实验报告,北航树莓派OS实验报告

树莓派实验报告

lab1

MACOS 访问串口教程https://software.intel.com/en-us/setting-up-serial-terminal-on-system-with-mac-os-x

命令行

 qemu-system-aarch64 -M raspi3 -k en-us -serial null -serial stdio -drive file=sdcard.img,format=raw -kernel kernel8.img

arm中的cpsr相当于MIPS CP0里的status

arm中 通过w0-30表示32位引用寄存器的方法, x0-30表示64位引用寄存器的方法

Broadcom Arm Cortex A53-architecture processor 是一个arm 处理器 为v8代ARM

配置树莓派开发板

将uart to usb转换口连接到GPIO上, 将kernel8.img和相关配置文件拷贝到microsd卡上, 连接usb,

上电, 启动, 使用screen -L /dev/cu.usbserial-00006014 115200 指令观察串口输出。

启动

配置include.mk, 修改gcc和ld的路径到自己电脑安装交叉编译器的路径

在start.S中, 首先获得当前CPU的编号

获得CPU编号的方法很简单, 通过MPIDR_EL1寄存级获得, 通过查阅手册, 可以发现

MPIDR_EL1这个寄存器可以提供关于当前运行的CPU的核的信息, 想要知道当前是第几个核心, 只需要访问最后四位就好了。

​ mrs x0, mpidr_el1

[外链图片转存失败(img-Zi99XmLM-1562856918022)(/Users/edward/Library/Application Support/typora-user-images/image-20190528153456748.png)]

[外链图片转存失败(img-nPKYt2K5-1562856918023)(/Users/edward/Library/Application Support/typora-user-images/image-20190528153524359.png)]

使用mrs指令以64位的方式放入0号寄存器中。

如果这是0号CPU的话, 也就是最低三位都是0, 那么跳转到main函数。

否则一直循环。

uart

参考了教程中的函数, 实现了uart和读取功能。

我把和GPIO相关的宏放到了gpio.h中, UART的宏定义放在uart.h中, uart的函数放在uart.c中

设置14, 15号为uart的端口, 初始化GPIO, 并且设置波特率为115200b/s

需要注意的是树莓派显示下\r和]\n的转化

lab2

to do list

设置间接内存属性寄存器

设置翻译控制寄存器

准备内核用的页目录

设置页表基地址寄存器

设置系统控制寄存器

修改启动代码 从EL2回落到EL1

改写链接脚本

MMU设置

通过这一个lab的学习, 我理解了之前计组的软件硬件接口。

在计算机中, 任何一个软件层级都采用了封装的方式去隐藏细节, 通过提供接口来给外界去使用。

而对于CPU来讲, 寄存器+手册就是CPU的接口, OS通过这个接口访问CPU, 同时给出自己的接口给用户。

对于ARM来说有不同的处理器权限

MAIR_EL1

这个寄存器的目的是给内存属性提供编码方式

通过查阅手册, 可以发现这个寄存器有8个attribute, 每个attribute8位

[外链图片转存失败(img-A0bjgdF7-1562856918024)(/Users/edward/Library/Application Support/typora-user-images/image-20190611230131206.png)]

通过下面的编码方式可以用户自定义内存属性

举个例子, 比如PTE_DEVICE = 1<<2, 也就是说PTE_DEVICE定义的内存在attr1里

那么ATTR1中存入, 0x04 对应device-nGnREmemeory

在arm v8中, G代表Gathering, R代表Reordering, E 代表early-achnowledge

[外链图片转存失败(img-Lq6N6Nkq-1562856918024)(/Users/edward/Library/Application Support/typora-user-images/image-20190611225902317.png)]

翻译控制寄存器

TCR_EL1是设置翻译控制的一个寄存器

[外链图片转存失败(img-kTkXfzc8-1562856918024)(/Users/edward/Library/Application Support/typora-user-images/image-20190611230917298.png)]

查到的资料表示, 这个寄存器表示哪个寄存器用来显示一级页表的地址。

TCR_EL1的38-0位是有效的

应设置使TTBR1_EL1作为内核空间一级页表物理地址, TTBR0_EL1用于用户空间

isb清除流水线中所有的指令

回落EL1

EL0 EL1 EL2 EL3

[外链图片转存失败(img-fb2mmYlZ-1562856918025)(/Users/edward/Library/Application Support/typora-user-images/image-20190526212639817.png)]

通过阅读手册, 可以知道这四种权限的功能。

[外链图片转存失败(img-WV5dD13A-1562856918025)(/Users/edward/Library/Application Support/typora-user-images/image-20190528155350192.png)]

[外链图片转存失败(img-Vqyikcy6-1562856918025)(/Users/edward/Library/Application Support/typora-user-images/image-20190528155331814.png)]

currentEL[3:2]代表了当前处于哪一级, 比如currentEL为4说明为EL1

在设置MMU之前, 首先需要回落到EL1

通过检查currentEl判断当前到底在哪个权限级上

[外链图片转存失败(img-70Bq6iib-1562856918026)(/Users/edward/Library/Application Support/typora-user-images/image-20190603223808046.png)]

在这张图中, 可以看到Arm cortex-A53的内存模型, 每个core有一个L1 cache, 同时四个core共用一个L2 cache, 在我的树莓派OS设计中, 我只用到了一个core。

在start.S中, 首先设置栈指针为0x80000, 然后进入vm函数

在这个函数中, 我做了如下事情

用boot_alloc分配一页内存给pgdir

用boot_map把0-P_LIMIT 和P_LIMIT往上0x1000000和0x40000000上BY2PG大小

分别对应正常的内存, IO以及控制寄存器

经过设置vm后, 开始一些寄存器的设置

首先通过currentel判断是否处在EL1

之后用给的参考代码来从EL2回落到EL1

之后再start里, 我设置了指导书中的一些寄存器

设置mair_el1为 0x440488, 代表内存类型

设置tcr_el1 0x2BA593A19,

把ttbr0_EL1和ttbr1_el1都设置为0x00200000

设置系统控制寄存器sctlr_el1为0x30d51825

之后, 仿照MIPS OS, 把boot_pgdir, 等函数改成 9 9 9 12三级页表的方式,

设置mmu.h中的宏

按照如下方式分配内存

#define K_TIMESTACK_TOP KADDR(P_TIMESTACK_TOP)

#define K_ENVS_BASE KADDR(P_ENVS_BASE)

#define K_PAGES_BASE KADDR(P_PAGES_BASE)

#define K_PGDIR_BASE KADDR(P_PGDIR_BASE)

#define K_STACK_TOP KADDR(P_STACK_TOP)

#define U_PAGES_BASE 0x90000000

#define U_ENVS_BASE 0x80000000

#define U_LIMIT 0x80000000

#define U_XSTACK_TOP 0x80000000

#define U_STACK_TOP 0x01000000

#define U_TEXT 0x00000000

通过page_alloc和page_insert来进行内存的分配

在pmap中, 除了pgdir_walk的时候要考虑三级页表pde, pme, 和pte之外,其他和MIPS OS基本相同。

lab3

ARM中R15位pc, 通过ISB, 冲刷

to do list

引入env.c中的内容。

加入kernel_elfloader.c。

TLB刷新, envrun。

时钟中断加入。

加入进程管理

从0x00B00000开始存储ENV结构体

Env结构体里存储了trapframe, env_id, parent_id, ipc value, ipc from ,ipc recving, env_pgfault_handler, env_xstacktop等变量。 和mips实验基本保持一致

在env_init里, 初始化envs数组, 把所有env结构体设置为ENV_FREE

创建一个进程的时候, 通过env_create, 读入u_char *binary和文件大小

调用env_alloc 分配一个env结构体

调用load_icode, 用load_elf把程序读入到entry point, 之后设置trapframe的elr, 让进程被调度的时候从elr开始运行,

在运行进程的时候, 首先把TIMESTACK中的内容拷贝到当前进程的trapframe结构体里

之后把 curenv 改为要新运行的进程

设置ttbr为curenv的 pgdir地址

最后tlb_invalidate, 运行新进程。

dsb data memry barrier

tlbi invalidate tlb

Isb 清空延迟槽中的所有指令

时钟中断

通过向cntp_tval寄存器写入开启中断

通过cntp_ctl_el0寄存器写入来控制主频

异常处理

处理时钟中断的时候

首先push time stack

之后跳转到handle_int

lab4

系统调用

系统调用在MIPS lab的基础上加入了emmc read

使用svc指令陷入内核态, 然后跳转到handle syscall

根据传入的sys callnumber 跳转到对应的处理函数

进程通信

进程通信和MIPS 实验没有改动

fork

fork中 写一个三重循环for i, j, k 遍历三级页表, 来复制页面

写时复制机制和MIPS类似, PTE_USER为EL0, EL1都可访问,

PTE_4KB仅仅为EL1可以访问

lab5

注意 如果读多了 会read_blk报错

macos下dd教程

https://www.cyberciti.biz/faq/how-to-create-disk-image-on-mac-os-x-with-dd-command/

diskutil list

diskutil unmountDisk /dev/disk2

dd if=user/pingpong.elf of=/dev/disk2 seek=4000 bs=512

写了后, 后面的磁盘会被清除cat

在文件系统中, 把文件系统挂载在了10000扇区开始的地方, 把MIPS OS里的read_block替换成EMMC的驱动, 就形成了树莓派的文件系统。

[外链图片转存失败(img-HNTIIMfe-1562856918026)(/Users/edward/Desktop/image-20190623000757962.png)]

lab6

需要加入的文件

icode.c

spawn.c

init.c

rsh.c

ls.c

cat.c

LAB6需要修改的主要是spawn和run.sh

在spawn中需要自己实现一个系统调用来完成set elr的工作, 此外在加载程序的时候, 还要用64位的elf方式加载。

其余部分, 参考MIPSOS和调用LAB5的接口就可以实现

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值