реклама на сайте
подробности

 
 
6 страниц V  < 1 2 3 4 5 > »   
Reply to this topicStart new topic
> Порты AVR и компиляция
singlskv
сообщение Sep 28 2007, 22:37
Сообщение #31


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(SasaVitebsk @ Sep 28 2007, 00:02) *
Выпад по поводу данных в EEPROM и FLASH - явно бредовый. Удобная вещь - она всегда удобная.

Зачем мне для обращения к Flash переменной обращаться ч/з подпрограмму?

Это просто яркий пример как можно всё с ног на голову поставить.
Давайте посмотрим, на Вашем любимом IAR:
Код
#include <string.h>

__eeprom char eeString[]="Prived !";
char String[10]="ABCDEFGHIJ";

int main(void)
{
  memcpy(String,  (void const *)eeString, 10);
  memcpy((void *)eeString, String, 10);
  return 0;
}

Скомпилируйте этот код и пройдитесь по нему отладчиком,
я думаю что результат Вас сильно порадует, особенно второй memcpy biggrin.gif

P.S Тока не нужно мне рассказывать что этот пример высосан из пальца...
Прямое преобразование типов конечно вставлено специально,
тока где и когда Вы наткнетесь на такой результат в реальной программе будете знать
тока Вы и Ваш доктор в дурке (после отладки такого кода) smile.gif
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Sep 28 2007, 23:06
Сообщение #32


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Преимущества они и в Африке преимущества.

Вы прекрасно понимаете, что ими можно не пользоваться. Иными словами, если вас не устраивает по какой то причине прямое обращение к EEPROM либо FLASH памяти, вы можете использовать обращение аналогичное применяемому в WinAVR. Никаких проблем не вижу. Более того вы, естественно можете переписать и сами процедуры обращения. Или использовать свои библиотеки.

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

Трагедии никакой здесь нет. Я думаю в WinAVR тоже найдётся немало скелетов в шкафу.

Я, совершенно не приумаляю достоинства WinAVR. Я просто отметил что им не так уж просто пользоваться и привёл свои аргументы. Исключительно исходя из своих наблюдений. Мне оказалось проще и приятнее работать в IAR. В то же время, если человек свободно программирует и в IAR и в WinAVR, то ему это только плюс. Знаний, как известно, лишних не бывает.
Go to the top of the page
 
+Quote Post
SergeiCh
сообщение Sep 29 2007, 07:05
Сообщение #33


Частый гость
**

Группа: Участник
Сообщений: 99
Регистрация: 22-03-07
Из: Novosibirsk
Пользователь №: 26 415



Если хочется писать PORTB_0 = 1, это можно сделать средствами любого ANSI C совместимого компилятора. Например, как в SDCC для HC08:

Код
struct __hc08_bits
{
  unsigned int bit0:1;
  unsigned int bit1:1;
  unsigned int bit2:1;
  unsigned int bit3:1;
  unsigned int bit4:1;
  unsigned int bit5:1;
  unsigned int bit6:1;
  unsigned int bit7:1;
};

#define PTB PORTB              /* Alias for PORTB */
  #define PTB0 ((struct __hc08_bits *)(&PTB))->bit0
  #define PTB1 ((struct __hc08_bits *)(&PTB))->bit1
  #define PTB2 ((struct __hc08_bits *)(&PTB))->bit2
  #define PTB3 ((struct __hc08_bits *)(&PTB))->bit3
  #define PTB4 ((struct __hc08_bits *)(&PTB))->bit4
  #define PTB5 ((struct __hc08_bits *)(&PTB))->bit5
  #define PTB6 ((struct __hc08_bits *)(&PTB))->bit6
  #define PTB7 ((struct __hc08_bits *)(&PTB))->bit7

Изменил одну строчку, чтобы работало для AVR. PTB0 = 1, и даже PTB0 = PTB2 будет работать без проблем, причем для всех портов (где-то как sbi/cbi, где-то lds + sts). Написали один раз что-нибудь типа bitio.h, и пользуйтесь. Но лучше (надеюсь, грамотные люди со мной согласятся) для конкретной задачи шевеления ногой писать макросы или online функции типа led_busy_on(), led_busy_off() и в коде использовать уже их. led_busy = 1, IMHO, хуже, разве что led_busy = ON smile.gif ...

Операцию = можно перегрузить для eeprom, но это уже будет C++.

Про генерацию кода ничего не скажу. Сам использую gcc для разных платформ, включая PC.
Go to the top of the page
 
+Quote Post
defunct
сообщение Sep 29 2007, 11:54
Сообщение #34


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(singlskv @ Sep 29 2007, 01:37) *
P.S Тока не нужно мне рассказывать что этот пример высосан из пальца...
Прямое преобразование типов конечно вставлено специально,
тока где и когда Вы наткнетесь на такой результат в реальной программе будете знать
тока Вы и Ваш доктор в дурке (после отладки такого кода) smile.gif

Ок, аналогичный пример:
Код
char Str[]="Hello";
char SomeChar;
int main(void)
{
     memcpy( (void *)SomeChar, Str, sizeof(Str));
}

Проблема здесь та же самая что и в вашем примере, и даже без переменных в eeprom.
Поэтому можете также вместе с доктором ковырять и этот код. Ибо когда нет понимания, что происходит в программе и что может происходить - забудьте про (void *).
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Sep 29 2007, 12:46
Сообщение #35


Гуру
******

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



Цитата(singlskv @ Sep 29 2007, 01:37) *
Прямое преобразование типов конечно вставлено специально,
И совершенно без понимания. Отсюда сюрпризы и жалобы на компилятор. Подсказка - любой указатель (на RAM) приводится к void * автоматически. Имеено поэтому в прототипе данной функции используется указатель на void* а не на char*. А любой указатель на флеш автоматически приводится к void __flash *. Поэтому в прототипе memcpy_P в качестве источника использован void __flash *. Чтобы если вы ошибетесь - компилятор мог распознать эту ошибку. Аналогично с указателями на __eeprom. Если вы примените __eeprom указатель как аргумент memcpy, компилятор вам выругался, что вы хотите невозможного. Если после этого вы тупо делаете явное приведение (и тем самым отключаете контроль типов) - то кто же вам злобный буратина? Вот вам встречный пример:
Код
typedef struct
{
    uint8_t     ParamA;
    uint32_t    ParamB;
    my_struct_t ParamC;
}config_t;

config_t const __flash Defaults =
{
    1,
    0x12345678,
    {
        'a',
        1,
        2,
    }
};

struct
{
    config_t   Config;
    uint8_t    CRC;
} cfg_RAM, __eeprom cfg_EE;

void ReadConfig()
{
    cfg_RAM = cfg_EE;
    if( CRC(&cfg_RAM, sizeof(cfg_RAM)) != 0)
    {
        cfg_RAM = Defaults;
        cfg_RAM.CRC = CRC(&cfg_RAM.Config, sizeof(config_t))
        cfg_EE = cfg_RAM;
    }
}
Напишите с функциями то же самое. Как минимум код будет менее понятный и вы не обойдетесь без приведений типов - а они источник потенциальных ошибок, что вы нам продемонстрировали сами чуть выше.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
singlskv
сообщение Sep 29 2007, 17:21
Сообщение #36


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(defunct @ Sep 29 2007, 15:54) *
Ок, аналогичный пример:
Код
....................

Проблема здесь та же самая что и в вашем примере, и даже без переменных в eeprom.
Ну все таки не совсем одно и тоже, я свой пример показал только с точки зрения
потенциально проблемной части в использовании __eeprom, а в вашем примере просто
нарисован баг который из-за преобразования типов не смог поймать компилятор.

Насколько я знаю, в стандарте С вобще нет такого типа void __eeprom * smile.gif

А вот теперь представьте себе:
Код
__eeprom char eeString[]="Prived !";
char String[10]="ABCDEFGHI";
int Int=1;
long Long=2;

typedef struct
{
    void *ptr;
    int  size;
} SomeData;

SomeData* MassivHrenZnaetSKakimiDannimy[10];
......................
  {
    MassivHrenZnaetSKakimiDannimy[0].ptr = eeString;
    MassivHrenZnaetSKakimiDannimy[0].size = sizeof(eeString);
    MassivHrenZnaetSKakimiDannimy[1].ptr = String;
    MassivHrenZnaetSKakimiDannimy[1].size = sizeof(String);
    MassivHrenZnaetSKakimiDannimy[2].ptr = &Int;
    MassivHrenZnaetSKakimiDannimy[2].size = sizeof(Int);
    MassivHrenZnaetSKakimiDannimy[3].ptr = &Long;
    MassivHrenZnaetSKakimiDannimy[3].size = sizeof(Long);
.............................
.............................
.............................
    memcpy(KudatoTam,  MassivHrenZnaetSKakimiDannimy[x].ptr, MassivHrenZnaetSKakimiDannimy[x].size);
..........................
..........................
  }

Хрен знает какие данные оказались не совсем хрен знает какими, а все по тому что
кое кто придумал свой новый тип данных... __eeprom xxx
Go to the top of the page
 
+Quote Post
singlskv
сообщение Sep 29 2007, 18:42
Сообщение #37


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(Сергей Борщ @ Sep 29 2007, 16:46) *
И совершенно без понимания. Отсюда сюрпризы и жалобы на компилятор.
А я жаловался на компилятор ?
Нет, ну конечно было пару раз когда я указывал на проблемы с оптимизацией, но не более того...
Разговор о том что нету в С таких типов __flash xxx и что не стоит этими придуманными типами
пользоваться как обычными типами.
Цитата
Вот вам встречный пример:
Код
................
Напишите с функциями то же самое. Как минимум код будет менее понятный и вы не обойдетесь без приведений типов - а они источник потенциальных ошибок, что вы нам продемонстрировали сами чуть выше.
Менее понятен/более понятен, это все таки очень субъективные вещи,
для меня например значительно более понятным при работе с EEPROM является или
прямой вызов функций записи в него, или просто запуск записи с последующей проверкой
что запись уже закончилась. При этом вопросов с приведением типов обычно не стоит,
поскольку посредством вызова функции я четко указываю о своих намерениях.
Тот код который Вы привели конечно выглядит красиво, мой намного зануднее...
НО, объясните мне как Вы будете пользоваться такими присвоениями в следующей
ситуации:
Есть прога:
- все события(опросы) синхронизированны(системный тик) например с тактом 200-500мкс
- есть одно или несколько прерываний которые получают данные
- есть основной цикл который ведет обработку полученных в прерывании данных
- НУЖНО, не прерывая обработку, писать некоторые изменения соcтояния проги в EEPROM

Где в этой проге можно написать cfg_EE = cfg_RAM ?

Момент номер 2,
когда Вы пишите cfg_EE = cfg_RAM , Вы принудительно заставляете перезаписывать
в EEPROM даже те ячейки которые в данный момент не требуют модификации.
Этим Вы осознанно уменьшаете ресурс EEPROM.
Во всех моих занудных алгоритмах записи в EEPROM, перед тем как
записать байт из какой-то структуры в соответствующее место EEPROM происходит
чтение этого адреса и проверка на то, а нужно ли его вобще перезаписывать.

Как Вы думаете, в среднем, какой вариант общения с EEPROM будет более
быстрым и более надежным(в смысле ресурса EEPROM) ?
Go to the top of the page
 
+Quote Post
defunct
сообщение Sep 29 2007, 19:47
Сообщение #38


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(singlskv @ Sep 29 2007, 20:21) *
Ну все таки не совсем одно и тоже, я свой пример показал только с точки зрения
потенциально проблемной части в использовании __eeprom, а в вашем примере просто
нарисован баг который из-за преобразования типов не смог поймать компилятор.

В вашем примере баг абсолютно такой же как и в моем.
Ибо нефиг несовместимый тип приводить к PVOID.

Цитата
Хрен знает какие данные оказались не совсем хрен знает какими, а все по тому что
кое кто придумал свой новый тип данных... __eeprom xxx

В AVR три адресных пространства. Насколько это удобно или неудобно не вам судить, и не мне. Они просто есть, IAR дает нам простой инструмент доступа к этим адресным пространствам, если вам такой способ доступа не подходит - пользуйтесь другим, более сложным.


Цитата
для меня например значительно более понятным при работе с EEPROM является или
прямой вызов функций записи в него, или просто запуск записи с последующей проверкой
что запись уже закончилась.

Кому что.. Меня как правило интересует конечный результат, если воспользовавшись фичей X я смогу добиться конечного результата меньшим числом строк кода и не в ущерб наглядности, читабельности программы и скорости испольнения, то обязательно ей воспользуюсь (по крайней мере подумаю об ее использовании). Минусом будет только "Портируемость" внутри семейства и на другие многоадресные семейства МК, а на "протируемость" на одноадресные МК (напр ARM) оно вообще никак не повлияет.

Да и палку вы здесь перегибаете. Что может быть понятнее присваивания?
x = y;
Go to the top of the page
 
+Quote Post
sensor_ua
сообщение Sep 29 2007, 19:56
Сообщение #39


Профессионал
*****

Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387



Цитата
IAR дает нам простой инструмент доступа

Замечу, что чтение из "откуда-попало" куда удобнее (хотя производительность несколько ниже) при использовании указателей с модификатором __generic, реализация которого у IAR есть, а у остальных аналогичного, похоже, даже в проекте нет.


--------------------
aka Vit
Go to the top of the page
 
+Quote Post
singlskv
сообщение Sep 29 2007, 20:15
Сообщение #40


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(defunct @ Sep 29 2007, 23:47) *
Да и палку вы здесь перегибаете. Что может быть понятнее присваивания?
x = y;
Хорошо, будем говорить тока за себя,
лично мне очень не нравится ситуация когда
x=y; выполняется несколько сот наносекунд, а
e=k; (где e - eeprom) выполняется несколько миллисекунд.

Ну и остальные отрицательные стороны использования EEPROM как переменных я
уже описал выше.
Go to the top of the page
 
+Quote Post
defunct
сообщение Sep 29 2007, 20:20
Сообщение #41


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(singlskv @ Sep 29 2007, 23:15) *
e=k; (где e - eeprom) выполняется несколько миллисекунд.
Ну и остальные отрицательные стороны использования EEPROM как переменных я
уже описал выше.

Ну и что?! У eeprom еще и ресурс ограничен, такова уж особенность этой памяти.
100k раз запишете дальше пойдут сбои.
Какое это имеет отношение к удобному механизму обращения к этой памяти?

Не нравится медленный внутренний eeprom используйте RAM или ставте быстрый внешний FRAM, но удобного способа доступа к нему средствами компилятора уже не будет, придется писать драйвер.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Sep 29 2007, 20:30
Сообщение #42


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(defunct @ Sep 30 2007, 00:20) *
Ну и что?! У eeprom еще и ресурс ограничен, такова уж особенность этой памяти.
100k раз запишете дальше пойдут сбои.
Какое это имеет отношение к удобному механизму обращения к этой памяти?
Похоже Вы невнимательно читаете мои посты,
перечитайте пожалуйста №37, и если Вас не затруднит,
ответьте на 2 поставленных мной вопроса,
продублирую их на всякий случай:

НО, объясните мне как Вы будете пользоваться такими присвоениями в следующей
ситуации:
Есть прога:
- все события(опросы) синхронизированны(системный тик) например с тактом 200-500мкс
- есть одно или несколько прерываний которые получают данные
- есть основной цикл который ведет обработку полученных в прерывании данных
- НУЖНО, не прерывая обработку, писать некоторые изменения соcтояния проги в EEPROM

Где в этой проге можно написать cfg_EE = cfg_RAM ?


.......................
Как Вы думаете, в среднем, какой вариант общения с EEPROM будет более
быстрым и более надежным(в смысле ресурса EEPROM) ?
Go to the top of the page
 
+Quote Post
defunct
сообщение Sep 29 2007, 20:40
Сообщение #43


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(singlskv @ Sep 29 2007, 23:30) *
[i]НО, объясните мне как Вы будете пользоваться такими присвоениями в следующей
ситуации:
Есть прога:
- все события(опросы) синхронизированны(системный тик) например с тактом 200-500мкс
- есть одно или несколько прерываний которые получают данные
- есть основной цикл который ведет обработку полученных в прерывании данных
- НУЖНО, не прерывая обработку, писать некоторые изменения соcтояния проги в EEPROM

Для этой задачи я поставлю исключительно внешний eeprom либо NVRAM и не буду даже морочиться с внутренним, которого судя по условию задачи просто не хватит для хранения какого либо существенного объема статистики.
Внутренний eeprom лично я использую только для: хранения параметров конфигурации устройства, хранения информации о рестартах + дамп критических структур в случае перезагрузки по WDT.
Цитата
Как Вы думаете, в среднем, какой вариант общения с EEPROM будет более
быстрым и более надежным(в смысле ресурса EEPROM) ?

Я думаю, что вариант общения должен быть обдуманным, т.е. надо минимизировать число записей. При этом инструмент которым непосредственно производится запись/чтение может быть каким угодно, но желательно простым, что нам и дает IAR.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Sep 29 2007, 20:58
Сообщение #44


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(defunct @ Sep 30 2007, 00:40) *
Для этой задачи я поставлю исключительно внешний eeprom либо NVRAM и не буду даже морочиться с внутренним, которого судя по условию задачи просто не хватит для хранения какого либо существенного объема статистики.
Внутренний eeprom лично я использую только для: хранения параметров конфигурации устройства, хранения информации о рестартах + дамп критических структур в случае перезагрузки по WDT.
А мне вот и для всей остальной статистики хватает smile.gif
Наверное по тому что я не умею пользоваться встроенной EEPROM ? biggrin.gif
Цитата
Я думаю, что вариант общения должен быть обдуманным, т.е. надо минимизировать число записей. При этом инструмент которым непосредственно производится запись/чтение может быть каким угодно, но желательно простым, что нам и дает IAR.
Это вы о чем ? Об этой простоте cfg_EE = cfg_RAM ?
Ну и где здесь минимизация количества записей ?

Свой вариант реализации я уже описал, читаем-проверяем-если нужно пишем, и
это все на уровне байта.
Раскажите мне как Вы планируете минимизировать количество записей при помощи
этой простоты cfg_EE = cfg_RAM ?
Go to the top of the page
 
+Quote Post
sensor_ua
сообщение Sep 29 2007, 21:05
Сообщение #45


Профессионал
*****

Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387



Цитата
Где в этой проге можно написать cfg_EE = cfg_RAM ?

такую операцию нельзя прерывать независимо от компилятора - это АППАРАТНОЕ ограничение. Если это не понимать, то знание особенностей использования диалекта языка и компилятора не помогут. Потому вопрос
Цитата
объясните мне как Вы будете пользоваться такими присвоениями в следующей
ситуации

просто не имеет смысла.
Если используется внешняя память, о чём упомянул defunct, то задача относится опять же не к компиляторам, а есть вопрос архитектуры программы.


--------------------
aka Vit
Go to the top of the page
 
+Quote Post

6 страниц V  < 1 2 3 4 5 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 16th July 2025 - 19:19
Рейтинг@Mail.ru


Страница сгенерированна за 0.01523 секунд с 7
ELECTRONIX ©2004-2016