I'm still with newbrain here, I'm not quite sure how you handle a queue full condition. From the code you posted, if Head == Tail, then you're just going in a low power mode. Then what?
Another thing I don't quite like with this kind of approach: there is no difference between a queue full and a queue empty condition. Then you may be tempted to work around this with some tricks. It's not pretty and not easy to test and prove correct.
I personally favor adding an extra member indicating the number of items currently in the queue, instead of comparing Head and Tail. The benefit of this approach is that it makes it easy and fast to determine the current number of items in the queue, but also see if it's full or empty. Without tricks.
A related point is that when using this extra member, only its accesses need to be atomic. You don't need atomic accesses to Head and Tail, as long as there is only one 'thread' writing to the queue and another one reading from it, which is a very common case.
This may not matter if such members are so small as you "know" the accesses will be atomic anyway with no extra cost, but this is pretty much always implementation-dependent. If you want a truly portable implementation that is provably correct, then the best approach IMO is to add this extra "n" member (current number of items) and define it as an atomic type (stdatomic) as long as you have access to a C11-compliant compiler. This may add zero cost if the type in question can be accessed atomically without any extra instruction on a given platform, but otherwise will add what it takes to make it atomic. So this is a portable approach.
Note that, as I hinted above, if there may be more than one thread reading the queue, or more than one thread writing to the queue, then atomic accesses would not be enough - you would need to add mutexes. So the above approach is thread-safe only if there is at most one thread reading the queue and one writing to the queue, which may two threads in total or a single thread depending on your needs. If typically the queue is written to in an ISR, and read somewhere else (either in another ISR or in main code), this will be the case, but if, say, two different ISRs with different priorities can write to the queue, then you'd need mutexes...