7
\$\begingroup\$

For a small micro controller without an OS what is the proper way to share data between different interrupts and the main loop?

With an OS one can just create a mutex for each critical part and carry on and the scheduler will switch between tasks for example.

If a mutex is used in an interrupt it will just lock forever so obviously this cannot work.

A simple approach I can think of can be to have copies of the variables in a table and when they are modified set a flag for each variable modified. Then in the main loop disabling interrupts copy the copies to the main variables and viceversa (with a system of priorities in case two or more were changed). This would take quite some time and but it should work.

\$\endgroup\$
9
\$\begingroup\$

There are several ways:

  1. Make each piece of state small enough to be updated atomically by the hardware. For example, if you're on a 16 bit machine (like a Microchip dsPIC, for example), then make each piece of shared state no more than 16 bits.

  2. Use FIFOs between interrupt and foreground code. There are ways to design FIFOs so that no mutex is needed, but foreground and interrupt code can still access their ends at any time.

  3. Have the foreground code temporarily shut off interrupts around accesses to critical shared data that is not atomically updated.

\$\endgroup\$
8
\$\begingroup\$

In my MCU programs (Atmel, PIC, ARM) I use:

disable interrupts
critical action
enable interrupts

My critical actions are of very short duration. Most of them are of the type: var = var +/- 1;

Note that you can use the above system to make your own mutex-es.

\$\endgroup\$
  • 1
    \$\begingroup\$ Yes but ideally theres a big loop that uses data from the interrupt and the interrupt changing the data in the fly should not affect the loop till the next iteration. Putting the whole loop in the critical section is too wasteful. \$\endgroup\$ – Carlos May 31 '18 at 12:37
  • \$\begingroup\$ I would need more details but there is normally a work around. Only the place where you touch common variables needs a critical section. Or you can pass buffers around for exclusive usage. Also, as I said, you can make a mutex using the method. The claim/free mutex code is the only place where interrupts are disabled. That can be done with one or two lines of code. \$\endgroup\$ – Oldfart May 31 '18 at 12:49
  • \$\begingroup\$ I am thinking in general terms. In this case there is a main loop that has a set of variables which is large and performs slow operations. Theres n interrupts which have arbitrary number of the variables shared by the main loop and most likely the variables do not collide (for example interrupt 1 has variables a,b,c and interrupt 2 d,e,f, but not a,b,c too). I'm thinking interrupts can add elements that modify to a queue and at the end of main loop update first the main loop variables from the queue and then update the interrupt copies from the main loop. \$\endgroup\$ – Carlos May 31 '18 at 12:59
  • \$\begingroup\$ If the critical action is really just incrementing or decrementing a counter, then you don't need to turn off interrupts at all on most machines. Most have a way of performing a atomic increment or decrement. On PIC 16 and PIC 18, for example, that would be done with the INCF and DECF instructions. \$\endgroup\$ – Olin Lathrop Aug 29 '18 at 0:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.