5 years, 7 months ago.

Problems with timeout timer on nRF51822 board.


I have two ISRs that are attached to the falling edge of two pins on the Arch BLE board. These lines provide data that I want to record, and it comes at unpredictable times. I know that the data is finished after I don't receive anymore for 3ms.

So I need to somehow start a timer from within the ISR that resets each time new data is received so when it hits 3ms it can process the data, then detach the timer and go back to the ble.WaitForEvent().

What I'm doing now doesn't seem to be working, can anyone help me out? I've tried tons of different variations of the code below.

see note below the code this code works on the FRDM K64F.

Thanks very much!

#include "mbed.h"
#include "BLEDevice.h"

#define MAX_BITS 100
#define WIEGAND_WAIT_TIME 3000     // wait for 3000us max for next Wiegand signal (max time between pulses is 2ms)

BLEDevice  ble;
Serial pc(USBTX, USBRX); 
Timeout wiegandTimer;

InterruptIn DATA0(p0);
InterruptIn DATA1(p1);

volatile unsigned char databits[MAX_BITS];  // stores all of the data bits
volatile unsigned char bitCount= 0;         // number of bits currently captured
volatile bool flagDone = false;             // goes low when data is currently being captured

void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
    ble.startAdvertising(); // restart advertising

void parseWiegand (void) {
    pc.printf("\r\nRead %d bits.\r\n", bitCount);
    bitCount = 0;
    for (uint8_t i=0; i<MAX_BITS; i++) {
        databits[i] = 0;

void DATA0_ISR() {
    //pc.printf("0 %db\r\n", bitCount); 
    flagDone = false;

void DATA1_ISR() {
    //pc.printf("1 %db\r\n", bitCount); 
    databits[bitCount] = 1;
    flagDone = false;

int main()
    pc.baud (115200);
    DATA0.fall(&DATA0_ISR); // assign ISRs 
    while (true) {
        if (bitCount > 0 && (!flagDone)) {
            wiegandTimer.attach_us(&parseWiegand, WIEGAND_WAIT_TIME);
            flagDone = true;
        else {
            ble.waitForEvent(); // let the library manage power and stuff. 

Additional Information:

OK, so I took out the BLE stuff and ported this to my FRDM-K64F and it works. I'm pretty sure there is a bug in the nrf51 interrupt library somewhere that's causing this.

I also tried to simply comment out the ble.waitForEvent(); and run again on the nRF incase that was the cause and it did NOT work. So... I'm lost. :( My C skillz are not good.

Question relating to:

printf in a callback is not ideal since these are blocking calls. What if you comment out all these pc.printf? Does it work?

posted by Sam Grove 04 Dec 2014

Nope. I tried that, but no luck. Thanks anyway for the suggestion!

posted by Mark Baseggio 04 Dec 2014

I think you should not make function call from within ISR routines, apart from commenting the printf you also need to comment out wiegandTimer.detach(); within the ISR , instead insert the code of the function within the ISR to avoid function jump

posted by Kanchan Debnath 04 Dec 2014

I did that too, and still no luck. As I said, I am nearly positive this is a bug in the nRF interrupt handling. Otherwise why would it work fine on the FRDM K64F and not on the nRF51?

I've been working on the K64F because it's working fine, obviously I removed *all* the BLE stuff, and just out of curiosity I compiled it for the nRF again, and it didn't work (of course I changed pins and everything specific to the board).

posted by Mark Baseggio 04 Dec 2014

If you're convinced of that I'd suggest writing a simple test case with instructions on how to run that is detached from your application. It'll be easier to track down root cause that way.

posted by Sam Grove 04 Dec 2014

Well here is the latest code from the FRDM board that works fine. I've also included a function to send Wiegand data called txWiegand. You'll see that I set up a quick and dirty test using one of the buttons on the FRDM and I've even included some random Wiegand data so you can test this.

Ideally you'd have one board to send the data using the txWiegand function and another board to receive it:

  • Hook up the DATA0_OUT_PIN output to the respective DATA0_PIN on the receiving board
  • Hook up the DATA1_OUT_PIN output to the respective DATA1_PIN on the receiving board
  • Send the sample data.
  • The FRDM processes the data correctly and outputs it to the serial terminal.
  • You'll see it doesn't work on the nRF but works fine on the FRDM boards.

Import programWiegand_Test

This code works on FRDM but not on nRF boards.

posted by Mark Baseggio 04 Dec 2014

Just as a sanity check, I recently ran this code on a completely different nrf51822 module and it didn't work.

It works FINE on FRDM series boards and I'm also about to test it on an Xpresso board. I wish I had the nrf knowledge and C skills to troubleshoot WHY the timers are broken but they certainly seem to be.

I hope someone with more knowledge about the nrf platform can take a look at this because I'd really like to use mbed for my project.

Thanks, I'll update you after I try the LPC Xpresso board with this code.

posted by Mark Baseggio 13 Dec 2014

Alright, so it's confirmed. The Wiegand_Test code works on:

  • LPC Xpresso 1549
  • FRDM K64F

So I'm 99% certain that there is an issue with the nrf Timer code. Why would it work on both other boards but not on two completely different nRF boards?

posted by Mark Baseggio 13 Dec 2014

Hi, perhaps we are suck on the same problem: https://developer.mbed.org/questions/3733/When-I-use-the-BLE-functionPWM-is-not-su/

posted by Rok Okorn 14 Dec 2014

1 Answer

5 years, 6 months ago.

sorry I posted an anwser by mistake not sure how to delete it...