Stackkontroll PIC16
Stackkontroll PIC16
PIC16 har begränsat med stackutrymme och det är en ren hårdvarustack för returadresser. Finns det något sätt att hålla koll på stackdjupet? Eller iallfall något sätt att detektera att man fått stack overflow?
Jag har räknat på det, och det borde inte vara ett stackproblem, men det hade varit bra att veta säkert att det inte är det. Jag kan ju ha missat något. En exceptionvektor som betydde just "stack overflow" hade varit guld att ha. Inte så mycket för att se när saker händer, utan snarare för att verkligen vara säker på att det inte händer.
Jag har räknat på det, och det borde inte vara ett stackproblem, men det hade varit bra att veta säkert att det inte är det. Jag kan ju ha missat något. En exceptionvektor som betydde just "stack overflow" hade varit guld att ha. Inte så mycket för att se när saker händer, utan snarare för att verkligen vara säker på att det inte händer.
Re: Stackkontroll PIC16
MPSIM håller koll och larmar.
Nyare PIC16 (PIC16F1xxx) har en "trapp" for over/underflow av stacken.
Äldre PIC16 bär sig bara underligt åt.
Annars är det bara manuell "code-review" som gäller.
Nyare PIC16 (PIC16F1xxx) har en "trapp" for over/underflow av stacken.
Äldre PIC16 bär sig bara underligt åt.
Annars är det bara manuell "code-review" som gäller.
Re: Stackkontroll PIC16
MPSIM är inte användbar i detta fallet. Det är alldeles för mycket kommunikation och annan hårdvarukontakt för att kunna simulera allting. Den har bl.a två UART kommunikationslinjer igång med kontinuerlig kommunikation som måste svara inom vissa specade tider. Den ena går på hårdvaru-UART:en och den andra på en soft-UART.
Det går heller inte att bryta ner programmet och isolera felet, eftersom felet då försvinner (eller iallafall alla synbara symtom av problemet). Det är under en väldigt speciell kombination av omständigheter som det inträffar. Det räcker att flytta kod eller variabler i minnet för att saker skall se annorlunda ut och kraschar på ett annat sätt. Eller att alla symtom försvinner, men grundfelet ligger kvar.
Nyare PIC16 (PIC16F1xxx) har en "trapp" for over/underflow av stacken.
Det är ju det som hade varit guld och haft nu. På gamla 12-bitars arkitekturen med bara två stacknivåer, så är det ju relativt enkelt att hålla koll på vad den gör. På 14-bitarsvarianten så blir det genast betydligt svårare att hålla hundraprocentig koll. En sådan TRAP borde dom ju egentligen kunna byggt in från början i arkitekturen, tycker man. Stacken är ju ett välkänt område för problem, och det borde inte ta mycket kiselyta att implementera.
Frågan är vad den egentligen gör när man får stack overflow. Det finns ju minst ett par olika scenarion:
1. Den nya returadressen kastas och inget rörs på stacken
2. Allting pushas med den nya returadressen överst. Den äldsta kastas.
Min gissning borde ju vara 2. Sedan om den informationen ger något användbart, är ju en annan sak.
En intressant sak att försöka göra för att få en koll på använt stackdjup, vore att använda någon form av "guard". Detta är ju väldigt vanligt på "normala" stackar. Nu är inte det så jäkla enkelt med en hårdvarustack som bara lagrar återhoppsadresser, men kanske inte helt omöjligt ändå. Om man antar scenario 2 ovan. Om man längst ned på stacken lägger en återhoppsadress till en funktion som gör något specifikt, t.ex en brytpunkt. Sedan inför man en "återhoppsfunktion" i programmet som kan triggas med någon valfri "yttre händelse". Denna funkion skall göra ytterligare en "return" från huvudprogrammet där den snurrar med stackdjup 0. Om man då börjat med att lägga upp en återhoppsadress till en känd funktion och den verkligen kommer dit vid "yttre händelse", så ligger ju uppenbarligen (eller iallafall troligen) det stackvärdet kvar utan att vara överskrivet.
Detta skulle sedan kunna upprepas flera ggr genom att lägga på ytterligare en callnivå för att få ut ett värde på hur många nivåer som faktiskt "finns kvar".
Det går heller inte att bryta ner programmet och isolera felet, eftersom felet då försvinner (eller iallafall alla synbara symtom av problemet). Det är under en väldigt speciell kombination av omständigheter som det inträffar. Det räcker att flytta kod eller variabler i minnet för att saker skall se annorlunda ut och kraschar på ett annat sätt. Eller att alla symtom försvinner, men grundfelet ligger kvar.
Nyare PIC16 (PIC16F1xxx) har en "trapp" for over/underflow av stacken.
Det är ju det som hade varit guld och haft nu. På gamla 12-bitars arkitekturen med bara två stacknivåer, så är det ju relativt enkelt att hålla koll på vad den gör. På 14-bitarsvarianten så blir det genast betydligt svårare att hålla hundraprocentig koll. En sådan TRAP borde dom ju egentligen kunna byggt in från början i arkitekturen, tycker man. Stacken är ju ett välkänt område för problem, och det borde inte ta mycket kiselyta att implementera.
Frågan är vad den egentligen gör när man får stack overflow. Det finns ju minst ett par olika scenarion:
1. Den nya returadressen kastas och inget rörs på stacken
2. Allting pushas med den nya returadressen överst. Den äldsta kastas.
Min gissning borde ju vara 2. Sedan om den informationen ger något användbart, är ju en annan sak.
En intressant sak att försöka göra för att få en koll på använt stackdjup, vore att använda någon form av "guard". Detta är ju väldigt vanligt på "normala" stackar. Nu är inte det så jäkla enkelt med en hårdvarustack som bara lagrar återhoppsadresser, men kanske inte helt omöjligt ändå. Om man antar scenario 2 ovan. Om man längst ned på stacken lägger en återhoppsadress till en funktion som gör något specifikt, t.ex en brytpunkt. Sedan inför man en "återhoppsfunktion" i programmet som kan triggas med någon valfri "yttre händelse". Denna funkion skall göra ytterligare en "return" från huvudprogrammet där den snurrar med stackdjup 0. Om man då börjat med att lägga upp en återhoppsadress till en känd funktion och den verkligen kommer dit vid "yttre händelse", så ligger ju uppenbarligen (eller iallafall troligen) det stackvärdet kvar utan att vara överskrivet.
Detta skulle sedan kunna upprepas flera ggr genom att lägga på ytterligare en callnivå för att få ut ett värde på hur många nivåer som faktiskt "finns kvar".
Re: Stackkontroll PIC16
> Frågan är vad den egentligen gör när man får stack overflow.
> Om man antar...
RTFM istället (från PIC16F88x databladet, DS41291D) :
analys av koden.
> Om man antar...
RTFM istället (från PIC16F88x databladet, DS41291D) :
Jag tror inte att det finns någon annan väg en en statisk/manuellThe stack operates as a circular buffer. This means that
after the stack has been PUSHed eight times, the ninth
push overwrites the value that was stored from the first
push. The tenth push overwrites the second push (and
so on).
analys av koden.
Re: Stackkontroll PIC16
> Om man antar scenario 2 ovan.
Gör inte det.
Det var mer ett antagande för resonemanget. Jag skulle aldrig anta det och basera en funktion på det utan att kontrollera det.
Stackräknaren "wrappar" tillbaka till första positionen och
push-9 skriver över push-1 o.s.v.
Det är alltså inte en riktig fysisk "stack" i den egentliga meningen, utan mer som en "vanlig" stack med stackpekare och ett minne. Med andra ord precis som i andra mikroprocessorer med större stack, fast allting inte är åtkomligt på samma sätt.
Å andra sidan så påverkar det egentligen ingenting i mitt resonemang ang. "guard". Det är fortfarande den äldsta adressen längst ner på stacken som försvinner, i motsats till scenario 1. Så då borde fortfarande "guard"-metoden kunna användas.
Gör inte det.
Det var mer ett antagande för resonemanget. Jag skulle aldrig anta det och basera en funktion på det utan att kontrollera det.
Stackräknaren "wrappar" tillbaka till första positionen och
push-9 skriver över push-1 o.s.v.
Det är alltså inte en riktig fysisk "stack" i den egentliga meningen, utan mer som en "vanlig" stack med stackpekare och ett minne. Med andra ord precis som i andra mikroprocessorer med större stack, fast allting inte är åtkomligt på samma sätt.
Å andra sidan så påverkar det egentligen ingenting i mitt resonemang ang. "guard". Det är fortfarande den äldsta adressen längst ner på stacken som försvinner, i motsats till scenario 1. Så då borde fortfarande "guard"-metoden kunna användas.
Senast redigerad av vfr 14 januari 2011, 13:20:12, redigerad totalt 1 gång.
Re: Stackkontroll PIC16
> Det var mer ett antagande för resonemanget.
Som ett tankeexperiment kanske, men det löser inte ditt problem.
> Det är alltså inte en riktig fysisk "stack" i den egentliga meningen,
> utan mer som en "vanlig" stack med stackpekare och ett minne.
Alla implementeringar jag har sett har en "pekare" och ett "minne".
Oasvett om det ligger i ett eget specifikt minne eller allokerat ur
ett större generellt minne.
> Så då borde fortfarande "guard"-metoden kunna användas.
Jag ser inte hur det skulle göras. Som sagt, stacken är inte tillgänglig
på en vanlig PIC16.
Som ett tankeexperiment kanske, men det löser inte ditt problem.
> Det är alltså inte en riktig fysisk "stack" i den egentliga meningen,
> utan mer som en "vanlig" stack med stackpekare och ett minne.
Alla implementeringar jag har sett har en "pekare" och ett "minne".
Oasvett om det ligger i ett eget specifikt minne eller allokerat ur
ett större generellt minne.
> Så då borde fortfarande "guard"-metoden kunna användas.
Jag ser inte hur det skulle göras. Som sagt, stacken är inte tillgänglig
på en vanlig PIC16.
Re: Stackkontroll PIC16
Alla implementeringar jag har sett har en "pekare" och ett "minne".
Inte grunddefinitionen av en stack som det lärs ut i digitaltekniken. Iallafall inte när jag läste det. Då definierades en stack som ett antal fysiska minnespositioner där innehållet verkligen flyttades från den ena positionen till den andra. Allt beror ju på hur många positioner man ska ha i stacken. Med två nivåer, som det var från början på 12-bitars, så skulle den metoden mycket väl varit användbar. Sedan är ju frågan om den ändå var det, och hur man sedan gjorde när man byggde ut den till 8 nivåer. Uppenbarligen är det ju stackpekarmodellen nu iallafall. Sedan har ju denna modell alltid använts när man pratar "stack" i mikroprocessorsammanhang. Men som sagt, eftersom PIC:ens stack är väldigt "hård" och ursprungligen bara två nivåer, så skulle det inte varit omöjligt alls.
Men strunt samma. Och ja, det står i manualen. Och jag har säker läst det hundra ggr. Men när man sedan läser samma sak igen, så tenderar man att läsa det på samma sätt som tidigare. Och då kanske prioriteringen på vad som var viktigt, inte var helt densamma. Tyvärr är man inte ofelbar..
Jag ser inte hur det skulle göras. Som sagt, stacken är inte tillgänglig
på en vanlig PIC16.
Enligt min beskrivning. Det enda (tror jag
) som var lite löst, var hur man lägger upp en guardadress på stacken när stacken inte kan manipuleras manuellt. Man börjar programmet med ett "call" till den funktion som skall vara "guardfunktion" (med breakpoint) enligt mitt resonemang. Sedan gör man inget återhopp förrän man vill kolla, t.ex när "yttre händelse" inträffar. Borde inte vara omöjligt, eller är det någon som ser någon direkt hake med det?
Inte grunddefinitionen av en stack som det lärs ut i digitaltekniken. Iallafall inte när jag läste det. Då definierades en stack som ett antal fysiska minnespositioner där innehållet verkligen flyttades från den ena positionen till den andra. Allt beror ju på hur många positioner man ska ha i stacken. Med två nivåer, som det var från början på 12-bitars, så skulle den metoden mycket väl varit användbar. Sedan är ju frågan om den ändå var det, och hur man sedan gjorde när man byggde ut den till 8 nivåer. Uppenbarligen är det ju stackpekarmodellen nu iallafall. Sedan har ju denna modell alltid använts när man pratar "stack" i mikroprocessorsammanhang. Men som sagt, eftersom PIC:ens stack är väldigt "hård" och ursprungligen bara två nivåer, så skulle det inte varit omöjligt alls.
Men strunt samma. Och ja, det står i manualen. Och jag har säker läst det hundra ggr. Men när man sedan läser samma sak igen, så tenderar man att läsa det på samma sätt som tidigare. Och då kanske prioriteringen på vad som var viktigt, inte var helt densamma. Tyvärr är man inte ofelbar..

Jag ser inte hur det skulle göras. Som sagt, stacken är inte tillgänglig
på en vanlig PIC16.
Enligt min beskrivning. Det enda (tror jag

- Swech
- EF Sponsor
- Inlägg: 4750
- Blev medlem: 6 november 2006, 21:43:35
- Ort: Munkedal, Sverige (Sweden)
- Kontakt:
Re: Stackkontroll PIC16
Flöde på hur du kan göra
swech
Kod: Markera allt
Start av program
call fortsätt_här
;--------------
; här hamnar vi vid stack problem
reset
;-------------
Fortsätt_här:
.
.
.
.
Re: Stackkontroll PIC16
Ett par problem med det... 
PIC16 (ej 16F1xxx) saknas "reset" instruktion.
Kan lösas med watchdog (WDT) eller liknande.
Det löser inte problemet, retur-adressen till adressen efter
"call fortsätt_här" skrivs över vid en stack-overflow. Jag ser
inte riktigt hur an skulle kunna hamna på "här hamnar vi..."
om man inte gör vanliga "return" *utan* overflow.
Plus att det hela förvärrar situationen eftersom det tar en
extra stack-nivå...
Om det nu är så stora problem så skulle jag kolla på att flytta det hela
till en PIC16F1xxxx med 16 stack nivåer och en hel del andra nyheter...

PIC16 (ej 16F1xxx) saknas "reset" instruktion.
Kan lösas med watchdog (WDT) eller liknande.
Det löser inte problemet, retur-adressen till adressen efter
"call fortsätt_här" skrivs över vid en stack-overflow. Jag ser
inte riktigt hur an skulle kunna hamna på "här hamnar vi..."
om man inte gör vanliga "return" *utan* overflow.
Plus att det hela förvärrar situationen eftersom det tar en
extra stack-nivå...

Om det nu är så stora problem så skulle jag kolla på att flytta det hela
till en PIC16F1xxxx med 16 stack nivåer och en hel del andra nyheter...
Re: Stackkontroll PIC16
Jag vet inte om det är stacken som är problemet ännu. Eller rättare sagt så tror jag inte att det är det, men skulle vilja utesluta det helt och kunna koncentrera mig på andra möjliga felorsaker. Problemet med PIC16F1xxxx är att dom inte finns i PLCC-kapsel. Dom måste i dagsläget vara utbytbara i befintliga enheter där det sitter 16C74, 16F74 eller16F877. Fr.o.m 16F887 så finns inte PLCC-varianten längre.
Den dagen det kortet görs om, så kommer det säkert att göras med QFP-kapsel istället. Fast det ställer också till problem då programmet skall uppgraderas och man inte kan byta chip längre. Ska man ladda via ICSP-kontakt så måste det springas runt med en handhållen programmerare till alla enheter som sitter utspridda över ett stort geografiskt område.
Den dagen det kortet görs om, så kommer det säkert att göras med QFP-kapsel istället. Fast det ställer också till problem då programmet skall uppgraderas och man inte kan byta chip längre. Ska man ladda via ICSP-kontakt så måste det springas runt med en handhållen programmerare till alla enheter som sitter utspridda över ett stort geografiskt område.
Re: Stackkontroll PIC16
Kolla så du inte har för många nästlade subrutiner. Jag har också råkat på detta och #¤%# innan jag hittade felet. CALL i för många led tror jag var det som kraschade för mig MPLAB varnade inte som jag minns det
När man kraschar pekaren så hoppar den till snudd på random minnesposition så att debugga är inte helt lätt.

När man kraschar pekaren så hoppar den till snudd på random minnesposition så att debugga är inte helt lätt.

Re: Stackkontroll PIC16
> MPLAB varnade inte som jag minns det...
Nja, *MPASM* varnar nog inte för det. Den kan helt enkelt inte "se"
att det eventuellt kommer att uppstå en stack overflow.
*MPLAB/SIM* däremot ska/borde varna för stack overflow om man lyckas
sätta upp det hela så att det motsvarar ett verkligt driftsfall.
Nja, *MPASM* varnar nog inte för det. Den kan helt enkelt inte "se"
att det eventuellt kommer att uppstå en stack overflow.
*MPLAB/SIM* däremot ska/borde varna för stack overflow om man lyckas
sätta upp det hela så att det motsvarar ett verkligt driftsfall.
Re: Stackkontroll PIC16
Om programmet som nämnts är skrivit i asm, ett förslag här att räkna stacknivåerna:
Med 'Sök o Ersätt' byt ut alla Call mot ett eget macro TestCall och alla Return mot TestReturn. I huvudprogrammets början ställs en variabel 'Stacknivå' till 8. Vid alla anrop räknas variabeln ner ett steg, vid alla återhopp räknas den upp. Om Stacknivå = 0 då har stacken tagit slut. Även retlw, interrupt-ingången och retfie, får ändras enligt detta.
Så här:
Med 'Sök o Ersätt' byt ut alla Call mot ett eget macro TestCall och alla Return mot TestReturn. I huvudprogrammets början ställs en variabel 'Stacknivå' till 8. Vid alla anrop räknas variabeln ner ett steg, vid alla återhopp räknas den upp. Om Stacknivå = 0 då har stacken tagit slut. Även retlw, interrupt-ingången och retfie, får ändras enligt detta.
Så här:
Kod: Markera allt
i huvudprogrammet
movlw 08h
movwf Stacknivåräknare
------------------------------------------
TestCall macro AnropsAdress
local anropa
decfsz Stacknivå, f
goto anropa
stackfel
; gör nåt här, stacken har tagit slut,
anropa
call AnropsAdress
endm
------------------------------------------
TestReturn macro
incfsz Stacknivå, f
nop
return
endm
------------------------------------------
Re: Stackkontroll PIC16
Mitt tips består av fler delar:
* Använd en PIC6F1xxx i detta skedet, migrering kan enkelt ske sedan om det är billigare när stack-problemet är avklarat.
* Använd en PIC18Fxxx generellt, alltså spola PIC16 om det är möjligt. Kan finnas ekonomiska orsaker att välja ena eller andra, inget enkelt svar där.
PIC16Fxxx är en bra serie MEN när man kommer upp i en viss komplexitet på program är det dags att stega upp lite.
* Använd en PIC6F1xxx i detta skedet, migrering kan enkelt ske sedan om det är billigare när stack-problemet är avklarat.
* Använd en PIC18Fxxx generellt, alltså spola PIC16 om det är möjligt. Kan finnas ekonomiska orsaker att välja ena eller andra, inget enkelt svar där.
PIC16Fxxx är en bra serie MEN när man kommer upp i en viss komplexitet på program är det dags att stega upp lite.
Re: Stackkontroll PIC16
Persika - bra idé!
Jag ser ett problem. Vid call kontrolleras stackdjupet innan anropet, men vid interrupt kontrolleras det efteråt, när det redan är försent. Ifall programmet saknar nästlade interrupt borde det dock funka, eftersom att huvudprogrammet skulle kunna begränsa stackdjupet till 7, så att även ett interrupt får plats.
Jag ser ett problem. Vid call kontrolleras stackdjupet innan anropet, men vid interrupt kontrolleras det efteråt, när det redan är försent. Ifall programmet saknar nästlade interrupt borde det dock funka, eftersom att huvudprogrammet skulle kunna begränsa stackdjupet till 7, så att även ett interrupt får plats.