Перейти к содержанию
    

artemkad

Свой
  • Постов

    2 442
  • Зарегистрирован

  • Посещение

  • Победитель дней

    11

Сообщения, опубликованные artemkad


  1. Там суть в глобальных ресурсах - сохраняет-же он при входе в прерывание SREG, так чем EEAR и EEDR хуже?

    Поразительное упорство.

    :) Я знаю :)

    А регисты таймера, портов, UARTa, АЦП и прочей периферии компилятор не должен сохранять при входе в прерывание? Нет? А чем они лучше чем EEAR, EEDR?

    Тем, что с этой самой переферией приходится работать самому. Т.е. ее в программе рассматриваешь как набор этих самых регистров. Т.е. в программе таймер ты видишь не как таймер, а как регистры. А ЕЕPROM компилятор представляет как ПАМЯТЬ в которую можно писать и из которой можно читать. Использование "потрохов" для работы с EEPROM для корректной работы выглядит как-то странно.

    По сути похожий пример - при вызове библиотечной процедуры ей КАК-ТО передаются параметры и она что-то куда-то возвращает. А теперь представь, как-бы ты посмотрел на IAR, если-бы вызов процедуры в прерывании разрушал параметры вызова этой-же процедуры в основном цикле.

  2. Вчера весь день испытывал UART AtMega168 при работе с внутренним RC. Надо было дать банальный ответ - делать термокомпенсацию или "и так сойдет".

    Работала связка AtMega168 и SIM100S. Каждую секунду отправлялось тестовое сообщение.

    Тестировал в диапазоне температур 20-80 гр С. Диапазон напряжений - 3,6-4,4В. Частота RC - 8МГц, скорость UART - 9600.

     

    Выводы - за 6 часов работы пары при +80 НИ ОДНОЙ ошибки обнаружено небыло. Частота, а следовательно и скорость передачи МК ушли по сравнению с исходным чуть меньше чем на 2% (1,8%). Существенных изменений при изменении питания не обнаружено (менее 0,1%). Тобишь, до ошибочной величины ошибки в пол бита (5%) еще о-го-го скока :) ...

    Вот теперь сижу и думаю - проветять при -40 или не стоит - вести азот целое дело :glare: . Тем более, что и +80 и -40 это уже за пределами рабочего диапазона SIM100S, что он и показал отказавшись связываться после +70 хоть UART продолжал работать...

     

    ЗЫ. Правда была одна малость на которой я возможно схалтурил - Мега у меня работала с двумя стоп-битами, а SIM100S с одним. Может это и не сильно важно, но....

  3. Судя по всему, никто из отвечавших здесь не заглянул сюда.

    Уже заглянул :blush: . Действительно нечто похожее уже обсуждали и в прикрепленном файле грабли были убраны.

    Что касается компилятора, то он и не должен строить предположения насчёт прерываний.

    Для него EEPROM и система прерываний - две разные сути. Если пользователю вдруг захотелось эти сути объединить в своей задаче (требованиях), то пусть он (пользователь) этим и займётся, причём тут компилятор.

    Там суть в глобальных ресурсах - сохраняет-же он при входе в прерывание SREG, так чем EEAR и EEDR хуже?

    Выдержка из атмеловского даташита: :1111493779:

    Caution: An interrupt between step 5 and step 6 will make the write cycle fail, since the

    EEPROM Master Write Enable will time-out. If an interrupt routine accessing the

    EEPROM is interrupting another EEPROM access, the EEAR or EEDR Register will be

    modified, causing the interrupted EEPROM access to fail. It is recommended to have

    the Global Interrupt Flag cleared during all the steps to avoid these problems.

    Тем более IAR-овцы должны были на эту выдержку обратить внимание :( .

  4. Не зная в какой момент должно прити второе? :blink: Еще раз - речь не о LIN и ей подобных проторолов в которых есть символы синхронизации...
    Я отвечал на Ваш пост #30.
    ;) Там было на что отвечать? Может на #23?
    И почему это не зная? Параметры канала связи известны, и я знаю, в каком интервале времени мне нужно ожидать переход.
    Параметры известны, не известен приходящий символ...
  5. Стартовый в начале старт-бита. Переход 1->0. Стоповый бит - это только минимальное гарантированное расстояние между двумя соседними байтами...
    Интересная трактовка.

    Если стартовый переход 1->0 гарантирован, то и переход 0->1 в течение одного символа, по-моему, также гарантирован. Иначе никак... :)

    Эти два события и можно использовать в качестве опорных.

    Не зная в какой момент должно прити второе? :blink: Еще раз - речь не о LIN и ей подобных проторолов в которых есть символы синхронизации...

  6. Гарантированный за время одного символа только ОДИН переход.
    Как это ОДИН? :blink: Где и в какую сторону?

    Стартовый в начале старт-бита. Переход 1->0. Стоповый бит - это только минимальное гарантированное расстояние между двумя соседними байтами...

  7. Как Вы это себе представляете особенно если учесть, что старт-бит имеет только один гарантированный фронт, а стоп-бит вообще ни одного :glare: ...
    Ну, два гарантированных перехода за время одной транзакции всё-таки имеются.

    :blink: Гарантированный за время одного символа только ОДИН переход. Расстояния между символами - не гарантированы...

  8. Вы сами руцями указываете ему, что процедура является обработчиком...

    Ну так напишите обертку и вручную используйте. Компилятор-то тут при чем?

    "Грабли" на то и грабли - мирный инструмент пока не получишь от него по носу... :a14: Я уже говорил - исправить не сложно, сложно заметить...

    ?? Ожидается готовность eeprom. Что значит при разрешенных прерываниях? Мы уже внутри обработчика.

    Именно так. Внутри обработчика (предворительно исключив собственную рекурсию если она могла быть) разрешается прерывание. Чего тут непонятного :blink: ?

    Опс. Еще и вложенные прерывания организовать там, где можно просто тупо взять данные из копии в ОЗУ. Тогда не удивительно, что "грабли" :-)

    Это не "грабли" - при вложении прерываний сразу ожидаешь неприятностей и особо обращаешь внимание на это место.

    Ну а по поводу "там, где можно просто тупо взять" - просто и тупо иногда обработка того прерывания и без ЕЕPROM занимает сотни милисекунд. Оставлять запрещенными прерывания на подобное время мне как-то влом :biggrin: .

  9. Под "качественным" я подразумевал такое, от которого конечный пользователь не будет плеваться. То есть, аппаратура должна гарантированно (в той степени, в какой это возможно) работать без глюков.
    Поддерживаю обеими руками :)
    В "мабилле" есть, но в "мабиллу" никто и не влазит. Речь о связи с нею...
    Ну, старт- и стоп- биты каждая транзакция имеет. Вот по ним и можно синхронизироваться...

    :blink: Как Вы это себе представляете особенно если учесть, что старт-бит имеет только один гарантированный фронт, а стоп-бит вообще ни одного :glare: ...
  10. Компилятор должен был запретить прерывания при всех обращениях в основном цикле... Как - это уже отдельная тема. У компилятора более чем один способ решить этот вопрос.

    Огласите хотя бы один способ.

    PUSH/POP-нуть глобальные временные регистры EEAR, EEDR...

    Он это должен сделать тогда и только тогда когда вызов идет из прерывания. Во всех остальных случаях это будут ненужные накладные расходы. Как компилятор определит, что вызов делается из прерывания?

    Вы сами руцями указываете ему, что процедура является обработчиком...

    Обращение к eeprom требует ожидания готовности eeprom, а ожидание чего-либо находясь в прерывании - ошибка алгоритма.

    Даже при разрешенных прерываниях? Даже если ожидаемое событие все равно глобально должно поменять весь алгоритм работы? :blink:

    ?? Ожидается готовность eeprom. Что значит при разрешенных прерываниях? Мы уже внутри обработчика.

    Именно так. Внутри обработчика (предворительно исключив собственную рекурсию если она могла быть) разрешается прерывание. Чего тут непонятного :blink: ?

  11. Компилятор должен был запретить прерывания при всех обращениях в основном цикле... Как - это уже отдельная тема. У компилятора более чем один способ решить этот вопрос.

    Огласите хотя бы один способ.

    PUSH/POP-нуть глобальные временные регистры EEAR, EEDR...

    Если уж вы решили извратиться и работать с eeprom в прерывании (что само по себе уже глюк, только алгоритма)

    Ну, не знал, что чтение в прерывании флагов сохраняемых в EEPROM в каком-то другом месте это глюк :cranky: ...

    Теперь знаете - вы сами на него напоролись. Для обхода приходится запрещать прерывания в основном цикле, хотя без этого можно было обойтись. Обращение к eeprom требует ожидания готовности eeprom, а ожидание чего-либо находясь в прерывании - ошибка алгоритма.

    Даже при разрешенных прерываниях? Даже если ожидаемое событие все равно глобально должно поменять весь алгоритм работы? :blink:

    TomaT абсолютно прав. Копии данных, которые могут потребоваться в прерывании надо держать в ОЗУ. И грабли сразу исчезнут.

    Исправить эти грабли не сложно - сложнее на них не наступить особенно когда о "такой малости" в доках ни слова...

  12. Какая версия IAR?

    Последняя не профи.

    Вопрос первый: Зачем запрещать прерывания если программа уже находится в прерывании?

    Из него плавно вытекает второй: как компилятор определит что в одном случае функция вызвана из прерывания и запрещать не нужно а в другом случае из фона и запрещать нужно?

    Компилятор должен был запретить прерывания при всех обращениях в основном цикле... Как - это уже отдельная тема. У компилятора более чем один способ решить этот вопрос.

    Если уж вы решили извратиться и работать с eeprom в прерывании (что само по себе уже глюк, только алгоритма)

    Ну, не знал, что чтение в прерывании флагов сохраняемых в EEPROM в каком-то другом месте это глюк :cranky: ...

     

    Предпочитаю работать с EEPROM вот так из основного цикла программы, когда знаю что, все прерывания запрещены и не что мне не помешает:

     

    void EEPROM_write(unsigned int adres,unsigned char data)

    {

    while(EECR & (1<<1));

    EEAR=adres;

    EEDR=data;

    EECR |= (1<<2);

    EECR |= (1<<1);

    }

     

    unsigned char EEPROM_read(unsigned int adres)

    {

    while(EECR & (1<<1));

    EEAR=adres;

    EECR |= (1<<0);

    return EEDR;

    }

    Вы не поверите - компилятор делает так-же :biggrin: ... Вот только представте, что произойдет если EEPROM_write было вызвано при не запрещенных прерываниях, а в прерывании вызвано EEPROM_read. И это самое прерывание попало между

    EEAR=adres; и EEDR=data;

    Результат ясен?

     

    Тоже самое когда без запрета прерывания будет вызван EEPROM_read. Только там последствия сразу не столь разрушительные....

  13. При чтении ЕЕPROM в прерывании нет сохранения регистров адреса/данных(EEAR EEDR). Или что то-же самое - не защищаются от прерываний участок с момента записи EEAR EEDR до собственно подачи комманды чтения/записи.

    Результат - при работе с ЕЕPROM в прерывании возможна ситация когда разрушаются адрес или данные в операции чтения/записи из основного цикла. В связи с редкостью подобного события возможен крайне трудноуловимый глюк :angry2: ...

  14. ...Насколько помню чатота RC во всем диапазоне температур и напряжений уплывает МАКСИМУМ на 5%(разность между крайними точками поверхности). Тобишь (т.к. и так "практически почти хватает") достаточно грубой коррекции частоты в нескольких точках T-U диапазона. Т.е. это не юстировка частоты - это коррекция при которой локальная ошибка в 0,5-1% (четверть ошибки по каждой из возмущающих параметров) более чем допустимы. Ну и можно допустить, что около коллиброванного значения наклоны кривых в разных чипах имеют достаточно высокую повторяемость.
    При качественном проектировании это нельзя допустить.

    Слово "качественное проектирование" как-то неуместно. Ежу понятно, что если можно использовать кварц, то кварц и используется. НО кварц это как минимум дополнительный элемент (площадь, ненадежность, цена) и кварц это задействованные лишние одна или две ноги (а ног всегда мало).

    То бишь "качественное проектирование" при использовании кварца может вылиться в использование более многоногого МК что очень часто от "плохо" до "недопустимо". Назвать такой выход "качественным" в ситуации когда такого размена можно избежать я НИКАК не могу.

    Кроме того, нельзя сбрасывать со счетов долговременную стабильность (старение) генератора.

    Не уверен, что этот параметр может повлиять настолько, да и стареют RC одновременно...

    Чтобы нормально спроектировать даже несложную систему, нужно быть уверенным в параметрах компонентов.

    Уверен я бываю только после недели собственноручных испытаний :glare: .

    Для Вас достаточно уверенности Atmel которая, заложив в доках точность коллибровки RC и его изменение от Vсс T и OSCCAL, ни в одном чипе не обмолвилась о нестабильности этого генератора из-за старения? Я думаю, что указанная нестабильность не выше нестабильности по причине Vсс и T....

    Коррекция же частоты по результатам измерения известных временнЫх интервалов мне кажется наиболее естественной.

    Для этого они должны быть известны и они должны быть. Для LIN протовола это просто, а вот при общении с каким нибудь GSM модулем(мобилкой) весьма проблематично

    Прочитайте посты #1 и #5 данной темы. А в "мабилле" тоже кварц имеется...

    В "мабилле" есть, но в "мабиллу" никто и не влазит. Речь о связи с нею....
  15. проще термодатчик поставить,снять зависимость внутреннего rc-генератора от температуры и менять

    OSCCAL.

    Неудобно по трём основным причинам:

    1. Нужен термодатчик;

    Да, это нужно. Правда его точность может быть никакая :) .

    2. Нужен датчик напряжения питания (RC-генератор "плывёт" также и с напряжением питания);
    С этим проблем нет - либо это напряжение "плывет" в пределах 10% (что меняет частоту на доли %) либо Мега меряет свое питание внутренним АЦП (через BANDGAP) даже без потери на это порта....

    3. Необходимо снимать зависимость частоты RC-генератора каждого прибора от обоих вышеуказанных параметров. Типовая зависимость не прокатит - гарантии в этом случае не обеспечивается.

    Насколько помню чатота RC во всем диапазоне температур и напряжений уплывает МАКСИМУМ на 5%(разность между крайними точками поверхности). Тобишь (т.к. и так "практически почти хватает") достаточно грубой коррекции частоты в нескольких точках T-U диапазона. Т.е. это не юстировка частоты - это коррекция при которой локальная ошибка в 0,5-1% (четверть ошибки по каждой из возмущающих параметров) более чем допустимы. Ну и можно допустить, что около коллиброванного значения наклоны кривых в разных чипах имеют достаточно высокую повторяемость.

    Кроме того, нельзя сбрасывать со счетов долговременную стабильность (старение) генератора.

    Не уверен, что этот параметр может повлиять настолько, да и стареют RC одновременно...

    Коррекция же частоты по результатам измерения известных временнЫх интервалов мне кажется наиболее естественной.

    Для этого они должны быть известны и они должны быть. Для LIN протовола это просто, а вот при общении с каким нибудь GSM модулем(мобилкой) весьма проблематично

  16. Точно - в другом месте ;) . А вставка лишнего nop-а перед вызываемой функцией благотворно влияет на карму Меги168 (она видать очень любит четные CALL-ы) поэтому она благополучно не замечает того другого ошибочного места.

    IAR-овцы тоже ошиблись когда патч на релиз выкладывали - у них всегда константные исполнимые вектора везде великолепно работали...

     

    "Доктор, не делайте из меня эйдиота" :) .

  17. SMD, 0603, максимум 3 класс сложности (на многослойку можно даже не расчитывать :a14: ), под автоматический односторонний монтаж на линии...

    А чего именно 3 класс?

    Потому как 2 класс с 0603 как-то плохо совместим ;)
    Что бы можно было в Киеве изготовить? Так у нас и боллее классные :biggrin: платы изготавливают.

    Вы мне еще многослойку с золочением контактов вместо банальной односторонки посоветуйте.... :tongue:

  18. Всвязи с непредвиденным увеличением объема разработок есть желание привлечь для разводки печатных плат стороннего специалиста.

    Работа разовая (а может и нет :glare: ) на 2-3 небольшие платы (в смысле места то-же не густо). SMD, 0603, максимум 3 класс сложности (на многослойку можно даже не расчитывать :a14: ), под автоматический односторонний монтаж на линии...

  19. И напоследок вопрос, который интересует меня:

    __root __flash const struct token token_table[]

    зачем в этой строке стоит "struct" ?

     

    Дык описываю массив структур типа token

    Там выше описана структура

    struct token

    {

    const char __flash *str;

    void (*fun)(void);

    };

    Иначе это было-бы описание простого типа (например через typedef) с именем token.

    По крайней мере так IAR не ругается :)

  20. Скомпилировал код версией 4.11А. NOP'ы повыкидывал.

    Как и ожидалось, структуры инициализируются правильно, указатели указывают, куда нужно.

     

    Наблюдая как этот код зависает в МК мне от его правильности как-то не легче :( ...

     

    void (*fun_OK_addr)();
    
    __root __flash const struct token token_table[] =
    {"\r\n",fun_VOID,
    "OK", fun_OK
    };
      0000000A: 0004
      0000000C: 0009; верно, байтовый адрес fun_VOID - 18
      0000000E: 0007
      00000010: 000A; верно, байтовый адрес fun_OK - 20
    
    
    fun_OK_addr = fun_VOID;
      00000018: E009                ldi     r16,#9
      0000001A: E010                ldi     r17,#0
      0000001C: EAE0                ldi     r30,#160
      0000001E: E0F0                ldi     r31,#0
      00000020: 8300                st      z,r16
      00000022: 8311                std     z+1,r17
    (*fun_OK_addr)();
      00000024: EAA0                ldi     r26,#160
      00000026: E0B0                ldi     r27,#0
      00000028: 91ED                ld      r30,x+
      0000002A: 91FC                ld      r31,x
      0000002C: 9509                icall
    
    
    fun_OK_addr = token_table[0].fun;
      0000002E: E0EC                ldi     r30,#12
      00000030: E0F0                ldi     r31,#0
      00000032: 9105                lpm     r16,z+
      00000034: 9114                lpm     r17,z
      00000036: EAE0                ldi     r30,#160
      00000038: E0F0                ldi     r31,#0
      0000003A: 8300                st      z,r16
      0000003C: 8311                std     z+1,r17
    (*fun_OK_addr)();
      0000003E: EAA0                ldi     r26,#160
      00000040: E0B0                ldi     r27,#0
      00000042: 91ED                ld      r30,x+
      00000044: 91FC                ld      r31,x
      00000046: 9509                icall
    
    
    
    (*token_table[0].fun)();
      00000048: E0EC                ldi     r30,#12
      0000004A: E0F0                ldi     r31,#0
      0000004C: 9105                lpm     r16,z+
      0000004E: 9114                lpm     r17,z
      00000050: 01F8                movw    r30,r16
      00000052: 9509                icall

    Ну предположим там был (*token_table[Response].fun)()

    Поэтому в настоящем коде вместо

    ldi константа

    было

    ldi r30, 0x02
    ldi r31, 0x02
    mov r16, r24
    ldi r17, 0
    lsl r16
    rol r17
    lsl r16
    rol r17
    add r30,r16
    adc r31,r17
    и далее те самые 
    lpm     r16,z+
    lpm     r17,z
    movw r26,r16
    movw r30,r26
    icall

     

    но это дела не меняет - если все адреса функций в таблице четные то программа не висла, если в разнобой - певый же нечетный чаще всего зависал... Причем больше всего бесило, что иногда и не зависал. Хотя сейчас я понимаю, что оптимизатор IARa мог просто удачно на тот момент перетасовать код.

     

    Лучший критерий - программа в МК это очень ярко показывает....

  21. Естественно есть прототипы описаные до констант - иначе компилятор выругается....

     

    По поводу & - .........

     

     

    Кстати, обращу внимание - это рабочий вариант. А вот если убрать nop из первой функции (длина которой станет 1 слово), то при вызове второй МК отправляется в "спячку" :( ...

    Собственно так и "спасаюсь" - все адреса функций в таблице нопами делаю четными. Но иногда ( когда IAR "с оптимизирует" очередную константу перед этим кодом) приходится увеличивать константы "загоняя" адрес первой функции в нужный диапазон....

     

    Естественно с оптимизацией тут уже почти никак :( .

    Вот если-бы можно было указать выравнивание кода процедур или явно указать их адреса....

  22. Примерно так:

    // Структура таблицы ключевых слов

    struct token

    {

    const char __flash *str;

    void (*fun)(void);

    };

     

    // Таблица ключевых слов и их обработчиков

    __root __flash const struct token token_table[] =

    {CR_LF,fun_VOID,

    OK, fun_OK,

     

    ..............................................................

     

    }

     

    void fun_VOID(void)

    {

    asm("nop"); // Лекарство от зависания :( !!!

    return;

    }

     

    /* Обработчик "OK" */

    void fun_OK(void)

    {

    if(error_cnt)

     

    error_cnt --;

    (*fun_OK_addr)(); // Запуск обработчика по указателю

    asm("nop"); // Лекарство от зависания :( !!!

    return;

    }

     

     

    ..........................................

    // а вот так вызывается в коде из таблицы....

    void (*p)(void);

    Response--;

    p = token_table[Response].fun;

    (*p)();

    // token_table[Response].fun(); - тоже самое, но так вроде стабильнее ;(

     

     

    .............................................

     

    К сожалению с кодом проблемы - надо перекомпилировать и много кода сюда писать....

  23. А шут его знает, вроде АВР :-) ... Адрес естественно в словах.

    Собственно патч по этому поводу у них на -про версию ВРОДИ-бы здесь:

    ftp://ftp.iar.se/WWWfiles/avr/PatchReadme_412b.html

    Так, что читайте "описание от производителей". Лично мне поймать условие когда 100% код виснет так и не удалось (не помог и асм полученного кода :( ).

     

    А вот что делать с -евал версией?

    Кстати, в 4,20 -евал этот баг все еще присутствует....

     

    Да, и еще любопытный вопрос - если в 4.20 EV баг все еще есть, где гарантия, что тот патч решает проблему в полной версии?

  24. ...и при чём тут nop'ы ?

    Да я ж говорю - код зависает. Насколько я понял зависит от адреса вызываемой функции. Если по четному, то вызывается нормально, а если по нечетному - то ИНОГДА зависает.

    Вот лишними nop-ами и приходится ровнять код вызываемых процедур (меняю одни, а подвисают другие....) - иначе не работает...

     

     

    А если учесть, что эта зараза константы втыкает перед кодом, то по мере развития проекта перетыкивать nop-ы приходится регулярно :-(

×
×
  • Создать...