View previous topic :: View next topic |
Author |
Message |
Plons
Joined: 24 May 2005 Posts: 435 Location: Hilversum - The Netherlands
|
Posted: Sat Feb 27, 2016 6:45 pm Post subject: An assembler puzzle |
|
|
Hi folks,
I need your advice. This problem has been nagging me for a day:
Timer2 generates an interrupt every millisecond.
The interrupt handler is written in assembler, for speed purposes.
All used registers are pushed and popped.
The odd thing is that the variable Qsec_counter should increment every 256ms. But it doesn't.
I must be overlooking something but cannot find what.
I need other eyes to have a look at the problem.
Code: |
'Ms_qsec_ticker_M16forum.bas
'Ms ticks for AVR's old style like Mega8, 16, 32
'Problem: Qsec_counter is not incremented : why ? 2079beta
$baud = 9600
$crystal = 8000000
$regfile = "m16def.dat"
$hwstack = 40
$swstack = 40
$framesize = 40
'Timer2 is the system-counter
'Mode2, CTC, /32 prescaler, top=OCR2, top=249
Tccr2 = &B00001011 'for M16 @ 8MHz
Ocr2 = 249
Enable Oc2
On Oc2 Ms_int Nosave '1kHz
Dim Ms_counter As Byte 'increments on every ms
Dim Qsec_counter As Byte At Ms_counter + 1 'is incremented every ~quarter of a second
Dim Ms_word As Word At Ms_counter Overlay 'is a 16bit ms counter
Dim Ms_flags As Byte
'Making ms handler using one byte for all flags
'bit 0: set every ms
'bit 7: set every quarter of a second: Qsec1. Set on overflow of Ms_counter
'bit 6: set every quarter of a second, but interleaved with Qsec1: Qsec2. Set on Ms_counter passing 128
Ms_flag Alias Ms_flags.0
Qsec1_flag Alias Ms_flags.7
Qsec2_flag Alias Ms_flags.6
'For test purposes
Scope Alias Portd.6
Set Ddrd.6
Enable Interrupts
Do
'Millisecond tasks
If Ms_flag = 1 Then
Reset Ms_flag
End If
'Quarter of a second Task Qsec1
If Qsec1_flag = 1 Then
Reset Qsec1_flag
Print Qsec_counter
End If
'Quarter of a second Task Qsec2
'
If Qsec2_flag = 1 Then
Reset Qsec2_flag
End If
Loop
End
'######################### Interrupts ##############################################################
Ms_int: 'OC2 kicks in every msec
$asm
push xl
in xl,sreg
push xl
push xh
push zl
sbi portd,6 'scope
'set ms_flag == bit 0
lds xh,{ms_flags}
sbr xh,$01
'increment ms_counter
lds xl,{ms_counter}
inc xl
brne check_qsec2
'set qsec1-flag == bit 7
sbr xh,$80
'increment Qsec_counter
lds zl,{qsec_counter} 'increments every 256 ms
inc zl
Check_qsec2:
cpi xl, 128 'halfway the qsec?
brne ms_int_done
'set qsec2-flag == bit 6
sbr xh,$40
Ms_int_done:
sts {qsec_counter},zl 'write back qsec counter
sts {ms_counter},xl 'write back millisecond counter
sts {ms_flags},xh 'write (updated) flags
cbi portd,6 'scope
pop zl
pop xh
pop xl
Out Sreg , Xl
pop xl
$end Asm
Return |
In desperation I moved the line Code: | sts {qsec_counter},zl 'write back qsec counter |
to right after the Inc Zl statement. Then it works.
But why doesn't the code work as shown ? Zl is not touched AFAIK between the Inc Zl statement and Sts {qsec_counter},zl
Your help is appreciated.
(BASCOM-AVR version : 2.0.7.9b , Latest : 2.0.7.8 ) _________________ Bascom AVR ver 2.0.8.6
Dragon-lair: http://www.aplomb.nl/TechStuff/Dragon/Dragon.html
"leef met vlag en wimpel, maar hou het simpel" |
|
Back to top |
|
|
MWS
Joined: 22 Aug 2009 Posts: 2262
|
Posted: Sat Feb 27, 2016 7:42 pm Post subject: Re: An assembler puzzle |
|
|
Plons wrote: | Hi folks,
I need your advice.
Code: | Dim Ms_counter As Byte 'increments on every ms
Dim Qsec_counter As Byte At Ms_counter + 1 'is incremented every ~quarter of a second
Dim Ms_word As Word At Ms_counter Overlay 'is a 16bit ms counter
Dim Ms_flags As Byte |
|
You really want the asm-guy's help? LOL
Think you don't like me, so next time you have to specify the group better where you send your request to.
This time's too late.
First, dimensioning works, but is not very clean, better is:
Code: | Dim Ms_word As Word
Dim Ms_counter As Byte At Ms_word Overlay
Dim Qsec_counter As Byte At Ms_word + 1 Overlay
Dim Ms_flags As Byte |
Second, you need to learn how to use the simulator.
Then with a simple
Code: | Do
Gosub Ms_int
Loop |
you can test your ISR.
Your mistake is simple, you save qsec_counter all the time, but you only selectively load it, and that's when ms_counter overflows.
For all other conditions, ZL contains at save-time a random value, which overwrites qsec_counter after next call of the ISR, even that it was incremented by one. |
|
Back to top |
|
|
Plons
Joined: 24 May 2005 Posts: 435 Location: Hilversum - The Netherlands
|
Posted: Sat Feb 27, 2016 10:45 pm Post subject: |
|
|
Quote: | Think you don't like me, so next time you have to specify the group better where you send your request to. | Like "Anyone but MWS" ? No chance ! I see no reason for excluding you. Sometimes your replies here can be harsh. AFAIK I made a remark about that, once, in a recent thread. Apparently enough for you to think I don't like you.
Thanks for pointing me out where my blind spot was. Much appreciated.
Nard _________________ Bascom AVR ver 2.0.8.6
Dragon-lair: http://www.aplomb.nl/TechStuff/Dragon/Dragon.html
"leef met vlag en wimpel, maar hou het simpel" |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You cannot download files in this forum
|
|