AMcTools Forum 
  HomeHelpSearchLogin  
 
Pages: 1 2 
Send Topic Print
ATmega168 Peripheral Models (Read 42770 times)
Milwaukee
YaBB Newbies
*
Offline

I Love Coding!

Posts: 22

Gender: male
Re: ATmega168 Peripheral Models
Reply #15 - 01/06/11 at 10:24:48
 
Hi,
I tried to use the timer model. Well, it seems to be not working as it should be.
Following you see the code to test the model. When you step through the code you will see that the counter TCNT0 doesn't behave like it should be. It seems  that the counter increments by 2 and not by 1.

[font=Courier New]
.def temp = r16
.def leds = r17

.org 0x0000
       rjmp    main              ; Reset Handler
.org OC0Aaddr      
       rjmp    timer0_CompA      ; Timer/Counter0 Compare Match A = 0x0020

main:
       ; Initialize Stackpointer
       ldi     temp, HIGH(RAMEND)
       out     SPH, temp
       ldi     temp, LOW(RAMEND)
       out     SPL, temp
     
       ldi     temp, 0xFF            ; Output Port B
       out     DDRB, temp
       ldi     leds, 0x00

       ; Initialize timers
       ldi     temp, (WGM01<<1)      ; Modus: Clear Timer on Compare Match
       out     TCCR0A, temp
       ldi     temp, (1<<CS01)       ; Interbal/8
       out     TCCR0B, temp
       ldi     temp, (1<<OCF0A)      ; Timer/Counter0 Compare Match A
       sts     TIMSK0, temp
       ldi     temp, 8               ; Compare Match Value
       out     OCR0A, temp

       sei

loop:   rjmp    loop               ; Endless loop

timer0_CompA:                      ; Timer/Counter0 Compare ISR
       out     PORTB, leds
       inc     leds
       reti
[/font]

Did already someone made a work around in the model?
Thx in advance! :-)
Back to top
 
 
  IP Logged
Milwaukee
YaBB Newbies
*
Offline

I Love Coding!

Posts: 22

Gender: male
Re: ATmega168 Peripheral Models
Reply #16 - 01/06/11 at 14:35:13
 
Hi,
So far I found the failure. The On_Remind_Me() function will be called to early for 2 cycle commands.  :-?
So, I wrote a work around in the model (search for WA_aim_io_cycles).
Is the issue known already?
Back to top
 
  IP Logged
ThVortex
Global Moderator
*****
Offline



Posts: 160
Austin, TX, USA
Gender: male
Re: ATmega168 Peripheral Models
Reply #17 - 01/08/11 at 06:33:25
 
Thank you for doing such detailed testing on the component and for even writing a patch to fix the problem.

Yes, this is definitely a problem which I didn't notice before. The problem appears to be with how GET_MICRO_INFO(INFO_CPU_CYCLES) interacts with multi-cycle instructions like "rjmp". It seems that the INFO_CPU_CYCLES count is not incremented until AFTER the instruction has finished executing. When I single stepped through your code, what I noticed is that "rjmp" begins at cycle 23 and finishes at 25. Meanwhile, the timer has scheduled a clock tick for cycle 24. However, when On_remind_me() runs at cycle 24, INFO_CPU_CYCLES still reports cycle 23 and causes the component to schedule a duplicate tick.

I will add your work around to my source repository. I made two small changes to it. First, the original fix will cause a compile error for TIMER2 because of this "else if" that would appear immediately after the "else" from the work around:
[code]
#ifdef TIMER_2
  else if(Async == ASY_32K) {[/code]
The second change will seem a little confusing. I changed the [tt]WA_aim_io_cycles[/tt] variable to an unsigned integer, and I changed the following line:
[code]if(WA_aim_io_cycles >= Get_io_cycles())[/code] to instead be:
[code]if(WA_aim_io_cycles - Get_io_cycles() < 0x80000000)[/code]

These two if statements are equivalent, except the second one will continue to work even if one of the unsigned 32 bit values has wrapped around. And yes, I know it's very unlikley the cycle count will ever wrap for anyone. You would have to run VMLAB for a really long time.

I'm attaching the final timer_168.cpp code that I will drop into my repository. Please verify that your AVR code increments the timer correctly now.
Back to top
 
WWW   IP Logged
Milwaukee
YaBB Newbies
*
Offline

I Love Coding!

Posts: 22

Gender: male
Re: ATmega168 Peripheral Models
Reply #18 - 01/08/11 at 21:33:44
 
Thanks you ThVortex for the correction.
I wrote the first correction in order to be able to continue the verifying. You're absolutely right, nice work. :-)
... but I'm sorry to say, I  found another small mistake. Here my sniped code to verify:
[code]
       ldi     temp, (1<<CS01)       ; Internal/8
       out     TCCR0B, temp          ; Start Counter
       sei
       ;         AVR CORE      Timer Model of ATmega168b
       nop  ;  1
       nop  ;  2
       nop  ;  3
       nop  ;  4
       nop  ;  5
       nop  ;  6               TCNT0 = 1
       nop  ;  7 TCNT0 = 1
[/code]

The model is one cycle to early. ... I'm guessing this relates to the problem with the function GET_MICRO_INFO(INFO_CPU_CYCLES).
Well, for the most application this won't matter.  ;-)
Back to top
 
 
  IP Logged
ThVortex
Global Moderator
*****
Offline



Posts: 160
Austin, TX, USA
Gender: male
Re: ATmega168 Peripheral Models
Reply #19 - 01/09/11 at 06:42:48
 
Keep in mind that the timer prescaler is free running even while the timer is disabled. That's why the very first timer tick may not come exactly after 8 cycles. However, every other tick thereafter should be 8 cycles apart.

If you need the timer to start at a predictable time, then you'll have to use the PSRSYNC and maybe the TSM bits in GTCCR to force a reset of the prescaler.
Back to top
 
 
WWW   IP Logged
Milwaukee
YaBB Newbies
*
Offline

I Love Coding!

Posts: 22

Gender: male
Re: ATmega168 Peripheral Models
Reply #20 - 01/09/11 at 13:41:54
 
Ohhh, I didn't think about that. So, yes, you're absolutely right! ... and the model works fine now. :-)
Back to top
 
 
  IP Logged
ThVortex
Global Moderator
*****
Offline



Posts: 160
Austin, TX, USA
Gender: male
Re: ATmega168 Peripheral Models
Reply #21 - 01/10/11 at 06:46:30
 
I have an improved fix for you. The original fix broke when executing a multi-cycle instruction and using the direct clock for the timer (Internal / 1). For example, "rjmp" takes two cycles but the timer would only increment once.

This new fix should take care of both cases. Basically, when calling Go() from On_remind_me() we avoid calling INFO_CPU_CYCLES and assume that WA_aim_io_cycles is the current cycle count for the purpose of scheduling a new timer tick.
Back to top
 
WWW   IP Logged
Milwaukee
YaBB Newbies
*
Offline

I Love Coding!

Posts: 22

Gender: male
Re: ATmega168 Peripheral Models
Reply #22 - 01/10/11 at 21:37:14
 
Thank you. I added the work around (interrupt handling failure) to the declaration of the ATmega168 and the regarding timer0. I didn't applied the work around to other timers so far.
Back to top
« Last Edit: 01/11/11 at 07:01:32 by Milwaukee »  
  IP Logged
ThVortex
Global Moderator
*****
Offline



Posts: 160
Austin, TX, USA
Gender: male
Re: ATmega168 Peripheral Models
Reply #23 - 02/04/11 at 18:44:11
 
I've applied the workarounds to all the timer models, and I have updated version of the DLLs available [url=http://thvortex-vmlab.googlecode.com/files/useravr-0.6.1.zip]for download[/url].

I moved the TIMSK and TIFR registers into the timer peripherals to work around the flag bit issue that forum user Milwaukee discovered. I also worked around an issue with the interrupt mask bits. Basically, when VMLAB is handling the mask registers, interrupts will remain enabled after a CPU only reset even through the mask register resets to all 0s. A CPU only reset occurs with a logic 0 on the RESET pin or by clicking on the "Force RESET" buttons in the "Special Registers" section of the GUI.
Back to top
 
 
WWW   IP Logged
Pages: 1 2 
Send Topic Print