Ассемблер и среда разработки Arduino
- Войдите на сайт для отправки комментариев
Вс, 30/12/2012 - 16:45
Господа, возник такой ламерский вопрос. можно ли в скетч вставлять куски ассемблерного кода? к примеру, если есть желание поковыряться с АЦП или еще каким узлом контроллера. если возможноть работы с регистрами напрямую есть в скетчах, то где покурить подробный мануал?
если возможноть работы с регистрами напрямую есть в скетчах, то где покурить подробный мануал?
http://www.atmel.com/Images/doc8161.pdf
спасибо, даташитом на мою мегу 1280 владею, и кое-какой опыт работы в avr studio тоже есть. Вопрос заключается в том, можно ли в теле С/С++ скетча вставлять куски ассемблерного кода? собсно, мануал нужен на более подробное описание языка ардуино, так как список функций, представленный на сайте неполон. к примеру, обратные тригонометрические функции здесь не описаны.
Можно
void setup() { pinMode(13, OUTPUT); pinMode(12, INPUT); Serial.begin(115200); } void loop() { unsigned char reg=26; cli(); asm volatile( "push %0 \n" "label_1%=: \n" "COM %0 \n" "out %1, %0 \n" "rjmp label_1%= \n" "pop %0 \n" : "=&r" (reg) : "I" (_SFR_IO_ADDR(PORTB)) ) ; sei(); }спасибо, надо попробовать
а как ассемблеру передать ссылку на массив?
писать можно на чистом асме без всяких извращений с кавычками и подчёркиваниями,просто код..
http://robocraft.ru/blog/981.html
ответ не заставил себя ждать многим более 2-х лет )))
ответ не заставил себя ждать многим более 2-х лет )))
Медаль нашла своего героя )))
Помогите сделать ассемблерную вставку: определить блок 512байт, затем на ассемблере байт АЦП в 1ю и так 512 раз, выскочить. Можно так? Это для пультоскопа.
Курсовики тут не делают.
Помогите сделать ассемблерную вставку: определить блок 512байт, затем на ассемблере байт АЦП в 1ю и так 512 раз, выскочить. Можно так? Это для пультоскопа.
Можно, я разрешаю.
значит сделаешь!
значит сделаешь!
Странная логика. Он разрешает.
Вот ты у учителя спрашиваешь: "Можно выйти?", и он разрешает. Ты думаешь, что курить в сортире он тоже сам будет или ты? ;))
Как вариант... Напиши это на ардуино, посмотри код ассемблера и отдай преподу . Google подскажет как посмотреть листинг кода ардуиновского в асме.
Нету препода...
Могли бы деду и помочь, а не хихикать...
Вставка на ассемблере для родного АЦП не даёт преимущества ...
Как без боли писать на ассемблере в arduino IDE
http://robocraft.ru/blog/981.html
https://embedderslife.wordpress.com/2012/02/19/avr-gcc-asm-and-c/
Нисмотря на то что автор по первой ссылке в названии написал какую-то дичь, статья именно про лучший способ писать на ассемблере в этой среде. Смысл в том что надо создать отдельный файл и писать в нем и затем вызывать по мере надобности.
Могли бы деду и помочь, а не хихикать...
Если ты знаешь ассемблер AVR, то вот, пользуйся без головняков
http://arduino.ru/forum/otvlechennye-temy/znaete-li-vy-shto-assembler-arduino-ide
Помогите сделать ассемблерную вставку: определить блок 512байт, затем на ассемблере байт АЦП в 1ю и так 512 раз, выскочить. Можно так? Это для пультоскопа.
Для ускорения пультоскопа нужно менять МК на 32-битный :). Ассемблер иногда конечно нужен, но не в данном случае. Смотрим:
Опрос АЦП из скетча пультоскопа на СИ:
ADMUX = (1<<REFS0)|(1<<ADLAR);// channel adc0 ADCSRB=0; ADCSRA = (1<<ADEN)|(1<<ADSC)|(1<<ADATE) |(1<<ADPS1); for (int i = 0; i < BUFSIZE; i++) { //for.. while (!(ADCSRA & ADIF)); //wait adif flag ADCSRA |= 0x10; //clear adif adcBuf[i] = ADCH; //load to buff }Дизассемблируем этот код с помощью avr-objdump, справа мои комментарии
Получаем ассемблерный код практически без излишеств. Т.е. если переписать тот фрагмент на голом ассемблере то выигрыша не будет совсем.
А если 512 раз написать: читать АЦП, писать в ячейку буфера, модифицировать адрес - так моно? Интересно, ск тактов надо АЦП для преобразования?
АЦП медленный (даже на самой высокой скорости) и нет разницы на каком языке писать программу !
uldin@mail.ru, как уже сказал командир - слабое звено тут АЦП, а не алгоритм. Пока АЦП тужится что-б выдать свой очередной семпл -МК за это время успевает отстрочить полсотни тактов. Алгоритм любой медлительности успеет положить взятый ранее байт в буфер, вернуться, и крутиться дальше в цикле ожидая флага готовности. Так что если хочется быстрее - вперёд осваивать ARM :)
Внук помог - написал расчет в массив и загрузка на комп. Осталось быстро-быстро заполнить массив из АЦП в 8266, передать по WiFi на Андроид и получить пультоскоп))
uldin@mail.ru http://arduino.ru/forum/proekty/virtualnyi-ostsillograf
float привести к int, а потом запихать во write()? За какой ассемблер тут речь вообще?
Подпрограмма AddMeasuring() не нужна, Короче и проще
а кто проверит, поддерживает ли компилятор, RAW формат ввода ?
с11 уже включена была такая возможность.
а кто проверит, поддерживает ли компилятор, RAW формат ввода ?
А сам? Если компилятор не заругался- значит поддерживает.
у меня небыло возможности
Проверил, работает.
void loop() { digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) delay(100); // wait for a second digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW delay(100); asm(R"( ldi r16,0x03 out 0x05,r16 out 0x04,r17 )");но имена портов не понимает PORTB PINB и т.д. . Такие конструкции: ldi r17,(1<<DDB3)|(1<<DDB2)|(1<<DDB1)|(1<<DDB0) - тоже не понимает возможно еще потому что формат assembler'a стоит по умолчанию AT&T а не intel. Надо как-то ключ компилятору отправить и попробовать.
Но это уже лучше чем через запятую все писать. Однако отдельным файлом еще лучше подключать.
Но это уже лучше чем через запятую все писать.
Это о чем Вы ?
Чем это лучше, чем:
asm volatile(
"ldi r16,0x03 \n\t"
"out 0x05,r16 \n\t"
"out 0x04,r17 \n\t"
)
Это о чем Вы ?
Чем это лучше, чем:
asm volatile(
"ldi r16,0x03 \n\t"
"out 0x05,r16 \n\t"
"out 0x04,r17 \n\t"
)
Ты дурак или прикидываешся ? По-моему даже дарак видит разницу,а ты не увидел...
Между твоим венегретом с какой-то левой х-той
asm
volatile(
"ldi r16,0x03 \n\t"
"out 0x05,r16 \n\t"
"ldi r16,0x03 \n\t"
)
и предложенным RAW форматом, безо всякой твоей х.еты с лишними символами в коде в каждой строчке.
Дурака вы каждое утро видите в зеркале !!!
Значит хуже дурака...
Только дураки не знают как пользоваться именами портов и пинов !
difine сделаны только для того что бы быстро переназначить порты/выводы
\n\t вставляются только для того, что бы в листинге было красиво.
#define SCL0PORT PORTB #define SCL0PIN PORTB1 #define SDA0PORT PORTB #define SDA0PIN PORTB2 #define SCL1PORT PORTB #define SCL1PIN PORTB3 #define SDA1PORT PORTB #define SDA1PIN PORTB4 void __attribute__ ((noinline)) i2c_init(uint8_t device=0) { asm volatile( "TST %8\n\t" "BRNE i2c_init_1\n\t" "CBI %0-1,%1\n\t" "CBI %2-1,%3\n\t" "CBI %2,%3\n\t" "CBI %0,%1\n\t" "RJMP i2c_init_2\n\t" "i2c_init_1:\n\t" "CBI %4-1,%5\n\t" "CBI %6-1,%7\n\t" "CBI %6,%7\n\t" "CBI %4,%5\n\t" "NOP\n\t" "i2c_init_2:\n\t" ::"I" (_SFR_IO_ADDR(SCL0PORT)), "I" (SCL0PIN), "I" (_SFR_IO_ADDR(SDA0PORT)), "I" (SDA0PIN), "I" (_SFR_IO_ADDR(SCL1PORT)), "I" (SCL1PIN), "I" (_SFR_IO_ADDR(SDA1PORT)), "I" (SDA1PIN), "r" (device) ); }Круто! Вот только ардуины не вижу в последнем сообщении. Может быть можно хоть один ардуиновский оператор вставить? А то как то совсем не по теме форума получается. В отвлечённые темы больше просится.
Могу весь скетч вставить, если интересно ... (Пишем в два i2c девайса на любых пинах под камень 16Мгц с полностью выдержанными интервалами в посылках). В качестве i2c - дисплей SSD1306 128x64.
#define SCL0PORT PORTB #define SCL0PIN PORTB1 #define SDA0PORT PORTB #define SDA0PIN PORTB2 #define SCL1PORT PORTB #define SCL1PIN PORTB3 #define SDA1PORT PORTB #define SDA1PIN PORTB4 #include <avr/pgmspace.h> void __attribute__ ((noinline)) i2c_init(uint8_t device=0) { asm volatile( "TST %8\n\t" "BRNE i2c_init_1\n\t" "CBI %0-1,%1\n\t" "CBI %2-1,%3\n\t" "CBI %2,%3\n\t" "CBI %0,%1\n\t" "RJMP i2c_init_2\n\t" "i2c_init_1:\n\t" "CBI %4-1,%5\n\t" "CBI %6-1,%7\n\t" "CBI %6,%7\n\t" "CBI %4,%5\n\t" "NOP\n\t" "i2c_init_2:\n\t" ::"I" (_SFR_IO_ADDR(SCL0PORT)), "I" (SCL0PIN), "I" (_SFR_IO_ADDR(SDA0PORT)), "I" (SDA0PIN), "I" (_SFR_IO_ADDR(SCL1PORT)), "I" (SCL1PIN), "I" (_SFR_IO_ADDR(SDA1PORT)), "I" (SDA1PIN), "r" (device) ); } void __attribute__ ((noinline)) i2c_start(uint8_t device=0) { asm volatile( "SBRS %4,0\n\t" "SBI %0-1,%1\n\t" "SBRC %4,0\n\t" "SBI %2-1,%3\n\t" ::"I" (_SFR_IO_ADDR(SDA0PORT)), "I" (SDA0PIN), "I" (_SFR_IO_ADDR(SDA1PORT)), "I" (SDA1PIN), "r" (device) ); } void __attribute__ ((noinline)) i2c_write(uint8_t data, uint8_t device=0) { uint8_t b,i; asm ( "LDI %10,8\n\t" "i2c_write_1:" "SBRS %8,0\n\t" "SBI %0-1,%1\n\t" "SBRC %8,0\n\t" "SBI %4-1,%5\n\t" "ROL %9\n\t" "BRCS i2c_write_2\n\t" "SBRS %8,0\n\t" "SBI %2-1,%3\n\t" "SBRC %8,0\n\t" "SBI %6-1,%7\n\t" "RJMP i2c_write_3\n" "i2c_write_2:\n\t" "SBRS %8,0\n\t" "CBI %2-1,%3\n\t" "SBRC %8,0\n\t" "CBI %6-1,%7\n\t" "NOP\n" "i2c_write_3:\n\t" "LDI %11,4\n" "i2c_write_4:\n\t" "DEC %11\n\t" "BRNE i2c_write_4\n\t" "SBRS %8,0\n\t" "CBI %0-1,%1\n\t" "SBRC %8,0\n\t" "CBI %4-1,%5\n\t" "LDI %11,2\n" "i2c_write_5:\n\t" "DEC %11\n\t" "BRNE i2c_write_5\n\t" "DEC %10\n\t" "BRNE i2c_write_1\n\t" "NOP\n\t" "SBRS %8,0\n\t" "SBI %0-1,%1\n\t" "SBRC %8,0\n\t" "SBI %4-1,%5\n\t" "SBRS %8,0\n\t" "CBI %2-1,%3\n\t" "SBRC %8,0\n\t" "CBI %6-1,%7\n\t" "TST %8\n\t" "BRNE i2c_write_6\n\t" "NOP\n" "i2c_write_7:\n\t" "SBIC %2-2,%3\n\t" "RJMP i2c_write_7\n\t" "RJMP i2c_write_8\n" "i2c_write_6:\n\t" "SBIC %6-2,%7\n\t" "RJMP i2c_write_6\n\t" "NOP\n\t" "NOP\n" "i2c_write_8:\n\t" "LDI %11,3\n\t" "i2c_write_9:\n\t" "DEC %11\n\t" "BRNE i2c_write_9\n\t" "SBRS %8,0\n\t" "CBI %0-1,%1\n\t" "SBRC %8,0\n\t" "CBI %4-1,%5\n\t" "LDI %11,3\n" "i2c_write_10:\n\t" "DEC %11\n\t" "BRNE i2c_write_10\n\t" "SBRS %8,0\n\t" "SBI %0-1,%1\n\t" "SBRC %8,0\n\t" "SBI %4-1,%5\n\t" "LDI %11,4\n" "i2c_write_11:\n\t" "DEC %11\n\t" "BRNE i2c_write_11\n\t" "NOP\n\t" "NOP\n\t" ::"I" (_SFR_IO_ADDR(SCL0PORT)), "I" (SCL0PIN), "I" (_SFR_IO_ADDR(SDA0PORT)), "I" (SDA0PIN), "I" (_SFR_IO_ADDR(SCL1PORT)), "I" (SCL1PIN), "I" (_SFR_IO_ADDR(SDA1PORT)), "I" (SDA1PIN), "r" (device), "r" (data), "r" (b), "r" (i) ); } void __attribute__ ((noinline)) i2c_stop(uint8_t device=0) { uint8_t i; asm volatile( "SBRS %8,0\n\t" "SBI %2-1,%3\n\t" "SBRC %8,0\n\t" "SBI %6-1,%7\n\t" "LDI %9,6\n" "i2c_stop_1:\n\t" "DEC %9\n\t" "BRNE i2c_stop_1\n\t" "SBRS %8,0\n\t" "CBI %0-1,%1\n\t" "SBRC %8,0\n\t" "CBI %4-1,%5\n\t" "LDI %9,2\n\t" "i2c_stop_2:\n\t" "DEC %9\n\t" "BRNE i2c_stop_2\n\t" "SBRS %8,0\n\t" "CBI %2-1,%3\n\t" "SBRC %8,0\n\t" "CBI %6-1,%7\n\t" "LDI %9,3\n" "i2c_stop_3:\n\t" "DEC %9\n\t" "BRNE i2c_stop_3\n\t" ::"I" (_SFR_IO_ADDR(SCL0PORT)), "I" (SCL0PIN), "I" (_SFR_IO_ADDR(SDA0PORT)), "I" (SDA0PIN), "I" (_SFR_IO_ADDR(SCL1PORT)), "I" (SCL1PIN), "I" (_SFR_IO_ADDR(SDA1PORT)), "I" (SDA1PIN), "r" (device), "r" (i) ); } static const uint8_t PROGMEM init_bytes[]={0x3C<<1,0x00,0xAE,0xD5,0x80,0xA8,0x1F,0xD3,0x00,0x40,0x8D,0x14,0x20,0x00,0xA0,0xC0, 0xDA,0x02,0xD9,0xF1,0xDB,0x40,0x21,0x00,0x7f,0x22,0x00,0x03,0xA4,0xA6,0xAF}; static const uint8_t PROGMEM impreza[] = { 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x38, 0x70, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0x70, 0x38, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x38, 0xF0, 0xE0, 0x00, 0x00, 0xF8, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x38, 0xF0, 0xE0, 0x00, 0x00, 0xE0, 0xF0, 0x38, 0x18, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x98, 0x98, 0xD8, 0xD8, 0x78, 0x78, 0x38, 0x38, 0x18, 0x18, 0x00, 0x00, 0xE0, 0xF0, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x38, 0xF0, 0xE0, 0x1F, 0x1F, 0x00, 0x00, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0E, 0x1C, 0x0E, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x00, 0x00, 0x1F, 0x1F, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x03, 0x01, 0x00, 0x00, 0x1F, 0x1F, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0E, 0x1F, 0x1B, 0x11, 0x00, 0x00, 0x07, 0x0F, 0x1C, 0x18, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x00, 0x00, 0x18, 0x18, 0x1C, 0x1C, 0x1E, 0x1E, 0x1B, 0x1B, 0x19, 0x19, 0x19, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x1F, 0x1F, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1F, 0x1F}; void setup() { i2c_init(); i2c_start(); for(uint8_t i=0;i<sizeof(init_bytes);i++) i2c_write(pgm_read_byte(init_bytes+i)); asm volatile ("nop\n\t""nop"); i2c_stop(); i2c_start(); i2c_write(0x3C<<1); asm volatile ("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop"); i2c_write(0x40); asm volatile ("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop"); } void loop() { for(uint8_t i=0;i<128;i++) i2c_write(0x00); for(uint8_t i=0;i<128;i++) i2c_write(pgm_read_byte(impreza+i)); for(uint8_t i=0;i<128;i++) i2c_write(pgm_read_byte(impreza+i+128)); for(uint8_t i=0;i<128;i++) i2c_write(0x00); while (1) {}; }Только дураки не знают как пользоваться именами портов и пинов !
Так это же Серёжа Селево! Хочет всё и сразу.) Он безобидный парень, только ругается иногда.)))
и предложенным RAW форматом, безо всякой твоей х.еты с лишними символами в коде в каждой строчке.
Ну так покажите нам как в вашей не х.ете (и она не моя, а разработана GCC для не скудоумных) обращаться к переменным, константам, ..., ... ?
Ты оказывается не только глуп но еще и ленив, тут два раза давали ссылки на статьи в которых описано как происходит взаимодействие Си-ассемблер в функциях и переменных
Ну вы же подняли тему RAW формата, а он про inline вставки на ассемблере. Чего завиляли то сразу ??? Нет сил/ума освоить несколько страниц - https://web.stanford.edu/class/ee281/projects/aut2002/yingzong-mouse/media/GCCAVRInlAsmCB.pdf