aboutsummaryrefslogtreecommitdiff
path: root/lib/pbdrv
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pbdrv')
-rw-r--r--lib/pbdrv/drv/rp2040/mod.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/lib/pbdrv/drv/rp2040/mod.c b/lib/pbdrv/drv/rp2040/mod.c
index 26882f7..b572c4e 100644
--- a/lib/pbdrv/drv/rp2040/mod.c
+++ b/lib/pbdrv/drv/rp2040/mod.c
@@ -11,12 +11,13 @@
#define PBDRV_I2C i2c0
#define BUF_SIZE 256
-// NOTE: this function is called from the I2C ISR, and should return as quickly
-// as possible.
+/**
+ * \note this function is called from the I2C ISR, and should return as quickly
+ * as possible.
+ */
static void recv_event(i2c_inst_t *i2c, i2c_slave_event_t event) {
- uint8_t data[BUF_SIZE];
- size_t size = 0;
- // pbdrv_i2c_recv(NULL, 0);
+ static uint8_t data[BUF_SIZE];
+ static size_t size = 0;
switch (event) {
case I2C_SLAVE_RECEIVE: {
@@ -39,6 +40,18 @@ void pbdrv_setup() {
i2c_slave_init(PBDRV_I2C, PBDRV_MOD_ADDR, &recv_event);
}
+/**
+ * While the RP2040's datasheet claims it supports multi-master configurations
+ * by implementing bus arbitration, it does not natively support a mode where
+ * it is configured as a (multi-)master with a slave address, such that it can
+ * be addressed by other multi-masters. This function includes a hacky
+ * workaround that teporarily sets the RP2040 to I2C master mode to send a
+ * message, and then restores it back to slave mode.
+ *
+ * This approach results in some received frames being (partially) dropped in
+ * the time period between the invocation of this function and the bus becoming
+ * idle (and the message is sent).
+ */
__weak void pbdrv_i2c_send(i2c_addr_t addr, const uint8_t * buf, size_t sz) {
i2c_set_slave_mode(PBDRV_I2C, false, PBDRV_MOD_ADDR);