Forum: Mikrocontroller und Digitale Elektronik Doxygen für Mikrocontroller-Projekte


von Walter T. (nicolas)


Lesenswert?

Hallo zusammen,

kennt jemand ein Positivbeispiel für ein Mikrocontrollerprojekt, wo 
Doxygen zur Dokumentation eingesetzt wurde, wo man sich mal ein paar 
Tricks abschauen kann?

Am meisten interessiert mich die sinnvolle Behandlung von Makro-Orgien, 
wie sie insbesondere bei der Definition von Pinouts und 
Hardware-Einstellungen vorkommt. Die meisten Tutorials und Anleitungen 
lassen dagegen Makros gerne außen vor und behandeln sie bestenfalls am 
Rande.

Ich nenne mal einen Klassiker: Das Pinout für einen 8-Bit-Parallel-Port. 
Der einzig denkbare Weg, der mir einfällt, das aufzunehmen, wäre so:
1
  /** @name Grafik-LCD - Ansteuerung
2
     *
3
     * Es koennen unterschiedlich angebundene Display-Module per Parallelport oder SPI angesteuert
4
     * werden.
5
     * Achtung: PC13, PC14 und PC15 am STM32F446 koennen die Datenleitungen am Parallel-Port des
6
     * Displaymoduls nicht treiben!
7
     * @{ */
8
9
10
    /** Variante der Anbindung des Grafik-LCDs/TFTs parallel/Soft-SPI/Hard-SPI */
11
    #define TFT_ILI9XXX_CONNEXION_PARALLEL_8BIT
12
    //#define TFT_ILI9XXX_CONNEXION_SPI_BITBANG
13
    //#define TFT_ILI9XXX_CONNEXION_SPI_DMA
14
15
    #define GLCD_RST_PIN  PC0               /**< Steuer-Port: Reset */
16
    #define GLCD_CS_PIN   PC1               /**< Steuer-Port: Chip select */
17
    #define GLCD_RS_PIN   PC2               /**< Steuer-Port: Register select / Data/Command */
18
    #define GLCD_WR_PIN   PC3               /**< Steuer-Port: Write enable (nur parallel) */
19
    #define GLCD_RD_PIN   PB0               /**< Steuer-Port: Read enable (nur parallel) */
20
21
    /* Grafik-LCD Daten-Port (Parallel) */
22
    #define GLCD_DATA_D0_PIN PC5            /**< Parallel-Port: D0 */
23
    #define GLCD_DATA_D1_PIN PC6            /**< Parallel-Port: D1 */
24
    #define GLCD_DATA_D2_PIN PC7            /**< Parallel-Port: D2 */
25
    #define GLCD_DATA_D3_PIN PC8            /**< Parallel-Port: D3 */
26
    #define GLCD_DATA_D4_PIN PC9            /**< Parallel-Port: D4 */
27
    #define GLCD_DATA_D5_PIN PC10           /**< Parallel-Port: D5 */
28
    #define GLCD_DATA_D6_PIN PC11           /**< Parallel-Port: D6 */
29
    #define GLCD_DATA_D7_PIN PC12           /**< Parallel-Port: D7 */
30
31
    /* Grafik-LCD: SPI-Port (Soft-SPI) */
32
    #define GLCD_SPI_SCK_PIN  PC10          /**< Soft-SPI: SCK  */
33
    #define GLCD_SPI_MISO_PIN PC11          /**< Soft-SPI: MISO */
34
    #define GLCD_SPI_MOSI_PIN PC12          /**< Soft-SPI: MOSI */
35
36
    /** Grafik-LCD: SPI-Port (Hard-SPI mit DMA) */
37
    //#define SPI_HARD_DMA spi_hard_STM32F4XX_SPI1_PA5_PA6_PA7
38
    //#define SPI_HARD_DMA spi_hard_STM32F4XX_SPI2_PB13_PB14_PB15
39
    #define SPI_HARD_DMA spi_hard_STM32F4XX_SPI3_PC10_PC11_PC12
40
41
42
43
    /** Definition des Grafik-LCDs/TFTs
44
45
      - TFT_ILI9341 : ILI9341 basiertes TFT (320x240 px)
46
      - TFT_ILI9488 : ILI9488 basiertes TFT (480x320 px)
47
48
      Auch im Falle der Display-Emulation per SDL wird die Groesse des emulierten TFT aus dieser
49
      Bezeichnung abgeleitet. */
50
    #define TFT_ILI9341
51
    //#define TFT_ILI9488
52
/** @} */

Klar - was hier entsteht, ist nicht hilfreich, sondern nur 
formalistische Dokumentation. Die erzeugte HTML-Seite ist deutlich 
unübersichtlicher als der Quelltext. Aber wie macht man es richtig? Wo 
findet ma Positivbeispiele?

: Bearbeitet durch User
von Markus W. (dl8mby)


Lesenswert?

Walter,

ob es ein gutes Beispiel für Dich ist kann ich nicht direkt
beurteilen, aber das mcHF Projekt des OV Sulingen,
siehe ersten Thread:

Beitrag "mcHF-SDR Selbstbau-Projekt"

Verwendet Doxygen zur Projektdokumentation.

Du musst ins github gehen, wo das Projekt gehosted wird.

Gruß
Markus

von Stefan F. (Gast)


Lesenswert?

Schreibe die erklärenden Kommentare immer oben drüber, nicht rechts 
daneben. Dann kommt dabei auch ein gescheiter Output heraus.

Hier ein Beispiel in C++ (nicht Mikrocontroller): 
http://stefanfrings.de/qtwebapp/index.html

Ich bevorzuge die Javadoc Syntax, weil ich hauptberuflich in Java 
programmiere und sie von da her auswendig kenne. Doxygen kann das.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Walter T. schrieb:
> Aber wie macht man es richtig?

Du musst halt überlegen, wo du überhaupt überall Doxygen-Tags dran haben 
möchtest, und wo das nicht sinnvoll ist.

Ansonsten bleibt immer noch die Möglichkeit, bestimmte Dinge "schön" mit 
#ifdef DOXYGEN zu kommentieren, die eigentliche Funktionalität (die der 
Compiler dann benutzt) jedoch im #else-Zweig unterzubringen. Ins 
doxyfile kommt dann ein -DDOXYGEN rein.

Die komplette avr-libc-Doku ist mit Doxygen erstellt. Sicher ist da 
manches auch nicht sooo schön drin, aber es ist allemal besser als gar 
keine Doku oder eine, die massiv von der eigentlichen Implementierung 
divergiert.

von Walter T. (nicolas)


Lesenswert?

Hallo,

in das MHCF-Projekt habe ich zuerst einen Blick geworfen. In der ersten 
Quelltext-Datei die ich gelesen habe, steht sinngemäß: "Das müßte mal 
jemand sauberer kommentieren!" Damit ist es als Vorbild zwar nicht 
unbedingt allererste Wahl, aber ich fühle mich jetzt weniger allein.

Den Trick mit dem #ifdef-Doxygen nutze ich auch schon an ein paar 
Stellen. Mir ist noch nicht klar, wie es als "best practice" bei 
Pin-Listen helfen soll. Aber ich werfe mal den Blick in den 
AVR-GCC-Quelltext. Da gehe ich mal davon aus, daß die vielen Augen schon 
die am wenigsten schlechte Lösung zusammengestellt haben.

von Mikro 7. (mikro77)


Lesenswert?

Vielleicht etwas Grundsätzliches: Ich würde, wenn möglich, Daten und 
Code zusammenhalten. Daher bin ich kein Fan von den #define Orgien in 
den Headern (bei Literalen ist es wohl noch ok, aber ich würde trotzdem 
versuchen, den Präprozessor rauszuhalten). Wenn man es denn doch macht 
(es gibt ja schon ein paar Gründe), dann einfach die Kommentare in den 
Code schreiben. Doxygen hilft da imho nicht groß weiter: Da wechselt man 
besser gleich zur Codeansicht. my 2 ct

von Walter T. (nicolas)


Lesenswert?

Jetzt habe ich mir mal die AVR-Libc angeschaut. Ganz durchgestiegen bin 
ich noch nicht, wie die Doku gebaut ist, aber zumindest ist mir 
aufgefallen, daß in den Registerlisten (ich greife jetzt einfach 
exemplarisch iom644.h heraus) die Kommentare gar nicht für Doxygen 
gedacht sind. Manche Header sind voll DoXumentiert (z.B. string.h), aber 
insgesamt scheint die Durchdringung von Doxygen-Kommentaren recht gering 
zu sein.

Für mich schließe ich den daraus, dass die AVR-libcs-Entwickler der 
Meinung sind, dass das Werkzeug für Makros mehr hinderlich als nützlich 
ist.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Naja, Ziel der avr-libc-Doku ist es nun nicht, eine Kopie des 
Datenblatts bereitzustellen und jegliche IO-Register dort nochmal zu 
dokumentieren. Das würde den Aufwand ins Unermessliche steigen.

Es soll eine Dokumentation der Library sein, aber dort gehören durchaus 
dann auch die Makros mit dazu, siehe beispielsweise hier:

https://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html

Wenn du dir das Headerfile dazu mal ansiehst, wirst du aber feststellen, 
dass wir da ganz viel mit besagtem #ifdef DOXYGEN gearbeitet haben, da 
es meiner Meinung nach eben nicht Sinn einer Anwenderdoku sein sollte, 
dass man dem Anwender dort dann die Details der Implementierung des 
Makros an den Kopf knallt, wie es Doxygen standardmäßig tut.

(Die Liste der Vektornamen weiter unten selbst ist irgendwie automatisch 
erstellt und leider nicht mehr wirklich aktuell.)

von DPA (Gast)


Lesenswert?

Die Doku, was wo angeschlossen ist würde ich sowieso nicht aus dem 
Sourcecoude ziehen, sondern in ein Markdown File oder so packen. Doxygen 
kann Markdown seiten in die Doku Aufnehmen.

von Walter T. (nicolas)


Lesenswert?

Jörg W. schrieb:
> siehe beispielsweise hier:
>
> https://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html

Danke, das gucke ich mir mal an.

Jörg W. schrieb:
> [...] da
> es meiner Meinung nach eben nicht Sinn einer Anwenderdoku sein sollte,
> dass man dem Anwender dort [...]

Okay, da habe ich auch einen komplett anderen Anwendungsfall. Ich will 
in Doxygen den Quelltext dokumentieren, nicht die Anwendung.

DPA schrieb:
> Die Doku, was wo angeschlossen ist würde ich sowieso nicht aus dem
> Sourcecoude ziehen, sondern in ein Markdown File oder so packen.

Soooo groß sind meine Projekte zum Glück doch noch nicht, daß ich im 
Header-File die Übersicht über die Pins verlieren würde.

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Walter T. schrieb:
> Ich will in Doxygen den Quelltext dokumentieren, nicht die Anwendung.

Naja, den Quelltext kommentiert man in Kommentaren. :-)

Doxygen brauche ich doch eigentlich nur dafür, dass jemand auch ohne 
Quelltext schon mal eine Idee hat, was er wie damit machen kann. 
Natürlich ist Doxygen auch Kommentar, aber ich kann eben zusätzlich im 
Quelltext noch weitere Kommentare unterbringen, die nicht verdoxygent 
werden.

Meiner Erfahrung nach ist es dabei sinnvoll, nicht jede Zeile (also 
jeden Makro bei dir) einzeln zu kommentieren, sondern lieber davor eine 
Erklärung "in Prosa" als Block setzen. In den Details dokumentiert sich 
vieles bei geschickter Namenswahl dann selbst, kommentiert werden muss 
nur noch das, was nicht so offensichtlich ist.

Beispiel aus einem aktuellen (QRL-)Projekt:
1
/*
2
 * Should be defined in the vendor header files but isn't.
3
 */
