Commit 7c84c62b authored by Robert Sprowson's avatar Robert Sprowson
Browse files

Modification to RISCOS_IICOpV

Now assumes an IICStatus return, per Kernel-5_35-4_79_2_196.
I2C sources lined up to column 17.
Built, but not tested.

Version 0.89. Tagged as 'OMAP3-0_89'
......@@ -11,13 +11,13 @@
GBLS Module_HelpVersion
GBLS Module_ComponentName
GBLS Module_ComponentPath
Module_MajorVersion SETS "0.88"
Module_Version SETA 88
Module_MajorVersion SETS "0.89"
Module_Version SETA 89
Module_MinorVersion SETS ""
Module_Date SETS "17 Aug 2013"
Module_ApplicationDate SETS "17-Aug-13"
Module_Date SETS "28 Sep 2013"
Module_ApplicationDate SETS "28-Sep-13"
Module_ComponentName SETS "OMAP3"
Module_ComponentPath SETS "castle/RiscOS/Sources/HAL/OMAP3"
Module_FullVersion SETS "0.88"
Module_HelpVersion SETS "0.88 (17 Aug 2013)"
Module_FullVersion SETS "0.89"
Module_HelpVersion SETS "0.89 (28 Sep 2013)"
END
/* (0.88)
/* (0.89)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
*
*/
#define Module_MajorVersion_CMHG 0.88
#define Module_MajorVersion_CMHG 0.89
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 17 Aug 2013
#define Module_Date_CMHG 28 Sep 2013
#define Module_MajorVersion "0.88"
#define Module_Version 88
#define Module_MajorVersion "0.89"
#define Module_Version 89
#define Module_MinorVersion ""
#define Module_Date "17 Aug 2013"
#define Module_Date "28 Sep 2013"
#define Module_ApplicationDate "17-Aug-13"
#define Module_ApplicationDate "28-Sep-13"
#define Module_ComponentName "OMAP3"
#define Module_ComponentPath "castle/RiscOS/Sources/HAL/OMAP3"
#define Module_FullVersion "0.88"
#define Module_HelpVersion "0.88 (17 Aug 2013)"
#define Module_LibraryVersionInfo "0:88"
#define Module_FullVersion "0.89"
#define Module_HelpVersion "0.89 (28 Sep 2013)"
#define Module_LibraryVersionInfo "0:89"
......@@ -22,8 +22,6 @@
GET Hdr:OSEntries
GET Hdr:HALEntries
GET Hdr:FSNumbers
GET Hdr:NewErrors
GET hdr.omap3530
GET hdr.StaticWS
......@@ -230,41 +228,41 @@ HAL_IICDevice
; } iic_transfer;
HAL_IICTransfer
LDRB a4, [sb, #BoardConfig_NumI2C]
CMP a1, a4
MOVHS a1, #IICStatus_Error
MOVHS pc, lr
LDRB a4, [sb, #BoardConfig_NumI2C]
CMP a1, a4
MOVHS a1, #IICStatus_Error
MOVHS pc, lr
; Quickly validate the transfer list
; We have several constraints:
; 1. Must have 1 or more iic_transfers
; 2. First transfer must not have nostart bit set
; 3. Between start bits (and between the last start bit and the end of the list) there must be between 1 and 65536 bytes of data (but for the moment we do allow individual iic_transfers to be 0-length)
CMP a2, #0
MOVLT a1, #IICStatus_Error
MOVLT pc, lr
LDR a4, [a3]
TST a4, #1:SHL:31 ; First transfer has nostart set!
MOVNE a1, #IICStatus_Error
MOVNE pc, lr
STMFD sp!, {v1-v5,lr}
ADD a4, a3, a2, LSL #3
ADD a4, a4, a2, LSL #2
MOV v1, a3
CMP a2, #0
MOVLT a1, #IICStatus_Error
MOVLT pc, lr
LDR a4, [a3]
TST a4, #1:SHL:31 ; First transfer has nostart set!
MOVNE a1, #IICStatus_Error
MOVNE pc, lr
STMFD sp!, {v1-v5,lr}
ADD a4, a3, a2, LSL #3
ADD a4, a4, a2, LSL #2
MOV v1, a3
30
MOV v5, #-1
MOV v5, #-1
10
LDMIB v1!, {v2-v4} ; data ptr & length from current transfer, flags from next
ADD v5, v5, v3
CMP v1, a4
BEQ %FT20 ; Last transfer just read
TST v4, #1:SHL:31
BNE %BT10 ; Still more data in this transfer
LDMIB v1!, {v2-v4} ; data ptr & length from current transfer, flags from next
ADD v5, v5, v3
CMP v1, a4
BEQ %FT20 ; Last transfer just read
TST v4, #1:SHL:31
BNE %BT10 ; Still more data in this transfer
20
CMP v5, #65536
MOVHS a1, #IICStatus_Error ; Too much (or too little) data
LDMHSIA sp! ,{v1-v5,pc}
CMP v1, a4
BNE %BT30
CMP v5, #65536
MOVHS a1, #IICStatus_Error ; Too much (or too little) data
LDMHSIA sp! ,{v1-v5,pc}
CMP v1, a4
BNE %BT30
_IICTransfer_Video ; Entry point for HAL_VideoIICOp
[ I2CDebug
DebugTX "HAL_IICTransfer"
......@@ -272,44 +270,44 @@ _IICTransfer_Video ; Entry point for HAL_VideoIICOp
DebugReg a2, "num="
DebugReg a3, "iic_transfer="
]
ADR v5, I2C_Table
MOV v4, #I2CBlockSize
MLA v5, a1, v4, v5
MRS ip, CPSR
ORR a4, ip, #I32_bit
MSR CPSR_c, a4 ; disable interrupts for atomic claim
LDR a4, [v5, #I2C_XStart]
TEQ a4, #0 ; in use already?
STREQ a3, [v5, #I2C_XStart] ; if not, claim it
MSR CPSR_c, ip
MOVNE a1, #IICStatus_Busy ; if it is, return "BUSY"
ADR v5, I2C_Table
MOV v4, #I2CBlockSize
MLA v5, a1, v4, v5
MRS ip, CPSR
ORR a4, ip, #I32_bit
MSR CPSR_c, a4 ; disable interrupts for atomic claim
LDR a4, [v5, #I2C_XStart]
TEQ a4, #0 ; in use already?
STREQ a3, [v5, #I2C_XStart] ; if not, claim it
MSR CPSR_c, ip
MOVNE a1, #IICStatus_Busy ; if it is, return "BUSY"
[ I2CDebug
BEQ %FT10
BEQ %FT10
DebugReg a4, "BUSY: XStart="
LDMFD sp!, {v1-v5,pc}
LDMFD sp!, {v1-v5,pc}
10
DebugTX "OK"
|
LDMNEFD sp!, {v1-v5,pc}
LDMNEFD sp!, {v1-v5,pc}
]
SUB a2, a2, #1 ; a2 = transfers - 1 (needed below)
ADD v1, a3, a2, LSL #3
ADD v1, v1, a2, LSL #2
STR v1, [v5, #I2C_XEnd]
LDR v4, [v5, #I2C_HW]
SUB a2, a2, #1 ; a2 = transfers - 1 (needed below)
ADD v1, a3, a2, LSL #3
ADD v1, v1, a2, LSL #2
STR v1, [v5, #I2C_XEnd]
LDR v4, [v5, #I2C_HW]
; Make sure controller is enabled, since we don't do any initialisation atm!
LDRH a4, [v4, #I2C_CON]
TST a4, #1:SHL:15
LDREQH v3, [v4, #I2C_STAT]
LDRH a4, [v4, #I2C_CON]
TST a4, #1:SHL:15
LDREQH v3, [v4, #I2C_STAT]
[ I2CDebugError
BNE %FT10
DebugTX "Controller not enabled!"
B unexpected_error
BNE %FT10
DebugTX "Controller not enabled!"
B unexpected_error
10
|
BEQ unexpected_error
BEQ unexpected_error
]
MOV v1, a3
MOV v1, a3
start_transfer ; Start the transfer in v1
; a1-a4 free
; v1 = iic_transfer to start
......@@ -319,114 +317,114 @@ start_transfer ; Start the transfer in v1
[ I2CDebug
DebugReg v1, "start_transfer: "
]
STR v1, [v5, #I2C_XCurrent]
MOV lr, #0
STR lr, [v5, #I2C_XBytes]
STR v1, [v5, #I2C_XCurrent]
MOV lr, #0
STR lr, [v5, #I2C_XBytes]
; Get its info
LDMIA v1, {a1-a3}
LDMIA v1, {a1-a3}
[ I2CDebug
DebugReg a1, "addr="
DebugReg a2, "data="
DebugReg a3, "len ="
]
; If it's a 'checksum-only' read, clear the checksum to 0
TST a1, #1:SHL:30
TSTNE a1, #1
MOVNE a2, #0
STRNE a2, [v1, #4]
TST a1, #1:SHL:30
TSTNE a1, #1
MOVNE a2, #0
STRNE a2, [v1, #4]
; Wait for the controller to be fully idle - if two iic_transfer lists are executed back-to-back then there's a chance the controller won't have yet sent the stop bit from the previous transfer. Thus we must wait here for the bit to be sent.
MOV v2, #100*1024 ; timeout - this should be more than adequate (with a CPU of 1GHz, there'd be 10K CPU clock cycles per 100kbps I2C clock cycle)
MOV v2, #100*1024 ; timeout - this should be more than adequate (with a CPU of 1GHz, there'd be 10K CPU clock cycles per 100kbps I2C clock cycle)
10
LDRH a4, [v4, #I2C_CON]
TST a4, #3 ; Check STT and STP (Although we're primarily interested in STP, the manual warns about bad things happening if STT is cleared)
BEQ %FT20
SUBS v2, v2, #1
BNE %BT10
LDRH a4, [v4, #I2C_CON]
TST a4, #3 ; Check STT and STP (Although we're primarily interested in STP, the manual warns about bad things happening if STT is cleared)
BEQ %FT20
SUBS v2, v2, #1
BNE %BT10
[ I2CDebug
DebugReg a4, "ISC_CON timeout: "
DebugReg a4, "ISC_CON timeout: "
]
MOV a1, #IICStatus_Busy
MOV v3, #0
STR v3, [v5, #I2C_XStart]
LDMFD sp!, {v1-v5,pc}
MOV a1, #IICStatus_Busy
MOV v3, #0
STR v3, [v5, #I2C_XStart]
LDMFD sp!, {v1-v5,pc}
20
; Flush the RX/TX FIFOs
; The manual says we only need to do this on NACK errors, but to play it safe I'm going to do it at the start of each transfer
LDRH v2, [v4, #I2C_BUF]
LDR v3, =&4040
ORR v2, v2, v3
STRH v2, [v4, #I2C_BUF]
LDRH v2, [v4, #I2C_BUF]
LDR v3, =&4040
ORR v2, v2, v3
STRH v2, [v4, #I2C_BUF]
10
LDRH v2, [v4, #I2C_BUF]
TST v2, v3
BNE %BT10
LDRH v2, [v4, #I2C_BUF]
TST v2, v3
BNE %BT10
; Configure controller
; 1. I2C_CON.MST, ISC_CON.TRX
BIC a4, a4, #&FF ; Clear STT, STP, XOA0-XOA3
BIC a4, a4, #&F00 ; Clear STB, MST, TRX, XSA
ORR a4, a4, #&400 ; Set MST (slave mode not supported ATM)
TST a1, #1
ORREQ a4, a4, #&200 ; Set transmitter mode if appropriate
STRH a4, [v4, #I2C_CON]
BIC a4, a4, #&FF ; Clear STT, STP, XOA0-XOA3
BIC a4, a4, #&F00 ; Clear STB, MST, TRX, XSA
ORR a4, a4, #&400 ; Set MST (slave mode not supported ATM)
TST a1, #1
ORREQ a4, a4, #&200 ; Set transmitter mode if appropriate
STRH a4, [v4, #I2C_CON]
; Clear any pending interrupts, just in case?
LDRH v2, [v4, #I2C_STAT]
STRH v2, [v4, #I2C_STAT]
LDRH v2, [v4, #I2C_STAT]
STRH v2, [v4, #I2C_STAT]
; 2. I2C_IE.XRDY_IE, I2C_IE.RRDY
MOVEQ v2, #&17 ; AL_IE, NACK_IE, ARDY_IE, XRDY_IE
MOVNE v2, #&0F ; AL_IE, NACK_IE, ARDY_IE, RRDY_IE
ORREQ v2, v2, #&4000 ; XDR_IE
ORRNE v2, v2, #&2000 ; RDR_IE
STRH v2, [v4, #I2C_IE]
MOVEQ v2, #&17 ; AL_IE, NACK_IE, ARDY_IE, XRDY_IE
MOVNE v2, #&0F ; AL_IE, NACK_IE, ARDY_IE, RRDY_IE
ORREQ v2, v2, #&4000 ; XDR_IE
ORRNE v2, v2, #&2000 ; RDR_IE
STRH v2, [v4, #I2C_IE]
; 3. Ignore DMA for now
; 4. I2C_SA, I2C_CNT
MOV v2, a1, LSR #1
AND v2, v2, #&7F
STRH v2, [v4, #I2C_SA]
MOV v2, a1, LSR #1
AND v2, v2, #&7F
STRH v2, [v4, #I2C_SA]
; The I2C controller doesn't seem to like it if we don't send a start bit - it simply ignores I2C_CNT and goes straight to sending the stop bit (or sits there and does nothing if no stop bit was wanted).
; So to get around this we scan forward through the iic_transfer list and set I2C_CNT to the number of bytes to transmit before the next start/stop bit is required
MOV v2, v1
LDR ip, [v5, #I2C_XEnd]
MOV v2, v1
LDR ip, [v5, #I2C_XEnd]
10
CMP ip, v2
ORREQ a4, a4, #2 ; Last transfer in list; set stop bit
BEQ %FT20
ADD v2, v2, #12 ; Increment after compare, just in case some crazy person creates an iic_transfer that wraps from &FFF.... to &000...
LDMIA v2,{a1-a2,v3} ; Get transfer info
TST a1, #1:SHL:31
ADDNE a3, a3, v3 ; nostart is set; increment length and loop around
BNE %BT10
CMP ip, v2
ORREQ a4, a4, #2 ; Last transfer in list; set stop bit
BEQ %FT20
ADD v2, v2, #12 ; Increment after compare, just in case some crazy person creates an iic_transfer that wraps from &FFF.... to &000...
LDMIA v2,{a1-a2,v3} ; Get transfer info
TST a1, #1:SHL:31
ADDNE a3, a3, v3 ; nostart is set; increment length and loop around
BNE %BT10
20
[ I2CDebug
DebugReg a3, "I2C_CNT="
DebugReg a3, "I2C_CNT="
]
STRH a3, [v4, #I2C_CNT]
STRH a3, [v4, #I2C_CNT]
; 5. Wait for I2C_STAT.BB to 0 (but only if this is the first iic_transfer of a sequence - otherwise we'll be stuck waiting to unlock a bus we already own)
LDR v2, [v5, #I2C_XStart]
CMP v1, v2 ; v1 = I2C_XCurrent from earlier
BNE %FT20
MOV v2, #50*1024 ; timeout
LDR v2, [v5, #I2C_XStart]
CMP v1, v2 ; v1 = I2C_XCurrent from earlier
BNE %FT20
MOV v2, #50*1024 ; timeout
10
LDRH v3, [v4, #I2C_STAT]
TST v3, #1:SHL:12
BEQ %FT20
SUBS v2, v2, #1
BNE %BT10
LDRH v3, [v4, #I2C_STAT]
TST v3, #1:SHL:12
BEQ %FT20
SUBS v2, v2, #1
BNE %BT10
[ I2CDebug
DebugReg v3, "BB timeout: I2C_STAT="
DebugReg v3, "BB timeout: I2C_STAT="
]
MOV a1, #IICStatus_Busy
B clear_and_return
MOV a1, #IICStatus_Busy
B clear_and_return
20
; 6. configure I2C_CON.STT=1, I2C_CON.STP=0/1
ORR a4, a4, #1 ; Always send start bit
ORR a4, a4, #1 ; Always send start bit
; If required, stop bit will already have been set by the I2C_CNT calculator
STRH a4, [v4, #I2C_CON]
STRH a4, [v4, #I2C_CON]
; Now we just sit back and wait for the interrupts?
[ I2CDebug
DebugTX "Transfer started"
DebugTX "Transfer started"
]
MOV a1, #IICStatus_InProgress
LDMFD sp!, {v1-v5,pc}
MOV a1, #IICStatus_InProgress
LDMFD sp!, {v1-v5,pc}
; For receive:
; 1. Use I2C_IE.RRDY_IE
......@@ -439,255 +437,255 @@ start_transfer ; Start the transfer in v1
; Called on appropriate interrupt
HAL_IICMonitorTransfer
; Process the interrupts, according to figures 18-31/18-32 in spruf98b
STMFD sp!, {v1-v5,lr}
STMFD sp!, {v1-v5,lr}
[ I2CDebug
DebugReg a1, "HAL_IICMonitorTransfer: bus "
DebugReg a1, "HAL_IICMonitorTransfer: bus "
]
ADR v5, I2C_Table
MOV v4, #I2CBlockSize
MLA v5, a1, v4, v5
LDR v4, [v5, #I2C_HW]
LDR a1, [v5, #I2C_XStart]
ADR v5, I2C_Table
MOV v4, #I2CBlockSize
MLA v5, a1, v4, v5
LDR v4, [v5, #I2C_HW]
LDR a1, [v5, #I2C_XStart]
[ I2CDebug
DebugReg a1, "XStart="
DebugReg a1, "XStart="
]
LDRH v3, [v4, #I2C_STAT]
TEQ a1, #0 ; If no transfer, shut off all interrupts
ASSERT IICStatus_Completed=0
LDRH v3, [v4, #I2C_STAT]
TEQ a1, #0 ; If no transfer, shut off all interrupts
ASSERT IICStatus_Completed=0
[ I2CDebug
BNE %FT10
DebugTX "No XStart!"
TEQ a1, #0 ; reset EQ condition
BNE %FT10
DebugTX "No XStart!"
TEQ a1, #0 ; reset EQ condition
10
]
STREQH a1, [v4, #I2C_IE]
STREQH v3, [v4, #I2C_STAT]
LDMEQFD sp!, {v1-v5,pc}
STREQH a1, [v4, #I2C_IE]
STREQH v3, [v4, #I2C_STAT]
LDMEQFD sp!, {v1-v5,pc}
[ I2CDebug
DebugReg v3, "I2C_STAT="
]
TST v3, #2
BNE i2c_nack
TST v3, #1
BNE i2c_al
TST v3, #4
BNE i2c_ardy
TST v3, #1:SHL:14
BNE i2c_xdr
TST v3, #1:SHL:4
BNE i2c_xrdy
TST v3, #1:SHL:13
BNE i2c_rdr
TST v3, #1:SHL:3
BNE i2c_rrdy
DebugReg v3, "I2C_STAT="
]
TST v3, #2
BNE i2c_nack
TST v3, #1
BNE i2c_al
TST v3, #4
BNE i2c_ardy
TST v3, #1:SHL:14
BNE i2c_xdr
TST v3, #1:SHL:4
BNE i2c_xrdy
TST v3, #1:SHL:13
BNE i2c_rdr
TST v3, #1:SHL:3
BNE i2c_rrdy
; Did anything actually happen?
BIC v3, v3, #&1d00 ; Clear XUDF, ROVR, BB, BF - they're status bits and don't indicate anything we care about here
CMP v3, #0
MOVEQ a1, #IICStatus_InProgress ; If nothing interesting happened, claim everything is OK (required for polling-mode transfers, e.g. HAL_VideoIICOp)
LDMEQFD sp!, {v1-v5,pc}
BIC v3, v3, #&1d00 ; Clear XUDF, ROVR, BB, BF - they're status bits and don't indicate anything we care about here
CMP v3, #0
MOVEQ a1, #IICStatus_InProgress ; If nothing interesting happened, claim everything is OK (required for polling-mode transfers, e.g. HAL_VideoIICOp)
LDMEQFD sp!, {v1-v5,pc}
; Else bad stuff - unhandled interrupt
[ I2CDebugError
DebugReg v3, "Unhandled IRQ - "
DebugReg v3, "Unhandled IRQ - "
]
unexpected_error
MOV a1, #IICStatus_Error
MOV a1, #IICStatus_Error
clear_and_return
[ I2CDebug
DebugReg a1, "clear_and_return: "
DebugReg a1, "clear_and_return: "
]
STRH v3, [v4, #I2C_STAT]
MOV v3, #0
STR v3, [v5, #I2C_XStart]
LDMFD sp!, {v1-v5,pc}
STRH v3, [v4, #I2C_STAT]
MOV v3, #0
STR v3, [v5, #I2C_XStart]
LDMFD sp!, {v1-v5,pc}
i2c_nack
; No ack was received - give up and return error
MOV a1, #IICStatus_NoACK
B clear_and_return
MOV a1, #IICStatus_NoACK
B clear_and_return
i2c_al
; Arbitration lost - restart the transfer list
STRH v3, [v4, #I2C_STAT]
LDR v1, [v5, #I2C_XStart]
B start_transfer
STRH v3, [v4, #I2C_STAT]
LDR v1, [v5, #I2C_XStart]
B start_transfer
i2c_ardy
; Previous transfer has completed successfully; start a new one
LDR a3, [v5, #I2C_XCurrent]
LDR a2, [v5, #I2C_XBytes]
LDR ip, [a3, #8]
CMP a2, ip
LDR a3, [v5, #I2C_XCurrent]
LDR a2, [v5, #I2C_XBytes]
LDR ip, [a3, #8]
CMP a2, ip
[ I2CDebugError
BEQ %FT10
DebugTX "HW requested wrong byte count"
DebugReg a2, "I2C_XBytes="
DebugReg ip, "xfer len="
B unexpected_error
BEQ %FT10
DebugTX "HW requested wrong byte count"
DebugReg a2, "I2C_XBytes="
DebugReg ip, "xfer len="
B unexpected_error
10
|
BNE unexpected_error ; Hardware hasn't requested the full number of bytes
BNE unexpected_error ; Hardware hasn't requested the full number of bytes
]
LDR a4, [v5, #I2C_XEnd]
CMP a3, a4
MOVEQ a1, #IICStatus_Completed
BEQ clear_and_return
LDR a4, [v5, #I2C_XEnd]
CMP a3, a4
MOVEQ a1, #IICStatus_Completed
BEQ clear_and_return
; Skip any zero-length nostart transfers that follow this one
ADD v1, a3, #12
ADD v1, a3, #12
10
LDMIA v1, {a1-a3}
TST a1, #1:SHL:31
STREQH v3, [v4, #I2C_STAT]
BEQ start_transfer
CMP a3, #0
LDMIA v1, {a1-a3}
TST a1, #1:SHL:31
STREQH v3, [v4, #I2C_STAT]
BEQ start_transfer
CMP a3, #0
[ I2CDebugError
BEQ %FT5
DebugReg a3, "nostart transfer with nonzero length, length="
B unexpected_error
BEQ %FT5
DebugReg a3, "nostart transfer with nonzero length, length="
B unexpected_error
5
|
BNE unexpected_error ; nostart transfer with nonzero length = hardware hasn't requested full number of bytes
BNE unexpected_error ; nostart transfer with nonzero length = hardware hasn't requested full number of bytes
]
CMP v1, a4
MOVEQ a1, #IICStatus_Completed
BEQ clear_and_return
ADD v1, v1, #12
B %BT10
CMP v1, a4
MOVEQ a1, #IICStatus_Completed
BEQ clear_and_return
ADD v1, v1, #12
B %BT10
i2c_xdr
; Transfer I2C_BUFSTAT[5:0] bytes
LDRH a4, [v4, #I2C_BUFSTAT]
AND a4, a4, #&3F
B send_bytes
LDRH a4, [v4, #I2C_BUFSTAT]
AND a4, a4, #&3F
B send_bytes
i2c_xrdy
; Transfer I2C_BUF[5:0]+1 bytes
LDRH a4, [v4, #I2C_BUF]
AND a4, a4, #&3F
ADD a4, a4, #1
LDRH a4, [v4, #I2C_BUF]
AND a4, a4, #&3F
ADD a4, a4, #1
send_bytes
[ I2CDebug
DebugReg a4, "send_bytes: "
]
LDR v2, [v5, #I2C_XCurrent]
LDR a3, [v5, #I2C_XBytes] ; Get bytes sent
LDMIB v2, {a2,ip} ; Get data ptr, transfer length
LDR v2, [v5, #I2C_XCurrent]
LDR a3, [v5, #I2C_XBytes] ; Get bytes sent
LDMIB v2, {a2,ip} ; Get data ptr, transfer length
10
; Check if we need to advance to the next iic_transfer
CMP a3, ip
BEQ %FT20
LDRB v1, [a2,a3]
CMP a3, ip
BEQ %FT20
LDRB v1, [a2,a3]
[ I2CDebugData
DebugRegByte v1
DebugRegByte v1
]
ADD a3, a3, #1
SUBS a4, a4, #1
STRB v1, [v4, #I2C_DATA]
BNE %BT10
ADD a3, a3, #1
SUBS a4, a4, #1
STRB v1, [v4, #I2C_DATA]
BNE %BT10
[ I2CDebugData
DebugTX ""
]
STR a3, [v5, #I2C_XBytes]
MOV a1, #IICStatus_InProgress
STRH v3, [v4, #I2C_STAT]
LDMIA sp!, {v1-v5,pc}
STR a3, [v5, #I2C_XBytes]
MOV a1, #IICStatus_InProgress
STRH v3, [v4, #I2C_STAT]
LDMIA sp!, {v1-v5,pc}
20
; Advance to next iic_transfer
LDR a3, [v5, #I2C_XEnd]
CMP a3, v2
LDR a3, [v5, #I2C_XEnd]
CMP a3, v2
[ I2CDebugError
BNE %FT5
DebugTX "End of transfer list but hardware wants more"
B unexpected_error
BNE %FT5
DebugTX "End of transfer list but hardware wants more"
B unexpected_error
5
|
BEQ unexpected_error ; Hardware is asking for more data than we can give
]
ADD v2, v2, #12
STR v2, [v5, #I2C_XCurrent]
MOV a3, #0
STR a3, [v5, #I2C_XBytes]
LDMIA v2, {a1-a2,ip}
TST a1, #1:SHL:31
BNE %BT10
BEQ unexpected_error ; Hardware is asking for more data than we can give
]
ADD v2, v2, #12
STR v2, [v5, #I2C_XCurrent]
MOV a3, #0
STR a3, [v5, #I2C_XBytes]
LDMIA v2, {a1-a2,ip}
TST a1, #1:SHL:31
BNE %BT10
[ I2CDebugError
DebugTX "nostart reached but hardware wants more"
DebugTX "nostart reached but hardware wants more"
]
B unexpected_error ; Hardware is asking for more data than we can give
B unexpected_error ; Hardware is asking for more data than we can give
i2c_rdr
; Read I2C_BUFSTAT[13:8] bytes
LDRH a4, [v4, #I2C_BUFSTAT]
MOV a4, a4, LSR #8
ANDS a4, a4, #&3F ; ERRATA - sometimes RDR is set when there's no data. So, don't attempt to read from the empty buffer.
BEQ %FT15
B read_bytes
LDRH a4, [v4, #I2C_BUFSTAT]
MOV a4, a4, LSR #8
ANDS a4, a4, #&3F ; ERRATA - sometimes RDR is set when there's no data. So, don't attempt to read from the empty buffer.
BEQ %FT15
B read_bytes
i2c_rrdy
; Read I2C_BUF[13:8]+1 bytes
LDRH a4, [v4, #I2C_BUF]
MOV a4, a4, LSR #8
AND a4, a4, #&3F
ADD a4, a4, #1
LDRH a4, [v4, #I2C_BUF]
MOV a4, a4, LSR #8
AND a4, a4, #&3F
ADD a4, a4, #1
read_bytes
[ I2CDebug
DebugReg a4, "read_bytes: "
]
LDR v2, [v5, #I2C_XCurrent]
LDMIA v2, {a1-a2,ip} ; Get checksum flag, data ptr/checksum, transfer length
LDR a3, [v5, #I2C_XBytes] ; Get bytes received
LDR v2, [v5, #I2C_XCurrent]
LDMIA v2, {a1-a2,ip} ; Get checksum flag, data ptr/checksum, transfer length
LDR a3, [v5, #I2C_XBytes] ; Get bytes received
10
; Check if we need to advance to the next iic_transfer
CMP a3, ip
BEQ %FT20
TST a1, #1:SHL:30 ; Checksum mode?
LDRB v1, [v4, #I2C_DATA]
ADDNE a2, a2, v1 ; adjust checksum
STREQB v1, [a2, a3]
CMP a3, ip
BEQ %FT20
TST a1, #1:SHL:30 ; Checksum mode?
LDRB v1, [v4, #I2C_DATA]
ADDNE a2, a2, v1 ; adjust checksum
STREQB v1, [a2, a3]
[ I2CDebugData
DebugRegByte v1
DebugRegByte v1
]
SUBS a4, a4, #1
ADD a3, a3, #1
BNE %BT10
SUBS a4, a4, #1
ADD a3, a3, #1
BNE %BT10
[ I2CDebugData
DebugTX ""
]
STR a2, [v2, #4] ; Update checksum
STR a3, [v5, #I2C_XBytes]
STR a2, [v2, #4] ; Update checksum
STR a3, [v5, #I2C_XBytes]
15
MOV a1, #IICStatus_InProgress
STRH v3, [v4, #I2C_STAT]
LDMIA sp!, {v1-v5,pc}
MOV a1, #IICStatus_InProgress
STRH v3, [v4, #I2C_STAT]
LDMIA sp!, {v1-v5,pc}
20
; Advance to next iic_transfer
LDR a3, [v5, #I2C_XEnd]
CMP a3, v2
LDR a3, [v5, #I2C_XEnd]
CMP a3, v2
[ I2CDebugError
BNE %FT5
DebugTX "End of transfer list but hardware received more data"
B unexpected_error
BNE %FT5
DebugTX "End of transfer list but hardware received more data"
B unexpected_error
5
|
BEQ unexpected_error ; Hardware is receiving more data than we want
]
ADD v2, v2, #12
STR v2, [v5, #I2C_XCurrent]
MOV a3, #0
STR a3, [v5, #I2C_XBytes]
LDMIA v2, {a1-a2,ip}
TST a1, #1:SHL:31
BEQ unexpected_error ; Hardware is receiving more data than we want
]
ADD v2, v2, #12
STR v2, [v5, #I2C_XCurrent]
MOV a3, #0
STR a3, [v5, #I2C_XBytes]
LDMIA v2, {a1-a2,ip}
TST a1, #1:SHL:31
[ I2CDebugError
BNE %FT5
DebugTX "nostart reached but hardware received more data"
B unexpected_error
BNE %FT5
DebugTX "nostart reached but hardware received more data"
B unexpected_error
5
|
BEQ unexpected_error ; Hardware is receiving more data than we want
BEQ unexpected_error ; Hardware is receiving more data than we want
]
TST a1, #1:SHL:30 ; Checksum mode?
MOVNE a2, #0 ; Start with zero checksum (as per start_transfer)
B %BT10
TST a1, #1:SHL:30 ; Checksum mode?
MOVNE a2, #0 ; Start with zero checksum (as per start_transfer)
B %BT10
; int HAL_VideoIICOp(uint32_t op, uint8_t *buffer, uint32_t *size)
......@@ -703,75 +701,62 @@ read_bytes
HAL_VideoIICOp
; Make sure we've got a valid IIC bus to use
LDRB a4, [sb, #BoardConfig_VideoI2C]
CMP a4, #255
MOV ip, #0
STREQ ip, [a3]
MOVEQ a1, #IICStatus_Error
MOVEQ pc, lr
LDRB a4, [sb, #BoardConfig_VideoI2C]
CMP a4, #255
MOV ip, #0
STREQ ip, [a3]
MOVEQ a1, #IICStatus_Error
MOVEQ pc, lr
; Check for input passed end
UBFX a4, a1, #0, #16
CMP a4, #256
STRCS ip, [a3]
MOVCS a1, #IICStatus_Completed
MOVCS pc, lr
UBFX a4, a1, #0, #16
CMP a4, #256
STRCS ip, [a3]
MOVCS a1, #IICStatus_Completed
MOVCS pc, lr
; Clip request at end
Push "a1-a3,lr"
LDR a3, [a3]
ADD ip, a4, a3
CMP ip, #256
RSBHI a3, a4, #256
Push "a1-a3,lr"
LDR a3, [a3]
ADD ip, a4, a3
CMP ip, #256
RSBHI a3, a4, #256
; Build a set of iic_transfer blocks and call RISCOS_IICOpV
; We construct two iic_transfer blocks
; - First block is a single byte write containing the start address (lower 8 bits of r0)
; - Second block is a read. r2 bytes written to r1.
; Block 2:
UBFX a1, a1, #16, #8 ; Extract base IICAddress
Push "a1-a3" ; Push the block on the stack (a2 & a3 are already correct)
UBFX a1, a1, #16, #8 ; Extract base IICAddress
Push "a1-a3" ; Push the block on the stack (a2 & a3 are already correct)
; Block 1:
BIC a1, a1, #1 ; Clear RnW of base address
ADD a2, sp, #12 ; sp+12 should point to the 8 bit offset
MOV a3, #1
Push "a1-a3"
BIC a1, a1, #1 ; Clear RnW of base address
ADD a2, sp, #12 ; sp+12 should point to the 8 bit offset
MOV a3, #1
Push "a1-a3"
; Now attempt to start the transfer
LDRB a2, [sb, #BoardConfig_VideoI2C]
MOV a2, a2, LSL #24
ADD a2, a2, #2
MOV a1, sp
LDRB a2, [sb, #BoardConfig_VideoI2C]
MOV a2, a2, LSL #24
ADD a2, a2, #2
MOV a1, sp
; If HAL_Init isn't done yet, we can't use RISCOS_IICOpV
LDR a3, HALInitialised
CMP a3, #0
BEQ %FT10
LDR a3, OSentries+4*OS_IICOpV
BLX a3
; Unmap RISC OS error numbers to IICStatus return codes
ASSERT IICStatus_Completed = 0
TEQ a1, #0
LDRNE a1, [a1]
LDRNE lr, =ErrorNumber_IIC_NoAcknowledge
SUBNE a1, a1, lr ; 0/1/2 = NoAck/Error/Busy
USATNE a1, #2, a1 ; 4+ => 3 = Error
ADRNE lr, %FT05
LDRNEB a1, [lr, a1]
B %FT20
05
ASSERT (ErrorNumber_IIC_Error - ErrorNumber_IIC_NoAcknowledge) = 1
ASSERT (ErrorNumber_IIC_Busy - ErrorNumber_IIC_NoAcknowledge) = 2
DCB IICStatus_NoACK, IICStatus_Error, IICStatus_Busy, IICStatus_Error
LDR a3, HALInitialised
CMP a3, #0
BEQ %FT10
LDR a3, OSentries+4*OS_IICOpV
BLX a3
B %FT20
10
BL IIC_DoOp_Poll
BL IIC_DoOp_Poll
20
; In case of error, assume nothing got transferred at all
CMP a1, #IICStatus_Completed
LDREQ a4, [sp, #(3*4)+(2*4)] ; Clipped block 2 request size
MOVNE a4, #0
ADD sp, sp, #24 ; Junk the iic_transfer blocks
STR a1, [sp, #0] ; Propagate return code
LDR a3, [sp, #8]
STR a4, [a3] ; Actual transfer size
Pull "a1-a3,pc"
CMP a1, #IICStatus_Completed
LDREQ a4, [sp, #(3*4)+(2*4)] ; Clipped block 2 request size
MOVNE a4, #0
ADD sp, sp, #24 ; Junk the iic_transfer blocks
STR a1, [sp, #0] ; Propagate return code
LDR a3, [sp, #8]
STR a4, [a3] ; Actual transfer size
Pull "a1-a3,pc"
IIC_DoOp_Poll
; IIC transfer function that performs a polling transfer, similar to HAL_VideoIICOp
......@@ -781,35 +766,35 @@ IIC_DoOp_Poll
; r1 = bits 0-23: iic_transfer count
; bits 24-31: bus number
; Returns IICStatus return code in R0 (0 success, anything else failure)
Push "v1,lr"
Push "v1,lr"
[ {FALSE}
; If IRQs and IIC IRQ are enabled, panic
Push "a1-a4"
MRS a1, CPSR
TST a1, #I32_bit
BNE %FT10
ADR a1, BoardConfig_HALI2CIRQ
LDRB a1, [a1, a2, LSR #24]
IMPORT HAL_IRQDisable
BL HAL_IRQDisable
CMP a1, #0
BEQ %FT10
DebugTX "Warning - IIC_DoOp_Poll called with IIC IRQ enabled!"
B .
Push "a1-a4"
MRS a1, CPSR
TST a1, #I32_bit
BNE %FT10
ADR a1, BoardConfig_HALI2CIRQ
LDRB a1, [a1, a2, LSR #24]
IMPORT HAL_IRQDisable
BL HAL_IRQDisable
CMP a1, #0
BEQ %FT10
DebugTX "Warning - IIC_DoOp_Poll called with IIC IRQ enabled!"
B .
10
Pull "a1-a4"
Pull "a1-a4"
]
MOV a3, a1
MOV a1, a2, LSR #24
BIC a2, a2, #&ff000000
MOV v1, a1
BL HAL_IICTransfer
MOV a3, a1
MOV a1, a2, LSR #24
BIC a2, a2, #&ff000000
MOV v1, a1
BL HAL_IICTransfer
; Now just poll until we're done
10
CMP a1, #IICStatus_InProgress ; Done?
Pull "v1,pc", NE
ADR lr, %BT10
MOV a1, v1
B HAL_IICMonitorTransfer
CMP a1, #IICStatus_InProgress ; Done?
Pull "v1,pc", NE
ADR lr, %BT10
MOV a1, v1
B HAL_IICMonitorTransfer
END
......@@ -33,8 +33,8 @@
; For the majority of uses, v1 simply needs to be initialised as follows:
; LDR v1, OSentries+4*OS_IICOpV
; i.e. the IIC transfer will be performed on IIC bus 0, via RISCOS_IICOpV. This means that 0
; will be returned on success, or an OS error block pointer on failure!
; i.e. the IIC transfer will be performed on IIC bus 0, via RISCOS_IICOpV,
; returning an IICStatus.
; When using OS_IICOpV, v2 can be left uninitialised.
; TODO - Tidy this up - TPSRead/TPSWrite can simply choose for themselves whether to use OS_IICOpV or IIC_DoOp_Poll
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment