From 7c84c62b90c5081e77b7416be701fb64f6be7beb Mon Sep 17 00:00:00 2001 From: Robert Sprowson <rsprowson@gitlab.riscosopen.org> Date: Sat, 28 Sep 2013 07:07:51 +0000 Subject: [PATCH] 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' --- VersionASM | 12 +- VersionNum | 20 +- s/I2C | 719 ++++++++++++++++++++++++++--------------------------- s/TPS | 4 +- 4 files changed, 370 insertions(+), 385 deletions(-) diff --git a/VersionASM b/VersionASM index e94a37f..de41309 100644 --- a/VersionASM +++ b/VersionASM @@ -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 diff --git a/VersionNum b/VersionNum index 9d3976c..062bbf1 100644 --- a/VersionNum +++ b/VersionNum @@ -1,23 +1,23 @@ -/* (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" diff --git a/s/I2C b/s/I2C index 74aa3ce..b8c5561 100644 --- a/s/I2C +++ b/s/I2C @@ -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 diff --git a/s/TPS b/s/TPS index e64cca6..1e4a45b 100644 --- a/s/TPS +++ b/s/TPS @@ -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 -- GitLab