Custom firmware is being killed after 1-2 seconds [Solved]

Hi all,

I’m working on some custom firmware for the Spark Core. For non-technical reasons, I’m not interested in using the Spark firmware or wifi, just the bootloader and my own code.

I can download to the Spark using DFU just fine, and the application runs as expected for 1-2 seconds. After that, the spark stops running the firmware I just downloaded and either:

  1. flashes red rapidly, then blinks yellow like it’s in DFU mode
  2. turns white, flashes white rapidly, then deep blue like it’s looking for a wifi connection

I have videos of these two scenareos, if they would be helpful to see. The applicaton code just reads a digital pin and turns on some LEDs in a loop. Could this have to do with a watchdog timer somewhere I’m missing? or something with the bootloader?

Thanks!

If possible, would you mind sharing the code?

Here it is:

#include "stm32f10x.h"

int main() {
  // initialization
  int count = 0;
  int button_down = 0;

  GPIOB->CRL = 0x11111111; // set all port B pins to output push-pull
  GPIOB->CRH = 0x11111111;
  
  GPIOA->CRL = 0x44444444; // set all port A pins to floating input
  GPIOA->CRH = 0x44444444;
  
  for (;;) {
    
    // set D0-2 to match count
    GPIOB->ODR = (GPIOB->ODR & 0xFFFF0000) | (count << 5);
    
    // if A0 is pressed, increment count
    if (GPIOA->IDR & 1 & ~button_down) {
      button_down = 1; 
      if (count < 7) {
        count++;
      } else {
        count = 0;
      }
    } else if (~button_down) {
      button_down = 0;
    }
  }
}

Thanks, that should make it easier to debug. Since this goes a bit above my head, I’m going to ping the reinforcements: @Dave, @kennethlimcp, @peekay123, @bko. I’d be highly surprised if they won’t be able to help you out. Good luck!

1 Like

I’m guessing it’s the watchdog that is causing the issue :slight_smile:

Any advice on how to remedy this? The relevent TRM says the watchdog is disabled by default, so I’m assuming the bootloader does something with it before my code runs. Actually, I’m not 100% sure on how the bootloader works anyway. How does it run with my firmware in there?

Thanks for the attention and suggestions :slight_smile:

EDIT: Some discoveries.

This behavior is indeed being caused by the independent watchdog timer. Feeding the dog at the end of the loop with

IWDG->KR = 0xAAAA;

stops the resets from happening. The TRM doesn’t mention how to disable the watchdog from software, so I’m guessing it’s impossible (unless someone here knows otherwise!). I guess I’d like to know if there’s ANY way to disable the watchdog without breaking out a jtag programmer and messing with the bootloader. Otherwise, I’d be willing to do that as a last resort.

This thread has a lot of info:

Since @BDub is now at Spark, I am he knows what the code is doing.

Maybe the best approach is the change the prescaler and “kick the dog” in your code.

1 Like

Yup, that’s what I’m doing right now. AFAIK, there’s no way to avoid having to feed the dog unless I mess with the bootloader, but for the time being that’s out of the question. I’ll follow up on this if I ever decide to go down that road.

Looks like you figured this out already, but my advice would be to keep the watchdog active. It’s always a good idea to prevent your application from completely locking up due to a hard loop. I’m sure there is some edge case you could come up with that would be better off without a watchdog, so it pays to just think about it thoroughly.

My reasoning for wanting to disable the watchdog was non-technical. I think I’ve found out how to disable it by writing to a backup register that the bootloader reads. Haven’t tried this yet because it’s pretty low on the priority list right now. For now I’m leaving it on while I work on other things.

Right, certainly while you are debugging and creating your software it’s a good idea to disable it to ensure you have one less thing getting in your way when you write code that will trip over the watchdog.

Also once it’s enabled with writing 0xCCCC to the IWDG->KR register… AFAIK there’s no way to disable it.

Writing 0xA5A5 to backup register BKP_DR9 looks like it will prevent IWDG from being enabled, but it’s used to signal Standby Mode…

So what you should probably do as a work around to make sure BKP_DR9 stays set is just write 0xAAAA to BKP_DR9 like this:

BKP_WriteBackupRegister(BKP_DR9, 0xAAAA);

/* Optionally SW Reset System */
NVIC_SystemReset();

Interesting, I’ll give it a shot next time I work on this.

My reason for wanting to disable the watchdog timer is that I’m working on course material for a university microcontroller programming class. We don’t want to introduce the watchdog until later in the semester.