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

📄 spi.asm

📁 ADI公司SHARC与BlackFin通过SPI协议相互通信的源代码
💻 ASM
📖 第 1 页 / 共 2 页
字号:
                        Initialize DMA for receiving if defined
 Input Parameters:      none
 Return Parameters:     none
 Registers Used:        R7:6,P5
 Global Variables Used: none
 C-Callable :           no
*****************************************************************************/

spi_init_rx:

    link 0;
    [--SP] = (R7:6,P5:5);
    IMM32(P5,SYS_MMR_BASE);


    /******
    * SPI *
    ******/
    R7 = SPI_CTL_VAL_RX (z);
    #if defined SPI_GM
        bitset(R7,bitpos(GM));
    #endif
    w[P5 + lo(SPI_CTL)] = R7;


    /******
    * DMA *
    ******/
    #if defined SPI_DMA
        R7 =    FLOW_STOP   |   /* Next Operation */
                DI_EN       |   /* Data Interrupt Enable */
               nDI_SEL      |   /* Data Interrupt Timing Select */
               nSYNC        |   /* Work Unit Transitions */
               nDMA2D       |   /* DMA Mode */
                WDSIZE_8    |   /* Transfer Word Size */
                WNR         |   /* DMA Direction */
               nDMAEN       (z);/* DMA Channel Enable */
        w[P5 + lo(DMA7_CONFIG)] = R7;

        IMM32(R7,rx_buf);
        [P5 + lo(DMA7_START_ADDR)] = R7;
    #endif

    call spi_init;


    (R7:6,P5:5) = [SP++];
    unlink;

    rts;
spi_init_rx.end:


/*****************************************************************************
 Function:              spi_init
 Description:           Basic SPI settings, that are not specific to
                        direction and/or master<->slave mode
                        Start SPI
                        Start DMA, if defined
 Input Parameters:      none
 Return Parameters:     none
 Registers Used:        R7:6,R0,P5,ASTAT
 Global Variables Used: none
 C-Callable :           no
*****************************************************************************/

spi_init:

    link 0;
    [--SP] = ASTAT;
    [--SP] = (R7:6,P5:5);
    [--SP] = R0;
    IMM32(P5,SYS_MMR_BASE);


    /* In Master SPI Receive Mode, TIMOD = 10 */
    /* Always enable first DMA, then SPI */
    /* SPI raises immediately an interrupt when enabled */

    /* In Master SPI Transmit Mode, TIMOD = 11 */
    /* SPI starts with the first write access of the DMA */
    /* When SPI is enabled (without enabled DMA), SPI clock is going down (if pulled-up) */


    /******
    * DMA *
    ******/
    #if defined SPI_DMA
        R7 = 0 (z);
        [P5 + lo(DMA7_NEXT_DESC_PTR)] = R7;
        [P5 + lo(DMA7_CURR_DESC_PTR)] = R7;
        [P5 + lo(DMA7_CURR_ADDR)] = R7;
        R7 = PMAP_SPI (z);
        w[P5 + lo(DMA7_PERIPHERAL_MAP)] = R7;
        R7 = DMA7_X_COUNT_VAL (z);
        w[P5 + lo(DMA7_X_COUNT)] = R7;
        R7 = DMA7_Y_COUNT_VAL (z);
        w[P5 + lo(DMA7_Y_COUNT)] = R7;
        R7 = DMA7_X_MODIFY_VAL (z);
        w[P5 + lo(DMA7_X_MODIFY)] = R7;
        R7 = DMA7_Y_MODIFY_VAL (z);
        w[P5 + lo(DMA7_Y_MODIFY)] = R7;

        R7 = w[P5 + lo(DMA7_CONFIG)] (z);

        #if defined SPI_WDSIZE_16
            bitset(R7,bitpos(WDSIZE_16));
        #endif

        w[P5 + lo(DMA7_CONFIG)] = R7;
    #endif


    /******
    * SPI *
    ******/
    #if defined SPI_MASTER_MODE
        #if defined SPI_BAUD_VAL
            R7 = SPI_BAUD_VAL (z);
            /* ensure that SPI baud register value is >= 2 */
            CC = R7 < 2;
            if !CC jump rskip;
            R7 = 2 (z);
            rskip:
            /* set SPI Baud register value */
            w[P5 + lo(SPI_BAUD)] = R7;
        #else
            call spi_calc_baud;
            w[P5 + lo(SPI_BAUD)] = R0;
        #endif

        R7 = w[P5 + lo(SPI_FLG)] (z);
        R6 = 0x1;
        R6 <<= SPI_SLAVE;
        R7 = R7 | R6;
        #if defined SPI_CPHA /* if CPHA = 1 and MSTR = 1, write to SPI_FLG to select slave(s) via FLGx bits */
            R6 <<= 8;
            R6 = ~R6;
            R7 = R6 & R7;
        #endif
        w[P5 + lo(SPI_FLG)] = R7;
    #endif


    R7 = w[P5 + lo(SPI_CTL)] (z);

    #if defined SPI_WDSIZE_16
        bitset(R7,bitpos(SIZE));
    #endif
    #if defined SPI_LSBF
        bitset(R7,bitpos(LSBF));
    #endif
    #if defined SPI_CPHA
        bitset(R7,bitpos(CPHA));
    #endif
    #if defined SPI_CPOL_LOW
        bitset(R7,bitpos(CPOL));
    #endif
    #if defined SPI_MASTER_MODE
        bitset(R7,bitpos(MSTR));
    #endif

    w[P5 + lo(SPI_CTL)] = R7;


    R0 = [SP++];
    (R7:6,P5:5) = [SP++];
    ASTAT = [SP++];
    unlink;

    rts;
spi_init.end:


/*****************************************************************************
 Function:              spi_start
 Description:           Basic SPI settings, that are not specific to
                        direction and/or master<->slave mode
                        Start SPI
                        Start DMA, if defined
 Input Parameters:      none
 Return Parameters:     none
 Registers Used:        R7:6,P5
 Global Variables Used: none
 C-Callable :           no
*****************************************************************************/

spi_start:

    link 0;
    [--SP] = (R7:6,P5:5);
    IMM32(P5,SYS_MMR_BASE);


    /* In Master SPI Receive Mode, TIMOD = 10 */
    /* Always enable first DMA, then SPI */
    /* SPI raises immediately an interrupt when enabled */

    /* In Master SPI Transmit Mode, TIMOD = 11 */
    /* SPI starts with the first write access of the DMA */
    /* When SPI is enabled (without enabled DMA), SPI clock is going down (if pulled-up) */


    /******
    * DMA *
    ******/
    #if defined SPI_DMA
        R7 = w[P5 + lo(DMA7_CONFIG)] (z);
        bitset(R7,bitpos(DMAEN));
        w[P5 + lo(DMA7_CONFIG)] = R7;
        ssync;
    #endif


    /******
    * SPI *
    ******/
    R7 = w[P5 + lo(SPI_CTL)] (z);
    bitset(R7,bitpos(SPE));
    w[P5 + lo(SPI_CTL)] = R7;
    ssync;

    #if defined (SPI_SLAVE_MODE) && defined (PFHW)
        call hostwait_deassert;
    #endif

    #if defined SPI_DMA
        idle; /* wait for SPI DMA interrupt wake-up */
    #endif


    (R7:6,P5:5) = [SP++];
    unlink;

    rts;
spi_start.end:


/****************************************************************************
 Function:              __spi_stop
 Description:           Stop and disable SPI (and SPI DMA)
                        Stop and disable SPI DMA, if defined
 Input Parameters:      none
 Return Parameters:     none
 Registers Used:        R7,P5
 Global Variables Used: none
 C-Callable :           no
*****************************************************************************/

__spi_stop:

    link 0;
    [--SP] = (R7:7,P5:5);
    IMM32(P5,SYS_MMR_BASE);

    #if defined (SPI_SLAVE_MODE) && defined (PFHW)
        call __hostwait_assert;
    #endif

    #if defined SPI_DMA
        R7 = 0 (z);
        w[P5 + lo(DMA7_CONFIG)] = R7; /* Disable DMA */
    #endif


    #if defined SPI_MASTER_MODE
        R7 = 0xFF00 (z);
        w[P5 + lo(SPI_FLG)] = R7; /* reset SPI_FLAG register */
    #endif

    R7 = 0 (z);
    w[P5 + lo(SPI_BAUD)] = R7;

    R7 = CPHA (z);
    w[P5 + lo(SPI_CTL)] = R7;   /* reset SPI_CTL register -> disable SPI */

    R7 =       nSPIF    |   /* SPI Finished (RO) */
                MODF    |   /* Mode Fault Error (W1C) */
                TXE     |   /* Transmission Error (W1C) */
               nTXS     |   /* TDBR Data Buffer Status (RO) */
                RBSY    |   /* Receive Error (W1C) */
               nRXS     |   /* RDBR Data Buffer Status (RO) */
                TXCOL   (z);/* Transmit Collision Error (W1C) */
    w[P5 + lo(SPI_STAT)] = R7; /* W1C: clear status bits */

    R7 = w[P5 + lo(SPI_RDBR)] (z); /* dummy read to clear RXS bit */
    R7 = w[P5 + lo(SPI_SHADOW)] (z); /* dummy read to clear RXS bit */


    (R7:7,P5:5) = [SP++];
    unlink;

    rts;
__spi_stop.end:


#if defined SPI_MASTER_MODE
/****************************************************************************
 Function:              spi_calc_baud
 Description:           generic SPI baud rate calculation function
 Input Parameters:      none
 Return Parameters:     R0
 Registers Used:        R1,R0,ASTAT
 Global Variables Used: none
 C-Callable :           no
*****************************************************************************/

spi_calc_baud:

    link 0;
    [--SP] = ASTAT;
    [--SP] = R1;

    call __get_sclk_hz;
    IMM32(R1,2*FSPI0CLK_Hz);
    udiv32();

    /* SPI_BAUD <= 0xFFFF */
    spi_calc_baud.check_once:
    IMM32(R1,0xFFFF);
    CC = R1 < R0;
    if !CC jump spi_calc_baud.check_twice;
    R0 = R1;
    jump spi_calc_baud.completed;

    /* SPI_BAUD > 0x1 */
    spi_calc_baud.check_twice:
    R1 = 2 (z);
    CC = R0 < R1;
    if !CC jump spi_calc_baud.completed;
    R0 = R1;

    spi_calc_baud.completed:
    R1 = [SP++];
    ASTAT = [SP++];
    unlink;

    rts;
spi_calc_baud.end:
#endif /* SPI_MASTER_MODE */


#if defined PFHW
/*****************************************************************************
 Function:              __hostwait_assert
 Description:           assert hostwait signal, active low signal
 Input Parameters:      none
 Return Parameters:     none
 Registers Used:        R7,P5
 Global Variables Used: none
 C-Callable :           no
******************************************************************************/

__hostwait_assert:
    link 0;
    [--SP] = (R7:7,P5:5);
    IMM32(P5,SYS_MMR_BASE);

    R7 = PFHW (z);
    w[P5 + lo(PORTFIO_CLEAR)] = R7;
    ssync;

    (R7:7,P5:5) = [SP++];
    unlink;

    rts;
__hostwait_assert.end:


/*****************************************************************************
 Function:              hostwait_deassert
 Description:           de-assert hostwait signal, active low signal
 Input Parameters:      none
 Return Parameters:     none
 Registers Used:        R7,P5
 Global Variables Used: none
 C-Callable :           no
******************************************************************************/

hostwait_deassert:
    link 0;
    [--SP] = (R7:7,P5:5);
    IMM32(P5,SYS_MMR_BASE);

    R7 = PFHW (z);
    w[P5 + lo(PORTFIO_SET)] = R7;
    ssync;

    (R7:7,P5:5) = [SP++];
    unlink;

    rts;
hostwait_deassert.end:


/*****************************************************************************
 Function:              __hostwait_check
 Description:           wait for HOSTWAIT signal to be deasserted
 Input Parameters:      none
 Return Parameters:     none
 Registers Used:        R7,P5,ASTAT
 Global Variables Used: none
 C-Callable :           no
*****************************************************************************/

__hostwait_check:
    link 0;
    [--SP] = ASTAT;
    [--SP] = (R7:7,P5:5);
    IMM32(P5,SYS_MMR_BASE);

    __hostwait_check.wait:
    R7 = w[P5 + lo(PORTFIO)] (z);
    CC = bittst(R7,bitpos(PFHW));
    if !CC jump __hostwait_check.wait;

    (R7:7,P5:5) = [SP++];
    ASTAT = [SP++];
    unlink;

    rts;
__hostwait_check.END:
#endif /* defined PFHW */


/*****************************************************************************
 EOF
******************************************************************************/

⌨️ 快捷键说明

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