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

📄 spi.asm

📁 ADI公司SHARC与BlackFin通过SPI协议相互通信的源代码
💻 ASM
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
 Include Section
*****************************************************************************/

#include "global.h"
#include "INIT.h"
#include "data.h"

/*****************************************************************************
 Symbolic constants / definitions
******************************************************************************/

#if defined SPI_DMA
    #define SPI_CTL_VAL_TX  TDBR_DMA
    #define SPI_CTL_VAL_RX  RDBR_DMA
#else
    #define SPI_CTL_VAL_TX  RDBR_CORE
    #define SPI_CTL_VAL_RX  RDBR_CORE
#endif


#define DMA7_CONFIG_VAL     FLOW_STOP
#define DMA7_X_COUNT_VAL    N
#if defined SPI_WDSIZE_16
    #define DMA7_X_MODIFY_VAL   2
#else
    #define DMA7_X_MODIFY_VAL   1
#endif
#define DMA7_Y_COUNT_VAL    0
#define DMA7_Y_MODIFY_VAL   0

/*****************************************************************************
 Prototypes
******************************************************************************/

.GLOBAL __spi_run_tx;
.GLOBAL __spi_run_rx;
.GLOBAL __spi_stop;
 
#if defined PFHW
    .GLOBAL __hostwait_check;
    .GLOBAL __hostwait_assert;
#endif

//.GLOBAL spi_core_loop_run_tx;
//.GLOBAL spi_core_loop_run_rx;
//.GLOBAL spi_init_tx;
//.GLOBAL spi_init_rx;
//.GLOBAL spi_init;
//.GLOBAL spi_start;
//.GLOBAL spi_putc;
//.GLOBAL spi_getc;
//.GLOBAL spi_calc_baud;
//.GLOBAL hostwait_deassert;

/*****************************************************************************
 Functions
******************************************************************************/

.SECTION L1_code;

/*****************************************************************************
 Function:              __spi_run_tx
 Description:           run a SPI transmission -> receive SPI
 Input Parameters:      none
 Return Parameters:     none
 Registers Used:        none
 Global Variables Used: none
 C-Callable :           no
*****************************************************************************/

__spi_run_tx:
    link 0;

    call spi_init_tx;
    call spi_start;
    #if defined SPI_CORE_LOOP
        call spi_core_loop_run_tx;
    #endif

    unlink;
    rts;
__spi_run_tx.END:


/*****************************************************************************
 Function:              __spi_run_rx
 Description:           run a SPI tranmission -> transmit SPI
 Input Parameters:      none
 Return Parameters:     none
 Registers Used:        none
 Global Variables Used: none
 C-Callable :           no
*****************************************************************************/

__spi_run_rx:
    link 0;

    call spi_init_rx;
    call spi_start;
    #if defined SPI_CORE_LOOP
        call spi_core_loop_run_rx;
    #endif

    unlink;
    rts;
__spi_run_rx.END:


/*****************************************************************************
 Function:              spi_core_loop_run_tx
 Description:           run a SPI tranmission -> transmit SPI
                        Hardware Loop used
                        No Interrupts
 Input Parameters:      none
 Return Parameters:     none
 Registers Used:        R7,R0,P5:3,ASTAT,LOOPREG
 Global Variables Used: none
 C-Callable :           no
*****************************************************************************/

spi_core_loop_run_tx:

    link 0;
    [--SP] = ASTAT;
    [--SP] = (R7:7,P5:3);
    [--SP] = R0;
    PUSH_LOOP_REGx(0);
    IMM32(P5,SYS_MMR_BASE);


    /*************
    * SPI Enable *
    *************/
    call spi_init_tx;
    call spi_start;

    /***************
    * SPI transmit *
    ***************/
    IMM32(P4,tx_buf);
    IMM32(P3,N);

    /***********************
    * SPI-Transfer Section *
    ***********************/
    lsetup( spi_core_loop_run_tx.loop_start, spi_core_loop_run_tx.loop_end ) LC0 = P3;
    spi_core_loop_run_tx.loop_start:
    #if defined SPI_WDSIZE_16
        R0 = w[P4++] (z); /* Get next data to be transmitted */
    #else
        R0 = b[P4++] (z); /* Get next data to be transmitted */
    #endif
    spi_core_loop_run_tx.loop_end: call spi_putc;

    /**************
    * SPI Disable *
    **************/
    call __spi_stop;


    POP_LOOP_REGx(0);
    R0 = [SP++];
    (R7:7,P5:3) = [SP++];
    ASTAT = [SP++];
    unlink;

    rts;
spi_core_loop_run_tx.end:


/*****************************************************************************
 Function:              spi_putc
 Description:           run a SPI tranmission -> transmit SPI
                        Hardware Loop used
                        No Interrupts
 Input Parameters:      R0
 Return Parameters:     none
 Registers Used:        R7:6,P5,ASTAT
 Global Variables Used: none
 C-Callable :           no
*****************************************************************************/

spi_putc:

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


    w[P5 + lo(SPI_TDBR)] = R0; /* Write to SPI_TDBR */

    #if defined SPI_MASTER_MODE
        R7 = w[P5 + lo(SPI_CTL)] (z);
        R6 = TIMOD (z);
        R7 = R7 & R6;
        CC = R7 == RDBR_CORE;
        if !CC jump spi_putc.check_txs;
       /* Dummy read of SPI_RDBR kicks off transfer */
        R7 = w[P5 + lo(SPI_RDBR)] (z);
    #endif

    spi_putc.check_txs:     R7 = w[P5 + lo(SPI_STAT)] (z);
                            CC = bittst (R7,bitpos(TXS));
                            if CC jump spi_putc.check_txs;

    /* Poll for SPIF = 1 (SPI finished) */
    spi_putc.check_spif:    R7 = w[P5 + lo(SPI_STAT)] (z);
                            CC = bittst (R7,bitpos(SPIF));
                            if !CC jump spi_putc.check_spif;


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

    rts;
spi_putc.end:


/*****************************************************************************
 Function:              spi_core_loop_run_rx
 Description:           run a SPI tranmission -> transmit SPI
                        Hardware Loop used
                        No Interrupts
 Input Parameters:      none
 Return Parameters:     none
 Registers Used:        R7,R0,P5:3,ASTAT,LOOPREG
 Global Variables Used: none
 C-Callable :           no
 HINT:                  SPI Master Mode Version
*****************************************************************************/

spi_core_loop_run_rx:

    link 0;
    [--SP] = ASTAT;
    [--SP] = (R7:7,P5:3);
    [--SP] = R0;
    PUSH_LOOP_REGx(0);
    IMM32(P5,SYS_MMR_BASE);


    /*************
    * SPI Enable *
    *************/
    call spi_init_rx;
    call spi_start;

    /**************
    * SPI Receive *
    **************/
    IMM32(P4,rx_buf);
    #if defined SPI_MASTER_MODE
        IMM32(P3,(N-1));
    #elif defined SPI_SLAVE_MODE
        IMM32(P3,N);
    #endif

    /***********************
    * Pre-Transfer Section *
    ***********************/
    #if defined SPI_MASTER_MODE
        R7 = w[P5 + lo(SPI_RDBR)] (z); /* first read, dummy read */
    #endif

    /***********************
    * SPI-Transfer Section *
    ***********************/
    lsetup( spi_core_loop_run_rx.loop_start, spi_core_loop_run_rx.loop_end ) LC0 = P3;
    spi_core_loop_run_rx.loop_start: call spi_getc;

    #if defined SPI_WDSIZE_16
        spi_core_loop_run_rx.loop_end: w[P4++] = R0;
    #else
        spi_core_loop_run_rx.loop_end: b[P4++] = R0;
    #endif

    /************************
    * Post-Transfer Section *
    ************************/
    #if defined SPI_MASTER_MODE
        /* two consecutive reads of RXS are necessary */
        spi_core_loop_run_rx.check_rxs_last: /* Poll for RXS = 0 (Receive Data Buffer empty) */
        R7 = w[P5 + lo(SPI_STAT)] (z);
        CC = bittst (R7,bitpos(RXS));
        if !CC jump spi_core_loop_run_rx.check_rxs_last;
        R7 = w[P5 + lo(SPI_STAT)] (z);
        CC = bittst (R7,bitpos(RXS));
        if !CC jump spi_core_loop_run_rx.check_rxs_last;

        /* Poll for SPIF = 1 (SPI finished) */
        spi_core_loop_run_rx.check_spif_last:
        R7 = w[P5 + lo(SPI_STAT)] (z);
        CC = bittst (R7,bitpos(SPIF));
        if !CC jump spi_core_loop_run_rx.check_spif_last;

        R7 = w[P5 + lo(SPI_SHADOW)] (z);
        #if defined SPI_WDSIZE_16
            w[P4] = R7; /* last word to be copied from SPI_SHADOW (=SPI_RDBR) to memory */
        #else
            b[P4] = R7; /* last word to be copied from SPI_SHADOW (=SPI_RDBR) to memory */
        #endif
    #endif

    /**************
    * SPI Disable *
    **************/
    call __spi_stop;


    POP_LOOP_REGx(0);
    R0 = [SP++];
    (R7:7,P5:3) = [SP++];
    ASTAT = [SP++];
    unlink;

    rts;
spi_core_loop_run_rx.end:


/*****************************************************************************
 Function:              spi_getc
 Description:           run a SPI tranmission -> transmit SPI
                        Hardware Loop used
                        No Interrupts
 Input Parameters:      none
 Return Parameters:     R0
 Registers Used:        R7,P5,ASTAT
 Global Variables Used: none
 C-Callable :           no
*****************************************************************************/

spi_getc:

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


    /* two consecutive reads of RXS are necessary */
    spi_getc.check_rxs: R7 = w[P5 + lo(SPI_STAT)] (z);
                        CC = bittst (R7,bitpos(RXS));
                        if !CC jump spi_getc.check_rxs;
                        R7 = w[P5 + lo(SPI_STAT)] (z);
                        CC = bittst (R7,bitpos(RXS));
                        if !CC jump spi_getc.check_rxs;

    /* Poll for SPIF = 1 (SPI finished) */
    spi_getc.check_spif:    R7 = w[P5 + lo(SPI_STAT)] (z);
                            CC = bittst (R7,bitpos(SPIF));
                            if !CC jump spi_getc.check_spif;

    /* read word from SPI_RDBR */
    /* for a SPI master device this read from SPI_RDBR is requesting a next word from a slave device */
    /* therefore SPI_SHADOW should be read for the very last word */
    R0 = w[P5 + lo(SPI_RDBR)] (z);


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

    rts;
spi_getc.end:


/*****************************************************************************
 Function:              spi_init_tx
 Description:           Initialize SPI for transmiting
                        Initialize DMA for transmiting if defined
 Input Parameters:      none
 Return Parameters:     none
 Registers Used:        R7,P5
 Global Variables Used: none
 C-Callable :           no
*****************************************************************************/

spi_init_tx:

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


    /******
    * SPI *
    ******/
    R7 = SPI_CTL_VAL_TX (z);
    #if defined SPI_SZ
        bitset(R7,bitpos(SZ));
    #endif
    /* use EMISO bit to identify transmit or receive mode for both master and slave */
    bitset(R7,bitpos(EMISO));
    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 */
               nWNR         |   /* DMA Direction */
               nDMAEN       (z);/* DMA Channel Enable */
        w[P5 + lo(DMA7_CONFIG)] = R7;

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

    call spi_init;


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

    rts;
spi_init_tx.end:


/*****************************************************************************
 Function:              spi_init_rx
 Description:           Initialize SPI for receiving

⌨️ 快捷键说明

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