⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bbu_i2c.s

📁 关于PXA310的最小系统的程序,初级学习阶段会有所帮助,汇编语言编写的
💻 S
📖 第 1 页 / 共 3 页
字号:
;
; 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 + -