Ассемблерная вставка - почему не работает?

Viator
Offline
Зарегистрирован: 18.01.2019

Доброго времени суток! Осваиваю ардуину, прошу помощи.

Имеется: плата "Pro Micro", среда программирования Arduino 1.8.8.

На контакт D2 платы, связанный с разрядом порта PORTD.1, подаётся внешний сигнал. Порт циклически опрашивается двумя способами.



register uint8_t result asm("r0");

void setup() {
  pinMode(17, OUTPUT);         // (RXLED)
  pinMode(18, INPUT_PULLUP);   // PORTF.7
  pinMode(19, INPUT_PULLUP);   // PORTF.6
  pinMode(20, INPUT_PULLUP);   // PORTF.5
  pinMode(21, INPUT_PULLUP);   // PORTF.4
  pinMode( 7, OUTPUT);         // PORTE.6
  pinMode( 6, INPUT_PULLUP);   // PORTD.7
  pinMode( 4, INPUT_PULLUP);   // PORTD.4
  pinMode( 1, INPUT_PULLUP);   // PORTD.3
  pinMode( 0, INPUT_PULLUP);   // PORTD.2
  pinMode( 2, INPUT_PULLUP);   // PORTD.1 = input
  pinMode( 3, INPUT_PULLUP);   // PORTD.0
  pinMode(10, INPUT_PULLUP);   // PORTB.6
  pinMode(14, INPUT_PULLUP);   // PORTB.3
  pinMode(16, INPUT_PULLUP);   // PORTB.2
  pinMode(15, INPUT_PULLUP);   // PORTB.1
  pinMode( 5, INPUT_PULLUP);
  pinMode( 8, INPUT_PULLUP);
  pinMode( 9, INPUT_PULLUP);
  Serial.begin(9600);
}

void loop() {

  __asm__ __volatile__("in r0, 0x0B"); // r0 <- PORTD
  Serial.write (result);
  delay(500);

  result = digitalRead(2);
  Serial.write (result);
  delay(500);
}

 

b707
Offline
Зарегистрирован: 26.05.2017

"И сразу план? - видать что вы штабной!" (с)

"Осваиваю ардуину" - и сразу ассемблерная вставка? - интеграл прежде таблицы умножения? -не рано?

Viator
Offline
Зарегистрирован: 18.01.2019

Прошу прощения, тема уже создалась, а вопрос не закончил. Так вот, при чтении порта функцией digitalRead видим входной сигнал, а при пересылке байта из порта командой in каждый раз получаем число 0xBF независимо от уровня на входе.

Что здесь не так?

И попутно ещё вопрос: нужно ли включать "подтяжку" на разрядах портов, не выведенных на внешние контакты платы, например PORTB.7, PORTD.7?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А что такое 0x0B в строке №28? А если попробовать правильно написать - 0x09 ? Не заработает? Я просто остальное не смотрел, попробуйте, если не заработает, то будем продолжать "посмотрушки".

Только зря Вы это затеяли. При таком описании перемнной result, Вы можете тупо на С писать

result = PIND;

и это скомпилируется ТОЧНО В ТУ ЖЕ САМУЮ команду in, только порт правильно подставит.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

_asm__ __volatile__("in r0, 0x0B"); // r0 <- PORTD

Viator, а кто вас этому научил? Вы пытаетесь отжать R0 у компилятора,  это основной рабочий регистр, без него вообще работа МК невозможна. Компилятор просто выбросит вашу строчку как бред.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

dimax пишет:

Компилятор просто выбросит вашу строчку как бред.

Да, не, компилирует, я проверял. Но подход, конечно :)

Viator
Offline
Зарегистрирован: 18.01.2019

Да, дело в этом. Заработало. Спасибо!

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Вы запомните PORTx - для вывода, а для ввода - PINx

Viator
Offline
Зарегистрирован: 18.01.2019

Вот в этой статье

https://sites.google.com/site/vanyambauseslinux/arduino/arduino-assemble...

утверждается, что значение регистра r0 следует сохранять и восстанавливать, если ассемблерный код вызывает функцию C. Такого не предполагается.

А компилятор строчку не выбросил.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Viator пишет:

Вот в этой статье

Вы тут человек новый, пока никого не знаете, вот запомните, dimax из тех, про которых надо рассуждать так: "пофиг что там ХЗ кто написал в ХЗ какой статье, специалист то-то". Я так к нему и отношусь и ни разу не пожалел об этом.

Ну, а в данном случае его слова не противоречат статье. Регистр r0 советуют сохранять потому, что он самый "модный" у компилятора. Тот его пихает везде. Отжав его под свои нужды, Вы создали проблемы компилятору (сособенно оптимизатору), которые могут сказаться на качестве кода. не должны, но могут.

Так вообще поступать некрасиво. Всегда лучше оставить компилятору возможность самому назначить регистр. Да и порт, зачем самому адрес искать, всегда можно написать название. Я покажу как это делается на примере Вашей вставки, хотя, как я писал Вам выше, Ваша вставка не нужна вовсе, т.к. прямая запись result = PIND; прямо на С приведёт ровно к такому же коду.

А пример - держите.

register uint8_t result = 0; // Не указываем регистр, компилятор сам назначит

__asm__ __volatile__  (
	"in %[reg], %[inport] \r\n" :
		[reg] "=r" (result)    // говорим, чтобы использовал тот самый регистр, что назначил result
	: 
		[inport]  "I" (_SFR_IO_ADDR(PIND)) // говорим, что нужен PIND, чтобы самим не считать 09 там или 0B - без нас разберутся
	); 

В результате вставка скомпилировалась в 

in	r24, 0x09

Обратите внимание какой регистр выделил компилятор.

nik182
Offline
Зарегистрирован: 04.05.2015

Евгений! Можно дальше вставить оператор вывода в ком порт и посмотреть через какой регистр передастся значение? 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Простите, я не понял вопроса. Напишите кусок кода и там укажите что именно Вы хотите посмотреть.

nik182
Offline
Зарегистрирован: 04.05.2015

К вашей вставке добавить 29 строку первого сообщения. Сейчас я без компа и сам проверить не могу. Мне интересно перед вызовом serial.Write r24 в r0 перегонит или нет. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Как только добавил, он тут же стал выделять под result не 24, а 22 регистр и никуда его потом не перегружал

  96:	69 b1       	in	r22, 0x09	; 9
  Serial.write (result);
  98:	80 e0       	ldi	r24, 0x00	; 0
  9a:	91 e0       	ldi	r25, 0x01	; 1
  9c:	0e 94 48 00 	call	0x90	; 0x90 <_ZN3Ser5writeEh>

 

nik182
Offline
Зарегистрирован: 04.05.2015

Спасибо. Забавно. 

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

ЕвгенийП пишет:

Как только добавил, он тут же стал выделять под result не 24, а 22 регистр и никуда его потом не перегружал

  96:	69 b1       	in	r22, 0x09	; 9
  Serial.write (result);
  98:	80 e0       	ldi	r24, 0x00	; 0
  9a:	91 e0       	ldi	r25, 0x01	; 1
  9c:	0e 94 48 00 	call	0x90	; 0x90 <_ZN3Ser5writeEh>

 

Евгений, как обычно, обос-ал всю интригу... Евгений - вы точно преподавали?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Да, даже в нескольких университетах и не только в России, но давно, сейчас только отдельные лекции иногда,типа раз в полгода, если позовут, читаю, а что?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

mykaida пишет:
обос-ал всю интригу...
Хоцца интриги? Прошу - http://arduino.ru/forum/otvlechennye-temy/bespamyatstvo-ili-zhizn-posle-marazma

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

ЕвгенийП пишет:

Да, даже в нескольких университетах и не только в России, но давно, сейчас только отдельные лекции иногда,типа раз в полгода, если позовут, читаю, а что?

Евгений, да ёклмнэ, да я 2**10 не сомневаюсь в Вашей квалификации. Но неужели Вы выпускаете ТАКИХ студентов?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Студенты всякие бывают. Обычно 1-3 с потока очень серьёзнае ребята. Вполне себе состоялись как специалисты. Но и дрючил я их по полной. Дебила ведь неинтересно дрючить - что с него взять? Вот, почитайте, например про одного.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

ЕвгенийП пишет:

Студенты всякие бывают. Обычно 1-3 с потока очень серьёзнае ребята. Вполне себе состоялись как специалисты. Но и дрючил я их по полной. Дебила ведь неинтересно дрючить - что с него взять? Вот, почитайте, например про одного.

Евгений, кстати я - Герман. Эту вещугу я прочитал где-то около первого входа на форум. Порадовало... Это пример правильного отношения преподаватель-студент.