GPIO state after entering standby mode(ATSAMD10D13AS)

Go To Last Post
3 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Before I enter standby mode I set the following pins to inputs.

REG_PORT_DIR0 &= (~PORT_PA05 | ~PORT_PA06 | ~PORT_PA07 | ~PORT_PA08 | ~PORT_PA09 | ~PORT_PA14 | ~PORT_PA15);

I set the seep mode: 

SYSCTRL->XOSC32K.bit.RUNSTDBY = 1;
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
__DSB();
__WFI();

And wake up the device with I2C. When in sleep mode my pins should stay in input mode, however I am noticing some weird behaviour. Do GPIO pins change state when in standby? I see a lot of thing that can be controlled before going to sleep (TCC, TC, GCLK, , etc) but don't see anything for INPUT/OUTPUT, is there a way to force the pins to stay INPUTs.

This topic has a solution.
Last Edited: Mon. Mar 7, 2022 - 11:53 AM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

You are not clearing anything in REG_PORT_DIR0, try
 

REG_PORT_DIR0 &= ~(PORT_PA05 | PORT_PA06 | PORT_PA07 | PORT_PA08 | PORT_PA09 | PORT_PA14 | PORT_PA15);

or use the DIRCLR register.
/Lars

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks, for pointing it out that was a dumb mistake. One more question I turn on my PWM like this:

PM->APBCMASK.reg |= PM_APBCMASK_TCC0; // Enables the APB clock inside Pwr Management for TCC0
	
	GCLK->GENCTRL.reg = GCLK_GENCTRL_IDC |			// Improve duty cycle
	GCLK_GENCTRL_GENEN |		// Enable gen clock
	GCLK_GENCTRL_SRC_OSC8M |	// Select prefered source (8 MHz oscilator in this case)
	GCLK_GENCTRL_ID(4);			// Select GCLK ID, in this case GCLK4
	
	while(GCLK->STATUS.bit.SYNCBUSY); // Wait until clock bus is synced
	
	GCLK->GENDIV.reg =	GCLK_GENDIV_DIV(1) |	// Divide clock by (in this case 1)
	GCLK_GENDIV_ID(4);		// Apply to selected clock
	
	while(GCLK->STATUS.bit.SYNCBUSY); // Wait until clock bus is synced
	
	GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN |		// Enable gen clock
	GCLK_CLKCTRL_GEN_GCLK4 |	// Select clock
	GCLK_CLKCTRL_ID_TCC0;	// Feed the clock to wanted TCC
	
	while(GCLK->STATUS.bit.SYNCBUSY); // Wait until clock bus is synced

	TCC0->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV1_Val); // Divide counter by 1 giving 8 MHz (125 ns) on each TCC0 tick
	TCC0->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM; // Use "Normal PWM" (single-slope PWM): count up to PER, match on CC[n]
	
	while(TCC0->SYNCBUSY.bit.WAVE); // Wait for synchronization
	
	TCC0->PER.reg = _period; // Set the period (the number to count to (TOP) before resetting timer)
	
	while(TCC0->SYNCBUSY.bit.PER); // Wait for synchronization
	
	// Configure PA18 to be output
	PORT->Group[0].DIRSET.reg = PORT_PA16;
	PORT->Group[0].OUTCLR.reg = PORT_PA16;
	
	// Enable the port multiplexer
	PORT->Group[0].PINCFG[16].reg |= PORT_PINCFG_PMUXEN;
	
	// Connect TCC0 timer to PA18. Function F is TCC0/WO[2] for PA18.
	// Odd pin num (2*n + 1): use PMUXO
	// Even pin num (2*n): use PMUXE
	PORT->Group[0].PMUX[8].reg = PORT_PMUX_PMUXE_F;
	
	// Enable output (start PWM)
	TCC0->CTRLA.reg |= TCC_CTRLA_ENABLE;
	while(TCC0->SYNCBUSY.bit.ENABLE); // Wait for synchronization

And set the I2C (code provided by ataradov, HAL_GPIO macros are from his github):
 

#define I2C_BASE_ADDRESS       0x52
#define I2C_SERCOM             SERCOM1
#define I2C_SERCOM_PMUX        HAL_GPIO_PMUX_C
#define I2C_SERCOM_APBCMASK    PM_APBCMASK_SERCOM1
#define I2C_SERCOM_GCLK_ID     SERCOM1_GCLK_ID_CORE
#define I2C_SERCOM_IRQ_HANDLER irq_handler_sercom1
#define I2C_SERCOM_IRQ         SERCOM1_IRQn

static void i2cInit(void) {
	// function from "hal_gpio.h" sets PMUX values for SDA and SCL
	HAL_GPIO_SDA_pmuxen(I2C_SERCOM_PMUX);
	HAL_GPIO_SCL_pmuxen(I2C_SERCOM_PMUX);

	PM->APBCMASK.reg |= I2C_SERCOM_APBCMASK;

	GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(I2C_SERCOM_GCLK_ID) | GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0);

	I2C_SERCOM->I2CS.ADDR.reg = I2C_BASE_ADDRESS;
	
	// SMART mode enable @see https://ww1.microchip.com/downloads/en/DeviceDoc/SAM_D21_DA1_Family_DataSheet_DS40001882F.pdf#page=499
	I2C_SERCOM->I2CS.CTRLB.reg = SERCOM_I2CS_CTRLB_SMEN;

	I2C_SERCOM->I2CS.CTRLA.reg = SERCOM_I2CS_CTRLA_ENABLE | SERCOM_I2CS_CTRLA_MODE_I2C_SLAVE | SERCOM_I2CS_CTRLA_RUNSTDBY;

	// Stop Received Interrupt Disable, ADDRESS matching mode, Data Interrupt Disable @see https://ww1.microchip.com/downloads/en/DeviceDoc/SAM_D21_DA1_Family_DataSheet_DS40001882F.pdf#page=501
	I2C_SERCOM->I2CS.INTENSET.reg = SERCOM_I2CS_INTENCLR_PREC | SERCOM_I2CS_INTENCLR_AMATCH | SERCOM_I2CS_INTENCLR_DRDY;

	NVIC_EnableIRQ(I2C_SERCOM_IRQ);
}

As far as I can tell from the datasheet all clock sources are stopped, except those where the RUNSTDBY bit is set. Since I set that bit in the I2C code it runs in the background and that's fine, I'm just wondering if the PWM clock gets turned off (this would be the desired result). If I had to guess I would say that it does get turned off but the clocks are a bit confusing to be honest.