|
|
|
|
185576 119 0 0 |
|
Опции темы | Поиск в этой теме |
16.11.2010, 22:22 | 41 |
Ветеран Фонарёвки
Регистрация: 15.02.2010 Последняя активность: 05.09.2022 18:18
Сообщений: 1034
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
А функция часом не inline определена?
|
16.11.2010, 22:25 | 42 |
Завсегдатай Фонарёвки
|
Код:
void spi_init(){ /* Set MOSI and SCK output */ PORTB = PORTB | (1<<3)|(1<<5); /* Enable SPI, Master, set clock rate fck/4 */ SPCR = (1<<SPE)|(1<<MSTR); } void spi_send(char cData){ /* Start transmission */ SPDR = cData; /* Wait for transmission complete */ while(!(SPSR & (1<<SPIF))){} } |
16.11.2010, 22:36 | 43 |
Ветеран Фонарёвки
Регистрация: 15.02.2010 Последняя активность: 05.09.2022 18:18
Сообщений: 1034
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Странно. Такое поведение, характерно для функций, определенных как
inline void spi_send(char cData) { } А определение ранее есть? т.е. такая строчка void spi_send(char cData); Я правда с winavr не работал, всех его заморочек не знаю. Возможно функции без определения он вставляет как inline |
16.11.2010, 22:45 | 44 | |
Завсегдатай Фонарёвки
|
C оптимизациями -O0 и -O1 он генерирует правильно, и функции вызывает через rcall.
С -O1 прошивка получается меньше, чем с -O2 С -O2, -O3 и -Os он начинает разбрасываться так, как я написал... Цитата:
Код:
spi_send(255); spi_send(255); spi_send(255); spi_send(255); Код:
void spi_send(char cData){ /* Start transmission */ SPDR = cData; 78: 9f ef ldi r25, 0xFF ; 255 7a: 9e bd out 0x2e, r25 ; 46 /* Wait for transmission complete */ while(!(SPSR & (1<<SPIF))){} 7c: 0d b4 in r0, 0x2d ; 45 7e: 07 fe sbrs r0, 7 80: fd cf rjmp .-6 ; 0x7c <lcd_clear+0x6> SPCR = (1<<SPE)|(1<<MSTR); } void spi_send(char cData){ /* Start transmission */ SPDR = cData; 82: 9e bd out 0x2e, r25 ; 46 /* Wait for transmission complete */ while(!(SPSR & (1<<SPIF))){} 84: 0d b4 in r0, 0x2d ; 45 86: 07 fe sbrs r0, 7 88: fd cf rjmp .-6 ; 0x84 <lcd_clear+0xe> SPCR = (1<<SPE)|(1<<MSTR); } void spi_send(char cData){ /* Start transmission */ SPDR = cData; 8a: 9e bd out 0x2e, r25 ; 46 /* Wait for transmission complete */ while(!(SPSR & (1<<SPIF))){} 8c: 0d b4 in r0, 0x2d ; 45 8e: 07 fe sbrs r0, 7 90: fd cf rjmp .-6 ; 0x8c <lcd_clear+0x16> SPCR = (1<<SPE)|(1<<MSTR); } void spi_send(char cData){ /* Start transmission */ SPDR = cData; 92: 9e bd out 0x2e, r25 ; 46 /* Wait for transmission complete */ while(!(SPSR & (1<<SPIF))){} 94: 0d b4 in r0, 0x2d ; 45 96: 07 fe sbrs r0, 7 98: fd cf rjmp .-6 ; 0x94 <lcd_clear+0x1e> spi_send(0b1000000); // Y (0...5) PORTB=PORTB | (1<<2); //LCD_D=1 } |
|
16.11.2010, 22:50 | 45 |
Ветеран Фонарёвки
Регистрация: 15.02.2010 Последняя активность: 05.09.2022 18:18
Сообщений: 1034
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Он не разбрасывается, а оптимизирует по скорости
|
16.11.2010, 22:56 | 46 | |
Завсегдатай Фонарёвки
|
А как ему обьяснить, что память у мк дорогая, это вам не комп с метрами и гектарами?
По идее, -Os должен оптимизировать для рамера. А он тоже "для скорости"... Дождаться бы Gall... Любителя -O2 и пророчащего, что Цитата:
|
|
16.11.2010, 23:04 | 47 |
Ветеран Фонарёвки
Регистрация: 15.02.2010 Последняя активность: 05.09.2022 18:18
Сообщений: 1034
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Так у тебя свободной памяти небось вагон, вот он скорость и выжимает
|
16.11.2010, 23:09 | 48 |
Завсегдатай Фонарёвки
|
Ну да, я только начал писать... Но я хочу с самого начала контролировать, что получается Потому как в итоге программа будет сложной - может даже и не влезть.
Или gcc так и будет выжимать скорость, пока петух не клюнет в обьём памяти? |
17.11.2010, 04:47 | 49 |
Ветеран Фонарёвки
Регистрация: 15.02.2010 Последняя активность: 24.08.2019 11:36
Сообщений: 1342
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Какой смысл тогда в выборе оптимизации, если компилятор всё равно делает по-своему?..
|
17.11.2010, 13:17 | 50 |
Ветеран Фонарёвки
Регистрация: 15.02.2010 Последняя активность: 05.09.2022 18:18
Сообщений: 1034
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
да хто-ж его знает, у меня ICCAVR - асбсолютно тупой послушный компилятор
|
17.11.2010, 14:52 | 51 |
Увлеченный
Регистрация: 21.06.2010 Последняя активность: 01.08.2015 23:26
Сообщений: 180
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Оптимизация -O2 - это оптимизация по скорости. Компилятор замечает, что вписать код функции прямо вместо ее вызова экономит пару тактов по сравнению с инструкцией CALL - и делает это.
Для микроконтроллеров лучше использовать опцию -Os, можно вместе с опцией -fcall-prologues. |
17.11.2010, 14:56 | 52 | ||
Завсегдатай Фонарёвки
|
Цитата:
Цитата:
Наверное -mcall-prologues Нет, всё равно не помогает! -Os -mcall-prologues всё равно вписывает функции прямо в место вызова Я так понимаю, надо более конкретно смотреть, какие оптимизации включают -Os и -O2, но не включает -O1... |
||
18.11.2010, 17:38 | 53 | |
Увлеченный
Регистрация: 21.06.2010 Последняя активность: 01.08.2015 23:26
Сообщений: 180
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Цитата:
Опция -Os НЕ дает "самый маленький" размер. Дело в том, что в большой программе вписывание функций инлайном в конечном итоге УМЕНЬШАЕТ общий размер кода. Это происходит потому, что при этом удается применить межпроцедурную оптимизацию - удалить лишние ldi, например. Написанный отдельно дубликат функции на этапе линковки будет вырезан из прошивки, если в программе не найдется ни одного call на него. Подавить его создание полностью можно, объявив функцию как static inline. Если очень хочется, чтобы функции не инлайнились, есть опция -fno-inline. |
|
18.11.2010, 17:44 | 54 | |
Завсегдатай Фонарёвки
|
Помогло! Добавил -fno-inline, получилась прошивка 176 байт вместо 230
Цитата:
|
|
20.11.2010, 14:42 | 55 |
Ветеран Фонарёвки
Регистрация: 15.02.2010 Последняя активность: 24.08.2019 11:36
Сообщений: 1342
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Переписываю и я сейчас программу на Си (RGB индикатор). Что-то меня эта оптимизация совсем не устраивает. Мало того что я не могу нормально выйти из прерывания (ему хочется сначала попрыгать туда-сюда), так ещё и обработчик меня серьёзно напугал. Вот что нужно было сделать:
Код:
ISR (TIM0_COMPA_vect) { PORTA &= 0b11001111; } Код:
compA0: in R16, PORTA ;Потушить все каналы andi R16, 0b11001111 out PORTA, R16 reti Код:
ISR (TIM0_COMPA_vect) { d2: 1f 92 push r1 d4: 0f 92 push r0 d6: 0f b6 in r0, 0x3f ; 63 d8: 0f 92 push r0 da: 11 24 eor r1, r1 dc: 8f 93 push r24 PORTA &= 0b11001111; de: 8b b3 in r24, 0x1b ; 27 e0: 8f 7c andi r24, 0xCF ; 207 e2: 8b bb out 0x1b, r24 ; 27 } e4: 8f 91 pop r24 e6: 0f 90 pop r0 e8: 0f be out 0x3f, r0 ; 63 ea: 0f 90 pop r0 ec: 1f 90 pop r1 ee: 18 95 reti Ещё я объявил глобальные переменные, свободных регистров ещё вагон, а он полез в ОЗУ. Зачем?.. И это на фоне довольно неплохой оптимизации более сложных вещей. Слип он нормально мне написал. Правда я конфигурирую всё равно ковыряясь в регистрах, не доверяю этим библиотекам. Он они что творят... Добавлено... Код:
ISR (TIM0_COMPA_vect, ISR_NAKED) { PORTA &= 0b11001111; d2: 8b b3 in r24, 0x1b ; 27 d4: 8f 7c andi r24, 0xCF ; 207 d6: 8b bb out 0x1b, r24 ; 27 reti (); d8: 18 95 reti Добавлено... Забросил затею. Мозги мои не заточены под логику этого языка. Программа разрастается в жуткие запутывающие условия. К ассемблеру уже привык. Очень послушный и понятный язык. Писать больше, но мозг кипит меньше. Может вернусь к затее когда понадобится написать большую программу, но пока что 2 килобайта ассемблерного кода меня пугают меньше Си... |
16.12.2010, 12:02 | 56 |
Ветеран Фонарёвки
|
Осилил кучу флуда и расборок по поводу "чья кочка зеленее" и возник вопрос...
А где продолжение обучения? К примеру я хотел бы увидеть как генерировать шым (на микроконтроллерах в которых он есть и так понятно а если нету, свою то функцию я напишу, но так как начинающий то не думаю что она будет оптимальной) И еще хотелось бы научиться шаговым движком рулить... в интернете примеры есть, но не всегда то что нужно или не всегда понятно. К тому же разные люди по разному объясняют. |
30.12.2010, 17:10 | 57 |
Увлеченный
Регистрация: 21.06.2010 Последняя активность: 01.08.2015 23:26
Сообщений: 180
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
Генерирование ШИМ программно
Идея очень проста, поэтому достаточно написать пример кода. Код:
while (1) { PORTB = 0xFF; delay(x); PORTB = 0x00; delay(k - x); } Функция delay может быть описана, например, так: Код:
void delay(unsigned n) { for (unsigned i = 0; i < n; ++i) { asm volatile ("nop"); } } |
30.12.2010, 18:25 | 58 |
Завсегдатай Фонарёвки
|
Gall Расскажи, как вообще в Си принято работать со строками. Для меня, после пхп, работать с "массивом букв" - это кошмар (если знаешь пхп - поймёшь всю суть моих страданий ).
Например, как можно короче записать этот код? Условия: 1. не занимать больше флеша, чем этот пример 2. не занимать больше озу, чем этот пример 3. записать компактнее char lcd[84] - промежуточный буффер, где находится полный текст, который должен выводиться на дисплей. В разных местах кода требуется менять лишь отдельные его фрагменты, например: Код:
switch(input){ case(INPUT_DISABLE): lcd[10]='['; lcd[11]='F'; lcd[12]='M'; lcd[13]='T'; lcd[14]='R'; lcd[15]=' '; lcd[16]='o'; lcd[17]='f'; lcd[18]='f'; lcd[19]=']'; return; case(INPUT_DIRECT): lcd[10]='['; lcd[11]='8'; lcd[12]='M'; lcd[13]='H'; lcd[14]='z'; lcd[15]=']'; lcd[16]=' '; lcd[17]=' '; lcd[18]=' '; lcd[19]=' '; return; case(INPUT_LOGIC): lcd[10]='['; lcd[11]='8'; lcd[12]='M'; lcd[13]='H'; lcd[14]='z'; lcd[15]=' '; lcd[16]='L'; lcd[17]='O'; lcd[18]='G'; lcd[19]=']'; return; case(INPUT_DIV16): lcd[10]='['; lcd[11]='1'; lcd[12]='2'; lcd[13]='8'; lcd[14]='M'; lcd[15]='H'; lcd[16]='z'; lcd[17]=']'; lcd[18]=' '; lcd[19]=' '; return; case(INPUT_DIV128): lcd[10]='['; lcd[11]='1'; lcd[12]='.'; lcd[13]='1'; lcd[14]='G'; lcd[15]='H'; lcd[16]='z'; lcd[17]=']'; lcd[18]=' '; lcd[19]=' '; return; } |
30.12.2010, 18:56 | 59 |
Ветеран Фонарёвки
Регистрация: 15.02.2010 Последняя активность: 05.09.2022 18:18
Сообщений: 1034
Сказал(а) спасибо: 0
Поблагодарили: 0 раз(а) в 0 сообщениях
|
например так:
_flash char str[][11]={"строка 1", "вторая","и тд." }; . case INPUT_DISABLE: memcpy(lcd+10, str[0], 10); .... case ... на строки при таком описании уйдет на 1 байт больше, из-за нуля в конце, но удобнее писать. А код сократиться. |
30.12.2010, 20:48 | 60 |
Ветеран Фонарёвки
|
Ну допустим аппаратный шим есть, но на 2х каналах а надо 4 разных на 4 при этом на всех 4х каналах должен шим быть разным, к примеру есть у меня 4 светодиодных линейки и яркость каждой мне нжно регулировать отдельно при этом в реальном времени в зависимости от определенных параметров, управление с компа или изменение входного сигнала - не суть важно.
Аппаратный это конечно хорошо, но наприпмер Mega8 должна регулировать 12 тью разными каналами (4 RGB линейки), как тут в реальном времени создавать и менять? Аппаратный не рассматриваем. Вижу 2 варианта - либо внутренний таймер либо через коэффициент как было сказано выше считая такты, вот и подходим к тому что я только начинаю осваивать и неумею нормально работать с прерываниями, а опыт программирования - самоучка на дельфях, хотя примеры для образования в интернете были - их решал сегодня закупил детали для программатора и пару тинек, одну на индикатор RGB вторая для экспериментов, там вав плеер или USB клавиатурное западло (хобби оно на самом деле так называется - в поиске посмотри, незнаю как переименовать эту фразу по другому). Пока мучаю програмный эмулятор. |