ATTINY3216-SN: UART Won't Work on Wakeup from Sleep

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

Hello,

 

My circuit was working exactly as I wanted until I realized that it was taking 25mA when it was sleeping.  Turns out, the TX pin was back-powering an external RS422 driver through the pin.  So I changed the code.

 

Right before going to sleep I know disable the UART and set the TX pin to an input.  Then right after waking up, I do the opposite.  It solved the problem with the extra current draw, but now the UART won't work after sleeping.  It works the first time through the code but as soon as the part goes to sleep and wakes up then the UART stops working.  So something is messed up on waking up I surmise.

 

Here is the code....

 

This code is run when the signal ANT_SWITCH is sampled and goes low.  There is no interrupt here, just polled in the main loop.

 


			SLPCTRL_set_sleep_mode( SLPCTRL_SMODE_PDOWN_gc );

			// turn RS422 transceiver power off to save power when asleep
			RS422_PWR_EN_set_level( false );

// turn off UART and disable TX pin so we don't power RS422 transceiver through the I/O pin
USART_0_disable();
PORTB_set_pin_dir(2, PORT_DIR_IN);

			// turn off NFC_IRQ interrupt and clear interrupt flag
			NFC_IRQ_set_isc( PORT_ISC_INTDISABLE_gc );
			VPORTA_INTFLAGS = (1 << 1);

			// turn off timer interrupt
			TCA0.SINGLE.INTCTRL &= ~TCA_SINGLE_OVF_bm;

			// clear flag and turn on interrupt for ANT_SWITCH pin for rising edge to wake up
			VPORTA_INTFLAGS = (1 << 2);
			ANT_SWITCH_set_isc( PORT_ISC_RISING_gc );

			// turn watchdog off or it will just wake up device
			ccp_write_io( (void *)&(WDT.CTRLA),
							  WDT_PERIOD_OFF_gc
							| WDT_WINDOW_OFF_gc /* Window mode off */);

			// enable sleep mode
			SLPCTRL.CTRLA = 1 << SLPCTRL_SEN_bp;

			// go to sleep
			asm( "sleep" );

			/*
			*
			*  Device is now asleep and will wake up on pin interrupt and continue below
			*
			*/

			// short delay
			uint16_t ii;
			for( ii=0; ii<UINT16_MAX; ii++ );

			// turn RS422 transceiver power back on
			RS422_PWR_EN_set_level( true );
			
			// turn off interrupt for ANT_SWITCH pin for rising edge
			ANT_SWITCH_set_isc( PORT_ISC_INTDISABLE_gc );

			// turn system interrupts back on
			TCA0.SINGLE.INTCTRL = TCA_SINGLE_OVF_bm;
			NFC_IRQ_set_isc( PORT_ISC_RISING_gc );

			// turn watchdog back on to ~4 second period
			ccp_write_io( (void *)&(WDT.CTRLA),
						  WDT_PERIOD_4KCLK_gc /* 4K cycles (4.1s) */
						| WDT_WINDOW_OFF_gc /* Window mode off */);

			// re-configure UART TX pin
			// Set pin direction to output
			UART_TX_set_dir(PORT_DIR_OUT);

			UART_TX_set_level(
			// <y> Initial level
			// <id> pad_initial_level
			// <false"> Low
			// <true"> High
			false);
			USART_0_enable();
			
			// send wakeup message
			UART_SEND_CHAR( 0x07 );
			

 

Any ideas what I don't have set back up correctly?

 

James.

This topic has a solution.
Last Edited: Tue. Sep 15, 2020 - 11:46 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Maybe a USART errata is a contributing cause of the defect; might expand USART_0_disable and USART_0_enable.

ATtiny3216/3217 Silicon Errata and Data Sheet Clarification (page 7)

via ATTINY3216 - 8-bit AVR Microcontrollers

 

"Dare to be naïve." - Buckminster Fuller

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I tested on a 3217 board. Although I did't spend a lot of time trying to figure it out, the errata seems to apply although worded a little odd. It makes it sound like the pin override (for the output value, which is all it controls) is not released. Doesn't sound so bad since are setting the dir to input anyway (whatever it is overriding on the output should not make a difference). But it seems there is more to it, or I just am not understanding, since I can disable/enable the tx and can then no longer tx. If a write to the baud reg is done after turning off the tx, then it works ok again (one fix in the errata).

 

Probably the simple thing to do in your case (and what I initially did below), is just leave the usart on. There is no need to disable tx, so just switch the pin to an input and back to an output when wake. There also may be an advantage to enabling the tx output before enabling the rs422 so the tx line isn;t floating when rs422 turns on.

...

int main(){
    Cpuint::vectorFunction( board.sw.portVector(),
        []{ board.sw.inputMode( INTDISABLE ); }
    );
    u0.setBaud1x(115200);
    u0.txOn(); //also sets tx to output
    for(;;){
        u0.write('X');
        wait( 1_sec );
        Port<USART0_TXD>::input(); //(not a feature in Usart, so do through Port)
        board.sw.inputMode( BOTHEDGES ); //also clears flag
    u0.txOff(); //if I do this (but no need to do)
    u0.setBaud1x(115200); //then any write to usart register 'fixes' (else no more tx)
        Slpctrl::sleep( Slpctrl::PDOWN );
        Port<PINS::USART0_TXD>::output(); //tx back to normal
    u0.txOn();
    }

}

Last Edited: Tue. Sep 15, 2020 - 04:27 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello @curtvm,

 

Have you tried setting it back to output after re-enabling the TX? 

The errata states that the TX overrides are held in the special case, and if you then try to set the pin to output again before re-enabling TX, it's never set to output and can't output anything. If you set to output after TX is enabled, this override is not held and the USART should work.

 

I haven't tried it myself, but I believe that should do the trick

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

Thank you for the ideas.  I tried just leaving the UART on and that seems to work now.  Not really sure why it was failing, but it works now.  I had done that because experience on other micros says you can't change the module pin directions when the module itself is enabled, but that doesn't seem to be the case here.

 

So things are working as expected now.  Thanks again.

 

James

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

Great to hear that it works :) 

 

Your problem absolutely seems to be the override errata. Since the USART is turned off in a way as described in the errata, any change to the data direction after it is disabled and before it is enabled is overridden.

So you can fix it in one of three ways:

- What you just did, i.e. don't turn off the USART at all. This is fine if your application allows it to always be on.

- Turn off the USART in a way which doesn't trigger the errata (i.e. turn off TX before RX or write some random USART register after disabling TX). Then your pin is free and you may set it to output before enabling USART again. This is the recommended fix since then the device functions as it should.

- Set the pin to output after enabling USART again.

 

Your fix is probably fine, I'm just writing this for future people wondering the same thing :) 

 

Amund

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

It is a little confusing, but I think I understand it better now, although not fully.

 

What is is a little unusual is the override that seems to be in play is the DIR override, which I think may be only used in open drain mode (the errata does not specify which override they are talking about). Also unusual is it seems the override signal makes it way to a register which we can see (DIR- you can read and see what is going on to some degree). Normally these override signals are not visible since the override is after the register.

 

We are required to set the DIR to output for most tx uses, so the DIR override is not used. But it seems when turning off TXEN the tx pin DIR will be set to input in any case (when TXEN 1->0, then tx pin DIR=0). If the tx pin needs to be an output for any use after tx disabled, then you have to first release the override the usart is still applying (DIR=0), by writing to a usart register. If the RXEN is 1, then this is not required, but the tx pin DIR still goes to 0.

 

So, a fix for turning off tx would be something like-

 

void txOff(){

    TXEN = 0;

    TXEN = 0;

    //but note that tx pin is now an input

    //any time txen is disabled

}

 

and then also deal with the pin direction again next time enabling tx.

 

 

This may still not be totally correct, but its close.

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

That's absolutely correct, that's how it works. The reason for the errata is simply the USART clock being gated before it has time to release its overrides. Writing any USART register gives it another clock edge, which is enough.

I agree - the overrides are a bit unusual for the USART as compared to the other peripherals for the AVRs, but fortunately nothing that can't be worked around. The errata is fixed for later devices by the way, like for the AVR DA: http://ww1.microchip.com/downloads/en/DeviceDoc/80000882A.pdf

 

Amund