|
|
  |
WINAVR: pgmspace, eeprom, отражаем актуальные проблемы |
|
|
|
Apr 8 2008, 18:50
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Предлагаю в этой ветке отражать передовые методы работы с pgmspace.h и eeprom.h Может, потом закрепить тему. Тем более, что видны динамичные изменения в этой области. Для начала. WINAVR-20071221 + Avr Studio 4.13 sp2 build 571 Делаю большой проект. Выложить не могу. Вкратце суть проблемы. Использую хедер, в котором сведены вместе все параметры, хранящиеся в EEPROM paramset.h Код #ifndef PARAMSET_H #define PARAMSET_H 1 EEMEM uint16_t nominal_rpm = 500; EEMEM uint8_t amplitude = 208; ................... etc #endif Хедер включается в разные модули. Их много. Везде константы из еепрома пользуются популярностью  И, BTW, надо иметь на выходе файл *.eep для начальной заливки. Для того, чтобы все работало, приходится объявлять параметры дважды - в основном модуле с инициализацией, а в остальных - как extern, т.е. Код #ifndef PARAMSET_H #define PARAMSET_H 1 #ifdef _IN_MAIN_ EEMEM uint16_t nominal_rpm = 500; EEMEM uint8_t amplitude = 208; ................... etc #else extern EEMEM uint16_t nominal_rpm; extern EEMEM uint8_t amplitude; ................... etc #endif
#endif Потом, в основной программе Код #define _IN_MAIN_ 1 #include "paramset.h" Иначе - чушь в распределении адресов. Как избежать двойного объявления переменных в приведенном примере, ессно, без использования макросов? Возможно ли это вообще?
|
|
|
|
|
Apr 8 2008, 19:16
|

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

|
Цитата(_Pasha @ Apr 8 2008, 21:50)  Как избежать двойного объявления переменных в приведенном примере, ессно, без использования макросов? Возможно ли это вообще? Объединить их в структуру: Код config.h: #ifndef CONFIG_H__ #define CONFIG_H__ #include <stdint.h> #include <avr/eeprom.h>
struct cfg_t { uint16_t Channel_Code; uint16_t Tx_Period; uint8_t Tx_Repeats; uint16_t Cycle_Len; uint16_t Cycle_Pos; uint8_t Sec_TimeSlot; }__attribute__((__packed__,__aligned__(1)));
extern EEMEM cfg_t Config_ee; #endif // CONFIG_H__
config.c: #include "config.h"
EEMEM cfg_t Config_ee = { 1, 2, 3, 4, };
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Apr 8 2008, 20:40
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(Сергей Борщ @ Apr 8 2008, 23:16)  Объединить их в структуру +1 у меня примерно так же: Код typedef struct { WORD Resets;
DWORD RUNTime;
WORD SysTickOverlapErrors;
WORD INTErrors;
WORD StackLeft;
WORD MinimumStackLeft;
WORD ADCErrors;
WORD EEPROMErrors;
WORD CRC16;
}TEEPROMStatisticBase;
TEEPROMBase EE[2] __attribute__ ((section (".eeprom")))= { { // первая копия 0xAA, // Bad { 1, // Resets 0, // RUNTime 0, // SysTickOverlapErrors 0, // INTErrors STACK_SIZE, // StackLeft STACK_SIZE, // MinimumStackLeft 0, // ADCErrors 0, // EEPROMErrors 0x7429, // CRC16 }, ............................................. .............................................
|
|
|
|
|
Apr 8 2008, 23:42
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Как автор темы позволю себе подытожить по этому примеру - Нечитабельность при инициализации достаточно большой структуры. - Постоянное добавление имени владельца структуры при обращении + Структура позволяет решить проблему описаний и легко заливать defaults из флеша. Если же последнее не предусмотрено, то Макрос, который напрашивается здесь, имеет вид Код #define PARAM(_TYPE_ , _NAME_ , _INIT_) #ifdef _IN_MAIN_\ EEMEM _TYPE_ _NAME_ = _INIT_\ #else\ extern EEMEM _TYPE_ _NAME_\ #endif НаписАл я эту довольно банальную вещь как раз для того, чтобы ее покритиковали.
|
|
|
|
|
Apr 9 2008, 06:47
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(_Pasha @ Apr 9 2008, 02:42)  - Нечитабельность при инициализации достаточно большой структуры. C99 позволяет Код typedef struct { uint8_t a; int b; char c; } cfg_t;
// даже порядок инициализации не важен, всё будет правильно cfg_t cfg EEMEM = { .b = -1 , .c = '2' , .a = 3 };
char arr[5] EEMEM = { [2] = 'c' , [4] = 'e' , [0] = 'a' // элементы массива 1 и 3 инициализированы нулями по умолчанию }; К сожалению, в С++ такого нет. Цитата(_Pasha @ Apr 9 2008, 02:42)  Макрос, который напрашивается здесь, имеет вид Код #define PARAM(_TYPE_ , _NAME_ , _INIT_) #ifdef _IN_MAIN_\ EEMEM _TYPE_ _NAME_ = _INIT_\ #else\ extern EEMEM _TYPE_ _NAME_\ #endif Нельзя делать проверку условия внутри макроса. И нельзя всё одной строкой. Надо так: Код #ifdef _IN_MAIN_ #define PARAM(_TYPE_ , _NAME_ , _INIT_) \ EEMEM _TYPE_ _NAME_ = _INIT_ #else #define PARAM(_TYPE_ , _NAME_ , _INIT_) extern EEMEM _TYPE_ _NAME_ #endif Кстати, С99 позволяет это даже не при инициализации делать, можно делать эдакие "литералы" Код void foo(cfg_t *p) { *p = (cfg_t){ .c = 'c', .b = -1, .a = 0 }; // ну или *p = (cfg_t){ 0, -1, 'c'}; для тех, кто помнит порядок полей;-) } вместо Код void foo(cfg_t *p) { p->c = 'c'; p->b = -1; p->a = 0; } И avr-gcc чудесно такое компилирует, я иногда пользуюсь. А потом как вспомню, что далеко не все так стандарт поддерживают, как gcc, так и начинаю стараться не привыкать. Ну и С++ такого не позволяет... Даже с -std=gnu++98, не говоря уже о -std=c++98 --pedantic
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Apr 9 2008, 09:27
|
Знающий
   
Группа: Свой
Сообщений: 601
Регистрация: 22-09-05
Из: Kharkov
Пользователь №: 8 847

|
Цитата Код #ifndef PARAMSET_H #define PARAMSET_H 1 EEMEM uint16_t nominal_rpm = 500; EEMEM uint8_t amplitude = 208; ................... etc #endif А почему переменные объяляются в *.h файле? Например config.h Код #ifndef PARAMSET_H #define PARAMSET_H 1 extern EEMEM uint16_t nominal_rpm; extern EEMEM uint8_t amplitude; ................... etc #endif config.c Код #include "config.h" EEMEM uint16_t nominal_rpm = 500; EEMEM uint8_t amplitude = 208; А во всех остальных файлах просто Код #include "config.h"
--------------------
- А мораль отсюда такова: всякому овощу свое время. Или, хочешь, я это сформулирую попроще: никогда не думай, что ты иная, чем могла бы быть иначе, чем будучи иной в тех случаях, когда иначе нельзя не быть. © Lewis Carroll. Alice's adventures in wonderland.
|
|
|
|
|
Apr 9 2008, 20:48
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(_Pasha @ Apr 9 2008, 17:38)  +1000 Потому что поддерживаемые в gcc операции с EEPROM тоже, мягко говоря, уникальны  Так что с подводной лодки далеко не уплывешь... и можно и привыкнуть, ничего страшного. Увы, это разные вещи. Одно дело чисто gcc-шные расширения, типа диапазонных case в switch и вложенных функций. Приятные, но абсолютно нестандартные. Не так и жалко. Другое дело - то, что с 1999 года в стандарте, уже скоро 10 лет, но от MS до IAR почти никто не поддерживает. Вот за это обидно. Вещи-то из СТАНДАРТА, а "виноват" потом окажется тот, кто этот стандарт поддержал.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|