Ejemplo n.º 1
0
int main() {
  systemReset(); // peripherals but not PC
  setupCLK();
  setupLED();
  setupUSB();
  setupBUTTON();
  setupFLASH();

  strobePin(LED_BANK,LED,STARTUP_BLINKS,BLINK_FAST);

  /* wait for host to upload program or halt bootloader */
  bool no_user_jump = !checkUserCode(USER_CODE_FLASH) && !checkUserCode(USER_CODE_RAM) || readPin(BUTTON_BANK,BUTTON);
  int delay_count = 0;

  while ((delay_count++ < BOOTLOADER_WAIT) 
	 || no_user_jump) {

    strobePin(LED_BANK,LED,1,BLINK_SLOW);

    if (dfuUploadStarted()) {
      dfuFinishUpload(); // systemHardReset from DFU once done
    }
  }
  
  if (checkUserCode(USER_CODE_RAM)) {
    jumpToUser(USER_CODE_RAM);
  } else if (checkUserCode(USER_CODE_FLASH)) {
    jumpToUser(USER_CODE_FLASH);
  } else {
    // some sort of fault occurred, hard reset
    strobePin(LED_BANK,LED,5,BLINK_FAST);
    systemHardReset();
  }
  
}
Ejemplo n.º 2
0
int main() 
{
    systemReset(); // peripherals but not PC
    setupCLK();
    setupLEDAndButton();
    setupUSB();
    setupFLASH();
	
//	strobePin(LED_BANK, LED_PIN, 9999, BLINK_SLOW,LED_ON_STATE);
	
	strobePin(LED_BANK, LED_PIN, STARTUP_BLINKS, BLINK_FAST,LED_ON_STATE);


	/* wait for host to upload program or halt bootloader */
	bool no_user_jump = (!checkUserCode(USER_CODE_FLASH0X8005000) && !checkUserCode(USER_CODE_FLASH0X8002000)) || readButtonState() ;
	
	int delay_count = 0;

    while ((delay_count++ < BOOTLOADER_WAIT) || no_user_jump)
	{

        strobePin(LED_BANK, LED_PIN, 1, BLINK_SLOW,LED_ON_STATE);

        if (dfuUploadStarted()) 
		{
            dfuFinishUpload(); // systemHardReset from DFU once done
        }
    }


	if (checkUserCode(USER_CODE_FLASH0X8002000)) 
	{
		jumpToUser(USER_CODE_FLASH0X8002000);
	} 
	else 
	{
		if (checkUserCode(USER_CODE_FLASH0X8005000))
		{
			jumpToUser(USER_CODE_FLASH0X8005000);
		} 
		else
		{
			// Nothing to execute in either Flash or RAM
			strobePin(LED_BANK, LED_PIN, 5, BLINK_FAST,LED_ON_STATE);
			systemHardReset();
		}
	}

	return 0;// Added to please the compiler
}
int main() 
{
    systemReset(); // peripherals but not PC
    setupCLK();
    setupLED();
    setupUSB();
    setupBUTTON();
    setupFLASH();

    strobePin(LED_BANK, LED, STARTUP_BLINKS, BLINK_FAST);

	/* wait for host to upload program or halt bootloader */
	bool no_user_jump = (!checkUserCode(USER_CODE_RAM) && !checkUserCode(USER_CODE_FLASH0X8005000) && !checkUserCode(USER_CODE_FLASH0X8002000)) || readPin(BUTTON_BANK,BUTTON);
	int delay_count = 0;

    while ((delay_count++ < BOOTLOADER_WAIT) || no_user_jump)
	{

        strobePin(LED_BANK, LED, 1, BLINK_SLOW);

        if (dfuUploadStarted()) 
		{
            dfuFinishUpload(); // systemHardReset from DFU once done
        }
    }

	if (checkUserCode(USER_CODE_RAM)) 
	{
		jumpToUser(USER_CODE_RAM);
	} 
	
	else if (checkUserCodeRam(USER_CODE_FLASH0X8002000+4))
	{
		int ptr;
		/*
		u32 *flashAdr = (u32 *)USER_CODE_FLASH0X8002000;
		u32 *ramAdr = (u32 *)USER_CODE_RAM;
		for (ptr = 0; ptr < ((RAM_END-USER_CODE_RAM)-1024)/4; ptr ++) {
			ramAdr[ptr] = flashAdr[ptr];
        }
		*/
		u32 const *flashAdr = (u32 const *)USER_CODE_FLASH0X8002000;
		u32 *ramAdr = (u32 *)USER_CODE_RAM;
		ptr = ((RAM_END-USER_CODE_RAM)-1024)>>2;
		while (ptr--)
		{
			*ramAdr++ = *flashAdr++;
		}
		jumpToUser(USER_CODE_RAM);
	}
Ejemplo n.º 4
0
int main() {
	systemReset(); // peripherals but not PC
	boardInit();
	strobePin(LED_BANK,LED,STARTUP_BLINKS,BLINK_FAST);
	pRCC->APB1ENR |= 0x00800000;
	usbAppInit();
	setupFLASH();
	

		
#ifdef CONFIG_EXTRA_MAIN_CODE
	CONFIG_EXTRA_MAIN_CODE
#endif

/* wait for host to upload program or halt bootloader */
		while (bootloaderCondition) {
			strobePin(LED_BANK,LED,1,BLINK_SLOW);
			if (dfuUploadStarted()) {
				dfuFinishUpload(); // systemHardReset from DFU once done
			}
#ifdef bootloaderExitCondition
			if (bootloaderExitCondition)
				break;
#endif
		}

	if (checkUserCode(USER_CODE_RAM)) {
		jumpToUser(USER_CODE_RAM);
	} else if (checkUserCode(USER_CODE_FLASH)) {
		jumpToUser(USER_CODE_FLASH);
	} else {
		// some sort of fault occurred, hard reset
		strobePin(LED_BANK,LED,5,BLINK_FAST);
		systemHardReset();
	}
	return 0;
}
Ejemplo n.º 5
0
bool dfuUpdateByRequest(void) {
  /* were using the global pInformation struct from usb_lib here,
     see comment in maple_dfu.h around DFUEvent struct */
  dfuBusy = TRUE;

  u8 startState = dfuAppStatus.bState;
  dfuAppStatus.bStatus = OK;
  /* often leaner to nest if's then embed a switch/case */
  if (startState == dfuIDLE)  {
    /*  device running inside DFU mode */
    dfuBusy = TRUE; // signals the main loop to defer to the dfu write-loop

    if (pInformation->USBbRequest == DFU_DNLOAD) {

      if (pInformation->USBwLengths.w > 0) {
        userFirmwareLen = 0;
        dfuAppStatus.bState  = dfuDNLOAD_SYNC;

        if (pInformation->Current_AlternateSetting == 1) {
          userAppAddr = USER_CODE_FLASH;
          userFlash = TRUE;

          /* make sure the flash is setup properly, unlock it */
          setupFLASH();
          flashUnlock();

        } else {
          userAppAddr = USER_CODE_RAM;
          userFlash = FALSE;
        }
      } else {
        dfuAppStatus.bState  = dfuERROR;
        dfuAppStatus.bStatus = errNOTDONE;
      }
    } else if (pInformation->USBbRequest == DFU_UPLOAD) {
      dfuAppStatus.bState  = dfuUPLOAD_IDLE;
    } else if (pInformation->USBbRequest == DFU_ABORT) {
      dfuAppStatus.bState  = dfuIDLE;
      dfuAppStatus.bStatus = OK;  /* are we really ok? we were just aborted */
    } else if (pInformation->USBbRequest == DFU_GETSTATUS) {
      dfuAppStatus.bState  = dfuIDLE;
    } else if (pInformation->USBbRequest == DFU_GETSTATE) {
      dfuAppStatus.bState  = dfuIDLE;
    } else {
      dfuAppStatus.bState  = dfuERROR;
      dfuAppStatus.bStatus = errSTALLEDPKT;
    }

  } else if (startState == dfuDNLOAD_SYNC)         {
    /* device received block, waiting for DFU_GETSTATUS request */

    if (pInformation->USBbRequest == DFU_GETSTATUS) {
      /* todo, add routine to wait for last block write to finish */
      if (userFlash) {
        if (code_copy_lock==WAIT) {
          code_copy_lock=BEGINNING;
          dfuAppStatus.bwPollTimeout0 = 0xFF; /* is this enough? */
          dfuAppStatus.bwPollTimeout1 = 0x01; /* is this enough? */
          dfuAppStatus.bState=dfuDNBUSY;

        } else if (code_copy_lock==BEGINNING) {
          dfuAppStatus.bState=dfuDNLOAD_SYNC;

        } else if (code_copy_lock==MIDDLE) {
          dfuAppStatus.bState=dfuDNLOAD_SYNC;

        } else if (code_copy_lock==END) {
          dfuAppStatus.bwPollTimeout0 = 0x00;
          code_copy_lock=WAIT;
          dfuAppStatus.bState=dfuDNLOAD_IDLE;
        }

      } else {
        dfuAppStatus.bState = dfuDNLOAD_IDLE;
        dfuCopyBufferToExec();
      }

    } else if (pInformation->USBbRequest == DFU_GETSTATE) {
      dfuAppStatus.bState  = dfuDNLOAD_SYNC;
    } else {
      dfuAppStatus.bState  = dfuERROR;
      dfuAppStatus.bStatus = errSTALLEDPKT;
    }

  } else if (startState == dfuDNBUSY)              {
    /* if were actually done writing, goto sync, else stay busy */
    if (code_copy_lock == END) {
      dfuAppStatus.bwPollTimeout0 = 0x00;
      code_copy_lock=WAIT;
      dfuAppStatus.bState = dfuDNLOAD_IDLE;
    } else {
      dfuAppStatus.bState= dfuDNBUSY;
    }

  } else if (startState == dfuDNLOAD_IDLE)         {
    /* device is expecting dfu_dnload requests */
    if (pInformation->USBbRequest == DFU_DNLOAD) {
      if (pInformation->USBwLengths.w > 0) {
        dfuAppStatus.bState  = dfuDNLOAD_SYNC;
      } else {
        /* todo, support "disagreement" if device expects more data than this */
        dfuAppStatus.bState  = dfuMANIFEST_SYNC;

        /* relock the flash */
        flashLock();
      }
    } else if (pInformation->USBbRequest == DFU_ABORT) {
      dfuAppStatus.bState  = dfuIDLE;
    } else if (pInformation->USBbRequest == DFU_GETSTATUS) {
      dfuAppStatus.bState  = dfuIDLE;
    } else if (pInformation->USBbRequest == DFU_GETSTATE) {
      dfuAppStatus.bState  = dfuIDLE;
    } else {
      dfuAppStatus.bState  = dfuERROR;
      dfuAppStatus.bStatus = errSTALLEDPKT;
    }

  } else if (startState == dfuMANIFEST_SYNC)       {
    /* device has received last block, waiting DFU_GETSTATUS request */

    if (pInformation->USBbRequest == DFU_GETSTATUS) {
      dfuAppStatus.bState  = dfuMANIFEST_WAIT_RESET;
      dfuAppStatus.bStatus = OK;
    } else if (pInformation->USBbRequest == DFU_GETSTATE) {
      dfuAppStatus.bState  = dfuMANIFEST_SYNC;
    } else {
      dfuAppStatus.bState  = dfuERROR;
      dfuAppStatus.bStatus = errSTALLEDPKT;
    }

  } else if (startState == dfuMANIFEST)            {
    /* device is in manifestation phase */

    /* should never receive request while in manifest! */
    dfuAppStatus.bState  = dfuMANIFEST_WAIT_RESET;
    dfuAppStatus.bStatus = OK;

  } else if (startState == dfuMANIFEST_WAIT_RESET) {
    /* device has programmed new firmware but needs external
       usb reset or power on reset to run the new code */

    /* consider timing out and self-resetting */
    dfuAppStatus.bState  = dfuMANIFEST_WAIT_RESET;

  } else if (startState == dfuUPLOAD_IDLE)         {
    /* device expecting further dfu_upload requests */

    if (pInformation->USBbRequest == DFU_UPLOAD) {
      /* todo, add routine to wait for last block write to finish */
      dfuAppStatus.bState  = dfuERROR;
      dfuAppStatus.bStatus = errSTALLEDPKT;
    } else if (pInformation->USBbRequest == DFU_ABORT) {
      dfuAppStatus.bState  = dfuIDLE;
    } else if (pInformation->USBbRequest == DFU_GETSTATUS) {
      dfuAppStatus.bState  = dfuUPLOAD_IDLE;
    } else if (pInformation->USBbRequest == DFU_GETSTATE) {
      dfuAppStatus.bState  = dfuUPLOAD_IDLE;
    } else {
      dfuAppStatus.bState  = dfuERROR;
      dfuAppStatus.bStatus = errSTALLEDPKT;
    }


  } else if (startState == dfuERROR)               {
    /* status is in error, awaiting DFU_CLRSTATUS request */

    if (pInformation->USBbRequest == DFU_GETSTATUS) {
      /* todo, add routine to wait for last block write to finish */
      dfuAppStatus.bState  = dfuERROR;
    } else if (pInformation->USBbRequest == DFU_GETSTATE) {
      dfuAppStatus.bState  = dfuERROR;
    } else if (pInformation->USBbRequest == DFU_CLRSTATUS) {
      /* todo handle any cleanup we need here */
      dfuAppStatus.bState  = dfuIDLE;
      dfuAppStatus.bStatus = OK;
    } else {
      dfuAppStatus.bState  = dfuERROR;
      dfuAppStatus.bStatus = errSTALLEDPKT;
    }

  } else {
    /* some kind of error... */
    dfuAppStatus.bState  = dfuERROR;
    dfuAppStatus.bStatus = errSTALLEDPKT;
  }

  if (dfuAppStatus.bStatus == OK) {
    return TRUE;
  } else {
    return FALSE;
  }
}
Ejemplo n.º 6
0
bool dfuUpdateByRequest(void) {
    /* were using the global pInformation struct from usb_lib here,
       see comment in maple_dfu.h around DFUEvent struct */
    dfuBusy = TRUE;

    u8 startState = dfuAppStatus.bState;
    dfuAppStatus.bStatus = OK;
    /* often leaner to nest if's then embed a switch/case */
    if (startState == dfuIDLE)  {
        /*  device running inside DFU mode */
        dfuBusy = TRUE; // signals the main loop to defer to the dfu write-loop

        if (pInformation->USBbRequest == DFU_DNLOAD) {

            if (pInformation->USBwLengths.w > 0) {
                userFirmwareLen = 0;
                dfuAppStatus.bState  = dfuDNLOAD_SYNC;

                if (pInformation->Current_AlternateSetting == 1) {
                    userAppAddr = USER_CODE_FLASH;
                    userFlash = TRUE;

                    /* make sure the flash is setup properly, unlock it */
                    setupFLASH();
                    flashUnlock();

                } else {
                    userAppAddr = USER_CODE_RAM;
                    userFlash = FALSE;
                }
            } else {
                dfuAppStatus.bState  = dfuERROR;
                dfuAppStatus.bStatus = errNOTDONE;
            }
        } else if (pInformation->USBbRequest == DFU_UPLOAD) {
            dfuAppStatus.bState  = dfuUPLOAD_IDLE;
            /* record length of first block for calculating target
               address from wValue in consecutive blocks */
            uploadBlockLen = pInformation->USBwLengths.w;
            thisBlockLen = uploadBlockLen; /* for this first block as well */
            /* calculate where the data should be copied from */
            userFirmwareLen = uploadBlockLen * pInformation->USBwValue;
            if (pInformation->Current_AlternateSetting == 1) {
                userAppAddr = USER_CODE_FLASH;
                userAppEnd = FLASH_END;
            } else {
                userAppAddr = USER_CODE_RAM;
                userAppEnd = RAM_END;
            }
        } else if (pInformation->USBbRequest == DFU_ABORT) {
            dfuAppStatus.bState  = dfuIDLE;
            dfuAppStatus.bStatus = OK;  /* are we really ok? we were just aborted */
        } else if (pInformation->USBbRequest == DFU_GETSTATUS) {
            dfuAppStatus.bState  = dfuIDLE;
        } else if (pInformation->USBbRequest == DFU_GETSTATE) {
            dfuAppStatus.bState  = dfuIDLE;
        } else {
            dfuAppStatus.bState  = dfuERROR;
            dfuAppStatus.bStatus = errSTALLEDPKT;
        }

    } else if (startState == dfuDNLOAD_SYNC)         {
        /* device received block, waiting for DFU_GETSTATUS request */

        if (pInformation->USBbRequest == DFU_GETSTATUS) {
            /* todo, add routine to wait for last block write to finish */
            if (userFlash) {
                if (code_copy_lock == WAIT) {
                    code_copy_lock = BEGINNING;
                    dfuAppStatus.bwPollTimeout0 = 0x20; /* 32 ms */
                    dfuAppStatus.bwPollTimeout1 = 0x00;
                    dfuAppStatus.bState = dfuDNBUSY;

                } else if (code_copy_lock == BEGINNING) {
                    dfuAppStatus.bState = dfuDNLOAD_SYNC;

                } else if (code_copy_lock == MIDDLE) {
                    dfuAppStatus.bState = dfuDNLOAD_SYNC;

                } else if (code_copy_lock == END) {
                    dfuAppStatus.bwPollTimeout0 = 0x00;
                    code_copy_lock = WAIT;
                    dfuAppStatus.bState = dfuDNLOAD_IDLE;
                }

            } else {
                dfuAppStatus.bState = dfuDNLOAD_IDLE;
                dfuCopyBufferToExec();
            }

        } else if (pInformation->USBbRequest == DFU_GETSTATE) {
            dfuAppStatus.bState  = dfuDNLOAD_SYNC;
        } else {
            dfuAppStatus.bState  = dfuERROR;
            dfuAppStatus.bStatus = errSTALLEDPKT;
        }

    } else if (startState == dfuDNBUSY)              {
        /* if were actually done writing, goto sync, else stay busy */
        if (code_copy_lock == END) {
            dfuAppStatus.bwPollTimeout0 = 0x00;
            code_copy_lock = WAIT;
            dfuAppStatus.bState = dfuDNLOAD_IDLE;
        } else {
            dfuAppStatus.bState = dfuDNBUSY;
        }

    } else if (startState == dfuDNLOAD_IDLE)         {
        /* device is expecting dfu_dnload requests */
        if (pInformation->USBbRequest == DFU_DNLOAD) {
            if (pInformation->USBwLengths.w > 0) {
                dfuAppStatus.bState  = dfuDNLOAD_SYNC;
            } else {
                /* todo, support "disagreement" if device expects more data than this */
                dfuAppStatus.bState  = dfuMANIFEST_SYNC;

                /* relock the flash */
                flashLock();
            }
        } else if (pInformation->USBbRequest == DFU_ABORT) {
            dfuAppStatus.bState  = dfuIDLE;
        } else if (pInformation->USBbRequest == DFU_GETSTATUS) {
            dfuAppStatus.bState  = dfuIDLE;
        } else if (pInformation->USBbRequest == DFU_GETSTATE) {
            dfuAppStatus.bState  = dfuIDLE;
        } else {
            dfuAppStatus.bState  = dfuERROR;
            dfuAppStatus.bStatus = errSTALLEDPKT;
        }

    } else if (startState == dfuMANIFEST_SYNC)       {
        /* device has received last block, waiting DFU_GETSTATUS request */

        if (pInformation->USBbRequest == DFU_GETSTATUS) {
            dfuAppStatus.bState  = dfuMANIFEST_WAIT_RESET;
            dfuAppStatus.bStatus = OK;
        } else if (pInformation->USBbRequest == DFU_GETSTATE) {
            dfuAppStatus.bState  = dfuMANIFEST_SYNC;
        } else {
            dfuAppStatus.bState  = dfuERROR;
            dfuAppStatus.bStatus = errSTALLEDPKT;
        }

    } else if (startState == dfuMANIFEST)            {
        /* device is in manifestation phase */

        /* should never receive request while in manifest! */
        dfuAppStatus.bState  = dfuMANIFEST_WAIT_RESET;
        dfuAppStatus.bStatus = OK;

    } else if (startState == dfuMANIFEST_WAIT_RESET) {
        /* device has programmed new firmware but needs external
           usb reset or power on reset to run the new code */

        /* consider timing out and self-resetting */
        dfuAppStatus.bState  = dfuMANIFEST_WAIT_RESET;

    } else if (startState == dfuUPLOAD_IDLE)         {
        /* device expecting further dfu_upload requests */

        if (pInformation->USBbRequest == DFU_UPLOAD) {
            if (pInformation->USBwLengths.w > 0) {
                /* check that this is not the last possible block */
                userFirmwareLen = uploadBlockLen * pInformation->USBwValue;
                if (userAppAddr + userFirmwareLen + uploadBlockLen <= userAppEnd) {
                    thisBlockLen = uploadBlockLen;
                    dfuAppStatus.bState  = dfuUPLOAD_IDLE;
                } else {
                    /* if above comparison was just equal, thisBlockLen becomes zero
                    next time when USBWValue has been increased by one */
                    thisBlockLen = userAppEnd - userAppAddr - userFirmwareLen;
                    /* check for overflow due to USBwValue out of range */
                    if (thisBlockLen >= pInformation->USBwLengths.w) {
                        thisBlockLen = 0;
                    }
                    dfuAppStatus.bState  = dfuIDLE;
                }
            } else {
                dfuAppStatus.bState  = dfuERROR;
                dfuAppStatus.bStatus = errNOTDONE;
            }
        } else if (pInformation->USBbRequest == DFU_ABORT) {
            dfuAppStatus.bState  = dfuIDLE;
        } else if (pInformation->USBbRequest == DFU_GETSTATUS) {
            dfuAppStatus.bState  = dfuUPLOAD_IDLE;
        } else if (pInformation->USBbRequest == DFU_GETSTATE) {
            dfuAppStatus.bState  = dfuUPLOAD_IDLE;
        } else {
            dfuAppStatus.bState  = dfuERROR;
            dfuAppStatus.bStatus = errSTALLEDPKT;
        }


    } else if (startState == dfuERROR)               {
        /* status is in error, awaiting DFU_CLRSTATUS request */

        if (pInformation->USBbRequest == DFU_GETSTATUS) {
            /* todo, add routine to wait for last block write to finish */
            dfuAppStatus.bState  = dfuERROR;
        } else if (pInformation->USBbRequest == DFU_GETSTATE) {
            dfuAppStatus.bState  = dfuERROR;
        } else if (pInformation->USBbRequest == DFU_CLRSTATUS) {
            /* todo handle any cleanup we need here */
            dfuAppStatus.bState  = dfuIDLE;
            dfuAppStatus.bStatus = OK;
        } else {
            dfuAppStatus.bState  = dfuERROR;
            dfuAppStatus.bStatus = errSTALLEDPKT;
        }

    } else {
        /* some kind of error... */
        dfuAppStatus.bState  = dfuERROR;
        dfuAppStatus.bStatus = errSTALLEDPKT;
    }

    if (dfuAppStatus.bStatus == OK) {
        return TRUE;
    } else {
        return FALSE;
    }
}
Ejemplo n.º 7
0
int main() {
  systemReset(); // peripherals but not PC
  setupCLK();
  setupLED();
  setupBUTTON();

#ifdef STM32F2
	setupDisconnectPin();
	disconnectUSB();
#else
  setupUSB();
  setupFLASH();
#endif


  strobePin(LED_BANK,LED,STARTUP_BLINKS,BLINK_FAST);

#ifdef STM32F2
  // enter built in boot load if magic number found in RAM
	if(*START_BOOT_LOADER_MAGIC_ADDR == START_BOOT_LOADER_MAGIC) {
 	  connectUSB();
		*START_BOOT_LOADER_MAGIC_ADDR = 0;
    jumpToUser(BUILT_IN_BOOT_LOADER);
	}
#endif



#ifdef FASTSTART
  // for an unknown reason the loader process hangs if the button port is not read
	bool pinState = readPin(BUTTON_BANK, BUTTON);
#else

	bool buttonStatusHigh = TRUE;
	bool buttonStatusLow  = FALSE;
	for(int i=0; i<10; i++) {
		bool pinState = readPin(BUTTON_BANK, BUTTON);
		buttonStatusHigh = buttonStatusHigh && pinState;
		buttonStatusLow  = buttonStatusLow || pinState;
	}

  /* wait for host to upload program or halt bootloader */
  bool no_user_jump = (!checkUserCode(USER_CODE_FLASH) && !checkUserCode(USER_CODE_RAM))
        								|| buttonStatusHigh;
  int delay_count = 0;


  while ((delay_count++ < BOOTLOADER_WAIT) || no_user_jump) {
    strobePin(LED_BANK,LED,1,BLINK_SLOW);

  #ifndef STM32F2
    if (dfuUploadStarted()) {
      dfuFinishUpload(); // systemHardReset from DFU once done
    }
  #endif
  }
#endif

	if (checkUserCode(USER_CODE_RAM)) {
    jumpToUser(USER_CODE_RAM);
  } else if (checkUserCode(USER_CODE_FLASH)) {
    jumpToUser(USER_CODE_FLASH);
  } else {
    // some sort of fault occurred, hard reset
    strobePin(LED_BANK,LED,5,BLINK_FAST);
    systemHardReset();
  }

  return 0;               /* can't happen, but placate the compiler */
}