|
WinAVR: Как правильно размещать и работать с таблицами данных во Flash (памяти программ) ?, Не читает данные из Flash-памяти! |
|
|
|
Dec 12 2011, 10:20
|

Местный
  
Группа: Участник
Сообщений: 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
|
|
|
|
|
Dec 12 2011, 10:53
|

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

|
QUOTE (MaxiMuz @ Dec 12 2011, 12:20)  почемуто не работает , увеличение p происходит на 2 байта вместо одного! А с чего бы ему увеличиваться на один, если вы его объявили как указатель на uint 16_t. Он честно, как вы и просите, увеличивается на sizeof(uint16_t). Пассаж про зеркалокомпилятор опустим.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 12 2011, 11:48
|

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

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

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

|
Кст Цитата ати, это тоже рабочий вариант и ни какой не шедевр! Если правильно задать массив , то работает, но байт информации в массиве пакуется в слово с 00h в ст.байте: Вы описали массив указателей на int8_t, инициализируя их целыми числами. Компилятор ругнулся по поводу инициализации десяток раз (или сколько у Вас там инициализаторов), а Вы и не заметили... Причём, в первых двух выкладываниях текста программы было всё нормально а в последнем (там где дизассемблерный листинг с кусочками исходного текста) эта ошибка уже внесена. Естественно, при перескоке через байт всё заработало.
Сообщение отредактировал Genadi Zawidowski - Dec 12 2011, 22:07
|
|
|
|
|
Dec 13 2011, 11:05
|

Местный
  
Группа: Участник
Сообщений: 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
|
|
|
|
|
Dec 13 2011, 12:02
|

Гуру
     
Группа: Модераторы
Сообщений: 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)
|
|
|
|
|
Dec 14 2011, 16:14
|

Местный
  
Группа: Участник
Сообщений: 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> Долго ломал голову зачем по несколько раз копировалась ссылка на массив! Создалось такое впечатление что, происходит дублирование пары регистров с адресом массива... Непомерно раздутый код , который можно заменить как минимум вдвое меньшим числом команд. Я понимаю что возможно ктото скажет, что если не нравиться, пользуйся асемблерными вставками. Программа работает правильно. Может я слишком требователен к компилятору, но может есть менее громоздкий способ обращению к массиву ?
|
|
|
|
|
Dec 14 2011, 19:29
|

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

|
 И кто будет после этого утверждать, что изучать ассемблер полезно? Вот изучил человек ассемблер, и что? Теперь он вместо написания программы, реализации своего алгоритма, создания своего устройства - занят анализом работы компилятора... MaxiMuz, вы сначала просто программу напишите, а оптимизировать её можно потом. Если возникнет нужда (а она скорее всего и не возникнет). Кроме того, со временем вы набьёте руку в Си, и будете автоматом писать наиболее оптимальным способом.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jan 20 2012, 17: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++; } } }
|
|
|
|
|
Jan 23 2012, 07:39
|

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

|
Цитата(ARV @ Jan 21 2012, 10:34)  какая проблема решилась? по-моему, что в скобках, что за скобками - все одно и то же... решилась проблема лишних сохранений и тусований ссылочного регистра Z. при использовании: Цитата pgm_read_byte(p); p++; вместо Цитата pgm_read_byte(p++); код сокращается на 18 байт!
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|