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 */
}
}
Nguồn
2013-03-11 19:35:01
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 :) –
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. –
Điều duy nhất có thể đi sai là không có khái niệm về rào cản * bộ nhớ *. –