Embedded systems will always have the big-endian/little-endian issue. My personal approach has been to always encode internal memory with the native endianiness and make any swaps right when data enters or leaves.
I load the data using spi reads into analogin0.spibytes[0]-[2], with [0] as the MSB
By loading [0] as the MSB, you're encoding the value as big-endian.
analogin0.spibytes[0]=0xFF and and analogin0.spibytes[1]=0xB5, analogin0.halfwords[0] was equal to 0xB5FF
This indicates that the processor is little-endian.
If instead, you load the first value into [2] and work back to [0], then you've encoded the incoming number as little-endian, essentially making the swap as the number enters. Once you're working with the native representation, you can return to your original approach of using arithmetic operations. Just make sure to flip it back to big-endian when you transmit the value.
I suppose it depends on where the x
's are in the design.
Take an example communication scheme within the chip. You may want to pass data around between two components, but lets say not on every clock cycle. You might decide then to have a data bus and a valid signal. The valid signal says when the data is valid. Because of this, whenever the valid signal is low, the value of the data signal doesn't matter (because it is ignored).
In this example as long as the valid signal is never a don't-care, the design will never do anything unexpected. The data signal can be don't-care, it doesn't really matter, because you always know that there will be valid data (whatever it is) when the valid signal is high.
If the valid signal was ever don't-care, then you do have a problem. Why? because it means you have some scenario where you have no idea what will happen. This may or may not cause an issue, but boy is it a nightmare to track down.
So, with that in mind, it is my opinion that:
If you come across x
's in a data bus, it isn't the end of the world, in reality you don't know what the data will be at any given time anyway.
If they appear in control signals it may or may not be bad, you don't know. In this situation you should run your simulation twice, once making sure that the don't care is forced to be 0, and a second time making sure it is a 1. This way you know what will happen in both cases.
If you cannot be certain (i.e. from the code you have written) that a don't care wont cause issues, then you should not ignore it, x
is an unknown potential disaster. If you know that the value at any given point doesn't matter, then x
is perfectly valid.
Also, all control registers, whatever they are for, should be initialised to a value at reset. An uninitialised control register at power on could be disastrous. Imagine you make a control system for launching nuclear weapons and didn't initialise the 'launch' register to 0. For all you know when you turn the power on you could start WW3.
Best Answer
In this particular case (and in similar cases I've seen) yes, it's done to help keep backward compatibility with older devices and minimise any changes required to the (perhaps well-tested and qualified / certified) code already written for those older devices. New features and functionality (requiring new register bits for control & configuration) therefore have to use non-contiguous bits, if the adjacent bits to the original register bits are already used.
For example, here is the
USART_CR1
register of the old STM32F1xx family.Figure 1. STM32F10xxx USART_CR1 register usage
Image source: STM32F10xxx family reference manual RM0008, section 27.6.4
That older USART (with only 2 word length options) needs only one
M
bit to configure the USART word length between the two options, and that is bit 12. Notice how bits 11 and 13 are also used, and therefore unavailable for future "expansion".As you said, on the newer STM32F7 (and, for example, also the STM32F4) the USART now has 3 word length options (7, 8 and 9 bits) and so needs another configuration bit - bit 12 is
M0
, withM1
now in bit 28 (previously reserved in the STM32F1 register map, as you see above).Figure 2. STM32F74xxx USART_CR1 register usage
Image source: STM32F75xxx and STM32F74xxx family reference manual RM0385, section 31.8.1
They couldn't put the new
M1
bit into register bits 11 or 13, without moving register bits already used for other functions, and so removing backwards compatibility with existing code (e.g. for the STM32F1) which used them.So they have tried to keep some backwards compatibility, which leads to new register bits being added in unexpected places.
Maintaining register mapping for standalone UARTs, from the 8250 to the 16550, with new registers added elsewhere in the register map, was another example.