English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Asm / Hardware

 
 
Thread Tools
Old 25 March 2020, 17:55   #21
phx
Natteravn
 
phx's Avatar
 
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,496
@Bruce: You really have to relax! What's the reason for your harsh tone in most discussions? Did Saimo do anything to you? Is it your ROM code he is talking about?
phx is offline  
Old 27 March 2020, 00:46   #22
saimo
Registered User
 
saimo's Avatar
 
Join Date: Aug 2010
Location: Italy
Posts: 787
Back from a little break (dedicated, among other things, to [ Show youtube player ], which provided me with some relaxing distraction from this matter).

I looked again and at a bit further into the log...
Code:
                                                SCL   SDA   operation   cycle
-----------------------------------------------------------------------------

* INITIALIZE

28-077 [98 062-111]: Direction write: 00->c0    o     o
28-077 [98 062-111]: Data write: c0->c0 (c0)    1     1

* START

28-077 [98 108-111]: I2C START
28-077 [98 108-111]: Data write: c0->80 (80)    1     0     start

* ADDRESS MEMORY (for write)

28-077 [98 167-111]: Data write: 80->00 (00)    0     0                 1v
28-077 [98 221-111]: Data write: 00->40 (40)    0     1     
28-077 [98 041-112]: Data write: 40->c0 (c0)    1     1     send 1      1^
28-077 [98 074-112]: Data write: c0->40 (40)    0     1
28-077 [98 104-112]: Data write: 40->00 (00)    0     0
28-077 [98 134-112]: Data write: 00->80 (80)    1     0     send 0      2^
28-077 [98 154-112]: Data write: 80->00 (00)    0     0
28-077 [98 188-112]: Data write: 00->40 (40)    0     1
28-077 [98 219-112]: Data write: 40->c0 (c0)    1     1     send 1      3^
28-077 [98 012-113]: Data write: c0->40 (40)    0     1
28-077 [98 046-113]: Data write: 40->00 (00)    0     0
28-077 [98 073-113]: Data write: 00->80 (80)    1     0     send 0      4^
28-077 [98 102-113]: Data write: 80->00 (00)    0     0
28-077 [98 132-113]: Data write: 00->00 (00)    0     0
28-077 [98 162-113]: Data write: 00->80 (80)    1     0     send 0      5^
28-077 [98 187-113]: Data write: 80->00 (00)    0     0     
28-077 [98 217-113]: Data write: 00->00 (00)    0     0
28-077 [98 020-114]: Data write: 00->80 (80)    1     0     send 0      6^
28-077 [98 040-114]: Data write: 80->00 (00)    0     0
28-077 [98 074-114]: Data write: 00->00 (00)    0     0
28-077 [98 101-114]: Data write: 00->80 (80)    1     0     send 0      7^
28-077 [98 130-114]: Data write: 80->00 (00)    0     0
28-077 [98 160-114]: Data write: 00->00 (00)    0     0
28-077 [98 190-114]: Data write: 00->80 (80)    1     0     send 0      8^

* GET ACK

28-077 [98 218-114]: Direction write: c0->80    o     i
28-077 [98 218-114]: Data write: 80->00 (40)    0     *                 9v

28-077 [98 041-115]: I2C device address 0xa0

28-077 [98 041-115]: Data write: 40->80 (c0)    1     *                 9^
28-077 [98 074-115]: Direction read: 80         o     i     
28-077 [98 074-115]: Data read: 00              *     0     get ACK

* ???

28-077 [98 082-115]: Data write: c0->00 (40)    0     *     ?           10v
28-077 [98 093-115]: Data write: 40->00 (40)    0     *     ?

* ADDRESS OFFSET

28-077 [98 128-115]: Direction write: 80->c0    o     o     
28-077 [98 128-115]: Data write: 40->00 (00)    0     0
28-077 [98 165-115]: Data write: 00->80 (80)    1     0                 10^
28-077 [98 198-115]: Data write: 80->00 (00)    0     0
28-078 [98 005-116]: Data write: 00->00 (00)    0     0
28-078 [98 032-116]: Data write: 00->80 (80)    1     0                 11
28-078 [98 061-116]: Data write: 80->00 (00)    0     0                 
28-078 [98 091-116]: Data write: 00->00 (00)    0     0                 
28-078 [98 121-116]: Data write: 00->80 (80)    1     0                 12
28-078 [98 146-116]: Data write: 80->00 (00)    0     0                 
28-078 [98 176-116]: Data write: 00->00 (00)    0     0                 
28-078 [98 206-116]: Data write: 00->80 (80)    1     0                 13
28-078 [98 226-116]: Data write: 80->00 (00)    0     0                 
28-078 [98 033-117]: Data write: 00->00 (00)    0     0                 
28-078 [98 060-117]: Data write: 00->80 (80)    1     0                 14
28-078 [98 089-117]: Data write: 80->00 (00)    0     0                 
28-078 [98 119-117]: Data write: 00->00 (00)    0     0                 
28-078 [98 149-117]: Data write: 00->80 (80)    1     0                 15
28-078 [98 174-117]: Data write: 80->00 (00)    0     0                 
28-078 [98 204-117]: Data write: 00->00 (00)    0     0                 
28-078 [98 007-118]: Data write: 00->80 (80)    1     0                 16
28-078 [98 027-118]: Data write: 80->00 (00)    0     0                 
28-078 [98 061-118]: Data write: 00->00 (00)    0     0                 
28-078 [98 088-118]: Data write: 00->80 (80)    1     0                 17

28-078 [98 170-118]: I2C device address 0x00 (Address 0000)

* GET ACK

28-078 [98 119-118]: Direction write: c0->80    o     i
28-078 [98 119-118]: Data write: 80->00 (40)    0     0
28-078 [98 170-118]: Data write: 40->80 (c0)    1     0                 18

28-078 [98 207-118]: Direction read: 80
28-078 [98 207-118]: Data read: 00              0     0     get ACK


* RESTART

28-078 [98 211-118]: Data write: c0->00 (40)    0     *                 19v
28-078 [98 001-119]: Direction write: 80->c0    o     o
28-078 [98 001-119]: Data write: 40->c0 (c0)    1     1                 19^ extra cycle
28-078 [98 047-119]: Data write: c0->80 (80)    1     0
28-078 [98 047-119]: I2C START

* ADDRESS MEMORY (for read)

28-078 [98 101-119]: Data write: 80->00 (00)    0     0                 20v
28-078 [98 135-119]: Data write: 00->40 (40)    0     1
28-078 [98 182-119]: Data write: 40->c0 (c0)    1     1                 20^
28-078 [98 215-119]: Data write: c0->40 (40)    0     1                 21v
28-078 [98 018-120]: Data write: 40->00 (00)    0     0                 
28-078 [98 048-120]: Data write: 00->80 (80)    1     0                 21^
28-078 [98 068-120]: Data write: 80->00 (00)    0     0                 22v
28-079 [98 102-120]: Data write: 00->40 (40)    0     1
28-079 [98 133-120]: Data write: 40->c0 (c0)    1     1                 22^
28-079 [98 153-120]: Data write: c0->40 (40)    0     1                 23v
28-079 [98 187-120]: Data write: 40->00 (00)    0     0
28-079 [98 214-120]: Data write: 00->80 (80)    1     0                 23^
28-079 [98 016-121]: Data write: 80->00 (00)    0     0                 24v
28-079 [98 046-121]: Data write: 00->00 (00)    0     0
28-079 [98 076-121]: Data write: 00->80 (80)    1     0                 24^
28-079 [98 101-121]: Data write: 80->00 (00)    0     0                 25v
28-079 [98 131-121]: Data write: 00->00 (00)    0     0
28-079 [98 161-121]: Data write: 00->80 (80)    1     0                 25^
28-079 [98 181-121]: Data write: 80->00 (00)    0     0                 26v
28-079 [98 215-121]: Data write: 00->00 (00)    0     0
28-079 [98 015-122]: Data write: 00->80 (80)    1     0                 26^
28-079 [98 044-122]: Data write: 80->00 (00)    0     0                 27v
28-079 [98 078-122]: Data write: 00->40 (40)    0     1
28-079 [98 105-122]: Data write: 40->c0 (c0)    1     1                 27^

* GET ACK

28-079 [98 137-122]: Direction write: c0->80    o     i
28-079 [98 137-122]: Data write: c0->40 (40)    0     *                 28v
28-079 [98 188-122]: Data write: 40->c0 (c0)    1     *                 28^
28-079 [98 224-122]: Direction read: 80
28-079 [98 224-122]: Data read: 00              0     0     get ACK

* ???

28-079 [98 001-123]: Data write: c0->00 (40)    0     *                 29v
28-079 [98 019-123]: Data write: 40->00 (40)    0     *
28-079 [98 021-123]: Data write: 40->00 (40)    0     *

* READ BYTE 0

28-079 [98 059-123]: I2C RX byte 0000 0x00
28-079 [98 059-123]: Data write: 40->80 (c0)    1     *                 29^
28-079 [98 092-123]: Direction read: 80
28-079 [98 092-123]: Data read: 00
28-079 [98 099-123]: Data write: c0->00 (40)
28-079 [98 122-123]: Data write: 40->80 (c0)                            31^
28-079 [98 143-123]: Direction read: 80
28-079 [98 143-123]: Data read: 00
28-079 [98 147-123]: Data write: c0->00 (40)
28-079 [98 172-123]: Data write: 40->80 (c0)                            32^
28-079 [98 192-123]: Direction read: 80
28-079 [98 192-123]: Data read: 00
28-079 [98 196-123]: Data write: c0->00 (40)
28-079 [98 217-123]: Data write: 40->80 (c0)                            33^
28-079 [98 011-124]: Direction read: 80
28-079 [98 011-124]: Data read: 00
28-079 [98 015-124]: Data write: c0->00 (40)
28-079 [98 040-124]: Data write: 40->80 (c0)                            34^
28-080 [98 060-124]: Direction read: 80
28-080 [98 060-124]: Data read: 00
28-080 [98 064-124]: Data write: c0->00 (40)
28-080 [98 085-124]: Data write: 40->80 (c0)                            35^
28-080 [98 106-124]: Direction read: 80
28-080 [98 106-124]: Data read: 00
28-080 [98 110-124]: Data write: c0->00 (40)
28-080 [98 135-124]: Data write: 40->80 (c0)                            36^
28-080 [98 155-124]: Direction read: 80
28-080 [98 155-124]: Data read: 00
28-080 [98 159-124]: Data write: c0->00 (40)
28-080 [98 180-124]: Data write: 40->80 (c0)                            37^
28-080 [98 201-124]: Direction read: 80
28-080 [98 201-124]: Data read: 00

* SEND ACK

28-080 [98 208-124]: Data write: c0->00 (40)    0     *                 38v
28-080 [98 048-125]: Direction write: 80->c0    o     o
28-080 [98 048-125]: Data write: 40->00 (00)    0     0
28-080 [98 085-125]: I2C ACKED
28-080 [98 085-125]: Data write: 00->80 (80)    1     0                 38^

* ???

28-080 [98 124-125]: Data write: 80->00 (00)    0     0                 39v
28-080 [98 135-125]: Direction write: c0->80    o     i
28-080 [98 135-125]: Data write: 00->00 (40)    0     *
28-080 [98 135-125]: Data write: 40->00 (40)    0     *

* READ BYTE 1

28-080 [98 163-125]: I2C RX byte 0001 0x56
28-080 [98 163-125]: Data write: 40->80 (c0)    1     *                 39^
28-080 [98 184-125]: Direction read: 80
28-080 [98 184-125]: Data read: 00
28-080 [98 188-125]: Data write: c0->00 (40)
28-080 [98 213-125]: Data write: 40->80 (c0)
28-080 [98 006-126]: Direction read: 80
28-080 [98 006-126]: Data read: c0
28-080 [98 010-126]: Data write: c0->00 (40)
28-080 [98 032-126]: Data write: 40->80 (c0)
28-080 [98 057-126]: Direction read: 80
28-080 [98 057-126]: Data read: 00
28-080 [98 065-126]: Data write: c0->00 (40)
28-080 [98 086-126]: Data write: 40->80 (c0)
28-080 [98 107-126]: Direction read: 80
28-080 [98 107-126]: Data read: c0
28-080 [98 111-126]: Data write: c0->00 (40)
28-080 [98 136-126]: Data write: 40->80 (c0)
28-080 [98 157-126]: Direction read: 80
28-080 [98 157-126]: Data read: 00
28-080 [98 161-126]: Data write: c0->00 (40)
28-080 [98 186-126]: Data write: 40->80 (c0)
28-080 [98 206-126]: Direction read: 80
28-080 [98 206-126]: Data read: c0
28-080 [98 210-126]: Data write: c0->00 (40)
28-080 [98 005-127]: Data write: 40->80 (c0)
28-080 [98 030-127]: Direction read: 80
28-080 [98 030-127]: Data read: c0
28-081 [98 038-127]: Data write: c0->00 (40)
28-081 [98 059-127]: Data write: 40->80 (c0)
28-081 [98 080-127]: Direction read: 80
28-081 [98 080-127]: Data read: 00
28-081 [98 084-127]: Data write: c0->00 (40)
28-081 [98 147-127]: Direction write: 80->c0
28-081 [98 147-127]: Data write: 40->00 (00)
28-081 [98 175-127]: I2C ACKED
... and noticed again that after the ACKs some extra-protocol writes are performed (not always in the same way), that the RESTART condition is performed by means of the extra cycle, that sometimes data is set/cleared together with setting the input/output, and that the flood of direction read/writes reported by Toni (and filtered out by the log settings) is due to the fact that all operations are performed as longwords spanning both the data and the direction registers.

(Continued in the next post.)
saimo is offline  
Old 27 March 2020, 00:56   #23
saimo
Registered User
 
saimo's Avatar
 
Join Date: Aug 2010
Location: Italy
Posts: 787
(Continued.)

I felt that looking at the log wasn't sufficient to fully understand the logic (and check the timings), so I decided to challenge my sanity and follow the execution from the UAE monitor (for those who find this strange, again, it's a limitation of mine). I couldn't take much, but something came out of it...

Code:
*** initialization
Memwatch 1: break at 00B80030.L  W  C000C000 PC=00E61A12 CPUDW (000)   hh oo

00E61A12 2a85                     MOVE.L D5,(A5) [c000c000]
00E61A14 4a39 00bf e001           TST.B $00bfe001
00E61A1A 4a39 00bf e001           TST.B $00bfe001
00E61A20 4a39 00bf e001           TST.B $00bfe001
00E61A26 4a39 00bf e001           TST.B $00bfe001
00E61A2C 0285 bfff ffff           AND.L #$bfffffff,D5


*** START condition

Memwatch 1: break at 00B80030.L  W  8000C000 PC=00E61A32 CPUDW (000)   hl oo

00E61A32 2a85                     MOVE.L D5,(A5) [0000c000] 8000C000
00E61A34 4a39 00bf e001           TST.B $00bfe001
00E61A3A 4a39 00bf e001           TST.B $00bfe001
00E61A40 4a39 00bf e001           TST.B $00bfe001
00E61A46 4e75                     RTS


*** send byte (address memory)

Memwatch 1: break at 00B80030.L  W  0000C000 PC=00E61ABC CPUDW (000)   ll oo   v

00E61AB4 7207                     MOVE.L #$07,D1
00E61AB6 0285 7fff ffff           AND.L #$7fffffff,D5
00E61ABC 2a85                     MOVE.L D5,(A5) [0000c000] 0000C000
00E61ABE 4a39 00bf e001           TST.B $00bfe001
00E61AC4 4a39 00bf e001           TST.B $00bfe001
00E61ACA 4a39 00bf e001           TST.B $00bfe001
00E61AD0 4a39 00bf e001           TST.B $00bfe001
00E61AD6 0285 bfff ffff           AND.L #$bfffffff,D5

Memwatch 1: break at 00B80030.L  W  4000C000 PC=00E61AEC CPUDW (000)   lh oo

00E61ADC 0085 0000 4000           OR.L #$00004000,D5
00E61AE2 e388                     LSL.L #$01,D0
00E61AE4 6406                     BCC.B #$06 == $00e61aec (T)
00E61AE6 0085 4000 0000           OR.L #$40000000,D5
00E61AEC 2a85                     MOVE.L D5,(A5) [c000c000] 4000C000
00E61AEE 4a39 00bf e001           TST.B $00bfe001
00E61AF4 4a39 00bf e001           TST.B $00bfe001
00E61AFA 4a39 00bf e001           TST.B $00bfe001
00E61B00 4a39 00bf e001           TST.B $00bfe001
00E61B06 0085 8000 0000           OR.L #$80000000,D5

Memwatch 1: break at 00B80030.L  W  C000C000 PC=00E61B0C CPUDW (000)   hh oo   ^

00E61B0C 2a85                     MOVE.L D5,(A5) [c000c000] C000C000
00E61B0E 4a39 00bf e001           TST.B $00bfe001
00E61B14 4a39 00bf e001           TST.B $00bfe001
00E61B1A 4a39 00bf e001           TST.B $00bfe001
00E61B20 51c9 ff94                DBF .W D1,#$ff94 == $00e61ab6 (F)


*** start cycle and set SDA to input

Memwatch 1: break at 00B80030.L  W  00008000 PC=00E61B2A CPUDW (000)   ll oi   v

00E61B24 0285 7fff bfff           AND.L #$7fffbfff,D5
00E61B2A 2a85                     MOVE.L D5,(A5) [c000c000] 00008000
00E61B2C 4a39 00bf e001           TST.B $00bfe001
00E61B32 4a39 00bf e001           TST.B $00bfe001
00E61B38 4a39 00bf e001           TST.B $00bfe001
00E61B3E 4a39 00bf e001           TST.B $00bfe001
00E61B44 4e75                     RTS


*** complete cycle

Memwatch 1: break at 00B80030.L  W  80008000 PC=00E61C10 CPUDW (000)   hl oi   ^

00E61C04 0085 8000 0000           OR.L #$80000000,D5
00E61C0A 0285 ffff bfff           AND.L #$ffffbfff,D5
00E61C10 2a85                     MOVE.L D5,(A5) [00008000] 80008000
00E61C12 7406                     MOVE.L #$06,D2

*** read ACK up to 7 times and then start cycle

Memwatch 0: break at 00B80030.L R   00000000 PC=00E61C26 CPUDR (000)

00E61C14 4a39 00bf e001           TST.B $00bfe001
00E61C1A 4a39 00bf e001           TST.B $00bfe001
00E61C20 4a39 00bf e001           TST.B $00bfe001
00E61C26 2a15                     MOVE.L (A5) [00008000],D5
00E61C28 0805 001e                BTST.L #$001e,D5
00E61C2C 6706                     BEQ.B #$06 == $00e61c34 (F)         if ACK...
00E61C2E 51ca ffe4                DBF .W D2,#$ffe4 == $00e61c14 (F)
00E61C32 600e                     BT .B #$0e == $00e61c42 (T)         if NACK (never happened)...

Memwatch 1: break at 00B80030.L  W  00008000 PC=00E61C3A CPUDW (000)  ll oi    v

00E61C34 0285 7fff ffff           AND.L #$7fffffff,D5
00E61C3A 2a85                     MOVE.L D5,(A5) [00008000] 00008000
00E61C3C 023c 00fe                AND.B #$00fe,CCR
00E61C40 4e75                     RTS

00E61C42 0285 7fff ffff           AND.L #$7fffffff,D5
00E61C48 2a85                     MOVE.L D5,(A5) [00008000]           lh oi    v
00E61C4A 003c 0001                OR.B #$0001,CCR
00E61C4E 4e75                     RTS


*** send offset
*** repeat initialization + START condition
*** address memory


* read byte

Memwatch 1: break at 00B80030.L  W  00008000 PC=00E61B4E CPUDW (000)  ll oi    v

00E61B46 7207                     MOVE.L #$07,D1
00E61B48 0285 ffff bfff           AND.L #$ffffbfff,D5                          ensures SDA is input (no assumption on previous state)
00E61B4E 2a85                     MOVE.L D5,(A5) [c0008000]                    loop here

Memwatch 1: break at 00B80030.L  W  00008000 PC=00E61B56 CPUDW (000)  ll oi    v   no delay

00E61B50 0285 7fff ffff           AND.L #$7fffffff,D5                          loop here
00E61B56 2a85                     MOVE.L D5,(A5) [c0008000]                    to pull SCL low 
00E61B58 4a39 00bf e001           TST.B $00bfe001
00E61B5E 4a39 00bf e001           TST.B $00bfe001
00E61B64 4a39 00bf e001           TST.B $00bfe001
00E61B6A 0085 8000 0000           OR.L #$80000000,D5

Memwatch 1: break at 00B80030.L  W  80008000 PC=00E61B70 CPUDW (000)  hl oi    ^

00E61B70 2a85                     MOVE.L D5,(A5) [c0008000]
00E61B72 4a39 00bf e001           TST.B $00bfe001
00E61B78 4a39 00bf e001           TST.B $00bfe001
00E61B7E 4a39 00bf e001           TST.B $00bfe001

Memwatch 0: break at 00B80030.L R   00000000 PC=00E61B84 CPUDR (000)           read SDA

00E61B84 2415                     MOVE.L (A5) [c0008000],D2
00E61B86 e388                     LSL.L #$01,D0
00E61B88 0802 001e                BTST.L #$001e,D2
00E61B8C 6704                     BEQ.B #$04 == $00e61b92 (F)
00E61B8E 0000 0001                OR.B #$01,D0
00E61B92 51c9 ffbc                DBF .W D1,#$ffbc == $00e61b50 (F)


* start cycle and exit

Memwatch 1: break at 00B80030.L  W  00008000 PC=00E61B9C CPUDW (000)  ll oi    v

00E61B96 0285 7fff ffff           AND.L #$7fffffff,D5
00E61B9C 2a85                     MOVE.L D5,(A5) [c0008000]
00E61B9E 4a39 00bf e001           TST.B $00bfe001
00E61BA4 4a39 00bf e001           TST.B $00bfe001
00E61BAA 4a39 00bf e001           TST.B $00bfe001
00E61BB0 4a39 00bf e001           TST.B $00bfe001
00E61BB6 023c 00fe                AND.B #$00fe,CCR
00E61BBA 4e75                     RTS


*** send ACK and start cycle

Memwatch 1: break at 00B80030.L  W  0000C000 PC=00E61BC8 CPUDW (000)  ll ii    v

00E61BBC 0285 bfff ffff           AND.L #$bfffffff,D5                          set SDA to 0 and to input
00E61BC2 0085 0000 4000           OR.L #$00004000,D5
00E61BC8 2a85                     MOVE.L D5,(A5) [0000c000]
00E61BCA 4a39 00bf e001           TST.B $00bfe001
00E61BD0 4a39 00bf e001           TST.B $00bfe001
00E61BD6 4a39 00bf e001           TST.B $00bfe001
00E61BDC 0085 8000 0000           OR.L #$80000000,D5

Memwatch 1: break at 00B80030.L  W  8000C000 PC=00E61BE2 CPUDW (000)  hl ii    ^

00E61BE2 2a85                     MOVE.L D5,(A5) [0000c000]        
00E61BE4 4a39 00bf e001           TST.B $00bfe001
00E61BEA 4a39 00bf e001           TST.B $00bfe001
00E61BF0 4a39 00bf e001           TST.B $00bfe001
00E61BF6 0285 7fff ffff           AND.L #$7fffffff,D5

Memwatch 1: break at 00B80030.L  W  0000C000 PC=00E61BFC CPUDW (000)  ll ii    v

00E61BFC 2a85                     MOVE.L D5,(A5) [0000c000]
00E61BFE 023c 00fe                AND.B #$00fe,CCR
00E61C02 4e75                     RTS
Things confirmed:
* the code always uses longwords (which, together with the many immediate ANDs/ORs, cause it to be a bit bigger / less efficient than it could be, unless it's mandatory to access both registers at the same time - which would be rather odd, but I don't want to exclude anything);
* additional operations are performed after the ACKs;
* the RESTART is performed by generating STOP condition through the simple initialization executed at the very beginning (this is a consequence of SCL being left low by routines as noted below).

Things discovered:
* receiving ACK is performed is a weird way: after clocking the cycle and waiting for the signal to stabilize, SDA is read up to 7 times consecutively until it reads 0... what for? the signal is already stable, and it isn't going to change since no pulse is sent to the EEPROM, and the datasheet doesn't even contemplate the case of a NACK;
* the extra unexpected writes depend on the fact that the routines use the convention of pulling SCL low (i.e. starting a cycle) before returning: when the next routine begins, it pulls SCL low again (so nothing changes, in practice);
* sometimes data and direction get set at the same time: this could be a good optimization (as it saves a delay each time), but can it be done always?
* delays are irregular (seemingly, without a logic): sometimes they are achived by accessing the CIA A 4 times, sometimes 3 (as if the code relied on the additional delay caused by the execution of the following instructions - which would of course would not work on faster CPUs, but, if the EEPROM is the 5 V version, then actually even just 1 access should always suffice), and in one case there is no delay at all between two consecutive writes (which don't change anything, though);

Side note: the code seems generated by a compiler (especially the part that reads the ACK).

Toni, a question regarding the registers: can they be accessed singularly, and by byte (as the comment in the UAE code suggests)? To be safe, given that it causes no penalty, I'll change my code to access them by word, but I'm wondering if for some reason I should always acccess them both at the same time as the Kernel does.
saimo is offline  
Old 27 March 2020, 18:09   #24
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,505
Quote:
* receiving ACK is performed is a weird way: after clocking the cycle and waiting for the signal to stabilize, SDA is read up to 7 times consecutively until it reads 0... what for? the signal is already stable, and it isn't going to change since no pulse is sent to the EEPROM, and the datasheet doesn't even contemplate the case of a NACK;
ROM code probably is based on some generic I2C code which has support for extra wait states.

Quote:
Toni, a question regarding the registers: can they be accessed singularly, and by byte (as the comment in the UAE code suggests)? To be safe, given that it causes no penalty, I'll change my code to access them by word, but I'm wondering if for some reason I should always acccess them both at the same time as the Kernel does.
I am quite sure they can be accesses any way possible (byte, word or long). Note that 68020+ does only long accesses if address is 32-bit capable (Akiko AFAIK is) and address is long aligned. So in this case CPU always splits it to 2 back to back word accesses.
Toni Wilen is offline  
Old 27 March 2020, 19:20   #25
saimo
Registered User
 
saimo's Avatar
 
Join Date: Aug 2010
Location: Italy
Posts: 787
Quote:
Originally Posted by Toni Wilen View Post
ROM code probably is based on some generic I2C code which has support for extra wait states.
After making the post, I realized that maybe it's a matter of misinterpretation of how the acknowledge polling works or a hack based on the assumption of the duration of the internal write cycle - the due explanation follows.

The EEPROM won't respond with an ACK to the request of starting an operation only when it's internally busy with committing the data written with a previous operation. To initiate any other operation, it is necessary to execute what described at page 7 of the ATMEL datasheet: ACKNOWLEDGE POLLING: Once the internally timed write cycle has started and the EEPROM inputs are disbled, acknowledge polling can be initiated. This involves sending a start condition followed by the device address word. The read/write bit is representative of the operation desired. Only if the internal write cycle has completed will the EEPROM respond with a zero allowing the read or write sequence to continue.

One might be mislead by the word "polling", as the operation doesn't involve just polling the SDA wire, but also generating the start condition and sending the device address each time. The explanation could have been better, but there can't be doubts. By the way, in a previous post I mentioned that the STM datasheet, whose text is quite poor, indeed explains this nicely:



The Kernal code, instead, simply polls the SDA wire 7 times in a row with a delay between the reads of about 4.2 microseconds. This won't work if the EEPROM is busy because it would respond only once (with a NACK) and then, anyway, SDA would never change because SCL is never pulsed. At boot of course this is not a problem since the EEPROM is not busy, but in theory there could be problems afterwards. Maybe this is fixed by SetPatch or maybe the condition never happens because of how the NVRAM is accessed (I didn't analyze the code further, but from the behaviour I had observed also in other occasions, it seems that the NVRAM is re-written entirely every time StoreNV() is called, so the problem could arise only if two access requests are made almost simultaneously, which is very unlikely).

Quote:
I am quite sure they can be accesses any way possible (byte, word or long). Note that 68020+ does only long accesses if address is 32-bit capable (Akiko AFAIK is) and address is long aligned. So in this case CPU always splits it to 2 back to back word accesses.
OK, thanks.


I have adjusted/improved a bit my code and also fixed a little bug: I had forgotten to send the NACK after reading the very last byte (but this wasn't the cause of the issues I reported). Now I'm waiting for other tests results.

Last edited by saimo; 30 March 2020 at 23:04.
saimo is offline  
Old 30 March 2020, 23:12   #26
saimo
Registered User
 
saimo's Avatar
 
Join Date: Aug 2010
Location: Italy
Posts: 787
The results proved my code still doesn't work: the usual variable bunch of 0s followed by all 1s.

Attached slightly revised code, whose most important change is a fix to a bug that trashed d2 (but it was not the cause of the failed tests thanks to the fact that the test address is 0).

Last edited by saimo; 09 July 2021 at 09:56.
saimo is offline  
Old 05 April 2020, 13:23   #27
saimo
Registered User
 
saimo's Avatar
 
Join Date: Aug 2010
Location: Italy
Posts: 787
After the previous post, I revised the code further and also made a version that accesses the registers by word (attached here); then, I prepared 2 new tests. Today I received the results, and unfortunately all they say is: 0.
In the meanwhile, my tester told me that he has a TerribleFire 330, so now I've realized what a hassle is to him to make these tests. I won't bother him anymore and I'll search for somebody who has an easier way to transfer files - by the way, anyone here?

EDIT: three persons offered to help with tests, so, for the moment being, don't bother answering the help request above Should I need further help, I'll let you know.

Last edited by saimo; 09 July 2021 at 09:56.
saimo is offline  
Old 05 January 2021, 16:48   #28
saimo
Registered User
 
saimo's Avatar
 
Join Date: Aug 2010
Location: Italy
Posts: 787
It's quite a long time since I last worked on this stuff - I got distracted by a couple of other Amiga things (I made the demo THE CURE and the graphics system ALS) and by this programming guide (in Italian) - but finally I have resumed work on this!

Having almost totally forgotten how the NVRAM and my code works, I studied the datasheet and my code again, and, remembering how the Kernel code always accesses both the Akiko registers at the same time, I decided to rewrite my code entirely according to that logic (although that's a bit more inefficient). Also, I seized the chance to change the way I send the clock signal.
The result is the code attached here.
The good news is that this one not only works on WinUAE, but also on real Amiga CD32 machines! A tester tried it on two different machines and it was able to: dump the contents of the whole NVRAMs correctly; save data to an OS-legal entry correctly.
Now I'm waiting for more test results from another friend. I still can't say that the code works 100% fine because, from the pictures on the net, I have noticed that the Amiga CD32 boards mount different versions of the chips (there are 5 V chip and chips that require a lower voltage but have slower timings) and I don't know (yet) which chips mount the machines that the tests have been performed on.

Last edited by saimo; 04 September 2021 at 10:51. Reason: Removed attachment (I'm reworking the code).
saimo is offline  
Old 28 January 2021, 15:25   #29
saimo
Registered User
 
saimo's Avatar
 
Join Date: Aug 2010
Location: Italy
Posts: 787
The code worked perfectly on two machines, both mounting 5V EEPROMs, with and without TF328 accelerator board. However, the game didn't fully work on a third machine with an unknown EEPROM chip and a TF300 accelerator. Unfortunately, life got in the way of my tester, so further tests remained pending for a couple of weeks. Does anybody here feel like running a few tests for me? An Amiga CD32 with a <= 2.5 V EEPROM chip and easy storage support (HD/CF/floppy/etc.) is needed.
saimo is offline  
Old 11 February 2021, 19:38   #30
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,505
Probably not much help but today I did some real I2C stuff (I2C IR temperature sensor MLX90614). Datasheet says it supports bus transfer rates from 10KHz to 100KHz. Except if it is less than about 20KHz, it failed to work every time (I think it NACKs the transfer for some unknown reason). 30KHz to 100KHz worked fine.

It also had another undocumented feature, mid transfer STOP/START condition state is not supported. If it sees STOP, it seems to reset its internal state. Only STARTs are accepted ("Repeated START"). Apparently some old EEPROMs have same limitation. So don't trust datasheets 100%..

Perhaps one possible reason is "clock stretching". Device will report NACK if host changes either line state during clock stretching.

Only way to be sure is to use some logic analyzer that has I2C decoding support. Perhaps someday I'll bother with that
Toni Wilen is offline  
Old 11 February 2021, 23:17   #31
jotd
This cat is no more
 
jotd's Avatar
 
Join Date: Dec 2004
Location: FRANCE
Age: 52
Posts: 8,163
@Saimo great work. I'd be delighted if you wrote a low-level CDTV sector read now
jotd is offline  
Old 12 February 2021, 14:25   #32
saimo
Registered User
 
saimo's Avatar
 
Join Date: Aug 2010
Location: Italy
Posts: 787
@Toni Wilen

It might be, but before assuming that there's a discrepancy between datasheet and chip, I want to be really sure that my code complies with what the datasheet says. I think it should, but the last test seems to say otherwise.
But now I realize I forgot to report the full results. It goes like this...
First, tests were made on the two machines that eventually proved that everything worked fine. I started with some little test proggies (among which the one that dumps the whole contents of the NVRAM, as mentioned above). Then, after getting positive results, I had SkillGrid tested (which is ultimately why I'm doing this), and, as said, it worked flawlessly.
Then, the game was tried on the machine with the unknown NVRAM chip: it failed to boot, at least when running from CD. When booting, the game first makes sure that a slot is properly allocated with nonvolatile.library and then, after switching the OS off, uses the custom code to see where exactly that slot is. My guess is that this last operation fails. Now, that is done by simply dumping the whole NVRAM to a RAM buffer and I can't see why that should fail given that... the proggie that dumps the NVRAM (and that uses the same code, of course) works perfectly also on that very same machine! So, I'm suspecting that, although very unlikely, I might have broken something else in the SkillGrid startup code; on the other hand, if it were so, how can it be that the game runs on the other machines? I won't know until I get more test results.
And that's the biggest issue: since I don't have an Amiga CD32, I have to rely on others. The guy who helps me with tests (a great chap, by the way) is busy with real life (well, like all of us), so at times I get a report or two after weeks or even months. When I go back to this matter I can't even remember where I was
Final outcome: the SkillGrid update has been on hold for about 1 year because of just this issue.


@jotd

Thank you. Now, if it only also worked...
As for the CDTV, I'm afraid I have to disappoint you: I don't really enjoy this sort of things, I'm no tech junkie... I just want to make games, and if I'm doing this is because the SkillGrid update I have here needs more RAM than before, and the only option I have to have it running on the Amiga CD32 is to trash the OS.
saimo is offline  
Old 07 September 2021, 23:07   #33
saimo
Registered User
 
saimo's Avatar
 
Join Date: Aug 2010
Location: Italy
Posts: 787
I finally returned to this.
I have rewritten the routines once again, and I have no idea of what happens on real machines. Therefore, I have prepared a proper test suite to have the routines tested... by anyone who feels like giving it a go on a real Amiga CD³² Any feedback will be much appreciated!

The test suite can be downloaded from https://www.retream.com/_temporary/NVRAMRTS.lha.

This short video shows what the test suite does:

[ Show youtube player ]

(Note: the operations will be surely slower on real machines.)

Code:
--------------------------------------------------------------------------------
OVERVIEW

This is a test suite that purposes to verify whether my custom routines for
direct access to the Amiga CD³² NVRAM work.
Developing them is quite challenging because:
 · I do not have an Amiga CD³², so I have to rely on emulation, which is not
   100% exact;
 · different machines mount different EEPROM chips, which behave differently;
 · there is no official documentation (my references are the documentation that
   has been thankfully produced by who studied the behaviour of Akiko and the
   EEPROM datasheet from ATMEL, the maker of the EEPROM).
The routines work perfectly under emulation, but that is no guarantee that they
work also on real machines. Indeed, previous versions worked under emulation and
on a couple of machines, but failed on another machine.


--------------------------------------------------------------------------------
WHAT DOES THIS DO?

This suite will perform several read/write operations from/to the NVRAM, whose
DATA WILL THUS BE ALTERED (unless the routines fail to access the NVRAM
altogether). At the end, it will attempt to restore the NVRAM data exactly as it
was at the beginning.
Given that the routines are experimental, though, first it will check if a
backup of the NVRAM items exists and ask you whether to make a (new) backup, so
that the NVRAM items can be restored after the tests if the custom restore does
not succeed or execute at all (only OS-compliant NVRAM items will be backed up;
the backup and restore operations are done by means of the OS-legal, reliable,
third-party tools DumpNVRAM and RestoreNVRAM - check out NVRAM_Tools.doc).
You will be informed about the backup status and asked what to do and whether to
continue.


--------------------------------------------------------------------------------
REQUIREMENTS

· An Amiga CD³² with a writable media drive (DO NOT TRY ON OTHER MACHINES)
· The AmigaDOS Copy, Delete and Execute commands in the commands path.


--------------------------------------------------------------------------------
INSTRUCTIONS

To perform the tests:
 1. copy the NVRAMRTS directory from the archive to anywhere on the drive;
 2. from shell, enter the NVRAMRTS directory;
 3. run the "test" script and follow the on-screen instructions.

At the end of the tests or if the tests hung:
 1. reboot the machine;
 2. if the NVRAM data is not restored correctly or you are not sure, and a
    backup exists:
     2.1. from shell, enter the NVRAMRTS directory;
     2.2. run the "restore" script;
 3. pack the NVRAMRTS directory into an archive;
 4. send your Amiga CD³²'s specifications(*), the archive and, if the tests
    hung, the color of the screen at that point to postmaster@retream.com.

(*)The marking on the EEPROM would be particularly helpful, but, since that
requires opening the machine, do not worry if you do not feel like going that
far.

Thank you!


--------------------------------------------------------------------------------
THE CORE TOOL

The tests are performed by means of a tool called WriteReadNVRAM. It is a shell
program that allows to access any arbitrary chunk of the Amiga CD³² NVRAM.
It works as follows:
 1. if requested, it writes some data from an input file to the NVRAM;
 2. if requested, it saves some data from NVRAM to an output file.

The shell arguments are:
 · INPUTFILE=IF/K     : input file (unspecified = do not write data to NVRAM)
 · WRITEADDRESS=WA/K/N: NVRAM address in [0, 1023] to start writing from
 · WRITESIZE=WS/K/N   : number of bytes in [1, 1024-WRITEADDRESS] to write
 · OUTPUTFILE=OF/K    : output file (unspecified = do not read data from NVRAM)
 · READADDRESS=RA/K/N : NVRAM address in [0, 1023] to start reading from
 · READSIZE=RS/K/N    : number of bytes in [1, 1024-READADDRESS] to read
 · QUIET/S            : do not print any information to the standard output

These values are used for unspecified arguments:
 · WRITEADDRESS: 0
 · WRITESIZE   : 1024
 · READADDRESS : 0
 · READSIZE    : 1024

These values are used for invalid arguments:
 · WRITEADDRESS: 0
 · WRITESIZE   : 1024-WRITEADDRESS
 · READADDRESS : 0
 · READSIZE    : 1024-READADDRESS

If QUIET is not specified, the following information gets printed:
 · startup code : <NVRAM startup code (see below)>
 · input file   : <input file path, if specified>
 · write address: <(corrected) NVRAM address for writing>
 · write size   : <(corrected) number of bytes for writing>
 · load code    : <load code (see below)>
 · output file  : <output file path, if specified>
 · read address : <(corrected) NVRAM address for reading>
 · read size    : <(corrected) number of bytes for reading>
 · save code    : <save code (see below)>
 · elapsed time : <elapsed time expressed in color clocks>

Operation code:
 :| = no operation
 :( = operation failed
 :) = operation succeeded

No data is written to the NVRAM if loading fails.
No data is read from the NVRAM and saved to file if the NVRAM startup fails.

During execution, AmigaOS is disabled entirely. Also, the screen gets blanked
and repainted dynamically as follows:
 · blue : writing;
 · cyan : preparing to read;
 · green: reading;
 · red  : starting an operation.

THIS TOOL IS BASED ON THE CUSTOM ROUTINES WHOSE VALIDITY IS TO BE VERIFIED WITH
THIS SUITE, SO IT IS BY NO MEANS RELIABLE.

Last edited by saimo; 10 September 2021 at 21:46. Reason: Improved test script and documentation
saimo is offline  
Old 08 September 2021, 19:25   #34
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,505
I can run the test this weekend (using floppy adapter)

I also have new logic analyzer (DSLogic U32Pro32) and scope (Siglent SDS2104X+) which both supports I2C decoding which should make it easy to see if there are any protocol errors. I'd like to have some explanation why some methods that you tried didn't work (but should have worked at least in theory)

But I am not sure if there is any easily accessible location to connect/solder required wires..
Toni Wilen is offline  
Old 08 September 2021, 22:48   #35
saimo
Registered User
 
saimo's Avatar
 
Join Date: Aug 2010
Location: Italy
Posts: 787
Quote:
Originally Posted by Toni Wilen View Post
I can run the test this weekend (using floppy adapter)

I also have new logic analyzer (DSLogic U32Pro32) and scope (Siglent SDS2104X+) which both supports I2C decoding which should make it easy to see if there are any protocol errors.
That would be utterly cool!

Quote:
I'd like to have some explanation why some methods that you tried didn't work (but should have worked at least in theory)
One thing I did with this last rewrite was eliminating the longword accesses to $b80030 in order to read/write also $b80032 at the same time. The first versions (which did not work on real hardware) did access $b80030 and $b80032 separately (with byte reads/writes), but then, seeing what the kernel does by looking at the logs, I moved to longword accesses (although I never liked the inherent inefficiency: the direction for SCL needs to be always output and the direction for SDA needs to be input only when reading the ACKs or data) - I thought that the (Akiko-related) magic was changing data and direction at the same time. Given that such code worked on two real machines, that seemed to be right. Longword accesses work only under the assumption that the CPU has direct 32-bit access to Akiko registers, but I guess that's a given, otherwise C2P would be even worse; and that's indeed what can be seen in this schematics (address and data lines A(23:0) and D(31:0), respectively). However, before making this last rewrite, I decided to use word accesses, so now I write $b80032 only when strictly needed (which allows more efficient code) - after all, I really can't see why it should make any difference to access both registers at the same time.
Another thing I changed is SCL handling: at some point I had SCL preset to low (a bit difficult to explain in few words: basically, I was anticipating the first half of the clock), but I don't think it was a good idea (yet, if I remember correctly, that did work on some machines).

Quote:
But I am not sure if there is any easily accessible location to connect/solder required wires..
Luckily, the EEPROM area (just under Alice) is quite free from physical obstacles Check this picture out.
saimo is offline  
Old 10 September 2021, 21:02   #36
saimo
Registered User
 
saimo's Avatar
 
Join Date: Aug 2010
Location: Italy
Posts: 787
The friend who has the machine where my routines never worked managed to give the suite a spin. And the (unsurprising result) was that the very first test hangs right at the beginning (black screen and complete freeze).
I suspect that what fails is the acknoweldge polling: for some reason, SDA always reads high, and so the code ends up looping endlessly. In theory, I could break the loop after 10 ms (that's the internal write time of the EEPROM), but that wouldn't solve the problem: the solution is understanding why SDA always reads high and fixing that. That is, or finding the actual problem, it's different.

I have uploaded a new test suite (the link is always the same). The new test tool includes these changes:
* at the very beginning (nvm_initialize()), SCL and SDA are first read and, if they are not both high (i.e. the EEPROM is stuck doing something), a reset procedure is executed (more about this below);
* if the reset procedure doesn't work, nvm_initialize() returns error (so the test program knows that the EEPROM cannot be used);
* to understand where the code hangs, the screen color gets changed dynamically as follows: green = writing; cyan = preparing to read; blue = reading; red = starting an operation (my money is on red).

I tried to look at the log produced by WinUAE to see if the code behaves correctly, and something strange seems to happen. This is what happens when "number" starts to get written at address 1010 (the stuff after "<-" are my comments, which indicate the exact piece of code that executes the action):
Code:
Direction write: 00->c0 <- n_initialize
I2C START

Data write: c0->80 (80) <- n_WriteBytes StartWrite StartOperation PullSDALow
Data write: 80->00 (00) <- n_WriteBytes StartWrite StartOperation SendByte PullSCLLow
Data write: 00->40 (40) <- n_WriteBytes StartWrite StartOperation SendByte SendBit (1)
Data write: 40->c0 (c0) <- n_WriteBytes StartWrite StartOperation SendByte SendBit PullSCLHigh
Data write: c0->40 (40) <- n_WriteBytes StartWrite StartOperation SendByte PullSCLLow
Data write: 40->00 (00) <- n_WriteBytes StartWrite StartOperation SendByte SendBit (0)
Data write: 00->80 (80) <- n_WriteBytes StartWrite StartOperation SendByte SendBit PullSCLHigh
Data write: 80->00 (00) <- n_WriteBytes StartWrite StartOperation SendByte PullSCLLow
Data write: 00->40 (40) <- n_WriteBytes StartWrite StartOperation SendByte SendBit (1)
Data write: 40->c0 (c0) <- n_WriteBytes StartWrite StartOperation SendByte SendBit PullSCLHigh
Data write: c0->40 (40) <- n_WriteBytes StartWrite StartOperation SendByte PullSCLLow
Data write: 40->00 (00) <- n_WriteBytes StartWrite StartOperation SendByte SendBit (0)
Data write: 00->80 (80) <- n_WriteBytes StartWrite StartOperation SendByte SendBit PullSCLHigh
Data write: 80->00 (00) <- n_WriteBytes StartWrite StartOperation SendByte PullSCLLow
Data write: 00->00 (00) <- n_WriteBytes StartWrite StartOperation SendByte SendBit (0)
Data write: 00->80 (80) <- n_WriteBytes StartWrite StartOperation SendByte SendBit PullSCLHigh
Data write: 80->00 (00) <- n_WriteBytes StartWrite StartOperation SendByte PullSCLLow
Data write: 00->40 (40) <- n_WriteBytes StartWrite StartOperation SendByte SendBit (1)
Data write: 40->c0 (c0) <- n_WriteBytes StartWrite StartOperation SendByte SendBit PullSCLHigh
Data write: c0->40 (40) <- n_WriteBytes StartWrite StartOperation SendByte PullSCLLow
Data write: 40->40 (40) <- n_WriteBytes StartWrite StartOperation SendByte SendBit (1)
Data write: 40->c0 (c0) <- n_WriteBytes StartWrite StartOperation SendByte SendBit PullSCLHigh
Data write: c0->40 (40) <- n_WriteBytes StartWrite StartOperation SendByte PullSCLLow
Data write: 40->00 (00) <- n_WriteBytes StartWrite StartOperation SendByte SendBit (0)
Data write: 00->80 (80) <- n_WriteBytes StartWrite StartOperation SendByte SendBit PullSCLHigh
Direction write: c0->80 <- n_WriteBytes StartWrite StartOperation SendByte move.w NVMR_SCL,(a3) ;make SDA input
Data write: 80->00 (40) <- n_WriteBytes StartWrite StartOperation SendByte PullSCLLow (40? NACK?)
I2C device address 0xa6 <- OK
Data write: 40->80 (c0) <- n_WriteBytes StartWrite StartOperation SendByte PullSCLHigh
Data read: 00           <- n_WriteBytes StartWrite StartOperation SendByte or.w	(a2),d2	;read SDA (ACK/NACK) OK
Direction write: 80->c0 <- move.w NVMR_SCLSDA,(a3) ;make SDA output
The line with the comment (40? NACK?) is suspicious - it looks like it says: the value was $80 (SCL high, SDA low), you wrote $00 (both low) and the final result is $40 (SCL low and SDA high). Basically, it seems to indicate that, in the first half of the 9th cycle, the EEPROM pulls SDA to respond with a NACK.
However, right after that, the log reports that the device address $a6 has been transmitted (which is correct) and then, after I complete the 9th cycle, SDA goes low again (although SDA is supposed to change only when SCL is low) and finally the ACK is received.
Maybe it's just matter of granularity of the log. But I wonder: is that (temporary) NACK supposed to simulate the fact that the EEPROM always starts with NACK and then corrects it, if needed? It looks unlikely to me, as that would equal to emulating the internal behaviour (which isn't even documented in the datasheet anyway). But then, where does that NACK come from?

Additional note: if my code hadn't been able to read SDA correctly in general, it wouldn't have been also to read the contents of the NVRAM, but that is not the case; and, after all, all there is to it is pull SCL low -> wait long enough -> pull SCL high -> wait long enough -> read SDA.

About the reset procedure...
I have followed what the datasheet says, i.e.
Code:
MEMORY RESET: After an interruption in protocol, power loss or system reset, any 2-wire part can be reset by follow-ing these steps:
1. Clock up to 9 cycles.
2. Look for SDA high in each cycle while SCL is high.
3. Create a start condition.
However, at the end, I also generate a STOP condition to allow operations to start actually when needed. Maybe it is not necessary (as in: the first operation afterwards can simply use that START condition - the EEPROM won't notice as the clock isn't pulsed in between and, electrically, there is no maximum time within which an operation has to start), but hopefully it causes no harm (according to the EEPROM / I2C logic, it shouldn't). I have searched the net to see how others handle this, and I found a variety of answers that didn't help.

Updated code attached here.

Closing note: last week, the same friend gave the latest version of SkillGrid (which included the newly rewritten NVRAM routines) a go; as usual, the game froze at startup; but then he discovered one thing: if he booted the game without the CF card connected to the TF330, the game started up just fine (although it didn't neither read nor save to NVRAM)! Go figure...

Edit: my friend just ran the latest test suite, and the result was... RED!

Last edited by saimo; 04 March 2022 at 16:10. Reason: Removed attachment as I attached an updated version in a later post.
saimo is offline  
Old 12 September 2021, 12:31   #37
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,505
Tested on unexpended CD32 + fWSI expansion using its internal floppy drive. No HD.

Not much happened: first some red flashing and then it hung, red screen.

I'll connect probes to SDA and SCL pins later (not sure if today). Two resistors next to the EEPROM chip are SDA/SCL pullups which makes connection easy.
Toni Wilen is offline  
Old 12 September 2021, 16:47   #38
saimo
Registered User
 
saimo's Avatar
 
Join Date: Aug 2010
Location: Italy
Posts: 787
Quote:
Originally Posted by Toni Wilen View Post
Tested on unexpended CD32 + fWSI expansion using its internal floppy drive. No HD.

Not much happened: first some red flashing and then it hung, red screen.
Well, at least you have a machine where the problem can be reproduced: that's a very good thing. The fact that such machine is in experts hands is even better


Quote:
I'll connect probes to SDA and SCL pins later (not sure if today). Two resistors next to the EEPROM chip are SDA/SCL pullups which makes connection easy.
No hurry, whenever you do it, it will be much appreciated.
saimo is offline  
Old 19 September 2021, 17:31   #39
modrobert
old bearded fool
 
modrobert's Avatar
 
Join Date: Jan 2010
Location: Bangkok
Age: 56
Posts: 775
I took a peek at nonvolatile.library, still trying to figure out what's going on in general, but thought it would be worth mentioning they always call Disable() (disabling interrupts) before doing something and Enable() when it's done.

Checking saimo's test code it looks like it relies on interrupts (CIA) to get proper timing.
Attached Files
File Type: s nonvolatile.library.s (24.3 KB, 72 views)
modrobert is offline  
Old 19 September 2021, 20:26   #40
saimo
Registered User
 
saimo's Avatar
 
Join Date: Aug 2010
Location: Italy
Posts: 787
@modrobert

Thanks for the time and the effort!

Quote:
Originally Posted by modrobert View Post
I took a peek at nonvolatile.library, still trying to figure out what's going on in general, but thought it would be worth mentioning they always call Disable() (disabling interrupts) before doing something and Enable() when it's done.

Checking saimo's test code it looks like it relies on interrupts (CIA) to get proper timing.
The code simply does tst.b (a4) (where a4 = $bfe001) to delay execution by at least 1 E clock cycle (lately I made extensive tests on a variety of machines that proved that such accesses always take at least 1 cycle and, depending on the hardware, sometimes 2 cycles; on the specific machine of my friend, the one where the routines hang, it takes always 1 cycle). For the details, check out the meticulous comments in the code itself.
And, yes, my routines are used exclusively when the OS is off (that's the whole point: I need the routines precisely because the OS is off/trashed)
saimo is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
Extend CD32 NVRAM? Amiga1992 Hardware mods 41 16 December 2018 14:59
CD32 NVRAM management Amiga1992 support.Hardware 9 20 February 2012 13:27
Access CD32-NVRam from Shell Retro1234 support.Other 3 08 August 2010 11:50
CD32 nvram file...? Christian support.WinUAE 11 13 December 2006 22:25
Cd32 Nvram Phantomz request.Apps 5 16 March 2003 21:09

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 10:52.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.17244 seconds with 16 queries