Keep buffer base & size mask in high registers.
The high registers (r8-r14) cannot be used directly by most of the instructions in the Cortex-M0 instruction set. One of the few instructions that can use them is mov, which can use any pair of registers. This allows saving two cycles, by replacing two loads (2 cycles each) with moves (1 cycle each), after stashing the required values in high registers at startup.
This commit is contained in:
@ -66,8 +66,8 @@ shadow registers.
|
|||||||
|
|
||||||
There are two key code paths, with the following worst-case timings:
|
There are two key code paths, with the following worst-case timings:
|
||||||
|
|
||||||
RX: 151 cycles
|
RX: 149 cycles
|
||||||
TX: 136 cycles
|
TX: 134 cycles
|
||||||
|
|
||||||
Design
|
Design
|
||||||
======
|
======
|
||||||
@ -120,6 +120,8 @@ registers and fixed memory addresses.
|
|||||||
|
|
||||||
/* Allocations of single-use registers */
|
/* Allocations of single-use registers */
|
||||||
|
|
||||||
|
buf_base .req r12
|
||||||
|
buf_mask .req r11
|
||||||
sgpio_data .req r7
|
sgpio_data .req r7
|
||||||
sgpio_int .req r6
|
sgpio_int .req r6
|
||||||
buf_ptr .req r5
|
buf_ptr .req r5
|
||||||
@ -134,6 +136,10 @@ main:
|
|||||||
// Initialise registers used for constant values.
|
// Initialise registers used for constant values.
|
||||||
ldr sgpio_int, =SGPIO_EXCHANGE_INTERRUPT_BASE // 2
|
ldr sgpio_int, =SGPIO_EXCHANGE_INTERRUPT_BASE // 2
|
||||||
ldr sgpio_data, =SGPIO_SHADOW_REGISTERS_BASE // 2
|
ldr sgpio_data, =SGPIO_SHADOW_REGISTERS_BASE // 2
|
||||||
|
ldr r0, =TARGET_DATA_BUFFER // 2
|
||||||
|
mov buf_base, r0 // 1
|
||||||
|
ldr r0, =TARGET_BUFFER_MASK // 2
|
||||||
|
mov buf_mask, r0 // 1
|
||||||
loop:
|
loop:
|
||||||
// The worst case timing is assumed to occur when reading the interrupt
|
// The worst case timing is assumed to occur when reading the interrupt
|
||||||
// status register *just* misses the flag being set - so we include the
|
// status register *just* misses the flag being set - so we include the
|
||||||
@ -164,7 +170,7 @@ loop:
|
|||||||
str r1, [sgpio_int, #INT_CLEAR] // 8
|
str r1, [sgpio_int, #INT_CLEAR] // 8
|
||||||
|
|
||||||
// ... and grab the address of the buffer segment we want to write to / read from.
|
// ... and grab the address of the buffer segment we want to write to / read from.
|
||||||
ldr r0, =TARGET_DATA_BUFFER // r0 = &buffer // 2
|
mov r0, buf_base // r0 = &buffer // 1
|
||||||
ldr r3, =TARGET_BUFFER_POSITION // r3 = &position_in_buffer // 2
|
ldr r3, =TARGET_BUFFER_POSITION // r3 = &position_in_buffer // 2
|
||||||
ldr r2, [r3] // r2 = position_in_buffer // 2
|
ldr r2, [r3] // r2 = position_in_buffer // 2
|
||||||
add buf_ptr, r0, r2 // buf_ptr = &buffer + position_in_buffer // 1
|
add buf_ptr, r0, r2 // buf_ptr = &buffer + position_in_buffer // 1
|
||||||
@ -212,7 +218,7 @@ direction_rx:
|
|||||||
done:
|
done:
|
||||||
|
|
||||||
// Finally, update the buffer location...
|
// Finally, update the buffer location...
|
||||||
ldr r0, =TARGET_BUFFER_MASK // 2
|
mov r0, buf_mask // 1
|
||||||
and r0, buf_ptr, r0 // r0 = (pos_in_buffer + size_copied) % buffer_size // 1
|
and r0, buf_ptr, r0 // r0 = (pos_in_buffer + size_copied) % buffer_size // 1
|
||||||
|
|
||||||
// ... restore &position_in_buffer, and store the new position there...
|
// ... restore &position_in_buffer, and store the new position there...
|
||||||
|
Reference in New Issue
Block a user