Author Topic: Questions about AVR sleep mode, interrupts and wake up  (Read 1163 times)

0 Members and 1 Guest are viewing this topic.

Online MathWizardTopic starter

  • Super Contributor
  • ***
  • Posts: 1622
  • Country: ca
Questions about AVR sleep mode, interrupts and wake up
« on: October 04, 2024, 10:57:14 pm »
I'm bare metal programming an ATtiny13A. So I'm making assembly, then the opcodes, then the intel hex. And for now running it in SimulIDE 1.1.0

I made a basic program that should setup the ADC to auto-trigger when the Timer/Counter gets Compare Match A. And I'm trying to put the system into IDLE mode right after starting the counter, and I'm setting the MCUCR reg for idle mode, including the enable bit. And then I'm giving the SLEEP command.

Except for maybe the ADC INT Flag, ADIF, I think the rest are setup right, and the Global int flag is set 1. It says in the datasheet, that you can clear ADIF, by setting 1. But looking in the ADCSRA reg in SimulIDE, it gets set to 0, even though my code was right. Maybe that's fine and not an issue.


So after the sleep command, I'm expecting the CPU to powerdown, but the ADC and T/C will keep running. Then the T/C should count up to MATCH the value in OCR0A. The T/C is set to Clear Timer on Compare. The output registers OC0A,B are set to toggle. I put nothing in any timer interrupt vector location, besides RJMP to main prgm.

The ADC is set to auto-trigger on Compare Match A, so I'm guessing it watches OC0A for a state change, and ADIF is set low, and ADIE is high for allowing the interrupt. I didn't see an explanation of how the T/C tells the ADC to trigger, or anything that says to set more interrupts. If I get it, the WGM and COM0x settings handle that.

So at the ADC INT vector, I put an RJMP to a routine, word 40 ATM (but the code in not working so never mind the exact end section). And I put a RETI at the end of it, expecting then the RETI would lead to the instruction after SLEEP.

Maybe I'm supposed to be doing PUSH/POP with the stack for those return instruction addresses ?




But I'm not sure the timer is running, I don't see the TCNT0 counter reg getting incremented, and the ADC never gets trigger as far as I can tell. It never gives any result. In the sim, the main osc is only set to ~1MHz, and only 1 instruction/sec.


But also for the SLEEP command, I get an error, saying it's not being fully implemented. The timer should count up ~83ms in real life, in the sim IDK, I have it slowed way down. But the PC goes to the next command, and carry's on. But I get the error
Quote
Warning: AVR SLEEP instruction not Fully implemented

Now for the sleep command, am I supposed to be storing in the stack, the location of the SLEEP ( or 1 after it) ? Or is that done automatically by the SLEEP command ? I don't see anything in the stack tho, I did set the top as 0x9F. Looking this up on the web, I just get the same old pages over and over, and usually only in C, not assembly. So IDK what PUSH or POP commands might be going on.

But the PC is jumping right to the next command after sleep, I had a NOP there, then I tried loading the code for disabling sleep-enable. And whatever the T/C is really doing, the ADC never seems to do anything. I've never seen the PC go to the ADC INT vector at 0x09, or to the little routine a few steps ahead of SLEEP. I had RJMP before it too, so it really never got there.

The end code and some rmps and branch aren't finished since it's not working. But all I was trying to do, is read a sine-wave with the ADC, and if the count was under 256, ADCH would be 0, and then I would do a CPI, and Branch IF Carry flag Set, and light up an LED. Otherwise, it would jump back to enabling sleep modes, reset the counter and SLEEP again, and count up and read the ADC again.

Here's a look at the main I/O reg's on PC36, so the NOP right before the sleep command. I added some of them so it would be easy to change the final intelhex in the spreadsheet. Besides ADIF in the ADCSRA set to 0, so it's 0xAB, not  0xBB, everything is as I set as I think it should be. I also had LED's on OC0A/B. They toggle some, but something wrong, certainly with the ADC not triggering, and the SLEEP.

The SLEEP on PC37, definitely takes longer, but then it just goes up to W39 and RJMP's to W34 and loops forever.

0   RJMP 9      
1   RJMP 8      
2   RJMP 7      
3   RJMP 6      
4   RJMP 5      
5   RJMP 4      
6   RJMP 3      
7   RJMP 2      
8   RJMP 1      
9   RJMP 30              ;ADC interrupt leads to W40
10   EOR R0,R0      
11   LDI R16,64      ; loads 0100 0000 for ADMUX
12   OUT 7,R16      ;sets ADMUX use 1V1ref and PB5=ADC0
13   LDI R17,187      :loads 1011 1011 for ADCSRA
14   OUT 6,R17      ;enables ADC, ADCinterrupts, /8 prescaler
15   LDI R18,3              ;loads 0000 0011 for ADCSRB
16   OUT 3,R18      ;sets ADC to trigger on T/C CompareMatchA
17   LDI R19,63      ;loads 0011 1111 for DIDR0
18   OUT 20,R19      ;disables DigitalData buffers for all 6 ports
19   LDI R20,129      ;loads 1000 0001 for GTCCR
20   OUT 40,R20      ;holds the T/C in reset while setting up
21   LDI R21,82      ;loads 0101 0010 for TCCR0A
22   OUT 47,R21      ;set OC0x to toogle on CompareMatch, WGM to ClearTimer on CompareMatch
23   LDI R22,5              ;loads 0000 0101 for TCCR0B
24   OUT 51,R22      ;does not Force CompareMatch, also sets a bit of WGM
25   LDI R23,100      ;loads 100d for OCR0A
26   OUT 54,R23      ;uses to compare with TCNT0 count
27   LDI R24,11      ;loads 0000 1011 for DDRB
28   OUT 23,R24      ;sets PB0,1,2 as outputs
29   OUT 63,R0      ;Clears SREG
30   SEI                      ;enable Global Interrupts
31   LDI R25,159      ;load 0x9F for SPL
32   OUT 61,R25      ;sets SPL to top of SRAM
33   LDI R26,32      ;loads 00010 0000 for MCUCR
34   OUT 53,R26      ;chooses IDLE sleep and enables SleepMode
35   OUT 40,R0      ;clears GTCCR so the T/C should start running
36   RJMP 0      
37   SLEEP      
38   OUT 53,R0      ;disables SleepMode
39   RJMP -6      
40   OUT 53,R0      ;disables SleepMode
41   IN 4,30              ;loads ADCH
42   IN 5,31              ;loads ADCL
43   CPI R31,1              ;ADCH-1 might set CarryFlag
44   BRCS 2              ;rjmp +2 if Cflag set , ADC count <256
45   RETI      
46   NOP      
47   SBI 24,3      
48   NOP      
49   OUT 40,R20      

« Last Edit: October 05, 2024, 11:32:43 am by MathWizard »
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4315
  • Country: us
Re: Questions about AVR sleep mode, interrupts and wake up
« Reply #1 on: October 05, 2024, 03:23:49 am »
Quote
I'm making assembly, then the opcodes, then the intel hex.
Too unreadable for me.
What do you have against using a real assembler, with, like, labels and symbols and such?

 

Offline T3sl4co1l

  • Super Contributor
  • ***
  • Posts: 22436
  • Country: us
  • Expert, Analog Electronics, PCB Layout, EMC
    • Seven Transistor Labs
Re: Questions about AVR sleep mode, interrupts and wake up
« Reply #2 on: October 05, 2024, 06:41:13 am »
Doing it is completely bare assembly, you also need to set stack pointer.

It's possible to do interrupts without register push/pop if you use exclusive sets of registers vs. main(), but you still need to save and restore SREG.

Maybe you're doing that, I don't know, I don't remember the addresses.  Using symbols is so much more descriptive.

The sleep instruction is broken when an interrupt occurs; if your ADC source is set to do this, then the next instruction executed is the interrupt (RJMP and so on), and main() resumes on RETI.  The timer either doesn't break sleep mode at all, or triggers the interrupt -- it's the same action.  But you said that interrupt is RJMP to init?  So it just resets the program.  Maybe that's intended for such a short program, but it would be very unusual for anything more substantial.

Tim
Seven Transistor Labs, LLC
Electronic design, from concept to prototype.
Bringing a project to life?  Send me a message!
 
The following users thanked this post: MathWizard

Online MathWizardTopic starter

  • Super Contributor
  • ***
  • Posts: 1622
  • Country: ca
Re: Questions about AVR sleep mode, interrupts and wake up
« Reply #3 on: October 05, 2024, 11:30:36 am »
Yeah I should have added some comments, I've used ArduinoIDE, but I'm trying to see more what the lower levels are doing, so it's not just a void in my mind, but yeah I want to learn more semiconductor physics too.

But really tho, taxcodes are some complicated, I'm worried people might be trying to hide them in my codes, or do their taxes in a shady way, using my MCU.


OK I'll try and get just the ADC working, or the T/C, or the sleep command, before trying them together. And try something with the stack.

I do see bytes getting written into RAM tho, I need to watch in the simulator, I'm not sure what would be doing that behind the scenes. None of it was around the top for the stack tho.
« Last Edit: October 05, 2024, 11:36:54 am by MathWizard »
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4315
  • Country: us
Re: Questions about AVR sleep mode, interrupts and wake up
« Reply #4 on: October 06, 2024, 06:58:00 am »
Quote
Warning: AVR SLEEP instruction not Fully implemented
That's going to make the simulator pretty useless for evaluating what you're trying to do, unless it does a really good job of documented what "fully" means...
 
The following users thanked this post: MathWizard

Online MathWizardTopic starter

  • Super Contributor
  • ***
  • Posts: 1622
  • Country: ca
Re: Questions about AVR sleep mode, interrupts and wake up
« Reply #5 on: October 06, 2024, 01:11:05 pm »
For the T/C interrupt, I don't get what the TIFR0 reg is doing. I'm mainly just using the ATTiny13A datasheet, not following guides. And it says the default is 0x00.

But on the 2nd instruction, so the MCU starts in the sim, and RJMPS to W10 the EOR, and ALREADY, the OCF0A and OCF0B flags for CompareMatch A,B, are getting set HIGH. But not the TOVF.

So later in the program I set GTCCR to hold reset, TCCR0A,B , OCR0A=100d, and TIMSK0 to only enable ISR for OCF0A.

But then as soon as I enable Interrupts Globally, the TIFR0 already has OCF0A,B set high, so the PC jumps to W6 for the TIM0_COMPA ISR.

So I added a line to set TIFR0 to 0x00, and the sim says it's 0 afterwards, yet again, as soon as do the SEI, even tho TIFR0 is all 0, AND THE GTCCR is still 1000 0001 for holding reset if I understand it correctly....the T/C isn't even running yet.....it still immediately jumps to TIM0_COMPA.


I don't quite get what the datasheet says about setting flags high is the TIFR0. Everything I've read, I think they are active HIGH. Like in this page.
https://web.ics.purdue.edu/~jricha14/Timer_Stuff/TIMSK.htm

Yet the datasheet says
Quote
• Bit 2 – OCF0A: Output Compare Flag 0 A
The OCF0A bit is set when a Compare Match occurs between the Timer/Counter0 and the data
in OCR0A – Output Compare Register0. OCF0A is cleared by hardware when executing the corresponding interrupt handling vector. Alternatively, OCF0A is cleared by writing a logic one to
the flag.
When the I-bit in SREG, OCIE0A (Timer/Counter0 Compare Match Interrupt Enable),
and OCF0A are set, the Timer/Counter0 Compare Match Interrupt is executed.

But an interrupt happens, leading to W6=TIM0_COMPA, when the MCU on it's own, sets both OCF0A/B HIGH on startup for some reason, or when I've set it them to 0, it still happens, while the T/C is held in reset, as soon as I allow interrupts globally.

Now I'm still setting up the ADC for auto-triggering from COMP_A, before setting up the T/C, there I'm setting ADIEnable HIGH, and ADIFlag LOW. I'll try version without all that now.

There has to be datasheets that explain all of this, I'll start checking some of the other ones I have just on the Timer.
But what can be going on ??



But another observation, in the sim, once the interrupt has happened after a SEI on Word35 in my current program, 0x24=36d gets stored to 0x9F, without me doing a PUSH.




Ok I see if I write the TIFR0 flags all high, then they get reset to all low, right after, so I don't have that interrupt problem now. So I'll check the other flags for that issue too.

Now to try getting the SLEEP working.
« Last Edit: October 06, 2024, 02:40:06 pm by MathWizard »
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4315
  • Country: us
Re: Questions about AVR sleep mode, interrupts and wake up
« Reply #6 on: October 06, 2024, 07:10:26 pm »
Quote
30   SEI                      ;enable Global Interrupts
31   LDI R25,159      ;load 0x9F for SPL
32   OUT 61,R25      ;sets SPL to top of SRAM
You should certainly set up the stack BEFORE you enable interrupts.

But the tiny13 is one of the chips that automatically sets the SP to the last memory location, so you don't NEED to set it at all.

(Old Datasheet (7/10) Page 11, section 4.5 "Stack Pointer"):

      This Stack space in the data SRAM is automaticall defined to the last address in SRAM during power on reset.

Quote
in the sim, once the interrupt has happened after a SEI on Word35 in my current program, 0x24=36d gets stored to 0x9F, without me doing a PUSH.
Interrupts work like "rcall", and automatically push the (old) PC at the time of the interrupt (that's why the stack setup should happen before SEI)

« Last Edit: October 06, 2024, 07:18:32 pm by westfw »
 
The following users thanked this post: MathWizard

Online MathWizardTopic starter

  • Super Contributor
  • ***
  • Posts: 1622
  • Country: ca
Re: Questions about AVR sleep mode, interrupts and wake up
« Reply #7 on: October 10, 2024, 08:12:18 pm »
OK so when this SimulIDE version says SLEEP is not fully IMPLEMENTED, they mean the program/developers, have not finished making the SLEEP simulation, part of their program.

I went off and fleshed out some stuff I'm doing with the ADC, and tried the sleep again last night, and started having a deja-vu about some other time, and some other problem where it was the sim or hardware that can't do want I want.

I actually bought the Oshon AVR simulator, and it just stops at the sleep command, and never goes to an interrupt. I need to check the sim settings, and their documentation. Otherwise I'll just change the SLEEP to some count down or whatever, while waiting the few cycles for the ADC.


But now I'm pretty sure I get the basics of the interrupts and returns from them, so I'm going to try my ADC program on a real chip. In the ADC ISR, I'm storing data each time, then once I get enough, it also calculates a bunch of averages. So I'll add an LED on/off and I should know.

Otherwise, I'll get use sleep in a real C IDE like Arduino, and see whats in the resultant assembly code.


I want to try outputting some data for 7-segment LED's, either doing it directly with multiplexing a few port pins, or outputting serial data to shift register's or a CD4026. I might even try doing basic I2C, and send LED data that way.

But yeah, I really don't know how much memory all that would take, or how much RAM it would take.

Soon enough I'll move back to C and those IDE's, and use library's for complex stuff like I2C.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf