Is there any ability to use the hardware timers on third generation devices without going to monolithic firmware? Without these the ability to leverage the M4 in the NRF52840 for real-time DSP is greatly impaired.
@dzimmanck, currently there is not. Furthermore, there is only one potential unused hardware timer available. As for “real -time DSP”, given the SoftDevice and Particle stacks running on FreeRTOS, I’m not sure how “real-time” you’ll be able to get on the nRF52840.
Interesting. I had a go at it anyways, as I appear to have access to nrf_drv_timer.h from the app level and was able to compile code which uses one of the hardware timers, but after re-flashing the device it can no longer connect with the particle cloud. I am wondering if I over-wrote a timer which was being used for a critical function in deviceOS.
Any idea which timer isn;t used?
@dzimmanck, I’ll inquire.
I got 10 red blinks after the SOS message, which I guess means I introduced an assertion error.
Here is my code. Attempting to run on an Argon. Basically a high performance blinky program.
#include <stdbool.h>
#include <stdint.h>
#include "nrf.h"
#include "nrf_drv_timer.h"
#include "app_error.h"
const nrf_drv_timer_t SIMPLE_TIMER = NRF_DRV_TIMER_INSTANCE(0);
int led1 = D7;
void on_receive(const char *event, const char *data) {
Serial.println(event);
Serial.println(data);
}
/**
* @brief Handler for timer events.
*/
void timer_event_handler(nrf_timer_event_t event_type, void* p_context)
{
static bool led_is_on = false;
switch (event_type)
{
case NRF_TIMER_EVENT_COMPARE0:
if(led_is_on)
{
digitalWrite(led1, LOW);
led_is_on = false;
}
else
{
digitalWrite(led1, HIGH);
led_is_on = true;
}
break;
default:
//Do nothing.
break;
}
}
void setup() {
// open the serial port at 9600 bps:
Serial.begin(9600);
// subscribe to the power meter data
Mesh.subscribe("meter-0", on_receive);
pinMode(led1, OUTPUT);
uint32_t time_ms = 500; //Time(in miliseconds) between consecutive compare events.
uint32_t time_ticks;
uint32_t err_code = NRF_SUCCESS;
// Calculate the number of time ticks to program the timer
time_ticks = nrf_drv_timer_ms_to_ticks(&SIMPLE_TIMER, time_ms);
// configure the timer
nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
err_code = nrf_drv_timer_init(&SIMPLE_TIMER, &timer_cfg, timer_event_handler);
nrf_drv_timer_extended_compare(
&SIMPLE_TIMER, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
nrf_drv_timer_enable(&SIMPLE_TIMER);
}
void loop() {
}
I was not able to recover my device even after manually re-flashing it over USB. This code appears to kill an Argon.
@dzimmanck, ouch! Testing might require a monolithic build. Does the device enter DFU mode?
I am able to get it in DFU mode and the CLI reports successful reflash, but still same error on bootup. I am wondering if I somehow damaged the flasher or the bootloader by changing a timer config setting. I sent a support request to Particle.
I shared the code above. Anyone have another Argon they want to sacrifice to see if the kill code is repeatable? I only had the one.
I think it was the bootloader that I damaged. I was able to recover the device if I first reflash the bootloader:
particle flash --usb “argon-bootloader@1.1.1-rc.1.bin” --force
Very interesting.
@peekay123, you ever able to acquire any more insight to this? My main objective is to build a VERY low-cost power meter, but in order to do proper power calculations, I need to do some operations on multiple ADC channels synchronously in “real-time” (~10kHz). The ARM M4 is plenty powerful to do this, but maybe deviceOS on third gen devices just makes this an ill suited platform architecturally.
@dzimmanck, not sure mesh devices are the right platform given the DeviceOS overhead. I believe most if not all DMA channels are used up. The Photon makes a better platform for what you want and @rickkas7 has a good example of multi-ADC sampling.