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

📄 bbu_i2c.s

📁 关于PXA310的最小系统的程序,初级学习阶段会有所帮助,汇编语言编写的
💻 S
📖 第 1 页 / 共 3 页
字号:
;*********************************************************************************
;
;     COPYRIGHT (C) 2006 Marvell International Ltd. All Rights Reserved.
;
;   The information in this file is furnished for informational use only,
;   is subject to change without notice, and should not be construed as
;   a commitment by Marvell. Marvell assumes no responsibility or liability
;   for any errors or inaccuracies that may appear in this software or any
;   documenation that may be provided in association with this software.
;
;*********************************************************************************
;
;                                     I2C_CS.s
;                           Subroutines for the I2C bus
;
        INCLUDE xlli_PXA3xx_defs.inc
        INCLUDE bbu_Monahans_defs.inc

        GLOBAL  BBU_getI2C      ; Read from I2C bus
        GLOBAL  BBU_putI2C      ; Write to  I2C bus
        GLOBAL  BBU_getPI2C     ; Read from the power I2C bus
        GLOBAL  BBU_putPI2C     ; Write to the power I2C bus
        GLOBAL  BBU_getI2C_16   ; Read from I2C bus using 16-bit register address
        GLOBAL  BBU_putI2C_16   ; Write to I2C bus using 16-bit register address
;
; I2C BUS INTERFACE UNIT base address and register offsets from the base address
; 

bbu_I2C_PHYSICAL_BASE   EQU     0x40301680

bbu_I2C_IMBR_offset     EQU     0X00    ; I2C Bus Monitor Register
bbu_I2C_IDBR_offset     EQU     0X08    ; I2C Data Buffer Register
bbu_I2C_ICR_offset      EQU     0X10    ; I2C Control Register
bbu_I2C_ISR_offset      EQU     0X18    ; I2C Status Register
bbu_I2C_ISAR_offset     EQU     0X20    ; I2C Slave Address Register
bbu_I2C_ICCR_offset     EQU     0x28    ; Clock Count Register

bbu_ICR_IUE             EQU     0X0040  ; ICR I2C Unit enable bit
bbu_ICR_SCLE            EQU     0X0020  ; ICR I2C SCL Enable bit
bbu_ICR_TB              EQU     0X0008  ; ICR Transfer Byte bit
bbu_ICR_ACKNAK          EQU     0x0004  ; ICR ACK bit
bbu_ICR_STOP            EQU     0x0002  ; ICR STOP bit
bbu_ICR_START           EQU     0X0001  ; ICR START bit

bbu_ISR_IRF             EQU     0x0080  ; ISR Receive full bit
bbu_ISR_ITE             EQU     0x0040  ; ISR Transmit empty bit
bbu_PI2C_EN             EQU     0x0040  ; Power I2C enable bit
bbu_ISR_BED             EQU     0x0400  ; Bus Error Detect bit

BBU_I2C_TimeOut         EQU     0x2000  ; I2C bus timeout loop counter value

bbu_PMRCREGS_PHYSICAL_BASE      EQU     0x40F50000      ; Power manager base address

bbu_PCFR_offset         EQU     0x00C   ; Offset to Power Manager general config register
bbu_PI2DBR_offset       EQU     0x188   ; Power I2C Data Buffer Register
bbu_PI2CR_offset        EQU     0x190   ; Power I2C Control Register
bbu_PI2SR_offset        EQU     0x198   ; Power I2C Status Register
bbu_PI2SAR_offset       EQU     0x1A0   ; Power I2C Slave Address Register

        AREA  |text|,CODE,READONLY

;
;*********************************************************************************
;
;       **************
;       *            * 
;       * BBU_getI2C * Subroutine
;       *            *
;       **************
;
; This subroutine is used to read data from the Standard I2C bus
;
; PARAMETER PASSING:
;
;       r0 = address in target device where data is to be read from (preserved)
;       
;       NOTE: If read address equals 0x100, the code just returns after the device
;             address is sent. This can be used to discover if an address is used
;             without reading or writing any data to the device.
;
;             If read address equals 0x200, the code will read data back from certain
;             GPIO expanders used on the platform.
;
; RETURNED VALUES:
;
;       r1 = data read from the register pointed to by r0
;       r2 = non zero if device was detected
;       r2 = zero if device not detected (usually a time out issue)  
;
BBU_getI2C     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
        cmp     r0,     #0x100                          ; Special case - Just seeing if device is there?
        beq     %F12                                    ; Yes - just exit
        cmp     r0,     #0x200                          ; Special case - for reading from certain GPIO expanders?
        beq     %F5                                     ; Yes - jump to this code
;
;       Set up and then send 2nd byte (ADDRESS)
;
        str     r0,     [r4, #bbu_I2C_IDBR_offset]              ; Set register address in the IDBR
        mov     r3,     #(bbu_ICR_TB | bbu_ICR_IUE | bbu_ICR_SCLE | bbu_ICR_STOP)
        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)
;
;       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 3rd 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

8       ldr    r3,  [r4, #bbu_I2C_ISR_offset]             ; Get status register contents
        ands   r3,  r3,  #bbu_ISR_ITE                     ; Was the byte sent yet?
        beq    %B8                                        ; No - still being transmitted
        str    r3,  [r4, #bbu_I2C_ISR_offset]             ; Write the ITE & IRF bits to clear them (sticky)
;
;       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
;
;       Set up and then receive data byte
;
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
12      ldmfd   sp!,    {r3-r6, pc}     ; Return to caller

        ENDFUNC
;
;*********************************************************************************
;
;       **************
;       *            * 
;       * BBU_putI2C * Subroutine
;       *            *
;       **************
;
; This subroutine is used to write data to the Regular 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      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)
;
        str    r0,  [r3, #bbu_I2C_IDBR_offset]            ; Set register address in the IDBR
        mov    r4,  #(bbu_ICR_TB | bbu_ICR_IUE | bbu_ICR_SCLE)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -