📄 bbu_i2c.s
字号:
;
; This subroutine is used to read data from the Standard I2C bus using 16-bit
; register addresses and 8 bit data.
;
; PARAMETER PASSING:
;
; r0 = address in target device where data is to be read from (preserved)
;
; RETURNED VALUES:
;
; r1 = data read from the register pointed to by r0 (8-bit data)
; r2 = non zero if device was detected
; r2 = zero if device not detected (usually a time out issue)
;
BBU_getI2C_16 FUNCTION
stmfd sp!, {r3-r6, lr} ; Save used registers
;
; Make sure the clock to the I2C unit is enabled
; Init the I2C controller for use
;
ldr r4, =bbu_I2C_PHYSICAL_BASE ; Load Power Manager controller base address
mov r3, #bbu_ISR_BED ; This is the Bus Detect Error detect bit
str r3, [r4, #bbu_I2C_ISR_offset] ; Insure this bit is cleared (sticky bit)
mov r1, #0 ; Set host controller slave address
str r1, [r4, #bbu_I2C_ISAR_offset] ; Set slave address register
str r1, [r4, #bbu_I2C_ICR_offset] ; Clear interrupts in ICR
mov r3, #(bbu_ICR_IUE | bbu_ICR_SCLE) ; Set IUE and SCLE bits
str r3, [r4, #bbu_I2C_ICR_offset] ; Enable the I2C in ICR
;
; Get the slave's address
;
ldr r5, =bbu_FFUART_PHYSICAL_BASE ; Fetch base address of the FFUART
ldrb r6, [r5, #bbu_UASPR_offset] ; Get contents of the scratch pad register
str r6, [r4, #bbu_I2C_IDBR_offset] ; Load Data Buffer Register
;
; Send 1st byte
;
orr r3, r3, #(bbu_ICR_TB | bbu_ICR_START)
str r3, [r4, #bbu_I2C_ICR_offset] ; Set TB and START bits (in addition to IUE & SCLE)
mov r2, #BBU_I2C_TimeOut ; Set up time out value
2 ldr r3, [r4, #bbu_I2C_ISR_offset] ; Get status register contents
subs r2, r2, #1 ; Decrement time out value
beq %F12 ; Exit path if timed out
ands r3, r3, #bbu_ISR_ITE ; Was the byte sent yet?
beq %B2 ; No - still being transmitted
str r3, [r4, #bbu_I2C_ISR_offset] ; Write the ITE bit to clear it (sticky)
mov r2, #0x10 ; Set time out loop count to allow time
3 subs r2, r2, #1 ; for the BED bit to (possibly) be set
bne %B3 ; Loop until time out is zero
ldr r3, [r4, #bbu_I2C_ISR_offset] ; Get status register contents
ands r3, r3, #bbu_ISR_BED ; Get status of Bus Error bit
moveq r2, #0xF ; Insure non-zero time out if no error
;
; Set up and then send 2nd byte (Register Address bits 15:8)
;
mov r3, r0, LSR #8 ; Shift bits 15:8 into bits 7:0 of r3
strb r3, [r4, #bbu_I2C_IDBR_offset] ; Set register address in the IDBR
mov r3, #(bbu_ICR_TB | bbu_ICR_IUE | bbu_ICR_SCLE)
str r3, [r4, #bbu_I2C_ICR_offset] ; Set TB bit to start transfer
mov r2, #BBU_I2C_TimeOut ; Set up time out value
4 ldr r3, [r4, #bbu_I2C_ISR_offset] ; Get status register contents
subs r2, r2, #1 ; Decrement time out value
beq %F12 ; Exit path if timed out
ands r3, r3, #bbu_ISR_ITE ; Was the byte sent yet?
beq %B4 ; No - still being transmitted
str r3, [r4, #bbu_I2C_ISR_offset] ; Write the ITE bit to clear it (sticky)
;
; Set up and then send 3rd byte (Register Address bits 7:0)
;
strb r0, [r4, #bbu_I2C_IDBR_offset] ; Set register address in the IDBR
mov r3, #(bbu_ICR_TB | bbu_ICR_IUE | bbu_ICR_SCLE)
str r3, [r4, #bbu_I2C_ICR_offset] ; Set TB bit to start transfer
mov r2, #BBU_I2C_TimeOut ; Set up time out value
7 ldr r3, [r4, #bbu_I2C_ISR_offset] ; Get status register contents
subs r2, r2, #1 ; Decrement time out value
beq %F12 ; Exit path if timed out
ands r3, r3, #bbu_ISR_ITE ; Was the byte sent yet?
beq %B7 ; No - still being transmitted
str r3, [r4, #bbu_I2C_ISR_offset] ; Write the ITE bit to clear it (sticky)
;
; Delay 50 uS (clock is 3.6864 MHz)
;
5 ldr r2, =xlli_OSTREGS_PHYSICAL_BASE ; Load OS timer base address
ldr r3, [r2, #xlli_OSCR0_offset] ; Fetch starting value of OSCR0
add r3, r3, #0xB8 ; 0xB8 is about 50usec
6 ldr r5, [r2, #xlli_OSCR0_offset] ; Fetch current OSCR0 value
cmp r5, r3 ; Is the timer past the time out value?
bmi %B6 ; Not yet
;
; Set up and then send 4th byte - Slave read address
;
orr r6, r6, #1 ; Turn the address into a slave address
str r6, [r4, #bbu_I2C_IDBR_offset] ; Load Data Buffer Register
mov r3, #(bbu_ICR_TB | bbu_ICR_IUE | bbu_ICR_SCLE | bbu_ICR_START)
str r3, [r4, #bbu_I2C_ICR_offset] ; Set TB bit to start transfer
14 ldr r3, [r4, #bbu_I2C_ISR_offset] ; Get status register contents
ands r3, r3, #bbu_ISR_ITE ; Was the byte sent yet?
beq %B14 ; No - still being transmitted
str r3, [r4, #bbu_I2C_ISR_offset] ; Write the ITE & IRF bits to clear them
;
; Set up to receive the MS data byte
;
; mov r3, #(bbu_ICR_TB | bbu_ICR_IUE | bbu_ICR_SCLE )
; str r3, [r4, #bbu_I2C_ICR_offset] ; Set TB bit to start transfer
; mov r2, #BBU_I2C_TimeOut ; Set up time out value
;
; Set up and then receive a data bytes (byte 5)
;
;10 ldr r3, [r4, #bbu_I2C_ISR_offset] ; Get status register contents
; subs r2, r2, #1 ; Decrement time out counter
; moveq r2, #1 ; Reset to 1 if this transfer timed out
; beq %F12 ; Exit path if timed out
; ands r3, r3, #bbu_ISR_IRF ; Was the byte received yet?
; beq %B10 ; no - keep looping
; str r3, [r4, #bbu_I2C_ISR_offset] ; Write the IRF bit to clear it (sticky)
; ldr r1, [r4, #bbu_I2C_IDBR_offset] ; Fetch data byte from the IDBR
;
; Send STOP signal
;
mov r3, #(bbu_ICR_TB | bbu_ICR_IUE | bbu_ICR_SCLE | bbu_ICR_STOP | bbu_ICR_ACKNAK)
str r3, [r4, #bbu_I2C_ICR_offset] ; Set TB bit to start transfer
mov r2, #BBU_I2C_TimeOut ; Set up time out value
;
mov r2, #BBU_I2C_TimeOut ; Set up time out value
16 ldr r3, [r4, #bbu_I2C_ISR_offset] ; Get status register contents
subs r2, r2, #1 ; Decrement time out counter
moveq r2, #1 ; Reset to 1 if this transfer timed out
beq %F12 ; Exit path if timed out
ands r3, r3, #bbu_ISR_IRF ; Was the byte received yet?
beq %B16 ; no - keep looping
str r3, [r4, #bbu_I2C_ISR_offset] ; Write the IRF bit to clear it (sticky)
ldr r1, [r4, #bbu_I2C_IDBR_offset] ; Fetch data byte from the IDBR
;
; Combine the data in r1 and r3 to generate a 16 bit data word
;
; mov r1, r1, LSL #8 ; Shift left by 8 bits
; orr r1, r1, r3 ; OR in the low byte
12 ldmfd sp!, {r3-r6, pc} ; Return to caller
ENDFUNC
;
;*********************************************************************************
;
; *****************
; * *
; * BBU_putI2C_16 * Subroutine
; * *
; *****************
;
; This subroutine is used to write 8-bit data to an 16-bit address on the I2C bus
;
; PARAMETER PASSING:
;
; r0 = address in target device where data is to be sent
; r1 = data to be loaded into the register pointed to by r0
;
; RETURNED VALUE:
;
; r2 = non zero if no I2C bus time out
; r2 = zero if I2C bus time out
;
BBU_putI2C_16 FUNCTION
stmfd sp!, {r3-r6, lr} ; Save used registers
;
; Make sure the clock to the I2C unit is enabled
; Init the I2C controller for use
;
ldr r3, =bbu_I2C_PHYSICAL_BASE ; Load Power Manager controller base address
mov r2, #0 ; Set host controller slave address
str r2, [r3, #bbu_I2C_ISAR_offset] ; Set slave address register
str r2, [r3, #bbu_I2C_ICR_offset] ; Clear interrupts in ICR
mov r4, #(bbu_ICR_IUE | bbu_ICR_SCLE) ; Set IUE and SCLE bits
str r4, [r3, #bbu_I2C_ICR_offset] ; Enable the I2C in ICR
;
; Get the slave's address
;
ldr r5, =bbu_FFUART_PHYSICAL_BASE ; Fetch base address of FFUART
ldrb r6, [r5, #bbu_UASPR_offset] ; Get contents of the scratch pad register
str r6, [r3, #bbu_I2C_IDBR_offset] ; Load Data Buffer Register
;
; Send 1st byte
;
orr r4, r4, #(bbu_ICR_TB | bbu_ICR_START)
str r4, [r3, #bbu_I2C_ICR_offset] ; Set TB and START bits (in addition to IUE & SCLE)
mov r2, #BBU_I2C_TimeOut ; Set up time out loop
2 ldr r4, [r3, #bbu_I2C_ISR_offset] ; Get status register contents
subs r2, r2, #1 ; Decrement time out count
beq %F8 ; Timed out - return to caller
ands r4, r4, #bbu_ISR_ITE ; Was the byte sent yet?
beq %B2 ; No - still being transmitted
str r4, [r3, #bbu_I2C_ISR_offset] ; Write the ITE bit to clear it (sticky)
;
; Set up and then send 2nd byte (address bits 15:8)
;
mov r4, r0, LSR #8 ; Fetch upper 8 bits of address
strb r4, [r3, #bbu_I2C_IDBR_offset] ; Set register address in the IDBR
mov r4, #(bbu_ICR_TB | bbu_ICR_IUE | bbu_ICR_SCLE)
str r4, [r3, #bbu_I2C_ICR_offset] ; Set TB bit to start transfer
mov r2, #BBU_I2C_TimeOut ; Set up time out value
4 ldr r4, [r3, #bbu_I2C_ISR_offset] ; Get status register contents
subs r2, r2, #1 ; Decrement time out value
beq %F8 ; Return if there was a time out
ands r4, r4, #bbu_ISR_ITE ; Was the byte sent yet?
beq %B4 ; No - still being transmitted
str r4, [r3, #bbu_I2C_ISR_offset] ; Write the ITE bit to clear it (sticky)
;
; Set up and then send 3rd byte (address bits 7:0)
;
strb r0, [r3, #bbu_I2C_IDBR_offset] ; Set register address in the IDBR
mov r4, #(bbu_ICR_TB | bbu_ICR_IUE | bbu_ICR_SCLE)
str r4, [r3, #bbu_I2C_ICR_offset] ; Set TB bit to start transfer
mov r2, #BBU_I2C_TimeOut ; Set up time out value
5 ldr r4, [r3, #bbu_I2C_ISR_offset] ; Get status register contents
subs r2, r2, #1 ; Decrement time out value
beq %F8 ; Return if there was a time out
ands r4, r4, #bbu_ISR_ITE ; Was the byte sent yet?
beq %B5 ; No - still being transmitted
str r4, [r3, #bbu_I2C_ISR_offset] ; Write the ITE bit to clear it (sticky)
;
; Set up and then send 4th byte (LSB of DATA) and STOP signal
;
strb r1, [r3, #bbu_I2C_IDBR_offset] ; Place data byte into the IDBR
mov r4, #(bbu_ICR_TB | bbu_ICR_IUE | bbu_ICR_SCLE | bbu_ICR_STOP)
str r4, [r3, #bbu_I2C_ICR_offset] ; Set TB bit to start transfer
7 ldr r4, [r3, #bbu_I2C_ISR_offset] ; Get status register contents
ands r4, r4, #bbu_ISR_ITE ; Was the byte sent yet?
beq %B7 ; No - still being transmitted
str r4, [r3, #bbu_I2C_ISR_offset] ; Write the ITE bit to clear it (sticky)
8 ldmfd sp!, {r3-r6, pc} ; Return to caller
ENDFUNC
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -