 |
www.elektronik.si Forum o elektrotehniki in računalništvu
|
Poglej prejšnjo temo :: Poglej naslednjo temo |
Avtor |
Sporočilo |
71GA Član


Pridružen-a: Tor 16 Jun 2009 18:53 Prispevkov: 391 Aktiv.: 2.00 Kraj: Ljubljana
|
Objavljeno: Ned Jan 30, 2011 2:45 pm Naslov sporočila: |
|
|
Hvala za ponujeni link. Moj procesor je LPC3141 (arm626ej-s), startup kodo imam in prav tako linker skripto a jih zaenkrat še ne razumem... Sem našel nekaj razlage tukaj: http://www.math.utah.edu/docs/info/ld_3.html
Če lahko na hitro preletiš pa mi poveš, če je to tisto, kar potrebujem za razumevanje?
LP Žiga |
|
Nazaj na vrh |
|
 |
domen_puncer Član

Pridružen-a: Čet 01 Maj 2008 13:30 Prispevkov: 78 Aktiv.: 0.37 Kraj: Ljubljana, Mozirje
|
Objavljeno: Ned Jan 30, 2011 4:30 pm Naslov sporočila: |
|
|
Odpri linker skripto, potem pa v tem manualu poisci vse direktive, ki jih ne razumes.  _________________ Tiskanje sudoku |
|
Nazaj na vrh |
|
 |
71GA Član


Pridružen-a: Tor 16 Jun 2009 18:53 Prispevkov: 391 Aktiv.: 2.00 Kraj: Ljubljana
|
Objavljeno: Ned Jan 30, 2011 5:01 pm Naslov sporočila: |
|
|
domen_puncer je napisal/a: |
Ce ze pa ves kaj tocno ne ves, me pa poisci na ircu al nekje. |
Zanima me za začetek, kaj pomeni spodaj zapisana koda. Še posebej del *(.data). Za .data{...} vem, da je to sekcija in znotraj sekcije je definiran absolutni simbol _edata = ABSOLUTE(.), ampak tu ne vem kaj pomeni (.) za ABSOLUTE.
Koda: |
SECTIONS{ ...
.data :
{
*(.data)
_edata = ABSOLUTE(.) ;
}
... } |
Na strani to kodo razlaga približno takole: "For example, to create an absolute symbol whose address is the last byte of an output section named .data: ". Kaj to pomeni, da *(.data) opravi skok na konec sekcije?
LP Žiga |
|
Nazaj na vrh |
|
 |
71GA Član


Pridružen-a: Tor 16 Jun 2009 18:53 Prispevkov: 391 Aktiv.: 2.00 Kraj: Ljubljana
|
Objavljeno: Ned Jan 30, 2011 9:27 pm Naslov sporočila: |
|
|
Odpravil sem še nekaj napak (vsaj upam). Zamenjal sem linker skripto s skripto navedeno spodaj in pripadajočo startup kodo.
linker skripta:
Koda: |
ENTRY(_Reset)
SECTIONS
{
. = 0x0;
.text : {
startup.o (INTERRUPT_VECTOR)
*(.text)
}
.data : { *(.data) }
.bss : { *(.bss) }
. = . + 0x1000; /* 4kB of stack memory */
stack_top = .;
}
|
startup datoteka:
Koda: |
.section INTERRUPT_VECTOR, "x"
.global _Reset
_Reset:
B Reset_Handler /* Reset */
B . /* Undefined */
B . /* SWI */
B . /* Prefetch Abort */
B . /* Data Abort */
B . /* reserved */
B . /* IRQ */
B . /* FIQ */
Reset_Handler:
LDR sp, =stack_top
[slovenščina je zame španska vas] c_entry
B . |
In še ukaz, ki mi vrne le še eno napako:
Koda: |
arm-none-eabi-gcc -Wall -mcpu=arm926ej-s adc_example.c -static -L/home/ziga/Desktop/test_lib -I/home/ziga/Desktop/test_lib -llpc3141 -Ttest.ld
/home/ziga/projects/cs_lite/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/libc.a(lib_a-sbrkr.o): In function `_sbrk_r':
sbrkr.c:(.text+0x18): undefined reference to `_sbrk'
collect2: ld returned 1 exit status |
[/code] |
|
Nazaj na vrh |
|
 |
chaos Član


Pridružen-a: Sob 16 Sep 2006 22:12 Prispevkov: 1063 Aktiv.: 4.65 Kraj: Zagorje ob Savi
|
Objavljeno: Ned Jan 30, 2011 9:51 pm Naslov sporočila: |
|
|
Kje v kodi uporabljaš malloc ali podobno funkcijo? Kaj če bi za začetek ta del kode odstranil / zakomentiral? Ravno tako se izogibaj uporabi printf, scanf, ...
A ne bi mogoče za začetek začel z najbolj preprosto kodo - blinkanje ene ledice, brez kakršnihkoli knjižnic, brez standardne knižnice (-nostdlib), in najbolj preprosto linker skripto, v kateri bi imel samo dve sekcije text in data, katere bi obe preusmeril v RAM (interni). To narediš v assemblerju, toliko da vidiš, da stvari približno delujejo. Potem nadaljuješ v C-ju, kjer uporabiš še svoj startup (manjka skok v C main funkcijo!). Ko vse to dela, se spraviš pisati linker skripto, ki bo imela kodo v flashu. Za to moraš v startup kodo dodati še kopiranje data sekcije v RAM in brisanje bss sekcije.
LP! |
|
Nazaj na vrh |
|
 |
71GA Član


Pridružen-a: Tor 16 Jun 2009 18:53 Prispevkov: 391 Aktiv.: 2.00 Kraj: Ljubljana
|
Objavljeno: Pon Jan 31, 2011 12:01 am Naslov sporočila: |
|
|
chaos je napisal/a: |
Kje v kodi uporabljaš malloc ali podobno funkcijo? Kaj če bi za začetek ta del kode odstranil / zakomentiral? Ravno tako se izogibaj uporabi printf, scanf, ...
A ne bi mogoče za začetek začel z najbolj preprosto kodo - blinkanje ene ledice, brez kakršnihkoli knjižnic, brez standardne knižnice (-nostdlib), in najbolj preprosto linker skripto, v kateri bi imel samo dve sekcije text in data, katere bi obe preusmeril v RAM (interni). To narediš v assemblerju, toliko da vidiš, da stvari približno delujejo. Potem nadaljuješ v C-ju, kjer uporabiš še svoj startup (manjka skok v C main funkcijo!). Ko vse to dela, se spraviš pisati linker skripto, ki bo imela kodo v flashu. Za to moraš v startup kodo dodati še kopiranje data sekcije v RAM in brisanje bss sekcije.
LP! |
Saj bi rad začel s preprostim primerom, pa ga ne najdem... mogoče veš za kak primer za utripanje ledice, me lahko usmeriš in bom tam pobrskal. Največja težava se mi zdi to, da nikjer ni napisan step by step vodič za pisanje startup kode in pisanje linker skripte. Povsod je naštetih le kup opcij, (npr. tu http://www.math.utah.edu/docs/info/ld_3.html#SEC20) katere lahko vključiš/izključiš, nikjer pa nobenega primera, ki bi postopno pripeljal do rešitve. |
|
Nazaj na vrh |
|
 |
chaos Član


Pridružen-a: Sob 16 Sep 2006 22:12 Prispevkov: 1063 Aktiv.: 4.65 Kraj: Zagorje ob Savi
|
Objavljeno: Pon Jan 31, 2011 1:22 am Naslov sporočila: |
|
|
Začni s tako linker skripto:
Koda: |
MEMORY
{
ram : org = 0x11028000, len = 192k
}
SECTIONS
{
.text :
{
*(.vectors);
. = ALIGN(4);
*(.init);
. = ALIGN(4);
*(.text);
. = ALIGN(4);
*(.rodata);
. = ALIGN(4);
*(.rodata*);
. = ALIGN(4);
etext = .;
} > ram
.data :
{
PROVIDE (__data_start = .);
*(.data)
. = ALIGN(4);
PROVIDE (__data_end = .);
} > ram
.bss :
{
PROVIDE (__bss_start = .);
*(.bss)
. = ALIGN(4);
PROVIDE (__bss_end = .);
} > ram
}
|
Potem pa napiši program v assemblerju, ki samo nastavi primerne registre za GPIO (mode in direction), piši v primeren register (SET in RESET) za postavljanje pina na 0 in 1, vmes pa dodaj eno zanko za delay.
LP! |
|
Nazaj na vrh |
|
 |
71GA Član


Pridružen-a: Tor 16 Jun 2009 18:53 Prispevkov: 391 Aktiv.: 2.00 Kraj: Ljubljana
|
Objavljeno: Pon Jan 31, 2011 12:11 pm Naslov sporočila: |
|
|
Sem videl, da si na začetku podal memory map. Moj mikrokrmilnik ima ISRAM0 (96K), ISRAM1(96K) in ISROM0(128K). Podatke sem našel tu: LPC3141 user manual (glej stran 14 memory map).
Bi v skladu s tem moral memory zapisati drugače, ali mi to zakomplicira zadevo? npr:
Koda: |
MEMORY
{
ISRAM0 : ORIGIN = 0x11028000, LENGTH = 96K
ISRAM1 : ORIGIN = 0x11040000, LENGTH = 96K
ISROM0 : ORIGIN = 0x12000000, LENGTH = 128K
} |
V naslednjem delu si nato podal 3 output sekcije (.text, .data in .bss) in pripadajoče input sekcije (za output sekcijo .text so to npr vsi inputi s končnicami: .vectors, .init, .text, .rodata in .rodata<in še nekaj> ) kar razumem, ampak, ali obstaja kak dogovor, kaj spada kam? Ko opazujem to strukturo, mi je nekako logično, da so najprej definirani vektorji, nato init, ki predvidevam skoči na reset vektor (nisem prepričan ali je ta init v bistvu ENTRY, ker ga drugje ne vidim, ali bi moral biti?)
Znotraj output sekcije .text si uporabil ukaz . = ALIGN(4). Ali to pomeni, da si tu ustvaril prazen prostor širine 4? Vem, da s tem ukazom ne spremeniš location countra (.) ampak ga le navidezno premakneš za 4. Se pravi do konca output sekcije .text location counter kaže na začetek output sekcije .text, znotraj katere v razmikih 4 postavimo input sekcije?
Naslednja output sekcija .data mi delno ni jasna, saj je na strani ukaz PROVIDE zelo na kratko razložen in bi pottreboval kratko obrazložitev. Glede na prebrano predvidevam, da z PROVIDE ustvarimo simbol __data_start na način, da ni v konfliktu z input sekcijami, nato z ukazom __data_start = . postavimo začetek output sekcije na trenutno lokacijo, nato se premaknemo za 4 mesta in postavimo konec soutput sekcije z __data_end = . Zanima me, ali smo tu podali simbola __data_start in __data_end zato, ker jih nameravamo definirati v startup kodi?
Je še nekaj. Na koncu vsake sekcije je lociran ukaz > ram ali si s tem želel postaviti celotno sekcijo v ram, katerega si definiral na začetku pod MEMORY? Jaz bi najbrž potem tu moral izbrati npr. > ISRAM0.
PS: Pisanje programa v assemblerju bo mogoče zame še zahtevnejše kot pisanje linker skripte, saj v asemblerju še nisem spisal nobenega programa in sem obupno potreben enega zgleda. |
|
Nazaj na vrh |
|
 |
chaos Član


Pridružen-a: Sob 16 Sep 2006 22:12 Prispevkov: 1063 Aktiv.: 4.65 Kraj: Zagorje ob Savi
|
Objavljeno: Pon Jan 31, 2011 1:07 pm Naslov sporočila: |
|
|
71GA je napisal/a: |
Bi v skladu s tem moral memory zapisati drugače, ali mi to zakomplicira zadevo? npr:
Koda: |
MEMORY
{
ISRAM0 : ORIGIN = 0x11028000, LENGTH = 96K
ISRAM1 : ORIGIN = 0x11040000, LENGTH = 96K
ISROM0 : ORIGIN = 0x12000000, LENGTH = 128K
} |
|
To je bolj pravilno ja, samo glede na to, da sta oba RAMa zlozena skupaj, jih lahko navedes kot eno sekcijo. Ce le nista tretirana kako drugace., verjetno ne.
Citiram: |
V naslednjem delu si nato podal 3 output sekcije (.text, .data in .bss) in pripadajoče input sekcije (za output sekcijo .text so to npr vsi inputi s končnicami: .vectors, .init, .text, .rodata in .rodata<in še nekaj> ) kar razumem, ampak, ali obstaja kak dogovor, kaj spada kam?
|
Dogovor niti ne, ampak prakticno je najbolje narediti tako. Najprej pridejo na vrsto interrupt vektorji - ti so zmeraj na zacetku pomnilnika, prvi od teh je reset vektor. To sekcijo uporabis v loader kodi, kjer uporabis npr.
.init sekcija v bistvu tukaj ni pomembna, je zraven samo zaradi popolnosti. Za tem text sekcija, kar je vsa tvoja koda. Rodata je read-only data in je naceloma locirana v ROMu, torej pride takoj za kodo (text). V tem primeru, ko gre vse v RAM, bi lahko bila tudi kje drugje, samo zakaj ne bi bila kar tukaj - manj popravljanja linker skript med ROM in RAM varianto .
Drugace, ce imas kaksen dober razlog, lahko sekcije razporedis po svoje (samo vectors mora biti na zacetku), samo takole je kar nekako standardno.
Citiram: |
Ko opazujem to strukturo, mi je nekako logično, da so najprej definirani vektorji, nato init, ki predvidevam skoči na reset vektor (nisem prepričan ali je ta init v bistvu ENTRY, ker ga drugje ne vidim, ali bi moral biti?)
|
Pozabi init. Init ne skoci na reset vektor, tja skoci kar procesor sam (hardversko gledano je to reset vrednost PC registra). ENTRY res manjka v tej skripti, samo to lahko dodas sam ali v skripto, ali jo podas kot command line parameter, ali jo pa navedes v startup kodi. Postavi jo na recimo "_boot", in to ime uporabi kot label na zacetku vektorjev (_boot:).
Citiram: |
Znotraj output sekcije .text si uporabil ukaz . = ALIGN(4). Ali to pomeni, da si tu ustvaril prazen prostor širine 4? Vem, da s tem ukazom ne spremeniš location countra (.) ampak ga le navidezno premakneš za 4. Se pravi do konca output sekcije .text location counter kaže na začetek output sekcije .text, znotraj katere v razmikih 4 postavimo input sekcije?
|
. = ALIGN(4) pomeni, da naslovni kazalec (po potrebi) poravna na 32bitni naslov. Se pravi, ce je trenutna vrednost . = 0x01, bo ta ukaz prestavil naslov na 0x04. Ce je pa ternutna vrednost . = 0x08, pa ne bo naredil nic.
To je uporabno zato, da se sekcije zmeraj zacnejo poravnane na 32bitni naslov, kar seveda (med drugim) olajsa npr. kopiranje data sekcije iz ROMa v RAM.
Citiram: |
Naslednja output sekcija .data mi delno ni jasna, saj je na strani ukaz PROVIDE zelo na kratko razložen in bi pottreboval kratko obrazložitev. Glede na prebrano predvidevam, da z PROVIDE ustvarimo simbol __data_start na način, da ni v konfliktu z input sekcijami, nato z ukazom __data_start = . postavimo začetek output sekcije na trenutno lokacijo, nato se premaknemo za 4 mesta in postavimo konec soutput sekcije z __data_end = . Zanima me, ali smo tu podali simbola __data_start in __data_end zato, ker jih nameravamo definirati v startup kodi?
|
Simbola __data_start in __data_end se dejansko definirata v linker skripti s tem ukazom PROVIDE. Npr. prvi PROVIDE definira "spremenljivko" __data_start, katere vrednost je trenutna pomnilniska lokacija (= .). Torej ta spremenljivka kaze zacetek data sekcije. Uporabi se pa v boot kodi, da lahko po potrebi skopiramo data sekcijo v RAM.
Citiram: |
Je še nekaj. Na koncu vsake sekcije je lociran ukaz > ram ali si s tem želel postaviti celotno sekcijo v ram, katerega si definiral na začetku pod MEMORY? Jaz bi najbrž potem tu moral izbrati npr. > ISRAM0.
|
Tako je, s tem ukazom poves, da hoces podane sekcije v ta poimenovani pomnilnik. Torej ti res uporabis > ISRAM0.
Citiram: |
PS: Pisanje programa v assemblerju bo mogoče zame še zahtevnejše kot pisanje linker skripte, saj v asemblerju še nisem spisal nobenega programa in sem obupno potreben enega zgleda.
|
Tukaj pobrskaj za en primer, pa bo.
LP! |
|
Nazaj na vrh |
|
 |
71GA Član


Pridružen-a: Tor 16 Jun 2009 18:53 Prispevkov: 391 Aktiv.: 2.00 Kraj: Ljubljana
|
Objavljeno: Tor Feb 01, 2011 2:02 pm Naslov sporočila: |
|
|
chaos je napisal/a: |
Tukaj pobrskaj za en primer, pa bo.
|
Sem se lotil najlažjega primera z GPIO, ki je napisan sicer za drug cpu ampak bom nekako poiskusil prebroditi zadevo, saj je ISA (Instruction Set Architecture) nazaj kompatibilen, moj procesor pa je novejši, kot uporabljeni. Opazil sem, da so user modi podani z najnižjimi biti cpsr identični... glede vektorjev bom gledal kar v user manual mojega procesorja in bo.
Nekako razumem jezik uporabljen v linker skriptah in stvar je vse bolj jasna. Naslednji cijl je naučiti se jezik uporabljen v startup datotekah. Kar sem do sedaj prebiral, opazim precej asembly jezika, kaj pa so ostale zadeve, kot na primer .global, .set,...? Kateri jezik je to in kje je kaj napisanega o tem? Samo usmeritev potrebujem, da začnem prebirati potem pa bo stvar nekako šla.
Bi pa na hitro vprašal, kaj pomeni spodnja koda. Približno vem, da tu nastavimo stack za undefined mode, a ne vem, kaj pomeni 0x00000004 za vejico.
Koda: |
.set UND_STACK_SIZE, 0x00000004
|
|
|
Nazaj na vrh |
|
 |
chaos Član


Pridružen-a: Sob 16 Sep 2006 22:12 Prispevkov: 1063 Aktiv.: 4.65 Kraj: Zagorje ob Savi
|
Objavljeno: Tor Feb 01, 2011 7:16 pm Naslov sporočila: |
|
|
Koda: |
.set UND_STACK_SIZE, 0x00000004 |
Temu bi se lahko reklo konstanta - z set simbolu, v tem primeru UND_STACK_SIZE, priredis vrednost, to je 0x4.
Za razlago drugih (bolj kot ne preprocesorskih) ukazov assemblerju, isci GNU oz. GCC ASSEMBLER manual, nekje okrog Preprocessor Directives ali Assembler Directives.
LP! |
|
Nazaj na vrh |
|
 |
71GA Član


Pridružen-a: Tor 16 Jun 2009 18:53 Prispevkov: 391 Aktiv.: 2.00 Kraj: Ljubljana
|
Objavljeno: Tor Feb 01, 2011 9:18 pm Naslov sporočila: |
|
|
Aha tu igra vlogo torej preprocessor o katerem sem že toliko slišal pa nisme vedel kaj dela  |
|
Nazaj na vrh |
|
 |
71GA Član


Pridružen-a: Tor 16 Jun 2009 18:53 Prispevkov: 391 Aktiv.: 2.00 Kraj: Ljubljana
|
Objavljeno: Sob Feb 05, 2011 6:01 pm Naslov sporočila: |
|
|
Okej malo sem se ukvarjal s projektom tukaj in ta projekt je bojda osnovni a je že kup nekih datotek. Nekako ne vem, kje začeti gledati. Našel sem nekaj o jeziku uporabljenem v startup kodi in to je kar assembly, mislim, da so vsi ukazi za assembly nanizani v enem izmed manualov priloženih k paketu codesourcery g++ lite in namreč:
dokument: as
poglavje: assembly directives
Mislim, da so tam nanizani vsi ampak preden bom lahko razumel vso startup kodo, bo še trajalo...
Potreboval bi le potrditev za naslednjo hipotezo:
"V kolikor želim uspešno razumeti startup datoteko (assembly jezik), jo moram brati simultano z linker skripto.(linker script jezik)". Ali je priporočeno skupaj z omenjenima datotekama brati še kakšno, datoteko, ali se tidve najbolj tesno povezujeta ena z drugo. Predvidevam, da ko bom razumel tidve, se lahko lotim para header datoteka in source datoteka spisana v c. Tako sem si postavil načrt kako bom raziskoval zadevo... |
|
Nazaj na vrh |
|
 |
71GA Član


Pridružen-a: Tor 16 Jun 2009 18:53 Prispevkov: 391 Aktiv.: 2.00 Kraj: Ljubljana
|
Objavljeno: Sre Feb 09, 2011 1:21 am Naslov sporočila: |
|
|
Pojavilo se mi je vprašanje glede nekega ukaza, ki nastavi zastavice I in F. Ukaz se glasi:
Koda: |
.equ I_BIT, 0x80
.equ F_BIT, 0x40 |
Prebral sem, da je ukaz .equ podoben ukazu .set a, kaj je tu razlika? poleg tega sem si ogledal, zastavici I in F, ki sta 6. in 7. bit registra cpsr in ne vem, kakšno povezavo imata s tem števili 0x80 in 0x40. |
|
Nazaj na vrh |
|
 |
domen_puncer Član

Pridružen-a: Čet 01 Maj 2008 13:30 Prispevkov: 78 Aktiv.: 0.37 Kraj: Ljubljana, Mozirje
|
Objavljeno: Sob Feb 12, 2011 10:56 am Naslov sporočila: |
|
|
1<<7 je 0x80, 1<<6 je 0x40 _________________ Tiskanje sudoku |
|
Nazaj na vrh |
|
 |
|
|
Ne, ne moreš dodajati novih tem v tem forumu Ne, ne moreš odgovarjati na teme v tem forumu Ne, ne moreš urejati svojih prispevkov v tem forumu Ne, ne moreš brisati svojih prispevkov v tem forumu Ne ne moreš glasovati v anketi v tem forumu Ne, ne moreš pripeti datotek v tem forumu Ne, ne moreš povleči datotek v tem forumu
|
Uptime: 6 dni
Powered by phpBB © 2001, 2005 phpBB Group
|