2013-02-17 26 views
5

Tôi đang viết mã nhúng cho STM32F3 mc (STM32F3-Discovery). Tôi cần phải xuất một số dữ liệu để UART và tôi đang sử dụng DMA cho điều này vì điều này cho phép tôi tập trung vào cảm biến đọc và xử lý dữ liệu hơn là chờ đợi hoàn thành truyền byte. Tuy nhiên vấn đề là tôi phải kết hợp:In được định dạng thành bộ đệm tròn

  1. đầu ra định dạng (ví dụ một số từ của printf)
  2. Một số bản in liên tục (xảy ra trước khi in trước đã hoàn tất)

Vì vậy, tôi đang nghĩ về một bộ đệm tròn. Nhưng tôi không nghĩ rằng tôi biết làm thế nào để làm cho sprintf tôn trọng sự kết thúc của bộ đệm và tiếp tục viết vào đầu bộ đệm. Tất nhiên tôi có thể tạo một bộ đệm tạm thời khác, in ở đó và sao chép từng byte một, nhưng nó trông không tao nhã với tôi.

+1

Yêu cầu thú vị, nhưng tôi không nghĩ bạn sẽ làm tốt hơn đáng kể so với 'định dạng thành đệm tạm thời, sau đó sao chép sang đệm tròn bằng chức năng sao chép thích hợp'. –

Trả lời

2

Một giải pháp có thể là để triển khai sprintf của riêng bạn mà có thể hoạt động với bộ đệm vòng. Thật không may điều này sẽ không giúp bạn về một vấn đề cơ bản hơn: Bạn sẽ làm gì nếu ringbuffer của bạn là đầy đủ và bạn gọi sprintf?

Nếu tình trạng bộ nhớ của bạn có thể đủ khả năng đó, tôi muốn đề nghị một giải pháp cho vấn đề này:

ý tưởng này dựa trên hai danh sách liên kết của bộ đệm (một danh sách cho các bộ đệm miễn phí, một danh sách như hàng đợi truyền) . Các bộ đệm có kích thước bằng nhau để chúng có thể lưu trữ chuỗi có độ dài trường hợp xấu nhất. Các bộ đệm xây dựng một đống đơn giản, nơi phân bổ/deallocation chỉ dequeuing/enqueuing một phần tử hoặc từ miễn phí hoặc từ danh sách truyền.

Có bộ đệm có kích thước bằng nhau đảm bảo bạn không bị ảnh hưởng phân mảnh bên ngoài như "kiểm tra" trong khi phân bổ bộ nhớ động. Xây dựng heap của riêng bạn cho công việc này cũng sẽ cung cấp cho bạn toàn quyền kiểm soát tổng kích thước bộ đệm có sẵn cho nhiệm vụ truyền tải.

tôi có thể tưởng tượng chạy này như sau:

  1. Bạn phân bổ một bộ đệm từ danh sách miễn phí để render dữ liệu vào.
  2. Sử dụng làm chức năng (suchas sprintf) của bạn hiển thị các dữ liệu trong bộ đệm
  3. Nối các dữ liệu được gửi tới hàng đợi truyền (và kích hoạt một truyền nếu cần thiết)

Đối với DMA chuyển bạn xử lý IRQ kết thúc chuyển. Ở đó bạn di chuyển bộ đệm vừa chuyển sang "danh sách miễn phí" và thiết lập chuyển cho bộ đệm tiếp theo trong hàng đợi.

Giải pháp này sẽ không phải là bộ nhớ hiệu quả nhất nhưng hiệu suất thời gian chạy là tốt vì bạn chỉ ghi vào bộ nhớ một lần và phân bổ/deallocation chỉ tìm nạp/lưu trữ một con trỏ ở đâu đó. Tất nhiên bạn sẽ phải chắc chắn rằng bạn không nhận được điều kiện chủng tộc giữa ứng dụng của bạn và IRQ để phân bổ/deallocation.

Có lẽ ý tưởng này cung cấp cho bạn một nguồn cảm hứng để giải quyết các yêu cầu của bạn.

1

Một cách bạn có thể ước tính đó là phân bổ bộ đệm printf của bạn bằng 2x kích thước của vòng đệm của bạn, và sau đó sử dụng nửa đầu làm bộ đệm vòng của bạn. Phát hiện một tràn, sao chép tràn trong nửa sau trở lại phía trước (phần vòng).Một cái gì đó như thế này:

void xprintf(const char *format, ...) 
{ 
    int written; 
    va_list args; 
    va_start(args, format); 
    written = vsnprintf(buffer, HALF_BUFFER_SIZE, format, args); 
    va_end(args); 
    if (buffer + written > bufferStart + HALF_BUFFER_SIZE) 
    { // time to wrap 
    int overflow = (buffer + written) - (bufferStart + HALF_BUFFER_SIZE); 
    memmove(bufferStart, bufferStart + HALF_BUFFER_SIZE, overflow; 
    buffer = bufferStart + overflow; 
    } 
} 
Các vấn đề liên quan