summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBluebie <a@creativepony.com>2012-10-04 13:59:25 +1000
committerBluebie <a@creativepony.com>2012-10-04 13:59:25 +1000
commit66b662fc71061e874bef879820112b397f04e746 (patch)
tree77f1b9b44964e29064a75936e28126f36b6a6cd8
parent239ed251b8adbeff9225e1fbabf04a73ecd9f1a1 (diff)
downloadmicronucleus-66b662fc71061e874bef879820112b397f04e746.tar.gz
micronucleus-66b662fc71061e874bef879820112b397f04e746.tar.bz2
micronucleus-66b662fc71061e874bef879820112b397f04e746.zip
Added low power mode, for chips which need to start with clkdiv8 and only switch to 16.5mhz when usb connection is detected somehow.
-rw-r--r--firmware/bootloaderconfig.h16
-rw-r--r--firmware/main.c31
2 files changed, 44 insertions, 3 deletions
diff --git a/firmware/bootloaderconfig.h b/firmware/bootloaderconfig.h
index 9869b72..b443d6e 100644
--- a/firmware/bootloaderconfig.h
+++ b/firmware/bootloaderconfig.h
@@ -16,7 +16,6 @@
#define BOOTLOADER_ADDRESS 0
#endif
-
/*
General Description:
This file (together with some settings in Makefile) configures the boot loader
@@ -207,9 +206,22 @@ these macros are defined, the boot loader uses them.
#define AUTO_EXIT_MS 2500
//#define AUTO_EXIT_CONDITION() (idlePolls > (AUTO_EXIT_MS * 10UL))
+// uncomment for chips with clkdiv8 enabled in fuses
+//#define LOW_POWER_MODE 1
+// restore cpu speed calibration back to 8/16mhz instead of 8.25/16.5mhz
+//#define RESTORE_OSCCAL 1
+// set clock prescaler to a value before running user program
+//#define SET_CLOCK_PRESCALER _BV(CLKPS0) /* divide by 2 for 8mhz */
#define bootLoaderCondition() (idlePolls < (AUTO_EXIT_MS * 10UL))
-
+#if LOW_POWER_MODE
+ // only starts bootloader if USB D- is pulled high on startup - by putting your pullup in to an external connector
+ // you can avoid ever entering an out of spec clock speed or waiting on bootloader when that pullup isn't there
+ #define bootLoaderStartCondition() \
+ (PINB & (_BV(USB_CFG_DMINUS_BIT) | _BV(USB_CFG_DMINUS_BIT))) == _BV(USB_CFG_DMINUS_BIT)
+#else
+ #define bootLoaderStartCondition() 1
+#endif
/* ----------------------- Optional MCU Description ------------------------ */
diff --git a/firmware/main.c b/firmware/main.c
index 08ec1db..62097b8 100644
--- a/firmware/main.c
+++ b/firmware/main.c
@@ -375,12 +375,26 @@ static inline void leaveBootloader(void) {
int __attribute__((noreturn)) main(void) {
/* initialize */
+ #ifdef RESTORE_OSCCAL
+ uint8_t osccal_default = OSCCAL;
+ #endif
+ #if (!SET_CLOCK_PRESCALER) && LOW_POWER_MODE
+ uint8_t prescaler_default = CLKPR;
+ #endif
+
wdt_disable(); /* main app may have enabled watchdog */
tiny85FlashInit();
bootLoaderInit();
- if (bootLoaderCondition()) {
+ if (bootLoaderStartCondition()) {
+ #if LOW_POWER_MODE
+ // turn off clock prescalling - chip must run at full speed for usb
+ // if you might run chip at lower voltages, detect that in bootLoaderStartCondition
+ CLKPR = 1 << CLKPCE;
+ CLKPR = 0;
+ #endif
+
initForUsbConnectivity();
do {
usbPoll();
@@ -404,6 +418,21 @@ int __attribute__((noreturn)) main(void) {
} while(bootLoaderCondition()); /* main event loop runs so long as bootLoaderCondition remains truthy */
}
+ // set clock prescaler to desired clock speed (changing from clkdiv8, or no division, depending on fuses)
+ #if LOW_POWER_MODE
+ #ifdef SET_CLOCK_PRESCALER
+ CLKPR = 1 << CLKPCE;
+ CLKPR = SET_CLOCK_PRESCALER;
+ #else
+ CLKPR = 1 << CLKPCE;
+ CLKPR = prescaler_default;
+ #endif
+ #endif
+
+ // slowly bring down OSCCAL to it's original value before launching in to user program
+ #ifdef RESTORE_OSCCAL
+ while (OSCCAL > osccal_default) { OSCCAL -= 1; }
+ #endif
leaveBootloader();
}