Problem about low power mode in sam4s-ek2

Discussion around product based on ARM Cortex M4 core.

Moderators: nferre, ncollot

moon-sik
Posts: 6
Joined: Tue Mar 31, 2015 1:35 pm

Problem about low power mode in sam4s-ek2

Tue Mar 31, 2015 2:18 pm

hello all.

I want to use low power mode in sam4s-ek2. (wait and sleep mode)
So I found Training-Manual pdf file and source code 'Atmel-42272-Using-Low-Power_Modes-on-the-Atmel-SAM4S-EK2_...-8427.zip'.

Code: Select all




#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

#include "../hdr/power_mode.h"

#include "../../itf_ubinos/hdr/bsp.h"
#include "../../itf_ubinos/hdr/bsp_dtty.h"
#include "../../itf_ubinos/hdr/bsp_intr.h"
#include "../../itf_ubinos/hdr/ubinos.h"
#include "../../lib_ubik/src/_ubik.h"

#include "../../bsp_sam4sek2/src/_board.h"
#include "../../bsp_sam4sek2/libchip_sam4s/chip.h"

#include "../../lib_board_sam4sek2/board.h"

/*----------------------------------------------------------------------------
 *        Global definitions
 *----------------------------------------------------------------------------*/
#define ACTIVE_MODE 0x00
#define WAIT_MODE 0x01
#define SLEEP_MODE 0x02
#define BACKUP_MODE 0x03

/** LCD COLOR */
//#define COLOR_CYAN 0x00FFFF
//#define COLOR_NAVY 0x000080
//#define COLOR_GRAY 0x808080
//#define COLOR_RED 0xFF0000

/** (SCR) Sleep deep bit */
#define SCR_SLEEPDEEP   (0x1 <<  2)

/** Definition of the Main On-chip RC Oscillator Frequency */
#define FAST_RC_OSC_4MHZ    ((0x0 << 4) & CKGR_MOR_MOSCRCF_Msk)

/** Push button #1 definition. Attributes = pull-up + deglitch + debounce + interrupt on rising edge or high level. */
#define INTERRUPT_PIN_PIO	{PIO_PB3, PIOB, ID_PIOB, PIO_INPUT, PIO_PULLUP | PIO_DEGLITCH | PIO_DEBOUNCE | PIO_IT_FALL_EDGE}
/** BP2 */
const Pin pinBP2 = INTERRUPT_PIN_PIO;

/** Push button #2 definition. Attributes = pull-up + deglitch + debounce + interrupt on rising edge or high level. */
#define WKUPSIG_PIN_PIO	{PIO_PC12, PIOC, ID_PIOC, PIO_INPUT, PIO_PULLUP | PIO_DEGLITCH | PIO_DEBOUNCE | PIO_IT_FALL_EDGE}

/** BP3 */
const Pin pinBP3 = WKUPSIG_PIN_PIO;

#define WAKEUP_PIN15 {PIO_PA16, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP}

const Pin pinPA16 = WAKEUP_PIN15;

///** Touchscreen controller IRQ pin definition. */
//#define PIN_TSC_IRQ  {PIO_PA16, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP}
//#define PIN_TSC_IRQ_WUP_ID (1 << 15)
///** Pins used by Interrupt Signal for Touch Screen Controller */
//const Pin pinPenIRQ  = PIN_TSC_IRQ;
//
///** Wakeup PIN Index definition */
//const uint32_t gWakeUpPinId = PIN_TSC_IRQ_WUP_ID;

/*----------------------------------------------------------------------------
 *        Global variables
 *----------------------------------------------------------------------------*/

//static uint32_t lowPowerMode = WAIT_MODE;
static uint32_t lowPowerMode = SLEEP_MODE;

/** Clock backup value */
static uint32_t gPllarValBackup = 0;
static uint32_t gPllbrValBackup = 0;
static uint32_t gMckrValBackup  = 0;

static uint32_t interruptType;

/*----------------------------------------------------------------------------
 *        Local functions
 *----------------------------------------------------------------------------*/

/**
 * \brief Initialize the chip.
 */
static void _LowPower_Prepare( void )
{
    /* Switch off the LCD */
    //LCD_Off();
    //LCD_PowerDown();
    /* Disable Systick interrupt (used to configure the LCD) */
    SysTick->CTRL=0x04;

    /* TODO1.1: Disable all the peripheral clocks */
    PMC_DisableAllPeripherals();

    /* TODO1.2: Disable USB Clock */
    REG_PMC_SCDR = 1<<7;

   /* TODO1.3: Enable PIO function except on PA16, PB3, PC12 */
//    PIOA->PIO_PER = 0xFFFEFFFF;
//    PIOB->PIO_PER = 0xFFFFFFFF;
//    PIOC->PIO_PER = 0xFFFFFFFF;
    PIOA->PIO_PER = (uint32_t)~((0x1<<16));
    PIOB->PIO_PER = (uint32_t)~(0x1<<3);
    PIOC->PIO_PER = (uint32_t)~(0x1<<12);

   /* TODO1.4: Set all I/Os as Input except on PA16, PB3, PC12 */
//    PIOA->PIO_ODR = 0xFFFEFFFF;
//    PIOB->PIO_ODR = 0xFFFFFFFF;
//    PIOC->PIO_ODR = 0xFFFFFFFF;
    PIOA->PIO_ODR = (uint32_t)~((0x1<<16));
    PIOB->PIO_ODR = (uint32_t)~(0x1<<3);
    PIOC->PIO_ODR = (uint32_t)~(0x1<<12);

   /* TODO1.5: Disable all I/Os pull-up except on PA16, PB3, PC12 */
//    PIOA->PIO_PUDR = 0xFFFEFFFF;
//    PIOB->PIO_PUDR = 0xFFFFFFFF;
//    PIOC->PIO_PUDR = 0xFFFFFFFF;
    PIOA->PIO_PUDR = (uint32_t)~((0x1<<16));
    PIOB->PIO_PUDR = (uint32_t)~(0x1<<3);
    PIOC->PIO_PUDR = (uint32_t)~(0x1<<12);
}

/**
 * \brief Interrupt handler for TS IRQ pin.
 */
//static void ISR_TSC_IRQ_Interrupt(void)
//{
//    /* Check if the button1 has been pressed */
//    if (!PIO_Get(&pinPenIRQ)) {
//
//        /* Do nothing here */
//    }
//}

static void SetFastStartupInput(uint32_t FSMR_inputs)
{
    PMC->PMC_FSMR &= (uint32_t)~0xFFFF;
    PMC->PMC_FSMR |= FSMR_inputs;
}

static void SaveWorkingClock(uint32_t *pPllarVal, uint32_t *pPllbrVal, uint32_t *pMckrVal)
{
    /* Save previous values for PLL A, PLL B and Master Clock configuration */
    *pPllarVal = PMC->CKGR_PLLAR;
    *pPllbrVal = PMC->CKGR_PLLBR;
    *pMckrVal = PMC->PMC_MCKR;
}

///**
// * \brief Restore working clock.
// * Here working clock must be running from PLL
// * and external crystal oscillator is used.
// */
static void RestoreWorkingClock(uint32_t PllarVal, uint32_t PllbrVal, uint32_t MckrVal)
{
	unsigned int timeout =0 ;
    /* switch to slow clock first */
    PMC->PMC_MCKR = (PMC->PMC_MCKR & (uint32_t)~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_SLOW_CLK;
    while (!(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ == 5000));
    timeout = 0;
    PMC->PMC_MCKR = (PMC->PMC_MCKR & (uint32_t)~PMC_MCKR_PRES_Msk) | PMC_MCKR_PRES_CLK_1;
    while (!(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ == 5000));
    timeout = 0;
    /* Restart Main Oscillator */
    PMC->CKGR_MOR = (0x37 << 16) | (0x3F<<8) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN;
    while (!(PMC->PMC_SR & PMC_SR_MOSCXTS)&& (timeout++ == 5000));
    timeout = 0;
    /* Switch to moscsel */
    PMC->CKGR_MOR = (0x37 << 16) | (0x3F<<8) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL;
    while (!(PMC->PMC_SR & PMC_SR_MOSCSELS)&& (timeout++ == 5000));
    timeout = 0;
    /* Switch to main oscillator */
    PMC->PMC_MCKR = (PMC->PMC_MCKR & (uint32_t)~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK;
    while (!(PMC->PMC_SR & PMC_SR_MCKRDY)&& (timeout++ == 5000));
    timeout = 0;
    PMC->PMC_MCKR = (PMC->PMC_MCKR & (uint32_t)~PMC_MCKR_PRES_Msk) | PMC_MCKR_PRES_CLK_1;
    while (!(PMC->PMC_SR & PMC_SR_MCKRDY)&& (timeout++ == 5000));
    timeout = 0;
    /* Restart PLL A */
    if ((PllarVal & CKGR_PLLAR_MULA_Msk) != 0) {
        PMC->CKGR_PLLAR = PllarVal;
        while(!(PMC->PMC_SR & PMC_SR_LOCKA)&& (timeout++ == 5000));
        timeout = 0;
    }

    /* Restart PLL B */
    if ((PllbrVal & CKGR_PLLBR_MULB_Msk) != 0) {
        PMC->CKGR_PLLBR = PllbrVal;
        while(!(PMC->PMC_SR & PMC_SR_LOCKB)&& (timeout++ == 5000));
        timeout = 0;
    }

    /* Switch to fast clock */
    PMC->PMC_MCKR = (MckrVal & (uint32_t)~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK;
    while (!(PMC->PMC_SR & PMC_SR_MCKRDY)&& (timeout++ == 5000));
    timeout = 0;
    PMC->PMC_MCKR = MckrVal;
    while (!(PMC->PMC_SR & PMC_SR_MCKRDY)&& (timeout++ == 5000));
    timeout = 0;
}

static void SwitchMck2FastRC(uint32_t moscrcf, uint32_t pres)
{
      /* Switch to main clock */
    PMC->PMC_MCKR = (PMC->PMC_MCKR & (uint32_t)~PMC_MCKR_CSS_Msk)
        | PMC_MCKR_CSS_MAIN_CLK;
    while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
    PMC->PMC_MCKR = (PMC->PMC_MCKR & (uint32_t)~PMC_MCKR_PRES_Msk)
        | pres;
    while (!(PMC->PMC_SR & PMC_SR_MCKRDY));

    /* Enable Fast RC oscillator but DO NOT switch to RC now . Keep MOSCSEL to 1 */
    PMC->CKGR_MOR = CKGR_MOR_MOSCSEL | (0x37 << 16)
        | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCRCEN;
    /* Wait the Fast RC to stabilize */
    while (!(PMC->PMC_SR & PMC_SR_MOSCRCS));

    /* Change frequency of Fast RC oscillator */
    PMC->CKGR_MOR = (0x37 << 16) | PMC->CKGR_MOR | moscrcf;
    /* Wait the Fast RC to stabilize */
    while (!(PMC->PMC_SR & PMC_SR_MOSCRCS));

    /* Switch from Main Xtal osc to Fast RC */
    PMC->CKGR_MOR = (0x37 << 16) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN ;
    /* Wait for Main Oscillator Selection Status bit MOSCSELS */
    while (!(PMC->PMC_SR & PMC_SR_MOSCSELS));

    /* Disable Main XTAL Oscillator */
    PMC->CKGR_MOR = (0x37 << 16) | CKGR_MOR_MOSCRCEN;

    /* Stop PLL A */
    /* STMODE must be set at 2 when the PLLA is Off */
    PMC->CKGR_PLLAR = 0x2 << 14;

    /* Stop PLLB */
    /* STMODE must be set at 2 when the PLLB is OFF */
    PMC->CKGR_PLLBR = 0x2 << 14;
}

/**
 * \brief Test Backup Mode.
 */
//extern void _EnterBackupMode(void)
//{
//    _LowPower_Prepare();
//
//    PIO_Configure(&pinPenIRQ, 1);
//    PIO_SetDebounceFilter(&pinPenIRQ, 10);
//    PIO_ConfigureIt(&pinPenIRQ, (void (*)(const Pin *)) ISR_TSC_IRQ_Interrupt);
//
//    /* GPBR0 is for recording times of entering backup mode */
//    GPBR->SYS_GPBR[0] += 1;
//
//    /* TODO4.1: Enable the touchscreen IRQ pin as the wake-up source */
//    SUPC->SUPC_WUIR = (1<<15);
//
//    /* TOD4.2: Entry in the Backup Mode: */
//    /* Set VROFF bit  */
//    //SUPC->SUPC_CR |= (SUPC_CR_KEY_PASSWD | SUPC_CR_VROFF_STOP_VREG);
//    SUPC->SUPC_CR |= (SUPC_CR_KEY_Msk | SUPC_CR_VROFF_STOP_VREG);
//}

/** intialize LCD for debugging output*/
//static void _Init_LCD(void)
//{
//    /* Initialize LCD */
//    TimeTick_Configure( (4000000) );
//    //Wait(200);//Wait 200 ms for let LCD power on before Initialization
//	task_sleep(200);
//    LCDD_Initialize();
//    LCDD_On();
//    //LCDD_Off();
//}

/**
 * \brief Set default master access for speed up.
 * Here assume code is put at flash, data is put at sram.
 * The PDC transfer target at SRAM
 */
static void _SetDefaultMaster( void )
{
    Matrix *pMatrix = MATRIX;

    /* Set default master: SRAM (slave 0)-> Cortex-M4 System (Master 1)*/
    pMatrix->MATRIX_SCFG[0] |= ((1 << 18) & MATRIX_SCFG_FIXED_DEFMSTR_Msk) | /* Master 1 */
                               ((2 << 16) & MATRIX_SCFG_DEFMSTR_TYPE_Msk);   /* Fixed Default Master */

    /* Set default master: Internal flash (slave 2) -> Cortex-M4 Instruction/Data (Master 0)*/
    pMatrix->MATRIX_SCFG[2] |= ((0 << 18) & MATRIX_SCFG_FIXED_DEFMSTR_Msk) | /* Master 0 */
                               ((2 << 16) & MATRIX_SCFG_DEFMSTR_TYPE_Msk);   /* Fixed Default Master */

    /* Set default master: EBI (slave 3) -> PDC (Master 2)*/
    pMatrix->MATRIX_SCFG[3] |= ((2 << 18) & MATRIX_SCFG_FIXED_DEFMSTR_Msk) | /* Master 2 */
                               ((2 << 16) & MATRIX_SCFG_DEFMSTR_TYPE_Msk);   /* Fixed Default Master */
}

/** BP2 Interrupt Handler **/
void _Button2_Handler( const Pin* pin )
{
   uint32_t status;

   /* Read PIO controller status */
   status = PIOB->PIO_ISR;
   status &= PIOB->PIO_IMR;

   if(lowPowerMode == WAIT_MODE)
      interruptType = WAIT_MODE;
   else if(lowPowerMode == BACKUP_MODE)
      interruptType = BACKUP_MODE;
   else if(lowPowerMode == SLEEP_MODE)
      interruptType = SLEEP_MODE;
   else
      interruptType = ACTIVE_MODE;
}

/** BP3 Interrupt Handler **/
void _Button3_Handler( const Pin* pin )
{
	uint32_t status;

	/* Read PIO controller status */
	status = PIOC->PIO_ISR;
	status &= PIOC->PIO_IMR;

	if (interruptType == WAIT_MODE)
		PIO_Clear(&pinPA16);//Signal to Pin WKUP15
}

/** Touchscreen IRQ pin handler */
//void _TSC_IRQ_Handler( const Pin* pin )
//{
//   uint32_t status;
//
//   /* Read PIO controller status */
//   status = PIOA->PIO_ISR;
//   status &= PIOA->PIO_IMR;
//
//   if(lowPowerMode == WAIT_MODE)
//      interruptType = WAIT_MODE;
//   else if(lowPowerMode == BACKUP_MODE)
//      interruptType = BACKUP_MODE;
//   else if(lowPowerMode == SLEEP_MODE)
//      interruptType = SLEEP_MODE;
//   else
//      interruptType = ACTIVE_MODE;
//}

static void _Init_WKUPPIN15_Trigger(void)
{
    PIO_Configure(&pinPA16, 1);

    PIO_SetDebounceFilter(&pinPA16, 10);

}

/** initialize push button(BP2) for state transition*/

static void _Init_Pushbutton_Trigger(void)
{
    /* Configure pios as inputs. */
    PIO_Configure( &pinBP2, 1 ) ;

    /* Adjust pio debounce filter patameters, uses 10 Hz filter. */
    PIO_SetDebounceFilter( &pinBP2, 10 ) ;

    /* Initialize pios interrupt handlers, see PIO definition in board.h. */
    PIO_ConfigureIt( &pinBP2, _Button2_Handler ) ; /* Interrupt on rising edge  */

    /* Enable PIO controller IRQs. */
    NVIC_EnableIRQ( (IRQn_Type)pinBP2.id ) ;

    intr_connectisr(ID_PIOB, _Button2_Handler, intr_getlowestpriority(), 0);

    /* Enable PIO line interrupts. */
    PIO_EnableIt( &pinBP2 ) ;

    intr_enable(ID_PIOB);
}

/** initialize push button(BP3) for wake up */

static void _Init_Wakeupbutton_Trigger(void)
{
	/* Configure pios as inputs. */
	PIO_Configure( &pinBP3, 1 ) ;

	/* Adjust pio debounce filter patameters, uses 10 Hz filter. */
	PIO_SetDebounceFilter( &pinBP3, 10 ) ;

	/* Initialize pios interrupt handlers, see PIO definition in board.h. */
	PIO_ConfigureIt( &pinBP3, _Button3_Handler ) ; /* Interrupt on rising edge  */

	/* Enable PIO controller IRQs. */
	NVIC_EnableIRQ( (IRQn_Type)pinBP3.id ) ;

	intr_connectisr(ID_PIOC, _Button3_Handler, intr_getlowestpriority(), 0);

	/* Enable PIO line interrupts. */
	PIO_EnableIt( &pinBP3 ) ;

	intr_enable(ID_PIOC);
}

/** initialize TSC IRQ for state transition*/
//static void _Init_TSC_IRQ_Trigger(void)
//{
//    /* Configure pios as inputs. */
//    PIO_Configure( &pinPenIRQ, PIO_LISTSIZE( pinPenIRQ ) ) ;
//
//    /* Adjust pio debounce filter patameters, uses 10 Hz filter. */
//    PIO_SetDebounceFilter( &pinPenIRQ, 10 ) ;
//
//    /* Initialize pios interrupt handlers, see PIO definition in board.h. */
//    PIO_ConfigureIt( &pinPenIRQ, _TSC_IRQ_Handler ) ; /* Interrupt on rising edge  */
//
//    /* Enable PIO controller IRQs. */
//    NVIC_EnableIRQ( (IRQn_Type)pinPenIRQ.id ) ;
//
//    intr_connectisr(ID_PIOA, _TSC_IRQ_Handler, intr_getlowestpriority(), 0);
//
//    /* Enable PIO line interrupts. */
//    PIO_EnableIt( &pinPenIRQ ) ;
//
//    intr_enable(ID_PIOA);
//}

/**
 * \brief Enter Wait Mode */
extern void _EnterWaitMode( void )
{

	/* Initialize PIOs for low power */
    _LowPower_Prepare();

    /* Initialize Touch Screen Pen Detect Interrupt */
    //_Init_TSC_IRQ_Trigger();
    //_Init_Wakeupbutton_Trigger();

    /* Save current working clock */
    SaveWorkingClock(&gPllarValBackup, &gPllbrValBackup, &gMckrValBackup);

    /* Disable Brownout Detector */
    SUPC->SUPC_MR |= (uint32_t)(0xA5 << 24) | (0x01 << 13) ;

    /* TODO2.1: Switch MCK to the fast RC oscillator */
    SwitchMck2FastRC(FAST_RC_OSC_4MHZ, PMC_MCKR_PRES_CLK_1);

    /* TODO2.2: Set WKUP15 (TSC_IRQ pin) as the fast startup event */
    SetFastStartupInput(PMC_FSMR_FSTT15);

    /* TODO2.3:  Entry in the Wait Mode: */
    /*Set FLPM bit */
    PMC->PMC_FSMR &= ~PMC_FSMR_FLPM_Msk; /**< \brief (PMC_FSMR) Flash Low Power Mode */
    PMC->PMC_FSMR |= (1<<21);

    /* Set Flash Wait State at 0 */
    EFC0->EEFC_FMR &= ~EEFC_FMR_FWS_Msk; /**< \brief (EEFC_FMR) Flash Wait State */
    EFC0->EEFC_FMR |= (0 << 8);

    /* Set waitmode bit*/
    //PMC->CKGR_MOR |= (CKGR_MOR_KEY_PASSWD | CKGR_MOR_WAITMODE);
    PMC->CKGR_MOR |= ( (0x37u<<16) | CKGR_MOR_WAITMODE);

    while( !(PMC->PMC_SR & PMC_SR_MCKRDY) );

}

/**
 * \brief Enter Sleep Mode */
extern void _EnterSleepMode( void )
{
    /* Initialize PIOs for low power */
    _LowPower_Prepare();

    /* Disable Brownout Detector */
    SUPC->SUPC_MR |= (uint32_t)(0xA5 << 24) | (0x01 << 13);

    /* Save current working clock */
    SaveWorkingClock(&gPllarValBackup, &gPllbrValBackup, &gMckrValBackup);

    /* Initialize TS IRQ pin as the wake-up interrupt */
    //_Init_TSC_IRQ_Trigger();
    _Init_Wakeupbutton_Trigger();

    /* TODO3.1: Switch to the Fast RC Oscillator 4MHz divided by 4 = 1 MHz */
    SwitchMck2FastRC(FAST_RC_OSC_4MHZ, PMC_MCKR_PRES_CLK_4);

    /* TODO3.2: Entry in the Sleep Mode: */
    /* Clear LPM bit */
    PMC->PMC_FSMR &= ~PMC_FSMR_LPM;

    /* Clear SLEEPDEEP bit */
    SCB->SCR &= ~SCR_SLEEPDEEP;

    /* Execute __WFI() function */
    __WFI();

    /* Waiting for MOSCRCEN bit is cleared is strongly recommended
    to ensure that the core will not execute undesired instructions */
    while ( !(PMC->CKGR_MOR & CKGR_MOR_MOSCRCEN) ) ;
}

//static void _Display_Startup_Screen(void)
//{
//  LCDD_Fill(COLOR_CYAN);
//  LCDD_DrawString(0, 10, (uint8_t *)"  - SAM4S-EK -", COLOR_NAVY);
//  LCDD_DrawString(0, 30, (uint8_t *)"  Low Power Modes", COLOR_NAVY);
//
//
//  if(lowPowerMode == WAIT_MODE){
//      LCDD_DrawString(0, 120, (uint8_t *)"    BP2 to Enter", COLOR_GRAY);
//      LCDD_DrawString(0, 140, (uint8_t *)"    in Wait mode", COLOR_GRAY);
//
//  }
//  else if(lowPowerMode == SLEEP_MODE){
//      LCDD_DrawString(0, 120, (uint8_t *)"    BP2 to Enter", COLOR_GRAY);
//      LCDD_DrawString(0, 140, (uint8_t *)"    in Sleep mode", COLOR_GRAY);
//
//  }
//  else if(lowPowerMode == BACKUP_MODE){
//    if (GPBR->SYS_GPBR[0] == 0){
//       LCDD_DrawString(0, 120, (uint8_t *)"   BP2 to Enter", COLOR_GRAY);
//       LCDD_DrawString(0, 140, (uint8_t *)"   in Backup mode", COLOR_GRAY);
//
//    }
//    else {
//       LCDD_DrawString(0, 120, (uint8_t *)"   Exit from backup", COLOR_RED);
//       LCDD_DrawString(0, 150, (uint8_t *)"   BP2 to Enter", COLOR_GRAY);
//       LCDD_DrawString(0, 170, (uint8_t *)"   in Backup mode", COLOR_GRAY);
//    }
//  }
//}
//
//static void _Display_Exit_Screen(void)
//{
//  LCDD_Fill(COLOR_CYAN);
//  LCDD_DrawString(0, 10, (uint8_t *)"  - SAM4S-EK -", COLOR_NAVY);
//  LCDD_DrawString(0, 30, (uint8_t *)"  Low Power Modes", COLOR_NAVY);
//  if(lowPowerMode == WAIT_MODE) {
//      LCDD_DrawString(0, 120, (uint8_t *)"Exit from Wait mode", COLOR_RED);
//      LCDD_DrawString(0, 150, (uint8_t *)"   BP2 to Enter", COLOR_GRAY);
//      LCDD_DrawString(0, 170, (uint8_t *)"   in Wait mode", COLOR_GRAY);
//  }
//  else if(lowPowerMode == SLEEP_MODE) {
//      LCDD_DrawString(0, 120, (uint8_t *)"Exit from Sleep mode", COLOR_RED);
//      LCDD_DrawString(0, 150, (uint8_t *)"   BP2 to Enter", COLOR_GRAY);
//      LCDD_DrawString(0, 170, (uint8_t *)"   in Sleep mode", COLOR_GRAY);
//  }
//}

extern void Exit_LP_Mode(void)
{
    uint32_t temp;

    /* Set FWS for Embedded Flash Access */
    EFC0->EEFC_FMR = (uint32_t)(0x6 << 8);

   /* Restore working clock */
    RestoreWorkingClock(gPllarValBackup, gPllbrValBackup, gMckrValBackup);
    SwitchMck2FastRC(FAST_RC_OSC_4MHZ, PMC_MCKR_PRES_CLK_1);

    /* Enable Brownout Detector */
    temp = SUPC->SUPC_MR & 0x00FFFFFF;
    SUPC->SUPC_MR = (uint32_t)(0xA5 << 24) | (temp & (uint32_t)(~(0x01 << 13)));

    /* Disable interrupt on BP2 IRQ pin to avoid wrong detect */
//    if(interruptType==SLEEP_MODE) {
////    NVIC_DisableIRQ( (IRQn_Type)pinPenIRQ.id ) ;
////    PIO_DisableIt( &pinPenIRQ ) ;
////    intr_disable((IRQn_Type)pinPenIRQ.id);
//    	NVIC_DisableIRQ( (IRQn_Type)pinBP2.id ) ;
//        PIO_DisableIt( &pinBP2 ) ;
//        intr_disable((IRQn_Type)pinBP2.id);
//    }

    /* configure the PIOs */
	/* Enable pull-up on specific I/Os */
//    PIOA->PIO_PUER = (1<<6)|(1<<10)|(1<<11)|(1<<16)|(1<<18)|(1<<21)|(1<<23)|(1<<26)|(1<<27)|(1<<28)|(1<<30)|(1<<31);
    PIOA->PIO_PUER = (uint32_t)((1<<6)|(1<<10)|(1<<11)|(1<<16)|(1<<18)|(1<<21)|(1<<23)|(1<<26)|(1<<27)|(1<<28)|(1<<30)|(1<<31));
    PIOB->PIO_PUER = (uint32_t)((1<<3)|(1<<6)|(1<<7)|(1<<11));
    PIOC->PIO_PUER = (uint32_t)((1<<12)|(1<<13)|(1<<14)|(1<<15)|(1<<18));

    /* Clear output on the other I/Os */
//    PIOA->PIO_CODR = (uint32_t)(~((1<<6)|(1<<10)|(1<<11)|(1<<21)|(1<<23)|(1<<26)|(1<<27)|(1<<28)|(1<<30)|(1<<31)));
    PIOA->PIO_CODR = (uint32_t)(~((1<<6)|(1<<10)|(1<<11)|(1<<19)|(1<<20)|(1<<21)|(1<<23)|(1<<26)|(1<<27)|(1<<28)|(1<<30)|(1<<31)));
    PIOB->PIO_CODR = (uint32_t)(~((1<<3) |(1<<4)|(1<<6)|(1<<7)|(1<<11)));
    PIOC->PIO_CODR = (uint32_t)(~((1<<12)|(1<<13)|(1<<14)|(1<<15)|(1<<18)));

    /* Enable pull-down on specific I/Os */
//    PIOA->PIO_PPDER = (uint32_t)(~((1<<6)|(1<<10)|(1<<11)|(1<<21)|(1<<23)|(1<<26)|(1<<27)|(1<<28)|(1<<30)|(1<<31)));
    PIOA->PIO_PPDER = (uint32_t)(~((1<<6)|(1<<10)|(1<<11)|(1<<19)|(1<<20)|(1<<21)|(1<<23)|(1<<26)|(1<<27)|(1<<28)|(1<<30)|(1<<31)));
    PIOB->PIO_PPDER = (uint32_t)(~((1<<3) |(1<<4)|(1<<6)|(1<<7)|(1<<11)));
    PIOC->PIO_PPDER = (uint32_t)(~((1<<12)|(1<<13)|(1<<14)|(1<<15)|(1<<18)));

    /* Enable output I/Os */
    PIOA->PIO_OER = (uint32_t)(~((1<<12)|(1<<13)|(1<<14)|(1<<18)));
//    PIOA->PIO_OER = (uint32_t)(~((1<<12)|(1<<13)|(1<<14)|(1<<18)|(1<<19)|(1<<20)));
    PIOB->PIO_OER = (uint32_t)(~((1<<3)|(1<<6)|(1<<7)|(1<<11)));
    PIOC->PIO_OER = (uint32_t)(~((1<<9)|(1<<12)|(1<<13)|(1<<15)|(1<<20)));

    /* Display menu */
    //_Init_LCD();
    //_Display_Exit_Screen();

    /* Init interrupt on BP2 pin to switch in Low Power mode */
    //_Init_Pushbutton_Trigger();
    /* Enable Interrupt on BP2 to switch again to wait mode if needed */
    _Init_Pushbutton_Trigger();
    //_Init_Wakeupbutton_Trigger();
    _Init_WKUPPIN15_Trigger();

    interruptType = ACTIVE_MODE;
}

/* system systick handler */
void SysTick_Handler( void )
{
    TimeTick_Increment() ;
}

extern void Low_Power_Test(void)
{
	int cpu_clock = 0;
	uint32_t tick = 0;
	/* Set FWS for Embedded Flash Access */
	   EFC0->EEFC_FMR = (uint32_t)(0x6 << 8);

	  /* Disable watchdog*/
	   WDT_Disable( WDT ) ;

	    /* Set Matrix Master*/
	   _SetDefaultMaster() ;

	   interruptType = ACTIVE_MODE;
	   //interruptType = WAIT_MODE;
	   LED_Configure(0);//Blue LED
	   LED_Toggle(0);
	   LED_Configure(1);//Green LED
	   LED_Toggle(1);

	    /* Initialize the LCD */
//	   tick = TimeTick_Configure( 4000000 );
//	   printf("systick config? %d\r\n", tick);
//	    _Init_LCD();
//	    _Display_Startup_Screen();

	    /* Init interrupt on BP2 to switch in Low Power mode */
	    _Init_Pushbutton_Trigger();
	    //_Init_Wakeupbutton_Trigger();
	    _Init_WKUPPIN15_Trigger();

//	    bsp_getcpuclockfreqk(&cpu_clock);
//	    printf("cpu_clock : %d\r\n", cpu_clock);
//	    bsp_getmckfreq(&cpu_clock);
//	    printf("mck : %d\r\n", cpu_clock);
	    while(1){
	    	//printf("%d\n", PIO_Get(&pinBP2));
	    	//task_sleep(1000);
	    	//tick=GetTickCount();
	    	//printf("tick : %d\r\n", tick);
	    	if (interruptType != ACTIVE_MODE) {
	    		if(interruptType == WAIT_MODE){

//	    			printf("Enter wait mode\r\n");
	    			/* Enter Wait Mode */
	    			_EnterWaitMode();

//	    			task_sleep(10);

	    			Exit_LP_Mode();

      interruptType= ACTIVE_MODE;
	    		}

       else if (interruptType == SLEEP_MODE){

//	    			printf("Enter sleep mode\r\n");
	    			/* Enter Sleep Mode */
	    			_EnterSleepMode();

//	    			task_sleep(10);

	    			Exit_LP_Mode();
//	    			printf("Exit sleep mode\r\n");
	    		}
	    		//	         else if(interruptType == BACKUP_MODE){
	    		//	             /* Enter Backup Mode */
	    		//	             _EnterBackupMode();
	    		//
	    		//	             while(1);
	    		//	         }
	    	}
//	    	task_sleep(100);
	   }
}
I succeeded to enter low-power mode(wait and sleep) and wake up.
But i found a problem when repeating this operation (enter low-power mode and wake up.)
In my environment, I can see abort system exactly fourth wake up.

Also I tested SAM4S-EK2 Demo source code. (I could get this code at atmel studio)
In this case, if this operation repeat 16times, I can see abnormaly system stop exactly 16th wake up.

What should i do??
Thanks for advice.

Return to “SAM4 Cortex-M4 MCU”

Who is online

Users browsing this forum: No registered users and 2 guests