Как освободить Стек контроллера??

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Аватара пользователя
O-LED
Мудрый кот
Сообщения: 1800
Зарегистрирован: Вт окт 05, 2010 01:08:57
Контактная информация:

Как освободить Стек контроллера??

Сообщение O-LED »

Настал момент когда компилятор мне выдал "The hardware Stack Size has a dangerously low value: 14byte" При этом флешь занят на 34%. Проанализировав свой код я понял что все заняли большущие массивы. Но почему они забивают стек. ведь я объявляю эти массивы как константы(т.е. они не изменяются), ни в какие функции их не передаю, тихо-мирно кручу их в основном цикле. Почему они переполняют стек, и как можно этого избежать???
Во незатейливый код полностью

Код: Выделить всё

#include <tiny2313.h>
#define BUT_MINYS   0x0E
#define BUT_PLUS    0x0B
bit flg_drebezg;
unsigned char  kanal,bytton,  x;
unsigned int drebezg, kadr,temp_speed;
char led []={0b01000001,0b10000010,0b00100001,0b10000100,0b00010001,0b10001000,0b00100010,0b01000100,0b00010010,0b01001000,0b00010100,0b00101000};
const unsigned int yzor1 []=    {0b100000000000,0b010000000000,0b001000000000,0b000100000000,0b000010000000,0b000001000000,
                                0b000000100000,0b000000010000,0b000000001000,0b000000000100,0b000000000010,0b000000000001,
                                0b100000000000,0b110000000000,0b111000000000,0b111100000000,0b111110000000,0b111111000000,
                                0b111111100000,0b111111110000,0b111111111000,0b111111111100,0b111111111110,0b111111111111,
                                0b011111111111,0b001111111111,0b000111111111,0b000011111111,0b000001111111,0b000000111111,
                                0b000000011111,0b000000001111,0b000000000111,0b000000000011,0b1111000000000001};
eeprom  unsigned int speed=50;
//*******************************************************************************//
interrupt [TIM0_COMPA] void timer0_compa_isr(void)
{
      kanal++;  if (kanal==12)  kanal= 0;
      if ((kadr<<kanal+4>>15)  ==  1)  {PORTB= led[kanal];}  else PORTB=0;
     
      drebezg++;  if (drebezg==200)  flg_drebezg=1;
      temp_speed++;
}
void main(void)
{
PORTB=0x00;DDRB=0xFF;
PORTD=0x7F;DDRD=0x00;

TCCR0A=0x02;
TCCR0B=0x03;
OCR0A=0xAD;

TIMSK=0x01;
ACSR=0x80;

#asm("sei")
while (1)
{
bytton=PIND&0x0F;   
if ((flg_drebezg==1) && (bytton != 0x0F)) {drebezg=0; flg_drebezg=0;}  else {bytton=0;}

if (bytton==BUT_MINYS ) {speed=speed+10;  if(speed==1000) speed=990; }
if (bytton==BUT_PLUS) {speed=speed-10;  if(speed == 0) speed=10; }                                       
   
    if (temp_speed >= speed) 
        {
        temp_speed=0;
        kadr=yzor1[x]; 
        x++;  if((yzor1[x-1]) >= 0xf000) {x=0;}     
        }
};
}
KIT
Аватара пользователя
Мурик
Друг Кота
Сообщения: 3383
Зарегистрирован: Пн окт 11, 2010 19:00:08

Re: Как освободить Стек контроллера??

Сообщение Мурик »

А разве нет возможности самому задать размер аппаратного стека.
Скажем, в BASCOM это делается так

Код: Выделить всё

$hwstack = 100    'Размер аппаратного стека - 100 байт
lix
Опытный кот
Сообщения: 703
Зарегистрирован: Вс янв 17, 2010 15:32:19
Откуда: Курган

Re: Как освободить Стек контроллера??

Сообщение lix »

Добавьте модификатор FLASH (или как там в CV), массивы не будут занимать ОЗУ.
Аватара пользователя
O-LED
Мудрый кот
Сообщения: 1800
Зарегистрирован: Вт окт 05, 2010 01:08:57
Контактная информация:

Re: Как освободить Стек контроллера??

Сообщение O-LED »

lix спасибо, работает.
я вообще думал что компиляторы поумнее..... нафига тащить в ОЗУ константы, с которыми ничего сделать все равно нельзя, только чтение. так и читай из флеша......
KIT
Аватара пользователя
>TEHb<
Друг Кота
Сообщения: 5726
Зарегистрирован: Ср ноя 11, 2009 17:19:30
Откуда: Воронеж
Контактная информация:

Re: Как освободить Стек контроллера??

Сообщение >TEHb< »

а потому как чтение из флеша занимает в разы больше времени, а потому всё, что не попадя он тащит в ОЗУ. Если что-то срочное, то я обычно подгружаю в переменные в ОЗУ, а с ними уже быстро работаю.
"Привет!" - соврал он.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Как освободить Стек контроллера??

Сообщение ARV »

>TEHb< писал(а):а потому как чтение из флеша занимает в разы больше времени, а потому всё, что не попадя он тащит в ОЗУ.
интересно, кто вам такое сказал? в какие такие РАЗЫ больше? что при чтении из ОЗУ надо загрузить индексные регистры адресом, а затем одной командой считать байт, что для чтения из флеша - кол-во тактов одно и то же. в редких случаях на 1 такт больше получается. в общем, разница если и есть, то незначительная. и ваше предположение не верно в корне: вы пытаетесь обяснить поведение компилятора какими-то личными домыслами, а на самом деле все просто: стандарт Си явно диктует поместить переменную в ОЗУ, если не сказано иное. в приведенном ранее коде - иное не сказано, вот все массивы и попадают в ОЗУ.

однако, это еще не все! те же самые константы и во флеше имеются и при старте программы тупо копируются в ОЗУ!!! ведь иначе они туда ниоткуда попасть не могут. поэтому происходит растрата как ОЗУ, так и флеш-памяти, т.е. двойные расхоы.

что касается "ума" компиляторов: компилятор не должен умничать, он должен соблюдать требования стандарта языка, ибо в противном случае невозможно будет обеспечить заявляемую переносимость программ и т.п.

потому я и советую не хвататься сразу за написание сложных программ, а хотя бы в общих чертах ИЗУЧИТЬ ЯЗЫК, на котором пишите программы.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Qwertty
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Сб окт 31, 2009 12:34:44

Re: Как освободить Стек контроллера??

Сообщение Qwertty »

ARV писал(а):что при чтении из ОЗУ надо загрузить индексные регистры адресом, а затем одной командой считать байт, что для чтения из флеша - кол-во тактов одно и то же. в редких случаях на 1 такт больше получается.

Этот "редкий случай" происходит всегда. Чтение из ОЗУ не обязательно требует косвенной адресации и вполне может быть выполнено одной командой LDS. Но и при доступе через указатель все равно доступ к ОЗУ быстрее. Например LD R16,X+, LD R17,X. Каждая на такт минимум быстрее LPM. Кроме того работает с любой индексной парой. Ну и не во всех АВР можно читать из флеши в произвольный регистр. Иногда только в R0. Дальше будет пересылка. Это тоже время. Не в любом АВР есть инкемент индекса при чтении из флеш. Еще возможно потребует времени.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Как освободить Стек контроллера??

Сообщение ARV »

да, вы, несомненно правы, все так. но вот тут и должен компилятор проявить свой интеллект, исключив лишние пересылки и т.п. проигрыш в любом случае не принципиален, слава богу, тактовая не менее мегагерца обычно :)))

но, тем не менее, причина "запихивания всего в ОЗУ" лежит не в медленности операций доступа, а в том, о чем я ранее писал :)))
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
BCluster
Собутыльник Кота
Сообщения: 2512
Зарегистрирован: Пн апр 06, 2009 19:33:29
Откуда: Молдова, Кишинев
Контактная информация:

Re: Как освободить Стек контроллера??

Сообщение BCluster »

однако, это еще не все! те же самые константы и во флеше имеются и при старте программы тупо копируются в ОЗУ!!! ведь иначе они туда ниоткуда попасть не могут. поэтому происходит растрата как ОЗУ, так и флеш-памяти, т.е. двойные расхоы.


Вот у меня куча констант которые в ОЗУ просто не влазят, поэтому храняться во флеше. Поэтому физически не могут читаться в ОЗУ.

ЗЫ в настройках компилятора CVAVR можно указать что хранить константы во флеше.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Как освободить Стек контроллера??

Сообщение ARV »

когда вы пишите int array[10] = {1,2,3,4,5,6,7,8,9,10}; то это значит, что массив в ОЗУ - так? а значения массива, которыми вы инициализируете его в ОЗУ откуда берутся? только из флеша, больше не откуда. вот и получается, что во флеше у вас 20 байтов, и в ОЗУ потом 20 байтов оказывается... вот о чем я говорил.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Pe3ucTop
Прорезались зубы
Сообщения: 231
Зарегистрирован: Пт ноя 16, 2007 13:52:44
Откуда: Рига, Латвия

Re: Как освободить Стек контроллера??

Сообщение Pe3ucTop »

ARV писал(а):... стандарт Си явно диктует поместить переменную в ОЗУ, если не сказано иное. в приведенном ранее коде - иное не сказано, вот все массивы и попадают в ОЗУ.
...
что касается "ума" компиляторов: компилятор не должен умничать, он должен соблюдать требования стандарта языка, ибо в противном случае невозможно будет обеспечить заявляемую переносимость программ и т.п.
...

Извините за нескромность : может подскажете как в языке Си - сказать хранить определённый массив во флеше ?? :))
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Как освободить Стек контроллера??

Сообщение ARV »

отчего же не подсказать :)

язык Си не был ориентирован на гарвардскую архитектуру, тем более с НЕОБНОВЛЯЕМОЙ памятью данных, т.е. ПЗУ, поэтому стандартных средств для указания места хранения (ОЗУ или ПЗУ) переменных и констант, не существует в языке Си. однако, каждый компилятор под гарвардские архитектуры (нас в данном случае интересует AVR) имеет собственные нестандартные фичи для этих целей.

в частности, в WinAVR для этого служит модуль pgmspace.h, в котором определен макрос PROGMEM:

Код: Выделить всё

#include <avr/io.h>
#include <avr/pgmspace.h>
PROGMEM unsigned char massiv[10] = {1,2,3,4,5,6,7,8,9,10}; // массив однозначно и безальтернативно во FLASH


в IAR для этого служит префикс _flash, а в CVAvr - просто flash (я не знаком с упомянутыми компиляторами и могу искажать действительность - лучше изучите документацию к IAR или CVAvr).
Последний раз редактировалось ARV Пн ноя 08, 2010 12:21:58, всего редактировалось 1 раз.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
avreal
Опытный кот
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна
Контактная информация:

Re: Как освободить Стек контроллера??

Сообщение avreal »

Вот что мне нравится в таких спорах — так это умение вырвать из контекста одну-две команды (примитивную операцию) и сравнивать.
Да, конечно, тут

Код: Выделить всё

        ld      r16, X+ ; 2

        lpm             ; 3
        adiw    r30, 1  ; +2
        mov     r16, r0 ; +1 = 6
Имеем разницу «разы», в три раза.
Но уже тут

Код: Выделить всё

        ldi     r17, BUF_SIZE
        ldi     r30, lo8(src)
        ldi     r31, hi8(src)
        ldi     r26, lo8(dst)
        ldi     r27, hi8(dst)
1:
        ld      r16, Z+ ; 2
        st      X+, r16 ; +2
        dec     r17     ; +1
        brne 1b         ; +2 = 7

        ldi     r17, BUF_SIZE
        ldi     r30, lo8(src)
        ldi     r31, hi8(src)
        ldi     r26, lo8(dst)
        ldi     r27, hi8(dst)
1:
        lpm             ; 3
        st      X+, r0  ; +2
        adiw    r30, 1  ; +2
        dec     r17     ; +1
        brne 1b         ; +2 = 10
приблизительно в корень из двух, отнюдь не «в разы». И это для старх AVR-ок, а у «народных» ATtiny2313, ATmega8 есть LPM R,Z+ и разница во времени выполнения становится уже меньше 15%.
Если немного усложнить работу, не тупо копировать, а, например, сравнивать строки, то разница уже будет не 8/7 (10/7 для старых), а 10/9 (12/9 для старых).
Случаев, когда на AVR константные массивы действительно нужно хранить в ОЗУ для скорости — очень малый процент от всего кода, не в каждой программе нужно, не у каждого программиста и встретится.

