📄 spi.asm
字号:
/****************************************************************************
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 + -