Hallo Forum.
Programmiersprachen fuer uC gibt es ja eher wenige, verglichen zu der
Masse an Programmiersprachen fuer den PC.
Von der Programmiersprache Rust gibt es den Ableger AVR-Rust, der Rust
fuer die AVRs verfuegbar macht.
AVR-Rust:
https://github.com/avr-rust
Das Projekt muss man selber compilieren. Wie das geht hab ich mal in
einem Bugreport beschrieben:
https://github.com/avr-rust/rust/issues/108#issuecomment-419130948
Als zusaetzliche Abhaengigkeiten sind avr-gcc (zum Linken) und avr-libc
zu installieren.
Ich hab ein kleines Testprojekt fuer den AT90USB1286 (Teensy++ 2.0)
gemacht um zu zeigen wie das geht, auch mit Interrupts.
avr-rust-teensy-blink
https://gitlab.com/Bloody_Wulf/avr-rust-teensy-blink
Ist noch nicht wirklich schoen der Code, sollte aber reichen um zu
zeigen wie es geht.
Zu dem Code:
Datei: std.rs
m.n. schrieb:> Danke.> Aber Compilieren macht der AVR-GCC auch, ohne double entsprechend zu> würdigen.
Ach so. Ich dachte Du beziehst dich auf diesen Bug:
Compiler uses f64 literals by default; both float and double are 32 bits
on AVR #76
https://github.com/avr-rust/rust/issues/76#issue-258761696
Da wird auch ueber die breite von f32 und f64 diskutiert.
Gut, f64 geht dann wohl nicht.
Die Argumente "ist zu langsam", "braucht man nicht" oder "schreib es Dir
doch selber" kenne ich von diesem Forum. Das sind Ausreden aber keine
Lösung. Schade.
Kaj G. schrieb:> fn enable_interrupts() {> unsafe {> asm!("SEI");> }> }
Das ist aber nicht ernstgemeint, oder?
Muss man im Jahr 2018 immer noch so eine bescheidene ASM-Einbindung
machen wie C im letzten Jahrhundert?
Karl K. schrieb:> Muss man im Jahr 2018 immer noch so eine bescheidene ASM-Einbindung> machen wie C im letzten Jahrhundert?
Noe, muss man nicht.
1
fn enable_interrupts() {
2
unsafe {
3
//asm!("SEI");
4
write_volatile(SREG, 0x80);
5
}
6
}
Ist nur zum Zeigen das man auch sowas machen kann, wenn man meint das
man es braucht. Ich werde es im Repo ergaenzen. Danke.
Oder wenn es C aehnlicher sein soll:
1
fn enable_interrupts() {
2
unsafe {
3
//asm!("SEI");
4
//write_volatile(SREG, 0x80);
5
*SREG = 0x80;
6
}
7
}
Letzteres macht den Code aber um 2 Byte groesser, was wohl aber nur fuer
SREG gilt. Spreche ich andere Register auf diese weise an, dann wird der
Code nicht groesser. :-/
Kaj G. schrieb:> Ist nur zum Zeigen das man auch sowas machen kann, wenn man meint das> man es braucht.
Das habe ich nicht gemeint. Es ist durchaus sinnvoll, für µC mal ASM mit
einzubinden, wenns schnell gehen soll.
Aber doch bitte nicht durch seitenweise asm!("..."); Das ist doch
peinlich.
Karl K. schrieb:> Muss man im Jahr 2018 immer noch so eine bescheidene ASM-Einbindung> machen wie C im letzten Jahrhundert?
Hardware-Interrupts existieren in allgemeinen Hochsprachen eher nicht,
also werden sie immer als ASM-Einbindung gemacht. Man kann das natürlich
auch in eine Bibliothek auslagern, wenn man will... es bleibt trotzdem
ein ASM.
S. R. schrieb:> Hardware-Interrupts existieren in allgemeinen Hochsprachen eher nicht,> also werden sie immer als ASM-Einbindung gemacht.
Das ist Quatsch, in Freepascal schreibe ich Hardware-Interrupts genauso
wie normale Prozeduren. Theoretisch brauche ich keinen ASM. Praktisch
ist er manchmal ganz nützlich.
Der Unterschied ist der:
Karl K. schrieb:> fn delay_ms(time : u8) {> let fmul = 1 * Cfcpu div 1000000;> unsafe {> asm!(" push r23");> asm!(" push r22");> asm!(" loop1:");> asm!(" ldi r23, fmul");> asm!(" loop2:"); // 1000 * fmul = 1000 1 8 = 8000 cycles> / 8MHz> asm!(" ldi r22, 250");> asm!(" loop3:"); // 4 * 250 = 1000 cycles> asm!(" nop");> asm!(" dec r22");> asm!(" brne loop3");> asm!(" dec r23");> asm!(" brne loop2");> asm!(" dec r24");> asm!(" brne loop1");> asm!(" pop r22");> asm!(" pop r23");> }> }>> Oder so... Letzteres kann in Detais falsch sein.>> Fällt Dir was auf?
Wahrschenlich kann man auch alle Befehle in ein einziges asm Makro
schreiben und wahrscheinlich kann man auch clobber Listen und dergleiche
nutzen und wahrscheinlich müßte man sich auch keine hartcodierten
Register aus den Fingern saugen sondern könnte sich die vom Compiler
zuweisen lassen. Schreib also das zweite Beispiel mal entsprechend um
bevor Du einen Vergleich ziehst.
[obiger Bereich absichtlich leer wegen bescheuerter Forensoftware]
Karl K. schrieb:> Fällt Dir was auf?
Nur, dass du mich vollständig bestätigt hast, obwohl meine
Ursprungsaussage falsch war. Ich bin mir nicht sicher, was du eigentlich
sagen wolltest.
"Interrupts ein- und ausschalten" sind sehr spezielle
Hardwarefunktionen, die in allgemeinen Hochsprachen nichts zu suchen
haben. Daher nutzt man dafür direkt Assembler, oder ein Makro/eine
Bibliotheksfunktion, die das irgendwie versteckt.
Zur Korrektur: Ich meinte nicht, dass Interrupt-Handler grundsätzlich in
Assembler geschrieben sein müssen. Mein eigener Code widerspräche dem
schon.
Aber ein asm("sti") ist schlicht keine Gotteslästerung.
Kaj G. schrieb:> Karl K. schrieb:>> Muss man im Jahr 2018 immer noch so eine bescheidene ASM-Einbindung>> machen wie C im letzten Jahrhundert?> Noe, muss man nicht.
.
>
1
> fn enable_interrupts() {
2
> unsafe {
3
> //asm!("SEI");
4
> write_volatile(SREG, 0x80);
5
> }
6
> }
7
>
.
> Ist nur zum Zeigen das man auch sowas machen kann, wenn man meint das> man es braucht. Ich werde es im Repo ergaenzen. Danke.
Wobei SEI nicht alle anderen Flags löscht!
Carl D. schrieb:> Wobei SEI nicht alle anderen Flags löscht!
Das ist ein sehr guter Einwand! Danke.
asm schrieb:> Gibts beim AVR-Rust auch die, IMHO, recht gelungenen 'Verzahnung'> zwischen Variablen und Asm Argumenten wie in AVR-C/AVR-Ada?
Was genau meinst du? Kannst du vielleicht ein kleines Beispiel geben?
Auch nicht besser.
> ... und wahrscheinlich kann man auch clobber Listen und dergleiche> nutzen und wahrscheinlich müßte man sich auch keine hartcodierten> Register aus den Fingern saugen sondern könnte sich die vom Compiler> zuweisen lassen.
Das sind mir zu viele Wahrscheinlichs. Komm bitte wieder, wenn Du es
weißt, nicht nur vermutest.
Kaj G. schrieb:> Von der Programmiersprache Rust gibt es den Ableger AVR-Rust, der Rust> fuer die AVRs verfuegbar macht.
**thumbs up!** Jetzt muss ich mir nur noch ein Projekt ausdenken wofür
ich ein AVR brauche :-D
Christopher J. schrieb:> Eric B. schrieb:>> **thumbs up!** Jetzt muss ich mir nur noch ein Projekt ausdenken wofür>> ich ein AVR brauche :-D>> Alternativ läuft das natürlich auch auf Cortex-M oder MSP430 ;)
Mein Ziel wäre eher Z80. Es gibt dafür aber kein funktionierendes
gcc/llvm...
Ein llvm-Backend scheint es für Z80 zu geben:
https://github.com/jacobly0/llvm-z80 . Alternativ kann man eventuell das
C-Backend von llvm nutzen und über den Umweg Rust->LLVM-IR->C das ganze
dann mit dem sdcc kompilieren. Auf dem gleichen Weg kann man auch C++
mit dem sdcc realisieren, siehe z.B.
http://www.colecovision.eu/llvm+sdcc/ aber das ist jetzt endgültig OT.
Hier findet man eine Übersicht wo derzeit so Rust im Embedded-Bereich
eingesetzt wird: https://github.com/rust-embedded/awesome-embedded-rust
http://llvm.org/doxygen/md_lib_Target_AVR_README.html
Das AVR Backend ist experimental, und es gibt eine beunruhigend
ausehende Liste von Fehlern. Aber vielleicht betreffen die rust ja nicht
weil die entsprechenden LLVM Funktionen nicht genutzt werden?
Christopher J. schrieb:> Ein llvm-Backend scheint es für Z80 zu geben:> https://github.com/jacobly0/llvm-z80 . Alternativ kann man eventuell das> C-Backend von llvm nutzen und über den Umweg Rust->LLVM-IR->C das ganze> dann mit dem sdcc kompilieren. Auf dem gleichen Weg kann man auch C++> mit dem sdcc realisieren, siehe z.B.> http://www.colecovision.eu/llvm+sdcc/ aber das ist jetzt endgültig OT.>
Das C-Backend existiert nicht mehr (leider) im aktuellen llvm.