Вонинг и EEPROM Mega8A

Обсуждаем контроллеры компании Atmel.
Ответить
Аватара пользователя
Gurvinok
Нашел транзистор. Понюхал.
Сообщения: 198
Зарегистрирован: Вт ноя 07, 2006 00:09:58
Откуда: Москва
Контактная информация:

Вонинг и EEPROM Mega8A

Сообщение Gurvinok »

Есть некая функция которая при вызове должна записать в четыре ячейки внутренней EEPROM нолики. Сброс пароля. Вот функция.

Код: Выделить всё

// Функция сброса пароля в 0000
void clear_password(void)
{
   uint8_t i=0;
   while(i<4)
   {
      eeprom_write_byte((uint8_t*)i,0x30);
      i++;
   }
}

А вот Вонинг:
Warning 5 cast to pointer from integer of different size [-Wint-to-pointer-cast]
Ругается вот на это:

Код: Выделить всё

eeprom_write_byte((uint8_t*)i,0x30);

При этом функция честно записывает нолики.

Если записать так:
eeprom_write_byte((uint8_t*)&i,0x30);
Ругаться не буден, но и работать тоже не будет. Кто знает, в чем загвоздка. Работаю в AtmelStudio 6.2
Я не волшебник, я только лечусь
Аватара пользователя
Hoksmur
Родился
Сообщения: 19
Зарегистрирован: Пт окт 22, 2010 12:24:24

Re: Вонинг и EEPROM Mega8A

Сообщение Hoksmur »

Если варнинг перевести - то пишет, что при преобразовании указателя на указатель другого типа могут быть ошибки.
Посмотрите листинг, если всё как надо - можно забыть( но не "православно"). Попробуйте так (пробел поставить):

Код: Выделить всё

 // Функция сброса пароля в 0000
void clear_password(void)
{
   uint8_t *i=0;
   while(i<((uint8_t *)4) )
   {
      eeprom_write_byte( i,0x30);
      i++;
   }
}

Указателю вполне можно присваивать значения. А чтобы сравнивать указатель с указателем - ((uint8_t *)4).
Последний раз редактировалось Hoksmur Пн авг 18, 2014 12:26:57, всего редактировалось 1 раз.
Аватара пользователя
Gurvinok
Нашел транзистор. Понюхал.
Сообщения: 198
Зарегистрирован: Вт ноя 07, 2006 00:09:58
Откуда: Москва
Контактная информация:

Re: Вонинг и EEPROM Mega8A

Сообщение Gurvinok »

И пробел пробовал, и указатель явно отдельно создавал, тоже самое. Я бы забил на это предупреждение, но устройство будет нещадно использоваться 24 часа в сутки и не дай бог где-нибудь оно вылезет. Причем вне цикла все работает как часы.
Я не волшебник, я только лечусь
Аватара пользователя
Hoksmur
Родился
Сообщения: 19
Зарегистрирован: Пт окт 22, 2010 12:24:24

Re: Вонинг и EEPROM Mega8A

Сообщение Hoksmur »

Попробовал у себя, отредактировал пост. теперь всё кошкерно. :)
Аватара пользователя
Gurvinok
Нашел транзистор. Понюхал.
Сообщения: 198
Зарегистрирован: Вт ноя 07, 2006 00:09:58
Откуда: Москва
Контактная информация:

Re: Вонинг и EEPROM Mega8A

Сообщение Gurvinok »

Гениально! :beer: Работает! Я вчера весь вечер на это убил. Замучил Гугл. Огромное спасибо! Надо это дело запомнить, а лучше записать.
Я не волшебник, я только лечусь
Аватара пользователя
YS
Друг Кота
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05
Контактная информация:

Re: Вонинг и EEPROM Mega8A

Сообщение YS »

Кто знает, в чем загвоздка.


Вы используете восьмибитное значение в качестве указателя. Но на AVR указатель по умолчанию занимает 16 бит. Соответственно, компилятор предупреждает, что размер не соответстует, и он дополнит недостающее нулями.

Проблемы могут начаться, если вы захотите записать по адресу, большему чем 255 (особенно опасно в цикле, кстати). Будет переполнение, и запись пойдет по тем же адресам. Так что предупреждение не лишено смысла.

