Reply by werty February 14, 20082008-02-14
On Feb 7, 3:55=A0am, "sohagiut" <sohag...@yahoo.com> wrote:
> hy, i am not very expert in C. Can any one give me a sample example on ISR=
> for UART.i am using MPLAB with c18. how to write IRQ in ISR. also how can > i add "case" in side ISR? can any =A0one give me any tips or any link. > > thanks in advance =A0
---------------------------------------------------------- Dont ISR . Main task polls the serial port , when busy it ignores you . You do want it to "work" for you ? dont you ? While developing the S/W , a key/button to break out of a faulty loop , saves time , but thats the only button . I have no interest in unstructured programming its a waste of my precoius time .
Reply by Mark Borgerson February 11, 20082008-02-11
In article <cLudnVARIPWQ4i3anZ2dnUVZ_h6hnZ2d@giganews.com>, 
sohagiut@yahoo.com says...
> >sohagiut wrote: > >> i need few example related to interrupt with serial port. please give > me > >> related links. it's batter for me if i get sample code as i told you i > am > >> not expert on C. please give me few times for it. > > > >No, you don't need examples of interrupt code. You need to learn to > >program in C - interrupt routines and synchronising data transfers > >between interrupts and the main program can be a little tricky. You > >need to take courses or read a book, or employ a qualified programmer - > >begging people to do your job is not the answer. > > > >You might like to get a keyboard with capital letters - it would make > >your posts more legible. > > > > > ok, good suggestion. the blogs are the place for learning the tricks, i > believe. do you? whetever... you might be very expert, then why do you > hesitate to assist some one, as the objectives of the blogs serve this. or > just to show off. i really like relevant suggestion. in all through the > post i ask for specific questions (how to call case in ISR) and you shows > your funny expertise!!!! all beginners might stupid. and the qualified > programmer..............what about you? >
I think most of the readers here are like C compilers----they are case-sensitive. If you want someone to help you with C code, you are going to have to learn to use the shift key. Mark Borgerson
Reply by David Brown February 11, 20082008-02-11
sohagiut wrote:
>> sohagiut wrote: >>> i need few example related to interrupt with serial port. please give > me >>> related links. it's batter for me if i get sample code as i told you i > am >>> not expert on C. please give me few times for it. >> No, you don't need examples of interrupt code. You need to learn to >> program in C - interrupt routines and synchronising data transfers >> between interrupts and the main program can be a little tricky. You >> need to take courses or read a book, or employ a qualified programmer - >> begging people to do your job is not the answer. >> >> You might like to get a keyboard with capital letters - it would make >> your posts more legible. >> > > > ok, good suggestion. the blogs are the place for learning the tricks, i > believe. do you? whetever... you might be very expert, then why do you > hesitate to assist some one, as the objectives of the blogs serve this. or > just to show off. i really like relevant suggestion. in all through the > post i ask for specific questions (how to call case in ISR) and you shows > your funny expertise!!!! all beginners might stupid. and the qualified > programmer..............what about you?
It's possible that there a few blogs around with useful tricks, but you have a long way to go (measured in *years*) before you have to worry about learning tricks. It's not clear from your post - are you mixing up blogs and Usenet? Because blogs are, for the most part, public masturbation for people who think their own little lives are fascinating to the world at large (I'm very happy with my own life - but I can't imagine for a moment that others would be interested in it). Your original post was "i (sic.) am not very expert in C. ... can any one give me any tips or any link". The best tip anyone can give you is that you learn C properly - the best link would be a pointer to your local bookshop. And your keyboard is still broken.
Reply by sohagiut February 11, 20082008-02-11
>sohagiut wrote: >> i need few example related to interrupt with serial port. please give
me
>> related links. it's batter for me if i get sample code as i told you i
am
>> not expert on C. please give me few times for it. > >No, you don't need examples of interrupt code. You need to learn to >program in C - interrupt routines and synchronising data transfers >between interrupts and the main program can be a little tricky. You >need to take courses or read a book, or employ a qualified programmer - >begging people to do your job is not the answer. > >You might like to get a keyboard with capital letters - it would make >your posts more legible. >
ok, good suggestion. the blogs are the place for learning the tricks, i believe. do you? whetever... you might be very expert, then why do you hesitate to assist some one, as the objectives of the blogs serve this. or just to show off. i really like relevant suggestion. in all through the post i ask for specific questions (how to call case in ISR) and you shows your funny expertise!!!! all beginners might stupid. and the qualified programmer..............what about you?
Reply by David Brown February 11, 20082008-02-11
sohagiut wrote:
> i need few example related to interrupt with serial port. please give me > related links. it's batter for me if i get sample code as i told you i am > not expert on C. please give me few times for it.
No, you don't need examples of interrupt code. You need to learn to program in C - interrupt routines and synchronising data transfers between interrupts and the main program can be a little tricky. You need to take courses or read a book, or employ a qualified programmer - begging people to do your job is not the answer. You might like to get a keyboard with capital letters - it would make your posts more legible.
Reply by sohagiut February 11, 20082008-02-11
i need few example related to interrupt with serial port. please give me
related links. it's batter for me if i get sample code as i told you i am
not expert on C. please give me few times for it. 
Reply by David Brown February 9, 20082008-02-09
Arlet wrote:
> On Feb 8, 9:56 pm, "David T. Ashley" <d...@e3ft.com> wrote: >> "David Brown" <da...@westcontrol.removethisbit.com> wrote in message >> >> news:47ac2c51$0$14988$8404b019@news.wineasy.se... >> >> >> >>> If you *don't* have access to such an atomic decrement, you have two >>> options - disable interrupts around the critical code to make the >>> operation atomic, or use a better buffer structure! (Hint - do you really >>> need nchars?) >> Good eye! >> >> You are correct! Holding too much state is a common cause of software >> defects. >> >> Between getpoint, putpoint, and nchars : I think you can show that only two >> (any two) of the three are required. >> >> I think though that if you eliminate nchars you can't fill the queue. If >> (getpoint == putpoint), the buffer is either empty or full, and you can't >> tell which without slightly more information. >> >> However, if you have (putpoint and nchars) or (getpoint and nchars) I think >> it will work. > > I've always liked the following: > > #define SIZE 64 // should be power of 2, and < 256 > > volatile unsigned char putptr; > unsigned char getptr; > unsigned char buffer[SIZE]; > > isr( ) > { > unsigned char c = GET_CHAR_FROM_HARDWARE(); > > if( (int) (putptr - getptr) < SIZE ) > buffer[putptr++ % SIZE] = c; > } > > int uart_getchar() > { > if( putptr == getptr ) > return -1; > return buffer[getptr++ % SIZE]; > } > > SIZE should be a power of two, and less than 256 so that you can tell > the difference between an empty and completely full buffer. >
That's a neat way to do it, if you are already happy being restricted to power-of-two buffer sizes. Since most buffer sizes in practical programs are picked as rough guestimates, that's no big loss.
> As long as the incremented value for 'putptr++' can be atomically > written to memory, interrupts don't need to be disabled in the > uart_getchar() routine.
You are also relying on putptr and getptr being atomically readable. That's fine with 8-bit variables, but is important to consider when using 16-bit counters for larger buffers on 8-bit micros.
Reply by David Brown February 9, 20082008-02-09
David T. Ashley wrote:
> "David Brown" <david@westcontrol.removethisbit.com> wrote in message > news:47ac2c51$0$14988$8404b019@news.wineasy.se... >> If you *don't* have access to such an atomic decrement, you have two >> options - disable interrupts around the critical code to make the >> operation atomic, or use a better buffer structure! (Hint - do you really >> need nchars?) > > Good eye! > > You are correct! Holding too much state is a common cause of software > defects. >
Holding too much state can be useful for efficiency, if you can be sure that the extra data is consistent. In this particular case, keeping consistency requires atomic operations or interrupt disabling, which is too expensive for the potential gains from knowing all three numbers.
> Between getpoint, putpoint, and nchars : I think you can show that only two > (any two) of the three are required. >
Yes - the number of characters in the buffer at any time is the number of characters put in the buffer, minus the number of characters removed.
> I think though that if you eliminate nchars you can't fill the queue. If > (getpoint == putpoint), the buffer is either empty or full, and you can't > tell which without slightly more information. >
That is correct. Without nchars, you can't fill the last byte of the buffer. But generally that is a cost worth paying for the advantages of the getpoint/putpoint method. Note that even with nchars, you come across the same situation if you have a 256 byte buffer and are keeping your variables as 8-bit data for efficiency.
> However, if you have (putpoint and nchars) or (getpoint and nchars) I think > it will work. >
True, but then you lose your independence of the variables. The point of using putpoint and getpoint is that the interrupt routine only ever modifies putpoint (it *reads* getpoint, but that's no problem), and the extraction routine only ever modifies getpoint (it *reads* putpoint - that's no problem if it can be read atomically, and if not, you can work around the issue without having to disable interrupts). If you track nchars, then the two functions both have to modify the same variable.
Reply by David Brown February 9, 20082008-02-09
Mark Borgerson wrote:
> In article <47ac830d$0$15002$8404b019@news.wineasy.se>, > david@westcontrol.removethisbit.com says... >> Mark Borgerson wrote: >>> In article <47ac2c51$0$14988$8404b019@news.wineasy.se>, >>> david@westcontrol.removethisbit.com says... >>>> Mark Borgerson wrote: >>>>> In article <MN2dnVFbIrGdszbanZ2dnUVZ_uidnZ2d@giganews.com>, dta@e3ft.com
<snip>
>>>> >>>> If you *don't* have access to such an atomic decrement, you have two >>>> options - disable interrupts around the critical code to make the >>>> operation atomic, or use a better buffer structure! (Hint - do you >>>> really need nchars?) >>>> >>>> >>> I've seen and used queue code that compares the get and put pointers to >>> detect whether a character is available. I avoided it for a couple of >>> reasons: >>> >>> * the pointer comparisons are not atomic on the 68K although that may >>> not matter when checking for getptr != putptr >> You simply calculate "nchars = putptr - getptr", then adjust if there >> has been a wrap around the end of the buffer. It does not matter that >> this is not atomic - if a new character has come in during this >> operation, then the new putptr will be greater than the one used, and >> your nchars will be one character too small. But that's just the same >> as if the new character came in after your code had finished. >> >>> * there are times when it is handy to have a count of the characters >>> in the buffer. With that count you can implement a faster loop to >>> pull characters from the queue. It's easier to increment and >>> decrement a counter at one instruction each, than it is to get >>> the queue length by pointer arithmetic that accounts for queue >>> wraparound. >>> >> Thus you calculate "nchars = putptr - getptr" at the start of your code, >> and any new incoming characters are ignored until you next run the code >> - just as if they arrived after the code was finished. > > That sounds simple--but there are a few details to remember: > > 1. putptr can be smaller than getptr if the buffer has just > wrapped around.
As I said above, "You simply calculate "nchars = putptr - getptr", then adjust if there has been a wrap around the end of the buffer."
> 2. because of #1, you have to be careful about correcting > for buffer wrap if you intend to actually use the character > count in a loop and not just compare it with zero.
It's not exactly hard to do: sint8_t nchars = putptr - getptr; if (nchars < 0) nchars += lengthOfBuffer; You might want to think about different cases if your buffer sizes are close to your counter type sizes (i.e., a buffer of more than 128 bytes when using 8-bit counters). If your buffers are a power of two in length, the an AND mask is even smaller and faster.
> 3. pointer arithmetic on 8 or 16-bit processors may involve > quite a large number of instructions. >
That's true, but irrelevant. We are working here with indexes into an array, not pointers - that way we can use minimal sized types, and happily do arithmetic, masking, and comparisons on them. Actually putting data into or taking data out of the buffer uses array access - it's the same whether or not you try to track nchars independently!
> > With 8-bit processors, it may be best to limit the buffer > size to something less than 256 bytes. If you need maximum > efficiency, you could also use the technique of making > the buffer length equal to an even power of 2. Then you > can handle buffer wrap with a single AND instruction. > I don't think I've had to worry that much about performance > since my 6502 and 6800 assembly coding days.
That's always the case when working with small micros - think about your types, and choose appropriate ones. It is unlikely, but not impossible, that you'll need a buffer of more than 256 bytes (255 actually - you can never have the buffer entirely full as it will be indistinguishable from entirely empty). The way to make your code flexible, efficient and portable is to typedef a "qcounter_t" type which is used throughout the implementation, and which is typedefed somewhere at the start of the module depending on the size of the buffers you need. Ideally you should typedef it to "uint_fast8_t" rather than just "uint8_t" - that will produce good code on everything from an 8-bit AVR to a ColdFire (which works faster with 32-bit data than 8-bit data).
>>> I do use that technique in my serial handler for the AT91SAM7 >>> processor. There, I use the DMA support in the Atmel chips, >>> so there is not an interrupt for each character or FIFO. >>> That leaves me with comparing the getptr with the DMA >>> receive pointer to detect incoming characters. >>> >>> One of the first uses for my serial I/O code on a new system >>> is always as part of the monitor used to upload new code. If >>> you start getting a lot of checksum errors when uploading >>> new code, it's a good indication that you've missed something >>> in the serial I/O driver. >>> >>> >>> The simple example code here also lacks a few elements: >>> 1: there is no error reporting for queue full errors >>> or queue empty errors. Without those error reports, >>> the program can't distinguish between a valid 0x00 >>> character and the result of a get operation on an >>> empty queue. >>> 2. There should be a ChAvailable() function that returns >>> the number of characters available. This prevents either >>> blocking on an empty queue or the queue empty 0x00 >>> character problem. >>> 3. Many UARTS have just one interrupt, which has to handle >>> receive, transmit and error interrupts, so the >>> ISR will be more complex than that shown. If the UART >>> has a FIFO, it gets to be even more fun! >>> >> All this is correct - the code above is (hopefully!) just an example. >> > > Yep. There's usually a lot more going on under the hood of a good > serial driver than we've discussed in these examples. It gets to > be even more fun if there are FIFOs or DMA and you really want to > minimize time in the handlers in high-traffic situations. > I went through all that in a data multiplexer/concentrator application > a decade or two back. We didn't exactly have to count cycles, > but with 4 input channels and no FIFOs, we did have to optimize > the receive interrupt handlers as best we could. The input data > could be pretty 'bursty' and we had to make sure we could handle > four separate channels in less than one character time at 115KB. > IIRC the result involved a separate handler for each channel and > each handler used hard-coded register addresses rather than > computing addresses from a channel index. > > > Mark Borgerson >
Reply by February 8, 20082008-02-08
David T. Ashley wrote:
> Between getpoint, putpoint, and nchars : I think you can show that only two > (any two) of the three are required. > > I think though that if you eliminate nchars you can't fill the queue. If > (getpoint == putpoint), the buffer is either empty or full, and you can't > tell which without slightly more information. > > However, if you have (putpoint and nchars) or (getpoint and nchars) I think > it will work.
Not really. nchars=0 and nchars=256 are just as indistinguishable (assuming the canonical case of keeping everything in 8-bit variables) as the two cases 'completely full' and 'completely empty' in the implementation using only pointers. A simpler solution is to step back a bit and re-consider how many bytes have to be in the buffer for it to be considered "full". If you keep the head and tail pointer separated by at least one position at all times, it becomes easier to implement the ring buffer. Squeezing out that one last byte of size is not always worth the effort.