drivers/can: Fix close drain, write-only reader lifecycle, and STM32 RX header#18759
drivers/can: Fix close drain, write-only reader lifecycle, and STM32 RX header#18759shizacat wants to merge 1 commit intoapache:masterfrom
Conversation
c9537e6 to
e1149b7
Compare
| * CONFIG_CAN_LOOPBACK) will falsely fail vs. zero-initialized TX header. | ||
| */ | ||
|
|
||
| memset(&hdr, 0, sizeof(hdr)); |
There was a problem hiding this comment.
@shizacat could you please verify if stm32f7, h7, and others using the same stm32_can.c driver need this fix too?
There was a problem hiding this comment.
I can’t reproduce this anymore with the fully modified code, so the issue might not be easily observable...
Do you think we should explicitly initialize the entire struct can_hdr_s (e.g., with memset), or rely on all fields being set individually before use?
Looking at the code
CAN, need fix every place that builds a struct can_hdr_s: stm32can_sceinterrupt and stm32can_rxinterrupt:
- stm32f7/stm32_can.c — yes
- stm32l4/stm32l4_can.c — yes
For FDCAN, the same idea applies to functions: fdcan_receive and fdcan_error:
- stm32h5/stm32_fdcan.c - yes
- stm32f0l0g0/stm32_fdcan.c - yes
There was a problem hiding this comment.
I think that only the timestamp is not set and can be garbage. If the problem is only with the timestamp, it may be better to zero its fields directly rather than using memset. I guess we'll save a few CPU cycles.
This problem can occur for other chips, not only stm32. The PR that added timestamp support for CAN character driver should reset this data filed for all lower CAN drivers.
e1149b7 to
267649d
Compare
|
|
||
| flags = enter_critical_section(); /* Disable interrupts */ | ||
|
|
||
| list_for_every(&dev->cd_readers, node) |
There was a problem hiding this comment.
why change? the behavour is same before/after modfication
There was a problem hiding this comment.
Rewritten this place as was
| while (!TX_EMPTY(&dev->cd_sender)) | ||
| { | ||
| nxsched_usleep(HALF_SECOND_USEC); | ||
| unsigned int n = 0; |
There was a problem hiding this comment.
move n declaration to the beginning, and
for (n = 0; !TX_EMPTY(&dev->cd_sender) && n < CAN_CLOSE_DRAIN_LOOPS; n++)
| nxsched_usleep(HALF_SECOND_USEC); | ||
| unsigned int n = 0; | ||
|
|
||
| while (!dev_txempty(dev) && n < CAN_CLOSE_DRAIN_LOOPS) |
| goto errout; | ||
| } | ||
|
|
||
| /* Last client: release the critical section before draining TX. |
There was a problem hiding this comment.
but new client may open device again after leaving critical section, how to handle this case
There was a problem hiding this comment.
... yep, you're right. I returned it as it was
198c069 to
c57c35d
Compare
…RX header Always allocate per-file can_reader on open so write-only descriptors get msgalign / ioctl state; free that context on close when it was never linked into cd_readers (fixes leak). Cap each drain loop (20×500 ms) so close() cannot block forever when bxCAN retries without ACK or dev_txempty never clears. Fix stm32can_vputreg debug log to print the written value (correct parameter name). Signed-off-by: Alexey Matveev <tippet@yandex.ru>
c57c35d to
9254bc3
Compare
Summary
This PR hardens the generic CAN character driver (drivers/can/can.c) and the STM32 bxCAN backend (arch/arm/src/stm32/stm32_can.c) for write-only use, safe shutdown, and consistent RX headers.
Impact
Loopback / full-header compare: Without clearing the RX header, apps that compare the whole header (loopback tests) could see spurious failures; this change makes RX headers deterministic.
close(): Unbounded waits on TX drain could freeze the app on a silent bus or endless retries; timeouts avoid infinite blocking while still calling dev_shutdown afterward.
Write-only open: Previously f_priv could stay NULL, breaking can_write (msgalign) and some ioctls—risk of fault/panic; allocating can_reader_s for every open fixes that.
Testing
Manual testing on stm32f103-minimum with a custom config (CAN loopback / Example CAN / app scenario as applicable).