2011-07-25 34 views
5

Tôi đang tìm ý tưởng cho bộ đệm nhận cho một ứng dụng nhỏ xử lý 15 gói byte tại 921.6Kbaud qua rs485. Tôi đang nghĩ đến việc sử dụng một bộ đệm tròn làm giao diện giữa ISR UART và chính. Vì nó là một bộ vi xử lý tôi đã muốn đặtCách chính xác để thực hiện bộ đệm nhận uart trong một vi điều khiển ARM nhỏ?

while (uartindex!=localindex) { do stuff } 

ở phần

while (;;) {do forever} 

của chính nhưng tôi đã được cho biết đây là không thể chấp nhận.

Làm cách nào để mọi người đối phó với các trò chơi của họ trong những trường hợp tương tự?

+0

Lol - Tôi là một anh chàng quân đội ARM và điều này khiến tôi cười khúc khích vì sự thiếu hiểu biết của chính tôi. Tôi sẽ xem điều này để soi sáng bản thân mình về phía trước :) –

+0

Tôi đã làm những việc như vậy và không có vấn đề gì, vì vậy tôi tò mò muốn biết những gì mọi người nói về điều này và tại sao nó sai. –

+0

Điều duy nhất có thể đi sai là không có khái niệm về rào cản * bộ nhớ *. –

Trả lời

2

Cách tiếp cận bạn đề xuất có thể là hoàn toàn khả thi nếu uartindex không bao giờ được viết trong vòng lặp chính (trừ khi khởi tạo nó trong khi ngắt bị vô hiệu hóa) và localindex không bao giờ bị tác động bởi gián đoạn.

Tôi khuyên bạn nên làm cho kích thước bộ đệm của bạn là công suất 2, sử dụng số nguyên không dấu cho hai chỉ mục và cho phép chúng tự do đếm trên kích thước 32 bit đầy đủ của chúng; sử dụng bit masking khi lập chỉ mục bộ đệm của bạn trong cả hai "công cụ" và "lấy" thói quen. Nếu bạn làm điều đó, sau đó

(unsigned)(uartindex-localindex) 

nên chỉ có bao nhiêu nhân vật trong bộ đệm, ngay cả khi nó hoàn toàn đầy đủ, mà không đòi hỏi hành vi đặc biệt hợp cụ thể trong trường hợp bộ đệm đầy đủ và không có giới hạn một bộ đệm N-byte để đang nắm giữ các mục N-1.

Lưu ý rằng trong khi các thợ đúc chư trong biểu thức nói trên là không thực sự cần thiết, tôi sẽ khuyên bạn nên bao gồm nó vì nó làm cho rõ ràng rằng các hành vi gói khi trừ đi số lượng unsigned là cố ýdự kiến ​​.

4

ISR phải điền vào FIFO. Chính nên tiêu thụ nó.

Bellow một thuật toán FIFO rất đơn giản:

#define RINGFIFO_SIZE (1024)    /* serial buffer in bytes (power 2) */ 
#define RINGFIFO_MASK (RINGFIFO_SIZE-1ul) /* buffer size mask     */ 

/* Buffer read/write macros             */ 
#define RINGFIFO_RESET(ringFifo)  {ringFifo.rdIdx = ringFifo.wrIdx = 0;} 
#define RINGFIFO_WR(ringFifo, dataIn) {ringFifo.data[RINGFIFO_MASK & ringFifo.wrIdx++] = (dataIn);} 
#define RINGFIFO_RD(ringFifo, dataOut){ringFifo.rdIdx++; dataOut = ringFifo.data[RINGFIFO_MASK & (ringFifo.rdIdx-1)];} 
#define RINGFIFO_EMPTY(ringFifo)  (ringFifo.rdIdx == ringFifo.wrIdx) 
#define RINGFIFO_FULL(ringFifo)  ((RINGFIFO_MASK & ringFifo.rdIdx) == (RINGFIFO_MASK & (ringFifo.wrIdx+1))) 
#define RINGFIFO_COUNT(ringFifo)  (RINGFIFO_MASK & (ringFifo.wrIdx - ringFifo.rdIdx)) 

/* buffer type                */ 
typedef struct{ 
    uint32_t size; 
    uint32_t wrIdx; 
    uint32_t rdIdx; 
    uint8_t data[RINGFIFO_SIZE]; 
} RingFifo_t; 
RingFifo_t gUartFifo; 

(Cần phải cẩn thận với thuật toán FIFO này, kích thước PHẢI được sức mạnh của 2)

Các ISR nên cư xử như thế này:

void ISR_Handler() 
{ 
    uint8_t c; 
    while(UART_NotEmpty()) { 
     c = UART_GetByte(); 
     RINGFIFO_WR(gUartFifo, c); 
    } 
} 

Và chính:

while(1) 
{ 
    if (!RINGFIFO_EMPTY(gUartFifo)) { 
     /* consume fifo using RINGFIFO_RD */ 
    }  
} 

Thuật toán này đọc FIFO trực tiếp từ vòng lặp chính, bạn nên sử dụng lớp trung gian để kiểm tra xem có gói đầy đủ trong bộ đệm hay không và xử lý nó theo cách như vậy:

uint8_t ptrToPacket; 
uint32_t packetSize; 
while(1) 
{ 
    if (!Uart_HasValidPacket()) { 
     Uart_GetPacket(&ptrToPacket, &packetSize) 
     /* Process packet using ptrToPacket and packetSize */ 
    }  
} 
Các vấn đề liên quan