⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pmicm.nc

📁 tinyos-2.x.rar
💻 NC
字号:
/* $Id: PMICM.nc,v 1.7 2008/06/11 00:46:26 razvanm Exp $ */
/*
 * Copyright (c) 2005 Arched Rock Corporation 
 * All rights reserved. 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *	Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *	Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *  
 *   Neither the name of the Arched Rock Corporation nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE ARCHED
 * ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 */
/*
 *  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.  By
 *  downloading, copying, installing or using the software you agree to
 *  this license.  If you do not agree to this license, do not download,
 *  install, copy or use the software.
 *
 *  Intel Open Source License 
 *
 *  Copyright (c) 2002 Intel Corporation 
 *  All rights reserved. 
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 * 
 *	Redistributions of source code must retain the above copyright
 *  notice, this list of conditions and the following disclaimer.
 *	Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *      Neither the name of the Intel Corporation nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 *  PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE INTEL OR ITS
 *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * 
 */

/*
 *
 * Authors:  Lama Nachman, Robert Adler
 */

#define START_RADIO_LDO 1
#define START_SENSOR_BOARD_LDO 1
/*
 * VCC_MEM is connected to BUCK2 by default, make sure you have a board
 * that has the right resistor settings before disabling BUCK2
 */
#define DISABLE_BUCK2 0	

//#include "trace.h"
#include "Timer.h"
#include "pmic.h"

module PMICM {
  provides{
    interface Init;
    interface PMIC;
  }

  uses interface Timer<TMilli> as chargeMonitorTimer;
  uses interface HplPXA27xGPIOPin as PMICGPIO;
  uses interface HplPXA27xI2C as PI2C;
  uses interface PlatformReset;
}

