Почему моя программа мигания ATtiny85 работает только с 4 из 16 регистров?

Следующая программа мерцания прекрасно работает на моей плате программатора Attiny85 SparkFun Tiny AVR. Он производит 5 коротких миганий, а затем останавливается.

Он также отлично работает, когда я изменяю r16 на любой из регистров r17, r21 или r29. Но попытка с любым другим регистром дает либо полное отсутствие мигания (r19, r20, r23, r25, r26, r27, r28, r31), либо бесконечное мигание (r18, r22, r24, r30).

Кто-нибудь может объяснить?

int ledPin = 0;

void setup() {

  pinMode(ledPin, OUTPUT);

  asm("ldi r16, 5");
  asm("blink:");
  digitalWrite(ledPin, HIGH);
  delay(500);
  digitalWrite(ledPin, LOW);
  delay(500);
  asm("dec r16");
  asm("brge blink");
}

void loop() {
}

, 👍-1

Обсуждение

Почему вы пытаетесь смешать ассемблер, не зная заранее, какие регистры уже используются программой для других целей? Либо используйте C, либо используйте сборку. Не смешивайте их так., @Majenko

Обычно я так не смешиваю, а вставил мерцающую часть по причине отладки. Почему я использую встроенный ассемблер, чтобы ускорить внутренний цикл., @RobertFo


2 ответа


0

Решил сам! Команда высокого уровня "delay(500)" уничтожает содержимое регистра. Сохранение регистра (используя push/pop) при выполнении delay() решает эту проблему. (Кстати, должно быть "brpl", а не "brge".)

,

0

Как вы заметили, вызов функции может привести к затиранию некоторых регистров. Чтобы быть точным, документация avr-gcc гласит:

Регистры, используемые при вызове

Регистры общего назначения (GPR), используемые или затираемые при вызове, — это регистры, которые могут быть уничтожены (затерты) вызовом функции.

R18–R27, R30, R31 Эти георадары называются затертыми. Обычная функция может использовать их без восстановления содержимого. Подпрограммы обслуживания прерываний (ISR) должны сохранять и восстанавливать каждый используемый ими регистр.

Регистрация сохраненных вызовов

R2–R17, R28, R29 Остальные GPR сохраняются при вызове, т.е. функция, использующая такие регистры, должна восстановить исходное содержимое. Это применимо, даже если регистр используется для передачи аргумента функции.

Теперь интересная деталь заключается в том, что, согласно документации, можно ожидать, что R28 будет работать. Может быть, это затирается не вызванной процедурой, а вашей локальной процедурой (смешивать ассемблер и C в нетривиальных количествах — сложная задача). задача именно по этой причине).

,