Первые прерывания не нужны для такого рода вещей, вы можете опрашивать таймер, нет необходимости перебивать прерывания. Да, причины, по которым в этих примерах используются прерывания, но это не означает, что это единственный способ использовать таймер.
Ответ Гая Сиртона звучит здраво, но я предпочитаю ассемблер, так как могу управлять им точно по такту (при условии, что на пути нет прерываний или других предметов). Таймер обычно проще, хотя, поскольку код немного более переносим (измените тактовую частоту процессора, и вам придется перенастроить цикл с помощью таймера, иногда все, что вам нужно сделать, это изменить код инициализации, чтобы использовать другой прескалер или измените одну строку в поисках вычисленного значения) и разрешите прерывания и тому подобное в системе.
В данном случае, хотя вы говорите о 12 МГц и одной микросекунде, это 12 инструкций, да? Положите в 12 нопс. Или переходите к какому-либо ассемблеру с 10 или 8 шайбами, чтобы компенсировать сбрасывание конвейера на двух ветвях. Таймер и прерывания сжигают более 12 циклов команд в служебной информации. Даже опрос таймера в цикле будет небрежным. Контурный цикл тоже подойдет, вам нужно понять затраты на ветку и настроить на это:
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
Вызовите эту функцию, что 30 миллионов раз в цикле, используя светодиод gpio или выход uart и секундомер, и увидите, что мигания с интервалом 30 секунд.
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 микросекунд, в идеале 30 миллионов циклов, но мне нужно 12 / 15-е число петель для компенсации. Это гораздо проще, если у вас есть осциллограф, чья временная база несколько точна, или, по крайней мере, настолько точна, насколько вы хотите, чтобы эта задержка.
Я сам не изучал стоимость филиала ARM, иначе я бы прокомментировал это. Вероятно, это два или три часа. Таким образом, значение mov равно единице, а sub - умножению числа циклов на единицу, скажем, в два раза больше числа циклов. Два для филиала, чтобы получить здесь два для возвращения. 5 + (3 *) + петли NOPS = 12. (3 * петли) + nops = 7 циклов - 2, а nops - 1, да? Я думаю, что объединить несколько nops вместе гораздо проще:
delay_one_ms:
nop
nop
nop
nop
nop
nop
nop
nop
bx lr
Возможно, вам придется записать еще несколько инструкций, временно отключающих прерывания, если вы их используете. Если вы ищете «хотя бы» одну микросекунду, не беспокойтесь об этом.