From d8a8d529bc9f1366a40130b1668e287a3510a606 Mon Sep 17 00:00:00 2001 From: Mariano Alvira Date: Tue, 12 May 2009 17:19:57 -0400 Subject: [PATCH] Sleep works now. Make sure to turn the radio off first. --- Makefile | 2 +- include/isr.h | 2 + tests/sleep.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 147 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index f664bf956..93ad8d3f5 100644 --- a/Makefile +++ b/Makefile @@ -66,7 +66,7 @@ tests/nvm-write.obj: src/maca.o src/nvm.o tests/rftest-rx.obj: src/maca.o src/nvm.o tests/rftest-tx.obj: src/maca.o src/nvm.o tests/tmr-ints.obj: src/isr.o -tests/sleep.obj: src/isr.o +tests/sleep.obj: src/isr.o src/maca.o src/nvm.o NOTHUMB_CPPFLAGS := $(DBGFLAGS) $(OPTFLAGS) $(RELFLAGS) \ -D__KERNEL__ -DTEXT_BASE=$(TEXT_BASE) \ diff --git a/include/isr.h b/include/isr.h index 22e1772be..ec4049b89 100644 --- a/include/isr.h +++ b/include/isr.h @@ -5,9 +5,11 @@ #define INTBASE (0x80020000) #define INTENNUM_OFF (0x8) +#define INTDISNUM_OFF (0xc) #define INTSRC_OFF (0x30) #define INTENNUM INTBASE + INTENNUM_OFF +#define INTDISNUM INTBASE + INTDISNUM_OFF #define INTSRC INTBASE + INTSRC_OFF #define enable_tmr_irq() *(volatile uint32_t *)(INTENNUM) = 5; diff --git a/tests/sleep.c b/tests/sleep.c index d223ad50b..e7b61b965 100644 --- a/tests/sleep.c +++ b/tests/sleep.c @@ -1,6 +1,8 @@ #define GPIO_PAD_DIR0 0x80000000 #define GPIO_DATA0 0x80000008 +#define GPIO_FUNC_SEL0 0x80000018 /* GPIO 15 - 0; 2 bit blocks */ + #define GPIO_PAD_PU_EN0 0x80000010 #define GPIO_PAD_PU_EN1 0x80000014 #define ADC_CONTROL 0x80000018 @@ -11,17 +13,98 @@ #define CRM_STATUS 0x80003018 #define CRM_XTAL_CNTL 0x80000040 +#define BASE_UART1 0x80005000 +#define UART1_CON 0x80005000 +#define UART1_STAT 0x80005004 +#define UART1_DATA 0x80005008 +#define UR1CON 0x8000500c +#define UT1CON 0x80005010 +#define UART1_CTS 0x80005014 +#define UART1_BR 0x80005018 + #define DELAY 400000 #include "embedded_types.h" #include "isr.h" #include "utils.h" +#include "maca.h" + +void putc(uint8_t c); +void puts(uint8_t *s); +void put_hex(uint8_t x); +void put_hex16(uint16_t x); +void put_hex32(uint32_t x); + +const uint8_t hex[16]={'0','1','2','3','4','5','6','7', + '8','9','a','b','c','d','e','f'}; + + +typedef void (*pfCallback_t)(void); + +typedef struct +{ + uint8_t sleepType:1;// 0 hibernate / 1 doze + uint8_t ramRet:2; + uint8_t mcuRet:1; + uint8_t digPadRet:1; + pfCallback_t pfToDoBeforeSleep; +}crmSleepCtrl_t; + +void do_nothing(void) { + return; +} + +void (*crm_gotosleep)(crmSleepCtrl_t *foo) = 0x0000364d; __attribute__ ((section ("startup"))) void main(void) { + crmSleepCtrl_t crmSleepCtrl; + reg32(GPIO_PAD_DIR0) = 0x00000100; reg32(GPIO_DATA0) = 0x00000100; + + /* Restore UART regs. to default */ + /* in case there is still bootloader state leftover */ + + *(volatile uint32_t *)UART1_CON = 0x0000c800; /* mask interrupts, 16 bit sample --- helps explain the baud rate */ + + /* INC = 767; MOD = 9999 works: 115200 @ 24 MHz 16 bit sample */ + #define INC 767 + #define MOD 9999 + *(volatile uint32_t *)UART1_BR = INC<<16 | MOD; + + /* see Section 11.5.1.2 Alternate Modes */ + /* you must enable the peripheral first BEFORE setting the function in GPIO_FUNC_SEL */ + /* From the datasheet: "The peripheral function will control operation of the pad IF */ + /* THE PERIPHERAL IS ENABLED. */ + *(volatile uint32_t *)UART1_CON = 0x00000003; /* enable receive and transmit */ + *(volatile uint32_t *)GPIO_FUNC_SEL0 = ( (0x01 << (14*2)) | (0x01 << (15*2)) ); /* set GPIO15-14 to UART (UART1 TX and RX)*/ + + reg32(0x00401ffc) = 0x01234567; + reg32(0x00407ffc) = 0xdeadbeef; + reg32(0x0040fffc) = 0xface00ff; + reg32(0x00410000) = 0xabcd0123; + + puts("sleep test\n\r"); + puts("0x00401ffc: "); + put_hex32(reg32(0x00401ffc)); + puts("\r\n"); + puts("0x00407ffc: "); + put_hex32(reg32(0x00407ffc)); + puts("\r\n"); + puts("0x0040fffc: "); + put_hex32(reg32(0x0040fffc)); + puts("\r\n"); + puts("0x00410000: "); + put_hex32(reg32(0x00410000)); + puts("\r\n"); + + /* radio must be OFF before sleeping */ + /* otherwise MCU will not wake up properly */ + /* this is undocumented behavior */ + radio_off(); + /* disable all pullups */ /* seems to make a slight difference (2.0uA vs 1.95uA)*/ // reg32(GPIO_PAD_PU_EN0) = 0; @@ -33,23 +116,32 @@ __attribute__ ((section ("startup"))) void main(void) { /* go to sleep */ // reg32(CRM_WU_CNTL) = 0; /* don't wake up */ reg32(CRM_WU_CNTL) = 0x1; /* enable wakeup from wakeup timer */ - reg32(CRM_WU_TIMEOUT) = 1875000; /* wake 10 sec later if doze */ -// reg32(CRM_WU_TIMEOUT) = 20000; /* wake 10 sec later if hibernate w/2kHz*/ +// reg32(CRM_WU_TIMEOUT) = 1875000; /* wake 10 sec later if doze */ + reg32(CRM_WU_TIMEOUT) = 20000; /* wake 10 sec later if hibernate w/2kHz*/ // reg32(CRM_SLEEP_CNTL) = 1; /* hibernate, RAM page 0 only, don't retain state, don't power GPIO */ /* approx. 2.0uA */ // reg32(CRM_SLEEP_CNTL) = 0x41; /* hibernate, RAM page 0 only, retain state, don't power GPIO */ /* approx. 10.0uA */ // reg32(CRM_SLEEP_CNTL) = 0x51; /* hibernate, RAM page 0&1 only, retain state, don't power GPIO */ /* approx. 11.7uA */ // reg32(CRM_SLEEP_CNTL) = 0x61; /* hibernate, RAM page 0,1,2 only, retain state, don't power GPIO */ /* approx. 13.9uA */ // reg32(CRM_SLEEP_CNTL) = 0x71; /* hibernate, all RAM pages, retain state, don't power GPIO */ /* approx. 16.1uA - possibly with periodic refresh*/ -// reg32(CRM_SLEEP_CNTL) = 0xf1; /* hibernate, all RAM pages, retain state, power GPIO */ /* approx. 16.1uA - possibly with periodic refresh*/ + reg32(CRM_SLEEP_CNTL) = 0xf1; /* hibernate, all RAM pages, retain state, power GPIO */ /* approx. 16.1uA - possibly with periodic refresh*/ // reg32(CRM_SLEEP_CNTL) = 2; /* doze , RAM page 0 only, don't retain state, don't power GPIO */ /* approx. 69.2 uA */ - reg32(CRM_SLEEP_CNTL) = 0x42; /* doze , RAM page 0 only, retain state, don't power GPIO */ /* approx. 77.3uA */ +// reg32(CRM_SLEEP_CNTL) = 0x42; /* doze , RAM page 0 only, retain state, don't power GPIO */ /* approx. 77.3uA */ // reg32(CRM_SLEEP_CNTL) = 0x52; /* doze , RAM page 0&1 only, retain state, don't power GPIO */ /* approx. 78.9uA */ // reg32(CRM_SLEEP_CNTL) = 0x62; /* doze , RAM page 0,1,2 only, retain state, don't power GPIO */ /* approx. 81.2uA */ // reg32(CRM_SLEEP_CNTL) = 0x72; /* doze , all RAM pages, retain state, don't power GPIO */ /* approx. 83.4uA - possibly with periodic refresh*/ // reg32(CRM_SLEEP_CNTL) = 0xf2; /* doze , all RAM pages, retain state, power GPIO */ /* approx. 82.8uA - possibly with periodic refresh*/ + +/* crmSleepCtrl.sleepType = 0; */ +/* crmSleepCtrl.ramRet = 3; */ +/* crmSleepCtrl.mcuRet = 1; */ +/* crmSleepCtrl.digPadRet = 1; */ +/* crmSleepCtrl.pfToDoBeforeSleep = do_nothing; */ + +/* crm_gotosleep(&crmSleepCtrl); */ + /* wait for the sleep cycle to complete */ while((reg32(CRM_STATUS) & 0x1) == 0) { continue; } /* write 1 to sleep_sync --- this clears the bit (it's a r1wc bit) and powers down */ @@ -62,6 +154,21 @@ __attribute__ ((section ("startup"))) void main(void) { /* write 1 to sleep_sync --- this clears the bit (it's a r1wc bit) and finishes wakeup */ reg32(CRM_STATUS) = 1; + puts("\n\r\n\r\n\r"); + puts("0x00401ffc: "); + put_hex32(reg32(0x00401ffc)); + puts("\r\n"); + puts("0x00407ffc: "); + put_hex32(reg32(0x00407ffc)); + puts("\r\n"); + puts("0x0040fffc: "); + put_hex32(reg32(0x0040fffc)); + puts("\r\n"); + puts("0x00410000: "); + put_hex32(reg32(0x00410000)); + puts("\r\n"); + + volatile uint32_t i; while(1) { @@ -75,3 +182,36 @@ __attribute__ ((section ("startup"))) void main(void) { }; } + + + +void putc(uint8_t c) { + while(reg32(UT1CON)==31); /* wait for there to be room in the buffer */ + reg32(UART1_DATA) = c; +} + +void puts(uint8_t *s) { + while(s && *s!=0) { + putc(*s++); + } +} + +void put_hex(uint8_t x) +{ + putc(hex[x >> 4]); + putc(hex[x & 15]); +} + +void put_hex16(uint16_t x) +{ + put_hex((x >> 8) & 0xFF); + put_hex((x) & 0xFF); +} + +void put_hex32(uint32_t x) +{ + put_hex((x >> 24) & 0xFF); + put_hex((x >> 16) & 0xFF); + put_hex((x >> 8) & 0xFF); + put_hex((x) & 0xFF); +}