Aus RN-Wissen.de
Wechseln zu: Navigation, Suche
Rasenmaehroboter fuer schwierige und grosse Gaerten im Test

(Betriebsystem für Bascom)
Zeile 3: Zeile 3:
 
Gleich vorweg: die im Text angesprochene Bascom-Library kommt in Kürze in den Download-Bereich, auch ein Verwendungsbeispiel dazu.  
 
Gleich vorweg: die im Text angesprochene Bascom-Library kommt in Kürze in den Download-Bereich, auch ein Verwendungsbeispiel dazu.  
  
Im Wesentlichen ist es die Aufgabe eine Betriebssystems, das Zusammenspiel der verschiedenen Programmteile, aus denen ja so  
+
Im Wesentlichen ist es die Aufgabe eine Betriebssystems, das Zusammenspiel der verschiedenen Programmteile, aus denen ja so eine µC-Applikation besteht, zu regeln. Die Nachteile des gewissen Overheads und der natürlich erforderlichen Restriktionen´sollten durch die Vorteile der Standardisierung und Modularisierung deutlich aufgewogen werden.  
eine µC-Applikation besteht, zu regeln. Die Nachteile des gewissen Overheads und der natürlich erforderlichen Restriktionen
+
sollten durch die Vorteile der Standardisierung und Modularisierung deutlich aufgewogen werden.  
+
  
Bascom bietet für sehr viele AVR-intere Geräte und Peripherie Funktionen an, die oft ganz einfach durch "Config" Anweisungen  
+
Bascom bietet für sehr viele AVR-intere Geräte und Peripherie Funktionen an, die oft ganz einfach durch "Config" Anweisungen initiiert werden können und dem Programmierer viel Detailentwicklungsarbeit abnehmen. Ein unschätzbarer Vorzug. Was aber immer wieder bleibt, ist das Problem des Zusammenwirkens dieser Komponenten und die gewünschte Mehrgleisigkeit, "Multithreading", des gesamten Projekts.
initiiert werden können und dem Programmierer viel Detail-Entwicklungsarbeit abnehmen. Ein unschätzbarer Vorzug. Was aber immer wieder
+
bleibt, ist das Problem des Zusammenwirkens dieser Komponenten und die gewünschte Mehrgleisigkeit, "Multithreading", des gesamten  
+
Projekts.
+
  
Es soll hier ein Konzept vorgestellt werden, das hauptsächlich in Hinblick auf eine Standardisierung der Rechner-Kommunikation entwickelt  
+
Es soll hier ein Konzept vorgestellt werden, das hauptsächlich in Hinblick auf eine Standardisierung der Rechner-Kommunikation entwickelt wurde. Also µC <-> PC und µC <-> Peripherie.
wurde. Also µC <-> PC und µC <-> Peripherie.
+
  
Das verwendete "Message-Queueing" ist natürlich keine neue Erfindung, jeder Windows-Programmierer kennt das. Das Problem war es, eine Form  
+
Das verwendete "Message-Queueing" ist natürlich keine neue Erfindung, jeder Windows-Programmierer kennt das. Das Problem war es, eine Form zu schaffen, die sich in Bascom so eingliedern läßt, daß auch die "normale" Verwendung des Compilers möglich ist. Nur an den Schnittstellen zu den Sys-Funktionen müssen die Konventionen eingehalten werden.  
zu schaffen, die sich in Bascom so eingliedern läßt, daß auch die "normale" Verwendung des Compilers möglich ist. Nur an den Schnittstellen  
+
zu den Sys-Funktionen müssen die Konventionen eingehalten werden.  
+
  
  
 
===Begriffe===
 
===Begriffe===
*Units: Ein Programmteil, der sozusagen mitspielen will, wird als Unit od. "Einheit" bezeichnet. In den meisten Fällen wird so eine Unit die  
+
*Units: Ein Programmteil, der sozusagen mitspielen will, wird als Unit od. "Einheit" bezeichnet. In den meisten Fällen wird so eine Unit die verschiedenen Funktionen umfassen, die für die Bedienung eines bestimmten Device od. "Gerät" erforderlich sind.  
verschiedenen Funktionen umfassen, die für die Bedienung eines bestimmten Device od. "Gerät" erforderlich sind.  
+
*Class/Ident: Es gibt Geräteklassen, die sich durch ein Set von "Methoden" definieren, die auf eines oder mehrere tatsächliche Geräte angewendet werden können. Anschauliches Beispiel: die Klasse "ADC", die für 8 Channels angewendet werden kann. Grundsätzlich werden die ADC-Channels ja völlig gleich behandelt, aber für jeden Kanal gelten unter Umständen verschiedene Parameter: Natürlich die Kanal-Nummer 0-7, aber auch Umrechnungsfaktoren und Grenzwerte
*Class/Ident: Es gibt Geräteklassen, die sich durch ein Set von "Methoden" definieren, die auf eines oder mehrere tatsächliche Geräte angewendet
+
*Tags: Jeder Class/Ident-Ausprägung wird ein Tag ("Etikett") zugeordnet, das einen vom System verwalteten Bereich bezeichnet, der für die Kommunikation Unit <-> System erforderlich ist. Tags werden bei jedem Aufruf an das System verwednet und bei Aufrufen durch das System immer mitgeliefert.  
werden können. Anschauliches Beispiel: die Klasse "ADC", die für 8 Channels angewendet werden kann. Grundsätzlich werden die ADC-Channels ja völlig
+
*Message-Queueing: An sich können alle Funktionen eines Units "normal" verwendet, also aufgerufen werden. Doch jede Unit bietet wenigstens eine "Sub"-function an, die auch indirekt über Messages angesprochen werden kann und daher auch ein standardisiertes Format haben muß.  
gleich behandelt, aber für jeden Kanal gelten unter Umständen verschiedene Parameter: Natürlich die Kanal-Nummer 0-7, aber auch Umrechnungsfaktoren
+
und Grenzwerte
+
*Tags: Jeder Class/Ident-Ausprägung wird ein Tag ("Etikett") zugeordnet, das einen vom System verwalteten Bereich bezeichnet, der für die  
+
Kommunikation Unit <-> System erforderlich ist. Tags werden bei jedem Aufruf an das System verwednet und bei Aufrufen durch das System immer  
+
mitgeliefert.  
+
*Message-Queueing: An sich können alle Funktionen eines Units "normal" verwendet, also aufgerufen werden. Doch jede Unit bietet wenigstens eine  
+
"Sub"-function an, die auch indirekt über Messages angesprochen werden kann und daher auch ein standardisiertes Format haben muß.  
+
 
   DECLARE SUB unit-entry ( Tag AS WORD, Byval cmd as BYTE, Byval Param as WORD )  
 
   DECLARE SUB unit-entry ( Tag AS WORD, Byval cmd as BYTE, Byval Param as WORD )  
 
Das ist auch die SUB, die beim Einlangen einer Nachricht über das Netzwerk aufgerufen wird.  
 
Das ist auch die SUB, die beim Einlangen einer Nachricht über das Netzwerk aufgerufen wird.  
 
*Tag  ist das erwähnte Etikett, mit dem die SUB alle ihre Referenzen zu privaten Daten und individuellen Parametern (im Flash Speicher) verwaltet.
 
*Tag  ist das erwähnte Etikett, mit dem die SUB alle ihre Referenzen zu privaten Daten und individuellen Parametern (im Flash Speicher) verwaltet.
*Cmd ist eine Aufrufspezifischer Code, der über die Art des Aufrufes Auskunft gibt. Einige Codes sind fest durch das System vergeben, andere  
+
*Cmd ist eine Aufrufspezifischer Code, der über die Art des Aufrufes Auskunft gibt. Einige Codes sind fest durch das System vergeben, andere können beliebig von der Geräteklasse für spezielle Befehle festgelgt werden  
können beliebig von der Geräteklasse für spezielle Befehle festgelgt werden  
+
*Param ist ein Beiwert zu CMD, der daher völlig unterschiedliche Bedeutung haben kann. (Beim Netzwerk-Nachrichten zeigt er auf die eingelangten Daten, die von der Unit zu bearbeiten sind).
*Param ist ein Beiwert zu CMD, der daher völlig unterschiedliche Bedeutung haben kann. (Beim Netzwerk-Nachrichten zeigt er auf die eingelangten Daten,  
+
die von der Unit zu bearbeiten sind).
+
  
 
===TAG-Referenzen===
 
===TAG-Referenzen===
Zeile 44: Zeile 27:
 
[[Bild:sysunits.png]]
 
[[Bild:sysunits.png]]
  
Das System findet durch den Tag die zugeordnete SUB-Routine (Vector). Die Unit hingegen findet durch die System-Function "Unit_REF()" ihre privaten  
+
Das System findet durch den Tag die zugeordnete SUB-Routine (Vector). Die Unit hingegen findet durch die System-Function "Unit_REF()" ihre privaten Daten, und kann auch durch "Unit_parbyte(tag), Unit_parword(tag),Unit_parlong(tag),Unit_parsing(tag)" ihre individuellen Parameter abfragen.  
Daten, und kann auch durch "Unit_parbyte(tag), Unit_parword(tag),Unit_parlong(tag),Unit_parsing(tag)" ihre individuellen Parameter abfragen.  
+
  
Die ersten beiden Bytes der Flash-Parameter sind genormt und beinhalten den Class-Code und Identifier der Unit. Die übrigen sind vom System nicht  
+
Die ersten beiden Bytes der Flash-Parameter sind genormt und beinhalten den Class-Code und Identifier der Unit. Die übrigen sind vom System nicht festgelegt und können beliebige Werte beinhalten.   
festgelegt und können beliebige Werte beinhalten.   
+
  
 
===Message-Queue===
 
===Message-Queue===
Zeile 55: Zeile 36:
  
 
*Durch msg_enqueue() wird ein indirekter Aufruf in die Queue gestellt. Es gibt keine Festlegung darüber, wann und wo dieser Call erfolgen kann.  
 
*Durch msg_enqueue() wird ein indirekter Aufruf in die Queue gestellt. Es gibt keine Festlegung darüber, wann und wo dieser Call erfolgen kann.  
*Die Abarbeitung erfolgt FIFO durch msg_dequeue(). Bei jedem Aufruf wird EINE Message (wenn eine vorhanden ist) abgearbeitet. Auch für diesen Aufruf  
+
*Die Abarbeitung erfolgt FIFO durch msg_dequeue(). Bei jedem Aufruf wird EINE Message (wenn eine vorhanden ist) abgearbeitet. Auch für diesen Aufruf gibt es keinen zwingenden Platz, doch ist es zweckmäßig und empfehlenswert, ihn nur einmal an zentraler Stelle (DO..LOOP) zu tätigen.  
gibt es keinen zwingenden Platz, doch ist es zweckmäßig und empfehlenswert, ihn nur einmal an zentraler Stelle (DO..LOOP) zu tätigen.  
+
  
Anmerkung: Enqueue() und Dequeue() führen sowohl Sub-Vector als auch Tag. "Vector" hat Vorrang, wenn er aber nicht angegeben wird (NULL), wird eben
+
Anmerkung: Enqueue() und Dequeue() führen sowohl Sub-Vector als auch Tag. "Vector" hat Vorrang, wenn er aber nicht angegeben wird (NULL), wird eben der Standard-Unit-Vector verwendet.  
der Standard-Unit-Vector verwendet.  
+
Sonderfall: Bei Angabe von "Vector" ist die Befüllung von TAG nicht zwingend. Dadurch kann auch jede x-beliebige sub-function aufgerufen werden, nur das Declare-Format MUSS stimmen. ("TAG" ist beim Aufruf dann eben NULL).
Sonderfall: Bei Angabe von "Vector" ist die Befüllung von TAG nicht zwingend. Dadurch kann auch jede x-beliebige sub-function aufgerufen werden, nur das  
+
Declare-Format MUSS stimmen. ("TAG" ist beim Aufruf dann eben NULL).
+
 
   
 
   
  
Zeile 180: Zeile 158:
 
Wenn die Klasse irgendein Command nicht kennt, zeigt sie es hier im Beispiel einfach an und macht sonst nichts.  
 
Wenn die Klasse irgendein Command nicht kennt, zeigt sie es hier im Beispiel einfach an und macht sonst nichts.  
  
Wichtig ist CMD_SETUP, das Setzen des Sprungzieles und der Parameter
+
Wichtig ist '''CMD_SETUP''', das Setzen des Sprungzieles und der Parameter
 
<pre>
 
<pre>
 
Local Par_word As Word
 
Local Par_word As Word
Zeile 187: Zeile 165:
 
       Call Unit_par_set(tag , Param)
 
       Call Unit_par_set(tag , Param)
 
</pre>
 
</pre>
Bascom läßt eine direkte Angabe eine Sprungzieles nicht zu. Daher der Umweg über eine word-variable. In dem Beispiel  
+
Bascom läßt eine direkte Angabe eine Sprungzieles nicht zu. Daher der Umweg über eine word-variable. In dem Beispiel wird einfach die eigene Adresse, also der Name der SUB als Unit-Vector eingetragen. Die Unit-Parameter vom FLASH werden einfach direkt aus dem Aufruf übernommen. Gibt es keine Parameter(NULL), macht das zwar nichts, aber dann kann die Unit nicht von den Kommunikations-Funktionen gefunden werden.  
wird einfach die eigene Adresse, also der Name der SUB als Unit-Vector eingetragen.  
+
Die Unit-Parameter vom FLASH werden einfach direkt aus dem Aufruf übernommen. Gibt es keine Parameter (NULL), macht das
+
zwar nichts, aber dann kann die Unit nicht von den Kommunikations-Funktionen gefunden werden.  
+
  
  
Nun wird ein privates Datenbereich reserviert. Der Klassenspezifische Index wird (bei jedem setup) erhöht und als Datenreferenz
+
Nun wird ein privates Datenbereich reserviert. Der Klassenspezifische Index wird (bei jedem setup) erhöht und als Datenreferenz in der Unit-Tabelle eingetragen  
in der Unit-Tabelle eingetragen  
+
 
<pre>
 
<pre>
 
       Incr Anyidx
 
       Incr Anyidx
Zeile 202: Zeile 176:
 
       Any_dta(anyidx) = 0
 
       Any_dta(anyidx) = 0
 
</pre>
 
</pre>
Die Klasse schreibt in ihre privaten Daten den Unit-Tag als Backlink dazu, damit sie auch von dort aus zu ihrem Tag findet. Das ist  
+
Die Klasse schreibt in ihre privaten Daten den Unit-Tag als Backlink dazu, damit sie auch von dort aus zu ihrem Tag findet. Das ist bei ISR- Funktionen oft nötig.   
bei ISR- Funktionen oft nötig.   
+
any_dta(anyidx) = 0 ist eben irgendwas.  
any_dta(anyidx) = 0 ist eben irgendwas, vermutlich sehr wichtig.  
+
  
Ab nun ist die Unit im System eingetragen und verwendbar.  
+
'''Ab nun ist die Unit im System eingetragen und verwendbar'''.  
  
 
+
Als Beispiel ein anderes Command: '''CMD_SHOW'''
Als Beispiel ein anderes Command: CMD_SHOW
+
 
<pre>
 
<pre>
 
Local Par_class As Byte
 
Local Par_class As Byte
Zeile 229: Zeile 201:
 
       Print " word:" ; Str(par_word) ; " Long:" ; Str(par_long) ; " Single:" ; Str(par_sing)
 
       Print " word:" ; Str(par_word) ; " Long:" ; Str(par_long) ; " Single:" ; Str(par_sing)
 
</pre>
 
</pre>
 
 
 
 
  
 
====Aufrufbeispiele====
 
====Aufrufbeispiele====

Version vom 10. Februar 2006, 14:42 Uhr

Betriebsystem für Bascom

Gleich vorweg: die im Text angesprochene Bascom-Library kommt in Kürze in den Download-Bereich, auch ein Verwendungsbeispiel dazu.

Im Wesentlichen ist es die Aufgabe eine Betriebssystems, das Zusammenspiel der verschiedenen Programmteile, aus denen ja so eine µC-Applikation besteht, zu regeln. Die Nachteile des gewissen Overheads und der natürlich erforderlichen Restriktionen´sollten durch die Vorteile der Standardisierung und Modularisierung deutlich aufgewogen werden.

Bascom bietet für sehr viele AVR-intere Geräte und Peripherie Funktionen an, die oft ganz einfach durch "Config" Anweisungen initiiert werden können und dem Programmierer viel Detailentwicklungsarbeit abnehmen. Ein unschätzbarer Vorzug. Was aber immer wieder bleibt, ist das Problem des Zusammenwirkens dieser Komponenten und die gewünschte Mehrgleisigkeit, "Multithreading", des gesamten Projekts.

Es soll hier ein Konzept vorgestellt werden, das hauptsächlich in Hinblick auf eine Standardisierung der Rechner-Kommunikation entwickelt wurde. Also µC <-> PC und µC <-> Peripherie.

Das verwendete "Message-Queueing" ist natürlich keine neue Erfindung, jeder Windows-Programmierer kennt das. Das Problem war es, eine Form zu schaffen, die sich in Bascom so eingliedern läßt, daß auch die "normale" Verwendung des Compilers möglich ist. Nur an den Schnittstellen zu den Sys-Funktionen müssen die Konventionen eingehalten werden.


Begriffe

  • Units: Ein Programmteil, der sozusagen mitspielen will, wird als Unit od. "Einheit" bezeichnet. In den meisten Fällen wird so eine Unit die verschiedenen Funktionen umfassen, die für die Bedienung eines bestimmten Device od. "Gerät" erforderlich sind.
  • Class/Ident: Es gibt Geräteklassen, die sich durch ein Set von "Methoden" definieren, die auf eines oder mehrere tatsächliche Geräte angewendet werden können. Anschauliches Beispiel: die Klasse "ADC", die für 8 Channels angewendet werden kann. Grundsätzlich werden die ADC-Channels ja völlig gleich behandelt, aber für jeden Kanal gelten unter Umständen verschiedene Parameter: Natürlich die Kanal-Nummer 0-7, aber auch Umrechnungsfaktoren und Grenzwerte
  • Tags: Jeder Class/Ident-Ausprägung wird ein Tag ("Etikett") zugeordnet, das einen vom System verwalteten Bereich bezeichnet, der für die Kommunikation Unit <-> System erforderlich ist. Tags werden bei jedem Aufruf an das System verwednet und bei Aufrufen durch das System immer mitgeliefert.
  • Message-Queueing: An sich können alle Funktionen eines Units "normal" verwendet, also aufgerufen werden. Doch jede Unit bietet wenigstens eine "Sub"-function an, die auch indirekt über Messages angesprochen werden kann und daher auch ein standardisiertes Format haben muß.
  DECLARE SUB unit-entry ( Tag AS WORD, Byval cmd as BYTE, Byval Param as WORD ) 

Das ist auch die SUB, die beim Einlangen einer Nachricht über das Netzwerk aufgerufen wird.

  • Tag ist das erwähnte Etikett, mit dem die SUB alle ihre Referenzen zu privaten Daten und individuellen Parametern (im Flash Speicher) verwaltet.
  • Cmd ist eine Aufrufspezifischer Code, der über die Art des Aufrufes Auskunft gibt. Einige Codes sind fest durch das System vergeben, andere können beliebig von der Geräteklasse für spezielle Befehle festgelgt werden
  • Param ist ein Beiwert zu CMD, der daher völlig unterschiedliche Bedeutung haben kann. (Beim Netzwerk-Nachrichten zeigt er auf die eingelangten Daten, die von der Unit zu bearbeiten sind).

TAG-Referenzen

Sysunits.png

Das System findet durch den Tag die zugeordnete SUB-Routine (Vector). Die Unit hingegen findet durch die System-Function "Unit_REF()" ihre privaten Daten, und kann auch durch "Unit_parbyte(tag), Unit_parword(tag),Unit_parlong(tag),Unit_parsing(tag)" ihre individuellen Parameter abfragen.

Die ersten beiden Bytes der Flash-Parameter sind genormt und beinhalten den Class-Code und Identifier der Unit. Die übrigen sind vom System nicht festgelegt und können beliebige Werte beinhalten.

Message-Queue

Sysmsg.png

  • Durch msg_enqueue() wird ein indirekter Aufruf in die Queue gestellt. Es gibt keine Festlegung darüber, wann und wo dieser Call erfolgen kann.
  • Die Abarbeitung erfolgt FIFO durch msg_dequeue(). Bei jedem Aufruf wird EINE Message (wenn eine vorhanden ist) abgearbeitet. Auch für diesen Aufruf gibt es keinen zwingenden Platz, doch ist es zweckmäßig und empfehlenswert, ihn nur einmal an zentraler Stelle (DO..LOOP) zu tätigen.

Anmerkung: Enqueue() und Dequeue() führen sowohl Sub-Vector als auch Tag. "Vector" hat Vorrang, wenn er aber nicht angegeben wird (NULL), wird eben der Standard-Unit-Vector verwendet. Sonderfall: Bei Angabe von "Vector" ist die Befüllung von TAG nicht zwingend. Dadurch kann auch jede x-beliebige sub-function aufgerufen werden, nur das Declare-Format MUSS stimmen. ("TAG" ist beim Aufruf dann eben NULL).


Initialisierung

  • Generell:

Die Library "mysyslib.lbx" muß in das Bascom-Library-Directory gestellt werden.

$INCLUDE "mysyslib.bas"

Hier erfolgen die Definitionen für die Library

Units

 Const Max_c_unit = 4
 Const Unit_arrsz = Max_c_unit * Unit_len
  • Max_c_unit gibt an, wieviele Units maximal verwendet werden können.
  • Unit_arrsz daraus wird errechnet, wie groß das Array sein muß
Dim Unitbase As Word
Dim Unitfill As Word
Dim Unittop As Word

Diese drei Felder müssen aufeinander folgen, die Namensvergabe ist aber wahlfrei

Und irgendwo wird Platz in der benötigten Länge bereitgestellt.

Dim Unitarr(unit_arrsz) As Byte

Jetzt kann die Kontrollstruktur initialisiert werden

  Call Unit_init(unitbase , Unitarr(1) , Unit_arrsz)

Message-Queue

recht analog dazu die Einrichtung der Message-Queue

Const Max_c_msg = 16
Const Msg_arrsz = Max_c_msg * Msg_len
Dim Msgbase As Word                                         ' address array
Dim Msgrdpnt As Word                                        ' read pointer
Dim Msgtop As Word                                          ' array top
Dim Msgwrpnt As Word                                        ' write pointer

Dim Msgarr(msg_arrsz) As Byte

Auch diese Felder müssen aufeinander folgen


  Call Msg_init(msgbase , Msgarr(1) , Msg_arrsz)


Anlegen einer Unit

Als Beispiel eine eigentlich völlig sinnlose Klasse, die nur demonstrieren soll, wie das Ganze funktioniert

  • Definitionen und Parameter
Const Cls_any = &H20

Irgendein Symbol, das allerdings in er gesamten µC Applikation eindeutig sein muß, wird als Klassen-Code festgelegt.

Declare Sub Anyclass(byval Tag As Word , Byval Cmd As Byte , Byval Param As Word)

Das ist der default-Unit-Entry

An einer geeigneten Stelle (nach "END") werden die Unit-Paramter deklariert.

 Any_par:
   Data Cls_any , 1 , &H78 , 16255% , 300000& , 3.55!

Obligat als erstes der Klassencode, dann der Identifier. Der Rest ist eben irgendwas, was diese eine konkrete Unit zum arbeiten benötigt.

  • Eintragen in der Tabelle

Natürlich NACH Unit-Init()

 Dim Par_addr As Word      'Hilfsfeld
 Dim Anytag As Word        

      Anytag = Unit_new(unitbase)       	

Die Funktion gibt den eindeutigen TAG der Unit zurück. Jetzt muß die Unit ihre Werte eintragen. Für den Aufruf übergeben wir die Adresse der Parameter

      Par_addr = Loadlabel(any_par)                         ' individial parameter
      Call Anyclass(mytag , Cmd_setup , Par_addr)	'CMD_SETUP ist festgelegt


  • Setup der Unit

Das macht die Unit am besten selbst, da sie durch die mitgelieferten Paramter modifizierbar ist.

'-----------------------------------------------
'        Class ANY
'-------------------------------------------------
'        private class data
'-------------------------------------------------
Const Max_c_any = 2
Dim Anyidx As Byte

Dim Any_bck(max_c_any) As Word
Dim Any_dta(max_c_any) As Byte

WENN die Klasse /Unit private Daten im SRAM braucht, muß sie sie natürlich dimensionieren. Und zwar am besten in Tabellenform, das kommt Bascom entgegen. (Max_c_any ist die maximale Anzahl der möglichen Units dieser Klasse)

Mögliches Grundmuster der Funktion, die anhand CMD entscheidet, was zu tun ist

'---------------------------------------------------------------------------
Sub Anyclass(byval Tag As Byte , Byval Cmd As Byte , Byval Param As Word)

   Select Case Cmd
   Case Cmd_setup:

   Case Cmd_show:

   Case Else:
      Print Str(tag) ; " CMD1:" ; Str(cmd) ; " PAR1:" ; Str(param)
   End Select
End Sub

Wenn die Klasse irgendein Command nicht kennt, zeigt sie es hier im Beispiel einfach an und macht sonst nichts.

Wichtig ist CMD_SETUP, das Setzen des Sprungzieles und der Parameter

Local Par_word As Word
      Par_word = Loadlabel(anyclass)
      Call Unit_vec_set(tag , Par_word)
      Call Unit_par_set(tag , Param)

Bascom läßt eine direkte Angabe eine Sprungzieles nicht zu. Daher der Umweg über eine word-variable. In dem Beispiel wird einfach die eigene Adresse, also der Name der SUB als Unit-Vector eingetragen. Die Unit-Parameter vom FLASH werden einfach direkt aus dem Aufruf übernommen. Gibt es keine Parameter(NULL), macht das zwar nichts, aber dann kann die Unit nicht von den Kommunikations-Funktionen gefunden werden.


Nun wird ein privates Datenbereich reserviert. Der Klassenspezifische Index wird (bei jedem setup) erhöht und als Datenreferenz in der Unit-Tabelle eingetragen

      Incr Anyidx
      Call Unit_ref_set(tag , Anyidx)

      Any_bck(anyidx) = Tag
      Any_dta(anyidx) = 0

Die Klasse schreibt in ihre privaten Daten den Unit-Tag als Backlink dazu, damit sie auch von dort aus zu ihrem Tag findet. Das ist bei ISR- Funktionen oft nötig. any_dta(anyidx) = 0 ist eben irgendwas.

Ab nun ist die Unit im System eingetragen und verwendbar.

Als Beispiel ein anderes Command: CMD_SHOW

Local Par_class As Byte
Local Par_ident As Byte
Local Par_devad As Byte
Local Par_word As Word
Local Par_long As Long
Local Par_sing As Single

   Case Cmd_show:
      Par_class = Unit_parbyte(tag , 0)	    ' Der Klassencode steht immer an der ersten Stelle der Parameter
      Par_ident = Unit_parbyte(tag , 1)     ' ebenso Ident

      Par_devad = Unit_parbyte(tag , 2)	    ' die Parameter werden einfach geholt und angezeigt.
      Par_word = Unit_parword(tag , 3)      ' das Daten-Offset muß man wissen, auch was dann dort steht
      Par_long = Unit_parlong(tag , 5)      ' es ist sicher sinnvoll, "CONST" zu definieren
      Par_sing = Unit_parsing(tag , 9)
      Print "Class/Id:" ; Str(par_class) ; "/" ; Str(par_ident) ; " Device:0x" ; Hex(par_devad)
      Print " word:" ; Str(par_word) ; " Long:" ; Str(par_long) ; " Single:" ; Str(par_sing)

Aufrufbeispiele

'------------ AUFBAU-----------------------------
      Anytag = Unit_new(unitbase)
      Par_addr = Loadlabel(any_par)                         ' individial parameter1
      Call Anyclass(mytag , Cmd_setup , Par_addr)

      Anytag = Unit_new(unitbase)
      Par_addr = Loadlabel(any_par2)                         ' individial parameter2
      Call Anyclass(mytag , Cmd_setup , Par_addr)

'------------ CALLS-----------------------------
' suchen des Tags nach Class und Ident
      Anytag = Unit_find_clsid(unitbase , Cls_any , 1)

' Direkter Aufruf
      Call Anyclass(anytag , Cmd_show , 0)

DIM Wrk_idx AS BYTE

' Indirekter Aufruf über die Queue
      Wrk_idx = Msg_enqueue(msgbase , 0 , Anytag , Cmd_show , 0)

' Auswerten der Queue
      Call Msg_dequeue(msgbase , 0 , 0)


END

Any_par:
   Data Cls_any , 1 , &H78 , 16255% , 300000& , 3.55!
Any_par2:
   Data Cls_any , 2 , &H44 , 255% , 250000& , 1.44!

Autor

Siehe auch


LiFePO4 Speicher Test