Skip to content

[I2C, hal, SW] Restructured and refactored the functions#535

Open
KinzaQamar wants to merge 5 commits into
lowRISC:mainfrom
KinzaQamar:i2c_sw_modif
Open

[I2C, hal, SW] Restructured and refactored the functions#535
KinzaQamar wants to merge 5 commits into
lowRISC:mainfrom
KinzaQamar:i2c_sw_modif

Conversation

@KinzaQamar
Copy link
Copy Markdown
Contributor

@KinzaQamar KinzaQamar commented May 7, 2026

Taking the transfer checking part out from the i2c_read_byte() and i2c_write_byte() functions. It is needed when you want to controller wants to read / write multiple bytes.

Merge #545 first as a dependency on this PR

@KinzaQamar KinzaQamar marked this pull request as draft May 7, 2026 20:26
@KinzaQamar KinzaQamar force-pushed the i2c_sw_modif branch 8 times, most recently from c431f00 to a0269e1 Compare May 8, 2026 14:49
@KinzaQamar KinzaQamar marked this pull request as ready for review May 8, 2026 15:38
Comment thread sw/device/examples/i2c.c Outdated
Comment thread sw/device/lib/hal/i2c.c Outdated
@KinzaQamar KinzaQamar marked this pull request as draft May 11, 2026 19:33
@KinzaQamar KinzaQamar force-pushed the i2c_sw_modif branch 8 times, most recently from 49e9862 to ab7f1dc Compare May 12, 2026 12:20
@KinzaQamar KinzaQamar marked this pull request as ready for review May 12, 2026 12:20
@KinzaQamar
Copy link
Copy Markdown
Contributor Author

KinzaQamar commented May 13, 2026

Tested examples/i2c.c on an FPGA server:

image

Comment thread sw/device/lib/hal/i2c.c
Comment thread sw/device/lib/hal/i2c.c Outdated
Comment thread sw/device/lib/hal/i2c.c Outdated
@KinzaQamar KinzaQamar force-pushed the i2c_sw_modif branch 2 times, most recently from f9b5397 to ff319ad Compare May 13, 2026 19:45
@KinzaQamar KinzaQamar requested a review from engdoreis May 13, 2026 21:52
Copy link
Copy Markdown
Collaborator

@engdoreis engdoreis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@KinzaQamar KinzaQamar force-pushed the i2c_sw_modif branch 2 times, most recently from 26efa97 to 6224074 Compare May 19, 2026 11:29
@KinzaQamar
Copy link
Copy Markdown
Contributor Author

Hi @engdoreis,

I've addresses your comment. Meanwhile, testing the change I found out that a loop back test can't happen when the bytes we want to read are greater than FIFO_DEPTH

Comment thread sw/device/lib/hal/i2c.c Outdated
@KinzaQamar KinzaQamar force-pushed the i2c_sw_modif branch 2 times, most recently from 2cf67af to 00dc426 Compare May 20, 2026 21:05
Comment thread sw/device/lib/hal/i2c.h Outdated
Comment on lines +93 to +97
// Transmits a single byte to the target
void i2c_write_byte(i2c_t i2c, uint8_t addr, uint8_t data);
// Transmits multiple bytes to the target
void i2c_write_n_bytes(i2c_t i2c, uint8_t addr, const uint8_t *data, uint8_t num_wr_bytes);

// Receive a single byte from the target
void i2c_read_byte(i2c_t i2c, uint8_t addr);
// Receive n bytes from the target
void i2c_read_n_bytes(i2c_t i2c, uint8_t addr, uint8_t num_rd_bytes);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would prefer these to be called i2c_write_bytes and i2c_read_bytes, and the length parameter should just be called len.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted an n in b/w to indicate that the function can read / write one byte as well.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I think I'd go with your suggestion. As n_bytes and only bytes are same meaning

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and the length parameter should just be called len

I wanted to call it with a _bytes suffix to be explicit that these are the number of bytes to read and write. I can change it to num_bytes or len_bytes. Does that look sensible to you?

Comment thread sw/device/lib/hal/i2c.h Outdated
Comment thread sw/device/lib/hal/i2c.c Outdated
Comment on lines +90 to +98
// Check the overflow condition on every byte which is a multiple of 64.
if (overflow) {
i2c_status i2c_status_reg = VOLATILE_READ(i2c->status);

// Wait until FMT FIFO has some space
while (i2c_status_reg & i2c_status_fmtfull) {
i2c_status_reg = VOLATILE_READ(i2c->status);
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there is a bug here - it could be that after writing 64 bytes, the FIFO isn't full but is also not empty, so another 64 bytes would be written before checking the FIFO status again, which would overflow it. It's much more robust and simple to check whether the FIFO is full before writing each byte.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, that's interesting. I wanted to only check an overflow when there is a chance of overflow. I2C controller is fast enough to drain the FIFO so we will never get it full. But your comment is right that when the SW is fast and controller is slow, this check will lead to data loss. Thanks @ziuziakowska

@KinzaQamar KinzaQamar force-pushed the i2c_sw_modif branch 4 times, most recently from 05b27ab to 0f8b757 Compare May 21, 2026 15:26
Comment thread sw/device/lib/hal/i2c.c
Comment on lines +100 to 103
// Reset the FMT FIFO as a precautionary step in case something goes wrong when controller's FSM
// is halted and the SW didn't manage to clear the FIFO during that scenario.
i2c_fifo_ctrl fifo_ctrl_reg = { .fmtrst = 1u };
VOLATILE_WRITE(i2c->fifo_ctrl, fifo_ctrl_reg);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@elliotb-lowrisc Do we still need to keep this precautionary step before the start of every read and write no that we are clearing on errors?

@KinzaQamar KinzaQamar requested a review from ziuziakowska May 21, 2026 15:30
@KinzaQamar
Copy link
Copy Markdown
Contributor Author

Comments addressed !

Taking the transfer checking part out from the i2c_read_byte()
and i2c_write_byte() functions. It is needed when you want to
controller wants to read / write multiple bytes.

Signed-off-by: Kinza Qamar <kqzaman@lowrisc.org>
This is suggested in programmer's guide.

As a precautionary step, reset the FMT fifo before sending any transfer

Signed-off-by: Kinza Qamar <kqzaman@lowrisc.org>
Signed-off-by: Kinza Qamar <kqzaman@lowrisc.org>
Signed-off-by: Kinza Qamar <kqzaman@lowrisc.org>
…depth

Signed-off-by: Kinza Qamar <kqzaman@lowrisc.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants