Fórum témák
» Több friss téma |
A kiíró rutinod biztos a ROM-ból kereste az adatokat... ha nem írod a const-ot, akkor a RAM-ba tette (?) és olvasni a ROM-ból (?) olvasott!
A C a tömböt pointerként kezeli ( hiszen az is !), ezért megy "simán" is !
Az alap felvetésem az volt, hogy nem sikerül ilyen nagy tömböt megcímeznie, ezért kell pointerrel ugrálni...
De mint most kiderült, a probléma, hogy ha nem konstans a tömb, akkor az adatterületre kerül, ha pedig konstans, akkor a programterületre és onnan jól éri el. Gondoltam most kap egy kis "erőszakolást", így a konstans tömböt meghagyva készítettem egy másikat is, majd ez utóbbit (ami az adatterületen van) feltöltöm a programterületen lévő tömbből. Ekkor ugyan úgy hibás adatokat ír ki, szóval arra kellene rájönnöm, vajon mi lehet a nyűgje az adatterülettel (létezhet, hogy a pic ezen része meg van makkanva?).
Szerintem azt kell megnézned, hogy a "WriteI2C1" függvény milyen memóriaterületet használ ( honnan tudná, hogy pl. egy 0xf0 cím az most RAM vagy ROM területre mutató pointer ?!), ez a doksiban kellene, hogy benne legyen...!
Nem hiszem, hogy baja lenne a PC memóriájának... ! A hozzászólás módosítva: Júl 18, 2017
Alljunk mar meg egy szora! Eloszor azt mondtad, hogy nem kuld ki semmit az I2C vonalon, ami arra enged kovetkeztetni, hogy meg sem hivja a WriteI2C1() fuggvenyt. Most meg azt mondod, hogy nem jo az adat, amit kikuld. Hat, akkor most mi az igazsag? Egyebkent meg, ha megnezed az (dis)assembly listajat a leforditott programodnak, akkor minden kerdesedre valaszt kapsz, ha ismered a PIC utasitaskeszletet.
Először még nem küldött ki semmit. Aztán volt haladás, mikor már felfogta, hogy a tömbből kell kiadnia valamit. A jelenlegi próbánál ott tartok, hogy ha konstans a tömb, vagyis a programterületen van, akkor kirakja, amit kell, ha az adatterületen, akkor meg nem megfelelő adat lesz.
Szóval az igazság ott van, hogy nem álltam meg egy pontnál és vártam a sültgalambot, hanem mindig az utolsó hozzászólásom az aktuálisan igaz.
A 8 bites pic-ek esetében külön memória bankok vannak, és csak úgy tudsz címezni nagyobb memória tömböt, hogy a felsőbb bitek esetén aktualizálni kell egy másik bankot. Ha teljesen a C fordítóra bízod a tömb elérését, tudnia kellene automatikusan memória bankot váltani. A jelek szerint azt nem teszi meg. Le kellene tisztázni egy lehető legegyszerűbb projectet, legyártani belőle a lista file-t, hogy tisztán látható legyen.
Most nem tudom, van-e hibalistája az aktuális xc8-nak valahol. Szerepel az a jelenség az ismert hibák között? Ha igen, lehet ott javasolt workaround a hibára.
Igen, ezzel a bankolással tisztában vagyok, de nem gondoltam volna, hogy nem képes az XC8 normálisan kezelni ezt a dolgot. A hibalistát még nem sikerült megtalálni, s ami furcsa, hogy más nemigen futott még bele ugyan ebbe a problémába (vagy csak én nem gugliztam eleget, hogy megtaláljam).
Minden esetre feladni nem fogom, legfeljebb átigazítom a kódot úgy, hogy jó legyen (akár úgy is, hogy beleférjek egy-egy bankba a tömbökkel és több tömbből rakom össze). Érdekes élmény lesz az már biztos.
Kotord fel a pic adatlapjában a memória bankokat, hány van belőle, milyen hosszúak, és kicsike ram tömböket gyárts, amik nem lépik át azt a korlátot. Aztán jó szórakozást a kezelésükkel. Vagy válts 32 bitre, és ott nulla problémád lesz egyben látni a ram tömböt. 32 biten már nincsenek külön bankok. Amelyik tetszik.
Melyik PIC-ről is beszélünk? Van benne elég RAM?
Hoppsz, nem neked akartam címezni. A hozzászólás módosítva: Júl 19, 2017
?.?.?.... Nem értem a kérdést.
Hozzászólásomra feltöltötte az egész projectet. Csak nekem sajnos nincs tapasztalatom a XC8 -cal (illetve a tapasztalataim miatt már nyugdíjaztam) és az MpLabX -el. 18F25J50 -ről van szó, 3776 byte RAM van benne. A fordító használja a dataBIGRAM szegmenst, a pic18_i2c.X\dist\default\production\pic18_i2c.X.production.lst szerint szépen átmásolja a program memóriában tárolt kezdeti értéket a tömbbe. A tömb elemének elküldése után a pointert 16 bitesen növeli.
A hozzászólás módosítva: Júl 19, 2017
A hozzászólásokból nem derült ki a típus, a mainben sem láttam, elindítani meg nem volt időm, ezért kérdeztem mivel játszik.
A tblptr a program memóriához fér hozzá (konstans tömb esetén), az nem ram elérés. "DS39931D-page 81" / "6.1.6.2 Table Reads" adatlap
Es ki beszelt itt a tblptr-rol? Hp41C csak annyit mondott, hogy a startup kod atmasolja a ROM-bol a RAM-ba a tombot, majd a main() onnan olvassa fel (es kuldi ki I2C-n). A pointer, amirol szo van (main@buf) egy 16 bites valtozo. Ezt mondtam kb. 12 HSZ-szel ezelott, hogy az assembly lista alapjan nincs semmi baj a koddal, inkrementalja a buf nevu valtozot. Es elotte meg lathatoan betolti az FSR2-be, es azt hasznalva veszi fel a tomb elemeit a RAM-bol.
Köszönöm, kívülről tudom már évek óta, főleg az utasításokat...
A WriteI2C1() után nem kellene megvizsgálni az ACK bit értékét? Hátha azért nem megy, mert a slave NACK -ot küld... A hozzászólás módosítva: Júl 19, 2017
Szia!
Folyamatosan néztem a logic programmal, hogy mi történik egyik, illetve másik esetben. "Sajnos" a slave ACK-t küld vissza akkor is, amikor hülyeséget küld neki a program, és akkor is, amikor jó adatokat. A különbség a jó eredmény és a rossz eredmény között ott van, hogy konstans a tömb és így a programterületre kerül (ekkor szépen kimegy a tömb értéke, csak ugye használhatatlan, mert nem tudom módosítani), vagy nem konstans és az adatterületre kerül (ekkor a tömb nulladik elemét küldi ki egyfolytában és olyan, mintha nem növelné az értékét a pointernek). A konstans tömb esetében teljesen mindegy, hogy direkt számolással címzem ki az elemet, vagy pointert növelgetek, mindkét esetben jó lesz az eredmény. A nem konstans tömb esetén ha pointert használok, amit ráállítok a tömb nulladik elemére, akkor azt küldi ki és megjön mindig az ACK, ha pedig direkt kicímezném számolással, akkor össze-vissza értékeket, viszont azt két kikapcsolás között nem változtatja, hogy mi lesz ez az össze-vissza halom, de ezekre is megjön az ACK minden esetben. Keresgéltem manuálok, leírások tucatjaiban a bigdata történetre, de látszólag az xc8 ezt automatikusan kezeli (a C18-hoz talált linkerben átírni a dataszekciót és pragma utasítással hivatkozni hova is kerüljön dolog itt nem ment). Ha a fordításkor a reportnál bekapcsolom a psect mutatása opciót, akkor szépen meg is mutatja, hogy ő elkészítette ezt a bigdata részt. Közben kíváncsiságból készítettem olyan (nem konstans) tömböt, ami nem ilyen nagy, mindössze 10 elemből áll. Az se működött jól a kódon belül! Holnap teljesen új lappal kezdek és a tömböket kipróbálom önmagukban (megbillegtetem velük a RA3, RA4 lábakat), hogy melyikkel működik, melyikkel nem, s jobb híján ha nem akar működni, akkor feldobom a labdát a microchip fórumon is, hátha...
Oké, akkor elkezdem nemérteni az egészet @bbb azt írta a sima ram tömb kezelés kipróbálásáról, hogy nem működik.
A feltöltött verzióról:
- Nincs a forrásban a konfigurációs regiszterek beállítása. Default beállításnál az utasításkiterjesztés és a watchdog aktív. - Működik a nagy tömb kezelése, csak van egy apró hiba a programban, a main.c 157. sorában:
Mit is kellene csinálnia ennek a sornak és mit csinál helyette? A buf által megcímzett adatot (a buffer[0] -t) növeli ahelyett, hogy magát a pointert növelné...
Ez már a pointert növeli. Sajnos nincs I2C tesztelésére lehetőségem. A régi MpLab 8.90 beépített szimulátora buktatta le a hibát. Sajnos azzal sem lehet az I2C rutinokat szimulálni.
Szerintem a buf-ot így is léptetni kéne, mert azonos a precedencia, jobbról-balra történik a kiértékelés és a léptetés van először értelmezve, de utólag végrehajtva.
A megcímzett adatot így növelné:
Lehet, hogy tévedek, nem ellenőriztem.
Jelen esetben a *buf++ pontosan azt csinalja, mint a buf++. Megnoveli buf-ot eggyel. Igazabol nem is ertem, hogy a kod miert nem WriteI2C1(*buf++);
Mivel ebben a mikor növeljük és mikor a mutatott értéket növeljük dologban én se voltam biztos, ezért megkerestem ezt a leírást a pointerekről.
Nemsokára nekilátok a minimálkódnak, hogy vajon ott hogyan viselkedik a tömb, s utána kiderül mi történik. Egyébként volt egy sokkal viccesebb hiba is a korábban mellékelt kódban, méghozzá, hogy a tömb kezdőelemét a pointernek egy ciklussal kijjebb adtam meg, mint kellett volna, így a végtelenségig (túlcsordulásig) növekedett volna, mert sose áll vissza az első elemre. A most mellékelt kódban viszont az az izgalmas, hogy ha tényleg csak annyit változtatok, hogy a tömb hova kerül (const kulcsszó bekerül elé, vagy sem), akkor látszik a probléma.
Ráadásul rosszul is mondom a tünetet. Most a kommunikációt figyelve azt látom, hogy nem a nulladik elemet írja ki, hanem mindig 0x8F kerül ki (0x00 lenne a tömb első eleme).
Nem vagyunk hivatásos hibavadászok. Állítsd be a fejlesztődön a szimulátort és kövesd végig a programodat saját magad. Egyrészt sokkal gyorsabb lesz, másrészt látni fogod a változásokat sorról sorra. Ha ez sem segít, a PICkit3 -mal is van mód a program követésére....
Érdemes továbbá a fordított kódot is nézegetni a Program memória ablakban a Symbolic nézettel vagy a lista állományban pic18_i2c.X\dist\default\production\pic18_i2c.X.production.lst. Egyébként a legutóbbi változat már nem tartalmazza a buffer adatainak a program tárból a RAM -ba való másolását. Így nem is tűnik rossznak, hogy nem a várt adatot írja ki, hanem a RAM -ban találtat. A konstansnak megadott tömb esetén azért működik, mert nem kell másolni. Egyébként akkor az I2C rutinok működnek? Nem lehet, hogy a Watchdog reset közbeszólt? Az inicializáló adatmásolás ideje elég hosszú. Én vettem a fáradságot, MpLab 8.90 -nel végiglépkedtem a kiküldő ciklust... A hozzászólás módosítva: Júl 20, 2017
Még ha a standard meg is határozza, hogyan kell a "*buf++"-nak viselkednie, létezik az alkalmazott gyakorlat is. Amennyire elfuserált fordító program fejlesztések vannak a mai világban, a hócipő sem szeret megbízni abban, hogy az mindig úgy fog működni, ahogyan kellene. Jobb explicite szétszedni két statement-re, ha csak nem akarsz valamelyik verzió váltásnál extra munkát csinálni magadnak csak azért, hogy néhány text karaktert megspórolj a forráskódban, ami egyébként nulla különbséget fog eredményezni a végleges gépikódban. Nagyon fiatalok biztos szeretnek azzal bravúrkodni, de aztán majd fájni is fog a fejük miatta párszor, és leszoknak róla.
Szerintem a standard ilyen merteku megserese meg a mikrocsipnek sem fer bele, bar az o 8 bites forditojuk tenyleg csapnivalo. Nem jobb szetszedni, mert ha a fordito rendesen van megcsinalva, akkor rovidebb kodot eredmenyez, ha egybeirod. En 30 eve programozok C-ben, es csak biztatni tudok minden nagyon fiatalt es idost is, hogy hasznalja ki a C nyelv adottsagait, hogy szebb, rovidebb, atlathatobb, gyorsabb programokat irjon. A 30 ev alatt rengeteg C forditval dolgoztam mar, de ilyen alapveto dolgot egy sem rontott el. Ettol nem kell tartani.
Ha ennek a problemanak a vegere akarsz jarni, akkor csak az fog hatekonyan segiteni, ha megnezed a C programbol forditott assembly kodot.
Roppant furcsa, ugyanis ebbol a verziobol hianyzik az a resz, ami bemasolja a FLASH-bol a RAM-ba a 'buffer' valtozo tartalmat. Ezt hogy sikerult? A .lst file 1 masodperccel kesobb keszult, mint a main.c, tehat nem a forras valtozott utobb. Valtoztattal valami beallitast a forditasi opciok kozott?
Feltehetnel egy olyan .zip-et, amiben const van es jol mukodik.
Szerintem a C fordítók eléggé szépen szanaszéjjel vannak már optimalizálva ahhoz, hogy ezt a két sort:
A mikrocsip - és mindegyi másik is - csinál a mai világban sokkal őrültebb dolgokat is. Szerintem most simán bele tud férni, hogy elszúrjanak egy másodlagos precedencia szabályt. (És majd azt mondják róla, hogy az nem a standard megsértése, hanem a felújítása - példának okáért. Vagy elismerik hibának, viszont soha az életbe ki nem fogják javítani, míg végül mindenki hozzászokik, alkalmazkodik, végül standard lesz belőle ) A hozzászólás módosítva: Júl 20, 2017
Szia!
Itt bent van a const és jól működik (azt rajzolja ki a kijelző, amit kell). A Hp41C által említett watchdog timert kikapcsoltam, illetve a debughoz szükséges bitet is átírtam, így most tudom szimulálni, de a kód többi részén nem változtattam. És igen, biztos jól működik az I2C, minden üzenet, amit a kijelzőnek küldök, visszakapja az ACK-t (hogy ezt megmutassam, ezért csatoltam legutóbb a Salea Logic-ból kimentett, értelmezett forgalmat). Az XC8 linker opciói között van egy "Initialize data" opció, azt próbáltam ki, hogy mi történik, ha bekapcsolom, ez okozhatta a kérdésedben felvetett jelenséget. A hozzászólás módosítva: Júl 20, 2017
Az igaz, hogy egy jo fordito a ket fenti sort ugyanarra forditja (felteve, hogy 'p' nem volatile), de attol meg nem kell slendriannak lenni, vagy mondkjuk úgy, C-ben érdemes C-ül programozni és nem BASIC-ben. Es az operatorok precedenciaja az baromira nem egy masodlagos szabaly. Ez egy alapszabaly, amit nem sertenek meg még a mikrocsip forditok sem. Jo, hogy nem azt mondod, hogy lassan az "a + b * c" kifejezesben inkabb zarojelezzuk be a b * c-t, mert ezt is elronthatjak a forditok. Persze az is igaz, hogy a 8 bites PIC fordito nem reentrans kodot general, ami alapjaiban ellenkezik a C nyelvvel, de ezt irja is a fordito dokumentacioja. Persze innentol kezdve nem is lehetne C-nek hivni, mert ez lenne a C nyelv masik nagyon fontos tulajdonsaga.
De, hogy valami ertelme is legyen ennek a beszelgetesnek, ha megnezed bbb altal leforditott kodot, akkor lathatod az assembly listaban, hogy nem rontja el a *buf++ kifejezest, jot fordit belole.
Megint nagyon elkalandoztatok...
Ahogy megírtátok már egy oldallal előbb, a pointer növelése rendben megtörténik a disassembly lista szerint. Inkább a C sorban kifogásoltam az indirekt elérés szimbólumát, ami teljesen felesleges abban a sorban. A fordító szépen el is hagyta az FSR beállítását és az indirekt olvasást... Egyáltalán nem a tömbkezeléssel lesz a probléma, hanem inkább azzal, hogyan is van a buffer deklarálva. Szerintem a csomagban található C forrás és az lst állomány nem fedi egymást. Tudni kellene mi is történik, miért maradt ki a buffer inicializálása a második csomagbeli lst -ből. |
Bejelentkezés
Hirdetés |