FreeRTOS semaphore met Serial.println() ?

Arduino specifieke Software
Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

FreeRTOS semaphore met Serial.println() ?

Berichtdoor Koepel » 23 Dec 2016, 22:25

In de Library Manager zit FreeRTOS voor AVR microcontrollers, dat is deze : https://github.com/feilipu/Arduino_FreeRTOS_Library.
Die ben ik aan het proberen op een Arduino Uno.

:?: Mijn vraag is of het nodig is om een semaphore te gebruiken voor de Serial.println() :?:

Dat wordt gebruikt in dit voorbeeld : https://github.com/feilipu/Arduino_FreeRTOS_Library/blob/master/examples/AnalogRead_DigitalRead/AnalogRead_DigitalRead.ino.
De FreeRTOS is niet pre-emptive, dus hij schakelt alleen van taak bij een functie van FreeRTOS, bijvoorbeeld tijdens "vTaskDelay()".
Volgens mij kunnen verschillende Serial.println() nooit door elkaar heen gaan. Zelfs niet als de Serial buffer vol zou raken.

Ik vermoed dat er nog veel meer Arduino libraries zijn die niet geschikt zijn voor pre-emptive multitasking, maar die worden gewoon gebruikt omdat FreeRTOS toch niet pre-emptive is. De Serial library is volgens mij niet anders.

Alleen als een tekst wordt opgebouwd en naar de seriële monitor wordt gestuurd, en daar tussendoor wordt "vTaskDelay()" aangeroepen. Dan kan het handiger zijn om de verschillende teksten van de verschillende taken te scheiden met een semaphore. Maar die situatie lijkt me nogal vergezocht.

Advertisement

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: FreeRTOS semaphore met Serial.println() ?

Berichtdoor nicoverduin » 24 Dec 2016, 11:20

Ik denk dat je gelijk hebt. Hoewel het gebruik van semaphoren geen kwaad kan om het in je "genen" te krijgen als je met de echte RToS'en gaat werken. Als ik kijk naar de routine :
cpp code
size_t HardwareSerial::write(uint8_t c)
{
_written = true;
// If the buffer and the data register is empty, just write the byte
// to the data register and be done. This shortcut helps
// significantly improve the effective datarate at high (>
// 500kbit/s) bitrates, where interrupt overhead becomes a slowdown.
if (_tx_buffer_head == _tx_buffer_tail && bit_is_set(*_ucsra, UDRE0)) {
*_udr = c;
sbi(*_ucsra, TXC0);
return 1;
}
tx_buffer_index_t i = (_tx_buffer_head + 1) % SERIAL_TX_BUFFER_SIZE;

// If the output buffer is full, there's nothing for it other than to
// wait for the interrupt handler to empty it a bit
while (i == _tx_buffer_tail) {
if (bit_is_clear(SREG, SREG_I)) {
// Interrupts are disabled, so we'll have to poll the data
// register empty flag ourselves. If it is set, pretend an
// interrupt has happened and call the handler to free up
// space for us.
if(bit_is_set(*_ucsra, UDRE0))
_tx_udr_empty_irq();
} else {
// nop, the interrupt handler will free up space for us
}
}

_tx_buffer[_tx_buffer_head] = c;
_tx_buffer_head = i;

sbi(*_ucsrb, UDRIE0);

return 1;
}

Dan wacht deze tot er ruimte is in de buffer om te schrijven. De ISR van de Serial die leest de buffer en verstuurd gewoon en past de head pointer aan. Echter bovenstaande wordt niet onderbroken en wacht zelfs totdat er ruimte is in de buffer. Dus in dit geval lijkt het mij overbodig.
De Arduino libraries zijn ongetwijfeld nog niet geschikt gemaakt voor RToS omdat RToS anders wel ondersteund zou worden in de standaard IDE. Daarnaast is het maar de vraag of de meerderheid van de gebruikers überhaupt begrijpen wat een RToS is en of men het begrijpt.
Daarnaast heb je ook nog eens te maken met allerlei modules die niet onderbroken mogen worden. Denk aan communicatie functies (SPI, I2C, Ethernet, WiFi etc). Als je te maken hebt met SoC's (ESP8266, TI CC2650 en steeds meer SoC's met WiFi en/of Bluetooth enz) mogen sommige functies niet onderbroken worden.
Ik ben op dit moment bezig met CC2650 SoC's van TI met BlueTooth communicatie waarbij TiRToS draait op de chip. Als je daar rechtstreeks een System_printf() doet zonder semaphoren, krijg je prachtige output op de Serial, maar de verbinding met BT is weg.....
Het wordt een ander verhaal als je 'time slicing' gaat toepassen waarbij je taken krijgt die pseudo naast elkaar draaien. Die truuk haalde ik regelmatig uit in de jaren 80 met MsDos om bijvoorbeeld dBase3 te laten praten met een Mainframe IMS toepassing. Beide in het geheugen en dan continu switchen van taken waarbij je alle registers, de stackpointer en de program counter moest opslaan en omzetten voor de andere taak. Dit zou ook in de Arduino kunnen maar ook dan moet je rekening houden welke taken je wel mag onderbreken en welke niet.
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: FreeRTOS semaphore met Serial.println() ?

Berichtdoor Koepel » 24 Dec 2016, 12:17

Bedankt Nico.
Dan klopt mijn vermoeden.

Ik ben alleen nog maar bezig met de basis dingen: taken, semaphores, en queues.
Gelukkig kan ik de HighWaterMark van de stack opvragen. Dat is de ruimte op de stack die nog nooit gebruikt is sinds het starten van de taak. Soms zie ik een aantal seconden na het starten die waarde opeens verminderen, dan waren er interrupt(s) bezig.

De Arduino loop() wordt bij FreeRTOS de idle task. Ik delete per ongeluk de idle task, en toen crashte alles. Dus tot nu toe gaat het alleen mis als ik iets verkeerds doe. Het lijkt best goed te werken :D

Om een volle Arduino TX buffer te voorkomen is de functie Serial.availableForWrite() toegevoegd. Daarmee is het mogelijk om te kijken of een bericht in zijn geheel in de TX buffer past.

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: FreeRTOS semaphore met Serial.println() ?

Berichtdoor nicoverduin » 24 Dec 2016, 12:29

Je zou voor het goede eens een grotere processor eens moeten bekijken om te zien wat er dan bij komt kijken. Voordat die TI rtos door hebt ben je weer ff zoet. Maar je moet er gewoon mee spelen. Het is de enige manier om het te snappen. Pas als je 'ziet' hoe het werkt kan je echte applicaties bouwen. Met plakken kom je meestal niet erg ver. Alleen komt die boodschap meestal niet over bij de meesten.
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: FreeRTOS semaphore met Serial.println() ?

Berichtdoor Koepel » 24 Dec 2016, 14:25

Ik blijf liever wat dichter bij de Arduino. Bijvoorbeeld met een M0+ processor. Maar dit neem ik niet erg serieus : https://www.arduino.cc/en/Reference/Scheduler.

Dus voorlopig ben ik al blij dat FreeRTOS stabiel lijkt te werken met een eenvoudige AVR microcontroller :D

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: FreeRTOS semaphore met Serial.println() ?

Berichtdoor nicoverduin » 24 Dec 2016, 14:44

Want? Ze draaien alleen niet tegelijkertijd. Maar zo werkt eigenlijk elke VM machine. Heel heel heel vroeger heette dat "Time sharing". IBM had het, Unix had het, Control Data (mijn werkgever) had het... Beetje het verhaal wat ik eerder vertelde waarbij je de registers gewoon op een stack knikkerde en dan ander weer binnenhaalde om elders verder te draaien zonder dat de processen het van elkaar wisten.
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Gebruikers-avatar
Berichten: 631
Geregistreerd: 15 Nov 2015, 11:54

Re: FreeRTOS semaphore met Serial.println() ?

Berichtdoor Gij Kieken » 24 Dec 2016, 17:58

Leuk om te lezen deze discussie ,maar voorlopig toch wel een brug te ver voor mij.
Ik hou het maar bij Blink & State Machine en ben heel erg blij als een sketch doet wat ik ervan verwacht.

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: FreeRTOS semaphore met Serial.println() ?

Berichtdoor Koepel » 24 Dec 2016, 19:27

@nicoverduin, je bedoelt met "want?" omdat ik schreef dat ik die scheduler niet erg serieus neem ?
Dit is de hele scheduler voor de M0+ : https://github.com/arduino-libraries/Scheduler/blob/master/src/Scheduler.cpp.
Alleen de yield() wordt gebruikt om te switchen tussen taken.

Tsja, nu ik er over nadenk... Misschien is meer niet nodig. Hij schakelt naar een andere taak wanneer een delay() wordt gedaan of als je zelf een yield() geeft. Dus dan zijn speciale semaphores en queues misschien niet nodig.

Ik heb lang geleden met pre-emptive multitasking gewerkt.
Dan is het eerste ontwerp van de software veel sneller op te zetten. Daarom heb ik moeite met deze manier, omdat een taak dan alsnog alle cpu tijd kan bezetten waardoor de andere taken niet aan de beurt komen. Als millis() wordt gebruikt dan gaat het er om, om de delay() zo weinig mogelijk te doen, maar met de Arduino scheduler is opeens de delay() essentieel om het soepel te laten draaien :roll:

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: FreeRTOS semaphore met Serial.println() ?

Berichtdoor nicoverduin » 24 Dec 2016, 20:59

Tja er zijn nu eenmaal vele wegen naar rome. Hoewel dit soort portings meer een doel opzichbegint te worden. Gewoonomdat het kan. Waar overigens niets mis mee is. Hier leer je hetmeeste van....
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Terug naar Arduino software

Wie is er online?

Gebruikers in dit forum: avezopar en 48 gasten