Tôi có trình điều khiển yêu cầu độ trễ micro giây. Để tạo độ trễ này, trình điều khiển của tôi đang sử dụng chức năng udelay của hạt nhân. Cụ thể, có một cuộc gọi đến udelay (90):Nhân Linux: udelay() trả về quá sớm?
iowrite32(data, addr + DATA_OFFSET);
iowrite32(trig, addr + CONTROL_OFFSET);
udelay(30);
trig |= 1;
iowrite32(trig, addr + CONTROL_OFFSET);
udelay(90); // This is the problematic call
Chúng tôi đã gặp sự cố về độ tin cậy với thiết bị. Sau nhiều lần gỡ lỗi, chúng tôi đã tìm ra vấn đề với trình điều khiển tiếp tục trước khi 90us trôi qua. (Xem "bằng chứng" bên dưới.)
Tôi đang chạy phiên bản hạt nhân 2.6.38-11-chung SMP (Kubuntu 11.04, x86_64) trên Intel Pentium Dual Core (E5700).
Theo như tôi biết, tài liệu tuyên bố rằng udelay sẽ trì hoãn thực hiện cho ít nhất độ trễ được chỉ định và không thể ngắt. Có lỗi nào trong phiên bản này của hạt nhân không, hoặc tôi có hiểu lầm về việc sử dụng udelay không?
Để thuyết phục bản thân rằng vấn đề là do udelay trở về quá sớm, chúng tôi ăn một đồng hồ 100kHz với một trong các cổng vào/O và thực hiện chậm trễ của chúng ta như sau:
// Wait until n number of falling edges
// are observed
void clk100_delay(void *addr, u32 n) {
int i;
for (i = 0; i < n; i++) {
u32 prev_clk = ioread32(addr);
while (1) {
u32 clk = ioread32(addr);
if (prev_clk && !clk) {
break;
} else {
prev_clk = clk;
}
}
}
}
... và người lái xe bây giờ hoạt động hoàn hảo.
Là một lưu ý cuối cùng, tôi thấy a discussion chỉ ra rằng tần số rộng có thể gây ra cho gia đình * delay() chức năng để misbehave, nhưng đây là một danh sách gửi thư ARM - Tôi giả sử các vấn đề như vậy sẽ không tồn tại trên một máy tính dựa trên Linux x86.
Tôi sẽ dùng thử và liên hệ lại với bạn. Vì vậy, tôi hiểu bạn đúng, mỗi lõi có TSC riêng của nó, vì vậy nếu quá trình điều khiển của tôi là phục vụ đã được lên lịch lại cho CPU khác, TSC có thể không giống nhau? Ngoài ra, tôi có hiểu chính xác rằng X86_FEATURE_CONSTANT_TSC biểu thị rằng TSC của CPU ổn định không phụ thuộc vào việc tăng tần số và X86_FEATURE_NONSTOP_TSC có nghĩa là TSC sẽ không bao giờ ngừng đếm? Nếu vậy, khi nào một CPU sẽ ngăn chặn nó là TSC? –
TSC có thể tạm dừng trong một số [C-States] (http://en.wikipedia.org/wiki/Advanced_Configuration_and_Power_Interface#Processor_states). –
[Mã trễ [TSC-based]] (http://lxr.linux.no/#linux+v2.6.38/arch/x86/lib/delay.c#L51) các tài khoản được chuyển giữa các CPU trong thời gian trễ. TSC dừng lại trong thời gian trễ sẽ chỉ làm cho độ trễ * dài hơn *, không * ngắn hơn *, do đó không phải là vấn đề. – caf