I have an I2C receive handler in a timing sensitive environment.
The vast majority of my I2C commands are only 2 bytes, so I have optimized performance for this case.
My interrupt handler reads from UCB0IV and dispatches to my RX handler using the typical IV offset trick.
The branch instruction reads the actual function address from RAM and dispatches the RX task to the target function.
In this example, my target functions are i2c_rx_0, i2c_rx_1 and i2c_rx_data.
i2c_rx_0 handles the first byte
i2c_rx_1 handles the second
i2c_rx_data handles the rest with bounds checking, etc but it is slow
I am finding that the code generated by GCC is subpar.
The flags used are
CFLAGS = -mmcu=$(MCU) -std=gnu11 -g -Os \
-Wall -pedantic -Wunused \
-ffunction-sections -fdata-sections -minrt -fomit-frame-pointer -fwrapv -MMD \
$(INCLUDES) $(USER_DEFINES)
I am expecting i2c_rx_0 and i2c_rx_1 to be only 21 clock cycles but I am seeing 29 clock cycles.
In what I post following, I should the culprit line that inflates the cycle count commented in i2c_rx_0 but left in i2c_rx_1
__attribute__ ((interrupt(EUSCI_B0_VECTOR))) static void USCIB0_ISR (void){ __asm__ ( "add &0x056e,r0 \n" /* SKIP This */ "reti \n" /* ALIFG */ "reti \n" /* NACKIFG */ "reti \n" .... /* RXIFG0 */ "jmp I2C_RX0\n" ... "I2C_RX0: br &APP_IRQ_I2C_RX0\n" .... } __attribute((interrupt)) void i2c_rx_0() { /* Store buffer in 0th position, * setup next interrupt call for 1st position. */ i2c_cmd_buffer[0] = UCB0RXBUF_L; APP_IRQ_I2C_RX0 = i2c_rx_1; //i2c_data_ptr = i2c_cmd_buffer + 1; } __attribute((interrupt)) void i2c_rx_1() { /* Store buffer in 1st position, * setup next interrupt call for general data. */ i2c_cmd_buffer[1] = UCB0RXBUF_L; APP_IRQ_I2C_RX0 = i2c_rx_data; i2c_data_ptr = i2c_cmd_buffer + 2; } Compiler output for i2_rx_0 0xf8d8: 0x42d2 mov.b &0x054c, &0x27b0 6 0xf8da: 0x054c 0xf8dc: 0x27b0 0xf8de: 0x40b2 mov.w #0xf8e6, &0x27de 5 0xf8e0: 0xf8e6 0xf8e2: 0x27de 0xf8e4: 0x1300 reti 5 Compiler output for i2c_rx_1 0xf8e6: 0x150c pushm.a #1, r12 3 0xf8e8: 0x403c mov.w #0x27b0, r12 2 0xf8ea: 0x27b0 0xf8ec: 0x42dc mov.b &0x054c, 0x1(r12) 6 0xf8ee: 0x054c 0xf8f0: 0x0001 0xf8f2: 0x40b2 mov.w #0xf902, &0x27de 5 0xf8f4: 0xf902 0xf8f6: 0x27de 0xf8f8: 0x532c add.w #2, r12 1 0xf8fa: 0x4c82 mov.w r12, &0x27c0 4 0xf8fc: 0x27c0 0xf8fe: 0x170c popm.a #1, r12 3
0xf900: 0x1300 reti 5