|
|
  |
перезапуск программы, непонятно почему. |
|
|
|
Jan 17 2007, 19:36
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(simsim @ Jan 17 2007, 20:00)  Цитата(simsim @ Jan 17 2007, 17:46)  Цитата(GDI @ Jan 17 2007, 12:42)  Индексы массивов не выходят ли за границы оных, стек не переполняется? Какой компилятор? Да может и исходник бы здесь тоже не помешал..
Компилятор CodeVisionAVR 1.24.8, индексы в порядке, потому что два раза проходит нормально, а на третий выполняя то же самое перезапускается. Размер стека 256 байт, неужели мало? Что такое HEAP SIZE в настройках CVAVR ? Увеличил стек до 500. Теперь перезапускается после 5-го обновления массива leds, а не 3-го как раньше. В подпрограмме обновления leds есть обращение к ассемблерной подпрограмме - #pragma warn- // this will prevent warnings unsigned char asm_font(unsigned char aa1, unsigned char bb1) { #asm .def temp =r16 .def zh =r31 .def zl =r30 .def ak =r23 .def bk =r24 .def yh =r29 .def yl =r28 .................. lpm r30,z ; результат ret #endasm } #pragma warn+ // enable warnings Может здесь причина? Если у Вас зависит от числа вызывов, то это однозначно указывает, что у Вас плывёт указатель стэка. Одного или другого. Зачем Вы замыливаете причину??? Просто найдите и устраните! Как собирались. Верните всё как было (всё таки два цикла меньше чем 5 гнать) и прогоните в Studio. Обратите внимание на указатель стэка в одном и том же месте. Теперь вопрос 2. Зачем Вы путаете Си и Asm если Вы ещё в самом начале пути??? Вы уверены что регистры которые Вы портите в Asm не использует компилятор??? Простите, но для меня Ваша прога, просто лишена смысла. Как можно результат занести в регистр? И что? А если при следующей компиляции компилятор поменяет использование регистров??? Это же его право! Я понимаю ещё если бы Вы с переменной работали, а используемые регистры сохраняли. И то! Зачем Вам вообще это. Используйте чистый Си. Я уверен, - то что Вы хотите сделать на Asm можно реализовать и в рамках языка! Просто спросите в форуме - как это сделать. Приведу пример. В начале своего последнего проекта, я хотел делать ассемблерные п/п. Чтобы ускорить работу в некоторых местах. Но решил сделать это после отладки проекта. А, сначала, всё реализовать на Си. Теперь проект закончен. И, наверное я уже просто не буду этим заниматься. У меня просто банально всё работает. Производительность отличная. Так зачем этот цирк?
|
|
|
|
|
Jan 17 2007, 20:14
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Чтобы все не спорили. Массивы, объявленные внутри функции(локальные), равно как и локальные переменные, и в С и в С++ размещаются на стеке. В ИАРе на стеке данных (CSTACK). В куче в С++ размещаются объекты созданные через вызов operator new. В "голом" С в куче "само" не размещается ничего. Программист может зарезервировать себе кусочек памяти в куче библиотечными функциями malloc, calloc и в этот кусочек разместить что захочет. Иначе никак. Цитата(SasaVitebsk @ Jan 17 2007, 18:36)  Как можно результат занести в регистр? И что? А если при следующей компиляции компилятор поменяет использование регистров??? Это же его право! В защиту автора функции: В данном случае речь идет о CV, а он использует именно R30:R31 для передачи параметров и возврата значений. Это описано в его доке и просто так не поменяется. Цитата(SasaVitebsk @ Jan 17 2007, 18:36)  Приведу пример. В начале своего последнего проекта, я хотел делать ассемблерные п/п. Чтобы ускорить работу в некоторых местах. Но решил сделать это после отладки проекта. А, сначала, всё реализовать на Си. Теперь проект закончен. И, наверное я уже просто не буду этим заниматься. У меня просто банально всё работает. Производительность отличная. Так зачем этот цирк? Вот тут полностью согласен. Но если автор настаивает, то можно порекомендовать вместо этой функции вставить затычку, типа такой: Код unsigned char pass; unsigned char asm_font(unsigned char aa1, unsigned char bb1) { return ++pass; } и посмотреть как будет работать. Если вешаться перестанет, то написать простую программу: Код void main() { for(;;) asm_font(1,2); } и прогнать ее в avrstudio, обращая внимание на стек, на изменяющуюся память, на регистры. А можно и сюда текст функции выложить - коллективом ошибки ловятся быстрее.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jan 17 2007, 20:37
|
Местный
  
Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527

|
Цитата(AndryG @ Jan 17 2007, 20:21)  Не вчитывался в посты народа ... звыняйте .. в АСМ-вставке Вы используете R30 - в CVAVR - это самый главный регистр - указатель стека!!! Вот с ним Вы беду и делаете. Если Ваша вставка - функция - подавно все развалится - прочтите раздел хелпа по функциям асемблерным - там указано что и как сохранять на примере кода. Цитата из хелпа CV - "The registers R0, R1, R22, R23, R24, R25, R26, R27, R30 and R31 can be freely used in assembly routines." R30,R31 используются для возврата результата функции. Указатель стека - R28,R29.
|
|
|
|
|
Jan 17 2007, 21:06
|
Участник

Группа: Новичок
Сообщений: 45
Регистрация: 30-10-06
Пользователь №: 21 801

|
Заменил ассемблерную функцию на СИ-шную unsigned char asm_font(unsigned char aa1, unsigned char bb1) { unsigned int tp; tp=(aa1*8)+bb1; return font8[tp]; } но теперь другая проблема- при отладке в AVR Studio аа1=207, tp получается равным 121 !!! не поддается осмыслению ... p.s. ОТ перезапуска избавился.спасибо.
Сообщение отредактировал simsim - Jan 17 2007, 21:08
|
|
|
|
|
Jan 17 2007, 21:35
|
Участник

Группа: Новичок
Сообщений: 45
Регистрация: 30-10-06
Пользователь №: 21 801

|
Цитата(simsim @ Jan 17 2007, 21:06)  Заменил ассемблерную функцию на СИ-шную unsigned char asm_font(unsigned char aa1, unsigned char bb1) { unsigned int tp; tp=(aa1*8)+bb1; return font8[tp]; } но теперь другая проблема- при отладке в AVR Studio аа1=207, tp получается равным 121 !!! не поддается осмыслению ... p.s. ОТ перезапуска избавился.спасибо. Спасибо, нашел - tp=aa1; tp*=8; tp+=bb1; (СИ это вам не математика :-)
|
|
|
|
|
Jan 18 2007, 00:49
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(SasaVitebsk @ Jan 17 2007, 20:10)  Для IAR даже если массив объявлен внутри ф-ции, то он всё равно будет создан "на этапе запуска стартап-кода". Даже если он и будет создан динамически (не программистом а компилятором), то он будет создан за счёт памяти выделенной под это на этапе линковки. А куча полностью предоставлена программисту. (Как в С++ не знаю). Я могу выделить память и освободить её. М/у моими действиями ничего происходить с кучей не должно. Ничего без моего участия. Таким образом учитывая, что парень не слышал о таком слове  - куча не занята, и она явно к этому не имеет никакого отношения. 2 defunct поясни пожалуйста, что я сказал неправильно. Я не для спора, а для своего понимания. Смею предположить, что неверна лишь выдержка из поста Prottoss "на этапе запуска стартап-кода". Но я её просто как выдержку привёл, а имелл ввиду что сама прога полностью сгенерирована к моменту запуска. И место под переменные уже выделены. Это так не только в Си. С динамической памятью работать приходилось. Посмотри пожалуйста следующую за вырванной фразу. Я пишу, "Даже если он и будет создан динамически (не программистом а компилятором), то он будет создан за счёт памяти выделенной под это на этапе линковки." То есть я как раз и описываю этот вариант. В моём сообщении не это главное. Опишу чуть ниже. 2 Сергей Борщ по поводу первого раздела, именно это я и хотел сказать но у меня не получилось.  Но я говорю немного уклончиво потому, что полностью компилятор не знает никто кроме разработчиков, а в полной мере проверить не удаётся. А в документах, можно кое что упустить. Пример специально для Вас Сергей Борщ.  В библиотеках которые я выкладывал по поводу 18b20 применено динамическое распределение памяти. И там же использован массив локальный. приведу текст для понимания. Код //Чтение температуры int8_t read_scratchpad(uint8_t tip) { uint8_t scratchpad[8]; uint8_t crc = 0;
OW_write_byte(READ_SCRATCHPAD); // читаем scratchpad 0xBE for (uint8_t c1 = 0; c1 < 8; c1++) { scratchpad[c1] = OW_read_byte(); // Принять данные с 1 Wire шины crc = OW_crc8(crc, scratchpad[c1]); // Посчитать CRC8 для 1 Wire шины } crc=OW_crc8(crc, OW_read_byte()); OW_reset(); if (crc == 0) // Проверить CRC8 для 1 Wire шины { if(tip==DS18B20TIP) return ((scratchpad[1] << 4) | ((scratchpad[0]+8) >> 4)); else return ((scratchpad[1] & 0x80) | ((scratchpad[0]+1) >> 1)); } else return ( ERROR_CRC); // Message -80 } Возможно Вы будете удивлены, но IAR данный массив размещает в регистрах. (Оптимизирует) 2 defunct. Главное, о чём я писал в своём сообщении, что если бы компилятор произвольно использовал бы кучу, то как с ней работать? А если я её освобождаю ниже занятого уровня? Я уверен, что она не занята. Потому, что мной она не занята. Он меня ещё может контролировать. Я его - нет. Поэтому я и высказал сомнение. Этого нет даже на PC.
|
|
|
|
|
Jan 18 2007, 03:43
|
Участник

Группа: Новичок
Сообщений: 19
Регистрация: 18-01-07
Пользователь №: 24 530

|
Всем привет. Я можнт что-то не понимаю скажите а разве между этими строками есть разница. tp=(aa1*8)+bb1; и tp=aa1; tp*=8; tp+=bb1;
|
|
|
|
|
Jan 18 2007, 08:27
|

developer
   
Группа: Свой
Сообщений: 902
Регистрация: 12-04-06
Из: Казань
Пользователь №: 16 032

|
Цитата(Dan_Dima @ Jan 18 2007, 03:43)  Всем привет. Я можнт что-то не понимаю скажите а разве между этими строками есть разница. tp=(aa1*8)+bb1; и tp=aa1; tp*=8; tp+=bb1; aa1 объявлена как char и при умножении aa1*8 вероятно происходит переполнение, а tp объявлена как int и при tp=aa1; tp*=8; так как tp это int переполнения не происходит. Сделай простую проверку, объяви aa1 как int и посмотри результат своего первого выражения tp = (aa1*8) + bb1;
--------------------
Все может быть и быть все может, и лишь того не может быть-чего уж точно быть не может, хотя..и это может быть.
|
|
|
|
|
Jan 18 2007, 09:19
|
Участник

Группа: Участник
Сообщений: 51
Регистрация: 8-01-07
Из: Одесса
Пользователь №: 24 196

|
Цитата(Dan_Dima @ Jan 18 2007, 02:43)  Всем привет. Я можнт что-то не понимаю скажите а разве между этими строками есть разница. tp=(aa1*8)+bb1; и tp=aa1; tp*=8; tp+=bb1; tp=(int)aa1*8+bb1;
--------------------
Опыт - это та чудесная штука, которая позволяет вам узнать ошибку, когда вы ее повторите.
|
|
|
|
|
Jan 18 2007, 12:28
|
Участник

Группа: Новичок
Сообщений: 19
Регистрация: 18-01-07
Пользователь №: 24 530

|
Цитата(dimka76 @ Jan 18 2007, 08:27)  Цитата(Dan_Dima @ Jan 18 2007, 03:43)  Всем привет. Я можнт что-то не понимаю скажите а разве между этими строками есть разница. tp=(aa1*8)+bb1; и tp=aa1; tp*=8; tp+=bb1;
aa1 объявлена как char и при умножении aa1*8 вероятно происходит переполнение, а tp объявлена как int и при tp=aa1; tp*=8; так как tp это int переполнения не происходит. Сделай простую проверку, объяви aa1 как int и посмотри результат своего первого выражения tp = (aa1*8) + bb1; Насколько я помню подобные преобразования компилятор делает сам ( только проверил) так как преобразование идет к "большему" типу. Поэтому эти две записи эквивалентны.
|
|
|
|
|
Jan 18 2007, 13:25
|
Участник

Группа: Участник
Сообщений: 51
Регистрация: 8-01-07
Из: Одесса
Пользователь №: 24 196

|
Насколько я помню подобные преобразования компилятор делает сам ( только проверил) так как преобразование идет к "большему" типу. Поэтому эти две записи эквивалентны. [/quote]
IAR компилятору все равно к какому типу вы приравниваете. Если в выражении берут участие 8-ми битные данные, то будет применена 8-ми битная арифметика. Для оптимизации программы. А за переполнением следите сами.
--------------------
Опыт - это та чудесная штука, которая позволяет вам узнать ошибку, когда вы ее повторите.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|