Hi all, I'm trying to implement a small buffer in my PIC code. Code within an interrupt (which may occur anytime) will receive bytes and push them to the top of the queue, while code in the main loop will pop them from the bottom. The queue is implemented as a circular buffer. [udata section] #define BUFFER_EXP 5 ; buffer length MUST be a power of two #define BUFFER_LEN 32 BUFFER RES BUFFER_LEN BSTART RES 1 ; buffer start / next byte to be popped out BEND RES 1 ; buffer end / next incoming byte goes here BFULL RES 1 ; current bytes in buffer B* are initialized to zero in startup code (before interrupts are enabled) [interrupt code] btfsc BFULL,BUFFER_EXP goto SOS ; buffer full - blargh movlw BUFFER ; get buffer address addwf BEND,W ; plus end position movwf FSR ; into FSR movf BYTE,W ; get byte movwf INDF ; and store it in buffer incf BFULL,F ; use up one buffer position incf BEND,W ; move buffer end andlw BUFFER_LEN-1 ; with wraparound movwf BEND ; [main code - we assume BFULL is checked to be >0 before calling this] GETBYTE movlw BUFFER ; get buffer address addwf BSTART,W ; plus start position movwf FSR ; into FSR movf INDF,W ; read byte movwf TMP ; and save it for later incf BSTART,W ; increment start address andlw BUFFER_LEN-1 ; with wraparound movwf BSTART decf BFULL,F ; and free up this buffer position movf TMP,W return As far as I can tell it should be threadsafe, but I'd like a couple more experienced eyes to have a look at it. It is assumed interrupt code runs atomically, and can never be interrupted itself (except by higher powers like /MCLR). Main code may be interrupted at any time. As I see it, both "threads" run independently of each other, each pushing bytes in and consuming bytes out of their side of the queue, and since both threads update BFULL atomically (incf,decf) and at the end of their operation (i.e. when it is safe to reuse the cleared position or safe to read the newly written position), I'd say it is fine. FSR is saved in the interrupt header, so that should be safe (otherwise I could wrap those two instructions in bcf/bsf INTCON,GIE) Of course I could just block interrupts by clearing GIE, but that would affect the (time-sensitive) interrupt (probably not enough to cause a problem, but I'd like to be safe), make it non-deterministic, and take all the fun out of it :) Comments? Maybe someone could find this useful (assuming I got it right). -- Hector Martin (hector@marcansoft.com) Public Key: http://www.marcansoft.com/hector.asc -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist