2008-12-11 31 views
6

Tôi có một vi điều khiển phải tải xuống một tệp lớn từ cổng nối tiếp PC (115200 baud) và ghi nó vào bộ nhớ flash nối tiếp qua SPI (~ 2 MHz). Ghi flash phải nằm trong các khối 256 byte trước một lệnh viết và địa chỉ trang. Tổng RAM có sẵn trên hệ thống là 1 kB với kích thước ngăn xếp 80 byte.Làm cách nào để bạn xử lý việc truyền dữ liệu lớn trên các hệ thống nhúng, bộ nhớ bị hạn chế?

Điều này hiện đang hoạt động bằng cách điền bộ đệm 256 byte từ UART và sau đó ping-ponging đến bộ đệm 256 byte khác được lấp đầy bằng ngắt trên tín hiệu sẵn sàng bộ đệm RX trong khi flash được ghi bằng ghi bận. Việc hoán đổi bộ đệm được lặp lại cho đến khi thao tác hoàn tất.

Tôi muốn thiết lập trình xử lý ngắt TX/RX cho cả hai cổng SPI và UART hoạt động trên bộ đệm tròn riêng biệt. Vì vậy, thay vì bỏ phiếu cho byte mới và chờ đợi cho các hoạt động để hoàn thành tôi chỉ có thể điền vào các bộ đệm TX và cho phép gián đoạn hoặc kiểm tra bộ đệm cho dữ liệu đến. Điều này sẽ cung cấp cho rất nhiều chu kỳ đồng hồ cho công việc thực tế thay vì chờ đợi trên thiết bị ngoại vi.

Sau khi triển khai IRQ với bộ đệm tròn 128 byte, tôi thăm dò bộ đệm RX UART cho dữ liệu và đặt ngay vào bộ đệm SPI TX để chuyển tệp. Vấn đề tôi gặp phải với cách tiếp cận này là tôi không có đủ bộ nhớ đệm cho bộ đệm và bộ đệm nhận PC được lấp đầy nhanh hơn tôi nhận được dữ liệu qua bộ đệm truyền phát flash. Rõ ràng, tốc độ truyền tải không phải là vấn đề (115,2 kHz trong và 2 MHz ra), nhưng có một chu kỳ ghi chờ sau mỗi trang 256-byte được truyền đi.


Dường như các ngắt SPI thường xuyên đang chặn một số ngắt UART và khiến byte bị bỏ qua. Giải pháp tôi chọn là sử dụng bộ đệm vòng cho UART nhận ngắt và cấp dữ liệu vào bộ đệm trang 256 byte được gửi tới đèn flash nối tiếp bằng cách bỏ phiếu chuyển byte và ghi hoàn thành. Một bộ đệm 128 vòng là đủ lớn để ngăn chặn tràn trong quá trình ghi SPI.

Trả lời

3

Tôi sẽ làm điều gì đó giống như phân tán tập trung trên PC. Tạo danh sách liên kết của một cấu trúc như sau:

typedef struct data_buffer { 
    char flags; 
    char[128] data; 
} 

Có một trong các bit trong cờ có nghĩa là "ReadyToFlash" và một cho "Nhấp nháy". Bạn sẽ có thể điều chỉnh số lượng bộ đệm trong danh sách được liên kết của bạn để giữ cho flash không bắt được UART khi nó viết hoặc ngược lại.

Nếu đèn flash đến khối đệm không phải là "ReadyToFlash", nó sẽ dừng và bạn cần phải có IRART UART của bạn khởi động lại. Nếu UART nhận được một khối là "ReadyToFlash" hoặc "Flashing" thì quá nhanh và bạn có thể cần một bộ đệm khác, nếu bạn có bộ nhớ động, bạn có thể thực hiện điều chỉnh này khi chạy và thêm bộ đệm vào danh sách , nếu không bạn sẽ chỉ cần làm một số thử nghiệm thực nghiệm.

+0

Lưu ý rằng RAM 1 kB (1024 byte) không cho phép nhiều bộ đệm! Tuy nhiên đó là ý tưởng tốt. –

+0

Đúng, mặc dù bạn cũng có thể thử điều chỉnh kích thước của bộ đệm xuống (có thể là 64b), nhưng chi phí của các cờ bắt đầu tác động đến hiệu quả bộ nhớ của bạn. – joshperry

+0

Tôi sẽ sử dụng một biến cờ đơn với các vết cắn cho mỗi bộ đệm. –

4

UART và phía PC của ứng dụng có hỗ trợ bắt tay RS-232 (điều khiển luồng) không? Nếu vậy, khi bộ đệm nhận của bạn gần đầy, hãy ISR bỏ dòng CTS - nếu phía PC được cấu hình để kiểm soát luồng phần cứng, nó sẽ dừng gửi khi thấy điều kiện này. Một khi bạn đã thoát (hoặc gần như thoát nước) bộ đệm nhận, hãy xác nhận lại CTS và PC sẽ bắt đầu gửi lại. Lưu ý rằng điều này làm cho phần mềm trên thiết bị nhúng phức tạp hơn nhiều - cho dù đó là sự cân bằng mà bạn sẵn sàng thực hiện sẽ phải được phân tích bởi bạn và nhóm quản lý của bạn &.

+0

Điều này thực sự xảy ra thông qua giao diện USB và các tín hiệu đó không khả dụng. Đó là lời khuyên tốt mặc dù. –

4

Đây chính là điều khiển luồng được tạo ra, tôi biết đó là một cơn đau lớn nhưng nếu bạn bật điều khiển luồng trên dòng nối tiếp thì vấn đề của bạn sẽ là lịch sử.

Tôi giả sử bạn đang chuyển một tệp nhị phân để XON-XOFF không phải là giải pháp tốt nhất, điều này giúp kiểm soát luồng phần cứng.

Tùy chọn khác là sử dụng giao thức có bộ điều khiển luồng tích hợp như XModem. Tôi có một dự án nhúng tương tự, nơi flash được viết trong các trang 128byte. Thật trùng hợp khi XModem gửi dữ liệu theo khối 128byte sau đó đợi ACK trước khi gửi dữ liệu tiếp theo.

+0

Tôi đã sử dụng XModem trong quá khứ và có mã đặt xung quanh cho nó. Tuy nhiên, tôi đang đi vào một hợp đồng và không thể thay đổi máy khách PC (nó chỉ cần spews toàn bộ tập tin cùng một lúc). –

1

Không chắc chắn những gì tôi đang thiếu ở đây, nhưng nếu thực tế là tốc độ trung bình của dữ liệu đến từ PC cao hơn tốc độ trung bình bạn có thể ghi nó vào flash, sau đó bạn sẽ cần rất nhiều RAM, hoặc bạn sẽ cần kiểm soát dòng chảy.

Nhưng bạn có nói rằng nó hoạt động khi bạn đã chặn bộ đệm, nhưng bây giờ bạn có bộ đệm byte không?

Bạn có thể gắn bó với bộ đệm khối được lấp đầy bởi ngắt UART RX và khi mỗi bộ đệm đầy, hãy chuyển nó sang mã SPI/Flash để làm trống bộ đệm đó bằng ngắt SPI không? Điều đó sẽ giúp bạn sao chép từng byte, và thay vì phải thực hiện logic đệm vòng hai lần cho mỗi byte, bạn sẽ chỉ phải thực hiện nó cho mỗi khối.

+0

Chu trình chờ cho một trang viết sau khi truyền là nút cổ chai. Tôi đã thêm thông tin đó vào câu hỏi. –

+0

Tôi có thể làm cho nó hoạt động với bộ đệm tròn 128 byte trên UART và một bộ đệm trung gian 256 byte với ghi/thăm dò bận đến SPI. Bộ đệm 128 byte không có 256 trung gian không hoạt động. –