LPC1768/ARM Cortex-M3 微秒延迟 [英] LPC1768 / ARM Cortex-M3 microsecond delay

查看:28
本文介绍了LPC1768/ARM Cortex-M3 微秒延迟的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在裸机臂环境 (LPC1768)/GCC 中实现微秒延迟.我看过使用 SysTimer 生成中断然后在 C 中进行一些计数的示例,用作时基

I'm trying to implement a microsecond delay in a bare metal arm environment( LPC1768 ) / GCC. I've seen the examples that use the SysTimer to generate an interrupt that then does some counting in C, which is used as a time base

https://bitbucket.org/jpc/lpc1768/src/dea43fb213ff/main.c

然而,在 12MHz 系统时钟下,我认为这不会很好地扩展到微秒延迟.基本上处理器会花所有的时间来服务中断.

However at 12MHz system clock I don't think that will scale very well to microsecond delays. Basically the processor will spend all it's time servicing the interrupt.

是否可以在循环中查询 SYSTICK_GetCurrentValue 的值,并确定一微秒内有多少滴答,一旦滴答数超过计算出的数量就退出循环?

Is it possible to query the value of SYSTICK_GetCurrentValue in a loop and determine how many ticks go in a microsecond and bail out of the loop once the number of ticks exceeds the calculated number?

我宁愿不为此使用单独的硬件计时器(但如果没有其他选择,我会这样做)

I'd rather not use a separate hardware timer for this (but will if there is no other choice)

推荐答案

这种事情不需要先中断,你可以轮询定时器,不需要用中断来过度.是的,这些示例使用中断的原因是,但这并不意味着这是使用计时器的唯一方法.

First off interrupts are not needed for this sort of thing, you can poll the timer, no need to overkill with an interrupt. yes reasons why those examples use interrupts, but that doesnt mean that is the only way to use a timer.

Guy Sirton 的回答是合理的,但我更喜欢汇编程序,因为我可以完全控制时钟周期(只要没有中断或其他项目妨碍).定时器通常更容易,因为代码更易于移植(更改处理器时钟频率并且您必须使用定时器重新调整循环,有时您所要做的就是更改初始化代码以使用不同的预分频器,或更改查找计算计数的一行),并允许系统中的中断和此类事情.

Guy Sirton's answer is sound, but I prefer assembler as I can control it exactly to the clock cycle (so long as there are no interrupts or other items that get in the way). A timer is usually easier though as the code is a bit more portable (change the processor clocks frequency and you have to re-tune the loop, with a timer, sometimes all you have to do is change the init code to use a different prescaler, or change the one line looking for the computed count), and allows for interrupts and such things in the system.

在这种情况下,虽然您说的是 12mhz 和 1 微秒,但也就是 12 条指令,是吗?放入 12 个 nops.或者分支到一些汇编程序,例如 10 个 nops 或 8 个,无论结果如何补偿两个分支上的管道冲洗.定时器和中断将消耗超过 12 个指令周期的开销.即使在循环中轮询计时器也会很草率.计数器循环也可以工作,但您需要了解分支成本并为此进行调整:

In this case though you are talking about 12mhz, and one microsecond, that is 12 instructions yes? Put in 12 nops. Or branch to some assembler with like 10 nops or 8, whatever it comes out to compensate for the pipeline flush on the two branches. A timer and interrupts is going to burn more than 12 instruction cycles in overhead. Even polling the timer in a loop is going to be sloppy. A counter loop would work too, you need to understand the branch costs though and tune for that:

delay_one_ms:
mov r0,#3
wait:
sub r0,#1 @cortex-m3 means thumb/thumb2 and gas complains about subs.
bne wait
nop  @might need some nops to tune the loop accurately
nop
bx lr

调用此函数,使用 gpio led 或 uart 输出和秒表在循环中循环 3000 万次,并查看闪烁间隔 30 秒.

Call this function, what 30 million times in a loop using a gpio led or uart output and a stop watch and see that the blinks are 30 seconds apart.

ldr r4,=uart_tx_register_address
mov r5,#0x55
again:
ldr r6,=24000000
str r5,[r4]
top:
bl delay_one_ms
sub r6,#1
bne top
str r5,[r4]
b again

实际上,因为我假设每个分支有 2 个时钟,所以测试循环有 3 个时钟,假设延迟总共是 12 个时钟,所以每个循环有 15 个时钟,30 秒是 30,000,000 微秒,理想情况下是 3000 万次循环,但我需要 12/15ths 循环次数来补偿.如果您的示波器的时基有点准确,或者至少与您希望的延迟一样准确,那么这会容易得多.

Actually since I assumed 2 clocks per branch, the test loop has 3 clocks, the delay is assumed to be a total 12 clocks so 15 clocks per loop, 30 seconds is 30,000,000 microseconds, ideally 30million loops, but I needed 12/15ths the number of loops to compensate. This is far easier if you have an oscilloscope whose timebase is somewhat accurate, or at least as accurate as you want this delay.

我自己没有研究过 ARM 的分支成本,否则我会对此发表评论.可能是两三个时钟.所以mov是1,sub是循环数的一倍,bne是循环数的两倍.两个分行到达这里两个返回.5+(3*loops)+nops=12.(3*loops)+nops=7 loops 是 2 而 nops 是 1,是吗?我认为将多个 nop 串在一起要容易得多:

I have not studied ARM's branch costs myself otherwise I would comment on that. It is likely two or three clocks. So the mov is one, the sub is one times the number of loops the bne is lets say two times the number of loops. Two for the branch to get here two for the return. 5+(3*loops)+nops=12. (3*loops)+nops=7 loops is 2 and nops is 1, yes? I think stringing a number of nops together is far easier:

delay_one_ms:
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    bx lr

如果您使用它们,您可能需要再刻录一些暂时禁用中断的指令.如果您正在寻找至少"一微秒,请不要担心.

You might have to burn a few more instructions temporarily disabling interrupts, if you use them. If you are looking for "at least" one microsecond then dont worry about it.

这篇关于LPC1768/ARM Cortex-M3 微秒延迟的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