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启动文件分析相关推荐

  1. STM32启动过程解析-2.02固件库启动文件分析

    源:STM32启动过程解析-2.02固件库启动文件分析 转载于:https://www.cnblogs.com/LittleTiger/p/9205372.html

  2. startup_LPC17XX.s 启动文件分析

    startup_LPC17XX.s 启动文件分析 工程中startup_LPC17XX.s是M3的启动文件,启动文件由汇编语言写的,它的作用一般是下面这几个: 1)堆和栈的初始化 2)中断向量表定义 ...

  3. 1.2 nuclei sdk gd32vf03 启动文件分析

    gd32vf103 启动文件分析 /*** Reset Handler called on controller reset*/ _start:/* ===== Startup Stage 1 === ...

  4. Cortex-M3 .s 启动文件分析

    Cortex-M3 .s启动文件分析 arm 中常见的汇编指令和伪指令 下面是startup_.s文件的源代码, 该文件主要完成三项工作:堆栈以及堆的初始化.定位中断向量表.调用Reset Handl ...

  5. STM32F4XX启动文件分析

    STM32F4XX启动文件分析 - STM32F4XX启动文件下载地址 导读:STM32F4XX启动文件的作用 初始化设置SP,即栈指针 初始化设置PC指针指向复位中断处理函数,即PC = Reset ...

  6. 二、IAR for ARM中STM32项目创建及其启动文件分析

    IAR for ARM STM32F10X官方固件库: 链接: https://pan.baidu.com/s/1U6vfGqp9IhhkvVuDXcxTtQ 提取码: 9mcx IAR for AR ...

  7. STM32启动文件分析

    相对于ARM上一代的主流ARM7/ARM9内核架构,新一代Cortex内核架构的启动方式有了比较大的变化. ARM7/ARM9内核的控制器在复位后,CPU会从存储空间的绝对地址0x000000取出第一 ...

  8. 秉火429笔记之四启动文件分析

    名为"startup_stm32f429_439xx.s"的文件,它里边使用汇编语言写好了基本程序,当STM32芯片上电启动的时候,首先会执行这里的汇编程序,从而建立起C语言的运行 ...

  9. startup_stm32f10x_hd.s启动文件分析

    ;* 文件名          : startup_stm32f10x_hd.s ;* 库版本           : V3.5.0 ;* 说明:             此文件为STM32F10x高 ...

最新文章

  1. 【CV知识学习】early stop、regularation、fine-tuning and some other trick to be known
  2. 为什么应该安装使用 Arch Linux
  3. 产品问答 | 领导把锅甩给你,你会怎么做?
  4. no need for pictures
  5. CentOS yum安装MySQL5.7.20
  6. You C.A.N.大赛 解锁7大行业智能硬件创新密码
  7. mysql版本 time类型
  8. Serilog 最佳实践
  9. thinkpad卡在logo界面_四大系列 一个品牌,超好用的商务伴侣Thinkpad
  10. 工信部下架37款侵害用户权益APP 114票务网等在列
  11. 管理中的计算机应用真题,0051管理系统中计算机应用试题历年真题
  12. matlab para for,matlab并行之parafor
  13. Ubuntu安装基础教程(No Zuo No Die)
  14. 【DB笔试面试642】在Oracle中,什么是基数反馈(Cardinality Feedback)?
  15. 阿里倡导成立“罗汉堂”, 6名诺贝尔奖得主加入
  16. 解决谷歌浏览器主页被篡改问题
  17. 求勾股数c语言OJ,C语言求勾股数(详解版)
  18. 火车采集器如何采集ajax数据和百度站内搜索数据
  19. 「Python爬虫系列讲解」五、用 BeautifulSoup 爬取电影信息
  20. linux具有写保护权限的文件,细说Linux权限

热门文章

  1. 前端HTML学习总结
  2. 国内网络摄像机的端口及RTSP地址
  3. 小白入门炒股票关键词解释及细节注意事项
  4. 个人银行账户管理程序(C++语言程序设计第4版)
  5. 硬件电路板调试方法及步骤
  6. 四六级备考 01 两会
  7. java基础知识复习(截取)
  8. SpringBootTest注解
  9. Jlink V8 灯不亮,重刷固件(亲测可用)
  10. 大连理工大学远程与继续教育学院生产实习报告报表