Pic Basic Proton Stack Kullanımı

Başlatan bymrz, 12 Mart 2010, 09:26:12

bymrz

Arkadaşlar 16 serisi işlemcilerle(2K dan büyük kapasiteli) Proton üzerinde çalıştığımızda "assemly view" seçeneğinden asm kodlarını incelediğimde program içerisinde komut aralarında sık sık " git hangi sayfadasın hesapla ona göre bank registerlerını ayarla" gibi bir alt rutin çağırılıyor.

Bunun kodu şişirmesinden ziyade, stack kullanımına da etkisi oluyor sanırım. Zaten 8 stack yığın deposu var. Bir tanesi interruptta kullanılıyor, bir kaçı da program içerisinde. Proton sanırım kendisi de stack kullandığı için, yazdığım program saçmalamaya başlıyor.

Proton kendisi ne kadar stack kullanıyor acaba , bileniniz var mı? Ve bu 16F serilerinde bu sorun için bir çözüm var mı?


Edit: Şimdi denedim, Programı 2046byte a kadar yazıyorum çalıştırıyorum. sorun olmuyor. Fakat programa biraz daha kod eklediğimde  işler karışıyor, çalışmıyor işlemci... çalışsa da kafasına göre bir şeyler yapıyor.

bymrz

Fikir yok mu hiç? Bu sorunle bi ben mi karşılaştım?  :D

Maxim

ben konuyu merak ediyorum ama bilgim yok malesef.
araştırma yapalım, nelere bakmalıyız ?

tyildizak

Alıntı yapılan: "alone_lover"
Proton kendisi ne kadar stack kullanıyor acaba , bileniniz var mı? Ve bu 16F serilerinde bu sorun için bir çözüm var mı?

Proton 4'ünü kullanıyor, çözüm 18 serisi kullanmak

bymrz

Alıntı yapılan: "tyildizak"
Alıntı yapılan: "alone_lover"
Proton kendisi ne kadar stack kullanıyor acaba , bileniniz var mı? Ve bu 16F serilerinde bu sorun için bir çözüm var mı?

Proton 4'ünü kullanıyor, çözüm 18 serisi kullanmak

Hocam hemencecik kestirip atıverdiniz yaa  :)
iliyorum 18 serisinin 31 stack yığın deposu var. Bu gayet yeteli fakat, Şu anki sisteme çözüm bulmam gerekiyor. Fakat hocam,

ben önceki dediğim gibi 2KB 'ı aşmadan programı yazıyorum, çalışıyor. Fakat bir kaç kod eklediğimde ( fakat bu eklediğim kodlar programde hiç işlemiyor, bu eklediğim yerlere hiç dallanma olmuyor, deneme amaçlı yazıyorum) neden çalışmıyor?

bir de Protonun 4 stack kullandığı bilgisi nerede var hocam, ben bulamadım da, Belirtirseniz sevinirim.

tyildizak

Üzgünüm, aklıma gelen ilk çözüm bu oluverdi :)

Hocam, bana bir terslik var gibi geliyor, stack taşması oluyorsa (ki sanırım şüpheniz bu yönde) bu program boyutu ile ilgili olmamalı diye düşünüyorum.

4 seviye bilgisini de yanılmıyorsam proton manuel'de görmüştüm. (Aynı şey pbp için de geçerliydi)

bymrz

hocam program kapasitesi bulunduğu bank değerini aşınca, bazı hesaplamalar yapı diğer banklar arası geçiş yapabilmek için  extra bir dallanma koyuyor olabilir. Bu da haliyle stack'in taşmasına neden olabilir belki..

Ama ben de emin değilim sorunun ne olduğuna.   :(

Ya benim bildiğim 16 serilerinde "POP" "PUSH" komutu kullanılamıyor muydu?

Datasheet'te "instruction set" te yazmıyor

bymrz

Hocam,

Şimdi şu şekilde kod yazdım;

main:

high portb.1
delayms 500
low portb.1

goto main


Bunu yazdım ve yine aşağılarda kodlar var(2K dan fazla) ve timer+usart interruptları mevcut. Bu halde bile, yani gosub komutu hiç kullanmadan yine de sapıtıyor işlemci.

Yani 2K yı geçmeye dursun program kapasitesi...
:oops:

muhittin_kaplan

evet 8 yığının 4 ünü kütüphaneler için proton kullanıyor.
ama hiç denememekle bareber
STACK_SIZE = 40
diye bir tanımlama vermiş 14 bitlerde işe yarıyormu bilmiyorum

bymrz

Alıntı yapılan: "muhittin_kaplan"evet 8 yığının 4 ünü kütüphaneler için proton kullanıyor.
ama hiç denememekle bareber
STACK_SIZE = 40
diye bir tanımlama vermiş 14 bitlerde işe yarıyormu bilmiyorum

Yok hocam olmuyor...

Tagli

Page değiştirmek için ayrıca hesap kitap yapmaya gerek yok. En azından çalışma sırasında yapılmaz, sadece fazladan 1-2 komut gerekebilir her atlamada. Bu durumda stack'tede fazladan bir yer işgali olmaması gerekir. Kodun hafızaya yerleşimi ve atlamadan önce gereken bu 1-2 asm kodu derleme sırasında hesaplanıyor olmalı. Derleyiciyi bilmediğim için yorum yapamıyorum ama belki 2k'nın ötesinde programlar için desteği yoktur. Örnek vermek gerekirse PicBasic (Pro'suz versiyonu) 2k'dan büyük programları desteklemiyor.

STACK_SIZE komutu 18 serisi için olsa gerek. Bu modellerde her ne kadar derinlik 31 olsa da uygun yazılım ile RAM'in tamamını stack olarak kullanabilirsiniz. 18 serisinde 31'lik alan dolunca bunu farkedip stack'i RAM'e aktararak tekrardan boş alan oluşturma imkanı var. Elbette bu biraz zaman kaybettiriyor. Bu PIC'lere işletim sistemi yüklenebilmesine imkan veren de bu özellik.
Gökçe Tağlıoğlu

Maxim

proton helpinden ..




What is a Stack?

All microprocessors and most microcontrollers have access to a STACK, which is an area of RAM allocated for temporary data storage. But this is sadly lacking on a PICmicro device. However, the 16-bit core devices have an architecture and low-level mnemonics that allow a STACK to be created and used very efficiently. A stack is first created in high memory by issuing the STACK_SIZE Declare.

STACK_SIZE = 40

The above line of code will reserve 40 bytes at the top of RAM that cannot be touched by any BASIC command, other than Push and Pop. This means that it is a safe place for temporary variable storage. Taking the above line of code as an example, we can examine what happens when a variable is pushed on to the 40 byte stack, and then popped off again.

First the RAM is allocated. For this explanation we will assume that a 18F452 PICmicro device is being used. The 18F452 has 1536 bytes of RAM that stretches linearly from address 0 to 1535. Reserving a stack of 40 bytes will reduce the top of memory so that the compiler will only see 1495 bytes (1535 - 40). This will ensure that it will not inadvertently try and use it for normal variable storage.

Pushing

When a word variable is pushed onto the stack, the memory map would look like the diagram below: -
 Top of Memory  |................Empty RAM..................................| Address 1535
                                ~     ~
                                ~     ~
               |................Empty RAM..................................| Address 1502
               |................Empty RAM..................................| Address 1501
               |  Low Byte address of WORD variable                        | Address 1496
Start of Stack |  High Byte address of WORD variable                       | Address 1495

The high byte of the variable is first pushed on to the stack, then the low byte. And as you can see, the stack grows in an upward direction whenever a Push is implemented, which means it shrinks back down whenever a Pop is implemented. If we were to Push a dword variable on to the stack as well as the word variable, the stack memory would look like: -

Top of Memory  |................Empty RAM..................................| Address 1535
                                ~     ~
                                ~     ~
               |................Empty RAM..................................| Address 1502
               |................Empty RAM..................................| Address 1501
               |  Low Byte address of DWORD variable                       | Address 1500
               |  Mid1 Byte address of DWORD variable                      | Address 1499
               |  Mid2 Byte address of DWORD variable                      | Address 1498
               |  High Byte address of DWORD variable                      | Address 1497
               |  Low Byte address of WORD variable                        | Address 1496
Start of Stack |  High Byte address of WORD variable                       | Address 1495

Popping

When using the Pop command, the same variable type that was pushed last must be popped first, or the stack will become out of phase and any variables that are subsequently popped will contain invalid data. For example, using the above analogy, we need to Pop a dword variable first. The dword variable will be popped Low Byte first, then MID1 Byte, then MID2 Byte, then lastly the High Byte. This will ensure that the same value pushed will be reconstructed correctly when placed into its recipient variable. After the Pop the stack memory map will look like: -

Top of Memory  |................Empty RAM..................................| Address 1535
                                ~     ~
                                ~     ~
               |................Empty RAM..................................| Address 1502
               |................Empty RAM..................................| Address 1501
               |  Low Byte address of WORD variable                        | Address 1496
Start of Stack |  High Byte address of WORD variable                       | Address 1495

If a word variable was then popped, the stack will be empty, however, what if we popped a byte variable instead? the stack would contain the remnants of the word variable previously pushed. Now what if we popped a dword variable instead of the required word variable? the stack would underflow by two bytes and corrupt any variables using those address's . The compiler cannot warn you of this occurring, so it is up to you, the programmer, to ensure that proper stack management is carried out. The same is true if the stack overflows. i.e. goes beyond the top of RAM. The compiler cannot give a warning.

Technical Details of Stack implementation

The stack implemented by the compiler is known as an Incrementing Last-In First-Out Stack. Incrementing because it grows upwards in memory. Last-In First-Out because the last variable pushed, will be the first variable popped. The stack is not circular in operation, so that a stack overflow will rollover into the PICmicro's hardware register, and an underflow will simply overwrite RAM immediately below the Start of Stack memory. If a circular operating stack is required, it will need to be coded in the main BASIC program, by examination and manipulation of the stack pointer (see below).

Indirect register pair FSR2L and FSR2H are used as a 16-bit stack pointer, and are incremented for every byte pushed, and decremented for every byte popped. Therefore checking the FSR2 registers in the BASIC program will give an indication of the stack's condition if required. This also means that the BASIC program cannot use the FSR2 register pair as part of its code, unless for manipulating the stack. Note that none of the compiler's commands, other than Push and Pop use FSR2.

Whenever a variable is popped from the stack, the stack's memory is not actually cleared, only the stack pointer is moved. Therefore, the above diagrams are not quite true when they show empty RAM, but unless you have use of the remnants of the variable, it should be considered as empty, and will be overwritten by the next Push command.

bymrz

Hocam bu bahsettiğin 16 bit işlemciler için, yani 18 serisi için...

wsxwsx

Alıntı yapılan: "alone_lover"Hocam,

Şimdi şu şekilde kod yazdım;

main:

high portb.1
delayms 500
low portb.1

goto main


Bunu yazdım ve yine aşağılarda kodlar var(2K dan fazla) ve timer+usart interruptları mevcut. Bu halde bile, yani gosub komutu hiç kullanmadan yine de sapıtıyor işlemci.

döngü içine clrwdt yazalım, delayms 500 yerine   delayms 5 yazıp döngü ile 100 kere çalıştıralım.

İnanması zor ama bu tip şeyler işe yarayabiliyor.

bymrz

Alıntı yapılan: "wsxwsx"
Alıntı yapılan: "alone_lover"Hocam,

Şimdi şu şekilde kod yazdım;

main:

high portb.1
delayms 500
low portb.1

goto main


Bunu yazdım ve yine aşağılarda kodlar var(2K dan fazla) ve timer+usart interruptları mevcut. Bu halde bile, yani gosub komutu hiç kullanmadan yine de sapıtıyor işlemci.

döngü içine clrwdt yazalım, delayms 500 yerine   delayms 5 yazıp döngü ile 100 kere çalıştıralım.

İnanması zor ama bu tip şeyler işe yarayabiliyor.


Hocam ben bunu örnek olarak yazdım, dediğiniz şekilde değişiklikleri denedim. Normalde zaten ben delayms,delayus kullanmam.

ms=500
gosub waitms


bu şekilde kullanırım. ve waitms altrutininde de dediğiniz şekilde döngüler var... Yani olay 2K yı aşınca patlak veriyor hocam...