Jump to content

    

Twin_by

Участник
  • Content Count

    32
  • Joined

  • Last visited

Posts posted by Twin_by


  1. Всем привет. Не стал создавать новую тему. У меня собственно тоже терморегулятор только на ATtiny88. И проблема с АЦП. Как видно на скриншоте не соответствуют значения. Это идет самое первое измерение после включения. Второе уже показывает правильно. Вопрос почему значение BuffADC после присвоения не равно значению ADC?

     

     

    read_adc.jpg

     

  2. Всем здравствуйте! Решил покрутить в руках FreeRTOS на ATmega324A. Нашел статью http://makesystem.net/?p=1363#.VrDha41a9qA . И когда дело дошло до сборки посыпали ошибки: undefined reference to pvPortMalloc. Посмотрел где идет определение, а там стандартная конструкция "если не определен, то определить". Или я что то не понимаю. В чем может быть проблема? Архив с проектом прилагается osrv_v2.zip

  3. Да, ваш файл я не посмотрел, поленился. Мне казалось очевидным, что вектора прибиты к своим адресам гвоздями и никто не догадается их сдвигать, запихнув перед ними какие-то данные..

    А я вот догадался, с вашей помощью кстати ))) Зато как красиво было ... Бинарник открываешь и в первой же строчке информация о версии прошивки. Но такой вариант оказался не рабочий.

     

    Огромное спасибо, что помогли замутить такую полезную штуку. В процессе я почерпнул много нового.

  4. Попробуйте тогда сделать так:

    *(.text)
    /*тут где-то еще должно быть*/  *(.text.*)
    KEEP(*(.fw_version))
    . = ALIGN(2);

    Помогло. Сейчас собирается без предупреждений. И создается два пустых байта после строки содержащей четное количество символов, и один байт если строка содержит не четное количество символов. Но была другая большая проблема. После прошивки микроконтроллера, он отказывался обрабатывать прерывания. Поэтому

    *(.fw_version)
    KEEP(*(.fw_version))
    . = ALIGN(2);

     

    перенес из начала секции .text чуть ниже после *(.vectors) KEEP(*(.vectors)). И вроде работает, прерывания и АЦП обрабатывает. Сейчас секция .text приняла следующий вид

    .text   :
     {
     *(.vectors)
    KEEP(*(.vectors))
    *(.fw_version)
    KEEP(*(.fw_version))
    . = ALIGN(2);
    /* For data that needs to reside in the lower 64k of progmem.  */
    *(.progmem.gcc*)
    *(.progmem*)
    . = ALIGN(2);
     __trampolines_start = .;
    /* The jump trampolines for the 16-bit limited relocs will reside here.  */
    *(.trampolines)
    *(.trampolines*)
     __trampolines_end = .;
    /* For future tablejump instruction arrays for 3 byte pc devices.
       We don't relax jump/call instructions within these sections.  */
    *(.jumptables)
    *(.jumptables*)
    /* For code that needs to reside in the lower 128k progmem.  */
    *(.lowtext)
    *(.lowtext*)
     __ctors_start = .;
     *(.ctors)
     __ctors_end = .;
     __dtors_start = .;
     *(.dtors)
     __dtors_end = .;
    KEEP(SORT(*)(.ctors))
    KEEP(SORT(*)(.dtors))
    /* From this point on, we don't bother about wether the insns are
       below or above the 16 bits boundary.  */
    *(.init0)  /* Start here after reset.  */
    KEEP (*(.init0))
    *(.init1)
    KEEP (*(.init1))
    *(.init2)  /* Clear __zero_reg__, set up stack pointer.  */
    KEEP (*(.init2))
    *(.init3)
    KEEP (*(.init3))
    *(.init4)  /* Initialize data and BSS.  */
    KEEP (*(.init4))
    *(.init5)
    KEEP (*(.init5))
    *(.init6)  /* C++ constructors.  */
    KEEP (*(.init6))
    *(.init7)
    KEEP (*(.init7))
    *(.init8)
    KEEP (*(.init8))
    *(.init9)  /* Call main().  */
    KEEP (*(.init9))
    *(.text)
    . = ALIGN(2);
    *(.text.*)
    . = ALIGN(2);
    *(.fini9)  /* _exit() starts here.  */
    KEEP (*(.fini9))
    *(.fini8)
    KEEP (*(.fini8))
    *(.fini7)
    KEEP (*(.fini7))
    *(.fini6)  /* C++ destructors.  */
    KEEP (*(.fini6))
    *(.fini5)
    KEEP (*(.fini5))
    *(.fini4)
    KEEP (*(.fini4))
    *(.fini3)
    KEEP (*(.fini3))
    *(.fini2)
    KEEP (*(.fini2))
    *(.fini1)
    KEEP (*(.fini1))
    *(.fini0)  /* Infinite loop after program termination.  */
    KEEP (*(.fini0))
     _etext = .;
     }  > text

  5. Это ошибка в линкере. По-хорошему надо писать сообщение об ошибке его авторам. Я на такое не нарывлася. Приложите весь проект в архиве.

     

    Я тут поигрался немного с форматом строчки, о точнее с содержимым строки name_fw[]. И заметил такую закономерность. Что если в строке четное количество символов, то проект соберется и выдаст Warning на вектора прерываний. А если в строке не четное количество символов, то все соберется без предупреждений.

  6. Тут имя секции .text не подходит. При линковке есть понятие "входные секции" - это которые компилятор создает в объектных файлах из вашего исходника и "выходные секции" - это в которые линкер складывает входные секции. То есть линкер берет входные секции и размещает их в выходные согласно скрипта. В выходном файле входных секций уже нет, в нем только выходные. Вы правильно разместили свою секцию внутри выходной секции .text. Но имя вашей секции надо было дать какое-то другое. Имя .text компилятор использует для кода.

     

    Минус лишний перед именем скрипта:-Wl,-T,version_fw.x

     

    А вы строчку KEEP(*(".init3")) из исходника убрали? Попробуйте так:

    В исходнике

    __attribute__ ((section (".fw_version")))
    const char name_fw[] = "xxxx";

    В скрипте линкера:

    *(.text)
    /*тут где-то еще должно быть*/  *(.text.*)
    KEEP(*(.fw_version))

     

    Вроде получилось. проект собрался. Но выдал 21 предупреждения:

     

    c:/program files/atmel/atmel toolchain/avr8 gcc/native/3.4.1061/avr8-gnu-toolchain/bin/../lib/gcc/avr/4.8.1/../../../../avr/lib/avr25/crttn88.o: In function `__vector_1':

    (.text+0x0)(0,0): warning: internal error: out of range error

     

    Все предупреждения касаются векторов прерывания.

     

     

  7. Поищите в комплекте вашего компилятора файлы с расширением .ld Посмотрите их содержимое, почитайте комментарии в них. выберите тот, который подходит к вашему процессору (можно было каким-то ключем линкера узнать, какой из них он использует по-умолчанию для вашего процессора, но я не помню какой именно ключ нужен. Вы можете найти его самостоятельно, почитав документацию на линкер Google->"gnu ld").

    Копируйте выбранный файл в папку проекта, дайте ему внятное имя и укажите линкеру использовать этот файл (в командную строку линкера добавьте -Wl,-T,имя_файла_скрипта).

    Что удалось узнать пока. Файлы ld Atmel Studio как таковые не использует. Она использует файлы в папке c:\WinAVR-20100110\avr\lib\ldscripts\avr2.* (avr2.* имеет поддержку процессора Attiny88 http://microsin.net/programming/avr/avr-gcc-options.html ) имеющие следующие описание:

     

    *.x script file is the default script

    *.xr script is for linking without relocation (-r flag)

    *.xu script is like .xr but *do* create constructors (-Ur flag)

    *.xn script is for linking with -n flag (mix text and data on same page).

    *.xbn script is for linking with -N flag (mix text and data on same page).

    Why are there five different linker scripts?

     

    Вот тут даются рекомендации по использованию своего скрипта AVR Libc Reference Manual Controlling the linker avr-ld. Там они предлагают заменить стандартный avr2.x на свой.

     

    Что я потом сделал. Я скопировал файл avr2.x в папку с проектом (там где Makefile, *.o, *.d), переименовал его в version_fw.x. Отредактировал его содержимое, добавив

    *(.text)
    KEEP(*(.text))

    строчка 75

     

    Потом в Atmel Studio main Properties -> Toolchain -> AVR/GNU Linker/Miscellaneous прописал -Wl,-T,-version_fw.x (или -version_fw). И при компилирование снова выдал ошибку: expected declaration specifiers or '...' before '*' token

     

    Прикрепил файл, расширение сменить на *.x

    version_fw.txt

  8. Так строку KEEP(*(".init3")) надо в скрипт лнкера вписывать, чтобы он знал, в какое именно место памяти надо вашу строку разместить. И не стоит использовать секции .initX - они уже используются стартапом.

    А какую секцию лучше использовать? Я кроме этих секций AVR GCC: секции памяти (что такое .text, .data, .bss, .noinit?) , других не знаю. И второй вопрос где и как отредактировать скрипт линкера или где можно прочитать про него? Так чтобы на доступном языке. Я с этими вещами первый раз столкнулся поэтому опыта в этом маловато.

  9. И тем самым отключить выбрасывание всех неиспользуемых переменных. Если бы у меня возникла необходимость оставить в памяти неиспользуемую константу, я бы поместил ее в отдельную секцию (__attribute__((section("имя_секции")))) и разместил бы эту секцию именно туда, где она мне нужна, запретив линкеру ее выкидывать ( KEEP(*(имя_секции)) )

     

    Что то не получается у меня реализовать ваш пример. Где я ошибся???

    const char name_fw[5] PROGMEM = "xxxx";
    __attribute__ ((section (".init3")));
    KEEP(*(".init3"));

  10. Вроде получилось. И получилось двумя способами: способ от Spider и от esaulenka. Единственное что общего у них, это что картинка флагов оптимизации (-Os) выглядела следующим образом

     

    -ffunction-sections (prepare functions for garbage collection) = SET

    -fdata-sections (prepare functions for data collection) = CLEAR (по умолчанию обычно SET)

    -fpack-struct (pack structure members together) = SET

    -fshort-enums (allocate only as many bytes needed by enaum types) = SET

    -mshort-calls (use rjamp/rcall (limited range) on > 8K devices) = CLEAR

     

    Поэтому, чтобы прописать версию прошивки (ПО) нужно было убрать флаг -fdata-sections и после инклудов написать:

     

    volatile const char fw_name[5] PROGMEM = "xxxx";

    ИЛИ

    const char name_fw[5] PROGMEM = "xxxx";
    __attribute__ ((used (name_fw)));

     

    Если есть еще какие замечания или комментарии с интересом выслушаю. Всем спасибо за помощь и советы. Esaulenka отдельное спасибо за ссылочку. Она еще мне пригодиться)

     

     

  11. Да что вы мучаетесь? напишите const volatile и будет вам счастье

     

    Volatile не помогает, при оптимизации строчка выкидывается

     

    Twin_by, а как Вы на работающем устройстве определяете версию залитой в него прошивки? Напишите команду чтения версии вот и будет обращение к строке и никаких volatile не понадобится.

     

    А на работающем никак не определить версию ПО. Этого и не нужно. Нужно после того как сняли модуль, прочитать микроконтроллер и с помощью hex-editor (XVI32) найти имя прошивки.

     

    Пишу в AVRStudio на ассемблере.

    Вот такая строка в кодовом сегменте:

    Version:
    .DB    __DAY__,__MONTH__,__YEAR__,__HOUR__,__MINUTE__,__SECOND__    ;версия ПО

    пропишет в память дату и время компиляции прошивки (удобнее,чем № версии).

    Если нет аналогичной возможности на Си, попробуйте сделать ассемблерную вставку.

     

    Попробовал ваш вариант. Но ругается ошибкой " Error 1 unknown pseudo-op: `.db' ". Пишу в AtmelStudio 6.2

    asm("Version: .DB DAY__,__MONTH__,__YEAR__,__HOUR__,__MINUTE__,__SECOND");

     

  12. Всем здравствуйте! Столкнулся с проблемой и никак не могу найти ее решение. Стоит задача прописывать в файле программы main.c имя версии. Я пробовал объявлять строку const char name_fw[] = "xxxx"; или const char name_fw[] PROGMEM = "xxxx"; Но при оптимизации эта строка вырезается т.к. в программе она нигде не используется. В итоге main.hex не содержит информации о версии ПО, и при считывании прошивки с микроконтроллера поди угадай какая версия туда была залита. Подскажите как можно решить эту проблему.

  13. Задаёте значения своим переменным:

    EEMEM eeprom_data_t eeprom =
    {
        .var1 = 33U,
        .var2 = 333.0f
    };

    Работаете с ними:

    В этом случае будет создан файл *.eep. Я так подозреваю

     

    Я уже об этом писал и объяснил зачем это нужно делать ВСЕГДА. Хотите я вам скину ссылку на avg-gcc 4.X.X, который вдруг стал располагать данные в EEPROM в обратном порядке (формально это не бага, т.к. стандарт ничего против такого поведения не имеет)?

    Да есть, такое. Когда первый раз с этим столкнулся долго не мог понять что у меня где в eeprom

     

     

  14. После сборки проекта вы получаете секцию с ЕЕПРОМ переменными в elf файле, после чего имеется возможность экспортировать эту секцию в eeprom-hex файл, а данные секции .text и иже с ним в flash-hex файл.

    Потом программатором зашиваете эти оба файла в микроконтроллер.

     

    Т.е все равно нужно использовать два файла для прошивки eeprom и flash?

  15. Например:

    #define EE_ADR_FLAG       ((void*)0x10)
    unsigned char    val = eeprom_read_byte(EE_ADR_FLAG);
    if(val == 0xFF)
    {    // инициализируем другие переменные
           // ................
           eeprom_write_byte(EE_ADR1,DEF_ADR1);
           eeprom_write_byte(EE_ADR2,DEF_ADR2);
           // ................
           //  изменяем флажок - все  записано
           eeprom_write_byte(EE_ADR_FLAG,0xAA);
    }
    
    // дальше считываем из EEPROM в рабочие переменные в оперативной памяти
    val1 = eeprom_read_byte(EE_ADR1);
    val2 = eeprom_read_byte(EE_ADR2);

     

    Если я правильно понял ваш код, то вы в нем сами присваиваете адрес ячейки в eeprom где будет хранится значение переменной? Т.е использовать директиву EEMEM (для автоматического присвоения адреса) не получится

  16. 2. По поводу работы с EEPROM. В начале программы определяется чиста ли EEPROM. Если чиста - то вызывается функция начальной инициализации. Далее - обычная работа программы. Таким образом не надо создавать отдельного файла для прошивки EEPROM - код программы сам ее инициализирует при первом запуске программы.

     

    Т.е вы предлагаете после начала функции main проверять пуста ли EEPROM. Если Да, то инициализировать переменную uint8_t var EEMEM = 15; Правильно я понимаю???

     

    Вот сейчас попробовал инициализировать переменную после начала функции main. И как то безрезультатно, не дает мне этого сделать. Позволяет инициализировать только перед функцией main где инициализируются глобальные переменные.

  17. Неправильно вы вопрос ставите.

    Всё зависит от того, какой утилитой вы пользуетесь для программирования (прошивки) микроконтроллера.

    Смотрите доку на утилиту в части поддерживаемых ей форматов входных файлов и делайте выводы...

    Одно могу сказать точно, что форматы с одним линейным адресным пространством

    вряд ли могут быть использованы для программирования сразу двух независимых типов памяти AVR ввиду их наложения.

     

    прошиваю я через Atmel Studio 6.2. В закладке Memories (Menu -> Tools -> Device Programming) указываю путь для elf файла и отдельно путь для eep файла. Встала задача для прошивки МК использовать только один файл (hex или elf). На форуме я видел что то похожее http://electronix.ru/forum/index.php?showt...73&hl=EEMEM . Там нужно что делать через линкеры, объектные файлы и тд. Но т.к у меня опыта еще маловато я не совсем понимаю о чем конкретно идет речь

  18. Здравствуйте!

    У меня такая вот ситуация. Подключаю библиотеку eeprom.h. Инициализирую переменную в eeprom памяти строчкой uint8_t var EEMEM = 15; . После сборки создается файл с расширением eep который заливается в МК отдельно. Интересен такой вопрос можно ли прошить flash и eeprom память avr используя только один файл hex или elf? Как это сделать: что добавить, что убрать? От библиотеки eeprom.h не хотелось бы отказываться (хорошая библиотека, удобная)

  19. Первый вопрос: вы отключили бит CKDIV8 ?

    Я фьюз биты не трогаю. Я в самом начале проги выставил 8МГц (#define F_CPU 8E6), а также в окне Processor View строка Frequency 8,000MHz. Да и где в Atmel Studio можно выставить фьюз биты???

  20. Столкнулся с непонятной мне проблемой. Есть проект выполненный на attiny88 в Atmel Studio 6. Прога должна выполнять мигание светодиодом раз в секунду, после 60 секунд должен загореться второй светодиод. И реализовать решил это двумя способами. Первый способ: проверка флага совпадения таймера каждую миллисекунду. Если было совпадение выполнить условие. Диод моргает, но гораздо чаще чем раз секунду. Второй способ это через прерывание: программа переходит к обработке прерывания, но диод моргает гораздо медленнее. Я прикрепил архив с проектом в Студии и схемой в Протеусе. project_1.rar

  21. Я за шпаргалки. Сначала ими активно пользуешься, а со временем запоминаются. Правила очень нужная и правильная вещь. Например выполняешь работу, все понятно, все идет гладко. А доходит дело до проверки того, что получилось, так всплывают ошибки

  22. Советую ещё почить FAQ. Ссылка на него есть в теме: "Найди ответ на свой вопрос". А также, отдельная ветка в форуме с одноимённым названием.

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

    Что касается шпаргалки - в общих чертах её неплохо иметь перед глазами, пока действия не отработаются до автоматизма.

    Я подумаю, может этот вопрос стоит добавить в ФАК.

     

    Так может я могу помочь как то в составлении? И практика заодно будет

     

  23. Всем доброго времени суток. Решил я потихоньку осваивать Altium. Скачал книгу Сабунина, просмотрел видеоуроки от BSVI.RU, просмотрел другие источники. . И чтобы каждый раз не заглядывать в источники, составил себе такую шпаргалку (см. ниже). В итоге получилось развести простую плату. Но она получилась с ошибками. Ошибки в основном связаны с сеткой (при создании УГО и схемы использовались разные сетки), и совмещением моделей. Теперь у меня возник вопрос, кто нибудь составлял такие алгоритмы-шпаргалки как у меня? Если да, то могли бы поделится какой нибудь информацией

     

    Шпаргалка

    1. Создание библиотек УГО

    File > New > Library > Shematic library

    2. Настройка рабочего пространства (Work Space)

    Tools > Document Options

    3. Этапы создания компонета

    3.1 Установка выводов

    3.2 Рисование графики символа

    3.3 Установка атрибутов

    4. Создание посадочного места (Footprint)

    File > New > Library > PCB Library

    5. Настройка рабочего пространства

    Tools > Document Options

    6 Этапы создания "футпринта"

    6.1 Установка контактных площадок

    6.2 Разработка графического изображения корпуса

    7. Подключение 3D модели в формате STEP

    7.1 Выполнить команду Place > 3D Body

    7.2 В появившимся окне выбираем Generic STEP Model и нажимаем кнопку Embed STEP Model.

    7.3 Далее выбираем файл модели и совмещаем ее с контактыми площадками (в режиме 2D (клавиша 2, клавиша 3 - режим 3D)). После чего жмем Cansel.

  24. "Крутятся" не контактные площадки, а резистор.

    Есть горячие клавиши, но для начала проще зайдите в свойства 3D тела и в низу в таблице указать нужный поворот относительно одной или нескольких из трех осей

    Спасибо за подсказку. Повернул