Чтобы втупую избавиться от варнинга, можно сделать так:

Код: Выделить всё

eeprom_write_byte((uint8_t*)((uint16_t)(i)),0x30);


То есть, сначала расширяем i до шестнадцати бит, потом пишем - компилятор не заподозрит подвоха. Но это косметическое решение, от переполнения это не спасет никак, разумеется. Нормальное решение - объявить i как uint16_t.

Код: Выделить всё

eeprom_write_byte((uint8_t*)&i,0x30);


Это вообще жуть. :))

(uint8_t*)&i - Эта запись значит следующее: эй, компилятор, вот переменная i. Возьми ее адрес и преврати его в указатель на восьмибитное значение. То есть, по факту, вы пишете не по тому адресу, что хранится в i, а по адресу самой переменной i, только направляя запись в EEPROM. Разумеется, вы вылетаете за пределы EEPROM, вот оно и не работает.

Решение, предложенное Hoksmur, рабочее, но там слишком много звездочек, в которых при небольшом усложнении легко запутаться. Всю магию с указателями лучше ограничивать одним местом (одной строкой), чтобы в перспективе было легче локализовать источник проблем.
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Аватара пользователя
Gurvinok
Нашел транзистор. Понюхал.
Сообщения: 198
Зарегистрирован: Вт ноя 07, 2006 00:09:58
Откуда: Москва
Контактная информация:

Re: Вонинг и EEPROM Mega8A

Сообщение Gurvinok »

(uint8_t*)&i - это мне посоветовали и от безысходности потраченного времени я все же испробовал хотя сам понимал что это бред. :)) А вот на счет 16 битных указателей я не знал. Надо это дела запомнить. Конкретно для данной задачи программа не должна залезать дальше 48 ячейки, так что переполнение не будет никак. Но замечания очень хорошие и по делу, приму на вооружение на будущее. Спасибо.

Пи.Си.
А как это понять? Из eeprom.h Или я еще не проснулся. :shock:

Код: Выделить всё

/** \ingroup avr_eeprom
    Write a byte \a __value to EEPROM address \a __p.
 */
void eeprom_write_byte (uint8_t *__p, uint8_t __value);

/** \ingroup avr_eeprom
    Write a word \a __value to EEPROM address \a __p.
 */
void eeprom_write_word (uint16_t *__p, uint16_t __value);


Пи.Си.Пи.Си.

Код: Выделить всё

// Функция сброса пароля в 0000
void clear_password(void)
{
   //uint8_t *i=0;
   uint16_t i=0;
   while(i<4)
   {
      eeprom_write_byte((uint16_t)i,0x30);
      i++;
   }
}


А в ответ
Warning 2 passing argument 1 of '__eewr_byte_m8a' makes pointer from integer without a cast [enabled by default] :dont_know:
Я не волшебник, я только лечусь
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Вонинг и EEPROM Mega8A

Сообщение ARV »

Может, вам литературу почитать про указатели?
В последнем примере вы переменную uint16_t принудительно приводите к типу uint16_t, хотя функция ждёт указатель на байт, о чем и варнингует компилятор
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
YS
Друг Кота
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05
Контактная информация:

Re: Вонинг и EEPROM Mega8A

Сообщение YS »

А вот на счет 16 битных указателей я не знал. Надо это дела запомнить.


Это написано в avr-libc reference.

У каждой архитектуры есть свой размер указателя. Он определяется пределом адресуемой памяти. Если указатель шестнадцатибитный, то, очевидно, памяти может быть максимум 64 кБ. Для AVR этого более чем достаточно (на моделях с большим количеством переключаются страницы памяти).

На x86 размер указателя 32 бита, потому и памяти может быть не более 4 ГБ. :))

А в ответ
Warning 2


Звездочку забыли. :wink:
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Аватара пользователя
Gurvinok
Нашел транзистор. Понюхал.
Сообщения: 198
Зарегистрирован: Вт ноя 07, 2006 00:09:58
Откуда: Москва
Контактная информация:

Re: Вонинг и EEPROM Mega8A

Сообщение Gurvinok »

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

Код: Выделить всё

void eeprom_write_byte (uint8_t *__p, uint8_t __value);

Хотя это логично, так как у 8 меги 512 байт и однобайтовым указателем не отделаться.
Я не волшебник, я только лечусь
Аватара пользователя
YS
Друг Кота
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05
Контактная информация:

Re: Вонинг и EEPROM Mega8A

Сообщение YS »

но даже с ней не работает


Ох. Правда, почитайте про указатели.

Ваш код должен выглядеть так:

Код: Выделить всё

// Функция сброса пароля в 0000
void clear_password(void)
{
   uint16_t i=0;

   while(i<4)
   {
      eeprom_write_byte((uint8_t *)i,0x30);
      i++;
   }
}


(uint8_t *) - шестнадцатибитный указатель на восьмибитное значение.

(uint16_t *) - шестнадцатибитный указатель на шестнадцатибитное значение.

(uint32_t *) - шестнадцатибитный указатель на тридцатидвухбитное значение.

(void *) - шестнадцатибитный указатель, просто указатель на что угодно.

eeprom_write_byte((uint16_t)i,0x30); - вы пытаетесь насильно запихать переменную туда, где компилятор ждет указатель, о чем он вам и сообщает.

eeprom_write_byte((uint16_t *)i,0x30); - вы пытаетесь сказать, что ваше 0x30 на самом деле 0x0030 (понятно почему?).

eeprom_write_byte((uint8_t *)i,0x30); - правильно. i - шестнадцатибитное значение, которое мы приводим к указателю на восьмибитное значение. Все ОК.
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Аватара пользователя
Gurvinok
Нашел транзистор. Понюхал.
Сообщения: 198
Зарегистрирован: Вт ноя 07, 2006 00:09:58
Откуда: Москва
Контактная информация:

Re: Вонинг и EEPROM Mega8A

Сообщение Gurvinok »

Все далеко не ОК.
Warning 1 passing argument 1 of '__eewr_byte_m8a' from incompatible pointer type [enabled by default]

Если бы все было ОК, я бы тогда не кипятился.
Я не волшебник, я только лечусь
Аватара пользователя
YS
Друг Кота
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05
Контактная информация:

Re: Вонинг и EEPROM Mega8A

Сообщение YS »

Если бы все было ОК, я бы тогда не кипятился.


Еще раз проверьте написанное.

uint16_t i;

но далее:

(uint8_t *)i

Это важно. Указатель шестнадцатибитный, но указывает он на восьмибитное значение! Посмотрите мое сообщение выше внимательно.

Вы путаете тип указателя и тип того, на что он указывает.
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Аватара пользователя
Gurvinok
Нашел транзистор. Понюхал.
Сообщения: 198
Зарегистрирован: Вт ноя 07, 2006 00:09:58
Откуда: Москва
Контактная информация:

Re: Вонинг и EEPROM Mega8A

Сообщение Gurvinok »

Я понял. Я даже скопировал код и верхнего сообщения. Именно eeprom_write_byte((uint8_t*)i,0x30); Все равно это предупреждение. Я уже разобрался с указателями, но эта сволочь все равно предупреждает.

(uint8_t *) - шестнадцатибитный указатель на восьмибитное значение.

(uint16_t *) - шестнадцатибитный указатель на шестнадцатибитное значение.

(uint32_t *) - шестнадцатибитный указатель на тридцатидвухбитное значение.

(void *) - шестнадцатибитный указатель, просто указатель на что угодно.

Зы, а вот за это спасибо! Я еще нигде про такое не встречал. Всегда думал что uint8_t = unsigned char и т.д.
Я не волшебник, я только лечусь
Аватара пользователя
YS
Друг Кота
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05
Контактная информация:

Re: Вонинг и EEPROM Mega8A

Сообщение YS »

Проверьте свой код. Возможно, проблема в ваших заголовочных файлах?

Я скомпилировал у себя:

Спойлер

Код: Выделить всё

/*
 */

#include <avr/io.h>
#include <avr/eeprom.h>

void clear_password(void)
{
   uint16_t i=0;

   while(i<4)
   {
      eeprom_write_byte((uint8_t *)i,0x30);
      i++;
   }
}

int main(void)
{

    clear_password();
    // Insert code

    while(1)
    ;

    return 0;
}



Вывод компилятора:

Спойлер

Код: Выделить всё

---------- Build: Release in t_avr ----------

[ 50,0%] Compiling: main.c
[100,0%] Linking console executable: bin\Release\t_avr.elf
Output size is 1,81 KB
[ 16,7%] Running project post-build steps
[ 33,3%] avr-size --mcu=atmega8 --format=avr bin\Release\t_avr.elf
AVR Memory Usage
----------
Device: atmega8
Program:     130 bytes (1.6% Full)
(.text + .data + .bootloader)
Data:          0 bytes (0.0% Full)
(.data + .bss + .noinit)
[ 50,0%] avr-objcopy -O ihex -R .eeprom -R .eesafe bin\Release\t_avr.elf bin\Release\t_avr.elf.hex
[ 66,7%] avr-objcopy --no-change-warnings -j .eeprom --change-section-lma .eeprom=0 -O ihex bin\Release\t_avr.elf bin\Release\t_avr.elf.eep.hex
[ 83,3%] avr-objcopy -O binary -R .eeprom -R .eesafe bin\Release\t_avr.elf bin\Release\t_avr.elf.bin
[100,0%] avr-objcopy --no-change-warnings -j .eeprom --change-section-lma .eeprom=0 -O binary bin\Release\t_avr.elf bin\Release\t_avr.elf.eep.bin
cmd /c "avr-objdump -h -S bin\Release\t_avr.elf > bin\Release\t_avr.elf.lss"
Process terminated with status 0 (0 minutes, 0 seconds)
0 errors, 0 warnings


- 0 errors, 0 warnings.

Компилятор AVR-GCC, WinAVR 20100110.

Всегда думал что uint8_t = unsigned char и т.д.


Определим uint16_t i; Теперь:

(uint8_t)i - "компилятор, обрежь все кроме младшего байта от i и используй оставшиеся 8 бит в выражении"
(uint8_t *)i - "компилятор, значение i - адрес восьмибитного значения. Используй значение i в выражении как адрес."

Пример - разыменование:

*((uint8_t *)i) - "компилятор, в i лежит адрес восьмибитного значения. Возьми это восьмибитное значение и используй в выражении."
*((uint32_t *)i) - "компилятор, в i лежит адрес тридцатидвухбитного значения. Возьми это тридцатидвухбитное значение и используй в выражении."

Разрядность указателя всегда одинакова и определяется платформой. А указывать он может на все что угодно.
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Вонинг и EEPROM Mega8A

Сообщение ARV »

Gurvinok писал(а):Всегда думал что uint8_t = unsigned char
char не всегда 8 бит :))) поэтоу и ввели тип, который точно 8 бит всегда.

YS писал(а):(void *) - шестнадцатибитный указатель, просто указатель на что угодно.
по стандарту Си этот тип указателя совместим с любым иным типом указателей, чем можно пользоваться для исключения варнингов :)))
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
Gurvinok
Нашел транзистор. Понюхал.
Сообщения: 198
Зарегистрирован: Вт ноя 07, 2006 00:09:58
Откуда: Москва
Контактная информация:

Re: Вонинг и EEPROM Mega8A

Сообщение Gurvinok »

Заработало... После того как создал новый проект и переписал все с нуля. Че за глюк так и не понял. Но все равно спасибо, очень полезная информация.
Я не волшебник, я только лечусь
Аватара пользователя
YS
Друг Кота
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05
Контактная информация:

Re: Вонинг и EEPROM Mega8A

Сообщение YS »

После того как создал новый проект и переписал все с нуля.


Да, у меня такое тоже пару раз бывало. Видимо, глюки IDE в работе с проектом. :dont_know:
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Аватара пользователя
Gurvinok
Нашел транзистор. Понюхал.
Сообщения: 198
Зарегистрирован: Вт ноя 07, 2006 00:09:58
Откуда: Москва
Контактная информация:

Re: Вонинг и EEPROM Mega8A

Сообщение Gurvinok »

Ладно. Пойду искать очередные грабли. :))
Я не волшебник, я только лечусь
Ответить

Вернуться в «AVR»