0

I am writing a program in C for PIC32 uC , that have a global variable(uint32_t type) that can be read/modified from multiple Interrupt Service Routines and from the main.
I know that is not safe so I was wondering how to make it safe ? Is there an example that show how to make it safe ?

Edit 1:

Can interrupts interrupt each other? yes
Does the ISR update the variable? yes Does main update the variable? yes Are writes and reads to the variable atomic and how do you know? Not sure
Is there a RTOS present? No

  • The safest way is: don't do that! BTW I hope you defined that var as `volatile`. – LPs Mar 29 '16 at 14:12
  • Well, it sounds like you're using a freestanding environment, so C doesn't mandate a lot, but if you wanted to write portable code, you'd look at C11 draft standard n1570: *5.1.2.3 Program execution 5 When the processing of the abstract machine is interrupted by receipt of a signal, the values of objects that are neither lock-free atomic objects nor of type volatile sig_atomic_t are unspecified[...]. The value of any object modified by the handler that is neither a lock-free atomic object nor of type volatile sig_atomic_t becomes indeterminate when the handler exits[...]* – EOF Mar 29 '16 at 14:16
  • 1
    If you're set up such that interrupts are disabled when you're servicing interrupts, then all you need to do is also disable interrupts anywhere you read or modify the global in main. – Ross Mar 29 '16 at 17:53
  • You have to declare the variable(s) volatile otherwise the compiler can optimize them into registers or optimize out the memory accesses. Or otherwise insure that the compiled code does not optimize out the accesses. Globals or any other solution you still will have that requirement. – old_timer Mar 29 '16 at 23:06
  • But PIC32 should read/modify variables smaller than 32 bits in single instruction so it should be safe , correct ? – Hisoka Hunter Mar 30 '16 at 06:29
  • but what happen if an higher priority interrupt stops an interrupt between reading and writing?... – LPs Mar 30 '16 at 07:08
  • @LPs the variable should be updated twice correctly since its take only one instruction to modify – Hisoka Hunter Mar 30 '16 at 07:23
  • No. E.g. int 1 read 2 -->interrupted by int 2 that read 2 and inc it to 3 --> return to int 1 that inc and write 3. The inc of int 2 is lost. – LPs Mar 30 '16 at 07:27
  • @LPs ok I get it, but this problem occur even between the main and an interrupt service routine – Hisoka Hunter Mar 30 '16 at 08:07
  • How to do this is highly specific from case to case. Can interrupts interrupt each other? Does the ISR update the variable? Does main update the variable? Are writes and reads to the variable atomic and how do you know? Is there a RTOS present? And so on. You need to narrow down the question to your specific case. – Lundin Mar 30 '16 at 09:55

1 Answers1

1

If you really need to keep global variables that can be modified during the servicing of several interrupts that can interrupt each other, I suggest you following way to do:

  1. Make all sequences of actions (read and/or write) on these variables "atomic" by disabling all interrupts before, then re-enable all interrupts after. On PIC32, you could do this by writing the global interrupt flag GIE.
  2. Declare these variables as volatile to avoid any unexpected optimization from compiler.
  3. Rename these variables with a specific prefix to identify them clearly, as Shared_XXXX, but it depends on the naming convention you are using.
  4. Put all sequences of actions on these variables in functions named with a specific prefix to identify them clearly, as Atomic_XXXX(). To implement the point 1: either these functions must all start by disabling all interrupts and end by reenabling all interrupts, or alternately you can systematically pass atomic functions as callback parameter to a function that will disable all interupts, call the callback function and reenables all interrupt.
Laurent H.
  • 6,316
  • 1
  • 18
  • 40