4
#ifndef USBHS_RAM_ADDR
5
#define USBHS_RAM_ADDR        (0xA0100000)
6
#endif
7
8
// This name is mentioned in datasheet, but defined nowhere
9
#define USBFIFOxDATA(ep)      ((uint8_t *)(USBHS_RAM_ADDR + 0x8000 * (ep)))
10
11
// The headers have USBHS_DEVEPTISR_BYCT() but it's implemented as a
12
// macro to write the byte count field rather than read it.
13
#define BYTECOUNT(ep)         ((USBHS->USBHS_DEVEPTISR[ep] & USBHS_DEVEPTISR_BYCT_Msk) >> USBHS_DEVEPTISR_BYCT_Pos)

Nun darf jeder raten, was für ein Controller das ist. :-))

von Gunnar F. (gufi36)


Lesenswert?

Hallo zusammen,

ich bin nicht sicher, ob meine Frage in diesen Thread gehört.
Seit einiger Zeit arbeite ich mich in die NXP-Controllerfamilien 
CortexM3 und ähnliche herein (.. war schon ein steiniger Weg...) und 
versuche die zu programmieren unter Keil MDK5.

Mein Problem (eins davon!) ist die mangelnde Unterstützung der Hilfe zu 
den Elementen, die nicht Teil von CMSIS sind. (Hier primär die 
fsl_gpio.h).
Es gibt dazu keine Hilfe und ich muss die Header und *.c dateien lesen 
um zu verstehen, wofür ich die Routinen einsetze. Das fällt mir 
besonders schwer wegen der vielen kryptischen #defines, z.B.

#if (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT) && 
FSL_FEATURE_GPIO_HAS_INTERRUPT)
#define GPIO_PIN_INT_LEVEL 0x00U
#define GPIO_PIN_INT_EDGE 0x01U

.. wovon ich dann keine Ahnung habe, wo die herkommen (definiert werden) 
und die es mir schwer machen, den Code zu lesen.
(Keil markiert scheinbar NICHT durch #if deaktivierten Codezeilen grau).

Und in diesen Headern IST etwas, was ich für Doxygen gehalten habe, aber 
ich verstehe nicht WAS TUT DIESE "HILFE" für mich beim Programmieren?
/*@}*/

/*! @name GPIO Output Operations */
/*@{*/

/*!
 * @brief Sets the output level of the one GPIO pin to the logic 1 or 0.
 *
 * @param base    GPIO peripheral base pointer(Typically GPIO)
 * @param port   GPIO port number
 * @param pin    GPIO pin number
 * @param output  GPIO pin output logic level.
 *        - 0: corresponding pin output low-logic level.
 *        - 1: corresponding pin output high-logic level.
 */
static inline void GPIO_PinWrite(GPIO_Type *base, uint32_t port, 
uint32_t pin, uint8_t output)
{
    base->B[port][pin] = output;
}

IST das überhaupt Doxygen?
Beim Eintippen im Code-Editor erscheint eben KEINE Hilfe zu den 
Funktionen, wie ich es von Eclipse-basierten IDEs kenne (Atollic True 
Studio)

Würde mich freuen, wenn ich dazu von Euch Hilfe bekommen könnte, es hat 
mich echt schon einige graue Haare gekostet!

von Walter T. (nicolas)


Lesenswert?

Gunnar F. schrieb:
> IST das überhaupt Doxygen?

Ja. Aber ob Keil das für sich interpretieren kann, weiß ich nicht. Meine 
IDE kann es nicht.

von Gunnar F. (gufi36)


Lesenswert?

Gunnar F. schrieb:
> #if (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT) &&
> FSL_FEATURE_GPIO_HAS_INTERRUPT)
> #define GPIO_PIN_INT_LEVEL 0x00U
> #define GPIO_PIN_INT_EDGE 0x01U

und kann mir jemand erklären, was das überhaupt bedeutet?

verkürzt:
#if (defined(A) && A)

versteh ich leider nicht...

von Walter T. (nicolas)


Lesenswert?

Das ist aber kein Doxygen-Problem und paßt irgendwie nicht in den 
Thread.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Gunnar F. schrieb:
> was ich für Doxygen gehalten habe

Ist es auch, man kann daher aus diesen Kommentaren (plus ggf. weiterem 
Blabla) eine separate Hilfe compilieren.

Aber mit dem Inhalt dieses Threads hat das ansonsten nichts zu tun, denn 
Nicolas wollte gern wissen, wie er selbst (und nicht CMSIS oder 
sonstwer) die Kommentare so sinnvoll gestalten kann, dass er sich eine 
passende Doku generieren kann.

von Olaf (Gast)


Lesenswert?

> Doxygen brauche ich doch eigentlich nur dafür, dass jemand auch ohne
> Quelltext schon mal eine Idee hat, was er wie damit machen kann.

Mein Eindruck ist das Doxygen erfunden wurde damit jemand der kein Bock 
hat irgendeine Dokumentation zu verfassen im Zweifelsfall dem Chef mal 
eben 200-500Seiten automatisch verfasste Doku auf dem Tisch legen kann 
die der dann auch nicht liest.
Ich hab jedenfalls bisher noch nichts von Doxygen verfasstes gelesen das 
mich in irgendeiner Weise aufgeschlaut hat. Dann liest man doch lieber 
gleich den Source. Wenn der dann auch Kacke ist dann weiss man 
wenigstens wen man rund machen muss.

Olaf

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Olaf schrieb:
> Ich hab jedenfalls bisher noch nichts von Doxygen verfasstes gelesen das
> mich in irgendeiner Weise aufgeschlaut hat.

Dann schau dir die Qt-Dokumentation an. Das ist zwar vermutlich nicht 
direkt Doxygen, aber das Prinzip ist das gleiche.

Sicher gibt es dort auch Dinge, die über den rudimentären Kommentar 
nicht hinaus reichen, aber zumindest hat man dadurch erst einmal eine 
vollständige Dokumentation – etwas, von dem viele andere 
Softwareprojekte (egal ob kommerziell oder Opensource) nur träumen 
können. Für alle wichtigeren Dinge hat dann üblichweise schon noch 
jemand ein wenig zusätzliche Prosa spendiert.

Ansonste hoffe ich, dass du mit der avr-libc noch nie was zu tun gehabt 
hast. Wenn doch, und deine obige Aussage auch dafür deiner Meinung nach 
zutrifft, dann wäre ich etwas enttäuscht gemessen daran, wieviel Arbeit 
ich dort mal in die Doku gesteckt habe. ;-)

von Stefan F. (Gast)


Lesenswert?

Olaf schrieb:
> Mein Eindruck ist das Doxygen erfunden wurde damit jemand der kein Bock
> hat irgendeine Dokumentation zu verfassen im Zweifelsfall dem Chef mal
> eben 200-500Seiten automatisch verfasste Doku auf dem Tisch legen kann
> die der dann auch nicht liest.

Ja, denke ich auch. Mir fällt aber noch ein Fall ein: Und zwar wenn man 
eine Library nur in Binärform weiter gibt.

von DPA (Gast)


Lesenswert?

Stefanus F. schrieb:
> Olaf schrieb:
>> Mein Eindruck ist das Doxygen erfunden wurde damit jemand der kein Bock
>> hat irgendeine Dokumentation zu verfassen im Zweifelsfall dem Chef mal
>> eben 200-500Seiten automatisch verfasste Doku auf dem Tisch legen kann
>> die der dann auch nicht liest.
>
> Ja, denke ich auch. Mir fällt aber noch ein Fall ein: Und zwar wenn man
> eine Library nur in Binärform weiter gibt.

Also bei einer Library erwarte ich schon eine API Dokumentation. Wisst 
ihr, wie ich das Ding hier: 
https://github.com/Daniel-Abrecht/alsa_pcm_tty schreiben konnte, ohne 
jegliche Tutorials, Anleitungen, Manpages, oder sonstige Manuals? Genau, 
mit der Doxygen Dokumentation von Alsa (obwohl die in dem Bereich 
(schreiben von ioplug plugins) auch nicht so besonders toll war.). In 
solchen fällen will man definitiv nicht ewig den Code & die inneren 
Abläufe studieren, viel zu aufwändig.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.