arduino / ArduinoCore-nRF528x-mbedos

[Archived] Arduino core supporting mbed-enabled boards
86 stars 34 forks source link

Accessing the underlying Nordic SDK #58

Open theelims opened 4 years ago

theelims commented 4 years ago

The last days I tried to gain access to the Nordic SDK below the mbed layer. My application needs tight timings and the mbed timers caused to much jitter. Therefore I tried going with the hardware timer and nrf52's PPI module. I tried to get a modified timer-example from the nordic SDK to compile. So far without success. I reached a dead end and are looking for advice.

  1. I learned about the role of sdk_config.h and how to overwrite the default configuration with the right defines.
  2. There are many missing headers and source files for the SDK. Some are already missing in the original mbed repos. But the arduino repo dismissed even more: ArduinoCore-nRF528x-mbedos/cores/arduino/mbed/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_15_0/modules/nrfx/drivers/src is missing all source files. The headers are complete. The mbed repo still has all sources present. ArduinoCore-nRF528x-mbedos/cores/arduino/mbed/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_15_0/integration/nrfx/legacy/ The legacy layer is missing most files also. But mbed is not better here.

I copied all missing files (nrfx_timer.c & nrf_drv_timer.h) into their respective folder. I took them from the nordic SDK 15.0.

  1. The compiler seems to find all headers now. However, the linker throws some errors:
    Arduino: 1.8.10 (Windows 10), Board: "Arduino Nano 33 BLE"
    sketch\sketch_mar06a.ino.cpp.o: In function `setup':
    C:\Users\elims\Documents\Arduino\Tests\sketch_mar06a/sketch_mar06a.ino:51: undefined reference to `nrfx_timer_init'
    C:\Users\elims\Documents\Arduino\Tests\sketch_mar06a/sketch_mar06a.ino:56: undefined reference to `nrfx_timer_extended_compare'
    C:\Users\elims\Documents\Arduino\Tests\sketch_mar06a/sketch_mar06a.ino:59: undefined reference to `nrfx_timer_enable'
    collect2.exe: error: ld returned 1 exit status
    exit status 1

Here is the actual code I'm trying to compile. Via googling I got the hint, that it doesn't find the nrfx_timer.c. The include paths in the includes.txt are all set to these folders. How do I tell the linker where to look?

//override settings in sdk_config.h to enable timer support
#define NRFX_TIMER_ENABLED 1
#define NRFX_TIMER0_ENABLED 1
//enable legacy support
#define TIMER_ENABLED 1
#define TIMER0_ENABLED 1

#include "nrf.h"
#include "nrf_drv_timer.h"
#include "app_error.h"

const nrf_drv_timer_t TIMER_LED = NRF_DRV_TIMER_INSTANCE(0);

mbed::DigitalOut led1(digitalPinToPinName(LED_BUILTIN));

void flip() {
    led1 = !led1;
}

/**
 * @brief Handler for timer events.
 */
void timer_led_event_handler(nrf_timer_event_t event_type, void* p_context)
{
    switch (event_type)
    {
        case NRF_TIMER_EVENT_COMPARE0:
            flip();
            break;

        default:
            //Do nothing.
            break;
    }
}

void setup() {
    uint32_t time_ms = 500; //Time(in miliseconds) between consecutive compare events.
    uint32_t time_ticks;
    uint32_t err_code = NRF_SUCCESS;

    //Configure all leds on board.
    led1 = 1;

    //Configure TIMER_LED for generating simple light effect - leds on board will invert his state one after the other.
    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    err_code = nrf_drv_timer_init(&TIMER_LED, &timer_cfg, timer_led_event_handler);
    APP_ERROR_CHECK(err_code);

    time_ticks = nrf_drv_timer_ms_to_ticks(&TIMER_LED, time_ms);

    nrf_drv_timer_extended_compare(
         &TIMER_LED, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);

    nrf_drv_timer_enable(&TIMER_LED);
}

void loop() {
  while(1){
    __WFI();
  }
}

Arduino and mbed are perfect for most high level stuff. However, some things need to be done with dedicated hardware peripherals. I would highly appreciate if it would be possible to use the advanced hardware features of this fantastic chip out of the arduino environment. Like it is possible an all other platforms.

facchinm commented 4 years ago

Hi @theelims , source files are not there since we precompile them (via mbed-os-to-arduino script) and only provide the headers. So, you can freely use all the functions defined in the headers files and they will be resolved when linking against libmbed.a . mBED provides a very specific version of the SDK with some custom patches applied so the files obtained from another SDK could not work as expected. Anyway, at least to fix compilation, you must place the extra files in a folder that is scanned at compile time (your sketch itself is a good place in this case). Just add them to the sketch folder and you are done :wink:

theelims commented 4 years ago

Hi @facchinm , thank you for your help. I tried as you suggested and moved to the two files into the sketch folder. But the compiler message stayed the same.

But I think I found the root cause. The timer functions are never pre-compiled into libmbed.a in the first place. They need to be activated inside sdk_config.h where they are disabled by default.

So I would either need to make my own pre-compiled version of libmed.a with the required nrfx-drivers enabled or tell the compiler to build everything from scratch.

Could you please advise me how to do so? That's way over my head.

facchinm commented 4 years ago

To produce a different libmbed.a the procedure is straightforward (from Linux and probably from Mac). You wound need to download a local copy of https://github.com/ARMmbed/mbed-os , modify the sdk, navigate to the NANO 33 BLE core (in ~/.arduino15/packages/arduino/hardware/mbed/1.1.4/) and run ./mbed-os-to-arduino -r $path_where_you_downloaded_mbed_os ARDUINO_NANO33BLE:ARDUINO_NANO33BLE . In this way, it will rerun our build script but using your modified sdk.

theelims commented 4 years ago

Can this be done on Windows as well? Cygwin maybe?

This way certainly works for one-off projects. But do you see a chance of somehow make the advanced sdk functions available natively from within the Arduino environment? Otherwise the whole NANO 33 BLE boards stay limited to what mbed is offering. Tight real-time applications or other advanced hardware peripherals won't be doable with this board.

I was planing on releasing shields or derived boards and open source them. But if everyone interested in playing with these boards would need to go through these steps this would be quite a steep barrier.

facchinm commented 4 years ago

@theelims mbed usually strives enable all the drivers; if a driver is deactivated in the sdk, it probably mean that:

Did you try measuring mbed::Timer 's jitter? It should be based on the same timer AFAIK, and you can improve the precision with this code

polldo commented 4 years ago

Hi @theelims , check https://github.com/arduino/ArduinoCore-nRF528x-mbedos/pull/72, in which I used functions of the Nordic SDK 15 directly, in order to exploit hardware peripherals (timer included). The problem of your sketch is that it refers to functions of the nordic SDK11. Instead, the SDK15 ones should be used. Try to use "nrfx_timer.c" from SDK15, that is the analogue of "nrf_drv_timer.c" from SDK11. Also, when using timers, take in mind that TIMER1 is already employed by nrf libraries to implement the us_ticker for mbed os. You can find it here: https://github.com/ARMmbed/mbed-os/blob/master/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/us_ticker.c Then, TIMER0 is used for nordic 'SoftDevice' that we are not exploiting, so if I'm not wrong it can be used for other purposes.

theelims commented 4 years ago

Hi @Polldo,

wow, you puzzled all the pieces together I need. Just the other way around. I will have a closer look at your code. Thanks. I'll revisit my project again.