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

 
 
2 страниц V  < 1 2  
Reply to this topicStart new topic
> WinAVR: Как правильно размещать и работать с таблицами данных во Flash (памяти программ) ?, Не читает данные из Flash-памяти!
MaxiMuz
сообщение Dec 12 2011, 10:20
Сообщение #16


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Вообщем я понял, из за неприспосбленного и непродуманного компилятора WinAVR и кривизны оптимизатора код с заранее настроенным на адрес регистром:
Код
int16_t *p;
p=&(a);
Cnt1=pgm_read_byte(p++);
- почемуто не работает , увеличение p происходит на 2 байта вместо одного!
Единственный правильный вариант:
Код
volatile uint8_t Cnt1;//фоновый счетчик длительности переключения свдиода
uint16_t p=0;

uint8_t a[] PROGMEM={22,15,233,40,69,39,203,2,1};
......
......
Cnt1=pgm_read_byte(&(a[p++]));

Хотя тоже корявый:
Код
            Cnt1=pgm_read_byte(&(a[p++]));
  aa:    84 91           lpm    r24, Z+
  ac:    80 93 62 00     sts    0x0062, r24
  b0:    31 96           adiw    r30, 0x01; 1

Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 12 2011, 10:53
Сообщение #17


Гуру
******

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



QUOTE (MaxiMuz @ Dec 12 2011, 12:20) *
почемуто не работает , увеличение p происходит на 2 байта вместо одного!
А с чего бы ему увеличиваться на один, если вы его объявили как указатель на uint16_t. Он честно, как вы и просите, увеличивается на sizeof(uint16_t). Пассаж про зеркалокомпилятор опустим.


--------------------
На любой вопрос даю любой ответ
"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
MaxiMuz
сообщение Dec 12 2011, 11:48
Сообщение #18


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Цитата(Сергей Борщ @ Dec 12 2011, 13:53) *
А с чего бы ему увеличиваться на один, если вы его объявили как указатель на uint16_t. Он честно, как вы и просите, увеличивается на sizeof(uint16_t). Пассаж про зеркалокомпилятор опустим.

Да, действительно! Я все провожу паралели с Ассемблером и посчитал что тип_данных перед указателем есть размер ячейки памяти которая используется для указания адреса.
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Dec 12 2011, 22:05
Сообщение #19


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

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



Кст
Цитата
ати, это тоже рабочий вариант и ни какой не шедевр! Если правильно задать массив , то работает, но байт информации в массиве пакуется в слово с 00h в ст.байте:

Вы описали массив указателей на int8_t, инициализируя их целыми числами. Компилятор ругнулся по поводу инициализации десяток раз (или сколько у Вас там инициализаторов), а Вы и не заметили...

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



Сообщение отредактировал Genadi Zawidowski - Dec 12 2011, 22:07
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение Dec 13 2011, 11:05
Сообщение #20


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Цитата(Genadi Zawidowski @ Dec 13 2011, 01:05) *
Вы описали массив указателей на int8_t, инициализируя их целыми числами. Компилятор ругнулся по поводу инициализации десяток раз (или сколько у Вас там инициализаторов), а Вы и не заметили...

Теперь понял какую я ерунду написал.
Почему то в строчке p=&a;
Код
volatile uint8_t Cnt1;//фоновый счетчик длительности переключения свдиода
uint8_t *p;
......
uint8_t a[] PROGMEM={22,15,233,40,69,39,203,2,1};
p=&a;
......
компил. выдает предупреждение:
Код
warning: assignment from incompatible pointer type
?

Сообщение отредактировал MaxiMuz - Dec 13 2011, 11:08
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 13 2011, 12:02
Сообщение #21


Гуру
******

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



QUOTE (MaxiMuz @ Dec 13 2011, 13:05) *
warning: assignment from incompatible pointer type[/code] ?
p - указатель на uint8_t. Имя массива является указателем на его нулевой член. Оператор & возвращает указательна свой аргумент. Т.е. запись &a имеет тип "указатель на указатель на uint8_t". Вам же надо просто "указатель на uint8_t". Поэтому либо берите адрес нулевого элемента массива p = &a[0], либо берите адрес массива p = a.

И еще - ваш массив находится во флеш, значит является константным по условию. Значит ваш указатель нужно делать указателем на константу: uint8_t const * p. И неважно, что компилятор сейчас позволяет объявить указатель на неконстантный объект - во первых, это уже исправлено в последних версиях, а во-вторых - это предохранит вас от ошибочной попытки изменить данные, на которые указывает p простым присваиванием, компилятор выдаст сообщение об ошибке.


--------------------
На любой вопрос даю любой ответ
"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
MaxiMuz
сообщение Dec 14 2011, 16:14
Сообщение #22


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Заменил p=&a; на p=&a[0]; действительно предупреждение пропало, спасибо Сергею!
Но возник другой вопрос. Я немного поменял алгоритм основной программы на:
Код
p=&a[0];
........................................
........................................
int main (void)
{
uint8_t temp;
init();
sei ();
while (1)
    {
    if (RF.bOne==0)
        { RF.bOne=1;
            temp=pgm_read_byte(p++);
            if (temp!=0)
                {Cnt1=pgm_read_byte(p++);}
        }
    }    
}

И получил код:
Код
p=&a[0];
  8a:    84 e1           ldi    r24, 0x14   ; 20
  8c:    90 e0           ldi    r25, 0x00   ; 0
  8e:    90 93 61 00     sts    0x0061, r25
  92:    80 93 60 00     sts    0x0060, r24
........................................
........................................
uint8_t temp;
init();
  98:    e8 df           rcall    .-48        ; 0x6a <init>
sei ();
  9a:    78 94           sei
  9c:    20 91 60 00     lds    r18, 0x0060
  a0:    30 91 61 00     lds    r19, 0x0061
  a4:    c9 01           movw    r24, r18
while (1)
    {
    if (RF.bOne==0)
  a6:    10 fd           sbrc    r17, 0
  a8:    fe cf           rjmp    .-4         ; 0xa6 <__stack+0x7>
        { RF.bOne=1;
  aa:    11 60           ori    r17, 0x01   ; 1
}
int main (void)
{
  ac:    ac 01           movw    r20, r24
  ae:    4f 5f           subi    r20, 0xFF   ; 255
  b0:    5f 4f           sbci    r21, 0xFF   ; 255
    {
    if (RF.bOne==0)
        { RF.bOne=1;
            temp=pgm_read_byte(p++);
  b2:    fc 01           movw    r30, r24
  b4:    84 91           lpm    r24, Z+
            if (temp!=0)
  b6:    88 23           and    r24, r24
  b8:    11 f4           brne    .+4         ; 0xbe <__stack+0x1f>
  ba:    ca 01           movw    r24, r20
  bc:    f4 cf           rjmp    .-24        ; 0xa6 <__stack+0x7>
            {
            Cnt1=pgm_read_byte(p++);
  be:    9a 01           movw    r18, r20
  c0:    2f 5f           subi    r18, 0xFF   ; 255
  c2:    3f 4f           sbci    r19, 0xFF   ; 255
  c4:    fa 01           movw    r30, r20
  c6:    84 91           lpm    r24, Z+
  c8:    80 93 62 00     sts    0x0062, r24
  cc:    eb cf           rjmp    .-42        ; 0xa4 <__stack+0x5>

Долго ломал голову зачем по несколько раз копировалась ссылка на массив! Создалось такое впечатление что, происходит дублирование пары регистров с адресом массива...
Непомерно раздутый код , который можно заменить как минимум вдвое меньшим числом команд. Я понимаю что возможно ктото скажет, что если не нравиться, пользуйся асемблерными вставками. Программа работает правильно. Может я слишком требователен к компилятору, но может есть менее громоздкий способ обращению к массиву ?
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Dec 14 2011, 19:29
Сообщение #23


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



bb-offtopic.gif И кто будет после этого утверждать, что изучать ассемблер полезно? Вот изучил человек ассемблер, и что? Теперь он вместо написания программы, реализации своего алгоритма, создания своего устройства - занят анализом работы компилятора... laughing.gif
MaxiMuz, вы сначала просто программу напишите, а оптимизировать её можно потом. Если возникнет нужда (а она скорее всего и не возникнет). Кроме того, со временем вы набьёте руку в Си, и будете автоматом писать наиболее оптимальным способом.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение Jan 20 2012, 17:24
Сообщение #24


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Проблема решилась выносом p++ за "скобки" функции pgm_read_byte:
Код
while (1)
    {
    if (RF.bOne==0)
        { RF.bOne=1;
            temp=pgm_read_byte(p);
            p++;
            if (temp!=0)
            {
            Cnt1=pgm_read_byte(p);
            p++;
            }
        }
    }
Go to the top of the page
 
+Quote Post
ARV
сообщение Jan 21 2012, 07:34
Сообщение #25


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

Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581



какая проблема решилась? по-моему, что в скобках, что за скобками - все одно и то же...


--------------------
Я бы взял частями... но мне надо сразу.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Jan 23 2012, 05:07
Сообщение #26


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(ARV @ Jan 21 2012, 10:34) *
по-моему, что в скобках, что за скобками - все одно и то же...
Однозначно!


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jan 23 2012, 05:37
Сообщение #27


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(ARV @ Jan 21 2012, 13:34) *
какая проблема решилась? по-моему, что в скобках, что за скобками - все одно и то же...

Что-то там не так оптимизировалось:
Цитата(MaxiMuz @ Dec 14 2011, 22:14) *
Долго ломал голову зачем по несколько раз копировалась ссылка на массив!



--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение Jan 23 2012, 07:39
Сообщение #28


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Цитата(ARV @ Jan 21 2012, 10:34) *
какая проблема решилась? по-моему, что в скобках, что за скобками - все одно и то же...

решилась проблема лишних сохранений и тусований ссылочного регистра Z.
при использовании:
Цитата
pgm_read_byte(p); p++;
вместо
Цитата
pgm_read_byte(p++);
код сокращается на 18 байт!
Go to the top of the page
 
+Quote Post

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

 


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


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