Обсуждаем контроллеры компании Atmel.
Ответить

Re: Нескольно простых вопросов о программировании AVR на Си.

Пт мар 24, 2017 07:14:22

WiseLord писал(а):А make должен любой абсолютно подходить.
ага. должен. но не подходит.
Изображение
во всяком случае в винде make от Borland (или как там теперь эта компания называется?) в упор не умеет работать с проектами avr-gcc - на каждую строчку ругается "неизвестная команда".

Re: Нескольно простых вопросов о программировании AVR на Си.

Пт мар 24, 2017 11:41:18

Andrew88 писал(а):При попытке хоть что-то скомпилить, получаю ошибку:

1) Под этой фразой я понимаю попытку скомпилировать самый простой исходник, типа
Спойлер
Код:
int main (void)
{
        return 0;
}

Код:
# avr-gcc -c -mmcu=atmega8  main.c


А Вы понимаете: собрать проект, который в архиве занимает около 200K (понятно, что там не только исходники,но "копать" проект не сильно хочется).
Andrew88 писал(а):
Код:
avr-gcc -g -Wall -Werror -lm -Os -mcall-prologues -fshort-enums -ffunction-sections -fdata-sections -MMD -MP -MT build/volume.o -MF build/./volume.d -mmcu=atmega8 -DF_CPU=8000000 -D_PIN1 -D_TEA5767 -D_RDA580X -D_TUX032 -c -o build/volume.o volume.c
as: неизвестный ключ «-mmcu=avr4»


2) Зачем Вы говорите про какой-то make, если у Вас ошибка при запуске avr-gcc. Вбейте "руками" строку запуска gcc и убедитесь, что проблема осталась (т.е make тут вообще "никаким боком").

Добавьте в строку запуска gcc ключик вывода расширенной информации (-v) и сюда все что Вам в ответ "вывалилось"

Код:
$ avr-gcc -v -g -Wall -Werror -lm -Os -mcall-prologues -fshort-enums -ffunction-sections -fdata-sections -MMD -MP -MT build/volume.o -MF build/./volume.d -mmcu=atmega8 -DF_CPU=8000000 -D_PIN1 -D_TEA5767 -D_RDA580X -D_TUX032 -c -o build/volume.o volume.c

Re: Нескольно простых вопросов о программировании AVR на Си.

Пт мар 24, 2017 15:12:53

viiv писал(а):1) Под этой фразой я понимаю попытку скомпилировать самый простой исходник, типа

Да. Создал в Code Blocks проект-"рыбу" под AVR, в выхлопе та же ошибка
Код:
---------- Build: Release in avr (compiler: GNU GCC Compiler for AVR)----------

avr-gcc -Wall -mmcu=atmega8 -DF_CPU=8000000UL -Os -I/usr/include -c fuse.c -o obj/Release/fuse.o
as: неизвестный ключ «-mmcu=avr4»
Process terminated with status 1 (0 minute(s), 0 second(s))
0 error(s), 0 warning(s) (0 minute(s), 0 second(s))
 


viiv писал(а):Добавьте в строку запуска gcc ключик вывода расширенной информации (-v) и сюда все что Вам в ответ "вывалилось"

Добавил, вот:
Код:
~/Desktop2/fm7segm-master> make all
avr-gcc -v -g -Wall -Werror -lm -Os -mcall-prologues -fshort-enums -ffunction-sections -fdata-sections -MMD -MP -MT build/volume.o -MF build/./volume.d -mmcu=atmega8 -DF_CPU=8000000 -D_PIN1 -D_TEA5767 -D_RDA580X -D_TUX032 -c -o build/volume.o volume.c
Using built-in specs.
Reading specs from /opt/cross/lib/gcc/avr/5.4.0/device-specs/specs-atmega8
COLLECT_GCC=/opt/cross/bin/avr-gcc
Target: avr
Configured with: ../gcc-5.4.0/configure -v --target=avr --disable-nls --mandir=/opt/cross/share/man --infodir=/opt/cross/share/info --program-prefix=avr- --prefix=/opt/cross --with-gnu-ld --with-gnu-as --enable-languages=c,c++ --disable-libssp --with-dwarf2
Thread model: single
gcc version 5.4.0 (GCC)
COLLECT_GCC_OPTIONS='-v' '-g' '-Wall' '-Werror' '-Os' '-mcall-prologues' '-fshort-enums' '-ffunction-sections' '-fdata-sections' '-MMD' '-MP' '-MT' 'build/volume.o' '-MF' 'build/./volume.d'  '-D' 'F_CPU=8000000' '-D' '_PIN1' '-D' '_TEA5767' '-D' '_RDA580X' '-D' '_TUX032' '-c' '-o' 'build/volume.o' '-specs=device-specs/specs-atmega8' '-mmcu=avr4'
 /opt/cross/libexec/gcc/avr/5.4.0/cc1 -quiet -v -imultilib avr4 -MMD build/volume.d -MF build/./volume.d -MP -MT build/volume.o -D__AVR_ATmega8__ -D__AVR_DEVICE_NAME__=atmega8 -D F_CPU=8000000 -D _PIN1 -D _TEA5767 -D _RDA580X -D _TUX032 volume.c -mn-flash=1 -mno-skip-bug -quiet -dumpbase volume.c -mcall-prologues -mmcu=avr4 -auxbase-strip build/volume.o -g -Os -Wall -Werror -version -fshort-enums -ffunction-sections -fdata-sections -o /tmp/cc4A5zi6.s
GNU C11 (GCC) version 5.4.0 (avr)
        compiled by GNU C version 4.8.3 20140627 [gcc-4_8-branch revision 212064], GMP version 5.1.3, MPFR version 3.1.2, MPC version 1.0.2
warning: GMP header version 5.1.3 differs from library version 5.1.2.
warning: MPC header version 1.0.2 differs from library version 1.0.
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/opt/cross/lib/gcc/avr/5.4.0/../../../../avr/sys-include"
#include "..." search starts here:
#include <...> search starts here:
 /opt/cross/lib/gcc/avr/5.4.0/include
 /opt/cross/lib/gcc/avr/5.4.0/include-fixed
 /opt/cross/lib/gcc/avr/5.4.0/../../../../avr/include
End of search list.
GNU C11 (GCC) version 5.4.0 (avr)
        compiled by GNU C version 4.8.3 20140627 [gcc-4_8-branch revision 212064], GMP version 5.1.3, MPFR version 3.1.2, MPC version 1.0.2
warning: GMP header version 5.1.3 differs from library version 5.1.2.
warning: MPC header version 1.0.2 differs from library version 1.0.
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 0968929aedc7da3ce3f041d621a0f017
COLLECT_GCC_OPTIONS='-v' '-g' '-Wall' '-Werror' '-Os' '-mcall-prologues' '-fshort-enums' '-ffunction-sections' '-fdata-sections' '-MMD' '-MP' '-MT' 'build/volume.o' '-MF' 'build/./volume.d'  '-D' 'F_CPU=8000000' '-D' '_PIN1' '-D' '_TEA5767' '-D' '_RDA580X' '-D' '_TUX032' '-c' '-o' 'build/volume.o' '-specs=device-specs/specs-atmega8' '-mmcu=avr4'
 as -v -mmcu=avr4 -mno-skip-bug -o build/volume.o /tmp/cc4A5zi6.s
GNU ассемблер, версия 2.28.0 (i586-suse-linux); используется BFD версии (GNU Binutils; devel:gcc / openSUSE_13.1) 2.28.0.20170308-270
as: неизвестный ключ «-mmcu=avr4»
make: *** [build/volume.o] Ошибка 1

Есть пара варнингов, но вряд ли дело в них.

WiseLord писал(а):Ругается на отсутствующий avr4. У меня в Gentoo это /usr/avr/lib/avr4/ (тут и для atmega8 объектный файл лежит). Но принадлежит это не пакету avr-gcc, а avr-libc. Убедитесь, что эта библиотека тоже установлена.

avr-libc установлен, без него Suse не давала ставить остальное - ругалась про неудовлетворенные зависимости и все такое.
Стоит это дело в /opt/cross/avr/lib/avr4
Пробовал копировать в /usr/avr/lib/ - разницы никакой :(

Re: Нескольно простых вопросов о программировании AVR на Си.

Пт мар 24, 2017 17:54:41

Andrew88 писал(а):Добавил, вот:

Ну Вы и упорный :)) Зачем make? Чтобы думать, что он там наставил в переменных окружения? Трудно в командную строку скопировать
Код:
avr-gcc -v -g -Wall -Werror -lm -Os -mcall-prologues -fshort-enums -ffunction-sections -fdata-sections -MMD -MP -MT build/volume.o -MF build/./volume.d -mmcu=atmega8 -DF_CPU=8000000 -D_PIN1 -D_TEA5767 -D_RDA580X -D_TUX032 -c -o build/volume.o volume.c


Ну да ладно.
Вот, похоже Ваша проблема:
Код:
 as -v -mmcu=avr4 -mno-skip-bug -o build/volume.o /tmp/cc4A5zi6.s
GNU ассемблер, версия 2.28.0 (i586-suse-linux); используется BFD версии (GNU Binutils; devel:gcc / openSUSE_13.1) 2.28.0.20170308-270
as: неизвестный ключ «-mmcu=avr4»

Вместо AVR ассемблера вызвался ассемблер для хоста (i586-suse-linux), который знать ничего не знает про avr. Скорей всего при конфигурировании при сборке Вашего gcc, что-то напутали (as вызывается без полного пути - а ассемблер хоста находится раньше).

Как временная мера - попробуйте, путь в котором лежат бинарники для avr указать самым первым в переменной PATH (чтобы avr-овский as находился раньше, чем as-хоста (обычно лежит /usr/bin)). По хорошему - надо собрать gcc чтобы вызывался свой-родной кросс-ассемблер (с полным путем).

Re: Нескольно простых вопросов о программировании AVR на Си.

Пт мар 24, 2017 18:07:51

viiv писал(а):Ну Вы и упорный :)) Зачем make? Чтобы думать, что он там наставил в переменных окружения? Трудно в командную строку скопировать
Код:
avr-gcc -v -g -Wall -Werror -lm -Os -mcall-prologues -fshort-enums -ffunction-sections -fdata-sections -MMD -MP -MT build/volume.o -MF build/./volume.d -mmcu=atmega8 -DF_CPU=8000000 -D_PIN1 -D_TEA5767 -D_RDA580X -D_TUX032 -c -o build/volume.o volume.c


Мы не ищем легких путей :)))
Просто раньше компилировал только через гуи в WinAvr, и пока не разобрался в консольных командах avr-gcc.

viiv писал(а):Как временная мера - попробуйте, путь в котором лежат бинарники для avr указать самым первым в переменной PATH (чтобы avr-овский as находился раньше, чем as-хоста (обычно лежит /usr/bin)). По хорошему - надо собрать gcc чтобы вызывался свой-родной кросс-ассемблер (с полным путем).

Ок, сейчас проверю, получится ли.

Re: Нескольно простых вопросов о программировании AVR на Си.

Пт мар 24, 2017 18:13:08

Возможно, в случае Makefile поможет AS=avr-as. Но не уверен.

Re: Нескольно простых вопросов о программировании AVR на Си.

Сб мар 25, 2017 05:54:54

Нет, ничего не вышло :(
Нашел багрепорты Suse с этой же проблемой: начиная с версий 4.19.x, компилятор упорно использует as, но на этот баг почему-то дружно забили и в репозитории продолжают выкладываться заведомо кривые пакеты (старая добрая традиция OpenSuse).
Вроде несколько пользователей пересобирали rpm с правильными путями к avr-as, буду искать.

Upd.
Решил проблему дешево и сердито :)) На время компиляции зашел в /usr/bin и переименовал as в as_old, а avr-as в as - прошивка собралась! :)) Это, конечно, не дело так каждый раз переименовывать, но хоть как-то добился нужного результата.

Re: Нескольно простых вопросов о программировании AVR на Си.

Сб мар 25, 2017 08:24:04

А попытка прописать переменную окружения AS=avr-as тоже не помогла?

Re: Нескольно простых вопросов о программировании AVR на Си.

Сб мар 25, 2017 10:10:14

Нет. Компилятор эту строку даже не заметил.

Помогло другое: в папке /usr/avr/bin/ лежат ссылки на правильные файлы, там файл as ссылается на нужный мне avr-as. В строку вызова avr-gcc дописал новый путь для поиска: -B /usr/avr/bin/ - и компиляция прошла!

В случае с Makefile'ом:
Код:
CC       = avr-gcc -B /usr/avr/bin/

Как я понимаю, этот путь надо бы добавить где-то в настройках системы.

Добавлено after 1 hour 19 minutes 10 seconds:
Ну вот и разобрался. Нашел такую штуку, что при создании в домашнем каталоге папки с именем bin этот путь автоматически добавляется в пути поиска программ, причем ставится он выше /usr/bin/
Так что просто создал эту папку, в ней создал симлинк as на файл /usr/bin/avr-as, и теперь все компилируется без лишней мороки :))

Re: Нескольно простых вопросов о программировании AVR на Си.

Сб мар 25, 2017 10:12:45

говорил же, что проблема в путях...

Re: Нескольно простых вопросов о программировании AVR на Си.

Сб мар 25, 2017 11:28:07

Да, в путях. Просто надеялся найти в репах пакеты, где компилятор работал бы "из коробки", но все связанное с avr в Suse требует доработки напильником.
Всем спасибо за подсказки :beer:

Re: Нескольно простых вопросов о программировании AVR на Си.

Сб апр 08, 2017 22:25:44

Помогите пожалуйста разобраться с ошибкой "multiple definition" в WinAvr. Дело в том что у меня в файле main.h есть глобальные переменные, которые используются в нескольких сишных файлах и поэтому я подключаю этот main.h в этих файлах. Вроде же это логично? И на этапе линковки происходит эта ошибка.
Если main.h не подключить хотя бы в одном файле, где используются переменные с него, то естественно ругается компилятор что не определена переменная в таком то файле.
Директива
#ifndef MAIN_H
#define MAIN_H
//код
#endif
в файле main.h стоит, но это не помогает избежать множественного определения
Видимо я еще слишком не опытный и что то делаю не так, буду благодарен за помощь.
А пока покопаюсь в чужих исходниках, может докопаюсь до истины.

Re: Нескольно простых вопросов о программировании AVR на Си.

Сб апр 08, 2017 22:47:44

hosturik писал(а):---- main.h
Код:
#ifndef MAIN_H
#define MAIN_H
extern int isTheWorldOnFire;
#endif


---- main.c

Код:
int isTheWorldOnFire = 0;

int main(int /*argc*/, char** /*argv*/) {

   forkTrumpAITask();

   while (!isTheWorldOnFire)
      drinkYetAnotherBottleOfBeerHandler();

   abort();

   return 34782567453;  /* es ist shon egal, kein Schwein kann diese Zeile erreichen */
}


---- tmp.c

Код:
void redButtonHandler() {

  if (!isTheWorldOnFire) {
    for (int i = 0; i < 59; i++)
       startYetAnotherTomahawk(i);
    isTheWorldOnFire = 1;
  }
}



как "полюбля́ют говоря́ть" на CRI "слово дня - extern". Сей модификатор намекает, что переменная isTheWorldOnFire "где-то там" определена. Без него переменная isTheWorldOnFire определена здесь и сейчас - т.е. в каждом отдельно компилируемом файле. Сводя подобные продукты компиляции в единую программку, линкер понятным делом ругается на множество isTheWorldOnFire. Поэтому определяем isTheWorldOnFire только в main.c (или кому как нравится) - а в остальных файлах на него ссылаемся помогая себе чудесным extern-ом. Amen ....

Re: Нескольно простых вопросов о программировании AVR на Си.

Вс апр 09, 2017 00:56:37

Siarzhuk, Спасибо большое буду пробовать, но что-то пока не получается.
Если я правильно понял, достаточно написать в заголовочном файле "extern имя переменной", объявить эту переменную в одном си файле (кстати есть ли разница в каком?) и эта переменная будет видна во всех си файлах и при этом заголовочный файл не нужно включать в сишные файлы? Достаточно один раз его включить.

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

вот так у меня не сработает
Спойлер
Код:
///////////////////
main.h
///////////////////
#ifndef MAIN_H
#define MAIN_H

//глобальные переменные                                    
extern volatile unsigned char power;

#endif
Код:
///////////////////
main.c
///////////////////
#include "main.h"
                  
volatile unsigned char power = 0;

int main( void )
{
   
  while(1)
   {
   abc(аргумент 1, аргумент 2);
   power // какое то действие
   }
}
Код:
//////////////////
menu.h
///////////////////
#ifndef MAIN_H
#define MAIN_H

прототип функции
void abc(unsigned long int a, unsigned char b);

#endif
Код:
//////////////////////
menu.c
//////////////////////
#include "menu.h"

void abc(unsigned long int a, unsigned char b)
{
   //какой-то код
   
   if(!power)
   {
   //что-то делаем
   power = 1;
   }
   
}

//ошибка
menu.c:5: error: 'power' undeclared (first use in this function)

По изучал чужие исходники и еще больше запутался. В некоторых из них один и тот же h файл, который в проекте, включается во все сишные файлы и при этом компилируется без проблем, нет ошибки линковщика - multiple definition (множественное определение). Интересно как это? Почему у меня тогда ругается если так же делаю?

Re: Нескольно простых вопросов о программировании AVR на Си.

Вс апр 09, 2017 04:09:33

hosturik писал(а):у меня в файле main.h есть глобальные переменные, которые используются в нескольких сишных файлах и поэтому я подключаю этот main.h в этих файлах. Вроде же это логично?
Нет. Поскольку каждый .c файл компилируется отдельно, то при таком подходе в каждом полученном .o файле будет копия этой переменной. А уже потом линкер при совмещении .o файлов в .elf выдаст ошибку "multiple definition". И трюк с #ifndef MAIN_H / #define MAIN_H / #endif тут не поможет.

Так что, как уже подсказали, нужно использовать модификатор extern. Возможно два равноценных варианта:

1) В одном .c файле объявить переменную как обычно, в других с extern. Неудобство в том, что в каждом из новых .c файлов, которым нужна эта переменная, придётся делать это объявление.

2) Обычно код оформляется в виде библиотек - парах файлов вроде module.c/module.h. Тогда в module.c переменная объявляется как обычно, а в module.h с extern, и тем самым она становится видимой во всех .c файлах, которые инклюдят этот хидер.

hosturik писал(а):А пока покопаюсь в чужих исходниках, может докопаюсь до истины.
Живой пример из одного моего проекта. Переменная tuner для доступа к параметрам тюнера определена в tuner.c и объявлена в tuner.h с модификатором extern. Любой другой файл просто её использует.

Ещё один возможный подход - использование функций-геттеров (ну и сеттеров при необходимости). Т.е. в tuner.c было бы что-то вроде:
Код:
static Tuner_type tuner;

Tuner_type getTuner(void)
{
    return tuner;
}

А в tuner.h вместо extern быо бы просто интерфейс функции
Код:
Tuner_type getTuner(void);

В нужном месте кода вместо прямого выхова глобальной переменной tuner использовалась бы локальная
Код:
Tuner_type tuner = getTuner();

Ну а дальше - как обычно.

Такой подход в больших проектах более правильный, т.к. глобальные переменные - это не очень безопасно. Но в проектах на МК часто (не всегда) глобальные переменные дают небольшой выигрыш в размере кода.

Re: Нескольно простых вопросов о программировании AVR на Си.

Вс апр 09, 2017 08:28:50

hosturik писал(а):[...] и эта переменная будет видна во всех си файлах и при этом заголовочный файл не нужно включать в сишные файлы?

Как это работает: 1. Препроцессор -> 2. Компилятор -> 3. Линкер Первый собирает из одного .c и всех .h на которые тот прямо либо косвенно (из включаемых .h) ссылается и комбинирует огромнейший [как правило] .с файл и отдаёт его на компиляцию. Это делается отдельно для каждого .с файла в проекте - поэтому подключать .h нужно в каждый .с где требуется знание об этой переменной. И лишь линкер собирает откомпилированные обьекты воедино - и тогда наступает Момент Истины - либо а) дубликаты переменных, либо б) одна переменная и ссылки на неё из других файлов, либо, что тоже не исключено, ц) одни только ссылки на несуществуюшую переменную.

Re: Нескольно простых вопросов о программировании AVR на Си.

Вс апр 09, 2017 10:33:09

Всем большое спасибо. Все получилось.

Re: Нескольно простых вопросов о программировании AVR на Си.

Чт июн 29, 2017 14:39:04

Господа, подскажите почему не работает код
Задача: по внешнему прерыванию INT0 изменяем значение переменной reg. В зависимости от состояния reg включается разный режим работы светодиода.
AVR Studio компилирует без ошибок, но ничего не работает в Proteus :(

Вот код:

Код:
#include <avr/io.h> //Подключаем библиотеку AVR
#include <avr/iotn2313.h> //Подключаем библиотеку ATtiny2313
#include <avr/interrupt.h> //Подключаем библиотеку прерываний

//Глобальные переменные сюда:
unsigned char reg=0; //Переменная reg - режим

//Обработка прерывания по спаду напряжения на INT0
ISR(INT0_vect)
{
reg++; //при нажатии на кнопку Увеличиваем значение переменной reg на 1
if (reg==4) reg=0; //Если досчитали до 4, то reg=0
}

void INTinit()
{
GIMSK=(1<<6); //Разрешаем прерывание INT0
MCUCR=(1<<0)|(1<<1); //Прерывыание по ниспадающему форонту (с 1 на 0); ISC01=1, ISC00=1
}

int main (void)
{
DDRB=(1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7); //Порт В на ВЫХод

PORTD=(1<<2); //Порт PD2 Подтягивающий резистор ВКлючен

INTinit();   // вызываем функцию инициализации прерываний
sei();   //Глобальное разрешение прерываний

while (1)
{
if (reg==1) PORTB=(1<<0); //Если reg досчитал до 1, то на ножке PD2 выставляем высокий уровень
};
}


Что я делаю не так?!

Re: Нескольно простых вопросов о программировании AVR на Си.

Чт июн 29, 2017 14:45:43

Уж сколько раз твердили миру... volatile.
Ну и антидребезга нет никакого. Для Proteus не важно, но в жизни при нажатии на кнопку прерываний до десятка будет за раз.
В коде последний комментарий вообще не в тему.
Итогом выполнения программы вижу постоянно находящийся в единичном состоянии PB0, веди ничто его в ноль в принципе не уводит.

Re: Нескольно простых вопросов о программировании AVR на Си.

Чт июн 29, 2017 15:09:33

Уж сколько раз твердили миру... volatile.
Ну и антидребезга нет никакого. Для Proteus не важно, но в жизни при нажатии на кнопку прерываний до десятка будет за раз.

Спасибо!!! Все заработало!
Как же все было не сложно...

Антидребезг обязательно добавлю!

Добавлено after 2 minutes 58 seconds:
В коде последний комментарий вообще не в тему.
Итогом выполнения программы вижу постоянно находящийся в единичном состоянии PB0, веди ничто его в ноль в принципе не уводит.

Это, так скажем, заготовка была с целью организовать выполнение прерывания по INT0, что с Вашей помощью и получилось
Теперь дальше дописывать режимы, добавлять антидребезг, так же понадобятся мне свои задержки с интервалами больше 15сек и тд...
А Вам еще раз Спасибо!
Ответить