|
|
  |
WinAVR-20080610, делимся впечатлениями |
|
|
|
Sep 25 2008, 11:25
|

Участник

Группа: Участник
Сообщений: 16
Регистрация: 27-04-05
Из: Воронеж
Пользователь №: 4 541

|
Цитата(Непомнящий Евгений @ Sep 25 2008, 14:56)  ну напишите руками приведение к тому типу, который ожидает eeprom_write_block - примерно так: eeprom_write_block (current_sensor_code, EEPROM_SENSOR2_ADR, (char*)8); Не, дык он же на 2-й аргумент функции ругается! Т.е. на EEPROM_SENSOR2_ADR, который выше обозначен как число 0x078. вот описание этой функции из доки: Цитата void eeprom_write_block (const void * pointer_ram, void * pointer_eeprom, size_t n)
Write a block of n bytes to EEPROM address pointer_eeprom from pointer_ram.
Сообщение отредактировал timex - Sep 25 2008, 11:30
|
|
|
|
|
Sep 25 2008, 11:45
|

Начинающий профессионал
    
Группа: Свой
Сообщений: 1 215
Регистрация: 25-10-06
Из: СПб
Пользователь №: 21 648

|
Достаточно распространенная ситуация, когда константы подставляются в вызов функции в том числе из макро. Лучше явно делать преобразование типа (как советует Непомнящий Евгений) для спокойной жизни. У Вас Цитата #define EEPROM_SENSOR2_ADR 0x078 // адрес хранения номера датчика Наверно, прошло бы без предупреждения, если не было бы ведущего нуля (0x78). Нет, не прошло бы. У Вас тип Код void , а это требует явного преобразования к типу используемой памяти. Посмотрел, как сам использовал Код uint8_t eeprom_buf[RECORD_SIZE]; /* Буфер блока данных */
int8_t eeprom_data_write(const int16_t address) /* Запись блока данных в EEPROM */ { int16_t tmp; if( (address > EEPMIN_ADDR) && (address < (EEPMAX_ADDR-RECORD_SIZE))) { tmp = address; eeprom_busy_wait(); eeprom_write_block(eeprom_buf, (uint16_t*)tmp, RECORD_SIZE); return EXIT_SUCCESS; } return EXIT_FAILUREN; /* Bad address */ } Явное преобразование типа, а заодно и контроль допустимых адресов записи
--------------------
Наука изощряет ум; ученье вострит память. Козьма Прутков
|
|
|
|
|
Sep 25 2008, 12:16
|

Участник

Группа: Участник
Сообщений: 16
Регистрация: 27-04-05
Из: Воронеж
Пользователь №: 4 541

|
mdmitry, да, спасиб. при такой записи строки Код eeprom_write_block (current_sensor_code, (unsigned int*) EEPROM_SENSOR2_ADR, 8); варнинг не выдаётся. Вдогонку! Обратил внимание, что в окне сообщений компилятора при Rebuld All выдаётся следующее (помечено "!!!!!!!!>"): Код Build started 25.9.2008 at 17:14:51 avr-gcc.exe -I"C:\AVRlib" -mmcu=atmega16 -Wall -gdwarf-2 -std=gnu99 -fgnu89-inline -O2 -fsigned-char -MD -MP -MT main.o -MF dep/main.o.d -c ../main.c !!!!!!!!> C:\WINDOWS\Temp/ccFQajf5.s: Assembler messages: !!!!!!!!> C:\WINDOWS\Temp/ccFQajf5.s:2433: Warning: expression dangerous with linker stubs !!!!!!!!> C:\WINDOWS\Temp/ccFQajf5.s:2434: Warning: expression dangerous with linker stubs avr-gcc.exe -mmcu=atmega16 main.o -o sensor_ibutton.elf avr-objcopy -O ihex -R .eeprom sensor_ibutton.elf sensor_ibutton.hex avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex sensor_ibutton.elf sensor_ibutton.eep || exit 0
AVR Memory Usage ---------------- Device: atmega16
Program: 4506 bytes (27.5% Full) (.text + .data + .bootloader) Data: 158 bytes (15.4% Full) (.data + .bss + .noinit)
Build succeeded with 0 Warnings... файлов таких в c:\windows\temp нету... где копать?
Сообщение отредактировал timex - Sep 25 2008, 13:14
|
|
|
|
|
Sep 25 2008, 13:23
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(timex @ Sep 25 2008, 16:16)  1. по поводу Linker Stubs - это глюки. Здесь уже была тема. Можно (по крайней мере, в предыдущей winavr 2007) не обращать внимания. 2. Вернемся к Код eeprom_write_block (current_sensor_code, (unsigned int*) EEPROM_SENSOR2_ADR, 8); Вроде как правильно, но Вы уверены, что Вам нужен именно (unsigned int*) ?  Имхо, бардака в голове только прибавилось.
|
|
|
|
|
Sep 25 2008, 13:31
|

Начинающий профессионал
    
Группа: Свой
Сообщений: 1 215
Регистрация: 25-10-06
Из: СПб
Пользователь №: 21 648

|
Цитата(_Pasha @ Sep 25 2008, 17:23)  1. по поводу Linker Stubs - это глюки. Здесь уже была тема. Можно (по крайней мере, в предыдущей winavr 2007) не обращать внимания. 2. Вернемся к Код eeprom_write_block (current_sensor_code, (unsigned int*) EEPROM_SENSOR2_ADR, 8); Вроде как правильно, но Вы уверены, что Вам нужен именно (unsigned int*) ?  Имхо, бардака в голове только прибавилось. 1. Это временные файлы, они удаляются после выполнения необходимых действий. 2. Полная аналогия относительно доступа к областям памяти по отношению к функциям типа Код memmove, memcpy и другим (IMHO). Нужен ведь адрес ячейки памяти, а их больше чем 256.
--------------------
Наука изощряет ум; ученье вострит память. Козьма Прутков
|
|
|
|
|
Sep 25 2008, 13:44
|

Участник

Группа: Участник
Сообщений: 16
Регистрация: 27-04-05
Из: Воронеж
Пользователь №: 4 541

|
Цитата(_Pasha @ Sep 25 2008, 17:23)  1. по поводу Linker Stubs - это глюки. Здесь уже была тема. Можно (по крайней мере, в предыдущей winavr 2007) не обращать внимания. Сейчас проверил - появляется только при оптимизации -O1, -O2, -O3. При -Оs и -O0 такого нету... (WinAVR-20071221). Обновил до 20080512 - глюк перестал проявлятся! Цитата(_Pasha @ Sep 25 2008, 17:23)  2. Вернемся к Код eeprom_write_block (current_sensor_code, (unsigned int*) EEPROM_SENSOR2_ADR, 8); Вроде как правильно, но Вы уверены, что Вам нужен именно (unsigned int*) ?  Имхо, бардака в голове только прибавилось. Упс, от созерцания прекращения выдачи варнингов незаметил  . Переправил на "(unsigned char*)". Но в данном случае, думается, между int и char нет разницы, т.к. в описании функции стоит "void"...?
Сообщение отредактировал timex - Sep 25 2008, 13:57
|
|
|
|
|
Sep 25 2008, 14:19
|

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

|
Цитата(timex @ Sep 25 2008, 16:44)  Переправил на "(unsigned char*)". Но в данном случае, думается, между int и char нет разницы, т.к. в описании функции стоит "void"...? Если вы хотите писать понятно, то приведите к указателю на тот тип, данные которого записываете, т.е. к тому типу, на который у вас указывает current_sensor_code. Если хотите чтобы было "просто правильно", то приведите к тому типу, который ожидает функция, т.е. к void *. Если хотите через полгода-год, смотря в этот кусок кода, мучительно думать "а какого черта здесь приводится именно к unsigned char *, а не к unsigned int *?" - оставьте так, как есть. P.S. параметр функции объявлен как void *, потому что к void * неявно приводится любой указатель.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 25 2008, 15:02
|

Начинающий профессионал
    
Группа: Свой
Сообщений: 1 215
Регистрация: 25-10-06
Из: СПб
Пользователь №: 21 648

|
Цитата(Сергей Борщ @ Sep 25 2008, 18:19)  Если вы хотите писать понятно, то приведите к указателю на тот тип, данные которого записываете, т.е. к тому типу, на который у вас указывает current_sensor_code. Если хотите чтобы было "просто правильно", то приведите к тому типу, который ожидает функция, т.е. к void *. Если хотите через полгода-год, смотря в этот кусок кода, мучительно думать "а какого черта здесь приводится именно к unsigned char *, а не к unsigned int *?" - оставьте так, как есть.
P.S. параметр функции объявлен как void *, потому что к void * неявно приводится любой указатель. Сергей Борщ, в функциях типа Код memmove и др. все же делается приведение к тому типу данных, который используется. Согласен, мой пример требует корректировки с точки зрения соблюдения всех стандартов.
--------------------
Наука изощряет ум; ученье вострит память. Козьма Прутков
|
|
|
|
|
Sep 25 2008, 18:17
|

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

|
Цитата(mdmitry @ Sep 25 2008, 18:02)  в функциях типа Код memmove и др. все же делается приведение к тому типу данных, который используется. Здесь какое-то недопонимание. Внутри функции memmove, memset и т.п. переданный указатель типа void * действительно приводится к тому типу, единицами которого осуществляется копирование, стирание (чаще всего к байту). Но сам параметр функции имеет тип void * чтобы при вызове этой функции можно было использовать любой указатель, не делая явного приведения: Код int var1; unsigned char var2; struct struct_t { unsigned int a; unsigned long b; } var3;
void Test() { memset(&var1, 0, sizeof(var1)); memset(&var2, 0, sizeof(var2)); memset(&var3, 0, sizeof(var3)); }
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 25 2008, 19:46
|

Начинающий профессионал
    
Группа: Свой
Сообщений: 1 215
Регистрация: 25-10-06
Из: СПб
Пользователь №: 21 648

|
Цитата(Сергей Борщ @ Sep 25 2008, 22:17)  Здесь какое-то недопонимание. Внутри функции memmove, memset и т.п. переданный указатель типа void * действительно приводится к тому типу, единицами которого осуществляется копирование, стирание (чаще всего к байту). Но сам параметр функции имеет тип void * чтобы при вызове этой функции можно было использовать любой указатель, не делая явного приведения Насколько я понимаю, в прототипе указатели на источник и приемник имеют тип void* с целью дать программисту возможность явного приведения типа указателей как для удобства (работа с конкретными типами данных), так и для контроля типов самим компилятором. Предполагаю, что приведение типа может улучшить как скорость работы функции, так и эффективность использования памяти (дырки и выравнивание). Исходный код этих функций я не смотрел (неверно, неплохо и ознакомиться  ).
--------------------
Наука изощряет ум; ученье вострит память. Козьма Прутков
|
|
|
|
|
Sep 25 2008, 20:13
|
Местный
  
Группа: Свой
Сообщений: 381
Регистрация: 27-07-08
Из: теплые края
Пользователь №: 39 233

|
Цитата(mdmitry @ Sep 25 2008, 22:46)  Насколько я понимаю, в прототипе указатели на источник и приемник имеют тип void* с целью дать программисту возможность явного приведения типа указателей как для удобства (работа с конкретными типами данных), так и для контроля типов самим компилятором. Нет. С точки зрения контроля типов void* - худшее что можно придумать. Цитата Предполагаю, что приведение типа может улучшить как скорость работы функции, так и эффективность использования памяти (дырки и выравнивание). Исходный код этих функций я не смотрел (неверно, неплохо и ознакомиться  ). Нет. С точки зрения компилятора (точнее ассемблера) не имеет никакой разницы, указатель на какой тип используется.
|
|
|
|
|
Sep 30 2008, 18:24
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Цитата(_Pasha @ Sep 30 2008, 11:06)  Хочу спросить: почему в хедерах контроллеров не прижилось описание SFR через структуры с битовыми полями? aesok - Вы ближе всего к идеологии...  Наверное по той-же самой причине по которой выкинули sbi и cbi, с помощью таких структур можно красиво изменять один бит, но если вам нужно сразу установить несколько бит в регистре, то код получается избыточным (нужно последовательно устанавливать каждый бит). Анатолий.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|