А одиночные константы (это к вопросу об LDS) вообще должны храниться во флеше, в поле данных команд LDI.
Писать одиночную константу в виде слова в ОЗУ и загружать её LDS-ом (два слова, два такта на байт константы) вместо LDI (одно слово, один такт) — как-то странно выглядит.

Другое дело, что, как уже сказано, по стандарту С квалификатор const не должен менять доступ к данным и компилятор от свого имени не имеет права переносить их во флеш для архитектур с раздельными адресными пространствами кода и данных, какой есть AVR…
И тут без расширений языка в виде разнообразных атрибутов flash (code у кейла для 51-ых, если я правильно помню) не обойтись.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Аватара пользователя
O-LED
Мудрый кот
Сообщения: 1800
Зарегистрирован: Вт окт 05, 2010 01:08:57
Контактная информация:

Re: Как освободить Стек контроллера??

Сообщение O-LED »

Cпасибо всем за помощь. с ОЗУ как я уже писал - разобрался. но вылезла еще одна проблема. у меня есть указатель

Код: Выделить всё

flash  unsigned int  *yzor;
он прекрасно указывает на массивы во flash, но понадобилось мне чтоб он мог указывать еще на один массив но из eeprom . и вот здесь компилятор ругается Error: a value of type 'eeprom unsigned int [12]' can't be assigned to an entity of type 'flash unsigned int *' Как я понял, указатель не может указывать на массив из флеша.
Если же указатель объявлять без flash то он уже может работать с массивом из eeprom, но перестает работать с массивами из flash. компилятор ругается Error: a value of type 'flash unsigned int [12]' can't be assigned to an entity of type 'unsigned int *'

как мне помирить массивы в flash, eeprom и указатель на них???
KIT
Аватара пользователя
BCluster
Собутыльник Кота
Сообщения: 2512
Зарегистрирован: Пн апр 06, 2009 19:33:29
Откуда: Молдова, Кишинев
Контактная информация:

Re: Как освободить Стек контроллера??

Сообщение BCluster »

ARV, ну это само собой, я вас не так понял по ходу.
Аватара пользователя
BCluster
Собутыльник Кота
Сообщения: 2512
Зарегистрирован: Пн апр 06, 2009 19:33:29
Откуда: Молдова, Кишинев
Контактная информация:

Re: Как освободить Стек контроллера??

Сообщение BCluster »

O-LED, кастить надо. То есть так - (eeprom unsigned int *)*ykaz; - но это бред, и неизвестно если будет работать :) И вообще вообще немного не понял про указывать еще на еепром. Покажи код. Как это указатель указывает на два разных массива, да еще и в разной памяти?
Аватара пользователя
O-LED
Мудрый кот
Сообщения: 1800
Зарегистрирован: Вт окт 05, 2010 01:08:57
Контактная информация:

Re: Как освободить Стек контроллера??

Сообщение O-LED »

легко.

Код: Выделить всё

flash      unsigned int yzor1 []
flash      unsigned int yzor2 []
flash      unsigned int yzor3 []
flash      unsigned int yzor4 []
eeprom     unsigned int yzor5 []

потом в основном цикле

Код: Выделить всё

while (1)
{
switch (yzor_nomer)
{
case 0: yzor=yzor1;  break;
case 1: yzor=yzor2;  break;
case 2: yzor=yzor3;  break;
case 3: yzor=yzor4;  break;
case 4: yzor=yzor5;  break;
};               
};
Т.е. указатель yzor может указывать на массивы yzor1-yzor5, причем yzor1-yzor4 находятся во флеши, а yzor5 в еепроме.
KIT
Murav
Опытный кот
Сообщения: 877
Зарегистрирован: Чт фев 18, 2010 13:51:56

Re: Как освободить Стек контроллера??

Сообщение Murav »

В указателе хранится только адрес переменной, но не способ доступа к ней, так что присвоить указатель можно(с преобразованием типов: "(flash unsigned int * )" ), но при обращении к такой переменной компилятор прочитает данные из flash, а не из eeprom, по указанному адресу. То же самое относится и к присвоению указателю в оперативной памяти адреса во flash или eeprom.
Аватара пользователя
>TEHb<
Друг Кота
Сообщения: 5726
Зарегистрирован: Ср ноя 11, 2009 17:19:30
Откуда: Воронеж
Контактная информация:

Re: Как освободить Стек контроллера??

Сообщение >TEHb< »

ARV писал(а):интересно, кто вам такое сказал? в какие такие РАЗЫ больше?

Воевал с таблицами в ЭСППЗУ, параллельно объясняя товарищу что к чему, да так и привык "для понятности" называть его "флешкой" :dont_know: . Дико извиняюсь за попытку дезинформации, надо быть внимательнее.
ARV писал(а):что касается "ума" компиляторов: компилятор не должен умничать, он должен соблюдать требования стандарта языка, ибо в противном случае невозможно будет обеспечить заявляемую переносимость программ и т.п.

AVR частный случай и не везде флеш быстрый - для того и такие стандарты. Думаете, откуда сами стандарты-то взялись?
"Привет!" - соврал он.
Аватара пользователя
avreal
Опытный кот
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна
Контактная информация:

Re: Как освободить Стек контроллера??

Сообщение avreal »

Как раз у AVR флеш медленный. У Xmega получше. Контроллеры с ядром AVR, но с программой, загружаемой в ОЗУ, давно работали на больших частотах, чем ATmega/ATtiny.
А разница 2 такта обращения к ОЗУ и 3 к флеш связана отнюдь не с быстродейстивем флеш (простые-то команды MOV/LDI/... за один такт вычитываются!).

Язык С складывался тогда, когда никаких флешов в помине не было. А в тех компьютерах, на которых С запускался, вся память была одинаковая, на ПЗУ/ОЗУ не делилась (ну кроме маленьких ПЗУ-шек начальной загрузки).

Не-занесение const-данных во флеш для AVR (но не для MSP430 или ARM) связано с архитектурой. Намёки в предыдщих сообщениях уже были, слова "гарвардская архитектура" и "раздельные адресные пространства кода и данных" видели? Да-нет-да?

Разжёвываю, наскоько могусреди ночи

Язык С как таковой вообще ничего не знает о разных адресных пространствах. О тех же портх ввода-вывода (из-за чего на x86-ых можно работать с портами только через функции inport/outport). Вся память единая, однородная. С точки зрения стандарта С флеша нет.

Квалификатор const в языке С означает запрет изменения данных в программе, позволена только начальная инициализация.
Причём квалификатор этот может стоять и в таком контексте

Код: Выделить всё

    int foo( const int *ptr, int len);
что означает, что функция foo приниимает указатель на данные, которые она не имеет права менять. Но сами данные могут быть доступными для изменения другими функциями. При этом в

Код: Выделить всё

    int arr[10];
    const int carr[5];
    int i = foo( arr, 10); // допускается передавать не-const данные в функцию, обещающую с ними обращаться бережно, как с const-данными
    i += foo( carr, 5);
оба взова функции foo() должны отрабатывать нормально. Т.е. метод доступа к данным const и не-const должен быть одинаков.
Т.е. они должны храниться в одно адресном пространстве.

Нет, ну конечно можно завести generic-указатели, для AVR 3-байтовые, и в генерируемом коде при обращениях проверять старший байт как признак обращения к ОЗУ или к флеш (или к EEPROM). В результате можно будет в функцию

Код: Выделить всё

    int foo( const generic int *ptr, int len);
передавать указатель и на флеш, и на ОЗУ (в каждом вызове компилятор или будет иметь и так generic-указатель, или будет видеть, обращение идёт к ОЗУ или к флеш и формировать нужный укаатель)

Код: Выделить всё

    const int carr[5];
можно будет размещать во флеше и т.д. Только о скорости точно придётся забыть. При каждом обращени будет проверятьс тот старший байт и по нему выбираться команда LD или LPM. Вот это действительно будет «в разы». Найдутся куски кода, где и такое замедление несущественно, но сразу закладывать такое в весь код — глупость. Вот и приходится const-даные оставлять в ОЗУ для единообразного, но не безобразного обращения ко всем данным по умолчанию, а для отклонений от стандарта использовать расширения.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»