artemkad
-
Постов
2 442 -
Зарегистрирован
-
Посещение
-
Победитель дней
11
Сообщения, опубликованные artemkad
-
-
Вчера весь день испытывал 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 с одним. Может это и не сильно важно, но....
-
Опубликовано · Изменено пользователем ArtemKAD · Пожаловаться
Судя по всему, никто из отвечавших здесь не заглянул сюда.Уже заглянул . Действительно нечто похожее уже обсуждали и в прикрепленном файле грабли были убраны.
Что касается компилятора, то он и не должен строить предположения насчёт прерываний.Для него 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-овцы должны были на эту выдержку обратить внимание :( .
-
;) Там было на что отвечать? Может на #23?
Я отвечал на Ваш пост #30.Не зная в какой момент должно прити второе? :blink: Еще раз - речь не о LIN и ей подобных проторолов в которых есть символы синхронизации...
Параметры известны, не известен приходящий символ...И почему это не зная? Параметры канала связи известны, и я знаю, в каком интервале времени мне нужно ожидать переход. -
Интересная трактовка.Стартовый в начале старт-бита. Переход 1->0. Стоповый бит - это только минимальное гарантированное расстояние между двумя соседними байтами...Если стартовый переход 1->0 гарантирован, то и переход 0->1 в течение одного символа, по-моему, также гарантирован. Иначе никак... :)
Эти два события и можно использовать в качестве опорных.
Не зная в какой момент должно прити второе? :blink: Еще раз - речь не о LIN и ей подобных проторолов в которых есть символы синхронизации...
-
Как это ОДИН? :blink: Где и в какую сторону?Гарантированный за время одного символа только ОДИН переход.Стартовый в начале старт-бита. Переход 1->0. Стоповый бит - это только минимальное гарантированное расстояние между двумя соседними байтами...
-
Ну, два гарантированных перехода за время одной транзакции всё-таки имеются.Как Вы это себе представляете особенно если учесть, что старт-бит имеет только один гарантированный фронт, а стоп-бит вообще ни одного :glare: ...:blink: Гарантированный за время одного символа только ОДИН переход. Расстояния между символами - не гарантированы...
-
"Грабли" на то и грабли - мирный инструмент пока не получишь от него по носу... :a14: Я уже говорил - исправить не сложно, сложно заметить...Вы сами руцями указываете ему, что процедура является обработчиком...
Ну так напишите обертку и вручную используйте. Компилятор-то тут при чем?
Это не "грабли" - при вложении прерываний сразу ожидаешь неприятностей и особо обращаешь внимание на это место.
Опс. Еще и вложенные прерывания организовать там, где можно просто тупо взять данные из копии в ОЗУ. Тогда не удивительно, что "грабли" :-)?? Ожидается готовность eeprom. Что значит при разрешенных прерываниях? Мы уже внутри обработчика.Именно так. Внутри обработчика (предворительно исключив собственную рекурсию если она могла быть) разрешается прерывание. Чего тут непонятного :blink: ?
Ну а по поводу "там, где можно просто тупо взять" - просто и тупо иногда обработка того прерывания и без ЕЕPROM занимает сотни милисекунд. Оставлять запрещенными прерывания на подобное время мне как-то влом .
-
Поддерживаю обеими руками :)Под "качественным" я подразумевал такое, от которого конечный пользователь не будет плеваться. То есть, аппаратура должна гарантированно (в той степени, в какой это возможно) работать без глюков.
:blink: Как Вы это себе представляете особенно если учесть, что старт-бит имеет только один гарантированный фронт, а стоп-бит вообще ни одного :glare: ...
Ну, старт- и стоп- биты каждая транзакция имеет. Вот по ним и можно синхронизироваться...В "мабилле" есть, но в "мабиллу" никто и не влазит. Речь о связи с нею... -
Он это должен сделать тогда и только тогда когда вызов идет из прерывания. Во всех остальных случаях это будут ненужные накладные расходы. Как компилятор определит, что вызов делается из прерывания?
Огласите хотя бы один способ.Компилятор должен был запретить прерывания при всех обращениях в основном цикле... Как - это уже отдельная тема. У компилятора более чем один способ решить этот вопрос.
PUSH/POP-нуть глобальные временные регистры EEAR, EEDR...
Вы сами руцями указываете ему, что процедура является обработчиком...
?? Ожидается готовность eeprom. Что значит при разрешенных прерываниях? Мы уже внутри обработчика.Обращение к eeprom требует ожидания готовности eeprom, а ожидание чего-либо находясь в прерывании - ошибка алгоритма.Даже при разрешенных прерываниях? Даже если ожидаемое событие все равно глобально должно поменять весь алгоритм работы? :blink:
Именно так. Внутри обработчика (предворительно исключив собственную рекурсию если она могла быть) разрешается прерывание. Чего тут непонятного :blink: ?
-
Огласите хотя бы один способ.Компилятор должен был запретить прерывания при всех обращениях в основном цикле... Как - это уже отдельная тема. У компилятора более чем один способ решить этот вопрос.
PUSH/POP-нуть глобальные временные регистры EEAR, EEDR...
Теперь знаете - вы сами на него напоролись. Для обхода приходится запрещать прерывания в основном цикле, хотя без этого можно было обойтись. Обращение к eeprom требует ожидания готовности eeprom, а ожидание чего-либо находясь в прерывании - ошибка алгоритма.Если уж вы решили извратиться и работать с eeprom в прерывании (что само по себе уже глюк, только алгоритма)Ну, не знал, что чтение в прерывании флагов сохраняемых в EEPROM в каком-то другом месте это глюк :cranky: ...
Даже при разрешенных прерываниях? Даже если ожидаемое событие все равно глобально должно поменять весь алгоритм работы? :blink:
TomaT абсолютно прав. Копии данных, которые могут потребоваться в прерывании надо держать в ОЗУ. И грабли сразу исчезнут.Исправить эти грабли не сложно - сложнее на них не наступить особенно когда о "такой малости" в доках ни слова...
-
Какая версия 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;
}
Вы не поверите - компилятор делает так-же ... Вот только представте, что произойдет если EEPROM_write было вызвано при не запрещенных прерываниях, а в прерывании вызвано EEPROM_read. И это самое прерывание попало между
EEAR=adres; и EEDR=data;
Результат ясен?
Тоже самое когда без запрета прерывания будет вызван EEPROM_read. Только там последствия сразу не столь разрушительные....
-
Опубликовано · Изменено пользователем ArtemKAD · Пожаловаться
При чтении ЕЕPROM в прерывании нет сохранения регистров адреса/данных(EEAR EEDR). Или что то-же самое - не защищаются от прерываний участок с момента записи EEAR EEDR до собственно подачи комманды чтения/записи.
Результат - при работе с ЕЕPROM в прерывании возможна ситация когда разрушаются адрес или данные в операции чтения/записи из основного цикла. В связи с редкостью подобного события возможен крайне трудноуловимый глюк :angry2: ...
-
Опубликовано · Изменено пользователем ArtemKAD · Пожаловаться
При качественном проектировании это нельзя допустить....Насколько помню чатота RC во всем диапазоне температур и напряжений уплывает МАКСИМУМ на 5%(разность между крайними точками поверхности). Тобишь (т.к. и так "практически почти хватает") достаточно грубой коррекции частоты в нескольких точках T-U диапазона. Т.е. это не юстировка частоты - это коррекция при которой локальная ошибка в 0,5-1% (четверть ошибки по каждой из возмущающих параметров) более чем допустимы. Ну и можно допустить, что около коллиброванного значения наклоны кривых в разных чипах имеют достаточно высокую повторяемость.Слово "качественное проектирование" как-то неуместно. Ежу понятно, что если можно использовать кварц, то кварц и используется. НО кварц это как минимум дополнительный элемент (площадь, ненадежность, цена) и кварц это задействованные лишние одна или две ноги (а ног всегда мало).
То бишь "качественное проектирование" при использовании кварца может вылиться в использование более многоногого МК что очень часто от "плохо" до "недопустимо". Назвать такой выход "качественным" в ситуации когда такого размена можно избежать я НИКАК не могу.
Чтобы нормально спроектировать даже несложную систему, нужно быть уверенным в параметрах компонентов.Кроме того, нельзя сбрасывать со счетов долговременную стабильность (старение) генератора.Не уверен, что этот параметр может повлиять настолько, да и стареют RC одновременно...
Уверен я бываю только после недели собственноручных испытаний :glare: .
Для Вас достаточно уверенности Atmel которая, заложив в доках точность коллибровки RC и его изменение от Vсс T и OSCCAL, ни в одном чипе не обмолвилась о нестабильности этого генератора из-за старения? Я думаю, что указанная нестабильность не выше нестабильности по причине Vсс и T....
В "мабилле" есть, но в "мабиллу" никто и не влазит. Речь о связи с нею....
Прочитайте посты #1 и #5 данной темы. А в "мабилле" тоже кварц имеется...Коррекция же частоты по результатам измерения известных временнЫх интервалов мне кажется наиболее естественной.Для этого они должны быть известны и они должны быть. Для LIN протовола это просто, а вот при общении с каким нибудь GSM модулем(мобилкой) весьма проблематично
-
Неудобно по трём основным причинам:проще термодатчик поставить,снять зависимость внутреннего rc-генератора от температуры и менятьOSCCAL.
1. Нужен термодатчик;
Да, это нужно. Правда его точность может быть никакая :) .
С этим проблем нет - либо это напряжение "плывет" в пределах 10% (что меняет частоту на доли %) либо Мега меряет свое питание внутренним АЦП (через BANDGAP) даже без потери на это порта....2. Нужен датчик напряжения питания (RC-генератор "плывёт" также и с напряжением питания);3. Необходимо снимать зависимость частоты RC-генератора каждого прибора от обоих вышеуказанных параметров. Типовая зависимость не прокатит - гарантии в этом случае не обеспечивается.Насколько помню чатота RC во всем диапазоне температур и напряжений уплывает МАКСИМУМ на 5%(разность между крайними точками поверхности). Тобишь (т.к. и так "практически почти хватает") достаточно грубой коррекции частоты в нескольких точках T-U диапазона. Т.е. это не юстировка частоты - это коррекция при которой локальная ошибка в 0,5-1% (четверть ошибки по каждой из возмущающих параметров) более чем допустимы. Ну и можно допустить, что около коллиброванного значения наклоны кривых в разных чипах имеют достаточно высокую повторяемость.
Кроме того, нельзя сбрасывать со счетов долговременную стабильность (старение) генератора.Не уверен, что этот параметр может повлиять настолько, да и стареют RC одновременно...
Коррекция же частоты по результатам измерения известных временнЫх интервалов мне кажется наиболее естественной.Для этого они должны быть известны и они должны быть. Для LIN протовола это просто, а вот при общении с каким нибудь GSM модулем(мобилкой) весьма проблематично
-
Точно - в другом месте ;) . А вставка лишнего nop-а перед вызываемой функцией благотворно влияет на карму Меги168 (она видать очень любит четные CALL-ы) поэтому она благополучно не замечает того другого ошибочного места.
IAR-овцы тоже ошиблись когда патч на релиз выкладывали - у них всегда константные исполнимые вектора везде великолепно работали...
"Доктор, не делайте из меня эйдиота" :) .
-
Потому как 2 класс с 0603 как-то плохо совместим ;)SMD, 0603, максимум 3 класс сложности (на многослойку можно даже не расчитывать :a14: ), под автоматический односторонний монтаж на линии...
А чего именно 3 класс?
Что бы можно было в Киеве изготовить? Так у нас и боллее классные платы изготавливают.Вы мне еще многослойку с золочением контактов вместо банальной односторонки посоветуйте.... :tongue:
-
Опубликовано · Изменено пользователем ArtemKAD · Пожаловаться
Всвязи с непредвиденным увеличением объема разработок есть желание привлечь для разводки печатных плат стороннего специалиста.
Работа разовая (а может и нет :glare: ) на 2-3 небольшие платы (в смысле места то-же не густо). SMD, 0603, максимум 3 класс сложности (на многослойку можно даже не расчитывать :a14: ), под автоматический односторонний монтаж на линии...
-
И напоследок вопрос, который интересует меня:
__root __flash const struct token token_table[]
зачем в этой строке стоит "struct" ?
Дык описываю массив структур типа token
Там выше описана структура
struct token
{
const char __flash *str;
void (*fun)(void);
};
Иначе это было-бы описание простого типа (например через typedef) с именем token.
По крайней мере так IAR не ругается :)
-
Скомпилировал код версией 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 мог просто удачно на тот момент перетасовать код.
Лучший критерий - программа в МК это очень ярко показывает....
-
Естественно есть прототипы описаные до констант - иначе компилятор выругается....
По поводу & - .........
Кстати, обращу внимание - это рабочий вариант. А вот если убрать nop из первой функции (длина которой станет 1 слово), то при вызове второй МК отправляется в "спячку" :( ...
Собственно так и "спасаюсь" - все адреса функций в таблице нопами делаю четными. Но иногда ( когда IAR "с оптимизирует" очередную константу перед этим кодом) приходится увеличивать константы "загоняя" адрес первой функции в нужный диапазон....
Естественно с оптимизацией тут уже почти никак :( .
Вот если-бы можно было указать выравнивание кода процедур или явно указать их адреса....
-
Примерно так:
// Структура таблицы ключевых слов
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(); - тоже самое, но так вроде стабильнее ;(
.............................................
К сожалению с кодом проблемы - надо перекомпилировать и много кода сюда писать....
-
А шут его знает, вроде АВР :-) ... Адрес естественно в словах.
Собственно патч по этому поводу у них на -про версию ВРОДИ-бы здесь:
ftp://ftp.iar.se/WWWfiles/avr/PatchReadme_412b.html
Так, что читайте "описание от производителей". Лично мне поймать условие когда 100% код виснет так и не удалось (не помог и асм полученного кода :( ).
А вот что делать с -евал версией?
Кстати, в 4,20 -евал этот баг все еще присутствует....
Да, и еще любопытный вопрос - если в 4.20 EV баг все еще есть, где гарантия, что тот патч решает проблему в полной версии?
-
Опубликовано · Изменено пользователем ArtemKAD · Пожаловаться
...и при чём тут nop'ы ?Да я ж говорю - код зависает. Насколько я понял зависит от адреса вызываемой функции. Если по четному, то вызывается нормально, а если по нечетному - то ИНОГДА зависает.
Вот лишними nop-ами и приходится ровнять код вызываемых процедур (меняю одни, а подвисают другие....) - иначе не работает...
А если учесть, что эта зараза константы втыкает перед кодом, то по мере развития проекта перетыкивать nop-ы приходится регулярно :-(
-
Может кто подскажет как бороться с зависанием полученного кода если в нем использованы указатели на функцию.
Бо шаманить с лишними nop-ами уже порядком надоело... :angry2:
Еще одни грабли от IAR AVR
в IAR
Опубликовано · Изменено пользователем ArtemKAD · Пожаловаться
:) Я знаю :)
Тем, что с этой самой переферией приходится работать самому. Т.е. ее в программе рассматриваешь как набор этих самых регистров. Т.е. в программе таймер ты видишь не как таймер, а как регистры. А ЕЕPROM компилятор представляет как ПАМЯТЬ в которую можно писать и из которой можно читать. Использование "потрохов" для работы с EEPROM для корректной работы выглядит как-то странно.
По сути похожий пример - при вызове библиотечной процедуры ей КАК-ТО передаются параметры и она что-то куда-то возвращает. А теперь представь, как-бы ты посмотрел на IAR, если-бы вызов процедуры в прерывании разрушал параметры вызова этой-же процедуры в основном цикле.