I am using a STM32F407 discovery board for ADC and I found that the DR or the data register of the ADC can be configured in left or right alignment. What does this mean? Also, what are the advantage/disadvantages of each alignment?
Alignment determines how the binary will end up in the hardware register. Suppose you have a 16 bit resolution register (or 2x8 bits) but only 12 bit ADC resolution. Your option is then either to get:
XXXX DDDD DDDD DDDD
DDDD DDDD DDDD XXXX
Where "D" is your data bits and "X" is "don't care" bits (usually filled with zeroes). The form requiring the least amount of bitwise arithmetic to get to your desired format is usual the preferred one. One will contain the need to shift, the other won't.
This in turn depends on endianess - the byte order. If the ADC is using the same endianess as your CPU then you'd pick the one matching best. In case of STM32 little endian that probably means the 2nd of the two forms. Built-in ADCs in microcontrollers typically have the same endianess as the CPU. In case of external ones, it could have either big or little endian.
The STM32 is a 32-bit CPU, but its ADC has a configurable 6, 8, 10 or 12-bit resolution.
If you take a look at the STM32F407's Reference Manual (RM0090) (this link is what I found now, for Rev 19 from Feb 2021), section 12.4, figures 48-50, you see this:
With this, you can see that a 16-bit register is being accessed, with the place for each bit from least significant (D0) to most significant (D11 if you're using the 12-bit configuration). You can also see the implications of sign extension (SEXT), which is usually a copy of the most significant bit after applying the injected offset. You can also see the 6-bit special case alignment in figure 50, which hints at the utility of left alignment.
Right alignment is the most obvious: you get the raw bits in the way they come from the ADC, resulting in numbers from zero to . If you are capturing with an injected group you can subtract an offset which may make the number negative, hence the sign extension bits.
Left alignment is less obvious, but can be used as a shortcut when one is dealing with fixed-point numbers. If one is considering a "full register" as the number 1.0, then one can add it easily when using the full width of the STM32's 32-bit registers. You can add many of those and then divide/shift when the final result is ready. If you multiply two of them, you get a 32-bit value, which can be rescaled back to 16-bit by a 16-bit shift, which may be faster than, for example, a 12-bit shift, because it would be just a matter of moving a half-word. Then, most of this can be also done with a right-aligned 12-bit word, but you have to manage your bits much more carefully. Perhaps the most benefit comes from the fact that one can start the math operations directly, without shifting the data first. Depending on which operation you're doing, the added bits on the right result in a finer result, with less machine instructions and less risk of having to manage your results bit-by-bit*.
* In the algorithm side, you always have to manage all of it bit-by-bit. However, there's less chance for error if "all operations are 16-bit wide" than if your position is "this operation is 12-bit, this one is 16-bit, and this one is 2*12-16=8-bit" and others.
You're applying a IIR filter to your ADC sample (12-bit). You multiply your sample with a number, let's say your coefficient is 16-bit and then accumulate in memory for the next iteration. The multiplication results in a 12+16=28 bits. How will you accumulate? As 28-bits? As 12-bits to be the proper scaling? Or a compromise of 16-bits? In the first option, you have to keep track that the number is really 28-bits for when you want to use in the next operation. If the next operation is a multiplication, you have to scale it before multiplying. Did you need to scale it down by 12 or 16 bits? Do you remember, if the algorithm is spread throughout the code? What if you use the number in two other operations? Will you keep track of the number of bits in each of them? Then again, if you scale it back to 12-bit, you lose all the least significant bits. If you store as 16-bits, it seems like a compromise, but you have to shift it by 12 bits, which may (or may not, I don't know the ISA all that much) be slower.
If you set yourself to use only 16-bits, you multiply a "virtual 16-bit" number with another 16-bit number, then shift it by 16-bits and still keeps 4 of the bits.