📄 spi_tc.s
字号:
;------------------------------------------------------------------------------
;- ATMEL Microcontroller Software Support - ROUSSET -
;------------------------------------------------------------------------------
;- File source : spi_tc.s
;- Librarian : Not applicable
;- Translator : ARM Software Development Toolkit V2.11
;-
;- Treatments : SPI software emulator using TC channels 1 and 2.
;-
;- Imported Resources : None
;- Exported Resources :
;- spi_tc_init
;- spi_tc_transfer
;-
;- 1.0 JCZ 19/06/98 : Creation
;------------------------------------------------------------------------------
AREA AsmCode, CODE, READONLY, INTERWORK
; -------------------------- List of Included Files ---------------------------
INCLUDE tc.inc
INCLUDE pio.inc
; ------------------------ List of constants and types ------------------------
MR1_INIT EQU WAVE:OR:TC_XC1:OR:BURST_XC2:OR:EEVT_XC0
MR2_INIT EQU TC_MCK2:OR:WAVE:OR:EEVT_XC0:OR:CPCTRG:OR:ACPA_SET:OR:BCPC_SET:OR:ASWTRG_SET:OR:BSWTRG_SET
; SPI pins definition
TCLK2 EQU (&1<<6)
TIOA2 EQU (&1<<7)
TIOB2 EQU (&1<<8)
MISO EQU TCLK2
MOSI EQU TIOB2
SCK EQU TIOA2
; Baud rate by Default
BAUD_RATE EQU 0x10
; ------------------------ List of Imported resources -------------------------
; None
; ------------------------ List of Internal resources -------------------------
PtTCBBase
DCD TCBBase
PtPIOBase
DCD PIOBase
PtMR1Init
DCD MR1_INIT
PtMR2Init
DCD MR2_INIT
; ------------------------ List of Exported resources -------------------------
;------------------------------------------------------------------------------
;- Function : spi_tc_init
;- Treatments : SPI Initialization function.
;- Input Parameters :
;- r0 = Register C Value : period in number of twice MCK period
;- Output Parameters : None
;- Registers lost : None
;- Called Functions : None
;- Called Macros : None
;------------------------------------------------------------------------------
EXPORT spi_tc_init
;- Begin
spi_tc_init
ldr r1, PtTCBBase
ldr r2, PtPIOBase
;- | Configure SPI lines as PIO
mov r3, #MOSI:OR:SCK
str r3, [r2, #PIO_SODR]
str r3, [r2, #PIO_OER]
mov r3, #MOSI:OR:SCK:OR:MISO
str r3, [r2, #PIO_PER]
;- | TCC 1 and 2 : Disable current state
;- | . Disable all interrupts
mov r3, #0xFF
str r3, [r1, #(1*TC_SIZE)+TC_IDR]
str r3, [r1, #(2*TC_SIZE)+TC_IDR]
;- | . Disable the clock
mov r3, #CLKDIS
str r3, [r1, #(1*TC_SIZE)+TC_CCR]
str r3, [r1, #(2*TC_SIZE)+TC_CCR]
;- | Initialise TCC1 :
;- | . Enable TIOA2 (SCK) as the channel clock
mov r3, #XC1_TIOA2
str r3, [r1, #TC_BMR]
;- | . Initialize the Mode Register
ldr r3, PtMR1Init
str r3, [r1, #(1*TC_SIZE)+TC_CMR]
;- | . Enable and trig the clock
mov r3, #CLKEN:OR:SWTRG
str r3, [r1, #(1*TC_SIZE)+TC_CCR]
;- | Set Default baud rate (1Mbit/sec @ 32MHz) if applicable
cmp r0, #0
moveq r0, #BAUD_RATE
;- | Initialise TCC2 :
;- | . Setup the Mode Register
ldr r3, PtMR2Init
str r3, [r1, #(2*TC_SIZE)+TC_CMR]
;- | . Initialize the A, B and C counter registers
str r0, [r1, #(2*TC_SIZE)+TC_RC]
mov r3, r0, LSR #1
str r3, [r1,#(2*TC_SIZE)+TC_RA]
;- | . Enable the clock and trig to set the output signals
mov r3, #CLKEN:OR:SWTRG
str r3, [r1, #(2*TC_SIZE)+TC_CCR]
;- | . Disable the clock
mov r3, #CLKDIS
str r3, [r1, #(2*TC_SIZE)+TC_CCR]
;- | Configure SPI lines as peripheral
mov r3, #MOSI:OR:SCK:OR:MISO
str r3, [r2, #PIO_PDR]
;- End
mov pc, r14
;------------------------------------------------------------------------------
;- Function : spi_tc_transfer
;- Treatments : SPI Transfer function.
;- Input Parameters :
;- r0 = Address of Data to be transmitted
;- r1 = Address of Data to be received
;- r2 = Number of bits to transfer
;- Output Parameters : None
;- Registers lost : None
;- Called Functions : None
;- Called Macros : None
;------------------------------------------------------------------------------
;- During treatment :
;- r0 = Address of Data to be transmitted
;- r1 = Address of Data to be received
;- r2 = Number of bits to transfer
;- r3 = Current sent byte
;- r4 = Current received byte
;- r5 = Tx Transfer Bit Mask
;- r6 = Rx Transfer Bit Mask
;- r7 = TC2 Mode register with BCPC to set TIOB
;- r8 = TC2 Mode register with BCPC to clear TIOB
;- r9 = TC2 Mode register with TIOA and TIOB set
;- r10 = TC1 counter register
;- r11 = TC Block Base Address
;- r14 = Working register
;-----------------------------------------------------------------------------
EXPORT spi_tc_transfer
;- Begin
spi_tc_transfer
stmdb sp!, {r4-r11,r14}
;- | Get TC Block Base Address
ldr r11, PtTCBBase
;- | Save the current value of Timer Counter 1
ldr r10, [r11, #(1*TC_SIZE)+TC_CV]
;- | Initialize the Tx and Rx Masks
ldr r5, =0x80808080
mov r6, r5
;- | SCK falling edge at software trig and RC Compare
ldr r7, [r11, #(2*TC_SIZE)+TC_CMR]
bic r7, r7, #ASWTRG
orr r7, r7, #ASWTRG_CLEAR
orr r7, r7, #ACPC_CLEAR
;- | Calculate Mode Register values to set or clear data
bic r7, r7, #BCPC
orr r8, r7, #BCPC_CLEAR
orr r7, r7, #BCPC_SET
;- | Initialize the received byte (0)
mov r4, #0
;- | Get first byte to transmit
ldrb r3, [r0], #1
;- | TIOB (MOSI) set/cleared at SWTRG following first bit
ands r14, r3, r5
bic r14, r7, #BSWTRG
orreq r14, r14, #BSWTRG_CLEAR
orrne r14, r14, #BSWTRG_SET
str r14, [r11, #(2*TC_SIZE)+TC_CMR]
;- | Read TC2 Status (clear events)
ldr r14, [r11, #(2*TC_SIZE)+TC_SR]
;- | Enable and trig TC2 Clock
mov r14, #(CLKEN | SWTRG)
str r14, [r11, #(2*TC_SIZE)+TC_CCR]
;- | While (all bits not transfered)
b RepeatEnd ; 3
RepeatBegin1
;- | | If bit before last one
;- | | | force TIOA2 (SCK) unchanged at RC compare
biceq r7, r7, #ACPC ; 1
moveq r8, r7 ; 1
;- | | Endif
RepeatBegin2
;- | | Prepare next Tx bit : Right Shift Tx Mask
movs r5, r5, ROR #1 ; 1
;- | | If (last bit of the byte)
;- | | | get next byte
ldrcsb r3, [r0], #1 ; 3
;- | | EndIf
;- | | Wait RA compare (rising edge of SCK)
WaitSCKhigh
ldr r14, [r11, #(2*TC_SIZE)+TC_SR] ; 3
ands r14, r14, #CPAS ; 1
beq WaitSCKhigh ; 3 (worst)
;- | | TIOB (MOSI) set/cleared at next RC compare following current bit
ands r14, r3, r5 ; 1
streq r8, [r11, #(2*TC_SIZE)+TC_CMR] ; 2
strne r7, [r11, #(2*TC_SIZE)+TC_CMR] ; 2
;- | | If (TC1 Counter Value modified)
mov r14, r10 ; 1
ldr r10, [r11, #(1*TC_SIZE)+TC_CV] ; 3
cmp r14, r10 ; 1
;- | | | Set Rx Data Bit (current bit set)
orrne r4, r4, r6 ; 1
;- | | EndIf
;- | | Prepare next bit to receive : Right Shift Rx Mask
movs r6, r6, ROR #1 ; 1
;- | | If (last bit of the byte)
;- | | | store byte
strcsb r4, [r1], #1 ; 2
;- | | | Initialize the received byte (0)
movcs r4, #0 ; 1
;- | | EndIf
RepeatEnd
;- | EndWhile
subs r2, r2, #1 ; 1
; beq RepeatBegin1 ; 1 (best)
bpl RepeatBegin1 ; 3 (worst)
;- | store last byte (if needed)
ands r14, r6, #0x80 ; 1
streqb r4, [r1], #1 ; 2
;- | Wait end of last bit ( RC Compare )
WaitEnd
ldr r14, [r11, #(2*TC_SIZE)+TC_SR] ; 3
ands r14, r14, #CPCS ; 1
beq WaitEnd ; 1
;- | Disable TC2 Clock
mov r14, #CLKDIS
str r14, [r11, #(2*TC_SIZE)+TC_CCR]
;- End
ldmia sp!, {r4-r11,pc}
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -