avr的应用程序启动我都做了啥(enrty.S)

avr(at90...)的中断处理函数"注册"流程:

  head.S中设置了默认中断处理(即:not_defined -> reset),同时注意到,这些位置的标记(symbol)都是弱的(.weak指明),也就是说,可以在程序中替换这些默认中断处理,也就是正常的方式,通过编译器定义好的方式写中断函数就可以了,编译器将我们自定义的中断处理函数做如下处理:

1. 保存现场(prologue);

2. 做真正的事;

3. 还原现场(epilogue);

4. reti从中断返回。

 

上面都是传统的方式,能够正常工作,也是大部分程序所采用的方法。 我们希望对其稍微改动,因为我们认为上面有几个不足:

1. 每个自定义中断处理函数,被编译器加上了头(prologue)和尾(epilogue),有点浪费code空间(,编译器加上naked参数能够跳过这些);

2. 不能为同一中断号注册多个处理函数,虽然一般不需要这样做(,当然也许你可以想到,把原来的中断处理例程中,改造为一个分发器也能实现这个,但我没有这样做);

3. 由1.引出的想法,中断处理的第一跳指令不是我们的指令,是不是不可控,作为新人类,我们要对我们的代码实行完全控制(代码控制控制欲),乱说的。。。

 

改造:

结合linux arm的还向量表构造来看,我们的难点将会是如果在我们所谓的“可控代码”中找到中断号(irq_nr):

1. 中断向量表处只能存放一条跳转指令,没有机会保存中断号;

2. 对这款芯片,各个中断标记分散在单独模块的寄存器中,如果做轮询的话,代码会很冗余;

取巧法:

hw_vect:

jmp reset

jmp sf_vect0

jmp sf_vect1

...

 

sf_vect0:

mov regX, 0

jmp prologue

sf_vect1:

mov regX, 1

jmp prologue

...

prologue:

do prologue

real_irq:

mov regY, regX ; 将irq_nr存入作为参数的寄存器

call do_IRQ ; 分发器,里面调用自定义的中断处理函数

epilogue:

do epilogue

 

reti

 

完成后,除了省了一些空间外,没发现有什么好的了,好玩而已?

 

补充(100506):用了这套东西,我们的串口无法输出爽快,输出几个字节就不动了,最后查找到问题在do_IRQ(int nr),我从内核里抄过来的原型,问题就出在这个int上,换成uint8_t它就爽了。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值