问题
I am writting a C code for Atmega Microcontroller and I want to use Mutex in it. What library to include? and how to implement the code?
I want this Mutex to prevent a Timer interrupt from changing a variable during a function.
回答1:
If you are using an RTOS or threading library, it almost certainly includes a mutex API, and if you are not then you don't need a mutex. In any case you cannot use a mutex in an interrupt handler in any case.
Instead, if your timer variable is modified in the interrupt context and is non-atomic, then a solution is to ensure the same value is read twice in succession to be sure it is consistent. For example:
volatile uint32_t tick ;
__interrupt timerISR()
{
tick++ ;
}
uint32_t getTick()
{
uint32_t tickval = tick ;
while( tickval != tick )
{
tickval = tick ;
}
}
回答2:
A mutex is not the right thing to use between a regular interrupt handler and the main program, resp. a thread. Main problem is that the interrupt handler cannot be suspended and later continued once it gets the mutex.
A deferred interrupt handler is different and for this it may work if the OS provides the corresponding features (but it is still uncommon). A a mutex is part of a multi-threading operating system and therefore does not come as isolated library. If you use an OS, you should find information how/when/were to use them in its documentation.
As stated in a comment, disable that interrupt while modifying the variable is one alternative. As nothing is for free (except FOSS, of course;-), this increases interrupt latency by the duration of the locked portion.
You might alternaitvely use atomic operations from C11 standard, but not sure if they are available for this platform (they are optional). @Clifford has shown an alternative if these are not available.
Regarding interrupt control: If you have an interrupt handler, you already must have enabled the interrupt, so it should be straight-forward how to disable it. However, a better way would be to use the CPU instructions which enable/disable the global interupt signal (might be something like dint/eint - just look into the reference manual). Most toolchains provide intrinsic functions for C(++) either built-in or in a header file, eliminating the need for assembler.
A solution without interrupt locking would be to use a helper flag:
volatile uint8_t modified; // global like ticks
ticksInterrupt() {
modified = 1;
// update ticks
}
uint32_t getTicks() {
uint32_t result;
do {
modified = 0;
result = ticks;
} while ( modified ) ;
return result;
}
This is faster and likely less code than a 32bit compare on 8bit CPUs at the cost of an additional flag-byte in RAM and the additional write to modified
in the int-handler (IIRC, this is a single instruction on AVR).
This approach assumes non-nested interrupts (which is standard on AVR and other 8-/16-bitters, but not mandatory - you need to know this anyway, however).
来源:https://stackoverflow.com/questions/30152676/how-to-use-mutex-in-embedded-c-and-atmega-16