Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ;--------------------------------------------------------------------------------
- ; File: rx_isr_asm.S - msp430 gcc asm version of SoftSerial_RX_ISR (faster code)
- ;
- ; Desc: This code handles receiving serial data using the TIMERA1 ISR
- ; It starts out in capture mode waiting for the start bit (transition from
- ; high to low) then switches to compare mode for 8 bits. It accumulates
- ; each lsb->msb received bit into a byte and stores it in a ringbuffer
- ; The code attempts to minimize register usage to just r15.
- ;
- ; This code is about ~21 cycles faster than the C version.
- ; However, the code size is about 22 bytes larger. Useful if you want
- ; to run your F_CPU at a really low frequency and still receive data
- ;
- ; Author: rick@kimballsoftware.com
- ; Date: 08-01-2012
- ;
- #include <msp430.h>
- #include "config.h" /* for F_CPU, BAUD_RATE, and RX_BUFFER_SIZE */
- ;--------------------------------------------------------------------------------
- ; --- Defines
- ;--------------------------------------------------------------------------------
- #define PC r0 /* program counter */
- #define TIMERA1_VEC 8 /* TIMERA1_VECTOR/2 (0x0010)/2 */
- #define BIT_DUR (F_CPU/BAUD_RATE) /* cycle count between samples */
- #define BIT_DUR_1_5 (BIT_DUR)+(F_CPU/BAUD_RATE/2) /* 1.5 times a BIT_DUR */
- #define rb_head rx_buffer+0 /* offsets into ringbuffer_t struct */
- #define rb_tail rx_buffer+2
- #define rb_buf rx_buffer+4
- #define FOO (TIMERA1_VECTOR+1)/2
- ;--------------------------------------------------------------------------------
- ; .interrupt - macro to declare an interrupt handler routine entry point
- ;--------------------------------------------------------------------------------
- .macro .interrupt isr_offset
- .global __isr_\isr_offset
- __isr_\isr_offset:
- .endm
- ;--------------------------------------------------------------------------------
- ; --- BSS Data
- ;--------------------------------------------------------------------------------
- .section .bss.rx_isr_asm
- .p2align 1,0
- .lcomm state_vector,2
- .lcomm rx_mask,2
- .lcomm rx_data,2
- ;isrNo:
- ; .word FOO
- ;--------------------------------------------------------------------------------
- ; --- Code
- ;--------------------------------------------------------------------------------
- .text
- .p2align 1,0
- .global SoftSerial_RX_ISR
- .type SoftSerial_RX_ISR,@function
- .interrupt TIMERA1_VEC
- ;--------------------------------------------------------------------------------
- SoftSerial_RX_ISR:
- ;--------------------------------------------------------------------------------
- ; push, push, jump... ISR entry overhead 6 clocks
- ;push r15 ; preserve ... don't need to main reserved it for us
- bis.b #BIT0,&P1OUT ; uncomment to see where function ends.
- mov &TAIV, r6 ; reset interrupt flag by reading, we ignore btw
- add &state_vector,PC ; use state vector to jump directly to a handler
- jmp handle_startbit ; 0 start bit
- jmp handle_databit_0_6 ; 2 bits 0 - 6
- jmp handle_databit_0_6 ; 4
- jmp handle_databit_0_6 ; 6
- jmp handle_databit_0_6 ; 8
- jmp handle_databit_0_6 ; 10
- jmp handle_databit_0_6 ; 12
- jmp handle_databit_0_6 ; 14
- jmp handle_databit_7 ; 16 bit 7
- handle_startbit: ; handle start bit
- add #2, &state_vector ; set next handler
- bic #CAP, &TACCTL1 ; go into compare mode
- add #BIT_DUR_1_5, &TA0CCR1 ; set next sample in the middle of D0
- mov #0, &rx_data ; initialize recv byte
- mov #1, &rx_mask ; mask lsb -> msb
- jmp rx_isr_exit
- handle_databit_0_6: ; handle bits 0-6
- add #2, &state_vector ; set next handler
- add #BIT_DUR, &TA0CCR1 ; set next sample time
- mov &rx_mask, r6 ; load mask
- bit #SCCI, &TACCTL1 ; check latched sampled data bit
- jz 1f
- bis r6, &rx_data ; if HI then set this bit
- 1:
- rla r6 ; make room for next data bit
- mov r6, &rx_mask
- jmp rx_isr_exit
- handle_databit_7: ; handle last bit and store in ringbuffer
- mov #0, &state_vector ; go back to capture handler
- bit #SCCI, &TACCTL1 ; check latched sample data bit
- jz 1f
- bis #BIT7, &rx_data
- 1:
- mov &rb_head, r6 ; load rx_buffer.head
- mov.b &rx_data, rb_buf(r6) ; rx_buffer.buffer[head] = rx_data
- inc r6 ; rx_buffer.head++
- and #RX_BUFFER_SIZE-1, r6 ; take care of buffer wraparound, assumes power of 2 sized buf
- cmp r6, &rb_tail ; compare with tail
- jz 2f
- mov r6, &rb_head ; save new rx_buffer.head
- 2:
- bis #CAP, &TACCTL1 ; go back to capture mode
- rx_isr_exit:
- ;pop r15 ; standard exit
- xor.b #BIT0,&P1OUT ; uncomment to see where function ends.
- ; xor.b takes 5 clocks
- reti ; ISR exit overhead 5 cycles
- .Lfe1:
- .size SoftSerial_RX_ISR,.Lfe1-SoftSerial_RX_ISR
- ;--------------------------------------------------------------------------------
- ; EOF rx_isr_asm.S
- ;--------------------------------------------------------------------------------
Add Comment
Please, Sign In to add comment