Forum: Mikrocontroller und Digitale Elektronik nRF5 SDK vs. nRF Connect SDK (Zephyr)


von Adam P. (adamap)


Lesenswert?

Guten Morgen zusammen,

ich habe dieses Jahr begonnen mich mit dem nRF52840 zu beschäftigen und 
bin immer noch von der Flut an Informationen etwas überfordert...

Vorhandene HW:
- nRF52840-DK
- nRF52840-Dongle

Installiert:
(1) nRF5 SDK 17.0.2 + SEGGER Embedded Studio
(2) nRF Connect v3.6.1 + nRF Connect SDK v1.4.2 (inkl. SEGGER ES)

Soweit ich es richtig verstanden habe, schreibt man bei (1) sein "Code" 
und nutzt dazu ein SoftDevice Paket.
Bei (2) nutzt man als Basis das Zephyr RTOS welches intern eine 
Anbindung an ein SoftDevice hat.

Hat von euch jemand Erfahrung mit (1) und/oder (2).

Habe nämlich mit Zephyr ein 1ms LED Toggle versucht, was so gar nicht 
funktioniert hat (zeitlich).

Im späteren Verlauf soll unteranderem ein AFE44xx angeschlossen werden, 
dieser sendet alle 2ms Daten.
Dazu kommt noch ein weiterer ADC bzw. µC für weitere AD Kanäle und eine 
SD-Karte zur Datenspeicherung.

Ist es mit dem RTOS überhaupt möglich diese Zeiten einzuhalten?
Oder wäre es mit (1) einfacher, da der ganze Overhead wegfallen würde.

Mein letztes Projekt mit einem SAM4E hatte viel mehr an verwendeter 
Peripherie und Datenfilterung - und da kam ich auf eine Laufzeit von ca. 
0,7ms für einen kompletten Durchlauf.

Dazu muss noch gesagt werden, ich habe bis jetzt noch nie ein RTOS 
verwendet - habe zwar mal hier und da in Linux Sourcen gestöbert aber 
noch nie programmiert (somit fehlt mir der ganze Zusammenhang der 
internen Funktionsweise).

Hoffe ihr habt ein paar Tipps für mich.

Gruß Adam

von Til S. (Firma: SEGGER) (til_s)


Lesenswert?

Adam P. schrieb:
> Hat von euch jemand Erfahrung mit (1) und/oder (2).

Mehr oder weniger ;-). Also zumindest mit (1).
Embedded Studio ist schon einmal eine gute Wahl weil es das für Nordic 
Kunden kostenlos gibt: 
https://www.nordicsemi.com/Software-and-tools/Development-Tools/Segger-Embedded-Studio

embOS kannst du recht einfach mit dem Nordic Softdevice Stack laufen 
lassen. Du musst nur ein paar Kleinigkeiten beachten, die hier 
beschrieben sind:
https://wiki.segger.com/Using_embOS_with_Nordic_BLE

Am besten du startest mit embOS Cortex-M Embedded Studio:
https://www.segger.com/products/rtos/embos/supported-cores-compiler/arm/cortex-m/embos-cortex-m-embedded-studio/

Darin findest du ein BSP für nRF52840, das out of the box funktioniert.
Anschließend kannst du dann weitere Nordic Software zu dem Projekt 
hinzufügen.

Adam P. schrieb:
> Ist es mit dem RTOS überhaupt möglich diese Zeiten einzuhalten?
> Oder wäre es mit (1) einfacher, da der ganze Overhead wegfallen würde.

(1) heißt ja nicht das du kein RTOS benutzt. Klar, kannst du solche 
Zeiten mit einem RTOS einhalten. Das hat dann weniger mit dem RTOS als 
mit der Leistung deiner CPU zu tun. Selbst mit RTOS kannst die CPU nicht 
mehr als 100% auslasten.
Ein Beispiel: Du musst jede Millisekunde einen Messwert aufnehmen. Das 
dauert 500 usec. Du musst aber jede Millisekunde auch noch etwas anderes 
machen, was 600 msec dauert. Ist das mit einem RTOS möglich? Nein, aber 
auch nicht ohne RTOS weil das 110% CPU Auslastung wären ;-).
Ein RTOS verursacht kaum weitere CPU Last. Bis auf den System Tick, als 
Basis für alle Zeit gesteuerten Aktionen, gibt es nichts, was irgendwie 
im Hintergrund läuft und die CPU belastet.

Du kannst dich auch gerne direkt bei uns melden, dann helfen wir dir 
weiter.

von Johannes (Gast)


Lesenswert?

Habe auch mit 1 Erfahrung, aber auf dem 51822 und 52832.

Es hat einige Zeit gedauert, die Beispiele so weit zu entrümpeln und 
aufzuräumen, dass man damit sauber arbeiten kann. Zur Entwicklung nehm 
ich CMake/Armgcc auf Linux.

Vom Timing her bist du sehr stark an BLE gebunden. Das gibt dir ein paar 
feste Zeitfenster vor zu denen sich der uC melden muss, die darfst du 
nicht auslassen sonst bricht die Verbindung ab. Daher sind die 
Controller auch ziemlich gut mit DMA ausgestattet.

Die sonstigen Berechnungen müssen im Hintergrund laufen wenn der BLE 
Stack keine Arbeit hat. Auch längere ISRs können sich sehr nachteilig 
auf die Verbindungsstabilität auswirken.

von Johannes (Gast)


Lesenswert?

Für mich am sinnvollsten war bisher, Messungen über eine State Machine 
gesteuert über einen AppTimer auszuführen. Die letztliche Ausführung der 
Messungen passiert dann im main loop.

von Adam P. (adamap)


Lesenswert?

Til S. schrieb:
> embOS kannst du recht einfach mit dem Nordic Softdevice Stack laufen
> lassen.

Danke für die Info, jedoch werde ich wohl den Weg ohne RTOS einschlagen.
Der Ablauf ist recht simpel (geradlinig), weiß nicht ob ein RTOS da 
wirklich nötig ist.

Johannes schrieb:
> Messungen über eine State Machine
> gesteuert über einen AppTimer auszuführen.

Ich habe gestern das Timer Bsp.-Projekt angepasst:
(nrf_dev_timer_example_main "\examples\peripheral\timer")
Prescaler: 0 (16Mhz) und mit 16000 "vorgeladen", sollte 1ms ergeben.

Gemessen mit LogicAnalyser habe ich Zeiten von 0.9894ms bis 0.9923ms...?

Wie kommt diese Schwankung zustande?

Im Datenblatt steht was von:
"Independent of prescaler setting the accuracy of the TIMER is 
equivalent to one tick of the timer frequency fTIMER as illustrated in 
Block schematic for timer/counter on page 459."

Ok, das würde bei 16MHz -> 62,5ns ausmachen, wenn ich es richtig 
verstanden habe, den 1 Tick könnte man ja anpassen, aber woher diese 
Schwankung.

Oder habe ich den Timer falsch eingestellt?
Weißt du da mehr?
Es läuft ja sonst nichts anderes...
1
#include <stdbool.h>
2
#include <stdint.h>
3
#include "nrf.h"
4
#include "nrf_drv_timer.h"
5
#include "bsp.h"
6
#include "app_error.h"
7
8
const nrf_drv_timer_t TIMER_LED = NRF_DRV_TIMER_INSTANCE(0);
9
10
/******************************************************************************/
11
void timer_led_event_handler(nrf_timer_event_t event_type, void* p_context)
12
{
13
    if(event_type == NRF_TIMER_EVENT_COMPARE0)
14
    {
15
        bsp_board_led_invert(0);
16
    }
17
}
18
19
/******************************************************************************/
20
int main(void)
21
{
22
    uint32_t time_ms = 1;
23
    uint32_t time_ticks;
24
    uint32_t err_code = NRF_SUCCESS;
25
26
    bsp_board_init(BSP_INIT_LEDS);
27
28
    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
29
  
30
    err_code = nrf_drv_timer_init(&TIMER_LED, &timer_cfg, timer_led_event_handler);
31
    APP_ERROR_CHECK(err_code);
32
33
    time_ticks = nrf_drv_timer_ms_to_ticks(&TIMER_LED, time_ms);
34
35
    nrf_drv_timer_extended_compare(&TIMER_LED,
36
        NRF_TIMER_CC_CHANNEL0,
37
        time_ticks,
38
        NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
39
        true);
40
41
    nrf_drv_timer_enable(&TIMER_LED);
42
43
    while (1)
44
    {
45
        __WFI();
46
    }
47
}

---
edit:

Kennt einer von euch "embedded centric"?
https://embeddedcentric.com/courses/nordic-nrf5x-ble-in-depth-training-course/

Finde im Internet nichts was sich auf die Seite beziehen würde.
Und außer der Tel. und Kontaktformular findet man auch keine weiteren 
Angaben wem die Seite gehört usw.

Vertrauenswürdig?

: Bearbeitet durch User
von Johannes (Gast)


Lesenswert?

Ich hab mir das Macro NRF_DRV_TIMER_DEFAULT_CONFIG nie genau angesehen. 
Die NRF51/2 haben aber 2 verschiedene Taktquellen für den LF Timer, es 
gibt einen internen RC Oszillator und einen mit externem Uhrenquarz.

Da der Uhrenquarz nicht wirklich mehr Strom verbraucht als der interne 
RC lohnt sich der interne imho nicht. Mein Code für den NRF51 sah 
ungefähr so aus, zusammengestückelt aus dem SDK 12:
1
#define NRF_CLOCK_LFCLKSRC \
2
  {\
3
    .source = NRF_CLOCK_LF_SRC_XTAL, \
4
    .rc_ctiv = 0, .rc_temp_ctiv = 0, \
5
    .xtal_accuracy=NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM\
6
  }

und später
1
    nrf_clock_lf_cfg_t clock_lf_cfg = NRF_CLOCK_LFCLKSRC;
2
    SOFTDEVICE_HANDLER_INIT(&clock_lf_cfg, NULL);


Beim NRF52 schaut die Init-Routine etwas anders aus. Soweit ich mich 
erinnere wird der LF Oszillator vom Softdevice initialisiert, wenn er 
noch nicht vorher initialisiert wurde.

Was da per default verwendet wird weis ich nicht, in deinem Fall würd 
ich aber schauen, ob der interne oder externe LF Osc. verwendet wird.

von Johannes (Gast)


Lesenswert?

Ansonsten kannst du die Frage auch hier stellen: 
https://devzone.nordicsemi.com/f/nordic-q-a

Der Nordic Support ist ziemlich gut.

von Johannes (Gast)


Lesenswert?

... und nochmal: Wenn ich so drüber nachdenke war ich auf dem falschen 
Dampfer unterwegs, du hast den Timer ja explizit auf den CPU Takt 
gelegt, wenn ich das richtig verstanden habe.

Deine Zeitdifferenz ergibt 333kHz, lief der Logic Analyzer vielleicht 
auf 333ksps?

von Adam P. (adamap)


Lesenswert?

Johannes schrieb:
> du hast den Timer ja explizit auf den CPU Takt
> gelegt, wenn ich das richtig verstanden habe.

Der Timer wird mit 16MHz getaktet. (PCLK16M ohne Teiler)
Der LA lief mit 100 MS/s.

Habs aber auch mit Oszi gemessen, da ist es genau so.

Oft findet man den hinweis, für PIN Output sollte man lieber
PPI mit GPIOTE nutzen - nützt nix, genau so ungenau.

Also irgendwie kann ich mir das nicht erklären (wahrscheinlich meine 
Unwissenheit).

Aber es muss doch eine Möglichkeit geben, Code in schönen stabilen 
Intervallen auszuführen.

Wenn ich jede ms um 0,0077ms (7,7µs) daneben liege, dann habe ich bei 
einer 8std. Messung einen Versatz von 221,76 sec. - das kanns ja nicht 
sein.

Der TIMER0_IRQHandler macht ja auch nicht viel außer meinen Callback 
aufzurufen, kann mir echt nicht erklären, warum die Schwankungen da sind 
und warum der LOAD-Value nicht dem entspricht was rechnerisch richtig 
wäre.

:-/

von Johannes (Gast)


Lesenswert?

Möglicherweise ist es das hier:
1
Hi,
2
3
The chip works from internal RC oscillator if you didn't enable HFXO. When SoftDevice starts radio activity, it switches to HFXO - the frequencies are slightly different, that's why you see a jitter. To work from HFXO all the time, call sd_clock_hfclk_request().

Offenbar gibt es auch für den 16MHz Takt einen internen RC Oszillator, 
den du erst auf den externen Quarz umstellen musst.


https://devzone.nordicsemi.com/f/nordic-q-a/66398/nrf52840-pwm-jitter
(Da hatte jemand ein ziemlich ähnliches Problem wie du)

von Adam P. (adamap)


Lesenswert?

Johannes schrieb:
> Hi,
> The chip works from internal RC oscillator if you didn't enable HFXO.
> When SoftDevice starts radio activity, it switches to HFXO - the
> frequencies are slightly different, that's why you see a jitter. To work
> from HFXO all the time, call sd_clock_hfclk_request().

Das würde vieles erklären :-)

Probier ich morgen früh mal direkt aus...

Ich dachte das der externe 16MHz verwendet wird und die internen müsste 
man erst aktivieren, aber das könnte es echt sein.

Johannes schrieb:
> Offenbar gibt es auch für den 16MHz Takt einen internen RC Oszillator,

Ja den gibt es.

Danke schonmal, werde morgen berichten.

von Johannes (Gast)


Lesenswert?

Ja das Ding ist kompromisslos auf stromsparen ausgelegt, über ein paar 
Eigenheiten bin ich auch schon gestolpert. Dafür erreicht man z.B. 
problemlos 25µA mit dauerhafter Erreichbarkeit über BLE. Ein STM32F103 
schafft das vielleicht gerade so im power down.

Der interne HF RC Osc. braucht sicher weniger Strom als ein Quarz, also 
ist es nur logisch, dass der uC auf dem läuft wenn der BLE Stack nicht 
gerade einen Takt mit hoher Genauigkeit benötigt.

Für exaktes Timing gibt es ja noch den LF XTAL, der braucht wenig Strom.

von Adam P. (adamap)


Angehängte Dateien:

Lesenswert?

...So einfach kann die Lösung sein :-)

Danke @Johannes!
1
void clocks_start( void )
2
{
3
    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
4
    NRF_CLOCK->TASKS_HFCLKSTART = 1;
5
6
    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
7
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.