总结
这边简单讲讲,代码上电后从0开始发生了什么,为什么要重定位把代码复制到sdram,
bin文件前面几条跳转函数都跳转去哪 中断产生后发生什么
重定位问题
1.为什么需要重定位
把程序从一个位置移到另一个位置 叫重定位
可以只重定位部分段的数据 也可以把所有的都重定位到sdram中
一个程序有代码段,数据段,只读数据段,和bss段
整个程序开始能在 norflash上 运行的时候代码段从norflash上0位置开始运行
但是对于数据段 必须在sdram里面运行 因为norflash不支持简单的读写 和速度需求
代码跑动流程
当时用norflash启动的时候,整个cpu通过内存控制器控制地址如下
1.cpu从0开始运行,也就是norflash上面开始运行,我们把bin文件烧在norflash上面
在bin文件前面的代码中也就需要把整个程序复制到sdram中
2.在链接脚本里面 指定runtime_addr(运行时地址) 变成sdram的地址 0x03000000
3.中断属于异常的一种,arm芯片有7种模式 通过cpu寄存器CPSR寄存器,表面自己目前处于哪种状态
在每种状态都有着专属的cpu寄存器(r0~PC15)能方便更快处理异常状态,当进入异常的时候,就会发送硬件行为,主动的跳到
异常向量表,这也就是为什么0地址,4地址,8地址等等等用来存放一些跳转地址,用来配置硬件的跳转
根据架构上的设定,在开发裸机的初始化程序,按照上面出来的设定有了如下的结构
编译出来的bin文件烧录到norflash后存储如下(注意:arm32位 一条指令占4位)
![在这里插入图片描述](https://img-blog.csdnimg.cn/5b558f9bff2247d6b86695c95cb36309.png
cpu从norflash的0地址开始运行 直接跳转到复位程序的地址,开始进行初始化跑动
初始化一般需要做重定位操作,把整个程序从nor_flash复制到sdram中,再从nor_flash跳到sdram继续运行,继续完成初始化操作
如果这时候突然发生了异常或者中断,会按照中断向量表的产生硬件行为,直接跳回nor_flash中 根据异常的不同进行 进行异常程序的跳转
用中断来举个例子
有很多种中断 什么软件中断 未识别指令异常中断
说到按键中断
1.初始化 设置中断,让它能发生中断(按键设置为中断引脚,定时器,网络数据这种硬件)
1.设置gpio为中断引脚
2.设置中断触发方式 中断方式为双边沿书触发
3.使能中断
4.读eintpend寄存器,分辨是哪个中断产生了
2.设置中断控制器,让中断控制器能发送中断给cpu
1.看起来外部中断4~7合用一条中断source通知中断控制器,也就是为什么上面的引脚设置中断还要读eintpend寄存器知道是哪条中断
2设置SRCPEND寄存器,知道是哪个中断产生了,同时执行完后需要清除对应位(bit0=外部中断0,bit2=外部中断2,bit5=外部中断8_23
如果bit5置1,还要读刚刚的eintpend寄存器,看是哪个中断产生了
3.设置是否要屏蔽这个中断(就算置为1,也不告诉cpu)
4.可能有多个中断产生,此时SRCPEND多个位设置为1,经过PRIORITY优先级寄存器,只有一个到cpu
5.最后优先级最高的被cpu处理,读取INTPND寄存器就知道哪个被cpu处理
3.设置cpu里面的寄存器cpsr寄存器,里面有个i位中断总开关,设置它使能中断
把cpu寄存器的CPSR第7位置0,这是中断总开关,bit7设置为1,cpu无法响应任何中断
4.中断发生,硬件处理
中断发生直接跳中断向量表的IRQ地址 ,再从这个地址跳去处理中断的函数地址
根据图中中断发生,此时硬件直接跳转到 0x18地址,在这个地址我们写的汇编为
b irq_handle 让cpu专门跳到我们写的中断处理函数地址,对中断进行识别和处理
5.跳过去的地址为我们自己写的中断处理函数,里面包含
1.程序先保存cpu寄存器地址,保存现场
cpu的lr_irq寄存器保存被中断时候,要处理的下一条地址
进入irq模式的时候会修改cpu寄存器的r0~r12所以要先保存
lr是处理完异常后的返回地址也要保存,处理完后把lr的值给cpu的PC寄存器就能返回上一次的地方
cpu寄存器SPSR_irq 保存被中断时候的 CPSR(区分cpu模式的cpu寄存器)
cpu寄存器CPSR M4~M0位置为10010,说明现在在中断模式
硬件主动跳到 0x18 中断向量表的IRQ地址 ,再从这个地址跳去处理中断的地址
2.程序处理异常
分辨中断源
读取INTPND寄存器就知道哪个中断被cpu处理
根据中断类型选择这个中断对应的中断函数
清理中断
3.恢复现场
把cpu寄存器的CPSR第7位清零,这是中断总开关,bit7设置为1,cpu无法响应任何中断
定时器怎么使用
定时器和pmw 只有先设置好定时器,才能初始化pwm
定时器设置
1.有个时钟进入定时器,每来个时钟 tcnt寄存器-1
2.当tcnt寄存器减少到 等于 tcnt_cmp寄存器的值 产生一个中断,也可以让对应的PMW引脚反转
3.tcnt寄存器继续减1,当tcnt寄存器等于0的时候,也能产生一个中断,pmw引脚也能翻转
4.当上面两个寄存器等于0的时候,可以选择从TCMPBN和TCNTBN里面把数值放入刚刚两个寄存器
上面就是定时器会触发中断 和 根pwm的关系
怎么使用定时器呢 也有个图
1,设置时钟
从PCLK(低速时钟)过来设置PREschar预分频寄存器
2.设置初值
3.加载初值, 启动时钟
4.设置为自动加载初始化值
5,上面的中断程序怎么产生的
去中断那一章找到和定时器有关的中断
和上面一样触发了中断后 看是哪个中断源产生的中断
如果是INT_TIMER0 调用定时器的中断函数