Ich nutze einen lpc2378 und als Basis das FatFS System von Chan / Martin
Thomas
http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/efsl_arm/lpc23xx_chan_mci_20080914.zip
Da der ARM seine Aufträge in Form einer doppelt verketteten Liste
speichert (es sind structs) und diese Liste gleichzeitig eine
Prioritätswarteschlange ist, muss ich sie leider mit malloc erstellen,
da ich nur so effektiv das jeweils erste löschen und auf das nächste
Objekt verlinken kann.
Problem: malloc liefert immer einen NULL pointer zurück.
Habe mir dann die LPC2368-ROM.ld angeschaut, dort finde ich folgenden
Abschnitt:
1
.stack ALIGN(256) :
2
{
3
*(.stack)
4
*(.STACK)
5
PROVIDE (_stack = .);
6
. = ALIGN(4);
7
} > RAM
8
9
_end = . ;
10
PROVIDE (end = .);
11
12
.heap :
13
{
14
*(.HEAP)
15
. = ALIGN(4);
16
} > RAM
Und in der startup_gnu.S
1
@@Heap_Size EQU 0x00000000
2
@@ AREA HEAP, NOINIT, READWRITE, ALIGN=3
3
@@Heap_Mem SPACE Heap_Size
4
5
.equ Heap_Size, 0x00001000
6
.section .HEAP, "w"
7
.align 3
8
HeapMem:
9
.if (Heap_Size>0)
10
.space Heap_Size
11
.endif
.equ Heap_Size, 0x00001000 stand vorher auf .equ Heap_Size,
0x00000000, das habe ich nun geändert.
Beim Compilieren bekomme ich nun folgendes zurück:
1
section size addr
2
.text 25496 0
3
.data 2076 1073741824
4
.bss 5144 1073743900
5
.stack 10240 1073749248
6
.heap 4096 1073759488
7
.comment 1044 0
8
.debug_aranges 3040 0
9
.debug_pubnames 5726 0
10
.debug_info 109632 0
11
.debug_abbrev 21918 0
12
.debug_line 24580 0
13
.debug_frame 8784 0
14
.debug_str 12124 0
15
.debug_loc 35754 0
16
.ARM.attributes 16 0
17
.debug_ranges 3600 0
18
Total 273270
Gebracht hat es aber nichts.
mallinfo() gibt immernoch überall nur 0 0 0 0 0 0 0 ... zurück und die
Pointer nach malloc bleiben bei NULL.
Habe ich noch etwas vergessen?
Ich weiß man soll kein malloc benutzen, aber es gibt nur eine Funktion
die malloc benutzt und auch nur einen struct, somit ist es recht
überschaubar einen Überlauf zu verhindern. Man kann es später immernoch
auf ein selbstverwaltetes array umschreiben, das dauert in meinen Augen
aber ewig und vermiest die Codelesbarkeit.
Hab auch nirgendwo ein funktionierendes malloc Beispielprojekt im Netz
gefunden was auf GCC basiert...
Marco .. wrote:
> Ich weiß man soll kein malloc benutzen, aber es gibt nur eine Funktion> die malloc benutzt und auch nur einen struct, somit ist es recht> überschaubar einen Überlauf zu verhindern. Man kann es später immernoch> auf ein selbstverwaltetes array umschreiben, das dauert in meinen Augen> aber ewig und vermiest die Codelesbarkeit.
Nicht wirklich.
Wenn du nur einen einzigen Typ dieser 'dynamischen' Strukturen hast,
dann ist es trivial sich einen malloc Ersatz zu bauen.
Du legst dir ein Array deiner Strukturen an, verpointerst sie
entsprechend. Zusätzlich hast du noch einen Pointer, der die Freelist
verkörpert, also alle Strukturen die vorrätig sind. Bei jeder
Allokierung rückst du eine Struktur raus (sofern noch was da ist) und
setzt den Freelist Pointer entsprechend nach. Bei jedem Free wird die
Stuktur wieder in die Freelist eingekettet.
1
structMyData{
2
3
...
4
structMyData*next;
5
};
6
7
#define MEMORY_SIZE 1024
8
structMyDatamemory[MEMORY_SIZE];// Vorrat an 'Objekten'
9
structMyData*freeList;
10
11
voidinitMemory()
12
{
13
inti;
14
for(i=0;i<MEMORY_SIZE-1;++i)
15
memory[i].next=&memory[i];
16
memory[MEMORY_SIZE-1].next=NULL;
17
18
freeList=&memory[0];
19
}
20
21
structMyData*allocate()
22
{
23
structMyData*retVal=freeList;
24
if(freeList)
25
freeList=freeList->next;
26
returnretVal;
27
}
28
29
voiddispose(structMyData*garbage)
30
{
31
if(garbage){
32
garbage->next=freeList;
33
freeList=garbage;
34
}
35
}
Wenn man nicht allgemein sein muss, ist es leicht, schnelle Funktionen
zu schreiben. Interessant wird es erst, wenn die Allokierung mit
beliebigen Größen zurecht kommen muss :-)
Vielen Dank!
Das sieht wirklich sehr gut aus. Gestern konnte ich mir einfach nicht
vorstellen wie ich die free Liste verwalten soll, aber das hier ist ein
wirklich schönes Beispiel.
Ich habe mir mal die Freiheit genommen es in meinen Code zu integrieren!
;) Ein paar kleinere Fehler muss ich noch beheben bei mir, dann bin ich
froh endlich zum nächsten Punkt auf der TODO-Liste überzugehen.
Falls ich trotzdem nochmal irgendwann in die Verlegenheit eines mallocs
kommen sollte, vielleicht weiß noch jemand die Lösung warum es nicht
geht?
Grüße
Hallo,
warum soll malloc nicht funktionieren beim GCC? Ich habe bald die
gleiche Aufgabe vor mir die Chan Fat ans Laufen zu bekommen, mir graust
jetzt schon davor.
Es ist ein neues Sample Projekt auf der Homepage aufgetaucht, was auf
einem 23xx laufen soll. Mir scheint der Code sehr stark von MT
abgeschrieben zu sein aber wesentlich komnpakter und vor allem von allen
Keil Funktionen befreit.
Mal eine allgemeine Frage:
Was macht dieses Demoprogramm? Ich habe so den Eindruck, dass es in
einem Terminalfenster bestimmte Funktionen bereitstellt, so dass man
Befehle eingeben kann, die auf die Karte bezogen werden.
Ich weiß nicht ob es am GCC liegt, kann auch ein Fehler im Startup-Code
des Projektes sein, dass das Heap anlegen verhindert. Ich muss nochmal
die Variante von Chan ausprobieren. Er hat im Linker auch die
Unterstützung für den Ethernet-RAM drin, was ich sowieso noch
integrieren muss.
Hatte ich noch garnicht gesehen mit .0.07a, die wichtigste Neuerung in
meinen Augen scheint die Unterstützung von langen Dateinamen zu sein,
was mich aus Lizenzrechtlichen Gründen eher stutzig macht. Packt man es
in ein kommerzielles Projekt, würde ich es eher bei der 0.06 belassen.
Multitaskunterstützung ist natürlich auch nett.
Ja das ist richtig, du hast eine schicke Kommandozeile mit der du zum
Beispiel die SD-Karte formatieren kannst (laut Empfehlung ist dann der
Zugriff schneller als wenn man es auf einem PC formatiert), Datei
anlegen und reinschreiben und auch einige Funktionen wie Uhrzeit setzen
geben dir einen guten Einstieg um die Prozeduraufrufe besser zu
verstehen. Nachdem ich meine Hardwareprobleme gelöst hatte und gemerkt
habe, dass ich nur FlashMagic an UART0 bei meinem Olimex benutzen kann
wegen der de-assert Mäglichkeit von RTS und CTS lief es eigentlich sogar
auf Anhieb. LED-Adresse hab ich spaßeshalber noch angepasst und das
wars.
Es wird 1000Mal pro Sekunde der Timer aufgerufen für diskio. In
Wirklichkeit tut sich dort aber nix mehr, außer dass glaub ich eine
Variable hochgezählt wird, die nirgendwo benutzt wird. Früher war das
anders, ich werds demnächst mal rausnehmen und schauen was passiert.
hallo,
ich habe ggrad mal versucht das Sample Projekt für den 2368 zu laden,
was am 14.4. hochgeladen wurde. Erzeugt in der Rowley Oberfläche
cryptische Fehler im Assemberteil, absolut keine Ahnung was da mit wem
kollidiert, angeblich wäre das .vector Segment voll usw. Es ist zwar
schön, wenn Leute ihre Codes ins Netz stellen aber mit Assemberdateien
werden diese einfach inkompatibel zudem so gut wie keiner heute mehr
Risc Assembler kann. Keine Ahnung wie ich das in Rowley importieren
soll, die Oberfläche stellt startup.s, makefile usw bereit, der User
sieht nur das Fronend aber nichts was auf Maschinenebene abläuft.
Wozu der Timer da läuft weiss ich auch nicht, für das Projekt absolut
unsinnig, da der Betreib einer SD karte keine derart ressourcen
fressende Sache braucht.
Trotzdem gut, dass Chan ein übersichtliches Projekt zusammen gestellt
hat und diese 5 Diskio Funktionen mit fertigem Code gefüllt hat.
Heap kann ich bei mir in einem GDI einstellen, daraus wird das Makefile
erzeugt, hilft Dir aber auch nicht weiter.
PS: Malloc klappt bei mir einwandfrei.
.heap 4000000c4 - 400004c3 (1024 Bytes)
testvec = (void*)malloc(100)
setzt testvec auf Adresse 0x40000458, also am oberen Rand des Heap
Hallo,
nochmal rauf damit. Wiese meckert der GCC diese Zeile an:
typedef enum { FALSE = 0, TRUE } BOOL;
"expected identifier before ( token"
Abgesehen davon dass ich sowas gar nicht erst schreiben würde, was ist
daran falsch? BOOL Funktionen können TRUE oder FALSE zurückliefern, also
0 oder 1.
Habe das mal durch
typedef unsigned char BOOL
ersetzt, dann ist Ruhe aber ob das das Gleiche ist....
Ich drehe bald ab.......
In der type.h bei Martin wird BOOL auch als unsigned char definiert,
TRUE und FALSE dann noch als define. Ansonsten seh ich an dem enum
eigentlich auch keinen Fehler. Vielleicht war TRUE und FALSE schon an
anderer Stelle definiert und der Compiler weiß nur mal wieder nicht den
wirklichen Fehler auszuspucken. Wäre zumindest möglich, denn sonst würde
er ja jetzt sagen, dass er TRUE und FALSE nicht kennt.
Früher wurden über den Timer wohl Timeouts erkannt, aber jetzt...
das ist ja wirklich sehr ärgerlich (für mich) mit dem malloc, dann werd
ich sein Beispiel auch mal ausprobieren. Aber ansonsten belasse ich es
mit meinem Array. Ich muss noch Inkonsistenzen rausbekommen, da ich das
erste Element in einem Interrupt entferne, einfügen findet aber im
normalen Programmablauf statt. Ganz böse...
Ich hab grad gesehen, dass Chan zwar den Ethernet-RAM definiert, der
Ethernet-Block aber in der startup.s überhaupt nicht aktiviert wird.
Naja... bei KEIL gibts nen Beispiel, werd ich am Wochenende mal
einbauen...
Hallo....
(4h später)
nachdem ich das Beispiel geradezu vergewaltigt habe, um es in mein
Basisprojekt für mein Thailand-Board als Unterverzeichnis einzubauen bin
ich zumindest soweit, dass die Karte initialisiert wird. Ausserdem habe
ich alle WORD,DWORD und sonsstigen Murks durch die stdint.h Definitionen
ersetzt usw. Kompiliert einwandfrei durch aber erzeugt mal eben 50kb
neuen Code.
Wieso der GCC den nicht benutzen Code nicht ausblendet weiss ich nicht.
Optimierung geht wegen eines Bugs (laut Rowley FAQ) nicht, sonst sind
meine ISRs futsch. Ich erhalte dann ständig die Fehlermeldung: Writeback
of Base registers is unpredictable.
1
Q:I'mgettinga"Warning: writeback of base register is UNPREDICTABLE"
Diese Funktion da unten ist sehr ärgerlich, weil sie jede Menge
Rechenzeit frisst aber wenn Du Dich nicht detailliert mit den IO
Funktionen in diskio.c auseinandersetzen willst, dann lass sie drin, die
bedient die Timeout Timer, die dutzendfach verwendet werden.
Es werden wohl noch einige Tage ins Land ziehen, bevor ich das am Rennen
habe.....
Ich lern gern dazu, was für ein Thailand-Board?
Schau dir mal das selbe disk_timerproc bei Martin Thomas an, alles unter
dem Timer decrement ist mit einem #if 0 auskommentiert. Timer1 wird
verringert, aber Timer1 wird nirgendwo im Projekt auch nur einmal
ausgelesen.
Somit nach einmal drüber sehen nutzlos. Auf jeden Fall hab ich hier im
Forum schonmal gelesen, dass man zumindest das Timerintervall verringern
kann und das bezog sich auf den Chan Originalcode.
http://cgi.ebay.de/ws/eBayISAPI.dll?ViewItem&item=170303047473
Schlage mich grad mit Fast GPIO und Slow GPIO herum, weil man die wohl
nicht mischen kann und mein LCD Slow GPIO benutzt und ich keine Lust
habe den nfertigen Code wieder umzuschreiben.... derzeit entweder SD
Karte oder LCD.
Ich nutze den Code von MT nicht, ist mir zu undurchsichtig. Der von Chan
im Sample projekt für LPC23xxx (wurde erst gestern hochgeladen!) ist
besser strukturiert und basiert nicht auf Keil.
(kipp ins Bett)
Hm, also da weiß ich, dass das geht.
SD-Karten Zugriff ist bei mir unabhängig ob GPIOM gesetzt ist oder
nicht. Hab ich mit der Status LED probiert die statt 500ms, 100ms
blinken sollte. GPIO war zu träge so dass sie nicht an ging, mit FGPIO
lief es. SD-Karten Zugriff war zu keiner Zeit beeinflusst. MCI ist ja
auch ne Zweitfunktion und ist völlig unabhängig von der GPIO-Config.
Sonst müsste man ja auch Output-Richtung setzen etc.
Gruß, Marco
Hallo,
es läuft.....teilweise...
Die Chan Fat schmiert hier ab, wenn ich eine 2GB SD karte (Type: 4)
einstecke, verliert sich vermutlich in einer Rekursion von diskio_ctl.
ergebnis = disk_ioctl(0, GET_BLOCK_SIZE, &p2);
Bei einer anderen 2GB (Type:2) läuft sie durch.
Tja, wird wohl kaum zu beheben sein das Problem.
Schon beim Einstecken, Formatieren ist also garnicht erst möglich? Sehr
merkwürdig. Ich nutze eine 4GB non-SDHC von Transcend und es tut ohne
Probleme bisher, einen Dauertest setze ich aber für nächste Woche an.
Die hier: Conrad 411848 TRANSCEND SD KARTE 4GB 133X ULTRA S
Class 6... hat vor ner Weile aber noch deutlich weniger gekostet.
Hallo,
ich habe die neue LFN Chan Fat auf meinem LPC2368 nachts durchlaufen
lassen, die Karte mit Uhrzeiten in einem File beschrieben. Klappt soweit
(ohne LFN!). MMC karten werden immer erkannt, bei "Typ 4" Karten (was
immer das auch ist meckert er manchmal, dass er "diskio_ctl get block
size" nicht ausführen kann, es kommt ein FP_NO_PATH Fehler aber eben nur
manchmal. File öffnen, schreiben, zumachen geht aber. Die Gschwindigkeit
habe ich auf 15 Mhz runtergedreht, ich halte 25 bei meinem Board bei
5-7cm Leitungslänge für zuviel.
Heute werde ich mal den Code aufräumen, alles nur drangeklatscht
gestern, hauptsache läuft. Wirklich befriedigend ist es leider nicht,
die disk_io Funktionen für den LPC2368 verstehe ich nicht mal im Ansatz,
Chan arbeitet sehr viel mit 2-Buchstaben Variablen, was es nicht gerade
lesbarer macht.
Der ganze Ramsch mit dem SD Interface ist viel komplizierter als es mit
der SPI war. Da war es eindeutig, Kommando raus, Datensatz oder response
rein, habe ich damals selbst geschrieben und lief super. In die ff.c
habe ich erst gar nicht reingeschaut, LFN läuft aber nicht, weil er
ff_convert anmeckert, da ist ein chinesischer Zeichensatz in einer
Datei, ich habe jedoch die Codepage auf US 437 eingestellt. Chan hat
hier vermutlich einen Fehler gemacht, ff_convert wird ständig benutzt.
Hat schonmal jemand von Euch das LPC2368 SD Interface in seiner Tiefe
durchdrungen und weiss es anzuwenden? Oder benutzt ihr auch Code, den
ihr zwar nicht versteht, dessen API aber läuft?
Können wir evtl. einen neuen Thread aufmachen für die neue Chan FAT auf
LPC ARM7 Controllern?
Ist übrigens schonmal jemandem aufgefallen, dass die Definition von
typedef unsigned short WORD
komischerweise beim compilieren nur 8 statt 16-Bit sind? Ein
schwerwiegender Fehler! Da aber nirgendwo WORD benutzt wird, ist es wohl
noch keinem aufgefallen. Liegt das am Compiler?
Christian J. wrote:
> Können wir evtl. einen neuen Thread aufmachen für die neue Chan FAT auf> LPC ARM7 Controllern?
Da hab ich nix dagegen. Wenn du es eröffnet hast, dann kannst du es ja
hier verlinken damit ich es nicht übersehe.
> Hat schonmal jemand von Euch das LPC2368 SD Interface in seiner Tiefe> durchdrungen und weiss es anzuwenden? Oder benutzt ihr auch Code, den> ihr zwar nicht versteht, dessen API aber läuft?
Naja, MCI, 4-Bit pro Takt da 4 Leitungen und das wars dann schon. Ich
kenne aber einen der den Code von Martin durchgearbeitet und
Fehlerbereinigt hat (er wird auch im Changelog erwähnt). Deswegen
benutze ich diese stabile Version und nicht die direkt von Chan.
Tilo Lutz wrote:
> Wie viel Ram hast du?> Benutzt du auch die Newlib?>> Eventuell hast du das selbe Problem, dass ich hatte:> Beitrag "Problem mit malloc() und -O2"
32KByte RAM von denen 6,5KByte voll sind, 10KByte Stack. Das mit der
Newlib ist ne gute Frage, benutze das yagarto Paket, ist das da mit bei?
Hm das Topic hatte ich schonmal über die Suche gefunden, aber hab leider
vergessen das mal mit den Compiler-flags auszuprobieren. Werde ich jetzt
mal tun.
Marco .. wrote:
> Ist übrigens schonmal jemandem aufgefallen, dass die Definition von> typedef unsigned short WORD> komischerweise beim compilieren nur 8 statt 16-Bit sind? Ein> schwerwiegender Fehler! Da aber nirgendwo WORD benutzt wird, ist es wohl> noch keinem aufgefallen. Liegt das am Compiler?
Ok, Kommando zurück. Hab mich dadurch irritieren lassen, dass er wohl in
structs bei BYTE ein WORD reserviert.
Das Beispiel von Chan funktioniert bei mir überhaupt nicht.
Bekomme immer FR_NO_PATH oder FR_NOT_READY zurück.
Die Initialisierung bei ihm ist ja ein echter Krampf. Vor allem warum
gibt er selbst diskio.c vor für die Implementierung der Routinen und
packt selbst alles in die mci.c?
Hat es jemand zum laufen bekommen? Bei Martins Code musste ich auf der
Konsole nur fi 0 eingeben und dann konnte ich schon mit fo 10 hallo eine
datei öffnen und reinschreiben. Hier hagelt es auf meinem Olimex nur
Fehler.