View previous topic :: View next topic |
Author |
Message |
CBailey
Joined: 07 May 2015 Posts: 102
|
Posted: Tue Apr 12, 2016 5:32 pm Post subject: Can't get interrupts working |
|
|
Below is a snippet of Clock code. It works fine in the simulator, but on my AT90USB1286, it never runs the ISR code. Is there a fuse bit I might have missed? Do I just have a bad chip?
Quote: |
'-------------------------------------------------------------------------------
' @16MHz
' Const Reload = 15625 '= 1s
const reload = 100
$crystal = 16000000
' choose the micro you use
$regfile = "usb1286.dat"
$hwstack = 40
$swstack = 40
$framesize = 40
Config CLOCKDIV = 1
$baud = 19200
'-------------------------------------------------------------------------------
' Config Clock
'-------------------------------------------------------------------------------
Dim Local_time As Long
Dim New_second As Byte
Config Timer1 = Timer , Prescale = 1024 , Clear timer = 1
Ocr1ah = High(reload)
Ocr1al = Low(reload)
Tccr1a = 0
Set Tccr1b.3
On Compare1a Isr_timer1
Enable Compare1a 'enable timer1 interrupt (Clock Interrupt)
gosub Isr_timer1
Enable Interrupts
do
if New_second > 0 then
'... do something every second
Print "We got here"
New_second = 0
endif
print timer1
loop
end
Isr_timer1:
Print "We got to the ISR"
pushall
Incr Local_time
New_second = 1
popall
Return
| [/quote]
(BASCOM-AVR version : 2.0.7.8 ) |
|
Back to top |
|
|
MWS
Joined: 22 Aug 2009 Posts: 2262
|
Posted: Tue Apr 12, 2016 7:24 pm Post subject: Re: Can't get interrupts working |
|
|
CBailey wrote: | Is there a fuse bit I might have missed? Do I just have a bad chip? |
You have a whole lot'a bunch of issues.
No issue:
Code: | const reload = 100
Ocr1ah = High(reload)
Ocr1al = Low(reload) |
but easier this way:
Code: | const reload = 100
Ocr1a = reload |
This is enough:
Code: | Config Timer1 = Timer , Prescale = 1024 , Clear timer = 1 |
While this is useless:
Code: | Tccr1a = 0
Set Tccr1b.3 |
Here:
Code: | Print "We got to the ISR" |
you waste a minimum of:
19 chars (incl. CR/LF) * 10 (1stb/8dtab/1stpb) * 833 cycles per sent bit (@19200 baud) = 158270 cycles
while the ISR fires every: (reload + 1) * 1024 = 103424 cycles.
Your actual problem however is:
Code: | pushall
' ...
popall |
in combination with:
Code: | $hwstack = 40
$swstack = 40
$framesize = 40 |
as registers are already and automatically saved. You save them a second time, which uses up more stack than you have defined, this results in a stack overflow, invalid return address from ISR and following crash. |
|
Back to top |
|
|
CBailey
Joined: 07 May 2015 Posts: 102
|
Posted: Tue Apr 12, 2016 8:15 pm Post subject: |
|
|
Thanks for the response!
I made the changes you recommended. I completely removed defining stacks, and removed pushall/popall. I removed the print within the ISR. However, it's still not working. |
|
Back to top |
|
|
MWS
Joined: 22 Aug 2009 Posts: 2262
|
Posted: Tue Apr 12, 2016 8:50 pm Post subject: |
|
|
CBailey wrote: | I completely removed defining stacks |
Why? You should try to increase, but not remove them. As then the IDE's stack settings apply, which set up likely even smaller stacks, thus resulting in a stack overflow. |
|
Back to top |
|
|
CBailey
Joined: 07 May 2015 Posts: 102
|
Posted: Tue Apr 12, 2016 9:01 pm Post subject: |
|
|
Ok, I re-enabled, and then incremented them up by 20, until I got to 200 at each. Still made no difference. The counter does reset and start from 0 when it gets to the reload value, but the ISR never runs. |
|
Back to top |
|
|
MWS
Joined: 22 Aug 2009 Posts: 2262
|
Posted: Tue Apr 12, 2016 9:18 pm Post subject: |
|
|
Leave out the print from the ISR and toggle a pin instead.
An AVR-Studio 4 simulation showed the code working and ISR executed.
In case of doubt, post your actual code. |
|
Back to top |
|
|
CBailey
Joined: 07 May 2015 Posts: 102
|
Posted: Tue Apr 12, 2016 9:26 pm Post subject: |
|
|
Well, I left out the print from the isr a while ago. I don't have anything handy at the moment to monitor a pin, so I was just monitoring the variable that should be set by the isr:
Quote: |
if New_second > 0 then
'... do something every second
Print "We got here *******************************************"
New_second = 0
endif
|
|
|
Back to top |
|
|
MWS
Joined: 22 Aug 2009 Posts: 2262
|
Posted: Tue Apr 12, 2016 9:46 pm Post subject: |
|
|
One idea: this chip can relocate the interrupt vectors to the boot section, if there's a bootloader active, this may be the case.
Try: MCUCR.IVSEL = 0 early in your code.
Edit, needs a special procedure:
MCUCR = Bits (IVCE)
MCUCR = 0
Edit II:
Use Bascom's included function: CONFIG INTVECTORSELECTION |
|
Back to top |
|
|
CBailey
Joined: 07 May 2015 Posts: 102
|
Posted: Tue Apr 12, 2016 11:51 pm Post subject: |
|
|
I think you may be right. I've got a bootloader (FLIP I believe). Now I just have to figure out what to do |
|
Back to top |
|
|
CBailey
Joined: 07 May 2015 Posts: 102
|
Posted: Wed Apr 13, 2016 5:58 am Post subject: |
|
|
I've been looking, but I must be looking in the wrong place. I'm unsure of the offset address for $LOADER, or any parameters for CONFIG INTVECTORSELECTION. I tried different variations, based on what I could find, but it either didn't work, or the program wouldn't run at all. |
|
Back to top |
|
|
MWS
Joined: 22 Aug 2009 Posts: 2262
|
Posted: Wed Apr 13, 2016 6:18 am Post subject: |
|
|
You can print the value of IVSEL in your program to check it. |
|
Back to top |
|
|
CBailey
Joined: 07 May 2015 Posts: 102
|
Posted: Wed Apr 13, 2016 5:44 pm Post subject: |
|
|
IVSEL was 1 |
|
Back to top |
|
|
MWS
Joined: 22 Aug 2009 Posts: 2262
|
Posted: Wed Apr 13, 2016 10:07 pm Post subject: |
|
|
CBailey wrote: | IVSEL was 1 |
Then you should set it to 0.
Data sheet:
Quote: | When the IVSEL bit in MCUCR is set, Interrupt Vectors will be moved to the start of the Boot Flash Section. The address of each Interrupt Vector will then be the address in this table added to the start address of the Boot Flash Section. |
Boot Flash Section = boot loader memory.
And now you know, why your ISR's aren't executed, because Bascom sets them up correctly at Application Section.
The Config IntVectorSelection should do, but even then, you can try this adapted sample code from the data sheet, put it in front of your code:
Code: | !IN r16, MCUCR
!mov r17, r16
!ori r16, 2^IVCE
!out MCUCR, r16
!ANDI r17, &hFF - 2^IVSEL
!out MCUCR , r17 |
Edit:
Quote: | The Config IntVectorSelection should do,... |
Also checked, and yes:
Code: | Config IntVectorSelection = normal |
does exactly the same as above ASM code. |
|
Back to top |
|
|
GerTronic
Joined: 17 Dec 2012 Posts: 7
|
Posted: Wed Apr 13, 2016 11:08 pm Post subject: |
|
|
Try omitting the gosub to the timer isr in:
Code: |
Enable Compare1a 'enable timer1 interrupt (Clock Interrupt)
gosub Isr_timer1
Enable Interrupts
do
|
The isr ends with a RETI requiring a return addres from the stack. The stack is empty at that moment, the RETI gets 0x0000, so the controller reboots.
Regards,
Gert |
|
Back to top |
|
|
MWS
Joined: 22 Aug 2009 Posts: 2262
|
Posted: Wed Apr 13, 2016 11:26 pm Post subject: |
|
|
GerTronic wrote: | The isr ends with a RETI requiring a return addres from the stack. |
The difference of RET and RETI isn't big, only the latter (re-)enables global interrupts.
Quote: | The stack is empty at that moment |
That's wrong, the gosub pushed an address to stack, the RETI returns to the address after gosub.
Only after RETI interrupts are globally enabled, while not explicitely done by a SEI and maybe not desired at this time in code. |
|
Back to top |
|
|
|