HAL_UART_Transmit() blocking như thế nào?
Giải thích vì sao HAL_UART_Transmit() giữ CPU trong lúc chờ UART truyền xong dữ liệu và khi nào nó trở thành vấn đề real-time.
Ghi chú nhanh
HAL_UART_Transmit() là hàm truyền UART kiểu blocking/polling trong STM32 HAL.
Khi gọi hàm này, CPU phải chờ quá trình truyền hoàn tất hoặc timeout xảy ra. Trong thời gian đó, CPU không quay lại xử lý logic chính.
Ví dụ:
HAL_UART_Transmit(&huart1, data, len, HAL_MAX_DELAY);
Nếu len lớn hoặc baudrate thấp, thời gian chờ có thể ảnh hưởng tới real-time.
Blocking nghĩa là gì trong trường hợp này?
Blocking không có nghĩa là MCU chết. Nó chỉ có nghĩa là CPU đang bị giữ trong hàm đó cho tới khi UART truyền xong.
Trong lúc chờ, interrupt vẫn có thể chạy nếu được enable, nhưng flow chính của task hoặc main loop thì bị kẹt lại.
main loop/task
|
| gọi HAL_UART_Transmit()
v
[chờ UART truyền xong]
|
v
quay lại xử lý tiếp
Với một dòng log ngắn, chuyện này có thể không đáng kể. Nhưng nếu log nằm trong đoạn timing nhạy, vài mili giây chờ UART có thể làm sai kết quả debug.
Ví dụ thực tế
Giả sử bạn đang debug một firmware đọc tín hiệu bằng timing rất sát. Bạn thêm một dòng:
printf("raw=%02X", raw);
Nếu printf() đi xuống _write() và _write() dùng HAL_UART_Transmit() blocking, mỗi lần log có thể làm CPU chậm thêm một khoảng phụ thuộc vào baudrate và độ dài chuỗi.
Kết quả là bug timing có thể biến mất, hoặc tệ hơn, bug mới xuất hiện. Đây là tình huống kinh điển: “thêm log để debug, nhưng log lại thay đổi thứ mình đang debug”.
Khi nào blocking transmit vẫn chấp nhận được?
Không phải lúc nào HAL_UART_Transmit() cũng xấu.
Nó vẫn ổn trong các trường hợp:
- log rất ít;
- chạy ở giai đoạn init;
- firmware không có yêu cầu real-time chặt;
- dùng cho prototype nhanh;
- timeout được đặt hợp lý;
- không gọi trong ISR hoặc task ưu tiên cao.
Vấn đề không nằm ở bản thân hàm blocking. Vấn đề là dùng nó ở nơi không được phép chờ.
Cách tự hỏi khi review source
Cách nhớ
HAL_UART_Transmit() dễ dùng, nhưng CPU phải đứng chờ.
Dùng ở init thì ổn.
Dùng trong đường real-time thì phải rất cẩn thận.
Bài liên quan nên đọc tiếp
- Cách tính thời gian truyền UART từ baudrate
- Redirect printf bằng _write() trên STM32 là gì?
- Thiết kế hệ thống UART logging non-blocking trên STM32
Thấy nội dung này hữu ích?
Lưu lại hoặc chia sẻ cho người cũng đang học firmware, BIOS/UEFI và embedded systems.
Nội dung liên quan
Một số bài viết, ghi chú hoặc project có liên quan đến nội dung bạn vừa đọc.
Flash Operations STM32: Erase, Write, Polling và tại sao program đứng
Cách thao tác Flash STM32 qua HAL: unlock, erase, write, polling vs interrupt, và nguyên nhân program freeze khi xóa Flash.
DMA Normal mode và Circular mode khác nhau thế nào?
Phân biệt DMA Normal mode và Circular mode khi dùng UART, ADC, audio stream hoặc logger trên STM32.
HAL_BUSY xảy ra khi nào trong UART DMA?
Giải thích lỗi HAL_BUSY khi gọi HAL_UART_Transmit_DMA() trong lúc UART/DMA vẫn đang truyền dữ liệu trước đó.
Biến note thành bài viết hoàn chỉnh
Notes là nơi ghi nhanh khái niệm.