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

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


Местный
***

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



Доброго времяни суток!
Видимо опять столкнулся с кривизной WinAVR sad.gif
Пример: нужно читать данные из памяти программ, и задействовать из в программе. Чтобы небыло лишних вопросов привожу весь текст программы:
Код
#include <avr/io.h>
#include <avr/interrupt.h>     // задает макросы sei() , cli()
#include <inttypes.h>
#include <avr/pgmspace.h>

uint8_t Cnt1;// фоновый счетчик длительности переключения свдиода
volatile int16_t *p;// указатель

volatile register struct
{
  uint8_t bOne : 1;
  uint8_t bTwo : 1;
  uint8_t bThree : 1;
  uint8_t bFour : 1;
} RF asm ("r17");

#define sbi(p,b) (p |= (1<<b)) //Установить бит

#define DIRB 0b00010001
#define PUPB 0b00000111
#define Led PB0    /* линия светодиода ("1" - вкл. ч/з резистор на общ.) */

//;----------------------------------------------------------------------------------------------------------------------------------------
//Определение констант:


#define Vl_DBKCnt 101
#define Vl_FLCnt 5


const uint8_t a[] PROGMEM={22,15,233,40,69,39,203,2,1};

//=====================================================================
ISR( TIM0_COMPA_vect)
{
    if (!(--Cnt1))
    {
     RF.bOne=0;
     sbi (PINB,Led);// ________ Переключение свдиода !
    }
}

//_______________ПОДПРОГРАММЫ_________________
void init (void)
{
PORTB=PUPB; //иницализация порта B
DDRB=DIRB; // задание направления для порта B
TIMSK0=(1<<OCIE0A); /* установка разр. прер-ия по совпадению т/сч.0 с регистром OCR0A */
OCR0A=234;    //загрузка регистра совпадения OCR0A коэф. деления
TCCR0A= (1<<WGM01);    //установка режима СТС - обнуление Т/С0 при совпадении с регистром OCR0A
TCCR0B=(1<<CS02)|(1<<CS00);    // <---- конфигурация и запуск сч-ка в реж. СТС с предделителем ckl/1024
RF.bOne=0;
Cnt1=100; //задание начальных значений для счетчиков

p=&a; // Установка указателя на начало таблицы a
}

//=============================================================================
int main (void)
{
//_________________________ ИНИЦИАЛИЗАЦИЯ _____________________________
uint16_t temp;

init();
sei ();// Разрешение общего прерывания
while (1)
    {
    if (RF.bOne==0)
        { RF.bOne=1;
            temp=*p;
            Cnt1=(uint8_t)temp;
            ++p;
        }
    }    
}

После использования команды PROGMEM в задании таблицы из программы удалилась секция где массив копировался в ОЗУ, что собственно и требовалось. Но обращение к таблице не поменялось.
Вопрос вызывает только место:
Код
temp=*p;
  a6:    81 91           ld    r24, Z+
  a8:    91 91           ld    r25, Z+
Cnt1=(uint8_t)temp;
  aa:    80 93 62 00     sts    0x0062, r24

Читает неизвестно откуда , только не из программы!
Как прочитать данные из программы?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 7 2011, 18:37
Сообщение #2


Гуру
******

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



QUOTE (MaxiMuz @ Dec 7 2011, 19:58) *
Видимо опять столкнулся с кривизной WinAVR sad.gif
Видимо опять поленились прочитать документацию.

QUOTE (MaxiMuz @ Dec 7 2011, 19:58) *
CODE
        temp=*p;

Читает неизвестно откуда , только не из программы!
Читает известно откуда - из ОЗУ, как вы и попросили. Посмотрите в папке doc от вашего WinAVR папочку с документацией на avr-libc. В том же файле, в котором описано использованное вами магическое слово PROGMEM, описано и как работать с данными, размещенными во флеш при помощи этого слова.


--------------------
На любой вопрос даю любой ответ
"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
Палыч
сообщение Dec 7 2011, 18:49
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(MaxiMuz @ Dec 7 2011, 21:58) *
Как прочитать данные из программы?

Коль поменяли размещение массива а, то нужно изменить и указатель р таким образом, чтобы он указывал не на ОЗУ, а на flash (PROGMEM добавьте).
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 8 2011, 06:57
Сообщение #4


Гуру
******

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



QUOTE (Палыч @ Dec 7 2011, 20:49) *
(PROGMEM добавьте).
Не поможет. В WinAVR (avr-gcc) пока нет поддержки адресных пространств.


--------------------
На любой вопрос даю любой ответ
"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
Genadi Zawidowsk...
сообщение Dec 8 2011, 08:21
Сообщение #5


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

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



Может, поможет:

Код
void uc1601s_put_str_P(const char * str)
{
    char c;

    uc1601s_put_char_begin();
    while((c = pgm_read_byte(str ++)) != '\0')
        uc1601s_put_char(c);
    uc1601s_put_char_end();
}
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение Dec 8 2011, 11:36
Сообщение #6


Местный
***

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



Цитата(Genadi Zawidowski @ Dec 8 2011, 11:21) *
Может, поможет:

Код
void uc1601s_put_str_P(const char * str)
{
    char c;

    uc1601s_put_char_begin();
    while((c = pgm_read_byte(str ++)) != '\0')
        uc1601s_put_char(c);
    uc1601s_put_char_end();
}

Ничего не понимаю !!! Уже пробывал и с pgm_read_byte и с _LPM результата никакого !

Цитата(Палыч @ Dec 7 2011, 21:49) *
Коль поменяли размещение массива а, то нужно изменить и указатель р таким образом, чтобы он указывал не на ОЗУ, а на flash (PROGMEM добавьте).

Куда конкретно добавлять PROGMEM ?

Цитата(Сергей Борщ @ Dec 8 2011, 09:57) *
Не поможет. В WinAVR (avr-gcc) пока нет поддержки адресных пространств.

чето я к такому же выводу прихожу, хотя в дока Data in Program Space четко описано как читать с Flash !
Вы вывод сделали на собственном опыте или по чужому ?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 8 2011, 13:03
Сообщение #7


Гуру
******

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



QUOTE (MaxiMuz @ Dec 8 2011, 13:36) *
Ничего не понимаю !!! Уже пробывал и с pgm_read_byte и с _LPM результата никакого !
Показывайте исходник и листинг с pgm_read_byte().
QUOTE (MaxiMuz @ Dec 8 2011, 13:36) *
чето я к такому же выводу прихожу, хотя в дока Data in Program Space четко описано как читать с Flash !
И оно таки работает именно так, как описано в доке.
QUOTE (MaxiMuz @ Dec 8 2011, 13:36) *
Вы вывод сделали на собственном опыте или по чужому ?
По своему, естетсвенно.


--------------------
На любой вопрос даю любой ответ
"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
Genadi Zawidowsk...
сообщение Dec 8 2011, 18:23
Сообщение #8


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

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



А немного пофантазируем...
Скорее всего, человек написал
const char PROGMEM * str = "1234";
и надеется на что-то...
ВОТ ТАК ДЕЛАТЬ НЕНАДО. тут Ни одного байта из СЕМИ занятых не попадёт по FLASH.
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение Dec 9 2011, 12:06
Сообщение #9


Местный
***

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



Код
#include <avr/io.h>
#include <avr/interrupt.h>  
#include <inttypes.h>
#include <avr/pgmspace.h>

//=====================================================================
uint8_t Cnt1;// фоновый счетчик длительности переключения свдиода
uint16_t *p;

volatile register struct
{
  uint8_t bOne : 1;
  uint8_t bTwo : 1;
  uint8_t bThree : 1;
  uint8_t bFour : 1;
} RF asm ("r17");

#define sbi(p,b) (p |= (1<<b)) //Установить бит

#define DIRB 0b00010001
#define PUPB 0b00000111

//;-------------------------------------------------------------------------------
//Определение контактов
#define Control1 PB4 /* линия управления VT (1 - откр; 0 - закр ) */
#define Led PB0 /* линия светодиода ("1" - вкл. ч/з резистор на общ.) */

uint8_t a[] PROGMEM={22,15,233,40,69,39,203,2,1};

//=====================================================================
ISR( TIM0_COMPA_vect)
{
if (!(--Cnt1))
{ RF.bOne=0;
   sbi (PINB,Led);// ________ Переключение свдиода !
}
}

//_______________ПОДПРОГРАММЫ_________________
void init (void)
{
PORTB=PUPB; //иницализация порта B
DDRB=DIRB; // задание направления для порта B
TIMSK0=(1<<OCIE0A); /* установка разр. прер-ия по совпадению т/сч.0 с регистром OCR0A */
OCR0A=234; //загрузка регистра совпадения OCR0A коэф. деления
TCCR0A= (1<<WGM01); //установка режима СТС - обнуление Т/С0 при совпадении с регистром OCR0A
TCCR0B=(1<<CS02)|(1<<CS00); // <---- конфигурация и запуск сч-ка в реж. СТС с предделителем ckl/1024
RF.bOne=0;
RF.bTwo=0;
Cnt1=100; //задание начальных значений для счетчиков
p=&(a);
}

//=============================================================================
//=============================================================================
int main (void)
{
init();
sei ();

while (1)
{
if (RF.bOne==0)
  { RF.bOne=1;
   //Cnt1=pgm_read_byte(&(a[p])); // варианте 2
   //Cnt1=__LPM(*p);                   // варианте 3
   Cnt1=pgm_read_byte(p);
   ++p;
  }
}
}

вот текст программы. были опробованы различные варианты и комбинации , результатов это не принесло !

Сообщение отредактировал MaxiMuz - Dec 9 2011, 12:12
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение Dec 9 2011, 12:07
Сообщение #10


Местный
***

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



_



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


Гуру
******

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



QUOTE (MaxiMuz @ Dec 9 2011, 14:06) *
вот текст программы.
Здесь все, что касается PROGMEM правильно.
А вот uint8_t Cnt1; должен быть volatile. В вашем же случае компилятор имеет право строку Cnt1=pgm_read_byte(p); выкинуть совсем.

И последний вопрос - файл компилируется как C или как C++?

QUOTE
CODE
volatile register

QUOTE
Следуя вашему FAQ "Как варить яйцо в микроволновке" я стал его варить, но оно взорвалось и сильно испачкало мне аппарат!


--------------------
На любой вопрос даю любой ответ
"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
Genadi Zawidowsk...
сообщение Dec 9 2011, 20:29
Сообщение #12


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

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



А это было вообще "шедевр"
Код
   //Cnt1=pgm_read_byte(&(a[p])); // варианте 2

Вы хоть немного читайте диагностику компилятора. А то на asm ("r17"); Вас хватило, а на адресную арифметику нет...

В приведённом тексте ++p будет через пропускать каждый второй элемент массива a.

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


Местный
***

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



Цитата(Сергей Борщ @ Dec 9 2011, 16:51) *
И последний вопрос - файл компилируется как C или как C++?

Я не знаю как определить как компилируется файл! Есть скопированный makefile, меняю в нем тип МК, имяфайла, оптимизацию , и все.

Про яйцо и микроволновку смешно sm.gif)) Вы хотите сказать что там где не нужно использовать volatile он был использован и наоборот? sm.gif
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Dec 12 2011, 07:56
Сообщение #14


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

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



Цитата(MaxiMuz @ Dec 12 2011, 10:09) *
Я не знаю как определить как компилируется файл! Есть скопированный makefile, меняю в нем тип МК, имяфайла, оптимизацию , и все.
Приведите строки вызова компилятора.

Цитата
Вы хотите сказать что там где не нужно использовать volatile он был использован и наоборот? sm.gif
Об этом всё в том же FAQ на avr-libc написано.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение Dec 12 2011, 08:20
Сообщение #15


Местный
***

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



Цитата(Genadi Zawidowski @ Dec 9 2011, 23:29) *
А это было вообще "шедевр"
Код
   //Cnt1=pgm_read_byte(&(a[p])); // варианте 2

Кстати, это тоже рабочий вариант и ни какой не шедевр! Если правильно задать массив , то работает, но байт информации в массиве пакуется в слово с 00h в ст.байте:
Код
uint8_t *a[] PROGMEM={22,15,233,40,69,39,203,2,1};
00000014 <a>:
  14: 16 00 0f 00 e9 00 28 00 45 00 27 00 cb 00 02 00     ......(.E.'.....
  24: 01 00  
uint16_t p;
p=0;
......
......
int main (void)
{
init();
  9c: ea df           rcall .-44    ; 0x72 <init>
sei ();
  9e: 78 94          sei
  a0: e0 91 60 00  lds r30, 0x0060
  a4: f0 91 61 00  lds r31, 0x0061
  a8: ee 0f           add r30, r30
  aa: ff 1f            adc r31, r31
  ac: ec 5e           subi r30, 0xEC; 236
  ae: ff 4f            sbci r31, 0xFF; 255
if (RF.bOne==0)
  b0: 10 fd           sbrc r17, 0
  b2: fe cf            rjmp .-4     ; 0xb0 <__stack+0x11>
  { RF.bOne=1;
  b4: 11 60           ori r17, 0x01; 1
   Cnt1=pgm_read_byte(&(a[p++]));
  b6: 84 91           lpm r24, Z+
  b8: 80 93 62 00   sts 0x0062, r24
  bc: 32 96           adiw r30, 0x02; 2
  be: f8 cf            rjmp .-16    ; 0xb0 <__stack+0x11>


Здесь я обнаружил неточную трансляцию команд, в месте :
Код
b6: 84 91           lpm r24, Z+

на самом деле заменяется командой lpm r24,Z !!! Что меня в начале смутило , так как инкремент судя по листингу происходит 3 раза.

Цитата(demiurg_spb @ Dec 12 2011, 10:56) *
Приведите строки вызова компилятора.

Код
> "make.exe" all

-------- begin --------
avr-gcc (WinAVR 20100110) 4.3.3
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Size before:
AVR Memory Usage
----------------
Device: attiny13a

Program:     196 bytes (19.1% Full)
(.text + .data + .bootloader)

Data:          3 bytes (4.7% Full)
(.data + .bss + .noinit)




Compiling C: table_Fsh.c
avr-gcc -c -mmcu=attiny13a -I. -gdwarf-2 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./table_Fsh.lst  -std=gnu99 -MMD -MP -MF .dep/table_Fsh.o.d table_Fsh.c -o table_Fsh.o
table_Fsh.c:56: warning: initialization makes pointer from integer without a cast
table_Fsh.c:56: warning: initialization makes pointer from integer without a cast
table_Fsh.c:56: warning: initialization makes pointer from integer without a cast
table_Fsh.c:56: warning: initialization makes pointer from integer without a cast
table_Fsh.c:56: warning: initialization makes pointer from integer without a cast
table_Fsh.c:56: warning: initialization makes pointer from integer without a cast
table_Fsh.c:56: warning: initialization makes pointer from integer without a cast
table_Fsh.c:56: warning: initialization makes pointer from integer without a cast
table_Fsh.c:56: warning: initialization makes pointer from integer without a cast

Linking: table_Fsh.elf
avr-gcc -mmcu=attiny13a -I. -gdwarf-2 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=table_Fsh.o  -std=gnu99 -MMD -MP -MF .dep/table_Fsh.elf.d table_Fsh.o --output table_Fsh.elf -Wl,-Map=table_Fsh.map,--cref,-gc-sections     -lm

Creating load file for Flash: table_Fsh.hex
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature table_Fsh.elf table_Fsh.hex

Creating load file for EEPROM: table_Fsh.eep
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 --no-change-warnings -O ihex table_Fsh.elf table_Fsh.eep || exit 0

Creating Extended Listing: table_Fsh.lss
avr-objdump -h -S -z table_Fsh.elf > table_Fsh.lss

Creating Symbol Table: table_Fsh.sym
avr-nm -n table_Fsh.elf > table_Fsh.sym

Size after:
AVR Memory Usage
----------------
Device: attiny13a

Program:     196 bytes (19.1% Full)
(.text + .data + .bootloader)

Data:          3 bytes (4.7% Full)
(.data + .bss + .noinit)



-------- end --------


> Process Exit Code: 0
> Time Taken: 00:04







Сообщение отредактировал MaxiMuz - Dec 12 2011, 08:15
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 - 23:30
Рейтинг@Mail.ru


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