or1k启动文件分析
or1k从spi flash启动文件spi_uimage_loader.S内容如下:
/* Assembly program to go into the boot ROM *//* For use with simple_spi SPI master core and standard SPI flashinterface-compatible parts (ST M25P16 for example.)*//* Currently just loads a program from SPI flash into RAM *//* Simple SPI的基址,用于和SPI Flash通信 */
#ifndef SPI_BASE
#define SPI_BASE 0xB0000000
#endif/* SPI Flash中24bit的地址,应用程序的起始地址 */
#ifndef BOOTROM_ADDR
#define BOOTROM_ADDR 0x000000
#endif /*A0-A2:代表24位地址的每个字节*/
#define HEADER_ADDR BOOTROM_ADDR + 0xc
#define A2 ((HEADER_ADDR) >> 16) & 0xFF
#define A1 ((HEADER_ADDR) >> 8) & 0xFF
#define A0 (HEADER_ADDR) & 0xFF#ifndef INIT_DELAY
#define INIT_DELAY 1250 //FIXME 0
#endif #define SPI_SPCR 0x0
#define SPI_SPSR 0x1
#define SPI_SPDR 0x2
#define SPI_SPER 0x3
#define SPI_SPSS 0x4#define SPI_SPCR_XFER_GO 0x51
#define SPI_SPSS_INIT 0x1
#define SPI_SPSR_RX_CHECK 0x01 /* Check bit 0 is cleared, fifo !empty*//* Registers usedr1 temp register (used in spi_xfer)r2 spi_xfer return valuer3 spi_xfer tx datar4 Simple SPI base addressr5 spi_xfer byte counterr6 temp registerr7 temp registerr8 temp registerr9 return addressr10r11 Image sizer12 Load addressr13 Reset vector*/
boot_init: l.movhi r0, 0l.movhi r2, 0l.movhi r5, 0l.movhi r1, hi(INIT_DELAY)l.ori r1, r1, lo(INIT_DELAY)
1: l.sfeqi r1, 0l.bnf 1bl.addi r1, r1, -1l.movhi r4, hi(SPI_BASE)spi_init:l.ori r2, r0, SPI_SPCR_XFER_GO /* Setup SPCR with enable bit set */l.sb SPI_SPCR(r4), r2l.sb SPI_SPSS(r4), r0 /* Clear SPI slave selects */l.ori r6, r0, SPI_SPSS_INITl.sb SPI_SPSS(r4), r6 /* Set appropriate slave select */l.ori r5, r0, 1 /*Set spi_xfer in byte mode */l.jal spi_xferl.ori r3, r0, 0x3 /* READ command opcode for SPI device*/l.jal spi_xfer/* Set start address in SPI Flash */l.ori r3, r0, A2l.jal spi_xferl.ori r3, r0, A1l.jal spi_xferl.ori r3, r0, A0l.ori r5, r0, 4 /* set spi_xfer in word mode *//* Load image size to r11 */
get_size:l.jal spi_xferl.nopl.or r11, r2, r0/* Load RAM base address to r12 */
get_load_addr:l.jal spi_xferl.nopl.or r12, r2, r0/* Load reset vector to r13 */
get_entry_point:l.jal spi_xferl.nopl.or r13, r2, r0/* Dummy read rest of the uimage header */l.ori r6, r0, 0x9
get_rest:l.jal spi_xferl.nopl.sfeqi r6, 0l.bnf get_restl.addi r6, r6, -1// r6 = loop counter// r7 = memory store address// Assumes at least one 32-bit word in image//Fixme: Copy last remaining words in byte model.movhi r6, 0
copy: l.jal spi_xfer /* Read a word into r2 */l.add r7, r12, r6 /* Set memory store address */l.sw 0(r7), r2 /* Write word */l.addi r6, r6, 4 /* Increse counter */l.sfgeu r6, r11 /* Check if file is completely copied */l.bnf copyl.nopgoto_reset:l.jr r13l.sb SPI_SPSS(r4), r0 /* Clear SPI slave selects *//* Write one byte, or read one to four bytes with Simple SPIr1 = temp registerr2 = Data read back from SPIr3 = Byte to writer4 = Simple SPI Base addressr5 = Number of transfers (1-4)*/
spi_xfer:l.or r1, r5, r0spi_xfer_loop: l.sb SPI_SPDR(r4), r3 /* Dummy write what's in r3 */l.ori r3, r0, SPI_SPSR_RX_CHECK /* r3 = , ensure loop just once */
spi_xfer_poll: l.andi r3, r3, SPI_SPSR_RX_CHECK /* AND read fifo bit empty */l.sfeqi r3, SPI_SPSR_RX_CHECK /* is bit set? ... */l.bf spi_xfer_poll /* ... if so, rxfifo empty, keep polling */l.lbz r3, SPI_SPSR(r4) /* Read SPSR */l.lbz r3, SPI_SPDR(r4) /* Get data byte */l.slli r2, r2, 8l.or r2, r2, r3l.sfeqi r1, 1l.bnf spi_xfer_loopl.addi r1, r1, -1l.jr r9l.nop
大家or1k环境地址划分如下:
地址划分:
设备 | 起始地址 | 地址掩码 | 大小 | |
---|---|---|---|---|
sdram | 0x0000_0000 | 0xfe00_0000 | 32MBytes | |
rom0 | 0xf000_0000 | 0xffff_fc00 | 1024Bytes | |
uart0 | 0x9000_0000 | 0xffff_ffe0 | 32Bytes | |
gpio0 | 0x9100_0000 | 0xffff_fffe | 1Bytes | |
gpio1 | 0x9200_0000 | 0xffff_fffe | 1Bytes | |
i2c0 | 0xa000_0000 | 0xffff_fff8 | 8Bytes | |
i2c1 | 0xa100_0000 | 0xffff_fff8 | 8Bytes | |
spi0 | 0xb000_0000 | 0xffff_fff8 | 8Bytes | |
spi1 | 0xb100_0000 | 0xffff_fff8 | 8Bytes | |
spi2 | 0xb200_0000 | 0xffff_fff8 | 8Bytes |
主要学习Linux开发,受限当前FPGA资源,只有1*uart+3*SPI+2*gpio+2*i2c+sdram
第一部分:
boot_init: l.movhi r0, 0l.movhi r2, 0l.movhi r5, 0l.movhi r1, hi(INIT_DELAY)l.ori r1, r1, lo(INIT_DELAY)
1: l.sfeqi r1, 0l.bnf 1bl.addi r1, r1, -1l.movhi r4, hi(SPI_BASE)
把 r0,r2,r5清零
l.movhi r1, hi(INIT_DELAY),取出INIT_DELAY高16位放到r1中
注意:hi(INIT_DELAY) === INIT_DELAY >> 16
l.movhi r1,k === r1=(k<<16) ,为什么要这么麻烦右移后又左移,是因为指令只能携带16位立即数
l.ori r1, r1, lo(INIT_DELAY),执行完这条指令后,r1中的内容就是INIT_DELAY,这两条指令就是把INIT_DELAY放到r1中
1: l.sfeqi r1, 0:当r1等于0时设置flag标志
l.bnf 1b :当flag标志没有设置时,跳到之前1处,b not flag
l.addi r1, r1, -1:当上面r1等于0的时候,flag标志会设置,程序执行到当前行,此时r1等于1,执行减一操作后,此时r1等于0xffff_ffff
l.movhi r4, hi(SPI_BASE):把SPI_BASE高16位放到r4中
l.ori r2, r0, SPI_SPCR_XFER_GO:把0x51放到r2中,此时r0=0,或运算的结果就是赋值
l.sb SPI_SPCR(r4), r2:把r2的值放到 r4+SPI_SPCR 指向的地址,就是向SPI_SPCR寄存器写入0x51, l.sb是store byte
l.sb SPI_SPSS(r4), r0:同理此时r0=0,则向SPI_SPSS写入0
l.ori r6, r0, SPI_SPSS_INIT:此时r0=0,设置r6=SPI_SPSS_INIT=1
l.sb SPI_SPSS(r4), r6:同理向SPI_SPSS寄存器写入r6=1
l.ori r5, r0, 1:把r5设置为1
l.jal spi_xfer:跳转到spi_xfer地址
本工程集成spi控制器为simple_spi,它有4个寄存器,每个寄存器8位
SPCR:控制寄存器,每位可读可写
bit7:中断使能位,1:使能中断 0:禁止中断
bit6: 控制器模块使能, 1:使能 0:禁止
bit5:保留位
bit4:设备模式选择,1:主设备 0:从设备
bit3,bit2:CPOL,CPHA
bit1-0 :SPI CLK频率选择位SPR,和ESPR配合完成分频
SPSR:状态寄存器,bit7-6:可读可写, 其它位只读
bit7:为1表示中断发生,写此位清除中断
bit6:wcol,写入冲突位,当写缓冲区满,写入时候出现此位,写入1清除此位
bit5-4:保留
bit3:写缓冲区满
bit2:写缓冲区空
bit1:接收缓冲区满
bit0:接收缓冲区空
SPDR:接收和发送缓冲区
读:接收缓冲区
写:发送缓冲区
SPER:扩展寄存器
bit7-6 : ICNT:传输完成1/2/3/4后设置中断标志
bit5-2:保留
bit1-0和控制寄存器bit1:0完成分频
从opencores下载的IPcore是没有片选的,下载的or1k添加第5个寄存器作为片选控制,每1位代表一个片选,写入1,对应片选拉低
对于上面操作
SPCR = 0x51
SPSS = 0
SPSS =1
功能,配置SPI控制器为master,并使能,spi clk为总线4分频,片选0拉低
再回头看上述汇编代码
l.ori r5, r0, 1 /*Set spi_xfer in byte mode */l.jal spi_xferl.ori r3, r0, 0x3 /* READ command opcode for SPI device*/l.jal spi_xfer......./* Write one byte, or read one to four bytes with Simple SPIr1 = temp registerr2 = Data read back from SPIr3 = Byte to writer4 = Simple SPI Base addressr5 = Number of transfers (1-4)*/
spi_xfer:l.or r1, r5, r0spi_xfer_loop: l.sb SPI_SPDR(r4), r3 /* Dummy write what's in r3 */l.ori r3, r0, SPI_SPSR_RX_CHECK /* r3 = , ensure loop just once */
spi_xfer_poll: l.andi r3, r3, SPI_SPSR_RX_CHECK /* AND read fifo bit empty */l.sfeqi r3, SPI_SPSR_RX_CHECK /* is bit set? ... */l.bf spi_xfer_poll /* ... if so, rxfifo empty, keep polling */l.lbz r3, SPI_SPSR(r4) /* Read SPSR */l.lbz r3, SPI_SPDR(r4) /* Get data byte */l.slli r2, r2, 8l.or r2, r2, r3l.sfeqi r1, 1l.bnf spi_xfer_loopl.addi r1, r1, -1l.jr r9l.nop
l.ori r5, r0, 1:把r5设置为1
l.jal spi_xfer:跳转到spi_xfer地址
l.ori r3, r0, 0x3 :设置r3为3,注意:这条跟在跳转指令后的指令称为延迟指令,一定会被执行
l.or r1, r5, r0:设置r1 = r5=1
l.sb SPI_SPDR(r4), r3: 设置SPI寄存器 SPDR = r3 = 3
l.ori r3, r0, SPI_SPSR_RX_CHECK:设置r3 = 1
l.andi r3, r3, SPI_SPSR_RX_CHECK:r3 = r3 & 1 = 1
l.sfeqi r3, SPI_SPSR_RX_CHECK:设置flag = (r3==1)?1:0
l.bf spi_xfer_poll:跳转到 spi_xfer_poll
l.lbz r3, SPI_SPSR(r4):读取SPI SPSR寄存器到r3, 这条是延迟指令,一定会执行
当l.bf spi_xfer_poll未发送生跳转说明接收缓冲区不为空,有数据可以读
l.lbz r3, SPI_SPDR(r4):读取SPI数据放大r3
l.slli r2, r2, 8
l.or r2, r2, r3
把r2左移8位,把r3低8位放到r2的低8为,上一条指令读取SPI SPDR做了零扩展,所以r3高24位都为0
l.sfeqi r1, 1
l.bnf spi_xfer_loop
l.addi r1, r1, -1
比较r1是否为1,不为1则跳转继续读数据,并把r1 = r1-1
l.jr r9
l.nop
返回spi_xfer调用点,注意后面l.nop是延迟指令,是必需的
or1k启动文件分析相关推荐
- STM32启动过程解析-2.02固件库启动文件分析
源:STM32启动过程解析-2.02固件库启动文件分析 转载于:https://www.cnblogs.com/LittleTiger/p/9205372.html
- startup_LPC17XX.s 启动文件分析
startup_LPC17XX.s 启动文件分析 工程中startup_LPC17XX.s是M3的启动文件,启动文件由汇编语言写的,它的作用一般是下面这几个: 1)堆和栈的初始化 2)中断向量表定义 ...
- 1.2 nuclei sdk gd32vf03 启动文件分析
gd32vf103 启动文件分析 /*** Reset Handler called on controller reset*/ _start:/* ===== Startup Stage 1 === ...
- Cortex-M3 .s 启动文件分析
Cortex-M3 .s启动文件分析 arm 中常见的汇编指令和伪指令 下面是startup_.s文件的源代码, 该文件主要完成三项工作:堆栈以及堆的初始化.定位中断向量表.调用Reset Handl ...
- STM32F4XX启动文件分析
STM32F4XX启动文件分析 - STM32F4XX启动文件下载地址 导读:STM32F4XX启动文件的作用 初始化设置SP,即栈指针 初始化设置PC指针指向复位中断处理函数,即PC = Reset ...
- 二、IAR for ARM中STM32项目创建及其启动文件分析
IAR for ARM STM32F10X官方固件库: 链接: https://pan.baidu.com/s/1U6vfGqp9IhhkvVuDXcxTtQ 提取码: 9mcx IAR for AR ...
- STM32启动文件分析
相对于ARM上一代的主流ARM7/ARM9内核架构,新一代Cortex内核架构的启动方式有了比较大的变化. ARM7/ARM9内核的控制器在复位后,CPU会从存储空间的绝对地址0x000000取出第一 ...
- 秉火429笔记之四启动文件分析
名为"startup_stm32f429_439xx.s"的文件,它里边使用汇编语言写好了基本程序,当STM32芯片上电启动的时候,首先会执行这里的汇编程序,从而建立起C语言的运行 ...
- startup_stm32f10x_hd.s启动文件分析
;* 文件名 : startup_stm32f10x_hd.s ;* 库版本 : V3.5.0 ;* 说明: 此文件为STM32F10x高 ...
最新文章
- 【CV知识学习】early stop、regularation、fine-tuning and some other trick to be known
- 为什么应该安装使用 Arch Linux
- 产品问答 | 领导把锅甩给你,你会怎么做?
- no need for pictures
- CentOS yum安装MySQL5.7.20
- You C.A.N.大赛 解锁7大行业智能硬件创新密码
- mysql版本 time类型
- Serilog 最佳实践
- thinkpad卡在logo界面_四大系列 一个品牌,超好用的商务伴侣Thinkpad
- 工信部下架37款侵害用户权益APP 114票务网等在列
- 管理中的计算机应用真题,0051管理系统中计算机应用试题历年真题
- matlab para for,matlab并行之parafor
- Ubuntu安装基础教程(No Zuo No Die)
- 【DB笔试面试642】在Oracle中,什么是基数反馈(Cardinality Feedback)?
- 阿里倡导成立“罗汉堂”, 6名诺贝尔奖得主加入
- 解决谷歌浏览器主页被篡改问题
- 求勾股数c语言OJ,C语言求勾股数(详解版)
- 火车采集器如何采集ajax数据和百度站内搜索数据
- 「Python爬虫系列讲解」五、用 BeautifulSoup 爬取电影信息
- linux具有写保护权限的文件,细说Linux权限