Проблема компиляции DigiSpark AT Tiny85?

Друг попросил меня найти проблему с компиляцией для его DigiSpark НА плате Tiny85. Мы пытаемся составить скетч отсюда: https://forum.arduino.cc/index.php?topic=314773.0

Но не повезло - что-то смешалось в заголовках или конфигурации, и я не знаю, что именно.

Этот ISR не компилируется:

ISR(TIMER1_OVF_vect) { //переполнение timer1

Сначала были некоторые ошибки, такие как TCR1 = 0; не определено в этом скетче, затем после игры с #define __ AVR_ATtiny85__, #undef _AVR_IOXXX_H_ и замены avr/io.h на iotn85.h пришли ошибки, такие как множественное определение __vector_x (?). Закомментируйте эту строку:
//attachInterrupt(0,zeroCrossingInterrupt, ПАДЕНИЕ)
помогло, но теперь даже это работает, а ИСР-нет.

Я знаю, что там много тайников и вы не видите, что происходит за занавесками, но я еще совсем потерялся...

Может быть, есть также проблема, у меня есть несколько установок в разных dirs, но я не знаю, как очистить старые (1.6.5-r2), и в конце концов оба работают одинаково, моя последняя свежая установка-1.8.9.

Есть ли у кого-нибудь опыт работы с демо-скетчом или какой-нибудь рабочий демо-скетч, использующий как compare match, так и overflow ISR ?

Обновлено
Информация о настройке
Эта плата выбрала (...\AppData\Roaming\Arduino15\packages\digistump\hardware\avr\1.6.7\boards.txt):

digispark-tiny.name=Digispark (Default - 16.5mhz)
digispark-tiny.upload.using=micronucleusprog
digispark-tiny.upload.protocol=usb
digispark-tiny.upload.tool=micronucleus
digispark-tiny.upload.maximum_size=6012
digispark-tiny.build.mcu=attiny85
digispark-tiny.build.f_cpu=16500000L
digispark-tiny.build.board=AVR_DIGISPARK
digispark-tiny.build.core=tiny
digispark-tiny.build.variant=digispark
digispark-tiny.upload.wait_for_upload_port = false
digispark-tiny.upload.use_1200bps_touch = false
digispark-tiny.upload.disable_flushing = false

И они доступны:

(...\AppData\Roaming\Arduino15\package_digistump_index.json)
...
"boards": [
  {
    "name": "Digispark (Default - 16.5mhz)"
  },
  {
    "name": "Digispark Pro (Default 16 Mhz)"
  },
  {
    "name": "Digispark Pro (16 Mhz) (32 byte buffer)"
  },
  {
    "name": "Digispark Pro (16 Mhz) (64 byte buffer)"
  },
  {
    "name": "Digispark (16mhz - No USB)"
  },
  {
    "name": "Digispark (8mhz - No USB)"
  },
  {
    "name": "Digispark (1mhz - No USB)"
  }
],
...

Правка 2
Новая попытка установки на W10
Еще несколько ссылок - 2-е руководство здесь:
https://www.electronicshub.org/getting-started-with-attiny85/

http://digistump.com/package_digistump_index.json
должны быть переведены на
https://raw.githubusercontent.com/digistump/arduino-boards-index/master/package_digistump_index.json

https://downloads.arduino.cc/arduino-1.8.9-windows.zip
W10
При установке отображается ошибка загрузки (тайм-аут?):
http://downloads.arduino.cc/tools/avr-gcc-4.8.1-arduino5-i686-mingw32.zip

Скачал вручную (там был пустой файл с таким именем):
...\AppData\Local\Arduino15\staging\packages\
avr-gcc-4.8.1-arduino5-i686-mingw32.zip

...\AppData\Local\Temp\arduino_build_139604\core\core.a(wiring.c.o): В функции `__vector_4':

...\AppData\Local\Arduino15\packages\digistump\hardware\avr\1.6.7\core\tiny/wiring.c:93: множественное определение `__vector_4'

...\AppData\Local\Temp\arduino_build_139604\sketch\sketch_jun28a.ino.cpp.o:...\arduino-1.8.9\SketchBook\sketch_jun28a/sketch_jun28a.ino:60: впервые определено здесь

collect2.exe: ошибка: ld вернул 1 статус выхода

статус выхода 1 Ошибка компиляции для платы Digispark (по умолчанию - 16,5 МГц).

...\AppData\Local\Arduino15\packages\digistump\hardware\avr\1.6.7\core\tiny\core_build_options.h (не нашел этот файл в arduino dir):

/*=============================================================================
  Build options for the ATtiny85 processor
=============================================================================*/

#if defined( __AVR_ATtiny25__ ) || defined( __AVR_ATtiny45__ ) || defined( __AVR_ATtiny85__ )
#define __AVR_ATtinyX5__
#endif

#if defined( __AVR_ATtinyX5__ )

/*
  For various reasons, Timer 1 is a better choice for the millis timer on the
  '85 processor.
*/
#define TIMER_TO_USE_FOR_MILLIS                   1

, 👍0

Обсуждение

Btw сделал лучшее сжатие и ускорение шрифтов Adafruit (примерно на 1/2 лучше, чем LZW) и C++ .Net simulator for old AT Mega project setup если кому интересно (он компилирует код Arduino напрямую, но мало файлов издевается и работает не во всех версиях - движок "черной магии" часто меняется., @Tom

Код с сайта кажется нормальным. Из сообщения об ошибке кажется, что вы не выбираете правильный тип платы в Arduino IDE. Поскольку ATtiny85 нет в стандартной библиотеке ядра: Какое ядро для ATtiny вы установили?, @chrisl

Он прислал мне ссылку https://www.instructables.com/id/Digispark-DIY-The-smallest-USB-Arduino/?%EF%BB%BF как настроить, думал, что я использовал то же самое, но помню, что я выбрал по умолчанию 16,5 МГц - может быть, из руководства с другой страницы, и теперь я вижу, что там упоминается Крошечное ядро ?? Проверю и это позже - не уверен, что был такой вариант. Не устанавливал драйверы, так как у меня нет модуля, и в этом zip-файле не было ничего связанного., @Tom

Больше информации добавлено к вопросу, проверено все платы, Tiny85 упомянул также @all 3 non-pro версии., @Tom

Пожалуйста, загляните в файл "arduino folder/packages/digistump/hardware/avr/1.6.7/core/tiny/core_build_options.h". Какое число используется для #define TIMER_TO_USE_FOR_MILLIS?, @chrisl

Не уверен, что в файле выбран правильный раздел, но в теории 1 есть только 0/1 для 3 разных групп процессоров (информация от 1-й установки сейчас)., @Tom


3 ответа


Лучший ответ:

1

Проблема заключается в следующем:

Ядро digispark уже реализует ISR TIMER1_OVF_vect (прерывание переполнения Timer1). Поскольку у вас есть 1 для #define TIMER_TO_USE_FOR_MILLIS, Timer1 будет использоваться для подсчета значения millis() в фоновом режиме. Для этого необходимо прерывание переполнения таймера 1.

Код, который вы скопировали с этого сайта, не предполагает, что вы можете использовать ядро, которое уже реализует прерывания. Он написан для общего ATtiny85, а не специально для версии Digispark.

Что вы можете сделать, чтобы решить эту проблему:

  • Вы можете использовать Timer0 для своего кода, сохраняя ядро Digispark нетронутым. Вы можете изменить все регистры с Timer1 на Timer0 (заменив 1 на 0). Кроме того, вам нужно заменить TCR1 на TCR0B, потому что для Timer0 это регистр, который устанавливает прескалер (и отключает таймер, если в него записан ноль). Также нужно учитывать, что Timer0 имеет другие настройки прескалера. Таким образом, строка TCR1 = B00001011; в zeroCrossingInterrupt() должна быть изменена на TCR0B = B00000101;. Это установит прескалер на 1024, как упоминалось в комментарии. Полученный код отлично компилируется для меня с ядром digispark (хотя я не тестировал его функциональность).

  • Вы можете настроить ядро Digispark на использование Timer0 для millis(), изменив определение TIMER_TO_USE_FOR_MILLIS в разделе Attiny85 файла arduino_folder/packages/digistump/hardware/avr/1.6.7/core/tiny/core_build_options.h на значение 0 вместо 1. Если вы сделаете это, исходный скетч будет скомпилирован нормально. Хотя в комментарии перед этим build options говорится, что Timer1 лучше для millis() "по разным причинам", что не очень конкретно. Вы можете попробовать, если это работает хорошо для вас.

  • Вы можете использовать другое ядро Attiny. Хотя вам, возможно, придется изменить его, чтобы приспособиться к необычной тактовой частоте fo 16,5 МГц (большинство ядер, которые я видел, имеют 16, 8 и 1 МГц). Это может быть так же просто, как изменить значение определенной тактовой частоты в файлах ядер, но я в этом не уверен.

,

Отлично ! Попробую, надеюсь и он поймет это как непрофессиональный программист и примет ваш ответ. Вы можете научить, как бороться с этой безумной системой 4 чайников ;-) Вы знаете, что простые вещи часто запутывают их..., @Tom

Кстати, если вам нужно будет уменьшить размер шрифтов GFX в два раза и ускорить печать или скомпилировать и запустить код Arduino + LCD на ПК, проверьте, что мои сопровождающие Github - lib защищаются от улучшений., @Tom

Когда я изменил значение millis с 1 на 0, ошибка компиляции исчезла, но программа не загрузилась должным образом. Я попытался загрузить простой blink blink sketch, он больше не может загружаться. Кажется, он больше не общается ! Во всяком случае, это, вероятно, "особенность", а не концепция плохой архитектуры..., @Tom

Загрузка не имеет ничего общего с компиляцией. Вы просто видите еще одну проблему. Я думаю, вы видите какую-то ошибку "программист не отвечает". Попробуйте погуглить, потому что на эту распространенную ошибку ответили несколько раз на этом сайте, @chrisl


1

Еще один простой вариант - переписать или удалить ISR в проводке.: ...\AppData\Local\Arduino15\packages \ digistump\hardware\avr\1.6.7\core\tiny\wiring.c

Например, после такого изменения удалось скомпилировать без проблем.

Самым простым решением было бы поместить этот код в мой ISR или вызвать его из другого.

#ifdef nothing
// bluebie изменил isr на noblock, чтобы он не испортил USB-библиотеки
ISR(MILLISTIMER_OVF_vect, ISR_NOBLOCK)
{
  // скопируйте их в локальные переменные, чтобы они могли храниться в регистрах
  // (изменчивые переменные должны считываться из памяти при каждом обращении)
  unsigned long m = millis_timer_millis;
  unsigned char f = millis_timer_fract;

/* rmv: The code below generates considerably less code (emtpy Sketch is 326 versus 304)...

  m += MILLIS_INC;
  f += FRACT_INC;
  if (f >= FRACT_MAX) {
    f -= FRACT_MAX;
    m += 1;
  }
...rmv */

  f += FRACT_INC;

  if (f >= FRACT_MAX) 
  {
    f -= FRACT_MAX;
    m = m + MILLIS_INC + 1;
  }
  else
  {
    m += MILLIS_INC;
  }

  millis_timer_fract = f;
  millis_timer_millis = m;
  millis_timer_overflow_count++;
}
#endif

Если вы переименуете wiring.c и перезапустите редактор, вы получите main.cpp:5: неопределенная ссылка на ошибку `init', есть это "дерьмовое" сердце arduino:

#include <WProgram.h>

int main(void)
{
    init();

    setup();

    for (;;)
        loop();

    return 0;
}

WProgram.h начинается с:

#ifndef WProgram_h
#define WProgram_h

#include <stdlib.h>
#include <string.h>
#include <math.h>

#include <avr/interrupt.h>

#include "core_build_options.h"
#include "core_pins.h"
#include "wiring.h"
...

И init этого ATtiny85 (внутренняя проводка.c) evn выглядит так:

void init(void)
{
  // калибровка часов
  // перекалибровать часы, если они были откалиброваны загрузчиком (например, micronucleus)
  #if F_CPU != 16500000L
    if (OSCCAL != read_factory_calibration()) {
      // отрегулируйте калибровку с 16,5 МГц до 16,0 МГц
      if (OSCCAL >= 128) {
        // может быть, 8 лучше? ну да ладно - в любом случае только около 0,3% 
        OSCCAL -= 7;
      } else {
        OSCCAL -= 5;
      }
    }
  #endif

  // TODO: определите, установлены ли предохранители на PLL, обычный внутренний генератор или внешний, и измените поведение в следующем разделе...
  #if F_CPU < 16000000L
    cli();
    CLKPR = 0b10000000;
    #if F_CPU == 8000000L
      CLKPR = 1; // div 2
    #elif F_CPU == 4000000L
      CLKPR = 2 // div 4
    #elif F_CPU == 2000000L
      CLKPR = 3; // div 8
    #elif F_CPU == 1000000L
      CLKPR = 4; // div 16
    #elif F_CPU == 500000L
      CLKPR = 5; // div 32 = 500khz
    #elif F_CPU == 250000L
      CLKPR = 6; // div 64 = 250 кГц
    #elif F_CPU == 125000L
      CLKPR = 7; // div 128 = 125 кГц тактовая частота процессора
    #else
      #warning "Cannot prescale chip to specified F_CPU speed"
    #endif
  #endif

  // это нужно вызвать перед setup (), иначе некоторые функции там не будут работать
  sei();

  // На случай, если загрузчик плохо оставил наш миллисекундный таймер
  #if defined( HAVE_BOOTLOADER ) && HAVE_BOOTLOADER
    MillisTimer_SetToPowerup();
  #endif

  // Используйте таймер Millis для быстрого ШИМ
  MillisTimer_SetWaveformGenerationMode( MillisTimer_(Fast_PWM_FF) );

  // Millis timer-это всегда часы процессора, разделенные на MillisTimer_Prescale_Value (64)
  MillisTimer_ClockSelect( MillisTimer_Prescale_Index );

  // Включить прерывание overlow (это базовый системный tic-toc для millis)
  MillisTimer_EnableOverflowInterrupt();

  // Инициализация таймера, используемого для тонального сигнала
  #if defined( INITIALIZE_SECONDARY_TIMERS ) && INITIALIZE_SECONDARY_TIMERS
    initToneTimerInternal();
  #endif

  // Инициализация АЦП
  #if defined( INITIALIZE_ANALOG_TO_DIGITAL_CONVERTER ) && INITIALIZE_ANALOG_TO_DIGITAL_CONVERTER
    ADC_PrescalerSelect( ADC_ARDUINO_PRESCALER );
    ADC_Enable();
  #endif
}
,

1

У меня была похожая проблема. Я удалил функции loop() и setup (), использовал классическую конструкцию C с функцией main (), и она начала работать. (Я думаю, что loop() и setup() позволяют использовать другие функции, такие как delay() - и он использует таймер - только моя гипотеза).

,