-
Notifications
You must be signed in to change notification settings - Fork 8.1k
drivers: ipm: add ipm_rpi_pico #92923
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
dsseng
commented
Jul 9, 2025
- dts: bindings: ipm: add raspberrypi,pico-sio-fifo
- drivers: ipm: add ipm_rpi_pico
- dts: arm: rp2350: add SIO FIFO
273b297
to
3d77304
Compare
drivers/ipm/ipm_rpi_pico.c
Outdated
}; | ||
static struct rpi_pico_ipm_data rpi_pico_mailbox_data; | ||
|
||
static int rpi_pico_mailbox_send(const struct device *dev, int wait, uint32_t id, const void *data, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had to look at the docs for ipm_send() to figure out that int wait
is (per the API) being used as a boolean. Strange!
I haven't tested these changes, but they look good to me. |
Rebased AMP on top of this, it works |
62e7f37
to
5aad599
Compare
@soburi could you please take another look when you have time? Thank you! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, your work is good. I have some comments. I'd appreciate if you could take a look.
drivers/ipm/ipm_rpi_pico.c
Outdated
const struct rpi_pico_mailbox_config *config = | ||
(const struct rpi_pico_mailbox_config *)dev->config; | ||
|
||
if (!(config->sio_regs->fifo_st & SIO_FIFO_ST_RDY_BITS) && !wait) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the wait parameter is not supported in this function, should we return it like this
Lines 133 to 136 in ba3662a
if (wait == 0) { | |
LOG_ERR("not support no wait mode when sending ipm msg"); | |
return -ENOTSUP; | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it unsupported on the API side? On my side (maybe I should refactor or comment if something is unclear) I do this:
If must not wait and no space in FIFO: EBUSY
Else: spin on FIFO becoming available
Could you please elaborate what is wrong with this model?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the wait
parameter represents microseconds for k_busy_wait
. I inferred this because it mentions busy-wait
zephyr/include/zephyr/drivers/ipm.h
Lines 129 to 133 in ba3662a
* @param wait If nonzero, busy-wait for remote to consume the message. The | |
* message is considered consumed once the remote interrupt handler | |
* finishes. If there is deferred processing on the remote side, | |
* or you would like to queue outgoing messages and wait on an | |
* event/semaphore, you can implement that in a high-level driver |
and this driver implementation seems to follow that approach.
zephyr/drivers/ipm/ipm_esp32.c
Lines 121 to 136 in ba3662a
while (!atomic_cas(&dev_data->control->lock, | |
ESP32_IPM_LOCK_FREE_VAL, | |
dev_data->this_core_id)) { | |
k_busy_wait(1); | |
if ((wait != -1) && (wait > 0)) { | |
/* lock could not be held this time, return */ | |
wait--; | |
if (wait == 0) { | |
irq_unlock(key); | |
return -ETIMEDOUT; | |
} | |
} | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure, because there are at least 2 examples where it is used as a bool, not time duration:
Line 187 in 5ac8c48
if (wait) { Line 215 in 5ac8c48
if (wait) { zephyr/tests/drivers/ipm/src/ipm_dummy.c
Lines 75 to 79 in 5ac8c48
if (wait) { while (driver_data->regs.busy) { /* busy-wait */ } }
@dcpleung could you please elaborate on this API aspect?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wait
acts as a boolean and is NOT the time to wait.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, it turns out we have no adequate means to check if TX FIFO is empty. We can know if TX FIFO is full or not, and if we tried to push to it while it was full. What could be the options here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I implement something like an ACK the opposite side would return when it has consumed the message, and when we receive that ACK we set a readiness flag/sync object?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dcpleung could you please suggest the correct implementation of IPM API for the device? Should it maybe not support wait or even be converted to MBOX?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An ACK mechanism should work. The driver can be made to never support waiting. As the doxygen said, you can implement such waiting on higher lever driver. You can then implement the ACK mechanism there. As long as it is documented correctly, it should be okay.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Used ARG_UNUSED(wait);
just like many examples in the subsys
status = "disabled"; | ||
}; | ||
|
||
ipm0: sio-fifo@d0000000 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other drivers cannot use the address range written here.
In other words, if you create a driver that uses other SIO addresses,
an address overlap will occur, and a DTS compilation error will occur.
It is best to limit the address range to that used by the FIFO.
(In fact, pico-sdk functions can escape this restriction. But expecting it is bad design.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes sense. SIO also features spinlocks, doorbells, timer and other interesting parts. So perhaps this should just cover the FIFO register ranges? Will handle that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Otherwise, it would be impossible to coexist with drivers for other functions.
In fact, the pico-sdk implementation doesn't take DTS into account, so it's just a formal check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would I instantiate a sio_hw_t
struct though? Shall I just subtract 0x50
from the address? Seems quite a bit hacky. Another option: just ignore the address from the DT, use a HAL-provided instance and assert on address other than SIO_BASE+SIO_FIFO_ST_OFFSET
, will probably go this way for now to avoid overabstraction
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think subtracting the offset from the dts value is fine, but
I'm not particularly picky as long as the symbol name is clear.
/* | ||
* FIFO mailbox allows a single 32 bit value to be sent - and we | ||
* use that as the channel identifier. | ||
*/ | ||
return 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could it maybe make sense to do some kind of a split, like 1/3 or 2/2 byte split for ID/Data? 2^32 seems like quite a huge number of channels for most applications, while sending some data as well might be a cool feature for debugging or if any IPM/MBOX consumers want to transfer some data as well
This device uses SIO block of RP2 chips to pass messages between cores. Signed-off-by: Dmitrii Sharshakov <[email protected]>
This commit introduces an interprocess mailbox driver for the RP2 family. Tested on RP2350, but should be compatible with RP2040 as well. For IPM communication, the driver sends ID as a 32-bit value through the SIO FIFO. The data size is always 0. Co-authored-by: Dan Collins <[email protected]> Signed-off-by: Dan Collins <[email protected]> Signed-off-by: Dmitrii Sharshakov <[email protected]>
SIO block has a pair of FIFO queues for inter-processor communication. Signed-off-by: Dmitrii Sharshakov <[email protected]>
|
ipm0: sio-fifo@d0000050 { | ||
compatible = "raspberrypi,pico-sio-fifo"; | ||
reg = <0xd0000050 0xc>; | ||
reg-names = "sio"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"sio_fifo" is better here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct, thanks. Now this range only covers 3 FIFO registers
k_busy_wait(1); | ||
} | ||
|
||
sio_hw->fifo_wr = id; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it okay not to use spinlock for exclusion here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, not sure, it could cause an issue when there're 3 items in the mailbox, we checked in 2 threads, one pushed and another is yet to push, which will discard the message. This fn has to be wrapped in some thread safety method, yes, thanks
This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time. |