|
Mega48-20 не пишет в EEPROM, Что я забыл? |
|
|
|
Dec 16 2014, 08:56
|
Гуру
     
Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446

|
Цитата(Сергей Борщ @ Dec 16 2014, 10:00)  Код EECR |= (1<<EEMPE); /* Write logical one to EEMPE */ EECR |= (1<<EEPE); /* Start eeprom write by setting EEPE */ Между установкой EEMPE и установкой EEPE должно пройти не более 4 тактов. Посмотрите, во что вылились эти операторы с вашими настройками компилятора. А чтобы работало железно - не используйте тут '|='. Вы ведь точно знаете сотояние всех остальных битов, вот и пишите каждый раз все биты через '='. Компилятор GCC. Кстати оптимизация О0. Если включить другую, то код ужимается раза в два и более при этом перестает работать. Что-то я упускаю в своем понимании. А как кстати тогда правильно если не использовать '|='?
--------------------
Живи днем так, чтобы ночью ты спал спокойно.
|
|
|
|
|
Dec 16 2014, 09:08
|

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

|
Цитата(smk @ Dec 16 2014, 10:56)  Компилятор GCC. Тогда используйте <avr/eeprom.h> и описанные в нем eeprom_write_byte(), eeprom_read_byte(). Там все проблемы времянок решены для всех уровней оптимизации: Код #include <avr/eeprom.h>
void test() { eeprom_write_byte((uint8_t *)0x0A, mode); } Цитата(smk @ Dec 16 2014, 10:56)  А как кстати тогда правильно если не использовать '|='? примерно так: Код void EEPROM_write(unsigned int Address, unsigned char Data) { while(EECR & (1<<EEPE)) /* Wait for completion of previous write */ ; EEAR = Address; /* Set up address and Data Registers */ EEDR = Data; EECR = (1<<EEMPE); /* Write logical one to EEMPE */ EECR = (1<<EEMPE)|(1<<EEPE); /* Start eeprom write by setting EEPE */ }
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 16 2014, 09:11
|
Гуру
     
Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446

|
Цитата(Сергей Борщ @ Dec 16 2014, 11:08)  Тогда используйте <avr/eeprom.h> и описанные в нем eeprom_write_byte(), eeprom_read_byte(). Там все проблемы времянок решены для всех уровней оптимизации: Код #include <avr/eeprom.h>
void test() { eeprom_write_byte((uint8_t *)0x0A, mode); } примерно так: Код void EEPROM_write(unsigned int Address, unsigned char Data) { while(EECR & (1<<EEPE)) /* Wait for completion of previous write */ ; EEAR = Address; /* Set up address and Data Registers */ EEDR = Data; EECR = (1<<EEMPE); /* Write logical one to EEMPE */ EECR = (1<<EEMPE)|(1<<EEPE); /* Start eeprom write by setting EEPE */ } Спасибо. Только я теперь не пойму что они в даташитах пишут и зачем? Раньше, помню, работало.
--------------------
Живи днем так, чтобы ночью ты спал спокойно.
|
|
|
|
|
Dec 16 2014, 13:43
|

Шаман
     
Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221

|
Цитата(smk @ Dec 16 2014, 14:40)  Ну а какой операцией? Операцией присваивания, как и советовал Сергей Борщ. Цитата(Bear_ku @ Dec 16 2014, 14:45)  Нашел старую программу для ATmega128, все было сделано по ДШ и именно с "|=", работает без нареканий. Листинг кода посмотрите. В Вашем случае могла быть некоторая неявная оптимизация, например, битовыми операциями (не помню, попадают ли эти регистры для работы с ними битовыми операциями). Но в любом случае следует избегать непереносимого кода и зависеть от трюков конкретной версии компилятора.
|
|
|
|
|
Dec 16 2014, 14:31
|
Гуру
     
Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446

|
Цитата(IgorKossak @ Dec 16 2014, 15:43)  Операцией присваивания, как и советовал Сергей Борщ.
Листинг кода посмотрите. В Вашем случае могла быть некоторая неявная оптимизация, например, битовыми операциями (не помню, попадают ли эти регистры для работы с ними битовыми операциями). Но в любом случае следует избегать непереносимого кода и зависеть от трюков конкретной версии компилятора. Да, компилятор я понимаю, это может быть причиной. А присваивание это я так понимаю состоит из трех этапов. Сначала вычитать, потом изменить и прописать обратно. В STM регистры специально заточены под присваивание. Но там обстоятельства таковы что это допустимо. Может Вы имеете в виду операции типа REGISTR |= 0x01; ?
--------------------
Живи днем так, чтобы ночью ты спал спокойно.
|
|
|
|
|
Dec 16 2014, 19:14
|
Гуру
     
Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446

|
Код ../trsm_m48.c:21: warning: passing argument 1 of '__eerd_byte_m48' makes pointer from integer without a cast Вот такое предупреждение. Что опять не так? Указатель нужен? Все заработало, Спасибо! Однако с предупреждением не вполне ясно и чую включу оптимизацию (хоть и нет нужды) но работать перестанет. Отпишусь...
--------------------
Живи днем так, чтобы ночью ты спал спокойно.
|
|
|
|
|
Dec 16 2014, 19:16
|