implementation {
#include "pmic.h"
  
  bool gotReset;
  
  
  error_t readPMIC(uint8_t address, uint8_t *value, uint8_t numBytes){
    //send the PMIC the address that we want to read
    if(numBytes > 0){
      call PI2C.setIDBR(PMIC_SLAVE_ADDR<<1); 
      call PI2C.setICR(call PI2C.getICR() | ICR_START);
      call PI2C.setICR(call PI2C.getICR() | ICR_TB); 
      while(call PI2C.getICR() & ICR_TB);
      
      //actually send the address terminated with a STOP
      call PI2C.setIDBR(address);
      call PI2C.setICR(call PI2C.getICR() & ~ICR_START);
      call PI2C.setICR(call PI2C.getICR() | ICR_STOP);
      call PI2C.setICR(call PI2C.getICR() | ICR_TB); 
      while(call PI2C.getICR() & ICR_TB);
      call PI2C.setICR(call PI2C.getICR() & ~ICR_STOP);
      
      //actually request the read of the data
      call PI2C.setIDBR(PMIC_SLAVE_ADDR<<1 | 1);
      call PI2C.setICR(call PI2C.getICR() | ICR_START); 
      call PI2C.setICR(call PI2C.getICR() | ICR_TB);
      while(call PI2C.getICR() & ICR_TB);
      call PI2C.setICR(call PI2C.getICR() & ~ICR_START);
      
      //using Page Read Mode
      while (numBytes > 1){
	call PI2C.setICR(call PI2C.getICR() | ICR_TB); 
	while(call PI2C.getICR() & ICR_TB);
	*value = call PI2C.getIDBR(); 
	value++;
	numBytes--;
      }
      
      call PI2C.setICR(call PI2C.getICR() | ICR_STOP);
      call PI2C.setICR(call PI2C.getICR() | ICR_ACKNAK);
      call PI2C.setICR(call PI2C.getICR() | ICR_TB); 
      while(call PI2C.getICR() & ICR_TB);
      *value = call PI2C.getIDBR(); 
      call PI2C.setICR(call PI2C.getICR() & ~ICR_STOP); 
      call PI2C.setICR(call PI2C.getICR() & ~ICR_ACKNAK);
      
      return SUCCESS;
    }
    else{
      return FAIL;
    }
  }

  error_t writePMIC(uint8_t address, uint8_t value){
    call PI2C.setIDBR(PMIC_SLAVE_ADDR<<1); 
    call PI2C.setICR(call PI2C.getICR() | ICR_START); 
    call PI2C.setICR(call PI2C.getICR() | ICR_TB); 
    while(call PI2C.getICR() & ICR_TB);
    
    PIDBR = address;
    call PI2C.setICR(call PI2C.getICR() & ~ICR_START); 
    call PI2C.setICR(call PI2C.getICR() | ICR_TB); 
    while(call PI2C.getICR() & ICR_TB);

    PIDBR = value;
    call PI2C.setICR(call PI2C.getICR() | ICR_STOP); 
    call PI2C.setICR(call PI2C.getICR() | ICR_TB); 
    while(call PI2C.getICR() & ICR_TB);
    call PI2C.setICR(call PI2C.getICR() & ~ICR_STOP); PICR &= ~ICR_STOP;

    return SUCCESS;
  }
  
  void startLDOs() {
    //uint8_t temp;
    uint8_t oldVal, newVal;

#if START_SENSOR_BOARD_LDO 
    // TODO : Need to move out of here to sensor board functions
    readPMIC(PMIC_A_REG_CONTROL_1, &oldVal, 1);
    newVal = oldVal | ARC1_LDO10_EN | ARC1_LDO11_EN;	// sensor board
    writePMIC(PMIC_A_REG_CONTROL_1, newVal);

    readPMIC(PMIC_B_REG_CONTROL_2, &oldVal, 1);
    newVal = oldVal | BRC2_LDO10_EN | BRC2_LDO11_EN;
    writePMIC(PMIC_B_REG_CONTROL_2, newVal);
#endif

#if START_RADIO_LDO
    // TODO : Move to radio start
    readPMIC(PMIC_B_REG_CONTROL_1, &oldVal, 1);
    newVal = oldVal | BRC1_LDO5_EN; 
    writePMIC(PMIC_B_REG_CONTROL_1, newVal);
#endif

#if DISABLE_BUCK2  // Disable BUCK2 if VCC_MEM is not configured to use BUCK2
    readPMIC(PMIC_B_REG_CONTROL_1, &oldVal, 1);
    newVal = oldVal & ~BRC1_BUCK_EN;
    writePMIC(PMIC_B_REG_CONTROL_1, newVal);
#endif

#if 0
    // Configure above LDOs, Radio and sensor board LDOs to turn off in sleep
    // TODO : Sleep setting doesn't work
    temp = BSC1_LDO1(1) | BSC1_LDO2(1) | BSC1_LDO3(1) | BSC1_LDO4(1);
    writePMIC(PMIC_B_SLEEP_CONTROL_1, temp);
    temp = BSC2_LDO5(1) | BSC2_LDO7(1) | BSC2_LDO8(1) | BSC2_LDO9(1);
    writePMIC(PMIC_B_SLEEP_CONTROL_2, temp);
    temp = BSC3_LDO12(1); 
    writePMIC(PMIC_B_SLEEP_CONTROL_3, temp);
#endif
  }

  error_t startPMICstuff() {
    //command result_t StdControl.start(){ XXX-pb
    //init unit
    uint8_t val[3];
    //call PI2CInterrupt.enable(); XXX-pb

  }

  command error_t Init.init(){
    uint8_t val[3];
    PCFR |= PCFR_PI2C_EN; // Overrides GPIO settings on pins
    call PI2C.setICR(call PI2C.getICR() | (ICR_IUE | ICR_SCLE));
    atomic{
      gotReset=FALSE;
    }    

    call PMICGPIO.setGAFRpin(0);
    call PMICGPIO.setGPDRbit(FALSE);
    call PMICGPIO.setGFERbit(TRUE);
    /*
     * Reset the watchdog, switch it to an interrupt, so we can disable it
     * Ignore SLEEP_N pin, enable H/W reset via button 
     */
    writePMIC(PMIC_SYS_CONTROL_A, 
              SCA_RESET_WDOG | SCA_WDOG_ACTION | SCA_HWRES_EN);

    // Disable all interrupts from PMIC except for ONKEY button
    writePMIC(PMIC_IRQ_MASK_A, ~IMA_ONKEY_N);
    writePMIC(PMIC_IRQ_MASK_B, 0xFF);
    writePMIC(PMIC_IRQ_MASK_C, 0xFF);
    
    //read out the EVENT registers so that we can receive interrupts
    readPMIC(PMIC_EVENTS, val, 3);

    // Set default core voltage to 0.85 V
#ifdef PXA27X_13M
    //P85 is not reliable, using P95
    call PMIC.setCoreVoltage(B2R1_TRIM_P95_V);
#else
    call PMIC.setCoreVoltage(B2R1_TRIM_1_25_V);
#endif
    startLDOs();
    return SUCCESS;
  }

  async event void PI2C.interruptI2C() { //PI2CInterrupt.fired(){
    uint32_t status, update=0;
    status = call PI2C.getISR(); //PISR;
    if(status & ISR_ITE){
      update |= ISR_ITE;
      //trace(DBG_USR1,"sent data");
    }

    if(status & ISR_BED){
      update |= ISR_BED;
      //trace(DBG_USR1,"bus error");
    }
    call PI2C.setISAR(update); //PISR = update;
  }
  
  async event void PMICGPIO.interruptGPIOPin(){
    uint8_t events[3];
    bool localGotReset;
   
    //call PMICGPIO.call PMICInterrupt.clear(); XXX autocleard by GPIO module
   
    readPMIC(PMIC_EVENTS, events, 3);
   
    if(events[EVENTS_A_OFFSET] & EA_ONKEY_N){
      atomic{
        localGotReset = gotReset;
      }
      if(localGotReset==TRUE){
	call PlatformReset.reset();
      }
      else{
        atomic{
	  gotReset=TRUE;
        }
      }
    }
    else{
      //trace(DBG_USR1,"PMIC EVENTs =%#x %#x %#x\r\n",events[0], events[1], events[2]);
    }
  }

  /*
   * The Buck2 controls the core voltage, set to appropriate trim value
   */
  command error_t PMIC.setCoreVoltage(uint8_t trimValue) {
    writePMIC(PMIC_BUCK2_REG1, (trimValue & B2R1_TRIM_MASK) | B2R1_GO);
    return SUCCESS;
  }
  
  command error_t PMIC.shutDownLDOs() {
    uint8_t temp;
    uint8_t oldVal, newVal;
    /* 
     * Shut down all LDOs that are not controlled by the sleep mode
     * Note, we assume here the LDO10 & LDO11 (sensor board) will be off
     * Should be moved to sensor board control
     */

    // LDO1, LDO4, LDO6, LDO7, LDO8, LDO9, LDO10, LDO 11, LDO13, LDO14

    readPMIC(PMIC_A_REG_CONTROL_1, &oldVal, 1);
    newVal = oldVal & ~ARC1_LDO13_EN & ~ARC1_LDO14_EN;
    newVal = newVal & ~ARC1_LDO10_EN & ~ARC1_LDO11_EN;	// sensor board
    writePMIC(PMIC_A_REG_CONTROL_1, newVal);

    readPMIC(PMIC_B_REG_CONTROL_1, &oldVal, 1);
    newVal = oldVal & ~BRC1_LDO1_EN & ~BRC1_LDO4_EN & ~BRC1_LDO5_EN &
             ~BRC1_LDO6_EN & ~BRC1_LDO7_EN;
    writePMIC(PMIC_B_REG_CONTROL_1, newVal);

    readPMIC(PMIC_B_REG_CONTROL_2, &oldVal, 1);
    newVal = oldVal & ~BRC2_LDO8_EN & ~BRC2_LDO9_EN & ~BRC2_LDO10_EN &
             ~BRC2_LDO11_EN & ~BRC2_LDO14_EN & ~BRC2_SIMCP_EN;
    writePMIC(PMIC_B_REG_CONTROL_2, newVal);
    
    return SUCCESS;
  }

  error_t getPMICADCVal(uint8_t channel, uint8_t *val){
    uint8_t oldval;
    error_t rval;
    
    //read out the old value so that we can reset at the end
    rval = readPMIC(PMIC_ADC_MAN_CONTROL, &oldval,1);
    if (rval == SUCCESS) {
      rval = writePMIC(PMIC_ADC_MAN_CONTROL, PMIC_AMC_ADCMUX(channel) | 
		       PMIC_AMC_MAN_CONV | PMIC_AMC_LDO_INT_Enable);
    }
    if (rval == SUCCESS) {
      rval = readPMIC(PMIC_MAN_RES,val,1);
    }
    if (rval == SUCCESS) {
    //reset to old state
    rval = writePMIC(PMIC_ADC_MAN_CONTROL, oldval);
    }

    return rval;
  }

  command error_t PMIC.getBatteryVoltage(uint8_t *val){
    //for now, let's use the manual conversion mode
    return getPMICADCVal(0, val);
  }
  
  command error_t PMIC.chargingStatus(uint8_t *vBat, uint8_t *vChg, 
                                       uint8_t *iChg){
    getPMICADCVal(0, vBat);
    getPMICADCVal(2, vChg);
    getPMICADCVal(1, iChg);
    return SUCCESS;
  }  
  
  command error_t PMIC.enableAutoCharging(bool enable){
    return SUCCESS;
  }
  
  command error_t PMIC.enableManualCharging(bool enable){
    //just turn on or off the LED for now!!
    uint8_t val;
    
    if(enable){
      //want to turn on the charger
      getPMICADCVal(2, &val);
      //if charger is present due some stuff...75 should be 4.65V or so 
      if(val > 75 ) {
	//trace(DBG_USR1,"Charger Voltage is %.3fV...enabling charger...\r\n", ((val*6) * .01035));
	//write the total timeout to be 8 hours
	writePMIC(PMIC_TCTR_CONTROL,8);
	//enable the charger at 100mA and 4.35V
	writePMIC(PMIC_CHARGE_CONTROL,PMIC_CC_CHARGE_ENABLE | PMIC_CC_ISET(1) | PMIC_CC_VSET(7));
	//turn on the LED
	writePMIC(PMIC_LED1_CONTROL,0x80);
	//start a timer to monitor our progress every 5 minutes!
	call chargeMonitorTimer.startPeriodic(300000);
      }
      else{
	//trace(DBG_USR1,"Charger Voltage is %.3fV...charger not enabled\r\n", ((val*6) * .01035));
      }
    }
    else{
      //turn off the charger and the LED
      call PMIC.getBatteryVoltage(&val);
      //trace(DBG_USR1,"Disabling Charger...Battery Voltage is %.3fV\r\n", (val * .01035) + 2.65);
      //disable everything that we enabled
      writePMIC(PMIC_TCTR_CONTROL,0);
      writePMIC(PMIC_CHARGE_CONTROL,0);
      writePMIC(PMIC_LED1_CONTROL,0x00);
    }
    return SUCCESS; 
  }  
  
  event void chargeMonitorTimer.fired(){
    uint8_t val;
    call PMIC.getBatteryVoltage(&val);
    //stop when vBat>4V
    if(val>130){
      call PMIC.enableManualCharging(FALSE);
      call chargeMonitorTimer.stop();
    }
    return;
  }


}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -