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
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.
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.
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.
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
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.
Ansonsten kannst du die Frage auch hier stellen: https://devzone.nordicsemi.com/f/nordic-q-a Der Nordic Support ist ziemlich gut.
... 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?
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. :-/
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)
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.
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.
...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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.