From ad55ccdec41c00aa31fc8563c409eb8a492d243a Mon Sep 17 00:00:00 2001 From: Mariano Alvira Date: Sun, 3 Feb 2013 14:48:38 -0500 Subject: [PATCH] add working routines to turn the mc1322x radio on and off --- cpu/mc1322x/contiki-maca.c | 2 +- cpu/mc1322x/lib/include/maca.h | 4 ++ cpu/mc1322x/lib/maca.c | 72 +++++++++++++++++++++++++++++----- 3 files changed, 68 insertions(+), 10 deletions(-) diff --git a/cpu/mc1322x/contiki-maca.c b/cpu/mc1322x/contiki-maca.c index 6fc554819..04de71608 100644 --- a/cpu/mc1322x/contiki-maca.c +++ b/cpu/mc1322x/contiki-maca.c @@ -265,7 +265,7 @@ int contiki_maca_transmit(unsigned short transmit_len) { #if BLOCKING_TX /* block until tx_complete, set by contiki_maca_tx_callback */ - while(!tx_complete && (tx_head != 0)); + while((maca_pwr == 1) && !tx_complete && (tx_head != 0)) { continue; } #endif } diff --git a/cpu/mc1322x/lib/include/maca.h b/cpu/mc1322x/lib/include/maca.h index d9bb283b8..4c67bf051 100644 --- a/cpu/mc1322x/lib/include/maca.h +++ b/cpu/mc1322x/lib/include/maca.h @@ -89,6 +89,10 @@ void ResumeMACASync(void); void radio_init(void); uint32_t init_from_flash(uint32_t addr); +/* maca_pwr indicates whether the radio is on or off */ +/* Test it before accessing any radio function or the CPU may hang */ +extern volatile uint8_t maca_pwr; + #define MAX_PACKET_SIZE (MAX_PAYLOAD_SIZE + 2) /* packet includes 2 bytes of checksum */ /* maca register and field defines */ diff --git a/cpu/mc1322x/lib/maca.c b/cpu/mc1322x/lib/maca.c index 744200b09..c39b27ccb 100644 --- a/cpu/mc1322x/lib/maca.c +++ b/cpu/mc1322x/lib/maca.c @@ -110,6 +110,10 @@ enum posts { }; static volatile uint8_t last_post = NO_POST; +/* maca_pwr indicates whether the radio is on or off */ +/* Test it before accessing any radio function or the CPU may hang */ +volatile uint8_t maca_pwr = 0; + volatile uint8_t fcs_mode = USE_FCS; volatile uint8_t prm_mode = PROMISC; @@ -182,6 +186,7 @@ void maca_init(void) { radio_init(); flyback_init(); init_phy(); + maca_pwr = 1; set_channel(0); /* things get weird if you never set a channel */ set_power(0); /* set the power too --- who knows what happens if you don't */ free_head = 0; tx_head = 0; rx_head = 0; rx_end = 0; tx_end = 0; dma_tx = 0; dma_rx = 0; @@ -879,21 +884,70 @@ const uint32_t addr_reg_rep[MAX_DATA] = { 0x80004118,0x80009204,0x80009208,0x800 const uint32_t data_reg_rep[MAX_DATA] = { 0x00180012,0x00000605,0x00000504,0x00001111,0x0fc40000,0x20046000,0x4005580c,0x40075801,0x4005d801,0x5a45d800,0x4a45d800,0x40044000,0x00106000,0x00083806,0x00093807,0x0009b804,0x000db800,0x00093802,0x00000015,0x00000002,0x0000000f,0x0000aaa0,0x01002020,0x016800fe,0x8e578248,0x000000dd,0x00000946,0x0000035a,0x00100010,0x00000515,0x00397feb,0x00180358,0x00000455,0x00000001,0x00020003,0x00040014,0x00240034,0x00440144,0x02440344,0x04440544,0x0ee7fc00,0x00000082,0x0000002a }; void maca_off(void) { + /* Do nothing if already off */ + if (maca_pwr == 0) return; + + /* wait here till complete and then go off */ + while (last_post == TX_POST) { + return; + } + disable_irq(MACA); - /* turn off the radio regulators */ - reg(0x80003048) = 0x00000f00; - /* hold the maca in reset */ - maca_reset = maca_reset_rst; + maca_pwr = 0; + + /* Disable clocks, cancel possible delayed RX post */ + /* Note mcu will hang if radio is off when a startclk post comes through */ + *MACA_TMRDIS = (1 << maca_tmren_sft) | ( 1<< maca_tmren_cpl) | ( 1 << maca_tmren_strt); + + /* Turn off the radio regulators */ + CRM->VREG_CNTLbits.VREG_1P8V_EN = 0; + CRM->VREG_CNTLbits.VREG_1P5V_EN = 0; + + /* Hold the maca in reset */ + maca_reset = maca_reset_rst; } void maca_on(void) { - /* turn the radio regulators back on */ - reg(0x80003048) = 0x00000f78; - /* reinitialize the phy */ - reset_maca(); - init_phy(); + + if (maca_pwr != 0) { + return; + } + maca_pwr = 1; + + /* Turn the radio regulators back on */ + CRM->VREG_CNTLbits.VREG_1P8V_EN = 1; + CRM->VREG_CNTLbits.VREG_1P5V_EN = 3; + while(CRM->STATUSbits.VREG_1P8V_RDY == 0) { continue; } + while(CRM->STATUSbits.VREG_1P5V_RDY == 0) { continue; } + /* Take out of reset */ + *MACA_RESET = (1 << maca_reset_clkon); + + /* Wait for VREG_1P5V_RDY indication */ + while (!((*(volatile uint32_t *)0x80003018) & (1<< 19))) {} + + /* If last turnoff had a pending RX post we will get an action complete/PLL unlock interrupt. + * If an abort is now issued we will get an action complete/abort interrupt. + * This action complete is delayed by some unknown amount, just clearing MACA_IRQ below will not stop it. + * However a NOP does the job! + */ + *MACA_CONTROL = maca_ctrl_seq_nop | (1 << maca_ctrl_asap); + +/* Something is allowing reserved interrupt 13 on restart? */ + + *MACA_MASKIRQ = ((1 << maca_irq_rst) | + (1 << maca_irq_acpl) | + (1 << maca_irq_cm) | + (1 << maca_irq_flt) | + (1 << maca_irq_crc) | + (1 << maca_irq_di) | + (1 << maca_irq_sftclk) + ); + + last_post = NO_POST; + *MACA_CLRIRQ = 0xffff; enable_irq(MACA); + *INTFRC = (1 << INT_NUM_MACA); }