Страница 1 из 1
Flash-массив в качестве параметра
Добавлено: Пн авг 24, 2009 15:52:14
Synergetik
Здравствуйте!
Нужно хранить большой массив (больше 100 байт) в Attiny2313. Оперативки не хвата (всего доступно 128 байт SRAM), приходится на flash'е. Этот массив (точнее его указатель на первый элемент) должен передаваться в качестве параметра в функцию обработки массива. Массив у меня назван, допустим, flash int mass[1, 2, 3, ...].
Собственно сама проблема: если в функции-обработчике задать параметры так: void read_mass(int mel[]), то ругается компилятор (CodeVisionAVR 2.03). Если так: void read_mass(flash int mel[]), то начиная с n-го элемента массива считывание этого самого элемента даёт сбой и программа как бы подвисает. Если же тело функции поместить сразу в main, то проблем нет. Это повторяется как в Протеусе, так и в железе.
Вопрос: можно ли каким-нибудь образом организовать так, чтобы:
1. В Attiny2313 можно было бы хранить массивы подобных размеров (до двух-трёх, может чуть больше штук)
2. Обработка выполнялась бы в отдельной функции (то есть передать в функцию в качестве параметра массив, хранящийся в flash, eeprom или ещё где-нибудь)
3. Происходило правильное считывание элементов массива.
4. Хотелось бы узнать причину происходящего.
О варианте взять Мегу я знаю сам, так что нужно решать проблему в рамках Тиньки. Поместить тело функции в main - крайний вариант.
Заранее благодарю за ответ.
Добавлено: Пн авг 24, 2009 18:20:51
mr.Kirill
Что мешает сделать что-то вроде такого:
Код: Выделить всё
flash int mel[5]={1,2,3,4,5};
void read_mass(int *mel)
{
int a;
a=*mel;
...
*mel++;
}
PS. Ногами не пинать, давно на CVAVR не писал. И его синтаксис подзабыл.
Добавлено: Пн авг 24, 2009 20:15:09
ARV
mr.Kirill писал(а):Что мешает сделать что-то вроде такого:
Код: Выделить всё
flash int mel[5]={1,2,3,4,5};
void read_mass(int *mel)
{
int a;
a=*mel;
...
*mel++;
}
PS. Ногами не пинать, давно на CVAVR не писал. И его синтаксис подзабыл.
наверное все-таки
void read_mass(flash int *mel)...
Добавлено: Пн авг 24, 2009 21:12:31
maglev
ARV писал(а):наверное все-таки void read_mass(flash int *mel)...
разумеется. Более того, указатели на Flash, EEPROM и RAM имеют полное право иметь различную разрядность и между собой несовместимы.
Добавлено: Пн авг 24, 2009 21:44:34
mr.Kirill
ARV писал(а):наверное все-таки void read_mass(flash int *mel)...
Если изначально Вы объявили массив как flash, то зачем в функции это указывать?
Функция может работать (и будет) с любым массивом, будь то Flash, EEPROM или RAM.
Добавлено: Пн авг 24, 2009 21:45:50
mr.Kirill
maglev писал(а):разумеется. Более того, указатели на Flash, EEPROM и RAM имеют полное право иметь различную разрядность и между собой несовместимы.
Наверное стоит напомнить что это AVR, и мало того - CodeVisionAVR.
Добавлено: Пн авг 24, 2009 22:17:47
maglev
mr.Kirill писал(а):ARV писал(а):наверное все-таки void read_mass(flash int *mel)...
Если изначально Вы объявили массив как flash, то зачем в функции это указывать?
Функция может работать (и будет) с любым массивом, будь то Flash, EEPROM или RAM.
С CodeVision я никогда не работал, но не представляю, как он может обойти эту проблему. Размер указателей разный, способ доступа к данным разный, функция не может этого знать.
IAR честно даст ошибку о том, что типы (
int * и
__flash int*) несовместимы. С EEPROM будет аналогично, и это правильно.
Добавлено: Пн авг 24, 2009 22:58:01
mr.Kirill
Такая вот особенность именно компилятора CVAVR, что нужно только в инициализации массива указать тип (по-умолчанию RAM, flash или eeprom) и дальше к этому можно не возвращаться.
Добавлено: Пн авг 24, 2009 23:20:00
Synergetik
mr.Kirill писал(а):Такая вот особенность именно компилятора CVAVR, что нужно только в инициализации массива указать тип (по-умолчанию RAM, flash или eeprom) и дальше к этому можно не возвращаться.
В том-то и дело, что если указать только при инициализации массива, то CodeVisionAVR выдаёт: "function argument #1 of type 'flash int[11]' is incompatible with required parameter of type 'int []'". Причём, если flash добавить и в функцию, то ошибок при трансляции нет, но только массив начиная с некоторого символа читается некорректно - у меня, например, начинается воспроизведение мелодии и подвисает, точнее выдаёт заведомо неверную длинную ноту, то есть элемент массива извращается. Аналогично было, когда в символьный массив пытался запихнуть больше 256 символов - тоже происходила порча элементов.
mr. Kirill, вот этот кусок не понял:
Если меется в виду локальной переменной присваивать по очереди элементы массива, то это не сработало - проверил. Явное указание длины массива тоже не помогло.
Добавлено: Пн авг 24, 2009 23:52:17
__Alexander
Улыбнула великая совместимость языка Си - WinAvr, CVAVR, ICC, IAR... ну просто абалдеть, а если переносить, то оказывается у каждого свои прелести

.
------------------------------
Я уже десять лет смеюсь.
------------------------------
-------------
Добавлено: Вт авг 25, 2009 01:05:43
mr.Kirill
__Alexander писал(а):Улыбнула великая совместимость языка Си - WinAvr, CVAVR, ICC, IAR... ну просто абалдеть, а если переносить, то оказывается у каждого свои прелести :))
Язык Си - он хоть и платформо-независимый, но в тоже время компиляторо-зависимый :)))
Synergetik , выложите проект, если это не супер секретно.
CVAVR порой жутко чудит.
Добавлено: Вт авг 25, 2009 08:21:24
ARV
1. если тип указателя в параметре функции не указать явно, что он flash, то внутри функции (если обойти недовольство компилятора несовпадением типов) этот указатель будет работать с ОЗУ - оно вам надо?
2. заметил, что изначальный код с "сюрпризом". напомню его:
Код: Выделить всё
flash int mel[5]={1,2,3,4,5};
void read_mass(flash int *mel)
{
int a;
a=*mel;
...
*mel++;
}
что-то мне подсказывает, что многие считают, будто
mel в параметре функции и массив
mel - это одно и то же. однако, это не так. обращаться к функции
read_mass надо примерно так:
или так:
P.S. после сказанного задумался:
а стало ли понятнее после моих пояснений?

Добавлено: Вт авг 25, 2009 09:22:07
Goodefine
Synergetik писал(а):
... вот этот кусок не понял:
Если меется в виду локальной переменной присваивать по очереди элементы массива, то это не сработало - проверил...
И не сработает, надо не
а
Это инкремент указателя, в первом случае - значения, на которое он указывает. Странно, что никто не обратил на это внимания...
Работайте с элементами массива через цикл и будет Вам счастье...
Добавлено: Вт авг 25, 2009 09:43:36
Synergetik
Уф, разобрался! А ответ дан был почти сразу. Ещё mr.Kirill'ом, когда он написал: "void read_mass(int *mel)". Всю жизнь считал, что "int mel[]" и "int *mel" в параметре функции одно и то же. Оказывается, это так для оперативки, но не для flash'а. Если не хватает оперативки для массива и нужно использовать flash, то рецепт такой:
1. Указываем тип массива: flash int mel[]= {1, 2, 3, ...};
2. В объявлении функции обработки пишем: void read_mel(flash int *mel) {};. "Писанина" вроде "flash int mel[]" не прокатит.
3. Вызывать функцию следующим образом: read_mel(mel);
Спасибо всем, кто принимал участие в беседе, и особенно mr.Kirill, кто первый предложил правильный вариант, и ARV, благодаря последнему посту которому я почему-то сразу сообразил, в чём может быть дело. Заинтересованным прилагаю проект.
А теперь главный вопрос: почему для ОЗУ выражения "int mel[]" и "int *mel" идентичны, а для flash нет? Ведь по идее и там и там создаётся временная переменная указатель (которая, кстати, по той же идее, всё равно где может размещаться, а КодВижн ругается, если не в flash'е), которая хранит адрес нулевого элемента массива. И впоследствии обращаться к нему можно как к имени массива mel.
P.S. В железе ещё не проверял. Но Протеус ещё ни разу меня не подводил, так что почти наверняка заработает и там.
Добавлено: Вт авг 25, 2009 11:24:43
mr.Kirill
Ради интереса пришлось скачать CVAVR версии 2.
Прикольно, CVAVR начал правильно ругаться, когда из
убираем flash и оставляем
Выходит что либо я немного ошибся с CVAVR, хотя давным давно наступал на такие грабли в версии 1..., либо это поправили :)
Ну да ладно, главное что разобрались и помогли человеку :)
Добавлено: Вт авг 25, 2009 13:07:46
__Alexander
mr.Kirill писал(а):
Язык Си - он хоть и платформо-независимый, но в тоже время компиляторо-зависимый
От чего он зависимый? Ведь в тысячах книг пишут именно про Язык С, а не по Язык С для АВР или ПИК, и тем более не пишут что для CVAVR или IAR.
И если CVAVR понимает ROM, а IAR понимает __flash... то он уже не универсальный. А это плохо.
------------------------------