Шаман
     
Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221

|
Цитата(smk @ Dec 16 2014, 16:31)  Да, компилятор я понимаю, это может быть причиной. А присваивание это я так понимаю состоит из трех этапов. Сначала вычитать, потом изменить и прописать обратно. В STM регистры специально заточены под присваивание. Но там обстоятельства таковы что это допустимо. Может Вы имеете в виду операции типа REGISTR |= 0x01; ? Присваивание это просто запись, а то, что Вы описали, называется чтение-модификация-запись. Т. е. надо так, как Вам советовали: Код EECR = (1<<EEMPE); /* Write logical one to EEMPE */ EECR = (1<<EEMPE)|(1<<EEPE); /* Start eeprom write by setting EEPE */
|
|
|
|
|
Dec 16 2014, 20:04
|
Гуру
     
Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446

|
Ну вот... О1 и уже не работает. прикладываю проект для студии целиком. На самом деле действительно интересно что происходит. С кейлом таких чудес небыло ни разу. Не суть, просто хочу понять что происходит...
tr.rar ( 21.31 килобайт )
Кол-во скачиваний: 49Цитата(IgorKossak @ Dec 16 2014, 21:16)  Присваивание это просто запись, а то, что Вы описали, называется чтение-модификация-запись. Т. е. надо так, как Вам советовали: Код EECR = (1<<EEMPE); /* Write logical one to EEMPE */ EECR = (1<<EEMPE)|(1<<EEPE); /* Start eeprom write by setting EEPE */ Ну пусть так. Однако серийное изделие (лет более 5-ти) на Тини24 работает и повторяется .... правда перепер на STM8S0003F, но это детали... и на тини отлично все работает. Версия компилятора не изменилась. В чем смысл тогда? оптимизация Os сильно убыстряет циклы мигания Код PORTC = 0b00010000; delay(30000); PORTC = 0b00000000; delay(30000); Это почему?
--------------------
Живи днем так, чтобы ночью ты спал спокойно.
|
|
|
|
|
Dec 16 2014, 20:09
|

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

|
Цитата(smk @ Dec 16 2014, 21:14)  Вот такое предупреждение. Что опять не так? Указатель нужен? Да, нужен. смотрите еще раз: Код eeprom_write_byte((uint8_t *)0x0A, mode); А теперь смотрите на свой код: Код mode = eeprom_read_byte (0x0A); Видите разницу около 0x0A? Цитата(smk @ Dec 16 2014, 21:31)  Ну вот... О1 и уже не работает. Естественно. Ваша функция delay не делает с точки зрения компилятора ничего полезного. Наоборот, она делает маленькую быструю программу большой и медленной. Оптимизатор выкинул ее нафиг. Изучайте <util/delay.h>Цитата(smk @ Dec 16 2014, 21:14)  С кейлом таких чудес небыло ни разу. Там настолько плохой компилятор, что не умеет выкидывать пустые циклы? Цитата(smk @ Dec 16 2014, 21:14)  на тини отлично все работает. Версия компилятора не изменилась. В чем смысл тогда? Откройте листинги, сравните, найдите разницу.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 16 2014, 20:19
|
Гуру
     
Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446

|
так предлагаете unsigned char *0x0A или как? Читает и пишет правильно. Код mode = eeprom_read_byte (0x0A); а на мой взгляд делей делает очень полезную штуку. как компилятору сказать?
--------------------
Живи днем так, чтобы ночью ты спал спокойно.
|
|
|
|
|
Dec 16 2014, 21:47
|
Гуру
     
Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446

|
в смысле цикл тот Код void delay (unsigned long t) { while(t--); } и еще, delay_ms... сразу дало большой довесок коду. включил оптимизацию, но это привело программу в нерабочий вид. хотя код ужало. в чем смысл?
--------------------
Живи днем так, чтобы ночью ты спал спокойно.
|
|
|
|
|
Dec 17 2014, 03:54
|
Частый гость
 
Группа: Участник
Сообщений: 154
Регистрация: 9-09-11
Пользователь №: 67 076

|
Цитата(IgorKossak @ Dec 16 2014, 18:43)  Но в любом случае следует избегать непереносимого кода и зависеть от трюков конкретной версии компилятора. Переносимость меня абсолютно не волнует. А вот "зависеть от трюков" это видимо действительно было, примеры в ДШ даны для IAR и поэтому в IAR работают без нареканий. Ну а по поводу того, что программа перестает работать при включении оптимизации - это нормально. Проблему можно легко вычислить воспользовавшись средствами отладки. Есть подозрение что виновата переменная consol, попробуйте в ее объявление добавить квалификатор volatile.
Сообщение отредактировал Bear_ku - Dec 17 2014, 03:55
|
|
|
|
|
Dec 17 2014, 07:17
|
Местный
  
Группа: Участник
Сообщений: 333
Регистрация: 19-12-13
Из: Новосибирск
Пользователь №: 79 709

|
Я делал один проект. Сначала взял ATMEGA8535. Проект писал в IAR. Когда прошил программу, все работало, кроме записи в EEPROM. Стал разбираться. Залил давний проект, написанный на асме. Запись в EEPROM работает. Стал сверять в дизасме. Вроде все нормально, а запись EEPROM не работает. Решил проверить эту же программу, но скомпилированную под ATMEGA32. Запись в EEPROM нормально работает. Выходит, что библиотеку записи в EEPROM нужно написать на асме. Но я в IAR так и не смог пока разобраться, как правильно писать и использовать функции на асме. Да и в тот раз обошелся ATMEGA32A. И некогда мне было с асмом в IAR разбираться. Еще один случай. Умер один человек, мне достались его проекты. Написаны в IAR. Его девайсы сделаны на ATMEGA1280. Для сохранения данных использовались внешние EEPROM. То есть, когда-то этот человек тоже испытывал трудности с записью в EEPROM в проектах, созданных в IAR, на некоторых МК AVR.
|
|
|
|
|
Dec 17 2014, 08:18
|
Местный
  
Группа: Участник
Сообщений: 333
Регистрация: 19-12-13
Из: Новосибирск
Пользователь №: 79 709

|
Цитата(Сергей Борщ @ Dec 17 2014, 14:00)  Я порой вам удивляюсь. ИАР еще пятнадцать лет назад имел квалификатор __eeprom. Достаточно было прочитать документацию, объявить переменную с таким квалификатором и просто читать-писать ее как обычную переменную. Компилятор подставлял доступ к eeprom куда нужно сам и этот доступ всегда 100% работал. Вот какой смысл было изобретать велосипед и реализовывать свои процедуры чтения/записи? Причем судя по вашему описанию велосипед-то получился с квадратными колесами. Сергей, вы заранее не исходите из ваших предположений, ладно? Все на месте, один и тот же проект, на ATMEGA8535 запись в EEPROM не работает, на ATMEGA32\A работает. Код __eeprom u08 ee_empty_val = 0; __eeprom u16 ee_tim_heat_val = 12; __eeprom u16 ee_tim_formovka_val = 12; __eeprom u16 ee_tim_pnevmosyem_val = 6; Этот случай давно был. На сахаре мне тогда ответили, что, возможно, придется писать свою библиотеку для работы с EEPROM на асме.
|
|
|
|
|
Dec 17 2014, 08:22
|

Гуру
     
Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237

|
Цитата(Сергей Борщ @ Dec 17 2014, 11:00)  Я порой вам удивляюсь. ИАР еще пятнадцать лет назад имел квалификатор __eeprom. Достаточно было прочитать документацию, объявить переменную с таким квалификатором и просто читать-писать ее как обычную переменную. Компилятор подставлял доступ к eeprom куда нужно сам и этот доступ всегда 100% работал. Вот какой смысл было изобретать велосипед и реализовывать свои процедуры чтения/записи? Причем судя по вашему описанию велосипед-то получился с квадратными колесами. Проблема именно в том, что у топикстартера компилятор не IAR, а GCC: Цитата(smk @ Dec 16 2014, 11:56)  Компилятор GCC. Однако те макросы, которые я привела из IAR, легко вживляемы в GCC. А вот __eeprom приживить едва ли будет возможно, т.к. это не просто определение типа, а в придачу встроенные возможности.
|
|
|
|
|
Dec 17 2014, 08:39
|

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

|
Цитата(demiurg1978 @ Dec 17 2014, 10:18)  Сергей, вы заранее не исходите из ваших предположений, ладно? Все на месте, один и тот же проект, на ATMEGA8535 запись в EEPROM не работает, на ATMEGA32\A работает. Видимо недопонял. Получается, была ошибка в компиляторе? Цитата(Xenia @ Dec 17 2014, 10:22)  Проблема именно в том, что у топикстартера компилятор не IAR, а GCC: Ксения, с топикстартером уже давно разобрались и перешли к стадии "бойцы вспоминают минувшие дни". Практически дословно содержимое вашего макроса уже было в этой теме на прошлой странице. И там же было обсосано, почему так лучше не делать.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 17 2014, 09:34
|
Местный
  
Группа: Участник
Сообщений: 333
Регистрация: 19-12-13
Из: Новосибирск
Пользователь №: 79 709

|
Цитата(Сергей Борщ @ Dec 17 2014, 14:39)  Видимо недопонял. Получается, была ошибка в компиляторе? Получается, что так. Досконально я не разбирался. Включал разные степени оптимизации кода. Смотрел в дизасме. А так как проект тогда оброс некоторыми дополнительными функциями, и размер кода увеличился, и запись в EEPROM заработала на другом МК, мне тем более пришлось взять вместо ATMEGA8535, ATMEGA32A. Кстати, прикол в том, что запись в EEPROM работает на МК, выпущенных позднее ATMEGA8535. Нужно уделить время, сесть и понять разницу между моим рабочим проектом на асме и дизасмом в IAR. Тогда не до этого было. Сейчас тоже со свободным временем не очень...
Сообщение отредактировал demiurg1978 - Dec 17 2014, 09:37
|
|
|
|
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|