- Akku Tests und Balkonkraftwerk Speicher         
Seite 3 von 4 ErsteErste 1234 LetzteLetzte
Ergebnis 21 bis 30 von 32

Thema: Multithreading mit AVRco

  1. #21
    Anzeige

    LiFePo4 Akku selber bauen - Video
    schaut mal bei www.avrfreaks.net vorbei. Da ist ein sehr guter Artikel zu dem Thema. Letzendlich installiert man ein Betriebssystem, das die verschieden Threads(Prozess)/Tasks(Aufgabe) oder wie auch immer ihr die nennen wollt verwaltet. (Will mich hier nicht festlegen, aber ich glaube als Task bezeichnet man ein Programm das mehrere Prozesse haben kann) Grundsätzlich werden die Befehle nacheinander verarbeitet. (Es gibt zwar auch IC's mit mehreren Prozessoren aber ich glaub nicht in dieser Preisklasse)

  2. #22
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    11.01.2004
    Ort
    Altomünster
    Alter
    36
    Beiträge
    148
    OK ich hab nochmal nach der ct gesucht: es ist die 6/2004(8.3.2004) ab Seite 248.
    Hier könnt ihr euch den kompletten Quellcode für den MSP430 downloaden, kann man aber sicher auch mim AVR realisieren:
    ftp://ftp.heise.de/pub/ct/listings/0406-248.zip

    Hier ist die komplette Linkseite von heise.de:
    http://www.heise.de/ct/04/06/links/248.shtml

    Wer die C't daheim hat hat Glück, denn da wird der Code erklärt.

    Es wird hier natürlich kein echtes Betriebssystem programmiert, ich muss zugeben "Scheduler"(recycle) passt deutlich besser. Es ist wie recycle sagt ein Programm, das per Timer verschiedenen Pseudo-Threads verschieden viel Rechenzeit zuschaufelt.

  3. #23
    malef
    Gast

    MultiThreading Kernels


    Also
    schaut mal unter http://instruct1.cit.cornell.edu/courses/ee476/


    und dann unter : AT90 MCU realtime operating systems

    da gibts ne Menge MultiThREADING KERNELS

    Thread bedeutet alle Funktionen (die Threads eben) laufen in einem gemeinsamen Speicherbereich (da der AVR oder sonstiger MC keine Memory Managment Unit besitzt um die Prozesse voneinaner zu schützen)
    diese Threads werden aber Preemtiv (also vom Kernel selbst(zBsp:durch TimerINT) umgeschaltet und alles was zum Thread gehört (Stack,Register) wind gesichert und wenn der Thread wieder aktiv wird , wieder zürückgeholt !(Context Switching)
    -Jeder Thread hat seinen eigenen Stack und seine eigenen Register

    usw....

  4. #24
    Gast
    Dort findet man zum Beispiel das:
    Code:
    ;***** Simple time-based scheduler ********
    ;
    ;The goal is to allow several tasks to execute at a regular rate
    ;without making a HUGE timer ISR. The timer 0 interrupt just
    ;decrements counters which are tested in a loop to dispatch
    ;subroutines. Timer 0 ticks at a mSec rate in this code.
    
    ;Task descriptions:
    ; task 1: blink LED 0 2/sec
    ; task 2: blink LED 1 1/sec
    ; task 3: Detect button 0 and change task 1 blink rate if the button is down
    ; 
    ;********************************
    ;You will need to CHANGE this path
    ,nolist
    .include "c:\avrtools\appnotes\8515def.inc"
    .list
    
    ;********************************
    ;define registers
    .def	save	=r1
    .def	temp	=r16	;temporary register
    .def	LED	=r17	;the actual LED value to display
    .def	reload	=r18	;holds timer reload value
    
    ;Specify the interval for each task to execute:
    ;since we are toggling LED state on each task entry,
    ;the task times are 1/2 the desired blink times
    .equ	t1	=250	;250 mSec
    .equ	t2	=125	;125 mSec - Task2 will need to have another counter
    .equ	t3	=30	;30 mSec interval for the keyboard scanner
    
    ;********************************
    ;RAM locations:
    
    ;Task execution time intervals 
    .dseg
    time1:	.byte 1
    time2:	.byte 1
    time3:	.byte 1
    
    ;Task2 state variable needed to 
    ;count 4 times the 1/4 second secheduled time
    tsk2c:	.byte 1
    
    ;message from task3 to task1 to change rate
    tsk3m:	.byte 1
    
    ;*******************************
    ; Initialization
    .cseg
    .org $0000
    	rjmp RESET	;reset entry vector
    	reti		
    	reti
    	reti
    	reti
    	reti
    	reti
    	rjmp TIMER
    	reti
    	reti		
    	reti
    	reti	
    	reti
    
    RESET:
    	ldi	Temp, LOW(RAMEND) 	;setup stack pointer
    	out 	SPL, Temp
    	ldi	Temp, HIGH(RAMEND)
    	out	SPH, Temp
    
    	;set up the PORTs
    	ser	Temp		;set PORTB to be
    	out	DDRB,Temp	;all outputs
    	ldi	Temp, 0xff	;turn off LEDs
    	out	PortB, Temp
    
    	clr	Temp		;set PORTD to be
    	out	DDRD,Temp	;all inputs
    
    	;set up timer 0 for 1 mSec ticks
    	ldi	Temp,exp2(TOIE0);enable timer interrupt
    	out	TIMSK, Temp
    	ldi 	Temp, 3		;prescale timer by 64
    	out 	TCCR0, Temp
    	ldi	Reload,256-62	;preload timer since
    	out 	TCNT0, Reload	;62.5 x (64x.25) microSec = 1.0 mSec.
    
    	;initialize task timers
    	ldi	temp, t1	;mSec
    	sts	time1, temp
    	ldi	temp, t2
    	sts	time2, temp
    	ldi	temp, t3
    	sts	time3, temp
    
    	;initialize LED state
    	ldi	LED, 0xff	;all LEDs off
    
    	;initialize task2 state variable (4 times thru equals 1/2 sec)
    	ldi	temp, 4
    	sts	tsk2c, temp
    
    	;initalize task3 message to zero (don't modify task1 rate)
    	ldi	temp, 0
    	sts	tsk3m, temp
    	
    	;Start the clock ticking
    	sei			;enable all interrupts	
    
    ******************************************************************
    ;Now start scheduling events.
    ;This is the main program loop.
    ;All tasks are subroutines called from here when
    ;their respective timers reach zero.
    
    Sched:		
    tsk1:	lds	temp, time1	;test for first task ready
    	tst	temp
    	brne	tsk2		;if not then skip it
    	rcall	Task1
    	
    tsk2:	lds	temp, time2	;test for second task ready
    	tst	temp
    	brne	tsk3		;if not then skip it
    	rcall	Task2
    
    tsk3:	lds	temp, time3	;test for third task ready
    	tst	temp
    	brne	Sched		;if not then skip it
    	rcall	Task3
    	
    	rjmp	Sched
    	
    ;*****************************************************************
    ;The three actual tasks:
    ;******************************
    ;LED 0 2/sec (but modified by Task 3)
    Task1:	lds	temp, tsk3m	;get the message from task 3
    	tst	temp		;and test it for "fast/normal"
    	brne	t1fast
    
    	;if we get here the message from task 3 ="normal rate"
    	ldi	temp, t1	;reinit time counter
    	sts	time1, temp
    	rjmp	t1blk
    
    	;if we get here the message from task 3 ="fast rate"
    t1fast:	ldi	temp, t1	;reinit time counter
    	lsr	temp		;divide time by four
    	lsr	temp
    	sts	time1, temp
    	
    	;now toggle the LED
    t1blk:	mov	temp, LED	;isolate the zero bit
    	andi	temp, 0b00000001; and invert it
    	andi	LED,  0b11111110
    	com	temp
    	andi	temp, 0b00000001
    	or	LED, temp	
    	out	PORTB, LED
    
    	ret			;go back to scheduler
    
    ;******************************
    ;LED 1 1/sec
    Task2: 	ldi	temp, t2	;reinit time counter
    	sts	time2, temp
    
    	lds	temp, tsk2c	;find out if 4 counts have occured
    	dec	temp		;so that we can count to 1/2 second
    	sts	tsk2c, temp
    	tst	temp	
    	brne 	t2exit		;if not then leave
    
    	;if we get here, then 1/2 second has passed and we
    	;should toggle the LED
    	mov	temp, LED	;isolate the zero bit
    	andi	temp, 0b00000010;  invert it
    	andi	LED,  0b11111101;  then combine it with LED again
    	com	temp
    	andi	temp, 0b00000010
    	or	LED, temp	
    	out	PORTB, LED	
    
    	ldi	temp, 4		;and reset the state variable
    	sts	tsk2c, temp
    
    t2exit:	ret			;go back to scheduler
    
    ;******************************
    ;Button detect and modify Task 1 blink rate
    Task3: 	ldi	temp, t3	;reinit time counter
    	sts	time3, temp
    
    	in	temp, PIND	;get all the buttons
    	com	temp		;convert a button-down to a one
    	andi	temp, 0b00000001;isolate button 0
    	brne	t3modt
    
    	;if we get here then set message to "normal" task1 rate
    	ldi	temp, 0		;set message value 
    	sts	tsk3m, temp	;and store it
    	rjmp	t3exit
    
    	;if we get here then set message to "fast" task1 rate
    t3modt:	ldi	temp, 1		;set message value
    	sts	tsk3m, temp	;and store it
    
    t3exit:	ret			;go back to scheduler
    
    
    ;**************************************************************
    ;timer 0 ISR (timer-zero overflow)
    ;Enters every 1.0 mSec
    
    TIMER:	in	save, SREG
    	out 	TCNT0, Reload	; keeps clock ticking at 1 mSec
    	push 	temp		; use temp in ISR
    	
    	;update each of the three timers
    	;for the three tasks
    	;BUT if the count is zero don't do anything until the process
    	;resets it
    
    	lds	temp, time1
    	tst	temp	
    	breq	t0t2
    	dec	temp	
    	sts	time1, temp
    	
    t0t2:	lds	temp, time2
    	tst	temp	
    	breq	t0t3
    	dec	temp	
    	sts	time2, temp
    
    t0t3:	lds	temp, time3
    	tst	temp	
    	breq	t0end
    	dec	temp	
    	sts	time3, temp
    
    t0end:	pop	temp
    	out	SREG, save
    	reti			;back to backgound tasks
    ;**************************************************************
    Ist glaub für Mega32

  5. #25
    Gast
    Und in C sieht es so aus:

    Code:
    //Dup the function of sched1.asm 
    //used as an example in the program organization doc.      
                 
    #include <90s8515.h> 
    
    //timeout values for each task
    #define t1 250  
    #define t2 125
    #define t3 60  
     
    //the three task subroutines
    void task1(void);  	//blink at 2 or 8 Hz
    void task2(void);	//blink at 1 Hz
    void task3(void);	//detect button and modify task 1 rate 
    
    void initialize(void); //all the usual mcu stuff 
              
    unsigned char reload;				//timer 0 reload to set 1 mSec
    unsigned char time1, time2, time3;	//timeout counters 
    unsigned char tsk2c;				//task 2 counter to get to 1/2 second
    unsigned char tsk3m;				//task 3 message to task 1 
    unsigned char led;					//light states  
             
    //**********************************************************
    //timer 0 overflow ISR
    interrupt [TIM0_OVF] void timer0_overflow(void)
      {       
      //reload to force 1 mSec overflow
      TCNT0=reload;
      
      //Decrement the three times if they are not already zero
      if (time1>0)	--time1;
      if (time2>0) 	--time2;
      if (time3>0)	--time3;
      }  
    
    //**********************************************************       
    //Entry point and task scheduler loop
    void main(void)
      {  
      initialize();
      
      //main task scheduler loop
      while(1)
        {     
        if (time1==0)	task1();
        if (time2==0) 	task2();
        if (time3==0)	task3();
        }
      }  
      
    //**********************************************************          
    //Task subroutines
    //Task 1
    void task1(void) 
      {  
      time1=t1;  //reset the task timer
      if (tsk3m != 0) time1 >>= 2;  //check for task 3 message
      
      //toggle the zeros bit
      if ((led & 0x01) == 0)
      	led = led | 0x01;
      else
      	led = led & 0xfe;	
      	
      PORTB = led;
      }  
     
    //******************************* 
    //Task 2  
    void task2(void) 
      {
      time2=t2;  //reset the task timer
      if (--tsk2c == 0)  //have we waited 1/2 second?
      	{  
      	tsk2c = 4;		//reload the 1/2 sec counter
      
         //toggle the ones bit
      	if ((led & 0x02) == 0)
      		led = led | 0x02;
      	else
       		led = led & 0xfd;
       		
      	PORTB = led;
    	}
      }  
     
    //*******************************   
    //Task 3  
    void task3(void) 
      {
      time3=t3;     //reset the task timer
      tsk3m = ~PIND & 0x01;  //generate the message for task 1
      } 
      
    //********************************************************** 
    //Set it all up
    void initialize(void)
    {
    //set up the ports
      DDRD=0x00;	// PORT D is an input
      DDRB=0xff;    // PORT B is an ouput  
      PORTB=0; 
               
      //set up timer 0
      reload=256-62; //value for 1 Msec  
      TCNT0=reload;
      TIMSK=2;		//turn on timer 0 overflow ISR
      TCCR0=3;		//prescalar to 64
        
      //init the LED status (all off)
      led=0xff; 
      
      //init the task timers
      time1=t1;
      time2=t2;
      time3=t3;    
      
      //init the task 2 state variable 
      //for four ticks
      tsk2c=4;
      
      //init the task 3 message
      //for no message
      tsk3m=0;
          
      //crank up the ISRs
      #asm
      	sei
      #endasm 
    }

  6. #26
    Gast
    Nach einigem Halbwissen werde ich erst mal ein bisschen Aufklärung betreiben

    In der Betriebssystemtechnik unterscheidet man grundsätzlich bei Multitasking-BS Prozesse und Threads.
    Der wesentliche Unterschied ist, dass Prozesse in einem eigenem Addressraum ablaufen, Threads hingegen nicht. Threads laufen im Kontext von Prozessen. Aufgeweicht wird das Ganze durch shared Memory, den sich Prozesse teilen können.

    Was ein Multitasking-Betriebssystem für Atemls AVR angeht, so muss man sich das in der Tat nicht als ein grosses BS ala Linux vorstellen.
    Im einfachsten Fall ist das ein simpler Round-Robin-Scheduler, der in festen Zeitscheiben die Threads aufruft. Basta. Ein paar Programmzeilen, das war es.
    Das Ganze kann man dann beliebig um die Üblichen Zutaten erweitern: variable Zeitscheiben, feste Prioritäten, variable Prioritäten, Interprozesskommunikation (Semaphore, shared Memory, etc).

    Auch wenn man es etwas komplexer macht, so kostet das auch nur Rechenzeit in der Gegend von maximal einigen Prozent.

    Ob das Ganze Sinn macht, muss jeder selbst wissen. Die weitaus meisten Controller-Anwendungen in der Industrie funktionieren nach einer Studie aus diesem Jahr immer noch nach dem guten alten Hauptschleife-Flags-Interrupt-Prinzip, wo in der Hauptschleife im Wesentlichen die Flags ausgewertet werden und der Controller dann die entsprechenden Routinen ausführt. In den entsprechenden Interrups werden die Flags dann je nach Ereignis gesetzt.
    Vorteile macht ein Multitasking-System sicher, wenn man mit mehreren Leuten relativ unabhängig voneinander an einem Projekt arbeitet.
    Und es macht sicherlich auch unabhängiger von der Hardware, wenn es ein komplexeres System ist, welches stärker abstrahiert.

  7. #27
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    15.02.2004
    Beiträge
    569
    wenn die microprozessoren noch schneller sind und mehr speicher haben machts mehr sinn. wenn 3 prozesse gleichzeitig laufen, braucht man 3 mal so viel ram
    Haftungsausschluß:
    Bei obigem Beitrag handelt es sich um meine private Meinung.
    Rechtsansprüche dürfen daraus nicht abgeleitet werden.
    Besonders VDE und die geltenden Gesetze beachten sowie einen gesunden Menschenverstand walten lassen!

  8. #28
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    02.07.2004
    Ort
    Mammendorf
    Alter
    67
    Beiträge
    1.062
    Hallo Freunde

    hab mal genau gewusst was der Unterschied zwischen Multitasking und Multithreading ist. Und zwar über Apples altes Mc68k basierendes Betriebssystem. Dort war es so, daß die Programmierrichtilinien verlangten Code so zu schreiben, dass wenn ein Unterprogramm ausgeführt war man keine Bits gesetzt haben durfte die dem eigenen Programm die Kontrolle über den Prozessor auschließßlich gewährten, also Interrupts maskieren. Das Betriebssystem speicherte die requests der einzelnen tasks selber auf seinen eigenen Stack, und so hat ein Interrupt dann eine Routine des Betriebssystems ausgelöst die der nächsten Task in Stack die Kontroller über den Computer gibt. Hat jetzt ein Programmierer diese maskable interrupts maskiert konnte er den Rechner ohne zeitlliche Begrenzung für sein Programm benutzen. Als dann bei Apple echtes Multitasking kam konnte das Betriebssystem über einen Timer und einem nicht maskable Interuupt die Kontrolle wieder übernehmen, hat die Inhalte aller Register auf das Stack gerettet und die nächste Task begann immer damit ihre Registerinhalte vom Stack zu holen und einzulesen.

    Diese Beschreibung zeigt wie man in jedem Prozessor Multitasking einführen kann. Ich kenne den AVR noch nicht, aber ich vermute in Analogie es gibt dort eine Möglichkeit über einen Hardware Timer einen Soft Interrupt auszulösen der einen Zeiger auf eine Interrupt-Service Rotine verweist. Diese Rotine müßte dann wie oben beschrieben die "Laufzeitumgebung der alten Task auf den Stack zu pushen, für die nächste Routine die "Laufzeit" Umgebung wieder einrichten und den Programm Counter auf den letzten Wert, oder letzten Wert plus eins setzen. Natürlich nicht vergessen den Timer zu reseten und neu zu starten.

    Wichtig erscheint mir aber der Hinweis, dass wenn eine Task eine "Echtzeit" Aufgabe bearbeitet die Möglichkeit haben muß das Interrupt des Taskmanagers zu maskieren und erst dann wieder entmaskieren wenn das zeitkritische erledigt ist. Gerade im embedded Bereich, und das sind wir hier ja.


    Beim Mu

  9. #29
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    15.02.2004
    Beiträge
    569
    vielleicht waere ein microprozessor mit linux besser geeignet (gibts fertig zu kaufen). die sind viel schneller als ein avr, haben viel mehr ram und mehr flash. sind nur etwas teurer.
    Haftungsausschluß:
    Bei obigem Beitrag handelt es sich um meine private Meinung.
    Rechtsansprüche dürfen daraus nicht abgeleitet werden.
    Besonders VDE und die geltenden Gesetze beachten sowie einen gesunden Menschenverstand walten lassen!

  10. #30
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    02.07.2004
    Ort
    Mammendorf
    Alter
    67
    Beiträge
    1.062
    Hallo hrrh

    Du weisst schon das wir über Routinen sprechen die nur wenige Zeilen lang sind? Übrigens werden in der Industrie viele sogenannte RTOS eingesetzt die damit werben extrem effizient und extrem kleines footprint zu haben?! Und das in sehr kostensensitiven Anwendungen, z.B 68hc05!?

Seite 3 von 4 ErsteErste 1234 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Labornetzteil AliExpress