-
Постов
4 619 -
Зарегистрирован
-
Победитель дней
2
Сообщения, опубликованные Rst7
-
-
Ждем-с…
Судя по описанию, если все заявленные характеристики окажутся правдой, безраздельному господству ARM-ов, прежде всего в сфере мобильных устройств, придет конец.
Я себе уже IAR Embedded Workbench V2.10 for Atmel AVR32 поставил. :tongue:
Можно погонять на симуляторе.
А посмотри, плиз, как он делает загрузку непосредственного лонга в регистр (unsigned long i=0x56781234), как ARM (т.е. берет константу со смещением) или как PPC (т.е. загружаем младшее слово с расширением нуля и делаем or старшему слову в регистре), т.е.
unsigned long i=0x1234;
i|=0x5678<<16;
Или как там можно по системе комманд, я не помню. Дело в том, что загрузка иммедитейта в ARM - узкое местечко, в PPC более грамотно, правда, на AVR32 загрузка лонга методом PPC будет занимать 64 бита, а не 48.
-
Вся работа программы зависит от ответа устройства, опрос его может быть из разных мест, если после каждого вызова каждой функции проверять флаг, а потом делать многоуровневый откат к началу программы, это тоже не выход. Устройство может быть выдернуто в любой момент, и обнаружение ведется по прерыванию, это нормально. Но уходить надо в определенную точку из прерывания. Я не совсем еще понимаю логику работы ИАРа, но, наверно, как то можно подменить адрес возврата из прерывания на адрес этой точки. Может longjmp это и делает?
setjmp запоминает в jmpbuf все необходимые регистры (в том числе Y, SP, PC) в точке вызова этой функции.
longjmp все это загружает обратно и возвращается по записанному в jmpbuf PC. Т.е. то, что надо.
-
Могут помочь стандартные функции setjmp и longjmp.
#include "setjmp.h"
jmp_buf redo_point;
__interrupt void foo1(void)
{
...
longjmp(&redo_point,1); //Тут будет переход на оператор за setjmp
}
main
{
....
setjmp(&redo_point); //Устанавливаем точку длинного перехода
}
-
Вообще-то AVR это RISC процессор,
а идеология RISC как раз и состоит в минимизации фокусов с регистрами
и максимизации простых операций load/store.
Ух ты, вот это формулировка ;)
А пояснить поподробней ;) А то я всегда считал, что для RISC важны именно операции регистр-регистр, т.к. load/store - это медленно.
-
:maniac: Ситуация такая: стоит у меня ATmega128 и флэшка на 8МегаБайт (AT45DB642 Atmel), вообщем я используя ее в режим параллельного програмирования заливаю и сливаю данные. Только вот проблема, после верификации получается, что на некоторых страницах данные не совпадают с исходными.
......
Можно заметить, что среди всех вариантов прослеживается повторяемость некоторого набора страниц. Флэш уже вторую ставлю - первая вообще глючила по страшному. Все тайминги уже тысячу раз проверял, даже на более медленных частотах пускал, чем по документации, - все рано результат тот же. Что делать не знаю, уже голову сломал, а прибор важный, так что ошибок не должно быть.
Посоветуйте, если уже сталкивались с такой проблемой...
От чего болезную питаешь? У меня были проблемы с 45DB021, которая питалась от LP2950-3.3ACZ с конденсатором на выходе 1 мкФ. При записи в страничку (при включении автомата записи) наблюдалась резкая просадка по питанию (все-таки LP2950 довольно медленная штука) и восстановление, но флеха успевала нагадить себе в страницы. Симптомы были очень похожи - пока писал по одной страничке - все работало, а как скопом весь флеш прочистить - то там страничка не записалась, то там. Излечилось кондером по питанию до полного устранения проседаний.
-
У меня с Уартом в порядке, а вот при сравнении компилятор выдает ошибку
char HexCom[9]; __flash char Status[] = "STATUS\0"; if (strcmp(HexCom, Status) == 0) response_sms(1);
Error[Pe167]: argument of type "char __flash *" is incompatible with parameter of type "char const *"
Логика компилятора железная - не совпадают типы. Пользуйтесь strcmp_P!
-
А у человека - IAR ;)
Думаешь он не догадается как переделать под IAR? :)
Ты не понял, то что он сделал - в IAR работает так как хочется - берет из flash, т.к. указатель с модификатором __flash
-
...
в GCC так делается
А у человека - IAR ;)
-
А USART_transmit функция или макрос? Если макром, то инструкции вида *ptr++ использовать нельзя!
А USART_transmit функция или макрос? Если макром, то инструкции вида *ptr++ использовать нельзя!
Обоснуй!
Обоснуй! ;)
-
Хорошо, имеется некая структура данных (массив и индексы), по сути в этой структуре хранится весь контекст приемника. В чем заключается сложность обращения к этой структуре из обработчика прерывания? Ни в чем. Непонятно для чего может потребоваться еще что-то сохранять, когда просто попав в обработчик прерывания можно работать непосредственно с этой структурой данных (не затрагивая других структур данных).
Можно, однако это раздувает код, т.к. все локальные переменные превращаются в статические. А само сохранение регистров (и последующее восстановление) остается и никуда не девается. А так убиваем двух зайцев - код уменьшаем, улучшаем читаемость этого всего дела, т.к. весь алгоритм лежит последовательно, а не по кусочкам, выполнить то, выполнть это...
for(;;) { task1(); task2(); task3(); }
Аналогично - все превращается в автомат и совершенно не читабельно. Тем более, что эта программа (это стек TCP/IP) как понимаете не самоцель, а лишь маленькая часть большой программы, а вы предлагаете весь софт писать вот так?
ЗЫ Наверное, надо другую тему организовать под названием "Какие у сапожников взгляды на искусство" ;)
-
Тогда у меня к Вам, как к автору кода, есть пара вопросов:
1. почему нельзя было просто вызвать IPrec() в обработчике прерывания?
2. из-за чего весь сыр-бор с сохранением стеков?
1. Возможно вы заметили, что IPreciver есть не конечный автомат, а обычный код, скажем так, поток (нить, thread) выполнения. Посему есть ответ и на вопрос 2 - весь сыр-бор - это организация двух (точнее трех) задач - main, IPreciver, IPtransmitter. Из них IPxxx - это задачи, которые передают управление в основную задачу только тогда, когда им надо ждать символ из входного потока (IPreciver) или ждать окончания передачи символа в выходной поток (IPtransmiter). И получают они управление по соответствующим прерываниям. Почему так - объясняю. Представте, что вам надо получить в буфер 20 байт. Как вы пишете это без использования прерываний:
char s[20];
char *p=s;
char i=20;
do
{
*p++=rxchar();
}while(--i);
Просто и понятно.
Теперь представте это как автомат. Необходимо хранить указатели, состояние, и т.д. Каждое прерывание их необходимо загрузить, потом выгрузить. Весьма накладно, когда обработчик большой и сложный - как например TCP/IP. Поэтому, в том проекте, который мы обсуждаем, сделана такая многозадачка с использованием функций исключительно библиотеки. Т.е. что получается с сохранением контекста:
1. Обработчик прерываний штатно сохраняет все scratch-регистры, т.к. есть вызов функции в обработчике (функция setjmp и longjmp). Также обработчик сохраняет SREG и если AVR большой, всяческие RAMPZ. Точнее сохраняет компилятор.
2. Функция setjmp сохраняет все localstore-регистры,оба указателя стека SP и Y, а также PC. В результате имеем полностью сохраненный контекст задачи в двух местах - часть регистров лежит в CSTACK задачи, остальное - в jmp_buf.
Назад - аналогично. Прелести метода в том, что ни одной асмовской комманды нет. Единственное колдовство - инициализация задачи прямо в jmp_buf. При анализе суммарного кода почти нет потерь на на переключение, если сравнивать чисто с асм-вариантом - буквально 1 лишний CALL.
-
По пункту 3 :
Предполагаю что setjmp запоминает регистры R0-R31, SREG ... в память а longjmp загружает из памяти указанной как аргмент к этим функциям . Тип jmp_buf используется для сохранения этих регистров наверху. Поддержка многозадачности .
jmp_buf main_task;
jmp_buf iprx_task;
jmp_buf iptx_task;
для каждой задачи по своему буферу для сохранения контекста (регистров и данных наверху)
char iprx_rstack[8]; - исползуется для сохранения RSTACK . У IAR два стека - CSTACK и RSTACK . В случае переключения от одной задачи к другой - оба надо сохранять . Посмотри документы по IAR для детального обяснения.
Гм, да можно было и у меня спросить... Приятно, когда на твоих исходниках люди учатся ;)
-
Rst7, одни и те же команды для всех семейств выполняются за одинаковое число тактов.
Возможны варианты только для очень специфических команд (сейчас не вспомню каких). Но в Вашей задаче они явно не будут использоваться.
Я знаю ;) Задача не моя ;) Просто я предложил человеку, как возложить на компилятор вопрос подсчета.
-
Необходимо отмерить задержки в миллисекундах с с точностью до 5%. Очевидно, что при использовании С для различных компиляторов может быть различен. Вывод: необходимо использовать inline-функций на Asm. Но вот вопрос одинаковое ли количество тактов выполняются одни и те же команды для различных семейств (Tini,Classic,Mega) ?
__delay_cycles(сколько тактов) в IAR'е решат ваши проблемы ;)
-
Кгхм...
Не поторопились, уважаемый? Делением на 16 проблему не решить, Там реально сначала нужно умножить на 10, а вот потом уже делить на 16, а то Ваши результаты будут врать ровно в 10 раз.
Обоснуй!
ЗЫ У меня это дело в измерителе уже года 4 работает, если бы оно в 10 раз врало - хрен бы я метрологию прошел ;)
-
В датащите об этом ни строчки!!!
Плохо смотрите. Там конечно не написано так же прямо, как я написал. Там есть табличка (пардон за форматирование):
Temperature/Data Relationships Table 2
MSb 2^3 2^2 2^1 2^0 2^-1 2^-2 2^-3 2^-4 LSB
MSb S S S S S 2^6 2^5 2^4 MSB
(unit = °C)
TEMPERATURE DIGITAL OUTPUT DIGITAL OUTPUT
(Binary) (Hex)
+125°C 0000 0111 1101 0000 07D0h
+85°C 0000 0101 0101 0000 0550h*
+25.0625°C 0000 0001 1001 0001 0191h
+10.125°C 0000 0000 1010 0010 00A2h
+0.5°C 0000 0000 0000 1000 0008h
0°C 0000 0000 0000 0000 0000h
-0.5°C 1111 1111 1111 1000 FFF8h
-10.125°C 1111 1111 0101 1110 FF5Eh
-25.0625°C 1111 1110 0110 1111 FF6Fh
-55°C 1111 1100 1001 0000 FC90h
*The power on reset register value is +85°C.
-
В описании на DS18B20 сказано, что значение положительной температуры - это один байт (нулевой).
Если его значение разделить на два, то получаем целое значение температуры в градусах Цельсия.
Если значение измеряемой температуры становится отрицательным, то первый байт становится 0xFF.
Измеряю комнатную температуру и вижу примерно следующие значения: нулевой байт=0xD7,
первый байт=0x01.(как видим, значение температуры - ДВА байта!!!) Значение измеряемой температуры получается 235 градусов! Вытащил датчик за окно. Значение начало добросовестно линейно уменьшаться и при переходе через ноль первый байт, опять же добросовестно,
становится 0xFF. CRC во всех случаях равна нулю. Второй датчик ведет себя точно так же.
Попробовал читать из DS1990. Правильно читает сто из ста.
Вопрос в следуещем. Так как же перевести то, что прочел из датчика в реальные градусы Цельсия или
Фаренгейта???
Берешь эти 2 байта как целое со знаком (int) и делишь на 16 (или двигаешь вправо на 4, например t>>=4).
Теперь Т у тебя температура в целых градусах Цельсия со знаком.
-
А вы пробовали другой экземпляр Tiny26
у меня как то раз была битая мега (один бит в регистре r14) не работал глюков было....
2 разных, один с L, другой без.
-
Попробовал на Tiny2313 - все пучком, на порту 0x55. Имя порта, естественно, пришлось заменить с A на B.
-
Бинарники смотрели ? Может криво компилятор генерит...
Грузил в AVRStudio, смотрел на дизасм, трассировал, сравнивал код с даташитом. Все правильно.
А если пойти другим путем, тестовый Ваш код запустить на другом камне, вернее другого типа - тини13,14, 15 или любом другом тини? Какие там будут результаты?
На Т15 - безъидейно - нет Х регистра и sram. Щас попробую на Tiny2313 запустить. Других нет.
-
Бинарники смотрели ? Может криво компилятор генерит...
Грузил в AVRStudio, смотрел на дизасм, трассировал, сравнивал код с даташитом. Все правильно.
-
Я тоже сделал код:
#include "iotiny26.h" NAME main PUBLIC main ORG $0 RJMP main RSEG CODE main ldi r16,0xFF out DDRA,r16 ldi r16,0 out PORTA,r16 ldi r26,0x60 ldi r27,0x55 ld r16,x+ out PORTA,r27 dead_loop rjmp dead_loop END main
Что должно быть на порту А? Правильно - 01010101. Смотрим на лапы - 00000000. Убираем "ld r16,x+". На порту A - 01010101.
Что я делаю неправильно?
2 камня, с L и без L
-
Вы невнимательно читаете мои посты. Я уже привел перевод из документации Atmel, который черным по белому говорит, что то, что я ожидаю, должно произойти и не должно привести к каким-либо непредсказуемым последствиям.
Понимаете, доверие к фирме Atmel у меня будет чуть-чуть повыше чем к Вам и намного выше чем к глючному IAR. Тема поднятая Вами достаточно серьезная. Либо Вы обнаружили баг ядра, который впоследствии появится в errata, либо баг IAR, либо третий наиболее неприятный вариант - вам померещилось.
В том самом даташите имеется допущение:
Not all variants of this instruction is available in all devices. Refer to the device specific instruction set summary.
Полагаю оно относится к Tiny15, но кто знает, может быть и к tiny26 оно тоже относится. Хотя буду откровенен, считаю, что оно не относится к tiny26.
Перевожу то, что вы процитировали: Не все варианты этой инструкции доступны во всех устройтвах.
Все описаные варианты данной инструкции доступны в Tiny26. Памяти данных у нее не более 256 байт, следовательно, старший байт игнорируется (см. посты выше). Все очень прозрачно написано.
Для чистоты эксперимента, предлагаю Вам скомпилировать Ваш код в AVR Studio, и проверить на реальном чипе. Если XH точно также затрется, тогда это явно баг ядра, если нет, тогда это явный баг IAR'а, и тогда следует писать в IAR, а не в Atmel.PS: такой эксперимент я уже проделал, угадайте результат.
Как Вы думаете, я не на живом камне третий день е....сь? :angry2: Про код, который я написал - это проверочная вставка, для того, чтобы убедится, что именно камень. Код компилирован правильно, т.е. так, как я написал - один к одному, без всяких изменений.
-
Я ожидаю, что при выполнении сл. действий:
X=0x380;
LD R16,X+;
будет в регистровой паре X число 0x381. Этого не происходит.
В эмуляторе все так и есть, но ведь в реальном чипе вполне возможна загрузка константы 0 при выходе за границу максимального адреса. Вы же читаете с несуществующего адреса, что уже само по себе неправильно и может привести к любым непредсказуемым последствиям.
Вы невнимательно читаете мои посты. Я уже привел перевод из документации Atmel, который черным по белому говорит, что то, что я ожидаю, должно произойти и не должно привести к каким-либо непредсказуемым последствиям.
По большому счету, скажите зачем использовать IAR для камня с 2kb Flash и 128 байт RAM?Так надо.
AVR32?
в AVR32
Опубликовано · Пожаловаться
Вот-вот, это способ загрузки лонга в ARM процах. Именно здесь и узкое место. Объясню.
Отвлечемся от конвейеров и т.д. Будем рассматривать проц без всяких наворотов в этом смысле(как AVR). Что надо на ARM, чтобы загрузить лонг (точнее, что происходит на шине):
...
читаем комманду
читаем комманду
читаем комманду (загрузка по PC+что-то)
вычисляем это PC+чтото
грузим данные
читаем комманду
....
Для PPC (возможна такая же фича на AVR32)
читаем комманду
читаем комманду (в комманде мл. 16 бит)
читаем комманду (в комманде ст. 16 бит)
читаем комманду
Вроде особой разницы нет, если вспомнить про конвейер, и что время на вычисление PC+xxx не тратится.
Однако, если учесть, что поток комманд вынимается заранее, да еще и не одна комманда за раз (а сколько в шину данных влезло), а если из динамической памяти, так еще и burst-mode, то загрузка одного лонга из выпадающего из основного потока истории ;) адреса все "чи" поломает. Вот в этом месте узкость ARM. PPC этой узкости не имеют. AVR32 - можно так, можно эдак, вообщем, как компилятору приспичит.