![]() |
![]() |
#1 |
<optimized out>
Join Date: Sep 2020
Location: <optimized out>
Posts: 321
|
CIA TOD Rollover
Editing post as my problem has now changed.
Can anyone explain why I get occasional silly values when reading the CIA B TOD clock? When reading it at the start and end of a function, I occasionally get bad values, with the finish time being less than the end time, or even the finish time being zero sometimes. More details in post 4 below. Last edited by Ernst Blofeld; 13 January 2021 at 14:38. |
![]() |
![]() |
#2 |
Registered User
Join Date: Jun 2016
Location: europe
Posts: 1,062
|
Read once in this order: high (latch activated), middle, low byte (latch deactivated).
|
![]() |
![]() |
#3 |
<optimized out>
Join Date: Sep 2020
Location: <optimized out>
Posts: 321
|
|
![]() |
![]() |
#4 |
<optimized out>
Join Date: Sep 2020
Location: <optimized out>
Posts: 321
|
It's strange though, that I'm occasionally getting start times that are greater than my end times...
Code:
In Profiler_EndFunction: startTime 65532 > finishTime 0 In Profiler_EndFunction: startTime 192250 > finishTime 192000 In Profiler_EndFunction: startTime 258555 > finishTime 258304 (edit - the low byte of all the finishTimes is zero, if that's a clue) Code:
ULONG GetCurrentTime(void) { ULONG hi = ciab->ciatodhi; // latch activated ULONG mid = ciab->ciatodmid; ULONG low = ciab->ciatodlow; // latch deactivated return (hi << 8 | mid) << 8 | low; } volatile struct CIA * ciab = CIAB;where CIAB is #define CIAB ((volatile struct CIA *) 0xbfd000UL) The generated assembly looks sensible, to me: Code:
00002c0a <GetCurrentTime>: ULONG GetCurrentTime(void) { 2c0a: move.l d2,-(sp) ULONG hi = ciab->ciatodhi; // latch activated 2c0c: move.b bfda00 <gcc8_c_support.c.62367fe7+0xbdadad>,d0 ULONG mid = ciab->ciatodmid; 2c12: move.b bfd900 <gcc8_c_support.c.62367fe7+0xbdacad>,d2 ULONG low = ciab->ciatodlow; // latch deactivated 2c18: move.b bfd800 <gcc8_c_support.c.62367fe7+0xbdabad>,d1 ULONG hi = ciab->ciatodhi; // latch activated 2c1e: andi.l #255,d0 return (hi << 8 | mid) << 8 | low; 2c24: lsl.l #8,d0 2c26: or.b d2,d0 2c28: lsl.l #8,d0 } 2c2a: or.b d1,d0 2c2c: move.l (sp)+,d2 2c2e: rts Last edited by Ernst Blofeld; 13 January 2021 at 14:20. |
![]() |
![]() |
#5 |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,570
|
Do you have OS running? TOD is reset periodically by system.
|
![]() |
![]() |
#6 |
<optimized out>
Join Date: Sep 2020
Location: <optimized out>
Posts: 321
|
No, I've taken over the system, I believe correctly. The only interrupts that should be running are a copper one for my screen flipping and a ports one for the keyboard, which I believe only uses cia a.
Code:
void TakeSystem(void) { Forbid(); // forbid multitasking ActiView = GfxBase->ActiView; // save current view // Save current interrupts and DMA settings. systemADKCON = custom->adkconr; systemINTENA = custom->intenar; systemDMACON = custom->dmaconr; // The VBR is stored in a different place on 68010s and above. if ((SysBase->AttnFlags & AFF_68010)) { UWORD getVBR [] = { 0x4e7a, 0x0801, // movec.l vbr, d0 0x4e73 // rte }; VBR = (APTR *) Supervisor((void *) getVBR); } // Save system interrupt handers. for (int i = 0; i < 6; i++) systemInterruptHandlers[i] = VBR[25 + i]; WaitForVerticalBlank(); WaitForVerticalBlank(); custom->dmacon = DMAF_MASTER | DMAF_BLITHOG | DMAF_ALL; // clear all DMA channels // Set all colours to black. for (int a = 0; a <= 31; a++) custom->color[a] = 0x000; LoadView(NULL); // has side effect of enabling VERTB WaitTOF(); WaitTOF(); WaitForVerticalBlank(); WaitForVerticalBlank(); OwnBlitter(); WaitForBlitter(); custom->intena = INTF_INTEN | INTF_ALL; // disable all interrupts custom->intreq = INTF_INTEN | INTF_ALL; // clear any interrupts that were pending } |
![]() |
![]() |
#7 |
<optimized out>
Join Date: Sep 2020
Location: <optimized out>
Posts: 321
|
At the moment I don't believe this is a problem with my code, because when the problem occurs the low byte of the is always zero. I could imagine something overwriting the variable on the stack, but only the lowest byte?
I've changed the code that detects the problem to the following: Code:
if (startTime > finishTime) * (WORD *) 0xdff180UL = 0xfff; I've attached the executable in case anyone wants to have a look. |
![]() |
![]() |
#8 |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,570
|
ALARM bit is set (CRB bit 7).
Reading TOD when ALARM bit is set won't latch the TOD but returns "live" TOD. (EDIT: which is undocumented feature) |
![]() |
![]() |
#9 |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 54
Posts: 4,491
|
I had just found this: https://eab.abime.net/showpost.php?p...8&postcount=14
But Toni already posted ![]() Last edited by ross; 13 January 2021 at 19:43. Reason: removed a silly question :D |
![]() |
![]() |
#10 | |
<optimized out>
Join Date: Sep 2020
Location: <optimized out>
Posts: 321
|
Quote:
I'm now clearing the ALARM bit, Code:
ciab->ciacrb = CIACRBF_ALARM; |
|
![]() |
![]() |
#11 |
<optimized out>
Join Date: Sep 2020
Location: <optimized out>
Posts: 321
|
Like this?
Code:
ciab->ciacrb &= ~CIACRBF_ALARM; |
![]() |
![]() |
#12 |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,570
|
Most CIA registers are normal read/write. Interrupt register is special.
|
![]() |
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
![]() |
||||
Thread | Thread Starter | Forum | Replies | Last Post |
Possible CIA problem | bwldrbst | support.Hardware | 8 | 05 July 2020 09:29 |
CIA interrupts... | bloodline | Coders. System | 6 | 18 January 2018 10:33 |
CIA-A TOD clock source with genlock | mark_k | support.WinUAE | 25 | 13 February 2014 20:30 |
example of a CIA timer interrupt in assembler using cia.resource | Apollo | Coders. Asm / Hardware | 3 | 05 July 2013 08:40 |
CIA test | Toni Wilen | Coders. General | 13 | 03 March 2007 22:14 |
|
|