PIC C-Compilervergleich
Da im Forum öfter diskutiert und behauptet wurde, habe ich mir vorgenommen ein paar gängige C-Compiler für die PICs zu vergleichen. Der Auslöser für mich war, als ich endlich wissen wollte, was nun stimmt: Ist der Microchip C-Compiler in der Free-Version nun unbrauchbar oder ist die Optimierungsbegrenzung vernachlässigbar. Und da ich schon dabei war, habe ich gleich andere Compiler mit ins Boot genommen. Meine Vorgabe war ein selbsterstelltes Programm, dass nur so zum Optimieren einläd. Ich wollte aber nur Syntax-Anpassungen machen wollen, sodass ich ggf. auch gucken kann, welches Programm welche PICs nicht unterstützt. Aus diesem Grund habe ich mich auch bemüht relativ neue PICs zu nehmen.
Compiler
PIC12/16/18
xc8-cc
Version: 2.00 (Juni 2018)
Unterstützt: PIC10/12/16/18
Erfordert: Windows Vista oder neuer; Linux X86, MacOS (ungetestet)
Im Gegensatz zu XC8 1.x (s.u.) ist die Gesamtfunktionalität schon deutlich näher an avr-gcc, was das Umsteigen erleichtert! Kommandozeilensyntax, ELF-Output (statt COFF) und C99-Kompatibilität sind ordentlich. XC8-1.x-Quelltexte bei Interruptroutinen und Inline-Assembler müssen / sollten umgeschrieben werden. Leider kein C++. Lizenzierungsgebaren unverändert. Nerv-Output ("Kaufen Sie die PRO-Version") ist endlich weg.
Standardmäßiger C-Compiler von Microchip, enthält mittlerweile avr-gcc.
Download-Größe: 230 MByte
Installationsgröße: 1,8 GByte (vor allem durch dusselig strukturierte, nämlich platte .H-Dateien)
XC8
Version: 1.30, MPLAB X 2.05
Unterstützt: PIC10/12/16/18
Preis (Standard/Pro): 495$ / 995$
Beschränkung der Freiversion: Begrenzte Code-Optimierung, 60-Tage PRO Version
Sonstiges: Ich habe mich für die XC-Reihe entschieden, da die C18,C30 und C32 von diesen abgelöst werden sollen.
Standardmäßiger C-Compiler von Microchip.
Hi-Tech C for PIC10/12/16
Version: 9.83, MPLAB X 1.51
Unterstützt: PIC10/12/16
Preis (Standard/Pro): 495$ / 1195$
Beschränkung der Freiversion: Begrenzte Code-Optimierung, 45-Tage PRO Version
Hi-Tech C for PIC18
Version: 9.80, MPLAB X 1.51
Unterstützt: PIC10/12/16/18
Preis (Pro): 1195$
Beschränkung der Freiversion: Begrenzte Code-Optimierung, 45-Tage PRO Version
SDCC
Version: 3.2.0
Unterstützt: PIC16/18
Sonstiges: Dieses Programm ist Freeware. In der Konsolenausgabe wird wie beim cc5x-Compiler eine Beschreibung der Parameter ausgegeben, sehr unübersichtlich.
Am Target PIC16 ist keine warnungsfreie Compilierung möglich. Maschinenkode größer als beim Microchip-Compiler XC8 freie Version (ohne Optimierung), daher nahezu nutzlos. Scheint noch Bugs zu haben, beispielhafter Quelltext für XC8 führte zu nicht lauffähigem Maschinenkode.
PIC-C PCWHD
Version: 4.136d
Unterstützt: PIC10/12/16/18/24/dsPIC
Preis (Pro): 600$
Beschränkung der Freiversion: Wie Vollversion, jedoch nur 15% der Beispielcodes und nur 45 Tage nutzbar, danach garnicht (nichtmal ohne Optimierungsoptionen).
Sonstiges: Ich finde, dass der Wizard beim Erstellen eines Projektes sehr komplex, jedoch auch übersichtlich ist. Dort können Konfigurationsbits gesetzt werden, aber auch Timer, Module, IOs usw konfiguriert werden. Leider ist dieses Menü nach dem "Fertig"-Klicken nicht mehr aufrufbar. Der Compiler hat eine eigene IDE.
CC5X
Version: 3.4H
Unterstützt: PIC12/16
Preis (Standard): 250€
Beschränkung der Freiversion: 32768 instructions, nur 16bit signed/unsigned int und 24bit float.
Sonstiges: Bei diesem Compiler konnte ich leider nur die Freiversion testen und diese konnte wie der SDCC nichts mit double anfangen. Auch ist keine Lib wie math.h dabei. In der Freiversion nur 3 Datentypen zu haben und die dann auch noch 2-3Byte groß sind, finde ich eher nicht so üppig. Wenn jemand die Vollversion von cc5x und/oder cc8e hat, der kann sich gerne bei mir melden (Hier) und ich schicke ihm mein Quellcode. Er kann natürlich auch gerne den Code weiter unten kopieren.
CC8E
Version: 1.3E
Unterstützt: PIC18
Preis (Standard): 250€
Beschränkung der Freiversion: 131072 instructions, nur 16bit signed/unsigned int und 24bit float.
Sonstiges: Siehe CC5X
MikroC for PIC
Version: 5.6.1
Unterstützt: PIC12/16/18
Preis (Pro): 199$
Beschränkung der Freiversion: max. Flash-Speicher 2048 Byte
Sonstiges: Diesen Compiler kenne ich wohl am besten, da ich ihn auch bisher ausschließlich benutzt habe. 2kB als Code-Grenze ist gerade bei PIC18er nicht gerade viel, jedoch reicht es für viele Projekte aus. Dazu sind die MikroC Compiler in der Voll-Version die günstigsten. Der Compiler kommt mit einem m.M. nach guten Konfigurator und auch mit diversen Standard-Libs und PIC-Bezogenen Bibliotheken. Der Compiler hat eine eigene IDE.
WIZ-C, SourceBoost
Diese beiden Compiler hab ich auch getestet, jedoch hatte SourceBoost z.B. keine Math-Lib und mit WIZ-C bin ich irgendwie nicht zurecht gekommen
PIC24/dsPIC
XC16
Version: 1.21, MPLAB X 2.05
Unterstützt: PIC24/dsPIC
Preis (Pro): 995$
Beschränkung der Freiversion: Begrenzte Code-Optimierung, 60-Tage PRO Version
Hi-Tech C for PIC24 & dsPIC
Version: 9.62, MPLAB X 1.51
Unterstützt: PIC24/dsPIC
Preis (Standard): 895$
Beschränkung der Freiversion: Begrenzte Code-Optimierung, 45-Tage Standard Version
PIC-C PCWHD
Siehe "PIC-C PCWHD" unter "PIC12/16/18".
MikroC for dsPIC/PIC24
Version: 5.7.0
Unterstützt: PIC24/dsPIC
Preis (Pro): 199$
Beschränkung der Freiversion: max. Flash-Speicher 6144 Byte
PIC32
XC32
Version: XC32 1.31, MPLAB X 2.05
Unterstützt: PIC32
Preis (Pro): 995$
Beschränkung der Freiversion: Begrenzte Code-Optimierung (maximal -O1), 60-Tage PRO Version. Keine Code Größen Beschränkung und keine Einschränkung für die Verwendung der Freiversion in kommerziellen Produkten
Hi-Tech C for PIC32
Version: 9.62, MPLAB X 1.51
Unterstützt: PIC32
Preis (Pro): 1495$
Beschränkung der Freiversion: Begrenzte Code-Optimierung, 45-Tage Standard Version
MikroC for PIC32
Version: 2.5.1
Unterstützt: PIC32
Preis (Pro): 249$
Beschränkung der Freiversion: max. Flash-Speicher 8192 Byte
Programmbeschreibung
char arr[5] = {1, 2, 3, 4, 5};
char gleiches_arr[5] = {1, 2, 3, 4, 5};
const char teilsgenutztes_arr[5] = {10, 20, 30, 40, 50};
const char ungenutztes_arr[5] = {3,2,5,3,1};
void sinnlose_funktion(char i){
i++;
return;
}
int unaufgerufene_funktion(double a){
int erg;
erg = a / 10;
return erg;
}
char f1(){
char var_in_f1;
var_in_f1 = PORTA * 3;
PORTA = 0;
if(var_in_f1 > 18) return 18;
else return 0;
}
char f2(){
char var_in_f2;
var_in_f2 = PORTB * 5;
PORTB = 0;
if(var_in_f2 > 30) return 30;
else return 0;
}
void main(){
char fuer_pointer = 5, i;
char *ptr;
char boolsch1 = 0, boolsch2 = 0;
bit b1, b2, b3;
int zahl1 = 0xFA00, zahl2;
double kommazahl1, kommazahl2;
ptr = &fuer_pointer;
*ptr = f1() + f2();
PORTB = *ptr;
b1 = 0;
b2 = 0;
b3 = 0;
if(PORTB > 30){
boolsch1 = 1;
b1 = 1;
}
if(PORTB == 0){
boolsch2 = 1;
b2 = 1;
}
if(boolsch1 && boolsch2){
PORTB = 255;
b3 = 1;
}
if(b1 && b2 && b3) PORTB = 0;
zahl1 |= PORTB;
zahl2 = zahl1 / 40000;
kommazahl1 = PORTA / 255.0;
kommazahl2 = PORTB / 255.0;
fuer_pointer = kommazahl1 / kommazahl2;
sinnlose_funktion(zahl2+kommazahl2);
for(i=0; i<5; i++){
PORTB = arr[i];
}
for(i=0; i<5; i++){
PORTB = gleiches_arr[i];
}
PORTB = teilsgenutztes_arr[2];
if(sqrt(PORTA) > 3) PORTB = 1; //PIC12/16/18/24/32/dsPIC
if(log(PORTA) < 2) PORTB = 5; //PIC12/16/18/24/32/dsPIC
if(pow(PORTA, PORTB) > 100) PORTB = 20; //PIC18/24/32/dsPIC
}
Die Arrays arr und gleiches_arr sind identisch und da diese nicht verändert werden bräuchte man nur eins speichern. teilsgenutztes_arr hat 5 Elemente, jedoch wird davon nur eins benutzt wird. Somit würde es reichen, nur diese eine Zahl zu speichern oder gar die Zahl fest in den Code zu schreiben. ungenutztes_arr wird komplett nicht benutzt.
sinnlose_funktion ergibt keinen Sinn. Beim Aufruf wird eine Variable i erstellt und inkrementiert, doch danach wird die Funktion ohne Rückgabewert beendet. Somit könnte man sich Code und RAM sparen.
unaufgerufene_funktion wird nie aufgerufen und kann deshalb auch weggelassen werden.
f1 und f2 unterscheiden sich und werden auch benutzt. Jedoch ruft keine der beiden Funktion die jeweils andere auf. Somit kann var_in_f1 und var_in_f2 in das gleiche Register, da sie niemals gleichzeitig genutzt werden.
∗ptr zeigt immer und ausschließlich auf "fuer_pointer" und kann somit auch weggelassen werden.
b1, b2 und b3 sind vom Typ bit und sollten/könnten in ein Register. Allerdings nehmen boolsch1 und boolsch2 auch nur die Werte 0 oder 1 an, obwohl sie vom Typ char sind. Somit könnten diese 2 Variablen auch statt char bit sein und mit in das eine Register.
Was Folgt ist die Benutzung von Variablen, damit diese nicht wegoptimiert werden und ein bisschen "sinnloses" gerechne mit int und double.
Zum Schluss wird noch eine Wurzel und der Logarithmus von PORTA gebildet und bei PIC18/24/32/dsPIC auch noch PORTA hoch PORTB gerechnet.
Ergebnisse
PIC12F1840 7kB ROM 256B RAM |
PIC16F1827 7kB ROM 384B RAM |
PIC18F46K22 64kB ROM 3896B RAM | |
---|---|---|---|
XC8 Free (Optimization: all) |
Used RAM: 118 Byte (46%) Used ROM: 2502 Words (61%) Built in 110ms |
Used RAM: 118 Byte (31%) Used ROM: 2502 Words (61%) Built in 94ms |
Used RAM: 143 Byte (4%) Used ROM: 6626 Byte (10%) Built in 109ms |
XC8 Standard (Optimization: all) |
Used RAM: 118 Byte (46%) Used ROM: 2021 Words (49%) Built in 110ms |
Used RAM: 118 Byte (31%) Used ROM: 2021 Words (49%) Built in 94ms |
Used RAM: 143 Byte (4%) Used ROM: 5264 Byte (8%) Built in 93ms |
XC8 PRO (Optimization: all) |
Used RAM: 108 Byte (42%) Used ROM: 1632 Words (40%) Built in 109ms |
Used RAM: 108 Byte (28%) Used ROM: 1632 Words (40%) Built in 93ms |
Used RAM: 135 Byte (3%) Used ROM: 4706 Byte (7%) Built in 109ms |
Hi-Tech C for PIC10/12/16 Lite | Used RAM: 115 Byte (45%) Used ROM: 2498 Words (61%) Built in 110ms |
Used RAM: 115 Byte (30%) Used ROM: 2498 Words (61%) Built in 110ms |
x |
Hi-Tech C for PIC10/12/16 Standard | Used RAM: 115 Byte (45%) Used ROM: 2017 Words (49%) Built in 110ms |
Used RAM: 115 Byte (30%) Used ROM: 2017 Words (49%) Built in 110ms |
x |
Hi-Tech C for PIC10/12/16 Pro | Used RAM: 105 Byte (44%) Used ROM: 1572 Words (38%) Built in 110ms |
Used RAM: 105 Byte (27%) Used ROM: 1572 Words (38%) Built in 110ms |
x |
Hi-Tech C for PIC18 Lite | x | x | Used RAM: 143 Byte (4%) Used ROM: 6518 Byte (10%) Built in 110ms |
Hi-Tech C for PIC18 Pro | x | x | Used RAM: 135 Byte (3%) Used ROM: 4688 Byte (7%) Built in 110ms |
SDCC | x | Keine double-Unterstützung | Keine double-Unterstützung |
PIC-C PCWHD Demo/Pro | Used RAM: 92 Byte (36%) Used ROM: 1920 Words (47%) Built in 1s |
Used RAM: 87 Byte (23%) Used ROM: 1920 Words (47%) Built in 1s |
Used RAM: 103 Byte (3%) Used ROM: 6622 Byte (10%) Built in 1s |
CC5X Free | Keine double-&Globals-Unterstützung | Keine double-&Globals-Unterstützung | x |
CC5X Standard | n.V. | n.V. | x |
CC8E Free | x | x | Keine double-&Globals-Unterstützung |
CC8E Standard | x | x | n.V. |
MikroC for PIC Free | Used RAM: 61 Byte (25%) Used ROM: 1879 Words (46%) Built in 203ms |
Used RAM: 61 Byte (17%) Used ROM: 1879 Words (46%) Built in 281ms |
Datei zu Groß |
MikroC for PIC Pro | Used RAM: 61 Byte (25%) Used ROM: 1879 Words (46%) Built in 188ms |
Used RAM: 61 Byte (17%) Used ROM: 1879 Words (46%) Built in 275ms |
Used RAM: 64 Byte (2%) Used ROM: 6955 Byte (11%) Built in 703ms |
PIC24FJ16MC102 16kB ROM 1024B RAM |
dsPIC33FJ16GS402 16kB ROM 2048B RAM |
PIC32MX220F032B 32kB ROM 8192B RAM | |
---|---|---|---|
XC16 Free (Optimizing Level 1) |
Used RAM: 12 Byte (1%) Used ROM: 1404 Byte (26%) Built in 109ms |
Used RAM: 12 Byte (1%) Used ROM: 1404 Byte (26%) Built in 110ms |
x |
XC16 PRO (Optimizing Level 3/s[Size]) |
Used RAM: 12 Byte (1%) Used ROM (LV: 3) : 1437 Byte (26%) Used ROM (LV: s) : 1408 Byte (25%) Built in 110ms |
Used RAM: 12 Byte (1%) Used ROM (LV: 3) : 1437 Byte (26%) Used ROM (LV: s) : 1408 Byte (25%) Built in 112ms |
x |
XC32 Free (Optimizing Level 1) |
x | x | Used RAM: 20 Byte (1%) Used ROM: 14532Byte (41%) Built in 625ms |
XC32 PRO (Optimizing Level 3/s[Size]) |
x | x | Used RAM: 20 Byte (1%) Used ROM (LV: 3) : 14568Byte (41%) Used ROM (LV: s) : 14496 Byte (40%) Built in 828ms |
Hi-Tech C for PIC24 & dsPIC Standard | PIC-Typ nicht Unterstützt | Used RAM: 1072 Byte (52%) Used ROM: 1289 Byte (23%) Built in 825ms |
x |
Hi-Tech C for PIC32 Lite | x | x | Nicht Unterstützt |
Hi-Tech C for PIC32 Pro | x | x | Nicht Unterstützt |
PIC-C PCWHD Demo/Pro | Used RAM: 438 Byte (43%) Used ROM: 5438 Byte (48%) Built in 2s |
Used RAM: 438 Byte (21%) Used ROM: 5438 Byte (48%) Built in 1s |
x |
MikroC for dsPIC/PIC24 Free/Pro | Used RX: 32 Byte (100%) Used RAM: 10 Byte Used ROM: 3599 Byte (32%) Built in 562ms |
Used RX: 32 Byte (100%) Used RAM: 10 Byte Used ROM: 3599 Byte (32%) Built in 468ms |
x |
MikroC for PIC32 Free/Pro | x | x | Used RX: 29 Byte (91%) Used RAM: 10 Byte (1%) Used ROM: 5851 Byte (18%) Used BOOTROM: 300 Byte (10%) Built in 1062ms |
Ergebnisse ein paar Beispielcodes
Da mich, wie Eingangs geschrieben, der Unterschied der Pro und Free-Version der Microchip-Compiler interessiert hat, hab ich mir bei microchip.com ein paar Beispielcodes runtergeladen, um auch mal anderen, realistischen Code zu haben.
Beispiel | Controller | XC8 Free | XC8 Standard | XC8 Pro | HiTech C Free | HiTech C Pro | Größen |
---|---|---|---|---|---|---|---|
ECAN Mode 0 with Baud | PIC18F46K80 | 18 / 1028 | 18 / 570 | 5 / 442 | 18 / 1008 | 5 / 422 | Bytes RAM / Flash |
PIC18 USART Code Example | PIC18F4685 | 50 / 544 | 50 / 410 | 47 / 376 | — | ||
Beispiel | Controller | XC16 Free | XC16 Pro (O3) | XC16 Pro (Os) | — | Größen | |
CE312, CRC | PIC24FJ128GA010 | 64 / 405 | 64 / 430 | 64 / 392 | — | Byte RAM / Word Flash | |
CE351, Extended CRC 32 | PIC24FJ64GB004 | 36 / 467 | 36 / 467 | 36 / 467 | |||
CE369, Complementary PWM | PIC24FJ16MC102 | 0 / 400 | 0 / 440 | 0 / 398 | |||
CE374, SPI Master and Framed Master Mode | PIC24FJ128GA010 | 0 / 483 | 0 / 550 | 0 / 479 |
Man sieht auch hier, das der Unterschied beim XC8 ziemlich groß ist (Free:Pro -> 2:1), jedoch beim XC16 von der Dateigröße zwischen den beiden höchsten Optimierungsstufen liegt.
Schlusswort
Das was natürlich bei den ganzen Ergebnissen berücksichtigt werden muss, ist, dass dort nur der Verbrauch von ROM und RAM steht. Dies sagt nichts über die Ablaufgeschwindigkeit aus. Ein Compiler kann evtl einen minimal kleineren Code erzeugen aber doppelt so lange dauern wie ein anderer. Ich hab bloß keine Ahnung, wie ich die Laufzeit ermitteln könnte. Alle Assembles durchgucken und die Takte zusammenrechnen werde ich sicher nicht. Es gibt aber vielleicht ein Programm dafür!?
zumindest für Microchip: Die Stopwatch (Stoppuhr) Funktion in MPLAB:
Wenn jemand einen Code genauso getestet haben will, kann mir gerne den Code schicken und ich versuch mein bestes ihn auf so vielen Compilern wie möglich zum laufen zu bringen. Auf folgende Compiler hab ich Zugriff:
- XC8/16/32 Free/Standard/Pro
- Hi-Tech C for PIC10/12/16/18/32 Free/Pro
- Hi-Tech C for PIC24 & dsPIC Free
- SDCC
- PIC-C PCWHD
- CC5X Free
- CC8E Free
- MikroC for PIC, dsPIC/PIC24, PIC32 Pro
Jedoch kann sich jeder bis auf die Pro-Version der MikroC-Compiler alles selber laden und testen.