26.02.2014 Views

Getting Started with QNX Neutrino - QNX Software Systems

Getting Started with QNX Neutrino - QNX Software Systems

Getting Started with QNX Neutrino - QNX Software Systems

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Writing interrupt handlers<br />

© 2009, <strong>QNX</strong> <strong>Software</strong> <strong>Systems</strong> GmbH & Co. KG.<br />

InterruptAttach() to minimize this interrupt latency. This is because the kernel is<br />

very fast at dispatching the ISR.<br />

• Buffering — if your hardware has buffering in it, you may be able to get away <strong>with</strong><br />

InterruptAttachEvent() and a single-entry queueing mechanism like SIGEV_INTR<br />

and InterruptWait(). This method lets the hardware interrupt as often as it wants,<br />

while letting your thread pick the values out of the hardware’s buffer when it can.<br />

Since the hardware is buffering the data, there’s no problem <strong>with</strong> interrupt<br />

latencies.<br />

ISR functions<br />

The next issue we should tackle is the list of functions an ISR is allowed to call.<br />

Let me digress just a little at this point. Historically, the reason that ISRs were so<br />

difficult to write (and still are in most other operating systems) is that the ISR runs in a<br />

special environment.<br />

One particular thing that complicates writing ISRs is that the ISR isn’t actually a<br />

“proper” thread as far as the kernel is concerned. It’s this weird “hardware” thread, if<br />

you want to call it that. This means that the ISR isn’t allowed to do any “thread-level”<br />

things, like messaging, synchronization, kernel calls, disk I/O, etc.<br />

But doesn’t that make it much harder to write ISR routines? Yes it does. The solution,<br />

therefore, is to do as little work as possible in the ISR, and do the rest of the work at<br />

thread-level, where you have access to all the services.<br />

Your goals in the ISR should be:<br />

• Fetch information that is transitory.<br />

• Clear the source of the ISR.<br />

• Optionally dispatch a thread to get the “real” work done.<br />

This “architecture” hinges on the fact that <strong>Neutrino</strong> has very fast context-switch times.<br />

You know that you can get into your ISR quickly to do the time-critical work. You<br />

also know that when the ISR returns an event to trigger thread-level work, that thread<br />

will start quickly as well. It’s this “don’t do anything in the ISR” philosophy that<br />

makes <strong>Neutrino</strong> ISRs so simple!<br />

So, what calls can you use in the ISR? Here’s a summary (for the official list, see the<br />

Summary of Safety Information appendix in the <strong>Neutrino</strong> Library Reference):<br />

• atomic_*() functions (such as atomic_set())<br />

• mem*() functions (such as memcpy())<br />

• most str*() functions (such as strcmp()). Beware, though, that not all these are safe,<br />

such as strdup() — it calls malloc(), which uses a mutex, and that’s not allowed.<br />

For the string functions, you should really consult the individual entries in the<br />

<strong>Neutrino</strong> Library Reference before using.<br />

186 Chapter 4 • Interrupts April 30, 2009

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!