hardbyte / hardbyte/python-can
`BitTiming.from_sample_point` rejects valid timing solutions due to hardcoded register limits
- Ngôn ngữ chính
- Python
- Star
- 1.6k
- Fork
- 697
- Chỉ số merge pull request
- Không có pull request nào được merge trong 30 ngày
Mô tả
## Description
`BitTiming.from_sample_point` cannot find valid bit timings for some clock/bitrate combinations. The method calls `iterate_from_sample_point`, which constructs each `BitTiming` with `strict=True`. This parameter cannot be changed by the caller.
The `_validate` method enforces hardcoded register limits:
- `tseg1` ≤ 16
- `tseg2` ≤ 8
- `brp` ≤ 64
The strict mode tightens `brp` further to 32. These limits follow the CAN 2.0 minimum register specification. Many modern controllers support larger register ranges.
When a clock/bitrate combination produces timing values that all exceed at least one of these limits, the solver rejects every solution and raises `ValueError`.
## Example
STM32G431 with candlelight v2.5 firmware from https://github.com/Elmue/CANable-2.5-firmware-Slcan-and-Candlelight has a 160 MHz CAN clock. The FDCAN peripheral supports `brp` up to 512 and `tseg1` up to 256.
```python
from can import BitTiming
bt = BitTiming.from_sample_point(f_clock=160_000_000, bitrate=250_000, sample_point=87.5)
# Raises: ValueError: No suitable bit timings found.
```
The valid solution is `brp=40, tseg1=13, tseg2=2` (sample point = 87.5% exact). The solver finds this combination but rejects it because `brp=40` exceeds the strict limit of 32.
All lower prescaler values produce `tseg1` values that exceed 16:
| brp | tseg1 | tseg2 | sample point | rejected by |
|-----|-------|-------|--------------|-------------|
| 16 | 34 | 5 | 87.50% | `tseg1 > 16` |
| 20 | 27 | 4 | 87.50% | `tseg1 > 16` |
| 32 | 17 | 2 | 90.00% | `tseg1 > 16` |
| 40 | 13 | 2 | 87.50% | `brp > 32` (strict) |
## Affected code
- `bit_timing.py` — `iterate_from_sample_point` passes `strict=True` with no option to override
- `bit_timing.py` — `_restrict_to_minimum_range` limits `brp` to 32
- `bit_timing.py` — `_validate` limits `tseg1` to 16, `tseg2` to 8, `brp` to 64
## Suggested fix
Add optional limit parameters to `from_sample_point` and `iterate_from_sample_point`:
```python
@classmethod
def from_sample_point(
cls,
f_clock: int,
bitrate: int,
sample_point: float = 69.0,
tseg1_max: int = 16,
tseg2_max: int = 8,
brp_max: int = 64,
) -> "BitTiming":
```
Pass these limits through to `_validate` instead of using hardcoded values. This approach lets callers supply the actual register ranges reported by the hardware. The defaults remain unchanged, so existing behavior is not affected.
The gs_usb interface could populate these limits automatically from the device's `GS_USB_BREQ_BT_CONST` capability response, which already reports `tseg1_max`, `tseg2_max`, and `brp_max`.
## Workaround
Construct the `BitTiming` object directly. The constructor defaults to `strict=False`:
```python
bt = BitTiming(f_clock=160_000_000, brp=40, tseg1=13, tseg2=2, sjw=2)
```
## Affected version
4.6.1 (also present on `main`)
Hướng dẫn đóng góp
Hướng nghiên cứu
Start in bit_timing.py with BitTiming.from_sample_point and follow its call to iterate_from_sample_point, then inspect _restrict_to_minimum_range and _validate. Verify that caller-supplied register limits allow the STM32G431 example to produce brp=40, tseg1=13, and tseg2=2, while the existing default limits preserve current behavior.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- python
- Lĩnh vực
- embedded-iot
- Loại issue
- Lỗi
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức độ hoạt động
- Ít trao đổi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức phù hợp với người mới
- 72/100