Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как разместить массив структур во флеш памяти (WinAVR)?
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > MCS51, AVR, PIC, STM8, 8bit
smac
Доброго времени суток, дамы и господа!
Есть такой вопрос: как разместить массив структур приведенный ниже во флеш памяти микроконтроллера (например ATMega32) с помощью компилятора WinAVR 20081205, желательно так, чтобы обеспечить удобную работу с этим массивом?
Код
    struct at_cmd cmd_set[]={
                                   {"A/",         cmd_a_},
                                   {"AT",         cmd_at},
                                   {"ATA",     cmd_ata},
                                   {"ATB",        cmd_atb},
                                   {"ATC",        cmd_atc},
                                   {"ATD",        cmd_atd}
                               };

Начал изучать С (пока читаю K&R и параллельно пробую применить к AVR, иногда заглядывая в документацию компилятора) хотелось бы узнать как правильно решить приведенную задачу.
Попытался проделать самостоятельно получилось вот так.
CODE
/* Ниже приведена попытка заменить приведенный массив структур массивом
структур, расположенным во флеш памяти*/
#include <avr/io.h>
#include <avr/pgmspace.h>

const char a__mnem[] PROGMEM = "A/"; // Записываем во флеш мнемоники команд
const char at_mnem[] PROGMEM = "AT";
const char ata_mnem[] PROGMEM = "ATA";
const char atb_mnem[] PROGMEM = "ATB";
const char atc_mnem[] PROGMEM = "ATC";
const char atd_mnem[] PROGMEM = "ATD";


int cmd_a_ (char*param); // Объявляем функции-обработчики команд
int cmd_at (char*param);
int cmd_ata (char*param);
int cmd_atb (char*param);
int cmd_atc (char*param);
int cmd_atd (char*param);

struct at_cmd{ PGM_P cmd_mnem;
int (*cmd_func)(char *);}; // Объявляем вид структуры at_cmd

struct at_cmd cmd_set [] PROGMEM ={ // Записываем во флеш массив структур at_cmd
{a__mnem, cmd_a_},
{at_mnem, cmd_at},
{ata_mnem, cmd_ata},
{atb_mnem, cmd_atb},
{atc_mnem, cmd_atc},
{atd_mnem, cmd_atd},
};


int main(void) // Пример работы (гипотетический)
{
struct at_cmd temp_cmd; // объявляем структуру с которой будем работать (буфер для 1 элемента
// массива структур расположенного во флеш памяти)
char i,s, par[8];
for (i=0; i<(sizeof(cmd_set)/sizeof(cmd_set[0]));i++){
memcpy_P(&temp_cmd, &cmd_set[i], sizeof(cmd_set[0])); // Копируем структуру из массива ( во флеш памяти) во временную
s=pgm_read_byte(temp_cmd.cmd_mnem); // Читаем первый символ мне моники коман ды
(*temp_cmd.cmd_func)(&par[0]); // Вызываем функцию-обработчик команды
}

return 0;
}

int cmd_a_ (char*param){ // функции-обработчики (тоже гипотетические)
return 10;
}

int cmd_at (char*param){
return 20;
}

int cmd_ata (char*param){
return 30;
}

int cmd_atb (char*param){
return 40;
}
int cmd_atc (char*param){
return 50;
}
int cmd_atd (char*param){
return 60;
}

Уверен, что полученное решение криво и неэлегантно, поэтому прошу подсказать знающих как оно должно быть на самом деле.
demiurg_spb
По работе с flash достаточно адекватно написано.
Что можно доработать:
1) Гораздо читабельнее если объявлены типы структур и функций:
Код
typedef void(*callback_t)(const char* name); // объявление типа функции

typedef struct
{
    const char* name;   // flash ptr
    uint8_t     age;      // age
    callback_t  make_manicure; // some function
} abc_t;

const char PROGMEM name_sasha[] = "Sasha";
const char PROGMEM name_masha[] = "Masha";

const abc_t PROGMEM abc1 = {name_sasha, 17,  NULL};
const abc_t PROGMEM abc2 = {name_masha, 15,  my_func};

2) Обработчик мог бы стать элегантнее:
Код
#define pgm_read_ptr(address)           ((void*)pgm_read_word(address))
void do_abc(const abc_t* abc) // abc - это указатель на структуру в ПЗУ не в RAM
{
    callback_t manicure_func = pgm_read_ptr(&abc->make_manicure);
    if (manicure_func)  // маникюр только для девочек:)
    {
        manicure_func( pgm_read_ptr(&abc->name) );
    }
}
    do_abc(&abc1);
    do_abc(&abc2);
А ещё лучше в callback передавать указатель на структуру в ПЗУ или указатель на ПЗУ указатель на сроку ПЗУ...
Так код будет компактнее. Но не всё сразу, а то Ваш мозг не выдержит перегрузокsmile.gif
defunct
Цитата(demiurg_spb @ Feb 17 2009, 22:18) *
1) Гораздо читабельнее если объявлены типы структур и функций:

Ну чтобы совсем элегантно - не брезговать объявлять тэг структуры (облегчает работу парсерам) и сразу объявлять тип-указатель на эту структуру:

Код
typedef struct tag<NEWTYPENAME>
{
     struct tag<NEWTYPENAME> *pNext;   // <-- практическое применение тэг'а
....
} <NEWTYPENAME>, *P<NEWTYPENAME>;
smac
Спасибо demiurg_spb и defunct буду учиться. На самом деле пока не совсем понятно о чем речь, ибо я как-то урывками начал WinAVR пользовать, но я обязательно разберусь rolleyes.gif .
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.