Hi Angus, thanks for the feedback!
I had a look at the performance penalty of using the slower address.
I counted the cycles used for a call to "i2cSetCmd" for both variants.
Using the 3xxx address, I get at 0.733µs,while the 6xxx address makes i2cSetCmd take 1.046µs or 142.7% of the original version.
That's not too bad, but generally a bit slow for both variants, considering we're only updating a single peripheral register.
Since the 6xxx address doesn't require a read-modify-write-cycle to work, there's some room for optimizations now:
I modified i2cSetCmd to update an I2C command in memory and write the resulting word into the hardware
Code: Select all
typedef struct {
union {
struct {
uint32_t byte_num: 8;
uint32_t ack_en: 1;
uint32_t ack_exp: 1;
uint32_t ack_val: 1;
uint32_t op_code: 3;
uint32_t reserved14: 17;
uint32_t done: 1;
};
uint32_t val;
} command;
} i2c_cmd_t;
i2c_cmd_t cmd = { .command.val=0 };
void i2cSetCmd(i2c_t * i2c, uint8_t index, uint8_t op_code, uint8_t byte_num, bool ack_val, bool ack_exp, bool ack_check)
{
cmd.command.ack_en = ack_check;
cmd.command.ack_exp = ack_exp;
cmd.command.ack_val = ack_val;
cmd.command.byte_num = byte_num;
cmd.command.op_code = op_code;
i2c->dev->command[index].val = cmd.command.val;
}
The new version clocks in @ 0.092µs , or about 8x faster than the original.
I'll let this run until tomorrow to see if something broke, and then do the same for the remaining i2c functions.
Cheers
Edit: forgot an initializer...