Go Down

Topic: How to set I/O pins as low outputs in bootloader? (Read 697 times) previous topic - next topic



I have a Zero-based product that drives relays.  My software is open-source, and my customers are able to modify my software and upload their sketches.  Unfortunately, sometimes they screw up and their software doesn't run correctly or puts the Zero in a weird state.

With I/O as floating inputs, the relays may end up being on - which can be dangerous.  I'd like to make sure the relays are off in the bootloader as a safety measure.  This means making them outputs and setting them low.  It isn't obvious how to do this.  I've downloaded the Zero bootloader sources and can compile and upload to the board. I just need to know which file to modify, and what the modification should be.

I know a pull-down resistor on the output would work too - but that isn't an option.

Thanks!  :)



One way to do what you need is to create your own custom variant and change the initVariant() function.


To answer my own question  :)

I added some code to the bootloader to turn off the relays as soon as possible.  The bootloader executes for just over 1/2 second, so this definitely helps.  This is the first thing that's called in main().

Code: [Select]

#define SETBIT08        0x00000100
#define SETBIT09        0x00000200
#define SETBIT11        0x00000800
#define SETBIT15        0x00008000
#define SETBIT17        0x00020000
#define SETBIT30        0x40000000

#define CLEARBIT08      0xFFFFFEFF
#define CLEARBIT09      0xFFFFFDFF
#define CLEARBIT11      0xFFFFF7FF
#define CLEARBIT15      0xFFFF7FFF
#define CLEARBIT17      0xFFFDFFFF
#define CLEARBIT30      0xBFFFFFFF

// Initialize the registers controlling the outputs, and turn them off
void initOutputs() {
  volatile uint32_t *portAOut, *portAMode, *portBOut, *portBMode;
  // Get pointer to the registers
  portAOut   = (uint32_t *) 0x41004410; //portOutputRegister(digitalPinToPort(5));
  portAMode  = (uint32_t *) 0x41004400; //portModeRegister(digitalPinToPort(5));
  portBOut   = (uint32_t *) 0x41004490; //portOutputRegister(digitalPinToPort(A2));
  portBMode  = (uint32_t *) 0x41004480; //portModeRegister(digitalPinToPort(A2));

  // Set all I/O modes to outputs
  *portAMode |= SETBIT15;
  *portBMode |= (SETBIT08 + SETBIT09 + SETBIT11 + SETBIT17 + SETBIT30);

  // Set all outputs low (turn off relays)
  *portAOut &= CLEARBIT15;
  *portBOut &= CLEARBIT30;
  *portBOut &= CLEARBIT17;
  *portBOut &= CLEARBIT09;
  *portBOut &= CLEARBIT08;
  *portBOut &= CLEARBIT11;

This keeps the outputs low while in the bootloader, but they start floating (become inputs) as soon as the reset handler for the sketch starts executing.  So this helps, but isn't the result I was hoping for.

To AloyseTech's point, I could (should) create a new variety and set the outputs low in initVariant() too but my users aren't too tech savvy.  I don't want to make everyone jump through another hoop when in reality it is a very rare occurrence that a user screws up.

Hope this helps someone!

Go Up